Cigarbox

Cigarbox closed Cigarbox open

Teensy audio library

#include <Audio.h>
#include <movingAvg.h>
#include <Wire.h>
#include <SPI.h>
#include <SerialFlash.h>
#include <Bounce.h>
#include <Metro.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine1;          //xy=167.9166717529297,448.3333435058594
AudioSynthWaveform       waveform1;      //xy=171.11111111111111,103.33333333333333
AudioSynthWaveformModulated waveformMod1;   //xy=187.5,215
AudioEffectEnvelope      envelope1;      //xy=346.25,105
AudioEffectEnvelope      envelope2;      //xy=367.5,217.5
AudioEffectFreeverb      freeverb1;      //xy=411.25,388.75
AudioSynthWaveformPWM    pwm1;           //xy=413.75,486.25
AudioAmplifier           amp3;           //xy=458.75,445
AudioFilterLadder        ladder1;        //xy=517.5,117.5
AudioFilterStateVariable filter1;        //xy=520,276.25
AudioEffectWaveFolder    wavefolder1;    //xy=587.5,491.25
AudioEffectFlange        flange1;        //xy=600,365
AudioEffectDigitalCombine combine1;       //xy=625.0000610351562,226.25
AudioAmplifier           amp4;           //xy=687.5,116.25
AudioAmplifier           amp5;           //xy=687.5,151.25
AudioAmplifier           amp6;           //xy=728.75,185
AudioMixer4              mixer2;         //xy=747.5,407.5
AudioAmplifier           amp2;           //xy=791.25,292.5
AudioMixer4              mixer1;         //xy=856.25,160
AudioAmplifier           amp1;           //xy=938.75,318.75
AudioOutputI2S           i2s1;           //xy=1000,396.25
AudioConnection          patchCord1(sine1, 0, waveformMod1, 0);
AudioConnection          patchCord2(waveform1, envelope1);
AudioConnection          patchCord3(waveformMod1, envelope2);
AudioConnection          patchCord4(envelope1, 0, ladder1, 0);
AudioConnection          patchCord5(envelope2, 0, combine1, 1);
AudioConnection          patchCord6(envelope2, 0, filter1, 0);
AudioConnection          patchCord7(envelope2, amp5);
AudioConnection          patchCord8(freeverb1, 0, mixer2, 2);
AudioConnection          patchCord9(pwm1, 0, wavefolder1, 1);
AudioConnection          patchCord10(amp3, 0, wavefolder1, 0);
AudioConnection          patchCord11(ladder1, 0, combine1, 0);
AudioConnection          patchCord12(ladder1, amp4);
AudioConnection          patchCord13(filter1, 0, amp3, 0);
AudioConnection          patchCord14(filter1, 1, flange1, 0);
AudioConnection          patchCord15(filter1, 2, freeverb1, 0);
AudioConnection          patchCord16(wavefolder1, 0, mixer2, 0);
AudioConnection          patchCord17(flange1, 0, mixer2, 1);
AudioConnection          patchCord18(combine1, amp6);
AudioConnection          patchCord19(amp4, 0, mixer1, 0);
AudioConnection          patchCord20(amp5, 0, mixer1, 1);
AudioConnection          patchCord21(amp6, 0, mixer1, 2);
AudioConnection          patchCord22(mixer2, amp2);
AudioConnection          patchCord23(amp2, 0, mixer1, 3);
AudioConnection          patchCord24(mixer1, amp1);
AudioConnection          patchCord25(amp1, 0, i2s1, 0);
AudioConnection          patchCord26(amp1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=925,478.75
// GUItool: end automatically generated code

#define FLANGE_DELAY_LENGTH (20*AUDIO_BLOCK_SAMPLES)
short delayline[FLANGE_DELAY_LENGTH];
int s_idx = FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
float s_freq = .5;

float noteMap[128] = { 8.18, 8.66, 9.18, 9.72, 10.3, 10.91, 11.56, 12.25, 12.98, 13.75, 14.57, 15.43, 16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87, 32.7, 34.65, 36.71, 38.89, 41.2, 43.65, 46.25, 49, 51.91, 55, 58.27, 61.74, 65.41, 69.3, 73.42, 77.78, 82.41, 87.31, 92.5, 98, 103.83, 110, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392, 415.3, 440, 466.16, 493.88, 523.25, 554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, 880, 932.33, 987.77, 1046.5, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1479.98, 1567.98, 1661.22, 1760, 1864.66, 1975.53, 2093, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2959.96, 3135.96, 3322.44, 3520, 3729.31, 3951.07, 4186.01, 4434.92, 4698.64, 4978.03, 5274.04, 5587.65, 5919.91, 6271.93, 6644.88, 7040, 7458.62, 7902.13, 8372.02, 8869.84, 9397.27, 9956.06, 10548.08, 11175.3, 11839.82, 12543.85 };
uint16_t knobs[15];
uint8_t I = 1;
uint8_t II = 3;
uint8_t III = 0;
uint8_t IV = 4;
uint8_t V = 2;
uint8_t VI = 6;
uint8_t VII = 5;
uint8_t VIII = 7;
uint8_t IX = 9;
uint8_t X = 8;
uint8_t XI = 12;
uint8_t XII = 10;
uint8_t XIII = 14;
uint8_t XIV = 13;
uint8_t XV = 11;
byte byteArray[32];
byte pot[7] = { A10, A11, A12, A14, A15, A16, A17 };
int potVal[7] = { 0, 0, 0, 0, 0, 0, 0 };
int potAvg[7] = { 0, 0, 0, 0, 0, 0, 0 };
int noteBuffer[2] = { 0, 0 };
int notes[128];
byte avgDepth = 10;
byte bufferIndex = 0;
movingAvg potAvg0(avgDepth);
movingAvg potAvg1(avgDepth);
movingAvg potAvg2(avgDepth);
movingAvg potAvg3(avgDepth);
movingAvg potAvg4(avgDepth);
movingAvg potAvg5(avgDepth);
movingAvg potAvg6(avgDepth);
bool knobMsg, noteMsg;
const int buttonPin = 36;
int envAttack = 8;
int envHold = 50;
int envDecay = 70;
float envSustain = 0.6;
int envRelease = 60;


Metro notePeriod = Metro(650);
Metro noteLength = Metro(200);
Metro blinkPeriod = Metro(400);
Metro blinkLength = Metro(400);
Metro logDelay = Metro(250);

unsigned long now;
unsigned long then;

int waveCurrent = 8;
int waveModCurrent = 8;
int octaveOffset = 0;

void setup() {
  Wire1.begin(33);
  Wire1.onReceive(onReceivePayload);
  Serial.begin(31250);
  potAvg0.begin();
  potAvg1.begin();
  potAvg2.begin();
  potAvg3.begin();
  potAvg4.begin();
  potAvg5.begin();
  potAvg6.begin();
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  then = millis();
  AudioMemory(10);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  //defaults
  waveform1.frequency(440);
  waveform1.amplitude(1.0);
  waveform1.begin(WAVEFORM_TRIANGLE);
  waveformMod1.frequency(440);
  waveformMod1.amplitude(1.0);
  waveformMod1.begin(WAVEFORM_TRIANGLE);
  sine1.frequency(15.0);
  sine1.amplitude(15.0);
  envelope1.releaseNoteOn(10);
  envelope2.releaseNoteOn(10);
  flange1.begin(delayline,FLANGE_DELAY_LENGTH,s_idx,s_depth,s_freq);

  mixer1.gain(0,1.0);
  mixer1.gain(1,1.0);
  mixer1.gain(2,1.0);
  mixer1.gain(3,1.0);
}

void loop() {
  bool buttonState = digitalRead(buttonPin);

  readKnobs();
  if (logDelay.check() == 1 && !buttonState) {
    logKnobs();
  }

  setWaveform();
  updateWaveformMod();
  updateLfo();
  setEnvelope();
  updateLadder();
  updateSplit();
  updateCombine();
  updateFlange();
  updateReverb();
  updateWavefolder();
  updateMixers();

  // testNotes();
  blinkLed();
}

void setWaveform() {
  int waveSelect = map(knobs[I], 0, 1023, 1, 8);
  int previousWave = waveCurrent;
  switch (waveSelect) {
    case 1:
      waveCurrent = WAVEFORM_SAWTOOTH;
      break;
    case 2:
      waveCurrent = WAVEFORM_SAWTOOTH_REVERSE;
      break;
    case 3:
      waveCurrent = WAVEFORM_SQUARE;
      break;
    case 4:
      waveCurrent = WAVEFORM_TRIANGLE;
      break;
    case 5:
      waveCurrent = WAVEFORM_TRIANGLE_VARIABLE;
      break;
    case 6:
      waveCurrent = WAVEFORM_PULSE;
      break;
    case 7:
      waveCurrent = WAVEFORM_SAMPLE_HOLD;
      break;
    case 8:
      waveCurrent = WAVEFORM_SINE;
      break;
  }
  if (previousWave != waveCurrent) {
    AudioNoInterrupts();
    waveform1.begin(waveCurrent);
    AudioInterrupts();
  }
};
void updateWaveformMod(){
  int waveSelect = map(knobs[II], 0, 1023, 1, 8);
  octaveOffset = map(knobs[VI], 0, 1023, -3, 3);
  int previousModWave = waveModCurrent;
  switch (waveSelect) {
    case 1:
      waveModCurrent = WAVEFORM_SAWTOOTH;
      break;
    case 2:
      waveModCurrent = WAVEFORM_SAWTOOTH_REVERSE;
      break;
    case 3:
      waveModCurrent = WAVEFORM_SQUARE;
      break;
    case 4:
      waveModCurrent = WAVEFORM_TRIANGLE;
      break;
    case 5:
      waveModCurrent = WAVEFORM_TRIANGLE_VARIABLE;
      break;
    case 6:
      waveModCurrent = WAVEFORM_PULSE;
      break;
    case 7:
      waveModCurrent = WAVEFORM_SAMPLE_HOLD;
      break;
    case 8:
      waveModCurrent = WAVEFORM_SINE;
      break;
  }
  if (previousModWave != waveModCurrent) {
    AudioNoInterrupts();
    waveformMod1.begin(waveModCurrent);
    waveformMod1.frequencyModulation(2);
    AudioInterrupts();
  }
};
void updateLfo(){
  AudioNoInterrupts();
  if (knobs[III] > 2) {
    float lfoRate = (knobs[III]/1023.0)*30.0;
    sine1.frequency(lfoRate);
    sine1.amplitude(1.0);
  } else {
    sine1.amplitude(0.0);
  }
  AudioInterrupts();
};
void setEnvelope(){
  int envSelect = map(knobs[XI], 0, 1023, 1, 4);
  switch (envSelect) {
    case 1:
      envAttack = 5;
      envHold = 10;
      envDecay = 50;
      envSustain = 1;
      envRelease = 5;
      break;
    case 2:
      envAttack = 8;
      envHold = 50;
      envDecay = 70;
      envSustain = 0.8;
      envRelease = 60;
      break;
    case 3:
      envAttack = 100;
      envHold = 100;
      envDecay = 150;
      envSustain = 1;
      envRelease = 200;
      break;
    case 4:
      envAttack = 300;
      envHold = 200;
      envDecay = 70;
      envSustain = 0.8;
      envRelease = 400;
      break;
  }
  AudioNoInterrupts();
  envelope1.attack(envAttack);
  envelope1.hold(envHold);
  envelope1.decay(envDecay);
  envelope1.sustain(envSustain);
  envelope1.release(envRelease);
  envelope2.attack(envAttack);
  envelope2.hold(envHold);
  envelope2.decay(envDecay);
  envelope2.sustain(envSustain);
  envelope2.release(envRelease);
  AudioInterrupts();
};
void updateLadder(){
  float ladFrequency = ((knobs[IV]/1023.0)*6000.0 + 20);
  float ladResonance = (knobs[VIII]/1023.0);
  AudioNoInterrupts();
  ladder1.inputDrive(1.5);
  ladder1.frequency(ladFrequency);
  ladder1.resonance(ladResonance);
  AudioInterrupts();
};
void updateSplit(){
  float splitFrequency = (knobs[VII]/1023.0)*4000.0;
  AudioNoInterrupts();
  filter1.frequency(splitFrequency);
  ladder1.resonance(0.705);
  AudioInterrupts();
};
void updateCombine(){
  int comSelect = map(knobs[IX], 0, 1023, 1, 5);
  byte comMode = 0;
    switch (comSelect) {
    case 1:
      comMode = 0;
      break;
    case 2:
      comMode = 0;
      break;
    case 3:
      comMode = 1;
      break;
    case 4:
      comMode = 2;
      break;
    case 5:
      comMode = 3;
      break;
  }
  AudioNoInterrupts();
  if (comSelect > 1) {
    amp4.gain(0);
    amp5.gain(0);
    amp6.gain(1.0);
    combine1.setCombineMode(comMode);
  } else {
    amp4.gain(1.0);
    amp5.gain(1.0);
    amp6.gain(0);
  }
  AudioInterrupts();
};
void updateFlange() {
  float flangeMod = (knobs[X]/1023.0);
  s_idx = ((flangeMod * 2)+2) * FLANGE_DELAY_LENGTH/4;
  s_depth = ((flangeMod * 2)+2) * FLANGE_DELAY_LENGTH/4;
  s_freq = .8;
  AudioNoInterrupts();
  flange1.voices(s_idx,s_depth,s_freq);
  AudioInterrupts();
}
void updateReverb() {
  float revTime = (knobs[V]/1023.0);
  AudioNoInterrupts();
  freeverb1.roomsize(revTime);
  AudioInterrupts();
}
void updateWavefolder() {
  float foldControl = (knobs[XIII]/1023.0);
  AudioNoInterrupts();
  amp3.gain(foldControl*5.0);
  pwm1.amplitude(foldControl);
  pwm1.frequency(150.0);
  AudioInterrupts();
}

void updateMixers(){
  float mainVolume = (knobs[XIV]/1023.0);
  float fxVolume = (knobs[XV]/1023.0);
  float mixFade = (knobs[XII]/1023.0);
  float chWave, chWaveMod;
  if (mixFade <= .5) {
    chWave = 1.0;
    chWaveMod = mixFade / .5;
  } else {
    chWave = 1.0 - ((mixFade - .5) / .5);
    chWaveMod = 1.0;
  }
  // Serial.print("chWave: ");
  // Serial.print(chWave);
  // Serial.print(" chWaveMod: ");
  // Serial.println(chWaveMod);
  AudioNoInterrupts();
  amp1.gain(mainVolume);
  amp2.gain(fxVolume);
  mixer1.gain(0,chWave);
  mixer1.gain(1,chWaveMod);
  AudioInterrupts();
};

void testNotes() {
  if (notePeriod.check() == 1) {
    AudioNoInterrupts();
    if (envelope1.isActive()) {
      envelope1.noteOff();
    }
    waveform1.frequency(random(100, 800));
    envelope1.noteOn();
    AudioInterrupts();
    noteLength.check();
  }

  if (noteLength.check() == 1 && envelope1.isActive()) {
    AudioNoInterrupts();
    envelope1.noteOff();
    AudioInterrupts();
  }
}

void readKnobs() {
  for (uint8_t i = 0; i < sizeof(potVal) / sizeof(potVal[0]); i++) {
    potVal[i] = analogRead(pot[i]);
  }
  knobs[8] = potAvg0.reading(potVal[0]);
  knobs[9] = potAvg1.reading(potVal[1]);
  knobs[10] = potAvg2.reading(potVal[2]);
  knobs[11] = potAvg3.reading(potVal[3]);
  knobs[12] = potAvg4.reading(potVal[4]);
  knobs[13] = potAvg5.reading(potVal[5]);
  knobs[14] = potAvg6.reading(potVal[6]);
}

void onReceivePayload(int payloadSize) {
  if (payloadSize > 0) {
    for (int i = 0; i < payloadSize; i++) {
      byteArray[bufferIndex] = Wire1.read();
      bufferIndex++;

      if (bufferIndex == payloadSize) {
        bufferIndex = 0;
        if (payloadSize == 16) {
          for (uint8_t i = 0; i < 8; i++) {
            knobs[i] = byteArray[i * 2] | byteArray[i * 2 + 1] << 8;
          }
          knobMsg = !knobMsg;
        }
        if (payloadSize == 4) {
          for (uint8_t i = 0; i < 2; i++) {
            noteBuffer[i] = byteArray[i * 2] | byteArray[i * 2 + 1] << 8;
          }
          handleMidiEvent(noteBuffer[0], noteBuffer[1]);
        }
      }
    }
  }
}

void logKnobs() {
  Serial.print("I: ");
  Serial.print(knobs[I]);
  Serial.print(" II: ");
  Serial.print(knobs[II]);
  Serial.print(" III: ");
  Serial.print(knobs[III]);
  Serial.print(" IV: ");
  Serial.print(knobs[IV]);
  Serial.print(" V: ");
  Serial.print(knobs[V]);
  Serial.print(" VI: ");
  Serial.print(knobs[VI]);
  Serial.print(" VII: ");
  Serial.print(knobs[VII]);
  Serial.print(" VIII: ");
  Serial.print(knobs[VIII]);
  Serial.print(" IX: ");
  Serial.print(knobs[IX]);
  Serial.print(" X: ");
  Serial.print(knobs[X]);
  Serial.print(" XI: ");
  Serial.print(knobs[XI]);
  Serial.print(" XII: ");
  Serial.print(knobs[XII]);
  Serial.print(" XIII: ");
  Serial.print(knobs[XIII]);
  Serial.print(" XIV: ");
  Serial.print(knobs[XIV]);
  Serial.print(" XV: ");
  Serial.print(knobs[XV]);
  now = millis();
  if (knobMsg) {
    Serial.print(" receiving");
    knobMsg = !knobMsg;
    then = now;
  } else if ((now - then) > 1000) {
    Serial.print(" not receiving");
  }
  Serial.println();
}

void handleMidiEvent(int p, int v) {
  // Serial.print("Note event: ");
  if (v == 0) {
    notes[p] = 0;
    // Serial.print("noteOff ");
    // Serial.print(p);
    digitalWrite(LED_BUILTIN, LOW);

    AudioNoInterrupts();
    envelope1.noteOff();
    envelope2.noteOff();
    AudioInterrupts();
  } else {
    int offset = p + (octaveOffset * 12);
    offset = constrain(offset, 0, 127);
    float noteFrequency = noteMap[p];
    float noteOffsetFrequency = noteMap[offset];
    float noteVelocity = v / 127.0;
    notes[p] = v;
    // Serial.print("noteOn p-");
    // Serial.print(p);
    // Serial.print(" v-");
    // Serial.print(noteVelocity);
    // Serial.print(" frequency-");
    // Serial.print(noteFrequency);
    digitalWrite(LED_BUILTIN, HIGH);

    AudioNoInterrupts();
    if (envelope1.isActive()) {
      envelope1.noteOff();
      envelope2.noteOff();
    }
    waveform1.frequency(noteFrequency);
    waveform1.amplitude(noteVelocity);
    envelope1.noteOn();
    waveformMod1.frequency(noteOffsetFrequency);
    waveformMod1.amplitude(noteVelocity);
    envelope2.noteOn();
    AudioInterrupts();
  }
  // Serial.println();
}

void blinkLed() {
  if (blinkPeriod.check() == 1) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else if (blinkLength.check() == 1) {
    digitalWrite(LED_BUILTIN, LOW);
  }
}