Being able to patch together units is a fundamental principle of a modular environment. Though I’m far from figuring out what the syntax should look like in my faux music language, I have been writing some mock up code just to get a sense of it.
Just a warning, the following example is ignorant of i/k/a-rates, along with pass-by-reference vs pass-by-value:
import FX import Master import Mixer from Envelope import line from TestLibrary.Instruments import SineTone # Create instances of objects and patch together st = SineTone() # Simple sine instrument reverb = FX.Reverb(input=st.out, time=3.1) # Reverb unit mix = Mixer.pan(0, st.out, reverb.out) # Dry/wet: value, sig 1, sig 2 output = Master.DAC(mix) # Main output # Score @0 turnon(reverb, mix, output) # Turn on selected instances @0 st.play(20, 1, 440) # Play for 20 seconds, amp = 1, frequency = 440 @0 st.amp *= line(0, 10, 1) # Amplitude rise @10 st.amp *= line(1, 10, 0) # Amplitude fall @20 mix.pan = line(1, 20, 0) # Dry to wet over 20 seconds @10 reverb.time += line(0, 5, 8.1) # Increase reverb time starting at 10 @20: @reverb.time turnoff(reverb, mix, output) # Turnoff selected instances
The import section loads classes from existing instrument/unit generator libraries.
In the orchestra, instances are created from the imported classes, and patched together into a simple instrument graph. There’s a simple sine instrument, which is plugged into a reverb unit. Next, there is the pan mixer, which has the dry sine instrument plugged into one side, and the wet reverb signal plugged into the other; It is initially set to 100% dry. The pan mixer is then patched into the output, which sends the audio to the DAC.
The first line in the score turns on three instruments: reverb, mix and output. There will be times when the duration is unknown. The ability to start and stop machines is a must.
The sine instrument starts with a duration of 20, an amplitude of 1 and a frequency of 440. The amplitude of the sine is modulated by two envelopes, creating a rise/fall shape. Line envelopes also modulate the dry/wet mixer and reverb time.
At the end, the turnoff function shuts down reverb, mix and output.
Bonus round: Why do you suppose I wrote,
@20: @reverb.time turnoff(reverb, mix, output) # Turnoff selected instances
instead of this?
@(20 + reverb.time) turnoff(reverb, mix, output) # Turnoff selected instances