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 * Module processes 16-bit audio samples to produces delay-based 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 "effects.h"
bw 0:bbf6cf0eab95 8 #include "delay.h"
bw 0:bbf6cf0eab95 9
bw 0:bbf6cf0eab95 10 // Delay based effects require significant RAM, so we must
bw 0:bbf6cf0eab95 11 // scavange two banks of RAM that mbed has reserved for ethernet:
bw 0:bbf6cf0eab95 12 // AHBSRAM0: 0x2007C000 - 0x2007FFFF (16KB)
bw 0:bbf6cf0eab95 13 // AHBSRAM1: 0x20080000 - 0x20083FFF (16KB)
bw 0:bbf6cf0eab95 14 // To keep the linker happy we allocate the RAM with a 16KB array in each bank,
bw 0:bbf6cf0eab95 15 // but since they are contiguous, we can treat them as one 32KB block.
bw 0:bbf6cf0eab95 16 static const int RAM_BANK0_SIZE = 16 * 1024;
bw 0:bbf6cf0eab95 17 static const int RAM_BANK1_SIZE = 16 * 1024;
bw 0:bbf6cf0eab95 18 __attribute((section("AHBSRAM0"),aligned)) char ramBank0[RAM_BANK0_SIZE];
bw 0:bbf6cf0eab95 19 __attribute((section("AHBSRAM1"),aligned)) char ramBank1[RAM_BANK1_SIZE];
bw 0:bbf6cf0eab95 20
bw 0:bbf6cf0eab95 21 static effect_mode_t effectMode;
bw 0:bbf6cf0eab95 22 static uint16_t effectGain;
bw 0:bbf6cf0eab95 23 static const int MAX_DELAYS = 7;
bw 0:bbf6cf0eab95 24 static delay_t *delay[MAX_DELAYS];
bw 0:bbf6cf0eab95 25
bw 0:bbf6cf0eab95 26 static void initializeEcho(void);
bw 0:bbf6cf0eab95 27 static void initializeReverb(void);
bw 0:bbf6cf0eab95 28
bw 0:bbf6cf0eab95 29 /*
bw 0:bbf6cf0eab95 30 * Initialize module.
bw 0:bbf6cf0eab95 31 */
bw 0:bbf6cf0eab95 32 void Effects_Initialize(void)
bw 0:bbf6cf0eab95 33 {
bw 0:bbf6cf0eab95 34 effectGain = 0;
bw 0:bbf6cf0eab95 35
bw 0:bbf6cf0eab95 36 // Create all the delay objects. They will be initialized and
bw 0:bbf6cf0eab95 37 // re-initialized as needed each time the mode changes, but the
bw 0:bbf6cf0eab95 38 // total number of delay objects is fixed.
bw 0:bbf6cf0eab95 39 for (int i = 0; i < MAX_DELAYS; i++)
bw 0:bbf6cf0eab95 40 {
bw 0:bbf6cf0eab95 41 delay[i] = Delay_Create();
bw 0:bbf6cf0eab95 42 }
bw 0:bbf6cf0eab95 43 Effects_SetMode(EFFECT_STRAIGHT);
bw 0:bbf6cf0eab95 44 }
bw 0:bbf6cf0eab95 45
bw 0:bbf6cf0eab95 46 /*
bw 0:bbf6cf0eab95 47 * Apply current effect to sample stream.
bw 0:bbf6cf0eab95 48 * @return Processed sample.
bw 0:bbf6cf0eab95 49 */
bw 0:bbf6cf0eab95 50 int16_t Effects_ProcessSample(int16_t dataIn)
bw 0:bbf6cf0eab95 51 {
bw 0:bbf6cf0eab95 52 int16_t dataOut;
bw 0:bbf6cf0eab95 53
bw 0:bbf6cf0eab95 54 switch (effectMode)
bw 0:bbf6cf0eab95 55 {
bw 0:bbf6cf0eab95 56 case EFFECT_ECHO:
bw 0:bbf6cf0eab95 57 dataOut = Delay_WriteWithFeedback(delay[0], dataIn, effectGain);
bw 0:bbf6cf0eab95 58 break;
bw 0:bbf6cf0eab95 59
bw 0:bbf6cf0eab95 60 case EFFECT_REVERB:
bw 0:bbf6cf0eab95 61 dataOut = (Delay_WriteWithFeedback(delay[0], dataIn, effectGain) +
bw 0:bbf6cf0eab95 62 Delay_WriteWithFeedback(delay[1], dataIn, effectGain) +
bw 0:bbf6cf0eab95 63 Delay_WriteWithFeedback(delay[2], dataIn, effectGain) +
bw 0:bbf6cf0eab95 64 Delay_WriteWithFeedback(delay[3], dataIn, effectGain) +
bw 0:bbf6cf0eab95 65 Delay_WriteWithFeedback(delay[4], dataIn, effectGain) +
bw 0:bbf6cf0eab95 66 Delay_WriteWithFeedback(delay[5], dataIn, effectGain) +
bw 0:bbf6cf0eab95 67 Delay_WriteWithFeedback(delay[6], dataIn, effectGain)) / 7;
bw 0:bbf6cf0eab95 68 break;
bw 0:bbf6cf0eab95 69
bw 0:bbf6cf0eab95 70 case EFFECT_STRAIGHT:
bw 0:bbf6cf0eab95 71 default:
bw 0:bbf6cf0eab95 72 dataOut = dataIn;
bw 0:bbf6cf0eab95 73 }
bw 0:bbf6cf0eab95 74
bw 0:bbf6cf0eab95 75 return dataOut;
bw 0:bbf6cf0eab95 76 }
bw 0:bbf6cf0eab95 77
bw 0:bbf6cf0eab95 78 /*
bw 0:bbf6cf0eab95 79 * Getter/setters.
bw 0:bbf6cf0eab95 80 */
bw 0:bbf6cf0eab95 81 void Effects_SetMode(effect_mode_t mode)
bw 0:bbf6cf0eab95 82 {
bw 0:bbf6cf0eab95 83 // Ignore if already in desired mode.
bw 0:bbf6cf0eab95 84 if (effectMode == mode) return;
bw 0:bbf6cf0eab95 85
bw 0:bbf6cf0eab95 86 // Effects_Process() will continue to be called by an ISR while
bw 0:bbf6cf0eab95 87 // changing modes, so first change to straight mode since this
bw 0:bbf6cf0eab95 88 // can safely play at any time. Then change to the desired mode
bw 0:bbf6cf0eab95 89 // once it is fully configured.
bw 0:bbf6cf0eab95 90 effectMode = EFFECT_STRAIGHT;
bw 0:bbf6cf0eab95 91
bw 0:bbf6cf0eab95 92 switch (mode)
bw 0:bbf6cf0eab95 93 {
bw 0:bbf6cf0eab95 94 case EFFECT_ECHO:
bw 0:bbf6cf0eab95 95 initializeEcho();
bw 0:bbf6cf0eab95 96 effectMode = mode;
bw 0:bbf6cf0eab95 97 break;
bw 0:bbf6cf0eab95 98
bw 0:bbf6cf0eab95 99 case EFFECT_REVERB:
bw 0:bbf6cf0eab95 100 initializeReverb();
bw 0:bbf6cf0eab95 101 effectMode = mode;
bw 0:bbf6cf0eab95 102 break;
bw 0:bbf6cf0eab95 103
bw 0:bbf6cf0eab95 104 case EFFECT_STRAIGHT:
bw 0:bbf6cf0eab95 105 default:
bw 0:bbf6cf0eab95 106 effectMode = mode;
bw 0:bbf6cf0eab95 107 }
bw 0:bbf6cf0eab95 108 }
bw 0:bbf6cf0eab95 109
bw 0:bbf6cf0eab95 110 void Effects_SetGain(uint16_t gain) { effectGain = gain; }
bw 0:bbf6cf0eab95 111
bw 0:bbf6cf0eab95 112 /*
bw 0:bbf6cf0eab95 113 * Configure one large delay for echo.
bw 0:bbf6cf0eab95 114 */
bw 0:bbf6cf0eab95 115 void initializeEcho(void)
bw 0:bbf6cf0eab95 116 {
bw 0:bbf6cf0eab95 117 // The maximum echo delay is 16K samples since each sample is 2 bytes
bw 0:bbf6cf0eab95 118 // and we have 32KB available.
bw 0:bbf6cf0eab95 119 static const int ECHO_DELAY_SAMPLES = 12000;
bw 0:bbf6cf0eab95 120 Delay_Configure(delay[0], (void *)ramBank0, ECHO_DELAY_SAMPLES * sizeof(int16_t));
bw 0:bbf6cf0eab95 121 }
bw 0:bbf6cf0eab95 122
bw 0:bbf6cf0eab95 123 /*
bw 0:bbf6cf0eab95 124 * Configure all delays for reverb.
bw 0:bbf6cf0eab95 125 */
bw 0:bbf6cf0eab95 126 void initializeReverb(void)
bw 0:bbf6cf0eab95 127 {
bw 0:bbf6cf0eab95 128 // Delay lengths are chosen as a base length times prime numbers to prevent
bw 0:bbf6cf0eab95 129 // interfernce patterns. Total size of all delay lines must fit within 32KB.
bw 0:bbf6cf0eab95 130 static const int REVERB_BASE_DELAY_SAMPLES = 256;
bw 0:bbf6cf0eab95 131 static const int PRIMES[MAX_DELAYS] = {2, 3, 5, 7, 11, 13, 17};
bw 0:bbf6cf0eab95 132
bw 0:bbf6cf0eab95 133 char *ram = ramBank0; // Location for first buffer.
bw 0:bbf6cf0eab95 134
bw 0:bbf6cf0eab95 135 for (int i = 0; i < MAX_DELAYS; i++)
bw 0:bbf6cf0eab95 136 {
bw 0:bbf6cf0eab95 137 // Configure each delay with proper buffer size and location
bw 0:bbf6cf0eab95 138 int size = PRIMES[i] * REVERB_BASE_DELAY_SAMPLES * sizeof(int16_t);
bw 0:bbf6cf0eab95 139 Delay_Configure(delay[i], (void *)ram, size);
bw 0:bbf6cf0eab95 140
bw 0:bbf6cf0eab95 141 // The next buffer location immediately follows this one.
bw 0:bbf6cf0eab95 142 ram += size;
bw 0:bbf6cf0eab95 143 }
bw 0:bbf6cf0eab95 144 }
bw 0:bbf6cf0eab95 145
bw 0:bbf6cf0eab95 146
bw 0:bbf6cf0eab95 147