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.
*/
Committer:
bw
Date:
Thu Mar 27 21:43:41 2014 +0000
Revision:
2:9429f84ea165
Parent:
0:bbf6cf0eab95
Clean up comments.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bw 0:bbf6cf0eab95 1 /*******************************************************************************
bw 0:bbf6cf0eab95 2 * Manages all aspects of audio playback with sound effects.
bw 0:bbf6cf0eab95 3 * Bryan Wade
bw 0:bbf6cf0eab95 4 * 27 MAR 2014
bw 0:bbf6cf0eab95 5 ******************************************************************************/
bw 0:bbf6cf0eab95 6 #include "mbed.h"
bw 0:bbf6cf0eab95 7 #include "USBAudio.h"
bw 0:bbf6cf0eab95 8 #include "buffer.h"
bw 0:bbf6cf0eab95 9 #include "effects.h"
bw 0:bbf6cf0eab95 10
bw 0:bbf6cf0eab95 11 static const int SAMPLE_FREQ = 50000;
bw 0:bbf6cf0eab95 12 static const int NUM_CHANNELS = 1;
bw 0:bbf6cf0eab95 13 static const int PACKET_FREQ = 1000;
bw 0:bbf6cf0eab95 14 static const int PACKET_LENGTH = SAMPLE_FREQ / PACKET_FREQ;
bw 0:bbf6cf0eab95 15 static const int PLAYBACK_BUFFER_SIZE = 8 * 1024;
bw 0:bbf6cf0eab95 16
bw 0:bbf6cf0eab95 17 static int16_t packetBuffer[PACKET_LENGTH];
bw 0:bbf6cf0eab95 18 static char playbackBufferRAM[PLAYBACK_BUFFER_SIZE];
bw 0:bbf6cf0eab95 19 static buffer_t *playbackBuffer;
bw 0:bbf6cf0eab95 20 static bool playbackReady = false;
bw 0:bbf6cf0eab95 21
bw 0:bbf6cf0eab95 22 AnalogOut speaker(p18);
bw 0:bbf6cf0eab95 23 USBAudio audio(SAMPLE_FREQ, NUM_CHANNELS, 8000, 1, 0x7180, 0x7500);
bw 0:bbf6cf0eab95 24 Ticker playbackTic;
bw 0:bbf6cf0eab95 25 DigitalOut bufferLED(LED1); // On when buffer is ready for playback.
bw 0:bbf6cf0eab95 26 DigitalOut playbackLED(LED2); // On when playing audio.
bw 0:bbf6cf0eab95 27 DigitalOut sampleLED(LED3); // Toggles on each audio sample played.
bw 0:bbf6cf0eab95 28 DigitalOut packetLED(LED4); // Toggles on each audio packet received.
bw 0:bbf6cf0eab95 29
bw 0:bbf6cf0eab95 30 /*
bw 0:bbf6cf0eab95 31 * Transfers packet to the playback buffer each time a packet is received.
bw 0:bbf6cf0eab95 32 */
bw 0:bbf6cf0eab95 33 void handlePacket(void) {
bw 0:bbf6cf0eab95 34 Buffer_WriteBlock(playbackBuffer, packetBuffer, PACKET_LENGTH);
bw 0:bbf6cf0eab95 35 packetLED = !packetLED;
bw 0:bbf6cf0eab95 36 }
bw 0:bbf6cf0eab95 37
bw 0:bbf6cf0eab95 38 /*
bw 0:bbf6cf0eab95 39 * Pulls a sample from the playback buffer, adds effects and sends to speaker.
bw 0:bbf6cf0eab95 40 */
bw 0:bbf6cf0eab95 41 void handlePlayback()
bw 0:bbf6cf0eab95 42 {
bw 0:bbf6cf0eab95 43 int16_t sample;
bw 0:bbf6cf0eab95 44
bw 0:bbf6cf0eab95 45 // Get a sample from playback buffer
bw 0:bbf6cf0eab95 46 if (playbackReady) {
bw 0:bbf6cf0eab95 47 if (Buffer_Read(playbackBuffer, &sample))
bw 0:bbf6cf0eab95 48 {
bw 0:bbf6cf0eab95 49 playbackLED = 1; // Playing
bw 0:bbf6cf0eab95 50 } else {
bw 0:bbf6cf0eab95 51 sample = 0; // Shouldn't get hear if buffer limits set properly.
bw 0:bbf6cf0eab95 52 playbackLED = 0;
bw 0:bbf6cf0eab95 53 }
bw 0:bbf6cf0eab95 54 } else {
bw 0:bbf6cf0eab95 55 sample = 0; // Nothing to play
bw 0:bbf6cf0eab95 56 playbackLED = 0;
bw 0:bbf6cf0eab95 57 }
bw 0:bbf6cf0eab95 58
bw 0:bbf6cf0eab95 59 // Add sound effects
bw 0:bbf6cf0eab95 60 int32_t out = Effects_ProcessSample(sample);
bw 0:bbf6cf0eab95 61
bw 0:bbf6cf0eab95 62 // Write the sample to the uni-polar A/D, which requires offseting the signed 16-bit sample.
bw 0:bbf6cf0eab95 63 speaker.write_u16(out + 32767);
bw 0:bbf6cf0eab95 64
bw 0:bbf6cf0eab95 65 sampleLED = !sampleLED;
bw 0:bbf6cf0eab95 66 }
bw 0:bbf6cf0eab95 67
bw 0:bbf6cf0eab95 68 /*
bw 0:bbf6cf0eab95 69 * Initialize audio module.
bw 0:bbf6cf0eab95 70 */
bw 0:bbf6cf0eab95 71 void Audio_Initialize(void)
bw 0:bbf6cf0eab95 72 {
bw 0:bbf6cf0eab95 73 Effects_Initialize();
bw 0:bbf6cf0eab95 74
bw 0:bbf6cf0eab95 75 // Create a buffer that will incomming audio packets and provide a consistent supply
bw 0:bbf6cf0eab95 76 // for playback at the desired sample rate.
bw 0:bbf6cf0eab95 77 playbackBuffer = Buffer_Create(playbackBufferRAM, sizeof(playbackBufferRAM));
bw 0:bbf6cf0eab95 78
bw 0:bbf6cf0eab95 79 // Start the playback timer interrupt that will call the playback handler at the desired
bw 0:bbf6cf0eab95 80 // sample rate.
bw 0:bbf6cf0eab95 81 playbackTic.attach_us(handlePlayback, 1000000.0/(float)(SAMPLE_FREQ));
bw 0:bbf6cf0eab95 82
bw 0:bbf6cf0eab95 83 // Attach the handler that will buffer packets from incomming USB audio.
bw 0:bbf6cf0eab95 84 // Perform the first read to set the buffer location, then all subsequent packets
bw 0:bbf6cf0eab95 85 // will go to this buffer, and the handler pulls them from this small buffer
bw 0:bbf6cf0eab95 86 // and places them in the large playback buffer.
bw 0:bbf6cf0eab95 87 audio.attachReadCallback(handlePacket);
bw 0:bbf6cf0eab95 88 audio.readNB((uint8_t *)packetBuffer);
bw 0:bbf6cf0eab95 89
bw 0:bbf6cf0eab95 90 // Reduce USB IRQ priority so that audio playback is not interrupted by USB activity.
bw 0:bbf6cf0eab95 91 static const int LOW_PRIORITY = 255; // Larger number is lower priority.
bw 0:bbf6cf0eab95 92 NVIC_SetPriority(USB_IRQn, LOW_PRIORITY);
bw 0:bbf6cf0eab95 93 }
bw 0:bbf6cf0eab95 94
bw 0:bbf6cf0eab95 95 /*
bw 0:bbf6cf0eab95 96 * Checks buffer level and updates playbackReady flag.
bw 0:bbf6cf0eab95 97 * @return Buffer level.
bw 0:bbf6cf0eab95 98 */
bw 0:bbf6cf0eab95 99 int32_t Audio_CheckPlaybackBufferLevel(void)
bw 0:bbf6cf0eab95 100 {
bw 0:bbf6cf0eab95 101 static int32_t PLAYBACK_START_LEVEL = 4 * PACKET_LENGTH;
bw 0:bbf6cf0eab95 102 static int32_t PLAYBACK_STOP_LEVEL = 2 * PACKET_LENGTH;
bw 0:bbf6cf0eab95 103
bw 0:bbf6cf0eab95 104 int32_t level = Buffer_GetLevel(playbackBuffer);
bw 0:bbf6cf0eab95 105 if (level > PLAYBACK_START_LEVEL) {
bw 0:bbf6cf0eab95 106 playbackReady = true;
bw 0:bbf6cf0eab95 107 } else if (level < PLAYBACK_STOP_LEVEL) {
bw 0:bbf6cf0eab95 108 playbackReady = false;
bw 0:bbf6cf0eab95 109 }
bw 0:bbf6cf0eab95 110
bw 0:bbf6cf0eab95 111 bufferLED = playbackReady;
bw 0:bbf6cf0eab95 112
bw 0:bbf6cf0eab95 113 return level;
bw 0:bbf6cf0eab95 114 }
bw 0:bbf6cf0eab95 115
bw 0:bbf6cf0eab95 116