commit
89af786679
4 changed files with 77 additions and 34 deletions
1
oregano/.gitignore
vendored
Normal file
1
oregano/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
scsynth
|
|
@ -3,71 +3,115 @@
|
||||||
|
|
||||||
|
|
||||||
## Goal
|
## Goal
|
||||||
I planned on writing a client for the SuperCollider (SC) music synthesis server for use in the Music Programming section of CSC123. Using the interface to SuperCollider, students will have access to real-time synthesis techniques.
|
|
||||||
|
I planned on writing a client for the SuperCollider (SC) music synthesis
|
||||||
|
server for use in the Music Programming section of CSC123. Using the
|
||||||
|
interface to SuperCollider, students will have access to real-time
|
||||||
|
synthesis techniques.
|
||||||
|
|
||||||
## Initial steps
|
## Initial steps
|
||||||
In the first quarter, after examining implementations in various languages, I set out on creating a new implementation in Racket from scratch. Quickly, however, it appeared that two quarters is not enough time, so I looked into porting the scheme implementation of a supercollider client, rsc3, to Racket.
|
|
||||||
|
In the first quarter, after examining implementations in various
|
||||||
|
languages, I set out on creating a new implementation in Racket from
|
||||||
|
scratch. Quickly, however, it appeared that two quarters is not enough
|
||||||
|
time, so I looked into porting the scheme implementation of a
|
||||||
|
supercollider client, rsc3, to Racket.
|
||||||
|
|
||||||
### The Porting process
|
### The Porting process
|
||||||
|
|
||||||
I first tried rsc3 in a scheme interpreter, including ikarus and DrRacket's r6rs mode (#lang r6rs). rsc3 ran with very little modification (one library funciton name was wrong). However, rsc3 could not be installed as a Racket package, due to a conflict of the way scheme and racket handle libraries.
|
I first tried rsc3 in a scheme interpreter, including ikarus and
|
||||||
Installing rsc3 as a package is an important aspect since that is how students will install rsc3.
|
DrRacket's r6rs mode (#lang r6rs). rsc3 ran with very little
|
||||||
|
modification (one library funciton name was wrong). However, rsc3 could
|
||||||
|
not be installed as a Racket package, due to a conflict of the way
|
||||||
|
scheme and racket handle libraries. Installing rsc3 as a package is an
|
||||||
|
important aspect since that is how students will install rsc3.
|
||||||
|
|
||||||
What I did is instead of using "#lang r6rs", which makes racket behave like a scheme interpreter confirming to the r6rs scheme standard, I used "#lang racket" and imported the rnrs library that has scheme functions in a racket environment. This way I could use Racket's provide and package functionality works.
|
What I did is instead of using "#lang r6rs", which makes racket behave
|
||||||
|
like a scheme interpreter confirming to the r6rs scheme standard, I used
|
||||||
|
"#lang racket" and imported the rnrs library that has scheme functions
|
||||||
|
in a racket environment. This way I could use Racket's provide and
|
||||||
|
package functionality works.
|
||||||
|
|
||||||
The process of porting was relatively straightforward. I compiled a file, looked for errors, and fixed them. Some defined utility functions were not necessary because racket had native implementations.
|
The process of porting was relatively straightforward. I compiled a
|
||||||
|
file, looked for errors, and fixed them. Some defined utility functions
|
||||||
|
were not necessary because racket had native implementations.
|
||||||
|
|
||||||
### Challenges when porting
|
### Challenges when porting
|
||||||
One tricky part was a difference in the list representations between r6rs scheme and Racket. Racket uses mutable pairs to construct lists, while scheme uses immutable pairs. This makes it so that a list created in Racket cannot be used in a scheme function that accepts a list. One way around this is to construct lists using mcons in Racket then pass it to a scheme function.
|
|
||||||
|
|
||||||
|
|
||||||
|
One tricky part was a difference in the list representations between
|
||||||
|
r6rs scheme and Racket. Racket uses mutable pairs to construct lists,
|
||||||
|
while scheme uses immutable pairs. This makes it so that a list created
|
||||||
|
in Racket cannot be used in a scheme function that accepts a list. One
|
||||||
|
way around this is to construct lists using mcons in Racket then pass it
|
||||||
|
to a scheme function.
|
||||||
|
|
||||||
## Features added
|
## Features added
|
||||||
|
|
||||||
It would be hard for first year students to use rsc3 directly, so I created simplified abstractions (functions and structures) to perform common tasks of creating and controlling sounds.
|
It would be hard for first year students to use rsc3 directly, so I
|
||||||
|
created simplified abstractions (functions and structures) to perform
|
||||||
|
common tasks of creating and controlling sounds.
|
||||||
|
|
||||||
### Instruments
|
### Instruments
|
||||||
|
|
||||||
|
|
||||||
Students could create instruments with parameters that could be changed in real-time. Students can use this defined instruments to play notes
|
Students could create instruments with parameters that could be changed
|
||||||
|
in real-time. Students can use this defined instruments to play notes
|
||||||
|
|
||||||
I used a Racket macro to create the instrument creation form.
|
I used a Racket macro to create the instrument creation form.
|
||||||
|
|
||||||
An instrument corresponds to a Synhtdef in SuperCollider. A Synthedef is a composition of functions called ugens. ugens, which stands for unit generator,
|
An instrument corresponds to a Synthdef in SuperCollider. A Synthdef is
|
||||||
|
a composition of functions called ugens. ugens, which stands for unit
|
||||||
|
generator,
|
||||||
|
|
||||||
Instruments are associated with functions that play notes. A note contains the instrument name and frequency. The functions can turn on a note, turn it off, and change some instrument parameters, which will only affect the playing note, while the note is playing.
|
Instruments are associated with functions that play notes. A note
|
||||||
|
contains the instrument name and frequency. The functions can turn on a
|
||||||
|
note, turn it off, and change some instrument parameters, which will
|
||||||
|
only affect the playing note, while the note is playing.
|
||||||
|
|
||||||
### GUI elements to control parameters
|
### GUI elements to control parameters
|
||||||
|
|
||||||
One interesting feature I implemented is the ability to easily create GUI elements to control note parameters. Currently there is a slider and checkbox. The slider works by passing a label, start value, end, initial, values, and a callback function that accepts the value of the slider.
|
One interesting feature I implemented is the ability to easily create
|
||||||
|
GUI elements to control note parameters. Currently there is a slider and
|
||||||
|
checkbox. The slider works by passing a label, start value, end,
|
||||||
|
initial, values, and a callback function that accepts the value of the
|
||||||
|
slider.
|
||||||
|
|
||||||
While this uses a lambda function, it could be easily changed to accept a particular note and the parameter string to change.
|
While this uses a lambda function, it could be easily changed to accept
|
||||||
|
a particular note and the parameter string to change.
|
||||||
|
|
||||||
I also added a slider funciton that can be used directly in the definition of an instrument. This encourages experimentation with parameter values.
|
I also added a slider funciton that can be used directly in the
|
||||||
|
definition of an instrument. This encourages experimentation with
|
||||||
|
parameter values.
|
||||||
|
|
||||||
|
|
||||||
### Filters
|
### Filters
|
||||||
|
|
||||||
I added functions that can be used to chain effects, such as reverb and low pass filters. An effect added after a previous effect will act on the output of the previus effect. To implement this, I originally planned on chaining nodes using SuperCollider's audio buses. However, I found a ugen that could do that called replace-out that provides this functionality. That is, replace-out can read, modify, and write to the same bus.
|
I added functions that can be used to chain effects, such as reverb and
|
||||||
|
low pass filters. An effect added after a previous effect will act on
|
||||||
|
the output of the previous effect. To implement this, I originally
|
||||||
|
planned on chaining nodes using SuperCollider's audio buses. However, I
|
||||||
|
found a ugen that could do that called replace-out that provides this
|
||||||
|
functionality. That is, replace-out can read, modify, and write to the
|
||||||
|
same bus.
|
||||||
|
|
||||||
### Scheduling notes
|
### Scheduling notes
|
||||||
|
|
||||||
Using the Bundle feature of the OSC protocol, I could schedule events to happen in the future. The function accepts the utc seconds and a fraction to denote milliseconds, duration, and the note to play.
|
Using the Bundle feature of the OSC protocol, I could schedule events to
|
||||||
|
happen in the future. The function accepts the utc seconds and a
|
||||||
|
fraction to denote milliseconds, duration, and the note to play.
|
||||||
|
|
||||||
## Cross platform issues
|
## Cross platform issues
|
||||||
|
|
||||||
SuperCollider has versions for Windows, Linux and OS X. On Windows and OS X, SuperCollider doesn't need dependencies, but on Linux, SuperCollider requires a Jack server to be running. Students will have to install Jack, which is a different procedure depending on their Linux distribution. It's one line in a terminal on a Debian based distribution such as Ubuntu.
|
SuperCollider has versions for Windows, Linux and OS X. On Windows and
|
||||||
|
OS X, SuperCollider doesn't need dependencies, but on Linux,
|
||||||
I added a function that starts the SuperCollider server if it's not already started whenever the library is initialized. Racket has functions to return the OS type, and I issue a system command to start the server based on the OS. For Linux, I wrote a script to also start the Jack audio server and connect SuperCollider's outputs to the system audio output.
|
SuperCollider requires a Jack server to be running. Students will have
|
||||||
|
to install Jack, which is a different procedure depending on their Linux
|
||||||
|
distribution. It's one line in a terminal on a Debian based distribution
|
||||||
|
such as Ubuntu.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
I added a function that starts the SuperCollider server if it's not
|
||||||
|
already started whenever the library is initialized. Racket has
|
||||||
|
functions to return the OS type, and I issue a system command to start
|
||||||
|
the server based on the OS. For Linux, I wrote a script to also start
|
||||||
|
the Jack audio server and connect SuperCollider's outputs to the system
|
||||||
|
audio output.
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
Simplified interface to SuperCollider, with new abstractions.
|
Simplified interface to SuperCollider, with new abstractions.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1
sosc/README.md
Normal file
1
sosc/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
This code comes from Rohan Drape's "sosc" package for Open Sound Control.
|
Loading…
Reference in a new issue