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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers audio.cpp Source File

audio.cpp

00001 /*******************************************************************************
00002  * Manages all aspects of audio playback with sound effects.
00003  * Bryan Wade
00004  * 27 MAR 2014
00005  ******************************************************************************/
00006 #include "mbed.h"
00007 #include "USBAudio.h"
00008 #include "buffer.h"
00009 #include "effects.h"
00010 
00011 static const int SAMPLE_FREQ = 50000;
00012 static const int NUM_CHANNELS = 1;
00013 static const int PACKET_FREQ = 1000;
00014 static const int PACKET_LENGTH = SAMPLE_FREQ / PACKET_FREQ;
00015 static const int PLAYBACK_BUFFER_SIZE = 8 * 1024;
00016 
00017 static int16_t packetBuffer[PACKET_LENGTH];
00018 static char playbackBufferRAM[PLAYBACK_BUFFER_SIZE]; 
00019 static buffer_t *playbackBuffer;
00020 static bool playbackReady = false;
00021 
00022 AnalogOut speaker(p18);
00023 USBAudio audio(SAMPLE_FREQ, NUM_CHANNELS, 8000, 1, 0x7180, 0x7500);
00024 Ticker playbackTic;
00025 DigitalOut bufferLED(LED1);   // On when buffer is ready for playback.
00026 DigitalOut playbackLED(LED2); // On when playing audio.
00027 DigitalOut sampleLED(LED3);   // Toggles on each audio sample played.
00028 DigitalOut packetLED(LED4);   // Toggles on each audio packet received.
00029 
00030 /*
00031  * Transfers packet to the playback buffer each time a packet is received.
00032  */
00033 void handlePacket(void) {
00034     Buffer_WriteBlock(playbackBuffer, packetBuffer, PACKET_LENGTH);
00035     packetLED = !packetLED; 
00036 }
00037 
00038 /*
00039  * Pulls a sample from the playback buffer, adds effects and sends to speaker.
00040  */
00041 void handlePlayback() 
00042 {
00043     int16_t sample; 
00044     
00045     // Get a sample from playback buffer
00046     if (playbackReady) {
00047         if (Buffer_Read(playbackBuffer, &sample))
00048         {
00049             playbackLED = 1; // Playing 
00050         } else {
00051             sample = 0;         // Shouldn't get hear if buffer limits set properly.
00052             playbackLED = 0; 
00053         }
00054     } else {
00055         sample = 0;             // Nothing to play
00056         playbackLED = 0;
00057     }
00058 
00059     // Add sound effects
00060     int32_t out = Effects_ProcessSample(sample);
00061             
00062     // Write the sample to the uni-polar A/D, which requires offseting the signed 16-bit sample.         
00063     speaker.write_u16(out + 32767);
00064             
00065     sampleLED = !sampleLED;   
00066 }
00067 
00068 /*
00069  * Initialize audio module.
00070  */
00071 void Audio_Initialize(void)
00072 {
00073     Effects_Initialize();
00074     
00075     // Create a buffer that will incomming audio packets and provide a consistent supply
00076     // for playback at the desired sample rate.
00077     playbackBuffer = Buffer_Create(playbackBufferRAM, sizeof(playbackBufferRAM));
00078          
00079     // Start the playback timer interrupt that will call the playback handler at the desired
00080     // sample rate.     
00081     playbackTic.attach_us(handlePlayback, 1000000.0/(float)(SAMPLE_FREQ));
00082 
00083     // Attach the handler that will buffer packets from incomming USB audio. 
00084     // Perform the first read to set the buffer location, then all subsequent packets
00085     // will go to this buffer, and the handler pulls them from this small buffer
00086     // and places them in the large playback buffer.
00087     audio.attachReadCallback(handlePacket);
00088     audio.readNB((uint8_t *)packetBuffer);
00089     
00090     // Reduce USB IRQ priority so that audio playback is not interrupted by USB activity.
00091     static const int LOW_PRIORITY = 255; // Larger number is lower priority.
00092     NVIC_SetPriority(USB_IRQn, LOW_PRIORITY);   
00093 }
00094 
00095 /*
00096  * Checks buffer level and updates playbackReady flag.
00097  * @return Buffer level.
00098  */
00099 int32_t Audio_CheckPlaybackBufferLevel(void)
00100 {
00101     static int32_t PLAYBACK_START_LEVEL = 4 * PACKET_LENGTH;
00102     static int32_t PLAYBACK_STOP_LEVEL = 2 * PACKET_LENGTH;
00103     
00104     int32_t level = Buffer_GetLevel(playbackBuffer);
00105     if (level > PLAYBACK_START_LEVEL) {
00106         playbackReady = true;
00107     } else if (level < PLAYBACK_STOP_LEVEL) {
00108         playbackReady = false;
00109     }
00110     
00111     bufferLED = playbackReady;
00112     
00113     return level;   
00114 }
00115 
00116