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. */
Diff: audio.cpp
- Revision:
- 0:bbf6cf0eab95
diff -r 000000000000 -r bbf6cf0eab95 audio.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/audio.cpp Thu Mar 27 21:27:04 2014 +0000 @@ -0,0 +1,116 @@ +/******************************************************************************* + * Manages all aspects of audio playback with sound effects. + * Bryan Wade + * 27 MAR 2014 + ******************************************************************************/ +#include "mbed.h" +#include "USBAudio.h" +#include "buffer.h" +#include "effects.h" + +static const int SAMPLE_FREQ = 50000; +static const int NUM_CHANNELS = 1; +static const int PACKET_FREQ = 1000; +static const int PACKET_LENGTH = SAMPLE_FREQ / PACKET_FREQ; +static const int PLAYBACK_BUFFER_SIZE = 8 * 1024; + +static int16_t packetBuffer[PACKET_LENGTH]; +static char playbackBufferRAM[PLAYBACK_BUFFER_SIZE]; +static buffer_t *playbackBuffer; +static bool playbackReady = false; + +AnalogOut speaker(p18); +USBAudio audio(SAMPLE_FREQ, NUM_CHANNELS, 8000, 1, 0x7180, 0x7500); +Ticker playbackTic; +DigitalOut bufferLED(LED1); // On when buffer is ready for playback. +DigitalOut playbackLED(LED2); // On when playing audio. +DigitalOut sampleLED(LED3); // Toggles on each audio sample played. +DigitalOut packetLED(LED4); // Toggles on each audio packet received. + +/* + * Transfers packet to the playback buffer each time a packet is received. + */ +void handlePacket(void) { + Buffer_WriteBlock(playbackBuffer, packetBuffer, PACKET_LENGTH); + packetLED = !packetLED; +} + +/* + * Pulls a sample from the playback buffer, adds effects and sends to speaker. + */ +void handlePlayback() +{ + int16_t sample; + + // Get a sample from playback buffer + if (playbackReady) { + if (Buffer_Read(playbackBuffer, &sample)) + { + playbackLED = 1; // Playing + } else { + sample = 0; // Shouldn't get hear if buffer limits set properly. + playbackLED = 0; + } + } else { + sample = 0; // Nothing to play + playbackLED = 0; + } + + // Add sound effects + int32_t out = Effects_ProcessSample(sample); + + // Write the sample to the uni-polar A/D, which requires offseting the signed 16-bit sample. + speaker.write_u16(out + 32767); + + sampleLED = !sampleLED; +} + +/* + * Initialize audio module. + */ +void Audio_Initialize(void) +{ + Effects_Initialize(); + + // Create a buffer that will incomming audio packets and provide a consistent supply + // for playback at the desired sample rate. + playbackBuffer = Buffer_Create(playbackBufferRAM, sizeof(playbackBufferRAM)); + + // Start the playback timer interrupt that will call the playback handler at the desired + // sample rate. + playbackTic.attach_us(handlePlayback, 1000000.0/(float)(SAMPLE_FREQ)); + + // Attach the handler that will buffer packets from incomming USB audio. + // Perform the first read to set the buffer location, then all subsequent packets + // will go to this buffer, and the handler pulls them from this small buffer + // and places them in the large playback buffer. + audio.attachReadCallback(handlePacket); + audio.readNB((uint8_t *)packetBuffer); + + // Reduce USB IRQ priority so that audio playback is not interrupted by USB activity. + static const int LOW_PRIORITY = 255; // Larger number is lower priority. + NVIC_SetPriority(USB_IRQn, LOW_PRIORITY); +} + +/* + * Checks buffer level and updates playbackReady flag. + * @return Buffer level. + */ +int32_t Audio_CheckPlaybackBufferLevel(void) +{ + static int32_t PLAYBACK_START_LEVEL = 4 * PACKET_LENGTH; + static int32_t PLAYBACK_STOP_LEVEL = 2 * PACKET_LENGTH; + + int32_t level = Buffer_GetLevel(playbackBuffer); + if (level > PLAYBACK_START_LEVEL) { + playbackReady = true; + } else if (level < PLAYBACK_STOP_LEVEL) { + playbackReady = false; + } + + bufferLED = playbackReady; + + return level; +} + +