libline: a library for lines in music
This past week I have been putting time into implementing a library whose primary responsibilty is in generating lines. I have given it the extremely creative name libline.
The need for lines
Lines are an important abstraction in the sonic domain. They can be used to describe musical gestures and changes over time.
When composing with Sporth, I have often found myself desiring lines to transform sounds over time. For a period of time, I considered using automation curves via LMMS, but I quickly found it to be clunky and not great for more than a few lines at a time.
My efforts with LMMS were not in vain, because it gave me a taste of lines in Sporth. Mapping a line (or lines) over an extended duration to a Sporth patch has the the potential of strengthening an underlying musical form such as a beginning, middle, and end. My Sporthlings up to this point have no such concepts, so this would be an interesting change.
Like my last project, Voc, libline is written using the literate documentation system CWEB. However, unlike that project, I have made the choice to include the generated C and header files with the repository, so that the library can be compiled on systems without CWEB installed. While it does add to the overhead in github, the size and scope of the project makes the issue negligible.
Literate programming is quite an addictive thing to do. It is simple enough to write code for a program, but there are so many wrong ways to explain why the code is there in the first place. It has challenged me to think about the presentation of code, and trying to make the experience of reading code be more than a nervous line-by-line skimming.
Functionality in Sporth
I have decided to provide an early (and rash) introduction of libline into Sporth via the scheme interface provided by polysporth, a utility inside of Sporth designed to do things beyond the Sporth language abstraction.
The following example shows how to control a sine wave oscillator using line segments generated via libline.
The program has two file: a polysporth interface files written using an internal dialect of scheme, and a sporth file.
The scheme file contains all code related to polysporth. It is here that the lines are constructed. Sporth syntax alone doesn't really have a concept of initialization code (only as a runtime mode in a ugen). With scheme, this concept exists.
Lines created in libline are audio-rate signals that are bound to Sporth variables:
; Create a new line stored in variable "freq" (ps-line-begin "freq") ; linearly go from 440 to 880 in one second (ps-line-linpoint 440 1.0) (ps-line-step 880 1.0) ; next, exponentially go from 440 to 880 in one second with a slope of 10 (ps-line-exppoint 440 1.0 10) (ps-line-step 880 1.0) ; end the line (ps-line-end) ; Create a gate signal so that the line shuts off after 4 seconds (ps-line-begin "gate") (ps-line-step 1 4) (ps-line-step 0 1) (ps-line-end) ; Export variables so they show up in the upper level sporth patch (ps-export "freq" "freq") (ps-export "gate" "gate") ; "ll" is the unit generator that is called exactly once to generate ; line segments. Export this to the upper level sporth patch as well (ps-export "ll" "ll")
The Sporth code is in charge of loading the polysporth scheme code and producing the sinusoidal sounds. It also bears the responsibility of making sure the lines generated are being computed:
# Load the file test.scm and create a polysporth handle. # No (0) voices needed. _ps 0 "test.scm" psh # Needed to be called exactly once. It will compute the line segments _ll fe # Map the frequency line to the frequency of a sine wave _freq get 0.5 sine # multiply it all by the gate signal _gate get *
This patch is run from the Sporth file. Save the Sporth code as "test.sp" and the polysporth code as "test.scm". Then run:
To generate a 5-second audio file with the sounds!
This work is ongoing and quite new, so expect everything to be subject of change. As has been with my projects, the trajectory will be determined by how I end up using this to make music. At the moment, my interests lie in generating automation curves and triggerable gestures. Some sort of higher-level construction of lines may also be in the equation. We will see...