// modular synth prototype // copyright 2008 Les Hall // This software is protected by the GNU General Public License // parameters 10 => int num_nodes; // number of nodes available for connection 4 => int num_osc; // number of oscillators 150 => int slot_width; // width in pixels of each card slot int osc[num_osc]; // the selected oscillators int osc_in[num_osc]; // the previous value of input node int osc_out[num_osc]; // the previous value of output node // the pages MAUI_View main_view; main_view.size (150, 50); main_view.name ("Synthesizer Lab - Main Panel"); MAUI_View osc_view; osc_view.size (num_osc * slot_width, 500); osc_view.name ("Synthesizer Lab - Oscillators"); // control declarations // oscillator controls MAUI_Button osc_label[num_osc]; MAUI_Slider osc_input[num_osc]; MAUI_Slider osc_output[num_osc]; MAUI_Slider osc_gain[num_osc]; MAUI_Slider osc_freq1[num_osc]; MAUI_Slider osc_freq2[num_osc]; MAUI_Slider osc_phase[num_osc]; MAUI_Slider osc_width[num_osc]; MAUI_Slider osc_sync[num_osc]; MAUI_Button osc_boost[num_osc]; // main panel controls MAUI_Button main_record; // oscillators for (0 => int o; o < num_osc; o++) { // initialize oscillator selection 1 => osc[o]; // osc label button osc_label[o].pushType (); osc_label[o].size (150, 60); osc_label[o].position (slot_width*o, 0); osc_label[o].name ("SinOsc " + o); osc_view.addElement (osc_label[o]); // osc input node scroller osc_input[o].name ("Input Node"); osc_input[o].range (0, num_nodes); osc_input[o].value (0); osc_input[o].size (150, 75); osc_input[o].position (slot_width*o, 50); osc_input[o].displayFormat (osc_input[o].integerFormat); osc_view.addElement (osc_input[o]); // osc output node scroller osc_output[o].name ("Output Node"); osc_output[o].range (0, num_nodes); osc_output[o].value (0); osc_output[o].size (150, 75); osc_output[o].position (slot_width*o, 100); osc_output[o].displayFormat (osc_output[o].integerFormat); osc_view.addElement (osc_output[o]); // osc gain scroller osc_gain[o].name ("Gain"); osc_gain[o].range (0, 1); osc_gain[o].value (0); osc_gain[o].size (150, 75); osc_gain[o].position (slot_width*o, 150); osc_view.addElement (osc_gain[o]); // osc freq1 scroller osc_freq1[o].name ("Freq, kHz"); osc_freq1[o].range (0, 20); osc_freq1[o].value (1); osc_freq1[o].size (150, 75); osc_freq1[o].position (slot_width*o, 200); osc_freq1[o].displayFormat (osc_freq1[o].integerFormat); osc_view.addElement (osc_freq1[o]); // osc freq scroller osc_freq2[o].name ("Freq, Hz"); osc_freq2[o].range (0, 1000); osc_freq2[o].value (100); osc_freq2[o].size (150, 75); osc_freq2[o].position (slot_width*o, 250); osc_freq2[o].displayFormat (osc_freq2[o].integerFormat); osc_view.addElement (osc_freq2[o]); // osc phase scroller osc_phase[o].name ("Phase"); osc_phase[o].range (0, 2*pi); osc_phase[o].value (pi); osc_phase[o].size (150, 75); osc_phase[o].position (slot_width*o, 300); osc_view.addElement (osc_phase[o]); // osc width scroller osc_width[o].name ("Width"); osc_width[o].range (0, 1); osc_width[o].value (0.5); osc_width[o].size (150, 75); osc_width[o].position (slot_width*o, 350); osc_view.addElement (osc_width[o]); // osc synch scroller osc_sync[o].name ("Sync"); osc_sync[o].range (0, 2); osc_sync[o].value (0); osc_sync[o].size (150, 75); osc_sync[o].position (slot_width*o, 400); osc_sync[o].displayFormat (osc_sync[o].integerFormat); osc_view.addElement (osc_sync[o]); // osc boost button osc_boost[o].toggleType (); osc_boost[o].size (150, 60); osc_boost[o].position (slot_width*o, 450); osc_boost[o].name ("Gain Boost"); osc_view.addElement (osc_boost[o]); } // main panel controls // record button main_record.toggleType (); main_record.size (150, 60); main_record.position (0, 0); main_record.name ("Record"); main_view.addElement (main_record); // display the pages osc_view.display (); main_view.display (); // instantiate the oscillators //Phasor phasor[num_osc]; SinOsc sinosc[num_osc]; //PulseOsc pulseosc[num_osc]; //SqrOsc sqrosc[num_osc]; //TriOsc triosc[num_osc]; //SawOsc sawosc[num_osc]; // the nodes are implemented as Gain ugens Gain g[num_nodes+1]; // initialize nodes for (0 => int n; n <= num_nodes; n++) { g[n].gain (1); } // initialize all connections to node zero for (0 => int o; o < num_osc; o++) { sinosc[o] => g[0]; 0 => osc_in[o]; 0 => osc_out[o]; } // hook up the highest node to the dac g[1] => Gain master => WvOut wave_out => dac; // shreds to watch the ugen select buttons // osc shreds function void osc_label_adj (int o) { while (true) { osc_label[o] => now; if (osc_label[o].state ()) { (osc[o] + 1) % 6 => osc[o]; if (osc[o] == 0) { osc_label[o].name ("Phasor " + o); } if (osc[o] == 1) { osc_label[o].name ("SinOsc " + o); } if (osc[o] == 2) { osc_label[o].name ("PulseOsc " + o); } if (osc[o] == 3) { osc_label[o].name ("SqrOsc " + o); } if (osc[o] == 4) { osc_label[o].name ("TriOsc " + o); } if (osc[o] == 5) { osc_label[o].name ("SawOsc " + o); } } } } for (0 => int o; o < num_osc; o++) { spork ~ osc_label_adj (o); } // shreds to watch the ChucK it buttons // shred for input node slider on oscillators function void osc_input_adj (int o) { while (true) { osc_input[o] => now; g[osc_in[o]] =< sinosc[o]; if (osc_input[0].value ()) { g[osc_input[o].value () $ int] => sinosc[o]; } osc_input[o].value () $ int => osc_in[o]; } } for (0 => int o; o < num_osc; o++) { spork ~ osc_input_adj (o); } // shred for output node slider on oscillators function void osc_output_adj (int o) { while (true) { osc_output[o] => now; sinosc[o] =< g[osc_out[o]]; sinosc[o] => g[osc_output[o].value () $ int]; osc_output[o].value () $ int => osc_out[o]; } } for (0 => int o; o < num_osc; o++) { spork ~ osc_output_adj (o); } // shred for gain slider on oscillators function void osc_gain_adj (int o) { while (true) { osc_gain[o] => now; if (osc_boost[o].state ()) { sinosc[o].gain (1000 * osc_gain[o].value ()); } else { sinosc[o].gain (osc_gain[o].value ()); } } } for (0 => int o; o < num_osc; o++) { spork ~ osc_gain_adj (o); } // shred for freq1 slider on oscillators function void osc_freq1_adj (int o) { while (true) { osc_freq1[o] => now; sinosc[o].freq (1000 * osc_freq1[o].value () + osc_freq2[o].value ()); } } for (0 => int o; o < num_osc; o++) { spork ~ osc_freq1_adj (o); } // shred for freq2 slider on oscillators function void osc_freq2_adj (int o) { while (true) { osc_freq2[o] => now; sinosc[o].freq (1000 * osc_freq1[o].value () + osc_freq2[o].value ()); } } for (0 => int o; o < num_osc; o++) { spork ~ osc_freq2_adj (o); } // shred for phase slider on oscillators function void osc_phase_adj (int o) { while (true) { osc_phase[o] => now; sinosc[o].phase (osc_phase[o].value ()); } } for (0 => int o; o < num_osc; o++) { spork ~ osc_phase_adj (o); } // shred for width slider on oscillators function void osc_width_adj (int o) { while (true) { osc_width[o] => now; } } for (0 => int o; o < num_osc; o++) { spork ~ osc_width_adj (o); } // shred for sync slider on oscillators function void osc_sync_adj (int o) { while (true) { osc_sync[o] => now; sinosc[o].sync (osc_sync[o].value () $ int); } } for (0 => int o; o < num_osc; o++) { spork ~ osc_sync_adj (o); } // shred for boost button on oscillators function void osc_boost_adj (int o) { while (true) { osc_boost[o] => now; if (osc_boost[o].state ()) { sinosc[o].gain (1000 * osc_gain[o].value ()); } else { sinosc[o].gain (osc_gain[o].value ()); } } } for (0 => int o; o < num_osc; o++) { spork ~ osc_boost_adj (o); } // shred for record button on main panel function void main_record_adj () { while (true) { // wait for the start button to be pushed main_record => now; if (main_record.state ()) { "Synth_Lab.wav" => wave_out.wavFilename; } else { wave_out.closeFile (); } } } spork ~ main_record_adj (); // initialization of instruments function void initialize () { for (0 => int o; o < num_osc; o++) { sinosc[o].gain (osc_gain[o].value ()); sinosc[o].freq (osc_freq1[o].value () + osc_freq2[o].value ()); sinosc[o].phase (osc_phase[o].value ()); } } initialize (); // loop forever while (true) { day => now; }