Last active
August 26, 2016 16:07
-
-
Save modlfo/77bc427f231a1d5b7d8a to your computer and use it in GitHub Desktop.
Vult examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| = A simple synthesizer with one LFO and a Delay effect | |
| CC30 - Volume | |
| CC31 - Detune/Resonance | |
| CC32 - LFO rate | |
| CC33 - LFO amount (bipolar) | |
| CC34 - Delay time | |
| CC35 - Delay feedback | |
| */ | |
| // Used to soften the transitions of controls | |
| fun smooth(input:real) : real { | |
| mem x; | |
| x = x+(input-x)*0.005; | |
| return x; | |
| } | |
| // Returns true every time the input value changes | |
| fun change(x:real):bool { | |
| mem pre_x; | |
| val v:bool = pre_x<>x; | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true if the value changes from 0 to anything | |
| fun edge(x:bool):bool { | |
| mem pre_x; | |
| val v:bool = (pre_x<>x) && (pre_x==false); | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true every 'n' calls | |
| fun each(n:int) : bool { | |
| mem count; | |
| val ret = (count == 0); | |
| count = (count + 1) % n; | |
| return ret; | |
| } | |
| // Converts the MIDI note to increment rate at a 44100 sample rate | |
| fun pitchToRate(d) return 8.1758*exp(0.0577623*d)/44100.0; | |
| fun phasor(pitch:real,reset:bool){ | |
| mem rate,phase; | |
| if(change(pitch)) | |
| rate = pitchToRate(pitch); | |
| phase = if reset then 0.0 else (phase + rate) % 1.0; | |
| return phase; | |
| } | |
| // A simple LFO with reset signal | |
| fun lfo(f:real,gate:bool) : real { | |
| mem phase; | |
| val rate = f * 10.0/44100.0; | |
| if(edge(gate)) phase = 0.0; | |
| phase = phase + rate; | |
| if(phase>1.0) phase = phase-1.0; | |
| return sin(phase*2.0*3.141592653589793)-0.5; | |
| } | |
| // Implements the resonant filter simulation as shown in | |
| // http://en.wikipedia.org/wiki/Phase_distortion_synthesis | |
| fun phd_osc(pitch:real,detune:real) : real { | |
| mem pre_phase1; // used to detect when the phase wrapps from 1 to 0 | |
| val phase1 = phasor(pitch,false); | |
| val comp = 1.0 - phase1; | |
| val reset = (pre_phase1 - phase1) > 0.5; | |
| pre_phase1 = phase1; | |
| val phase2 = phasor(pitch+smooth(detune)*32.0,reset); | |
| val sine = sin(2.0*3.14159265359*phase2); | |
| return sine*comp; | |
| } | |
| // Simple delay. | |
| fun delay(x:real, time:real, feedback:real) : real { | |
| mem buffer : array(real,44100); | |
| mem write_pos; | |
| // Constraints the parameter values | |
| time = clip(time,0.0,1.0); | |
| feedback = clip(feedback,0.0,1.0); | |
| // Gets the position in the buffer to read | |
| val index_r = real(size(buffer)) * time; | |
| val index_i = int(floor(index_r)); | |
| val delta = write_pos - index_i; | |
| val read_pos = if delta < 0 then size(buffer)+delta else delta; | |
| // Gets the decimal part of the position | |
| val decimal = index_r - real(index_i); | |
| // Reads the values in the buffer | |
| val x1 = get(buffer,read_pos); | |
| val x2 = get(buffer,(read_pos+1) % size(buffer)); | |
| // Interpolates the value | |
| val ret = (x2-x1)*decimal + x1; | |
| // Write the data to the buffer | |
| write_pos = (write_pos+1) % size(buffer); | |
| _ = set(buffer,write_pos,clip(x+feedback*ret,-1.0,1.0)); | |
| return ret; | |
| } | |
| /* These three functions handle midi on/off events in order to behave | |
| * like a monophonic sinthesizer that can hold 4 notes */ | |
| // Activates a note and returns the current note value | |
| fun mono_noteOn(n:int){ | |
| mem count,pre; | |
| mem notes : array(int,4); | |
| // Do not add more that the size of array | |
| if(count < size(notes)) { | |
| _ = set(notes,count,n); | |
| pre = n; | |
| if(count < size(notes)) count = count + 1; | |
| } | |
| return pre; | |
| } | |
| // Deactivates a note and returns the following note value; | |
| and mono_noteOff(n:int){ | |
| mem count,pre; | |
| mem notes : array(int,4); | |
| val found = false; | |
| val pos; | |
| val i = 0; | |
| // if there are no notes, no dot do anything | |
| if(count == 0) | |
| return pre; | |
| // Finds the location of the note | |
| while(i < size(notes) && not(found)){ | |
| if(get(notes,i) == n) { | |
| pos = i; | |
| found = true; | |
| } | |
| i = i + 1; | |
| } | |
| // if the note was found moves all the notes one location | |
| if(found) { | |
| val k = pos + 1; | |
| while(k < size(notes)) { | |
| _ = set(notes,k-1,get(notes,k)); | |
| k = k + 1; | |
| } | |
| // If found, decrease the number of active notes | |
| if(found && count>0) { | |
| count = count - 1; | |
| pre = get(notes,count - 1); | |
| } | |
| } | |
| return pre; | |
| } | |
| // Returns 1 if any note is active | |
| and mono_isGateOn() { | |
| mem count; | |
| return count > 0; | |
| } | |
| // Main processing function | |
| fun process(input:real){ | |
| mem volume,detune; // values set in 'controlChange' | |
| mem pitch; | |
| mem lfo_rate,lfo_amt; | |
| mem time, feedback; | |
| val gate = notes:mono_isGateOn(); | |
| // creates one LFO | |
| val lfo_val = lfo(lfo_rate,gate)*lfo_amt; | |
| // creates one oscillator | |
| val o1 = phd_osc(pitch,detune+lfo_val); | |
| // gets the amplification by using a low-pass on the gate | |
| val amp = smooth(if gate then 1.0 else 0.0); | |
| val osc_out = o1 * amp; | |
| val delay_out = delay(osc_out,smooth(time),smooth(feedback)); | |
| return volume * (osc_out+delay_out) /2.0; | |
| } | |
| // Called when a note On is received | |
| and noteOn(note:int,velocity:int){ | |
| mem pitch = real(notes:mono_noteOn(note)); | |
| } | |
| // Called when a note Off is received | |
| and noteOff(note){ | |
| mem pitch = real(notes:mono_noteOff(note)); | |
| } | |
| // Called when a control changes | |
| and controlChange(control,value){ | |
| mem volume; | |
| mem detune; | |
| mem lfo_rate, lfo_amt; | |
| mem time, feedback; | |
| // Control 30 defines the volume | |
| if(control==30) volume = value/127.0; | |
| if(control==31) detune = value/127.0; | |
| if(control==32) lfo_rate = value/127.0; | |
| if(control==33) lfo_amt = 2.0*((real(value)/127.)-0.5); | |
| if(control==34) time = value/127.0; | |
| if(control==35) feedback = value/127.0; | |
| } | |
| // Called on initialization to define initial values | |
| and default(){ | |
| mem volume = 0.5; | |
| mem pitch = 45.0; | |
| mem detune = 0.8; | |
| mem lfo_rate = 0.07; | |
| mem lfo_amt = -0.8; | |
| mem time = 0.5; | |
| mem feedback = 0.5; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| = Phase distortion oscillator = | |
| CC30 - Volume | |
| CC31 - Detune/Resonance | |
| Keyboard - Pitch | |
| */ | |
| // Used to soften the transitions of controls | |
| fun smooth(input){ | |
| mem x; | |
| x = x+(input-x)*0.005; | |
| return x; | |
| } | |
| // Returns true every time the input value changes | |
| fun change(x):bool { | |
| mem pre_x; | |
| val v:bool = pre_x<>x; | |
| pre_x = x; | |
| return v; | |
| } | |
| // Converts the MIDI note to increment rate at a 44100 sample rate | |
| fun pitchToRate(d) return 8.1758*exp(0.0577623*d)/44100.0; | |
| // Produces a non-bandwith-limited saw used as phase of oscillators | |
| fun phasor(pitch,reset){ | |
| mem rate,phase; | |
| if(change(pitch)) | |
| rate = pitchToRate(pitch); | |
| phase = if reset then 0.0 else (phase + rate) % 1.0; | |
| return phase; | |
| } | |
| // Implements the resonant filter simulation as shown in | |
| // http://en.wikipedia.org/wiki/Phase_distortion_synthesis | |
| fun phd_osc(pitch:real,detune:real) : real { | |
| mem pre_phase1; // used to detect when the phase wrapps from 1 to 0 | |
| val phase1 = phasor(pitch,false); | |
| val comp = 1.0 - phase1; | |
| val reset = (pre_phase1 - phase1) > 0.5; | |
| pre_phase1 = phase1; | |
| val phase2 = phasor(pitch+smooth(detune)*32.0,reset); | |
| val sine = sin(2.0*3.14159265359*phase2); | |
| return sine*comp; | |
| } | |
| // Main processing function | |
| fun process(input:real){ | |
| mem volume,detune; // values set in 'controlChange' | |
| mem pitch; | |
| // Generates one oscilator | |
| val o1 = phd_osc(pitch,detune); | |
| return smooth(volume)*o1; | |
| } | |
| // Called when a note On is received | |
| and noteOn(note:int,velocity:int){ | |
| mem pitch = real(note); | |
| } | |
| // Called when a note Off is received | |
| and noteOff(note:int){ | |
| } | |
| // Called when a control changes | |
| and controlChange(control:int,value:int){ | |
| mem volume; | |
| mem detune; | |
| // Control 30 defines the volume | |
| if(control==30) volume = real(value)/127.0; | |
| if(control==31) detune = real(value)/127.0; | |
| } | |
| // Called on initialization to define initial values | |
| and default(){ | |
| mem volume = 0.5; | |
| mem pitch = 45.0; | |
| mem detune = 0.0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| = A simple synthesizer with one LFO | |
| CC30 - Volume | |
| CC31 - Detune/Resonance | |
| CC32 - LFO rate | |
| CC33 - LFO amount (bipolar) | |
| */ | |
| // Used to soften the transitions of controls | |
| fun smooth(input:real) : real { | |
| mem x; | |
| x = x+(input-x)*0.005; | |
| return x; | |
| } | |
| // Returns true every time the input value changes | |
| fun change(x:real):bool { | |
| mem pre_x; | |
| val v:bool = pre_x<>x; | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true if the value changes from 0 to anything | |
| fun edge(x:bool):bool { | |
| mem pre_x; | |
| val v:bool = (pre_x<>x) && (pre_x==false); | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true every 'n' calls | |
| fun each(n:int) : bool { | |
| mem count; | |
| val ret = (count == 0); | |
| count = (count + 1) % n; | |
| return ret; | |
| } | |
| // Converts the MIDI note to increment rate at a 44100 sample rate | |
| fun pitchToRate(d) return 8.1758*exp(0.0577623*d)/44100.0; | |
| fun phasor(pitch:real,reset:bool){ | |
| mem rate,phase; | |
| if(change(pitch)) | |
| rate = pitchToRate(pitch); | |
| phase = if reset then 0.0 else (phase + rate) % 1.0; | |
| return phase; | |
| } | |
| // A simple LFO with reset signal | |
| fun lfo(f:real,gate:bool) : real { | |
| mem phase; | |
| val rate = f * 10.0/44100.0; | |
| if(edge(gate)) phase = 0.0; | |
| phase = phase + rate; | |
| if(phase>1.0) phase = phase-1.0; | |
| return sin(phase*2.0*3.141592653589793)-0.5; | |
| } | |
| // Implements the resonant filter simulation as shown in | |
| // http://en.wikipedia.org/wiki/Phase_distortion_synthesis | |
| fun phd_osc(pitch:real,detune:real) : real { | |
| mem pre_phase1; // used to detect when the phase wrapps from 1 to 0 | |
| val phase1 = phasor(pitch,false); | |
| val comp = 1.0 - phase1; | |
| val reset = (pre_phase1 - phase1) > 0.5; | |
| pre_phase1 = phase1; | |
| val phase2 = phasor(pitch+smooth(detune)*32.0,reset); | |
| val sine = sin(2.0*3.14159265359*phase2); | |
| return sine*comp; | |
| } | |
| /* These three functions handle midi on/off events in order to behave | |
| * like a monophonic sinthesizer that can hold 4 notes */ | |
| // Activates a note and returns the current note value | |
| fun mono_noteOn(n:int){ | |
| mem count,pre; | |
| mem notes : array(int,4); | |
| // Do not add more that the size of array | |
| if(count < size(notes)) { | |
| _ = set(notes,count,n); | |
| pre = n; | |
| if(count < size(notes)) count = count + 1; | |
| } | |
| return pre; | |
| } | |
| // Deactivates a note and returns the following note value; | |
| and mono_noteOff(n:int){ | |
| mem count,pre; | |
| mem notes : array(int,4); | |
| val found = false; | |
| val pos; | |
| val i = 0; | |
| // if there are no notes, no dot do anything | |
| if(count == 0) | |
| return pre; | |
| // Finds the location of the note | |
| while(i < size(notes) && not(found)){ | |
| if(get(notes,i) == n) { | |
| pos = i; | |
| found = true; | |
| } | |
| i = i + 1; | |
| } | |
| // if the note was found moves all the notes one location | |
| if(found) { | |
| val k = pos + 1; | |
| while(k < size(notes)) { | |
| _ = set(notes,k-1,get(notes,k)); | |
| k = k + 1; | |
| } | |
| // If found, decrease the number of active notes | |
| if(found && count>0) { | |
| count = count - 1; | |
| pre = get(notes,count - 1); | |
| } | |
| } | |
| return pre; | |
| } | |
| // Returns 1 if any note is active | |
| and mono_isGateOn() { | |
| mem count; | |
| return count > 0; | |
| } | |
| // Main processing function | |
| fun process(input:real){ | |
| mem volume,detune; // values set in 'controlChange' | |
| mem pitch; | |
| mem lfo_rate,lfo_amt; | |
| val gate = notes:mono_isGateOn(); | |
| // creates one LFO | |
| val lfo_val = lfo(lfo_rate,gate)*lfo_amt; | |
| // creates one oscillator | |
| val o1 = phd_osc(pitch,detune+lfo_val); | |
| // gets the amplification by using a low-pass on the gate | |
| val amp = smooth(if gate then 1.0 else 0.0); | |
| return volume * o1 * amp; | |
| } | |
| // Called when a note On is received | |
| and noteOn(note:int,velocity:int){ | |
| mem pitch = real(notes:mono_noteOn(note)); | |
| } | |
| // Called when a note Off is received | |
| and noteOff(note){ | |
| mem pitch = real(notes:mono_noteOff(note)); | |
| } | |
| // Called when a control changes | |
| and controlChange(control,value){ | |
| mem volume; | |
| mem detune; | |
| mem lfo_rate; | |
| mem lfo_amt; | |
| // Control 30 defines the volume | |
| if(control==30) volume = value/127.0; | |
| if(control==31) detune = value/127.0; | |
| if(control==32) lfo_rate = value/127.0; | |
| if(control==33) lfo_amt = 2.0*((real(value)/127.)-0.5); | |
| } | |
| // Called on initialization to define initial values | |
| and default(){ | |
| mem volume = 0.5; | |
| mem pitch = 45.0; | |
| mem detune = 0.8; | |
| mem lfo_rate = 0.07; | |
| mem lfo_amt = -0.8; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| = A synthesizer with a bandwidth-limited multi-oscillator | |
| and a state variable filter | |
| CC30 - Volume | |
| CC31 - Wave selector (pulse,saw,triangle) | |
| CC32 - Pulse width | |
| CC33 - LFO rate | |
| CC34 - LFO amount (bipolar, connected to PW) | |
| CC35 - Filter cut | |
| CC36 - Filter resonance | |
| */ | |
| // Minimum value represented with fixed-point q16 | |
| fun minFixed() return 0.0000152588; | |
| // Returns true every time the input value changes | |
| fun change(x:real):bool { | |
| mem pre_x; | |
| val v:bool = pre_x<>x; | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true every time the input value changes | |
| fun bchange(x:bool):bool { | |
| mem pre_x; | |
| val v:bool = pre_x<>x; | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true if the value changes from 0 to anything | |
| fun edge(x):bool { | |
| mem pre_x; | |
| val v:bool = (pre_x<>x) && (pre_x==true); | |
| pre_x = x; | |
| return v; | |
| } | |
| // Returns true every 'n' calls | |
| fun each(n){ | |
| mem count; | |
| val ret = (count == 0); | |
| count = (count + 1) % n; | |
| return ret; | |
| } | |
| // Returns true if the input value is near zero (< 1e-2) | |
| fun near_zero(x) : bool return abs(x)<2e-2; | |
| // Filters the DC component of a signal | |
| fun dcblock(x0:real) : real { | |
| mem x1,y1; | |
| val y0 = x0-x1+y1*0.995; | |
| x1,y1 = x0,y0; | |
| return y0; | |
| } | |
| // Used to soften the transitions of controls | |
| fun smooth(input:real) : real { | |
| mem x; | |
| x = x+(input-x)*0.005; | |
| return x; | |
| } | |
| // Average two samples | |
| fun lpfilter(x:real) : real { | |
| mem pre_x; | |
| val ret = (x+pre_x)/2.; | |
| pre_x = x; | |
| return ret; | |
| } | |
| // ==== OSCILLATOR ===== | |
| // Converts the MIDI note to increment rate at a 44100 sample rate | |
| fun pitchToRate(d) : real | |
| return 8.1758*exp(0.0577623*d)/44100.0; | |
| // Generates a BW-limited pulse train given the phase and the number of harmonics | |
| fun pulse_train(m:real,phase:real) : real { | |
| val pi_phase = phase * 3.141592653589793; | |
| val denominator1 = sin(pi_phase); | |
| val tmp1 = 0.; | |
| if(near_zero(denominator1)) { | |
| tmp1 = 1.; | |
| } | |
| else { | |
| tmp1 = sin(m * pi_phase); | |
| tmp1 = tmp1 / (m * denominator1); | |
| } | |
| return tmp1; | |
| } | |
| // Generates BW-limited waveforms using the blit algorithm. | |
| // It can generate PWM puses, saws and triangles. | |
| fun osc(pitch:real,pw:real,wave:real) : real { | |
| mem m; | |
| mem rate; | |
| mem phase; | |
| mem state_triang; | |
| mem state_pulse; | |
| mem state_saw; | |
| mem output; | |
| val fixed_pitch = 0.; | |
| if(wave < 2. / 3.) { | |
| fixed_pitch = pitch; | |
| } | |
| else { | |
| fixed_pitch = pitch + 12.; | |
| } | |
| // Updates the parameters if the pitch changed | |
| if(change(fixed_pitch)) { | |
| rate = pitchToRate(fixed_pitch); | |
| val p = 1. / rate; | |
| val maxHarmonics = floor(p/2.); | |
| m = 2. * maxHarmonics + 1.; | |
| } | |
| // Generates a shifted version of the phase | |
| val shift05 = 0.5 + pw * 0.49; | |
| val shift = phase + shift05; | |
| if(shift > 1.) { | |
| shift = shift - 1.; | |
| } | |
| // Generates the first pulse train | |
| val tmp1 = pulse_train(m,phase); | |
| // Generates the second pulse train | |
| val tmp2 = pulse_train(m,shift); | |
| // Updates the phase | |
| phase = phase + rate; | |
| if(phase > 1.) { | |
| phase = phase - 1.; | |
| } | |
| // Calculates the waveforms based on the pulse trains | |
| state_pulse = clip(state_pulse * 0.9995 + tmp1 - tmp2, -1., 1.); | |
| state_saw = clip(state_saw * 0.9995 + (tmp1 + tmp2 - 2. * rate)/shift05/2., -1.,1.); | |
| state_triang = clip(state_triang * 0.9995 + 2. * state_pulse * rate, -1.,1.); | |
| // Select the wave to output | |
| if(wave < 1. / 3.) { | |
| output = state_pulse; | |
| } | |
| else if(wave < 2. / 3.) { | |
| output = 2. * state_saw; | |
| } | |
| else { | |
| output = 2. * state_triang*(1. + pw); | |
| } | |
| output = dcblock(output); | |
| return clip(output/4.,-1.,1.); | |
| } | |
| // ==== FILTER ===== | |
| // Calculates one step of the oversampled state-variable filter | |
| fun svf_step(input:real,g:real,q:real,sel:int) : real { | |
| mem dlow, dband; | |
| val low = dlow + g * dband; | |
| val high = input - low - q*dband; | |
| val band = g * high + dband; | |
| val notch = high + low; | |
| dband = clip(band,-1.,1.); | |
| dlow = clip(low,-1.,1.); | |
| val output = | |
| if sel == 0 then low else | |
| if sel == 1 then high else | |
| if sel == 2 then band else | |
| notch; | |
| return output; | |
| } | |
| // Main function for the state-variable filter with 2x of oversampling | |
| fun svf(input,fc,q,sel){ | |
| mem g; | |
| fc = clip(fc, 0., 1.); | |
| q = clip(q, 0., 1.); | |
| val fix_q = 2. * (1. - q); | |
| if(change(fc)){ | |
| g = fc/2.; | |
| } | |
| // In Vult oversamplig in very easy! | |
| val x1 = step:svf_step(input,g,fix_q,sel); | |
| val x2 = step:svf_step(input,g,fix_q,sel); | |
| return (x1+x2)/2.; | |
| } | |
| // ======= LFO ====== | |
| fun lfo(f,gate){ | |
| mem phase; | |
| val rate = f * 100. * minFixed() + minFixed(); | |
| if(edge(gate)) phase = 0.; | |
| if(each(4)) | |
| phase = phase + rate; | |
| if(phase>1.) phase = phase-1.; | |
| return sin(phase * 2. * 3.141592653589793)+0.5; | |
| } | |
| // ==== MONOPHONIC VOICE ===== | |
| /* These three functions handle midi on/off events in order to behave | |
| * like a monophonic sinthesizer that can hold 4 notes */ | |
| // Activates a note and returns the current note value | |
| fun mono_noteOn(n:int){ | |
| mem count,pre; | |
| mem notes : array(int,4); | |
| // Do not add more that the size of array | |
| if(count < size(notes)) { | |
| _ = set(notes,count,n); | |
| pre = n; | |
| if(count < size(notes)) count = count + 1; | |
| } | |
| return pre; | |
| } | |
| // Deactivates a note and returns the following note value; | |
| and mono_noteOff(n:int){ | |
| mem count,pre; | |
| mem notes : array(int,4); | |
| val found = false; | |
| val pos; | |
| val i = 0; | |
| // if there are no notes, no dot do anything | |
| if(count == 0) | |
| return pre; | |
| // Finds the location of the note | |
| while(i < size(notes) && not(found)){ | |
| if(get(notes,i) == n) { | |
| pos = i; | |
| found = true; | |
| } | |
| i = i + 1; | |
| } | |
| // if the note was found moves all the notes one location | |
| if(found) { | |
| val k = pos + 1; | |
| while(k < size(notes)) { | |
| _ = set(notes,k-1,get(notes,k)); | |
| k = k + 1; | |
| } | |
| // If found, decrease the number of active notes | |
| if(found && count>0) { | |
| count = count - 1; | |
| pre = get(notes,count - 1); | |
| } | |
| } | |
| return pre; | |
| } | |
| // Returns 1 if any note is active | |
| and mono_isGateOn() { | |
| mem count; | |
| return count > 0; | |
| } | |
| // Main process function | |
| fun process(i:real){ | |
| mem volume; | |
| mem pitch, pw, wave; // oscillator parameters | |
| mem lfo_rate,lfo_amt; // LFO parameter | |
| mem cut, res; // Filter parameters | |
| val gate = monoin:mono_isGateOn(); | |
| // Creates one LFO | |
| val lfo1 = lfo(lfo_rate,gate)*lfo_amt; | |
| // Creates one oscillator | |
| val o1 = osc(pitch,pw+lfo1,wave); | |
| // gets the amplification by using a low-pass on the gate | |
| val amp_env = smooth(if gate then 1.0 else 0.0); | |
| // creates one state-variable filter | |
| val output = amp_env * svf(o1,cut,res,0); | |
| return volume * output; | |
| } | |
| and noteOn(note:int,velocity:int){ | |
| mem pitch = real(monoin:mono_noteOn(note)); | |
| } | |
| and noteOff(note:int){ | |
| mem pitch = real(monoin:mono_noteOff(note)); | |
| } | |
| // Called when a control changes | |
| and controlChange(control:int,value:int){ | |
| mem volume; | |
| mem pitch, pw, wave; // oscillator parameters | |
| mem lfo_rate,lfo_amt; // LFO parameter | |
| mem cut, res; // Filter parameters | |
| val value_0_1 = real(value) / 127.0; | |
| val value_m1_1 = value_0_1 * 2.0 - 1.0; | |
| if(control == 30) volume = value_0_1; | |
| if(control == 31) wave = value_0_1; | |
| if(control == 32) pw = value_0_1; | |
| if(control == 33) lfo_rate = value_0_1; | |
| if(control == 34) lfo_amt = value_m1_1; | |
| if(control == 35) cut = value_0_1; | |
| if(control == 36) res = value_0_1; | |
| } | |
| // Called on initialization to define initial values | |
| and default() @[init] { | |
| mem pw = 0.0; | |
| mem pitch = 42.0; | |
| mem cut = 1.0; | |
| mem res = 0.0; | |
| mem amp_s = 1.0; | |
| mem lfo_amt = 0.5; | |
| mem lfo_rate = 0.0; | |
| mem volume = 0.5; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* You can use a this template to start a program */ | |
| // Main processing function | |
| // 'input' is by default a sine wave at 440 Hz | |
| fun process(input:real){ | |
| return input; | |
| } | |
| // Called when a note On is received | |
| and noteOn(note:int,velocity:int){ | |
| } | |
| // Called when a note Off is received | |
| and noteOff(note:int){ | |
| } | |
| // Called when a control changes | |
| and controlChange(control:int,value:int){ | |
| } | |
| // Called on initialization to define initial values | |
| and default(){ | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| = A simple volume control = | |
| CC30 - Volume | |
| */ | |
| // Used to soften the transitions of controls | |
| fun smooth(input){ | |
| mem x; | |
| x = x+(input-x)*0.005; | |
| return x; | |
| } | |
| // Main processing function | |
| // 'input' is by default a sine wave at 440 Hz | |
| fun process(input:real){ | |
| mem volume; // the value is set in 'controlChange' | |
| return input*smooth(volume); | |
| } | |
| // Called when a note On is received | |
| and noteOn(note:int,velocity:int){ | |
| } | |
| // Called when a note Off is received | |
| and noteOff(note:int){ | |
| } | |
| // Called when a control changes | |
| and controlChange(control:int,value:int){ | |
| mem volume; | |
| // Control 30 defines the volume | |
| if(control==30) volume = real(value)/127.0; | |
| } | |
| // Called on initialization to define initial values | |
| and default(){ | |
| mem volume = 0.5; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment