shithub: leaf

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

View raw version
/*
 * audiostream.c
 *
 *  Created on: Aug 30, 2019
 *      Author: jeffsnyder
 */


/* Includes ------------------------------------------------------------------*/
#include "audiostream.h"
#include "main.h"
#include "leaf.h"
#include "codec.h"
#include "ui.h"
#include "oled.h"
#include "tunings.h"
#include "i2c.h"
#include "gpio.h"
#include "sfx.h"
#include "tim.h"

//the audio buffers are put in the D2 RAM area because that is a memory location that the DMA has access to.
int32_t audioOutBuffer[AUDIO_BUFFER_SIZE] __ATTR_RAM_D2;
int32_t audioInBuffer[AUDIO_BUFFER_SIZE] __ATTR_RAM_D2;

#define SMALL_MEM_SIZE 8192
#define MED_MEM_SIZE 500000
#define LARGE_MEM_SIZE 33554432 //32 MBytes - size of SDRAM IC
char small_memory[SMALL_MEM_SIZE];
char medium_memory[MED_MEM_SIZE]__ATTR_RAM_D1;
char large_memory[LARGE_MEM_SIZE] __ATTR_SDRAM;

#define DISPLAY_BLOCK_SIZE 512
float audioDisplayBuffer[128];
uint8_t displayBufferIndex = 0;
float displayBlockVal = 0.0f;
uint32_t displayBlockCount = 0;


void audioFrame(uint16_t buffer_offset);
float audioTickL(float audioIn);
float audioTickR(float audioIn);
void buttonCheck(void);

HAL_StatusTypeDef transmit_status;
HAL_StatusTypeDef receive_status;

uint8_t codecReady = 0;

uint16_t frameCounter = 0;

tMempool smallPool;
tMempool largePool;

tRamp adc[6];

tNoise myNoise;
tCycle mySine[2];
float smoothedADC[6];
tEnvelopeFollower LED_envelope[4];

uint32_t clipCounter[4] = {0,0,0,0};
uint8_t clipped[4] = {0,0,0,0};


float rightIn = 0.0f;
float rightOut = 0.0f;
float sample = 0.0f;



// Vocoder
float glideTimeVoc = 5.0f;

// Formant
float formantShiftFactor = -1.0f;
float formantKnob = 0.0f;

// PitchShift
float pitchFactor = 2.0f;
float formantWarp = 1.0f;
float formantIntensity = 1.0f;

// Autotune1

// Autotune2
float glideTimeAuto = 5.0f;

// Sampler Button Press


// Sampler Auto Grab






BOOL frameCompleted = TRUE;

BOOL bufferCleared = TRUE;

int numBuffersToClearOnLoad = 2;
int numBuffersCleared = 0;

/**********************************************/

void (*allocFunctions[PresetNil])(void);
void (*frameFunctions[PresetNil])(void);
void (*tickFunctions[PresetNil])(float);
void (*freeFunctions[PresetNil])(void);

void audioInit(I2C_HandleTypeDef* hi2c, SAI_HandleTypeDef* hsaiOut, SAI_HandleTypeDef* hsaiIn)
{
	// Initialize LEAF.

	LEAF_init(SAMPLE_RATE, AUDIO_FRAME_SIZE, medium_memory, MED_MEM_SIZE, &randomNumber);

	tMempool_init (&smallPool, small_memory, SMALL_MEM_SIZE);
	tMempool_init (&largePool, large_memory, LARGE_MEM_SIZE);

	initFunctionPointers();

	//ramps to smooth the knobs
	for (int i = 0; i < 6; i++)
	{
		tRamp_init(&adc[i],19.0f, 1); //set all ramps for knobs to be 9ms ramp time and let the init function know they will be ticked every sample
	}

	for (int i = 0; i < 4; i++)
	{
		tEnvelopeFollower_init(&LED_envelope[i], 0.02f, .9995f);
	}

	initGlobalSFXObjects();

//	allocFunctions[currentPreset]();

	loadingPreset = 1;
	previousPreset = PresetNil;

	HAL_Delay(10);

	for (int i = 0; i < AUDIO_BUFFER_SIZE; i++)
	{
		audioOutBuffer[i] = 0;
	}

	HAL_Delay(1);

	// set up the I2S driver to send audio data to the codec (and retrieve input as well)
	transmit_status = HAL_SAI_Transmit_DMA(hsaiOut, (uint8_t *)&audioOutBuffer[0], AUDIO_BUFFER_SIZE);
	receive_status = HAL_SAI_Receive_DMA(hsaiIn, (uint8_t *)&audioInBuffer[0], AUDIO_BUFFER_SIZE);

	// with the CS4271 codec IC, the SAI Transmit and Receive must be happening before the chip will respond to
	// I2C setup messages (it seems to use the masterclock input as it's own internal clock for i2c data, etc)
	// so while we used to set up codec before starting SAI, now we need to set up codec afterwards, and set a flag to make sure it's ready

	//now to send all the necessary messages to the codec
	AudioCodec_init(hi2c);
	HAL_Delay(1);

	//now reconfigue so buttons C and E can be used (they were also connected to I2C for codec setup)
	HAL_I2C_MspDeInit(hi2c);

	GPIO_InitTypeDef GPIO_InitStruct = {0};

    //PB10, PB11     ------> buttons C and E
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void audioFrame(uint16_t buffer_offset)
{
	frameCompleted = FALSE;

	int i;
	int32_t current_sample;

	buttonCheck();
	adcCheck();

	if (!loadingPreset)
	{
		frameFunctions[currentPreset]();
	}

	//if the codec isn't ready, keep the buffer as all zeros
	//otherwise, start computing audio!

	bufferCleared = TRUE;

	if (codecReady)
	{
		for (i = 0; i < (HALF_BUFFER_SIZE); i++)
		{
			if ((i & 1) == 0)
			{
				current_sample = (int32_t)(audioTickR((float) (audioInBuffer[buffer_offset + i] << 8) * INV_TWO_TO_31) * TWO_TO_23);
			}
			else
			{
				current_sample = (int32_t)(audioTickL((float) (audioInBuffer[buffer_offset + i] << 8) * INV_TWO_TO_31) * TWO_TO_23);
			}

			audioOutBuffer[buffer_offset + i] = current_sample;
		}

	}

	if (bufferCleared)
	{
		numBuffersCleared++;
		if (numBuffersCleared >= numBuffersToClearOnLoad)
		{
			numBuffersCleared = numBuffersToClearOnLoad;
			if (loadingPreset)
			{
				if (previousPreset != PresetNil)
				{
					// do this if you want to save knob values when changing off a preset
//					for (int i = 0; i < NUM_ADC_CHANNELS; i++)
//					{
//						presetKnobValues[previousPreset][i] = smoothedADC[i];
//					}
					freeFunctions[previousPreset]();
				}
				else
				{
					leaf.clearOnAllocation = 1;
				}
				setLED_A(0);
				setLED_B(0);
				setLED_1(0);
				allocFunctions[currentPreset]();
				for (int i = 0; i < NUM_ADC_CHANNELS; i++)
				{
					knobActive[i] = 0;
					floatADCUI[i] = -1.0f;
					tRamp_setVal(&adc[i], presetKnobValues[currentPreset][i]);
					tRamp_setDest(&adc[i], presetKnobValues[currentPreset][i]);
					smoothedADC[i] = presetKnobValues[currentPreset][i];
				}
				leaf.clearOnAllocation = 0;
				loadingPreset = 0;
			}
		}
	}
	else numBuffersCleared = 0;

	frameCompleted = TRUE;

	OLED_process(); // process what to write to the screen but don't actually draw
}




float audioTickL(float audioIn)
{
	sample = 0.0f;

	for (int i = 0; i < NUM_ADC_CHANNELS; i++)
	{
		smoothedADC[i] = tRamp_tick(&adc[i]);
	}

	if (loadingPreset) return sample;

	bufferCleared = FALSE;

	tickFunctions[currentPreset](audioIn);
/*
	displayBlockVal += fabsf(sample);
	displayBlockCount++;
	if (displayBlockCount >= DISPLAY_BLOCK_SIZE)
	{
		displayBlockVal *= INV_TWO_TO_9;
		audioDisplayBuffer[displayBufferIndex] = displayBlockVal;
		displayBlockVal = 0.0f;
		displayBlockCount = 0;
		displayBufferIndex++;
		if (displayBufferIndex >= 128) displayBufferIndex = 0;
	}
	*/

	if ((audioIn >= 0.999999f) || (audioIn <= -0.999999f))
	{
		setLED_leftin_clip(1);
		clipCounter[0] = 10000;
		clipped[0] = 1;
	}
	if ((clipCounter[0] > 0) && (clipped[0] == 1))
	{
		clipCounter[0]--;
	}
	else if ((clipCounter[0] == 0) && (clipped[0] == 1))
	{
		setLED_leftin_clip(0);
		clipped[0] = 0;
	}

	float current_env = tEnvelopeFollower_tick(&LED_envelope[0], audioIn);
	uint16_t audioLEDLevel = LEAF_clip(0, (current_env * 32.0f), 16);
	 __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, audioLEDLevel);


	current_env = tEnvelopeFollower_tick(&LED_envelope[1], sample);
	audioLEDLevel = LEAF_clip(0, (current_env * 32.0f), 15);
	 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, audioLEDLevel);



	if ((sample >= 0.999999f) || (sample <= -0.999999f))
	{
		setLED_leftout_clip(1);
		clipCounter[2] = 10000;
		clipped[2] = 1;
	}
	if ((clipCounter[2] > 0) && (clipped[2] == 1))
	{
		clipCounter[2]--;
	}
	else if ((clipCounter[2] == 0) && (clipped[2] == 1))
	{
		setLED_leftout_clip(0);
		clipped[2] = 0;
	}

	return sample;
}



float audioTickR(float audioIn)
{
	rightIn = audioIn;


	if ((rightIn >= 0.999999f) || (rightIn <= -0.999999f))
	{
		setLED_rightin_clip(1);
		clipCounter[1] = 10000;
		clipped[1] = 1;
	}
	if ((clipCounter[1] > 0) && (clipped[1] == 1))
	{
		clipCounter[1]--;
	}
	else if ((clipCounter[1] == 0) && (clipped[1] == 1))
	{
		setLED_rightin_clip(0);
		clipped[1] = 0;
	}



	if ((rightOut >= 0.999999f) || (rightOut <= -0.999999f))
	{
		setLED_rightout_clip(1);
		clipCounter[3] = 10000;
		clipped[3] = 1;
	}
	if ((clipCounter[3] > 0) && (clipped[3] == 1))
	{
		clipCounter[3]--;
	}
	else if ((clipCounter[3] == 0) && (clipped[3] == 1))
	{
		setLED_rightout_clip(0);
		clipped[3] = 0;
	}


	float current_env = tEnvelopeFollower_tick(&LED_envelope[2], rightIn);
	uint16_t audioLEDLevel = LEAF_clip(0, (current_env * 32.0f), 16);
	 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, audioLEDLevel);


	current_env = tEnvelopeFollower_tick(&LED_envelope[3], rightOut);
	audioLEDLevel = LEAF_clip(0, (current_env * 32.0f), 16);
	 __HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, audioLEDLevel);


	return rightOut;
}

void initFunctionPointers(void)
{
	allocFunctions[Vocoder] = SFXVocoderAlloc;
	frameFunctions[Vocoder] = SFXVocoderFrame;
	tickFunctions[Vocoder] = SFXVocoderTick;
	freeFunctions[Vocoder] = SFXVocoderFree;

	allocFunctions[Pitchshift] = SFXPitchShiftAlloc;
	frameFunctions[Pitchshift] = SFXPitchShiftFrame;
	tickFunctions[Pitchshift] = SFXPitchShiftTick;
	freeFunctions[Pitchshift] = SFXPitchShiftFree;

	allocFunctions[AutotuneMono] = SFXNeartuneAlloc;
	frameFunctions[AutotuneMono] = SFXNeartuneFrame;
	tickFunctions[AutotuneMono] = SFXNeartuneTick;
	freeFunctions[AutotuneMono] = SFXNeartuneFree;

	allocFunctions[AutotunePoly] = SFXAutotuneAlloc;
	frameFunctions[AutotunePoly] = SFXAutotuneFrame;
	tickFunctions[AutotunePoly] = SFXAutotuneTick;
	freeFunctions[AutotunePoly] = SFXAutotuneFree;

	allocFunctions[SamplerButtonPress] = SFXSamplerBPAlloc;
	frameFunctions[SamplerButtonPress] = SFXSamplerBPFrame;
	tickFunctions[SamplerButtonPress] = SFXSamplerBPTick;
	freeFunctions[SamplerButtonPress] = SFXSamplerBPFree;

	allocFunctions[SamplerAutoGrab] = SFXSamplerAutoAlloc;
	frameFunctions[SamplerAutoGrab] = SFXSamplerAutoFrame;
	tickFunctions[SamplerAutoGrab] = SFXSamplerAutoTick;
	freeFunctions[SamplerAutoGrab] = SFXSamplerAutoFree;

	allocFunctions[Distortion] = SFXDistortionAlloc;
	frameFunctions[Distortion] = SFXDistortionFrame;
	tickFunctions[Distortion] = SFXDistortionTick;
	freeFunctions[Distortion] = SFXDistortionFree;

	allocFunctions[Wavefolder] = SFXWaveFolderAlloc;
	frameFunctions[Wavefolder] = SFXWaveFolderFrame;
	tickFunctions[Wavefolder] = SFXWaveFolderTick;
	freeFunctions[Wavefolder] = SFXWaveFolderFree;

	allocFunctions[BitCrusher] = SFXBitcrusherAlloc;
	frameFunctions[BitCrusher] = SFXBitcrusherFrame;
	tickFunctions[BitCrusher] = SFXBitcrusherTick;
	freeFunctions[BitCrusher] = SFXBitcrusherFree;

	allocFunctions[Delay] = SFXDelayAlloc;
	frameFunctions[Delay] = SFXDelayFrame;
	tickFunctions[Delay] = SFXDelayTick;
	freeFunctions[Delay] = SFXDelayFree;

	allocFunctions[Reverb] = SFXReverbAlloc;
	frameFunctions[Reverb] = SFXReverbFrame;
	tickFunctions[Reverb] = SFXReverbTick;
	freeFunctions[Reverb] = SFXReverbFree;

	allocFunctions[Reverb2] = SFXReverb2Alloc;
	frameFunctions[Reverb2] = SFXReverb2Frame;
	tickFunctions[Reverb2] = SFXReverb2Tick;
	freeFunctions[Reverb2] = SFXReverb2Free;

	allocFunctions[LivingString] = SFXLivingStringAlloc;
	frameFunctions[LivingString] = SFXLivingStringFrame;
	tickFunctions[LivingString] = SFXLivingStringTick;
	freeFunctions[LivingString] = SFXLivingStringFree;

	allocFunctions[LivingStringSynth] = SFXLivingStringSynthAlloc;
	frameFunctions[LivingStringSynth] = SFXLivingStringSynthFrame;
	tickFunctions[LivingStringSynth] = SFXLivingStringSynthTick;
	freeFunctions[LivingStringSynth] = SFXLivingStringSynthFree;

	allocFunctions[ClassicSynth] = SFXClassicSynthAlloc;
	frameFunctions[ClassicSynth] = SFXClassicSynthFrame;
	tickFunctions[ClassicSynth] = SFXClassicSynthTick;
	freeFunctions[ClassicSynth] = SFXClassicSynthFree;

	allocFunctions[Rhodes] = SFXRhodesAlloc;
	frameFunctions[Rhodes] = SFXRhodesFrame;
	tickFunctions[Rhodes] = SFXRhodesTick;
	freeFunctions[Rhodes] = SFXRhodesFree;
}



void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
{
	if (!frameCompleted)
	{
		setLED_C(1);
	}
}

void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
{
	if (!frameCompleted)
		{
			setLED_C(1);
		}
}

void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
	if (!frameCompleted)
		{
			setLED_C(1);
		}
}


void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
{
	if (!frameCompleted)
	{
		setLED_C(1);
	}

	audioFrame(HALF_BUFFER_SIZE);
}

void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
	if (!frameCompleted)
	{
		setLED_C(1);
	}

	audioFrame(0);
}