Streams USB audio with sound effects applied. Sound effect selected by joystick and intensity altered by tilting the mbed. Output to the mbed-application-board phono jack.
Dependencies: C12832_lcd MMA7660 USBDevice mbed
/* Uses the mbed LPC1768 and mbed-application-board to create a USB audio device * that streams audio from a host computer to headphones or powered speakers. * A couple different sound effects can be applied to the stream in real-time, * and tilting the mbed alters intensity of the effect. * * ECHO * The joystick selects ) | * one of three effect ) STRAIGHT - o - STRAIGHT * modes. ) | * REVERB * * * * \\ || * Tilting the mbed ) ====== \\ || * determines intensity ) \\ || * of the effect. ) * 0% 50% 100% * * The LCD display shows the current effect mode, intesity and buffer level. */
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; } }