Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: C12832_lcd MMA7660 USBDevice mbed
effects.cpp
- Committer:
- bw
- Date:
- 2014-03-27
- Revision:
- 2:9429f84ea165
- Parent:
- 0:bbf6cf0eab95
File content as of revision 2:9429f84ea165:
/*******************************************************************************
* Module processes 16-bit audio samples to produces delay-based sound effects.
* Bryan Wade
* 27 MAR 2014
******************************************************************************/
#include "mbed.h"
#include "effects.h"
#include "delay.h"
// Delay based effects require significant RAM, so we must
// scavange two banks of RAM that mbed has reserved for ethernet:
// AHBSRAM0: 0x2007C000 - 0x2007FFFF (16KB)
// AHBSRAM1: 0x20080000 - 0x20083FFF (16KB)
// To keep the linker happy we allocate the RAM with a 16KB array in each bank,
// but since they are contiguous, we can treat them as one 32KB block.
static const int RAM_BANK0_SIZE = 16 * 1024;
static const int RAM_BANK1_SIZE = 16 * 1024;
__attribute((section("AHBSRAM0"),aligned)) char ramBank0[RAM_BANK0_SIZE];
__attribute((section("AHBSRAM1"),aligned)) char ramBank1[RAM_BANK1_SIZE];
static effect_mode_t effectMode;
static uint16_t effectGain;
static const int MAX_DELAYS = 7;
static delay_t *delay[MAX_DELAYS];
static void initializeEcho(void);
static void initializeReverb(void);
/*
* Initialize module.
*/
void Effects_Initialize(void)
{
effectGain = 0;
// Create all the delay objects. They will be initialized and
// re-initialized as needed each time the mode changes, but the
// total number of delay objects is fixed.
for (int i = 0; i < MAX_DELAYS; i++)
{
delay[i] = Delay_Create();
}
Effects_SetMode(EFFECT_STRAIGHT);
}
/*
* Apply current effect to sample stream.
* @return Processed sample.
*/
int16_t Effects_ProcessSample(int16_t dataIn)
{
int16_t dataOut;
switch (effectMode)
{
case EFFECT_ECHO:
dataOut = Delay_WriteWithFeedback(delay[0], dataIn, effectGain);
break;
case EFFECT_REVERB:
dataOut = (Delay_WriteWithFeedback(delay[0], dataIn, effectGain) +
Delay_WriteWithFeedback(delay[1], dataIn, effectGain) +
Delay_WriteWithFeedback(delay[2], dataIn, effectGain) +
Delay_WriteWithFeedback(delay[3], dataIn, effectGain) +
Delay_WriteWithFeedback(delay[4], dataIn, effectGain) +
Delay_WriteWithFeedback(delay[5], dataIn, effectGain) +
Delay_WriteWithFeedback(delay[6], dataIn, effectGain)) / 7;
break;
case EFFECT_STRAIGHT:
default:
dataOut = dataIn;
}
return dataOut;
}
/*
* Getter/setters.
*/
void Effects_SetMode(effect_mode_t mode)
{
// Ignore if already in desired mode.
if (effectMode == mode) return;
// Effects_Process() will continue to be called by an ISR while
// changing modes, so first change to straight mode since this
// can safely play at any time. Then change to the desired mode
// once it is fully configured.
effectMode = EFFECT_STRAIGHT;
switch (mode)
{
case EFFECT_ECHO:
initializeEcho();
effectMode = mode;
break;
case EFFECT_REVERB:
initializeReverb();
effectMode = mode;
break;
case EFFECT_STRAIGHT:
default:
effectMode = mode;
}
}
void Effects_SetGain(uint16_t gain) { effectGain = gain; }
/*
* Configure one large delay for echo.
*/
void initializeEcho(void)
{
// The maximum echo delay is 16K samples since each sample is 2 bytes
// and we have 32KB available.
static const int ECHO_DELAY_SAMPLES = 12000;
Delay_Configure(delay[0], (void *)ramBank0, ECHO_DELAY_SAMPLES * sizeof(int16_t));
}
/*
* Configure all delays for reverb.
*/
void initializeReverb(void)
{
// Delay lengths are chosen as a base length times prime numbers to prevent
// interfernce patterns. Total size of all delay lines must fit within 32KB.
static const int REVERB_BASE_DELAY_SAMPLES = 256;
static const int PRIMES[MAX_DELAYS] = {2, 3, 5, 7, 11, 13, 17};
char *ram = ramBank0; // Location for first buffer.
for (int i = 0; i < MAX_DELAYS; i++)
{
// Configure each delay with proper buffer size and location
int size = PRIMES[i] * REVERB_BASE_DELAY_SAMPLES * sizeof(int16_t);
Delay_Configure(delay[i], (void *)ram, size);
// The next buffer location immediately follows this one.
ram += size;
}
}