diff --git a/FM/FM.ino b/FM/FM.ino new file mode 100644 index 0000000..8605b16 --- /dev/null +++ b/FM/FM.ino @@ -0,0 +1,129 @@ +#include +#include // oscillator +#include // table for Oscils to play +#include +#include // maps unpredictable inputs to a range +#include + +#define CONTROL_RATE 64 + +bool gate = 0; + + +// desired carrier frequency max and min, for AutoMap +const int MIN_CARRIER_FREQ = 22; +const int MAX_CARRIER_FREQ = 440; + +const int MIN = 1; +const int MAX = 10; + +const int MIN_2 = 1; +const int MAX_2 = 15; + +// desired intensity max and min, for AutoMap, note they're inverted for reverse dynamics +const int MIN_INTENSITY = 700; +const int MAX_INTENSITY = 10; + +// desired mod speed max and min, for AutoMap, note they're inverted for reverse dynamics +const int MIN_MOD_SPEED = 10000; +const int MAX_MOD_SPEED = 1; + +AutoMap kMapCarrierFreq(0,1023,MIN_CARRIER_FREQ,MAX_CARRIER_FREQ); +AutoMap kMapIntensity(0,1023,MIN_INTENSITY,MAX_INTENSITY); +AutoMap kMapModSpeed(0,1023,MIN_MOD_SPEED,MAX_MOD_SPEED); +AutoMap mapThis(0,1023,MIN,MAX); +AutoMap mapThisToo(0,1023,MIN_2,MAX_2); + +//Mapping the knob pins +const int CONTROLL1 = 0; +const int CONTROLL2 = 1; +const int CONTROLL3 = 2; +const int CONTROLL4 = 3; + +Oscil aCarrier(COS2048_DATA); +Oscil aModulator(COS2048_DATA); +Oscil kIntensityMod(COS2048_DATA); + +int mod_ratio = 5; // brightness (harmonics) +long fm_intensity; // carries control info from updateControl to updateAudio + +// smoothing for intensity to remove clicks on transitions +float smoothness = 0.95f; +Smooth aSmoothIntensity(smoothness); + +const float notefreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85}; +int carrier_freq = 440; + +void noteOn(byte channel, byte note, byte velocity) { + carrier_freq = notefreqs[(int) note]; + gate = 1; +} + +void noteOff(byte channel, byte note, byte velocity) { + gate = 0; +} + +void setup(){ + startMozzi(); + + pinMode(LED_BUILTIN_TX,INPUT); //switch rx and tx leds of, so they don't blink on midi + pinMode(LED_BUILTIN_RX,INPUT); +} + + +void updateControl(){ + midiEventPacket_t rx; + do { + rx = MidiUSB.read(); + if (rx.header == 0x09) { + noteOn(rx.byte1, rx.byte2, rx.byte3); + } else if (rx.header == 0x08) { + noteOff(rx.byte1, rx.byte2, rx.byte3); + } + } while (rx.header != 0); + + int freqVal = mozziAnalogRead(CONTROLL3); // value is 0-1023 + int FRQ = mapThis(freqVal); + + int knob2 = mozziAnalogRead(CONTROLL4); // value is 0-1023 + int knob2Val = mapThis(knob2); + + //calculate the modulation frequency to stay in ratio + int mod_freq = carrier_freq * mod_ratio * FRQ; + + // set the FM oscillator frequencies + aCarrier.setFreq(carrier_freq); + aModulator.setFreq(mod_freq); + + // read the light dependent resistor on the width Analog input pin + int LDR1_value= mozziAnalogRead(CONTROLL1); // value is 0-1023 + + + int LDR1_calibrated = kMapIntensity(LDR1_value); + + + // calculate the fm_intensity + fm_intensity = ((long)LDR1_calibrated * knob2Val * (kIntensityMod.next()+128))>>8; // shift back to range after 8 bit multiply + + + // read the light dependent resistor on the speed Analog input pin + int LDR2_value= mozziAnalogRead(CONTROLL2); // value is 0-1023 + + + // use a float here for low frequencies + float mod_speed = (float)kMapModSpeed(LDR2_value)/1000; + + kIntensityMod.setFreq(mod_speed); +} + + +int updateAudio(){ + long modulation = aSmoothIntensity.next(fm_intensity) * aModulator.next(); + if (gate == 1) { + return aCarrier.phMod(modulation);//(int)(envelope.next() * aCarrier.phMod(modulation))>>8; + } +} + +void loop(){ + audioHook(); +}