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

/media/uploads/bw/img_1293.jpg

/* 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.
*/
Revision:
0:bbf6cf0eab95
--- /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;   
+}
+
+