#include #include #include // oscillator #include // table for Oscils to play #include #include // maps unpredictable inputs to a range #include #include MIDI_CREATE_DEFAULT_INSTANCE(); #define CONTROL_RATE 64 #define MIDI_CHANNEL 3 bool gate = 0; byte noteBuffer[8]; byte bufferIndex = 0; // 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; const int MIN = 10; const int MAX = 1; const int MIN_2 = 1; const int MAX_2 = 15; 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); int carrier_freq; void noteOn(byte channel, byte note, byte velocity) { if (channel == MIDI_CHANNEL) { gate = 1; updateBuffer(note, gate); //playNote(); // this is called from within buffer update } } void noteOff(byte channel, byte note, byte velocity) { if (channel == MIDI_CHANNEL) { gate = 0; updateBuffer(note, gate); } } void updateBuffer(byte bNote, bool bGate) { if (bGate == 1) { noteBuffer[bufferIndex] = bNote; playNote(); bufferIndex++; } if (bGate == 0) { // && bufferIndex != 0 for (int i = 0; i <= bufferIndex; i++) { if (noteBuffer[i] == bNote) { // Removing the note from the array and shifting everything to close the gap for (int n = i; n <= bufferIndex; n++) { noteBuffer[n] = noteBuffer[n + 1]; // what happens if it's the last note in buffer? } if (i == bufferIndex) { //this does not fire bufferIndex--; gate = 1; playNote(); } else { //this does fire bufferIndex--; } } } } } void playNote() { byte note = noteBuffer[bufferIndex]; carrier_freq = mtof((int) note); } void setup(){ // switch rx and tx leds of, so they don't blink on midi pinMode(LED_BUILTIN_TX,INPUT); pinMode(LED_BUILTIN_RX,INPUT); startMozzi(); //MIDI DIN MIDI.setHandleNoteOn(noteOn); MIDI.setHandleNoteOff(noteOff); MIDI.begin(MIDI_CHANNEL); } void updateControl(){ //MIDI USB midiEventPacket_t rx; do { rx = MidiUSB.read(); if (rx.header == 0x09) { noteOn(rx.byte1 - 143, rx.byte2, rx.byte3); //need to figure out what's with this 143 and 127 on noteoff } else if (rx.header == 0x08) { noteOff(rx.byte1 - 127, rx.byte2, rx.byte3); } } while (rx.header != 0); //Knob 3 int freqVal = mozziAnalogRead(CONTROLL3); // value is 0-1023 int FRQ = mapThis(freqVal); //Knob 4 int knob4 = mozziAnalogRead(CONTROLL4); // value is 0-1023 int knob4calibrated = mapThis(knob4); //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); //Knob 1 int Knob1value= mozziAnalogRead(CONTROLL1); // value is 0-1023 int Knob1calibrated = kMapIntensity(Knob1value); // calculate the fm_intensity fm_intensity = ((long)Knob1calibrated * knob4calibrated * (kIntensityMod.next()+128))>>8; // shift back to range after 8 bit multiply // Knob 2 int Knob2value= mozziAnalogRead(CONTROLL2); // value is 0-1023 // use a float here for low frequencies float mod_speed = (float)kMapModSpeed(Knob2value)/1000; kIntensityMod.setFreq(mod_speed); // Debugging Serial.print("Buffer Index: "); Serial.print(bufferIndex); Serial.print(" | Knob1: "); //3rd on the pannel, connected to A0 Serial.print(Knob1calibrated); Serial.print(" | Knob2: "); //2nd on the pannel, conntcted to A1 Serial.print(Knob2value); Serial.print(" | Knob3: "); //1st on the pannel, connected to A2, unstable around 0 Serial.print(FRQ); Serial.print(" | Knob4: "); //4th on the pannel, A3 Serial.print(knob4calibrated); Serial.println(); // MIDI DIN MIDI.read(); } AudioOutput_t 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(); }