ref: 21f5ac6f65245a6d5f1b63b0f1a38d4001f1d5dc
dir: /LEAF/Src/sfx.c/
/* * sfx.c * * Created on: Dec 23, 2019 * Author: josnyder */ #include "main.h" #include "sfx.h" #include "oled.h" #include "tunings.h" #include "MIDI_application.h" float presetKnobValues[PresetNil][NUM_ADC_CHANNELS]; uint8_t knobActive[NUM_ADC_CHANNELS]; //audio objects tFormantShifter fs; tAutotune autotuneMono; tAutotune autotunePoly; tRetune retune; tRetune retune2; tRamp pitchshiftRamp; tRamp nearWetRamp; tRamp nearDryRamp; tPoly poly; tRamp polyRamp[NUM_VOC_VOICES]; tRamp comp; tBuffer buff; tBuffer buff2; tSampler sampler; tEnvelopeFollower envfollow; tOversampler oversampler; tLockhartWavefolder wavefolder1; tLockhartWavefolder wavefolder2; tLockhartWavefolder wavefolder3; tLockhartWavefolder wavefolder4; tHighpass wfHP; tCrusher crush; tCrusher crush2; tTapeDelay delay; tSVF delayLP; tSVF delayHP; tTapeDelay delay2; tSVF delayLP2; tSVF delayHP2; tHighpass delayShaperHp; tFeedbackLeveler feedbackControl; tCycle testSine; tExpSmooth smoother1; tExpSmooth smoother2; tExpSmooth smoother3; tExpSmooth neartune_smoother; #define NUM_STRINGS 6 tLivingString theString[NUM_STRINGS]; float myFreq; float myDetune[NUM_STRINGS]; float synthDetune[NUM_VOC_VOICES][NUM_OSC_PER_VOICE]; //control objects float notes[128]; float notePeriods[128]; float noteFreqs[128]; int chordArray[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int chromaticArray[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; int lockArray[12]; float freq[NUM_VOC_VOICES]; float oversamplerArray[OVERSAMPLER_RATIO]; void initGlobalSFXObjects() { calculateNoteArray(); tPoly_init(&poly, NUM_VOC_VOICES); tPoly_setPitchGlideActive(&poly, FALSE); tPoly_setBendSamplesPerTick(&poly, 128); tPoly_setBendGlideTime(&poly, 1.0f); for (int i = 0; i < NUM_VOC_VOICES; i++) { tRamp_init(&polyRamp[i], 10.0f, 1); } tRamp_init(&nearWetRamp, 10.0f, 1); tRamp_init(&nearDryRamp, 10.0f, 1); tRamp_init(&comp, 10.0f, 1); // Note that these are the actual knob values // not the parameter value // (i.e. 0.5 for fine pitch is actually 0.0 fine pitch) presetKnobValues[Vocoder][0] = 0.4f; // volume presetKnobValues[Vocoder][1] = 0.0f; presetKnobValues[Vocoder][2] = 0.0f; presetKnobValues[Vocoder][3] = 0.0f; presetKnobValues[Vocoder][4] = 0.0f; presetKnobValues[Vocoder][5] = 0.0f; presetKnobValues[Pitchshift][0] = 1.0f; // pitch presetKnobValues[Pitchshift][1] = 0.5f; // fine pitch presetKnobValues[Pitchshift][2] = 0.0f; // f amount presetKnobValues[Pitchshift][3] = 0.5f; // formant presetKnobValues[Pitchshift][4] = 0.0f; presetKnobValues[Pitchshift][5] = 0.0f; presetKnobValues[AutotuneMono][0] = 1.0f; // fidelity thresh presetKnobValues[AutotuneMono][1] = 1.0f; // amount presetKnobValues[AutotuneMono][2] = 1.0f; // speed presetKnobValues[AutotuneMono][3] = 0.0f; presetKnobValues[AutotuneMono][4] = 0.0f; presetKnobValues[AutotuneMono][5] = 0.0f; presetKnobValues[AutotunePoly][0] = 1.0f; // fidelity thresh presetKnobValues[AutotunePoly][1] = 0.0f; presetKnobValues[AutotunePoly][2] = 0.0f; presetKnobValues[AutotunePoly][3] = 0.0f; presetKnobValues[AutotunePoly][4] = 0.0f; presetKnobValues[AutotunePoly][5] = 0.0f; presetKnobValues[SamplerButtonPress][0] = 0.0f; // start presetKnobValues[SamplerButtonPress][1] = 1.0f; // end presetKnobValues[SamplerButtonPress][2] = 0.75f; // speed presetKnobValues[SamplerButtonPress][3] = 0.25f; // crossfade presetKnobValues[SamplerButtonPress][4] = 0.0f; presetKnobValues[SamplerButtonPress][5] = 0.0f; presetKnobValues[SamplerAutoGrab][0] = 0.95f; // thresh presetKnobValues[SamplerAutoGrab][1] = 0.5f; // window presetKnobValues[SamplerAutoGrab][2] = 0.0f; // rel thresh presetKnobValues[SamplerAutoGrab][3] = 0.25f; // crossfade presetKnobValues[SamplerAutoGrab][4] = 0.0f; presetKnobValues[SamplerAutoGrab][5] = 0.0f; presetKnobValues[Distortion][0] = 0.25f; // gain presetKnobValues[Distortion][1] = 0.0f; presetKnobValues[Distortion][2] = 0.0f; presetKnobValues[Distortion][3] = 0.0f; presetKnobValues[Distortion][4] = 0.0f; presetKnobValues[Distortion][5] = 0.0f; presetKnobValues[Wavefolder][0] = 0.25f; // gain presetKnobValues[Wavefolder][1] = 0.5f; // offset1 presetKnobValues[Wavefolder][2] = 0.5f; // offset2 presetKnobValues[Wavefolder][3] = 0.5f; // offset3 presetKnobValues[Wavefolder][4] = 0.0f; presetKnobValues[Wavefolder][5] = 0.0f; presetKnobValues[BitCrusher][0] = 0.1f; // quality presetKnobValues[BitCrusher][1] = 0.5f; // samp ratio presetKnobValues[BitCrusher][2] = 0.0f; // rounding presetKnobValues[BitCrusher][3] = 0.0f; // operation presetKnobValues[BitCrusher][4] = 0.5f; // gain presetKnobValues[BitCrusher][5] = 0.0f; presetKnobValues[Delay][0] = 0.25f; // delayL presetKnobValues[Delay][1] = 0.25f; // delayR presetKnobValues[Delay][2] = 0.5f; // feedback presetKnobValues[Delay][3] = 1.0f; // lowpass presetKnobValues[Delay][4] = 0.0f; // highpass presetKnobValues[Delay][5] = 0.0f; presetKnobValues[Reverb][0] = 0.5f; // size presetKnobValues[Reverb][1] = 0.5f; // in lowpass presetKnobValues[Reverb][2] = 0.5f; // in highpass presetKnobValues[Reverb][3] = 0.5f; // fb lowpass presetKnobValues[Reverb][4] = 0.5f; // fb gain presetKnobValues[Reverb][5] = 0.0f; presetKnobValues[Reverb2][0] = 0.2f; // size presetKnobValues[Reverb2][1] = 0.5f; // lowpass presetKnobValues[Reverb2][2] = 0.5f; // highpass presetKnobValues[Reverb2][3] = 0.5f; // peak freq presetKnobValues[Reverb2][4] = 0.5f; // peak gain presetKnobValues[Reverb2][5] = 0.0f; presetKnobValues[LivingString][0] = 0.5f; // freq presetKnobValues[LivingString][1] = 0.5f; // detune presetKnobValues[LivingString][2] = 0.5f; // decay presetKnobValues[LivingString][3] = 0.8f; // damping presetKnobValues[LivingString][4] = 0.5f; // pick pos presetKnobValues[LivingString][5] = 0.0f; presetKnobValues[LivingStringSynth][0] = 0.0f; presetKnobValues[LivingStringSynth][1] = 0.0f; presetKnobValues[LivingStringSynth][2] = 0.5f; // decay presetKnobValues[LivingStringSynth][3] = 0.8f; // damping presetKnobValues[LivingStringSynth][4] = 0.5f; // pick pos presetKnobValues[LivingStringSynth][5] = 0.0f; presetKnobValues[ClassicSynth][0] = 1.0f; // volume presetKnobValues[ClassicSynth][1] = 1.0f; // lowpass presetKnobValues[ClassicSynth][2] = 0.2f; // detune presetKnobValues[ClassicSynth][3] = 0.0f; presetKnobValues[ClassicSynth][4] = 0.0f; presetKnobValues[ClassicSynth][5] = 0.0f; presetKnobValues[Rhodes][0] = 0.5f; presetKnobValues[Rhodes][1] = 0.25f; presetKnobValues[Rhodes][2] = 0.25f; presetKnobValues[Rhodes][3] = 0.0f; presetKnobValues[Rhodes][4] = 0.0f; presetKnobValues[Rhodes][5] = 0.0f; } ///1 vocoder internal poly tTalkbox vocoder; tSawtooth osc[NUM_VOC_VOICES * NUM_OSC_PER_VOICE]; uint8_t numVoices = NUM_VOC_VOICES; uint8_t internalExternal = 0; void SFXVocoderAlloc() { tTalkbox_init(&vocoder, 1024); tPoly_setNumVoices(&poly, numVoices); for (int i = 0; i < NUM_VOC_VOICES; i++) { tSawtooth_initToPool(&osc[i], &smallPool); } setLED_A(numVoices == 1); setLED_B(internalExternal); } void SFXVocoderFrame() { //glideTimeVoc = 5.0f; //tPoly_setPitchGlideTime(&poly, glideTimeVoc); if (buttonActionsSFX[ButtonA][ActionPress] == 1) { numVoices = (numVoices > 1) ? 1 : NUM_VOC_VOICES; tPoly_setNumVoices(&poly, numVoices); buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(numVoices == 1); } if (buttonActionsSFX[ButtonB][ActionPress] == 1) { internalExternal = !internalExternal; buttonActionsSFX[ButtonB][ActionPress] = 0; setLED_B(internalExternal); } for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { tRamp_setDest(&polyRamp[i], (tPoly_getVelocity(&poly, i) > 0)); calculateFreq(i); tSawtooth_setFreq(&osc[i], freq[i]); } if (tPoly_getNumActiveVoices(&poly) != 0) tRamp_setDest(&comp, 1.0f / tPoly_getNumActiveVoices(&poly)); } void SFXVocoderTick(float audioIn) { if (internalExternal == 1) sample = rightIn; else { tPoly_tickPitch(&poly); knobParams[0] = smoothedADC[0]; //vocoder volume for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { sample += tSawtooth_tick(&osc[i]) * tRamp_tick(&polyRamp[i]); } sample *= tRamp_tick(&comp); } sample *= knobParams[0]; sample = tTalkbox_tick(&vocoder, sample, audioIn); sample = tanhf(sample); rightOut = sample; } void SFXVocoderFree(void) { tTalkbox_free(&vocoder); for (int i = 0; i < NUM_VOC_VOICES; i++) { tSawtooth_freeFromPool(&osc[i], &smallPool); } } //4 pitch shift void SFXPitchShiftAlloc() { //tRetune_init(&retune, NUM_RETUNE, 2048, 1024); tFormantShifter_initToPool(&fs, 7, &smallPool); tRetune_init(&retune, NUM_RETUNE, 1024, 512); tRetune_init(&retune2, NUM_RETUNE, 1024, 512); tRamp_init(&pitchshiftRamp, 100.0f, 1); tRamp_setVal(&pitchshiftRamp, 1.0f); tExpSmooth_init(&smoother1, 0.0f, 0.01f); tExpSmooth_init(&smoother2, 0.0f, 0.01f); tExpSmooth_init(&smoother3, 0.0f, 0.01f); } void SFXPitchShiftFrame() { } void SFXPitchShiftTick(float audioIn) { //pitchFactor = (smoothedADC[0]*3.75f)+0.25f; float myPitchFactorCoarse = (smoothedADC[0]*2.0f) - 1.0f; float myPitchFactorFine = ((smoothedADC[1]*2.0f) - 1.0f) * 0.1f; float myPitchFactorCombined = myPitchFactorFine + myPitchFactorCoarse; knobParams[0] = myPitchFactorCombined; knobParams[1] = myPitchFactorCombined; float myPitchFactor = fastexp2f(myPitchFactorCombined); tRetune_setPitchFactor(&retune, myPitchFactor, 0); tRetune_setPitchFactor(&retune2, myPitchFactor, 0); knobParams[2] = LEAF_clip( 0.0f,((smoothedADC[2]) * 3.0f) - 0.2f,3.0f); knobParams[3] = fastexp2f((smoothedADC[3]*2.0f) - 1.0f); tExpSmooth_setDest(&smoother3, knobParams[2]); tFormantShifter_setIntensity(&fs, tExpSmooth_tick(&smoother3)+.1f); tFormantShifter_setShiftFactor(&fs, knobParams[3]); if (knobParams[2] > 0.01f) { tRamp_setDest(&pitchshiftRamp, -1.0f); } else { tRamp_setDest(&pitchshiftRamp, 1.0f); } float crossfadeVal = tRamp_tick(&pitchshiftRamp); float myGains[2]; LEAF_crossfade(crossfadeVal, myGains); tExpSmooth_setDest(&smoother1, myGains[0]); tExpSmooth_setDest(&smoother2, myGains[1]); float formantsample = tanhf(tFormantShifter_remove(&fs, audioIn)); float* samples = tRetune_tick(&retune2, formantsample); formantsample = samples[0]; sample = audioIn; samples = tRetune_tick(&retune, sample); sample = samples[0]; formantsample = tanhf(tFormantShifter_add(&fs, formantsample)) * tExpSmooth_tick(&smoother2) ; sample = (sample * (tExpSmooth_tick(&smoother1))) + formantsample; rightOut = sample; } void SFXPitchShiftFree(void) { tFormantShifter_freeFromPool(&fs, &smallPool); tRetune_free(&retune); tRetune_free(&retune2); tRamp_free(&pitchshiftRamp); tExpSmooth_free(&smoother1); tExpSmooth_free(&smoother2); tExpSmooth_free(&smoother3); } //5 neartune uint8_t autotuneChromatic = 0; void SFXNeartuneAlloc() { tAutotune_init(&autotuneMono, 1, 512, 256); calculateNoteArray(); tExpSmooth_init(&neartune_smoother, 100.0f, .007f); setLED_A(autotuneChromatic); } void SFXNeartuneFrame() { if ((tPoly_getNumActiveVoices(&poly) != 0) || (autotuneChromatic == 1)) { tRamp_setDest(&nearWetRamp, 1.0f); tRamp_setDest(&nearDryRamp, 0.0f); } else { tRamp_setDest(&nearWetRamp, 0.0f); tRamp_setDest(&nearDryRamp, 1.0f); } if (buttonActionsSFX[ButtonA][ActionPress]) { autotuneChromatic = !autotuneChromatic; buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(autotuneChromatic); } } void SFXNeartuneTick(float audioIn) { knobParams[0] = 0.75f + (smoothedADC[0] * 0.22f); tAutotune_setFidelityThreshold(&autotuneMono, knobParams[0]); knobParams[1] = LEAF_clip(0.0f, smoothedADC[1] * 1.1f, 1.0f); // amount of forcing to new pitch knobParams[2] = smoothedADC[2]; //speed to get to desired pitch shift tExpSmooth_setFactor(&neartune_smoother, (knobParams[2] * .01f)); float detectedPeriod = tAutotune_getInputPeriod(&autotuneMono); if (detectedPeriod > 0.0f) { float detectedNote = LEAF_frequencyToMidi(leaf.sampleRate / detectedPeriod); float desiredSnap = nearestNote(detectedPeriod); float destinationNote = (desiredSnap * knobParams[1]) + (detectedNote * (1.0f - knobParams[0])); float destinationFreq = LEAF_midiToFrequency(destinationNote); tExpSmooth_setDest(&neartune_smoother, destinationFreq); } tAutotune_setFreq(&autotuneMono, tExpSmooth_tick(&neartune_smoother), 0); float* samples = tAutotune_tick(&autotuneMono, audioIn); //tAutotune_setFreq(&autotuneMono, leaf.sampleRate / nearestPeriod(tAutotune_getInputPeriod(&autotuneMono)), 0); sample = samples[0] * tRamp_tick(&nearWetRamp); sample += audioIn * tRamp_tick(&nearDryRamp); // crossfade to dry signal if no notes held down. rightOut = sample; } void SFXNeartuneFree(void) { tAutotune_free(&autotuneMono); tExpSmooth_free(&neartune_smoother); } //6 autotune void SFXAutotuneAlloc() { tAutotune_init(&autotunePoly, NUM_AUTOTUNE, 1024, 512); tPoly_setNumVoices(&poly, NUM_AUTOTUNE); //tAutotune_init(&autotunePoly, NUM_AUTOTUNE, 2048, 1024); //old settings } void SFXAutotuneFrame() { for (int i = 0; i < tPoly_getNumVoices(&poly); ++i) { calculateFreq(i); } if (tPoly_getNumActiveVoices(&poly) != 0) tRamp_setDest(&comp, 1.0f / tPoly_getNumActiveVoices(&poly)); } void SFXAutotuneTick(float audioIn) { knobParams[0] = 0.75f + (smoothedADC[0] * 0.22f); tAutotune_setFidelityThreshold(&autotunePoly, knobParams[0]); tPoly_tickPitch(&poly); for (int i = 0; i < tPoly_getNumVoices(&poly); ++i) { tAutotune_setFreq(&autotunePoly, freq[i], i); } float* samples = tAutotune_tick(&autotunePoly, audioIn); for (int i = 0; i < tPoly_getNumVoices(&poly); ++i) { sample += samples[i] * tRamp_tick(&polyRamp[i]); } sample *= tRamp_tick(&comp); rightOut = sample; } void SFXAutotuneFree(void) { tAutotune_free(&autotunePoly); } //7 sampler - button press int samplePlayStart = 0; int samplePlayEnd = 0; float sampleLength = 0.0f; int crossfadeLength = 0; float samplerRate = 1.0f; float maxSampleSizeSeconds = 1.0f; uint8_t samplePlaying = 1; void SFXSamplerBPAlloc() { tBuffer_initToPool(&buff, leaf.sampleRate * 172.0f, &largePool); tBuffer_setRecordMode(&buff, RecordOneShot); tSampler_init(&sampler, &buff); tSampler_setMode(&sampler, PlayLoop); } void SFXSamplerBPFrame() { } void SFXSamplerBPTick(float audioIn) { int recordPosition = tBuffer_getRecordPosition(&buff); sampleLength = recordPosition * leaf.invSampleRate; knobParams[0] = smoothedADC[0] * sampleLength; knobParams[1] = smoothedADC[1] * sampleLength; knobParams[2] = (smoothedADC[2] - 0.5f) * 4.0f; knobParams[3] = smoothedADC[3] * 4000.0f; samplePlayStart = smoothedADC[0] * recordPosition; samplePlayEnd = smoothedADC[1] * recordPosition; samplerRate = knobParams[2]; crossfadeLength = knobParams[3]; tSampler_setStart(&sampler, samplePlayStart); tSampler_setEnd(&sampler, samplePlayEnd); tSampler_setRate(&sampler, samplerRate); tSampler_setCrossfadeLength(&sampler, crossfadeLength); if (buttonActionsSFX[ButtonDown][ActionPress]) { if (samplePlaying) { samplePlaying = 0; tSampler_stop(&sampler); } else { samplePlaying = 1; tSampler_play(&sampler); } buttonActionsSFX[ButtonDown][ActionPress] = 0; } if (buttonActionsSFX[ButtonA][ActionPress]) { tSampler_stop(&sampler); tBuffer_record(&buff); buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(1); } if (buttonActionsSFX[ButtonA][ActionRelease]) { tBuffer_stop(&buff); if (samplePlaying) tSampler_play(&sampler); tSampler_setStart(&sampler, samplePlayStart); tSampler_setEnd(&sampler, samplePlayEnd); tSampler_setRate(&sampler, samplerRate); tSampler_setCrossfadeLength(&sampler, crossfadeLength); buttonActionsSFX[ButtonA][ActionRelease] = 0; setLED_A(0); } tBuffer_tick(&buff, audioIn); sample = tanhf(tSampler_tick(&sampler)); rightOut = sample; } void SFXSamplerBPFree(void) { tBuffer_freeFromPool(&buff, &largePool); tSampler_free(&sampler); } //8 sampler - auto volatile float currentPower = 0.0f; volatile float previousPower = 0.0f; float samp_thresh = 0.0f; volatile int samp_triggered = 0; uint32_t sample_countdown = 0; PlayMode samplerMode = PlayLoop; uint32_t powerCounter = 0; uint8_t triggerChannel = 0; uint8_t firstTrigger = 0; void SFXSamplerAutoAlloc() { tBuffer_initToPool(&buff2, leaf.sampleRate * 2.0f, &largePool); tBuffer_setRecordMode(&buff2, RecordOneShot); tSampler_init(&sampler, &buff2); tSampler_setMode(&sampler, PlayLoop); tEnvelopeFollower_init(&envfollow, 0.05f, 0.9999f); setLED_A(samplerMode == PlayBackAndForth); setLED_B(triggerChannel); firstTrigger = 1; } void SFXSamplerAutoFrame() { } void SFXSamplerAutoTick(float audioIn) { if (triggerChannel > 0) currentPower = tEnvelopeFollower_tick(&envfollow, rightIn); else currentPower = tEnvelopeFollower_tick(&envfollow, audioIn); samp_thresh = 1.0f - smoothedADC[0]; knobParams[0] = samp_thresh; int window_size = smoothedADC[1] * 10000.0f; knobParams[1] = window_size; knobParams[3] = smoothedADC[3] * 1000.0f; crossfadeLength = knobParams[3]; tSampler_setCrossfadeLength(&sampler, crossfadeLength); if ((currentPower > (samp_thresh)) && (currentPower > previousPower + 0.001f) && (samp_triggered == 0) && (sample_countdown == 0)) { samp_triggered = 1; setLED_1(1); tBuffer_record(&buff2); if (firstTrigger) { tSampler_play(&sampler); firstTrigger = 0; } buff2->recordedLength = buff2->bufferLength; sample_countdown = window_size + 24;//arbitrary extra time to avoid resampling while playing previous sample - better solution would be alternating buffers and crossfading powerCounter = 1000; } if (sample_countdown > 0) { sample_countdown--; } tSampler_setEnd(&sampler,window_size); tBuffer_tick(&buff2, audioIn); //on it's way down if (currentPower <= previousPower) { if (powerCounter > 0) { powerCounter--; } else if (samp_triggered == 1) { setLED_1(0); samp_triggered = 0; } } if (buttonActionsSFX[ButtonA][ActionPress]) { if (samplerMode == PlayLoop) { tSampler_setMode(&sampler, PlayBackAndForth); samplerMode = PlayBackAndForth; setLED_A(1); buttonActionsSFX[ButtonA][ActionPress] = 0; } else if (samplerMode == PlayBackAndForth) { tSampler_setMode(&sampler, PlayLoop); samplerMode = PlayLoop; setLED_A(0); buttonActionsSFX[ButtonA][ActionPress] = 0; } } if (buttonActionsSFX[ButtonB][ActionPress]) { triggerChannel = (triggerChannel > 0) ? 0 : 1; buttonActionsSFX[ButtonB][ActionPress] = 0; setLED_B(triggerChannel); } sample = tSampler_tick(&sampler); rightOut = sample; previousPower = currentPower; } void SFXSamplerAutoFree(void) { tBuffer_freeFromPool(&buff2, &largePool); tSampler_free(&sampler); tEnvelopeFollower_free(&envfollow); } //10 distortion tanh uint8_t distortionMode = 0; void SFXDistortionAlloc() { leaf.clearOnAllocation = 1; tOversampler_init(&oversampler, OVERSAMPLER_RATIO, OVERSAMPLER_HQ); setLED_A(distortionMode); leaf.clearOnAllocation = 0; } void SFXDistortionFrame() { if (buttonActionsSFX[ButtonA][ActionPress]) { distortionMode = !distortionMode; buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(distortionMode); } } void SFXDistortionTick(float audioIn) { //knob 0 = gain sample = audioIn; knobParams[0] = ((smoothedADC[0] * 20.0f) + 1.0f); // 15.0f sample = sample * knobParams[0]; tOversampler_upsample(&oversampler, sample, oversamplerArray); for (int i = 0; i < OVERSAMPLER_RATIO; i++) { if (distortionMode > 0) oversamplerArray[i] = LEAF_shaper(oversamplerArray[i], 1.0f); else oversamplerArray[i] = tanhf(oversamplerArray[i]); } sample = tOversampler_downsample(&oversampler, oversamplerArray); sample *= .65f; // .75f rightOut = sample; //sample = tOversampler_tick(&oversampler, sample, &tanhf); } void SFXDistortionFree(void) { tOversampler_free(&oversampler); } //12 distortion wave folder void SFXWaveFolderAlloc() { leaf.clearOnAllocation = 1; tLockhartWavefolder_init(&wavefolder1); tLockhartWavefolder_init(&wavefolder2); tLockhartWavefolder_init(&wavefolder3); tLockhartWavefolder_init(&wavefolder4); tHighpass_init(&wfHP, 20.0f); tOversampler_init(&oversampler, 2, FALSE); leaf.clearOnAllocation = 0; } void SFXWaveFolderFrame() { } void SFXWaveFolderTick(float audioIn) { //knob 0 = gain sample = audioIn; knobParams[0] = (smoothedADC[0] * 20.0f) + 1.0f; knobParams[1] = (smoothedADC[1] * 2.0f) - 1.0f; knobParams[2] = (smoothedADC[2] * 2.0f) - 1.0f; //knobParams[3] = (smoothedADC[3] * 2.0f) - 1.0f; float gain = knobParams[0]; sample = sample * gain * 0.33f; sample = sample + knobParams[1]; tOversampler_upsample(&oversampler, sample, oversamplerArray); for (int i = 0; i < 2; i++) { oversamplerArray[i] = tLockhartWavefolder_tick(&wavefolder1, oversamplerArray[i]); //sample = sample * gain; oversamplerArray[i] = sample + knobParams[2]; oversamplerArray[i] = tLockhartWavefolder_tick(&wavefolder2, oversamplerArray[i]); //oversamplerArray[i] = sample + knobParams[3]; //sample *= .6f; //oversamplerArray[i] = tLockhartWavefolder_tick(&wavefolder3, oversamplerArray[i]); //sample = tLockhartWavefolder_tick(&wavefolder4, sample); oversamplerArray[i] *= .8f; oversamplerArray[i] = tanhf(oversamplerArray[i]); } sample = tHighpass_tick(&wfHP, tOversampler_downsample(&oversampler, oversamplerArray)); rightOut = sample; /* sample = tLockhartWavefolder_tick(&wavefolder1, sample); //sample = sample * gain; sample = sample + knobParams[2]; sample = tLockhartWavefolder_tick(&wavefolder2, sample); sample = sample + knobParams[3]; //sample *= .6f; sample = tLockhartWavefolder_tick(&wavefolder3, sample); //sample = tLockhartWavefolder_tick(&wavefolder4, sample); sample *= .8f; sample = tanhf(sample); rightOut = sample; */ } void SFXWaveFolderFree(void) { tLockhartWavefolder_free(&wavefolder1); tLockhartWavefolder_free(&wavefolder2); tLockhartWavefolder_free(&wavefolder3); tLockhartWavefolder_free(&wavefolder4); tHighpass_free(&wfHP); tOversampler_free(&oversampler); } //13 bitcrusher void SFXBitcrusherAlloc() { tCrusher_init(&crush); tCrusher_init(&crush2); } void SFXBitcrusherFrame() { } void SFXBitcrusherTick(float audioIn) { knobParams[0] = smoothedADC[0]; tCrusher_setQuality (&crush, smoothedADC[0]); tCrusher_setQuality (&crush2, smoothedADC[0]); knobParams[1] = smoothedADC[1]; tCrusher_setSamplingRatio (&crush, smoothedADC[1]); tCrusher_setSamplingRatio (&crush2, smoothedADC[1]); knobParams[2] = smoothedADC[2]; tCrusher_setRound (&crush, smoothedADC[2]); tCrusher_setRound (&crush2, smoothedADC[2]); knobParams[3] = smoothedADC[3]; tCrusher_setOperation (&crush, smoothedADC[3]); tCrusher_setOperation (&crush2, smoothedADC[3]); knobParams[4] = smoothedADC[4] + 1.0f; sample = tCrusher_tick(&crush, tanhf(audioIn * (smoothedADC[4] + 1.0f))) * .9f; rightOut = tCrusher_tick(&crush2, tanhf(rightIn * (smoothedADC[4] + 1.0f))) * .9f; } void SFXBitcrusherFree(void) { tCrusher_free(&crush); tCrusher_free(&crush2); } //delay int delayShaper = 0; void SFXDelayAlloc() { leaf.clearOnAllocation = 1; tTapeDelay_init(&delay, 2000, 30000); tTapeDelay_init(&delay2, 2000, 30000); tSVF_init(&delayLP, SVFTypeLowpass, 16000.f, .7f); tSVF_init(&delayHP, SVFTypeHighpass, 20.f, .7f); tSVF_init(&delayLP2, SVFTypeLowpass, 16000.f, .7f); tSVF_init(&delayHP2, SVFTypeHighpass, 20.f, .7f); tHighpass_init(&delayShaperHp, 20.0f); tFeedbackLeveler_init(&feedbackControl, .99f, 0.01, 0.125f, 0); delayShaper = 0; setLED_A(delayShaper); leaf.clearOnAllocation = 0; } void SFXDelayFrame() { if (buttonActionsSFX[ButtonA][ActionPress]) { delayShaper = !delayShaper; buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(delayShaper); } } float delayFB1; float delayFB2; void SFXDelayTick(float audioIn) { knobParams[0] = smoothedADC[0] * 30000.0f; knobParams[1] = smoothedADC[1] * 30000.0f; knobParams[2] = smoothedADC[2] * 1.1f; knobParams[3] = faster_mtof((smoothedADC[3] * 128) + 10.0f); knobParams[4] = faster_mtof((smoothedADC[4] * 128) + 10.0f); tSVF_setFreq(&delayLP, knobParams[3]); tSVF_setFreq(&delayLP2, knobParams[3]); tSVF_setFreq(&delayHP, knobParams[4]); tSVF_setFreq(&delayHP2, knobParams[4]); //swap tanh for shaper and add cheap fixed highpass after both shapers float input1, input2; if (delayShaper == 0) { input1 = tFeedbackLeveler_tick(&feedbackControl, tanhf(audioIn + (delayFB1 * knobParams[2]))); input2 = tFeedbackLeveler_tick(&feedbackControl, tanhf(audioIn + (delayFB2 * knobParams[2]))); } else { input1 = tFeedbackLeveler_tick(&feedbackControl, tHighpass_tick(&delayShaperHp, LEAF_shaper(audioIn + (delayFB1 * knobParams[2] * 0.5f), 0.5f))); input2 = tFeedbackLeveler_tick(&feedbackControl, tHighpass_tick(&delayShaperHp, LEAF_shaper(audioIn + (delayFB2 * knobParams[2] * 0.5f), 0.5f))); } tTapeDelay_setDelay(&delay, knobParams[0]); delayFB1 = tTapeDelay_tick(&delay, input1); tTapeDelay_setDelay(&delay2, knobParams[1]); delayFB2 = tTapeDelay_tick(&delay2, input2); delayFB1 = tSVF_tick(&delayLP, delayFB1) * 0.95f; delayFB2 = tSVF_tick(&delayLP2, delayFB2)* 0.95f; delayFB1 = tanhf(tSVF_tick(&delayHP, delayFB1)* 0.95f); delayFB2 = tanhf(tSVF_tick(&delayHP2, delayFB2)* 0.95f); sample = delayFB1; rightOut = delayFB2; } void SFXDelayFree(void) { tTapeDelay_free(&delay); tTapeDelay_free(&delay2); tSVF_free(&delayLP); tSVF_free(&delayHP); tSVF_free(&delayLP2); tSVF_free(&delayHP2); tHighpass_free(&delayShaperHp); tFeedbackLeveler_free(&feedbackControl); } //reverb uint32_t freeze = 0; tDattorroReverb reverb; void SFXReverbAlloc() { leaf.clearOnAllocation = 1; tDattorroReverb_init(&reverb); tDattorroReverb_setMix(&reverb, 1.0f); freeze = 0; leaf.clearOnAllocation = 0; } void SFXReverbFrame() { knobParams[1] = faster_mtof(smoothedADC[1]*135.0f); tDattorroReverb_setInputFilter(&reverb, knobParams[1]); knobParams[2] = faster_mtof(smoothedADC[2]*128.0f); tDattorroReverb_setHP(&reverb, knobParams[2]); knobParams[3] = faster_mtof(smoothedADC[3]*135.0f); tDattorroReverb_setFeedbackFilter(&reverb, knobParams[3]); } void SFXReverbTick(float audioIn) { float stereo[2]; if (buttonActionsSFX[ButtonA][ActionPress]) { if (freeze == 0) { freeze = 1; tDattorroReverb_setFreeze(&reverb, 1); setLED_1(1); } else { freeze = 0; tDattorroReverb_setFreeze(&reverb, 0); setLED_1(0); } buttonActionsSFX[ButtonA][ActionPress] = 0; } //tDattorroReverb_setInputDelay(&reverb, smoothedADC[1] * 200.f); audioIn *= 4.0f; knobParams[0] = smoothedADC[0]; tDattorroReverb_setSize(&reverb, knobParams[0]); knobParams[4] = smoothedADC[4]; tDattorroReverb_setFeedbackGain(&reverb, knobParams[4]); tDattorroReverb_tickStereo(&reverb, audioIn, stereo); sample = tanhf(stereo[0]) * 0.99f; rightOut = tanhf(stereo[1]) * 0.99f; } void SFXReverbFree(void) { tDattorroReverb_free(&reverb); } //reverb2 tNReverb reverb2; tSVF lowpass; tSVF highpass; tSVF bandpass; tSVF lowpass2; tSVF highpass2; tSVF bandpass2; void SFXReverb2Alloc() { leaf.clearOnAllocation = 1; tNReverb_init(&reverb2, 1.0f); tNReverb_setMix(&reverb2, 1.0f); tSVF_init(&lowpass, SVFTypeLowpass, 18000.0f, 0.75f); tSVF_init(&highpass, SVFTypeHighpass, 40.0f, 0.75f); tSVF_init(&bandpass, SVFTypeBandpass, 2000.0f, 1.0f); tSVF_init(&lowpass2, SVFTypeLowpass, 18000.0f, 0.75f); tSVF_init(&highpass2, SVFTypeHighpass, 40.0f, 0.75f); tSVF_init(&bandpass2, SVFTypeBandpass, 2000.0f, 1.0f); freeze = 0; leaf.clearOnAllocation = 0; } void SFXReverb2Frame() { } void SFXReverb2Tick(float audioIn) { float stereoOuts[2]; knobParams[0] = smoothedADC[0] * 4.0f; if (!freeze) { tNReverb_setT60(&reverb2, knobParams[0]); } else { tNReverb_setT60(&reverb2, 1000.0f); audioIn = 0.0f; } knobParams[1] = faster_mtof(smoothedADC[1]*135.0f); tSVF_setFreq(&lowpass, knobParams[1]); tSVF_setFreq(&lowpass2, knobParams[1]); knobParams[2] = faster_mtof(smoothedADC[2]*128.0f); tSVF_setFreq(&highpass, knobParams[2]); tSVF_setFreq(&highpass2, knobParams[2]); knobParams[3] = faster_mtof(smoothedADC[3]*128.0f); tSVF_setFreq(&bandpass, knobParams[3]); tSVF_setFreq(&bandpass2, knobParams[3]); knobParams[4] = (smoothedADC[4] * 4.0f) - 2.0f; if (buttonActionsSFX[ButtonA][ActionPress]) { if (freeze == 0) { freeze = 1; setLED_1(1); } else { freeze = 0; setLED_1(0); } buttonActionsSFX[ButtonA][ActionPress] = 0; } tNReverb_tickStereo(&reverb2, audioIn, stereoOuts); float leftOut = tSVF_tick(&lowpass, stereoOuts[0]); leftOut = tSVF_tick(&highpass, leftOut); leftOut += tSVF_tick(&bandpass, leftOut) * knobParams[4]; float rightOutTemp = tSVF_tick(&lowpass2, stereoOuts[1]); rightOutTemp = tSVF_tick(&highpass2, rightOutTemp); rightOutTemp += tSVF_tick(&bandpass, rightOutTemp) * knobParams[4]; sample = tanhf(leftOut); rightOut = tanhf(rightOutTemp); } void SFXReverb2Free(void) { tNReverb_free(&reverb2); tSVF_free(&lowpass); tSVF_free(&highpass); tSVF_free(&bandpass); tSVF_free(&lowpass2); tSVF_free(&highpass2); tSVF_free(&bandpass2); } //Living String void SFXLivingStringAlloc() { for (int i = 0; i < NUM_STRINGS; i++) { myFreq = (randomNumber() * 300.0f) + 60.0f; myDetune[i] = (randomNumber() * 0.3f) - 0.15f; //tLivingString_init(&theString[i], myFreq, 0.4f, 0.0f, 16000.0f, .999f, .5f, .5f, 0.1f, 0); tLivingString_init(&theString[i], 440.f, 0.2f, 0.f, 9000.f, 1.0f, 0.3f, 0.01f, 0.125f, 0); } } void SFXLivingStringFrame() { knobParams[0] = mtof((smoothedADC[0] * 135.0f)); //freq knobParams[1] = smoothedADC[1]; //detune knobParams[2] = ((smoothedADC[2] * 0.09999999f) + 0.9f); knobParams[3] = mtof((smoothedADC[3] * 130.0f)+12.0f); //lowpass knobParams[4] = (smoothedADC[4] * 0.5) + 0.02f;//pickPos for (int i = 0; i < NUM_STRINGS; i++) { tLivingString_setFreq(&theString[i], (i + (1.0f+(myDetune[i] * knobParams[1]))) * knobParams[0]); tLivingString_setDecay(&theString[i], knobParams[2]); tLivingString_setDampFreq(&theString[i], knobParams[3]); tLivingString_setPickPos(&theString[i], knobParams[4]); } } void SFXLivingStringTick(float audioIn) { for (int i = 0; i < NUM_STRINGS; i++) { sample += tLivingString_tick(&theString[i], audioIn); } sample *= 0.0625f; rightOut = sample; } void SFXLivingStringFree(void) { for (int i = 0; i < NUM_STRINGS; i++) { tLivingString_free(&theString[i]); } } //Living String void SFXLivingStringSynthAlloc() { tPoly_setNumVoices(&poly, NUM_STRINGS); for (int i = 0; i < NUM_STRINGS; i++) { tLivingString_init(&theString[i], 440.f, 0.2f, 0.f, 9000.f, 1.0f, 0.0f, 0.01f, 0.125f, 1); } } void SFXLivingStringSynthFrame() { //knobParams[0] = mtof((smoothedADC[0] * 135.0f)); //freq //knobParams[1] = smoothedADC[1]; //detune knobParams[2] = ((smoothedADC[2] * 0.09999999f) + 0.9f); knobParams[3] = mtof((smoothedADC[3] * 130.0f)+12.0f); //lowpass knobParams[4] = (smoothedADC[4] * 0.5) + 0.02f;//pickPos for (int i = 0; i < NUM_STRINGS; i++) { //tLivingString_setFreq(&theString[i], (i + (1.0f+(myDetune[i] * knobParams[1]))) * knobParams[0]); tLivingString_setDecay(&theString[i], knobParams[2]); tLivingString_setDampFreq(&theString[i], knobParams[3]); tLivingString_setPickPos(&theString[i], knobParams[4]); } for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { //tRamp_setDest(&polyRamp[i], (tPoly_getVelocity(&poly, i) > 0)); calculateFreq(i); tLivingString_setFreq(&theString[i], freq[i]); tLivingString_setTargetLev(&theString[i],(tPoly_getVelocity(&poly, i) > 0)); } } void SFXLivingStringSynthTick(float audioIn) { for (int i = 0; i < NUM_STRINGS; i++) { sample += tLivingString_tick(&theString[i], audioIn); } sample *= 0.0625f; rightOut = sample; } void SFXLivingStringSynthFree(void) { for (int i = 0; i < NUM_STRINGS; i++) { tLivingString_free(&theString[i]); } } //17 living string void SFXClassicSynthAlloc() { tPoly_setNumVoices(&poly, numVoices); for (int i = 0; i < NUM_VOC_VOICES; i++) { for (int j = 0; j < NUM_OSC_PER_VOICE; j++) { tSawtooth_initToPool(&osc[(i * NUM_OSC_PER_VOICE) + j], &smallPool); synthDetune[i][j] = (leaf.random() * 0.2f) - 0.1f; } } tSVF_init(&delayLP, SVFTypeLowpass, 6000.0f, 1.0f); setLED_A(numVoices == 1); } void SFXClassicSynthFrame() { if (buttonActionsSFX[ButtonA][ActionPress] == 1) { numVoices = (numVoices > 1) ? 1 : NUM_VOC_VOICES; tPoly_setNumVoices(&poly, numVoices); buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(numVoices == 1); } } //make detuning more independant - maybe based on midi instead of frequency //add filters //waveshaper? void SFXClassicSynthTick(float audioIn) { tPoly_tickPitch(&poly); knobParams[0] = smoothedADC[0]; //synth volume knobParams[1] = faster_mtof(smoothedADC[1] * 128.0f); //lowpass cutoff knobParams[2] = smoothedADC[2]; //detune for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { tRamp_setDest(&polyRamp[i], (tPoly_getVelocity(&poly, i) > 0)); float myMidiNote = calculateTunedMidiNote(tPoly_getPitch(&poly, i)); float myFrequency = LEAF_midiToFrequency(myMidiNote); for (int j = 0; j < NUM_OSC_PER_VOICE; j++) { //tSawtooth_setFreq(&osc[i + (j*NUM_VOC_VOICES)], LEAF_midiToFrequency(myMidiNote + synthDetune[i][j])); tSawtooth_setFreq(&osc[i + (j*NUM_VOC_VOICES)], myFrequency * (1.0f + (synthDetune[i][j] * knobParams[2] * 0.1f))); } } if (tPoly_getNumActiveVoices(&poly) != 0) tRamp_setDest(&comp, 1.0f / tPoly_getNumActiveVoices(&poly)); for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { float amplitudeTemp = tRamp_tick(&polyRamp[i]); sample += tSawtooth_tick(&osc[i]) * amplitudeTemp; sample += tSawtooth_tick(&osc[i + NUM_VOC_VOICES]) * amplitudeTemp; sample += tSawtooth_tick(&osc[i] + (NUM_VOC_VOICES * 2)) * amplitudeTemp; } sample *= 0.125f * knobParams[0]; tSVF_setFreq(&delayLP, knobParams[1]); sample = tSVF_tick(&delayLP, sample); sample = tanhf(sample); } void SFXClassicSynthFree(void) { for (int i = 0; i < NUM_VOC_VOICES; i++) { for (int j = 0; j < NUM_OSC_PER_VOICE; j++) { tSawtooth_freeFromPool(&osc[(i * NUM_OSC_PER_VOICE) + j], &smallPool); } } tSVF_free(&delayLP); } tCycle FM_sines[NUM_VOC_VOICES][6]; float FM_freqRatios[6] = {1.0f, 3.0001f, 0.4999f, 3.0f, 4.0f, 5.0f}; float FM_indices[6] = {1000.0f, 100.0f, 300.0f, 300.0f, 800.0f, 900.0f}; float FM_decays[6] = {2000.0f, 300.0f, 800.0f, 3000.0f, 340.0f, 50.0f}; tEnvelope leakers[NUM_VOC_VOICES][2]; tADSR FM_envs[NUM_VOC_VOICES][6]; float feedback_output = 0.0f; tCycle tremolo; //FM Rhodes void SFXRhodesAlloc() { for (int i = 0; i < NUM_VOC_VOICES; i++) { for (int j = 0; j < 6; j++) { tCycle_init(&FM_sines[i][j]); tADSR_init(&FM_envs[i][j], 7.0f, FM_decays[j], 0.3f, 100.0f); } tEnvelope_init(&leakers[i][0], 7.0f, 4000.0f, 0); tEnvelope_init(&leakers[i][1], 7.0f, 4000.0f, 0); } tCycle_init(&tremolo); tCycle_setFreq(&tremolo, 3.0f); tPoly_setNumVoices(&poly, NUM_VOC_VOICES); setLED_A(numVoices == 1); } void SFXRhodesFrame() { if (buttonActionsSFX[ButtonA][ActionPress] == 1) { numVoices = (numVoices > 1) ? 1 : NUM_VOC_VOICES; tPoly_setNumVoices(&poly, numVoices); buttonActionsSFX[ButtonA][ActionPress] = 0; setLED_A(numVoices == 1); } tPoly_tickPitch(&poly); for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { calculateFreq(i); } } float lastsamp = 0.0f; volatile uint8_t checkMe = 0; void SFXRhodesTick(float audioIn) { knobParams[0] = smoothedADC[0] * 2.0f; //brightness knobParams[1] = smoothedADC[1]; //tremolo amount knobParams[2] = smoothedADC[2] * 12.0f; //tremolo speed tCycle_setFreq(&tremolo, knobParams[2]); for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { //tRamp_setDest(&polyRamp[i], (tPoly_getVelocity(&poly, i) > 0)); //float myMidiNote = calculateTunedMidiNote(tPoly_getPitch(&poly, i)); float myFrequency = freq[i]; tCycle_setFreq(&FM_sines[i][5], (myFrequency * FM_freqRatios[5]) + (FM_indices[5] * feedback_output * knobParams[0])); feedback_output = tCycle_tick(&FM_sines[i][5]); tCycle_setFreq(&FM_sines[i][4], (myFrequency * FM_freqRatios[4]) + (FM_indices[4] * feedback_output * knobParams[0] * tADSR_tick(&FM_envs[i][5]))); tCycle_setFreq(&FM_sines[i][3], (myFrequency * FM_freqRatios[3]) + (FM_indices[3] * knobParams[0] * tCycle_tick(&FM_sines[i][4]) * tADSR_tick(&FM_envs[i][4]))); tCycle_setFreq(&FM_sines[i][2], (myFrequency * FM_freqRatios[2]) + (FM_indices[2] * knobParams[0] * tCycle_tick(&FM_sines[i][3]) * tADSR_tick(&FM_envs[i][3]))); tCycle_setFreq(&FM_sines[i][1], myFrequency * FM_freqRatios[1]); tCycle_setFreq(&FM_sines[i][0],( myFrequency * FM_freqRatios[0]) + (FM_indices[0] * knobParams[0] * tCycle_tick(&FM_sines[i][1]) * tADSR_tick(&FM_envs[i][1]))); } //if (tPoly_getNumActiveVoices(&poly) != 0) tRamp_setDest(&comp, 1.0f / tPoly_getNumActiveVoices(&poly)); for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { //float amplitudeTemp = tRamp_tick(&polyRamp[i]); //amplitudeTemp = 1.0f; sample += tCycle_tick(&FM_sines[i][2]) * tADSR_tick(&FM_envs[i][2]) * tEnvelope_tick(&leakers[i][0]); sample += tCycle_tick(&FM_sines[i][0]) * tADSR_tick(&FM_envs[i][0]) * tEnvelope_tick(&leakers[i][1]); } float tremoloSignal = ((tCycle_tick(&tremolo) * 0.5f) + 0.5f) * knobParams[1]; sample = sample * (tremoloSignal + (1.0f - knobParams[1])); sample *= 0.125f; //sample = LEAF_shaper(sample, 1.0f); //sample *= 0.8f; } void SFXRhodesFree(void) { for (int i = 0; i < NUM_VOC_VOICES; i++) { for (int j = 0; j < 6; j++) { tCycle_free(&FM_sines[i][j]); tADSR_free(&FM_envs[i][j]); } tEnvelope_free(&leakers[i][0]); tEnvelope_free(&leakers[i][1]); } tCycle_free(&tremolo); } // midi functions void calculateFreq(int voice) { float tempNote = tPoly_getPitch(&poly, voice); float tempPitchClass = ((((int)tempNote) - keyCenter) % 12 ); float tunedNote = tempNote + centsDeviation[(int)tempPitchClass]; freq[voice] = LEAF_midiToFrequency(tunedNote); } float calculateTunedMidiNote(float tempNote) { float tempPitchClass = ((((int)tempNote) - keyCenter) % 12 ); return (tempNote + centsDeviation[(int)tempPitchClass]); } void calculateNoteArray() { for (int i = 0; i < 128; i++) { float tempNote = i; float tempPitchClass = ((((int)tempNote) - keyCenter) % 12 ); float tunedNote = tempNote + centsDeviation[(int)tempPitchClass]; notes[i] = tunedNote; } } float nearestNote(float period) { float note = LEAF_frequencyToMidi(leaf.sampleRate / period); float leastDifference = fabsf(note - notes[0]); float difference; int index = 0; int* chord; if (autotuneChromatic > 0) { chord = chromaticArray; } else { chord = chordArray; } //if (autotuneLock > 0) chord = lockArray; for(int i = 1; i < 128; i++) { if (chord[i%12] > 0) { difference = fabsf(note - notes[i]); if(difference < leastDifference) { leastDifference = difference; index = i; } } } return notes[index]; } void noteOn(int key, int velocity) { if (!velocity) { if (chordArray[key%12] > 0) chordArray[key%12]--; int voice = tPoly_noteOff(&poly, key); if (voice >= 0) { tRamp_setDest(&polyRamp[voice], 0.0f); if (currentPreset == Rhodes) { for (int j = 0; j < 6; j++) { tADSR_off(&FM_envs[voice][j]); } } } for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { if (tPoly_isOn(&poly, i) == 1) { tRamp_setDest(&polyRamp[i], 1.0f); calculateFreq(i); } } setLED_USB(0); } else { chordArray[key%12]++; int whichVoice = tPoly_noteOn(&poly, key, velocity); if (whichVoice >= 0) { if (currentPreset == Rhodes) { for (int j = 0; j < 6; j++) { tADSR_on(&FM_envs[whichVoice][j], velocity * 0.0078125f); } tEnvelope_on(&leakers[whichVoice][0], 1.0f); tEnvelope_on(&leakers[whichVoice][1], 1.0f); } } for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { if (tPoly_isOn(&poly, i) == 1) { tRamp_setDest(&polyRamp[i], 1.0f); calculateFreq(i); } } setLED_2(1); } } void noteOff(int key, int velocity) { if (chordArray[key%12] > 0) chordArray[key%12]--; int voice = tPoly_noteOff(&poly, key); if (voice >= 0) { tRamp_setDest(&polyRamp[voice], 0.0f); if (currentPreset == Rhodes) { for (int j = 0; j < 6; j++) { tADSR_off(&FM_envs[voice][j]); } } } for (int i = 0; i < tPoly_getNumVoices(&poly); i++) { if (tPoly_isOn(&poly, i) == 1) { tRamp_setDest(&polyRamp[i], 1.0f); calculateFreq(i); } } setLED_2(0); } void pitchBend(int data) { tPoly_setPitchBend(&poly, (data - 8192) * 0.000244140625f); } void sustainOff() { } void sustainOn() { } void toggleBypass() { } void toggleSustain() { } void ctrlInput(int ctrl, int value) { }