shithub: leaf

ref: 21f5ac6f65245a6d5f1b63b0f1a38d4001f1d5dc
dir: /LEAF/Src/sfx.c/

View raw version
/*
 * 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)
{

}