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.
*/

audio.cpp

Committer:
bw
Date:
2014-03-27
Revision:
2:9429f84ea165
Parent:
0:bbf6cf0eab95

File content as of revision 2:9429f84ea165:

/*******************************************************************************
 * 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;   
}