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
effects.cpp
00001 /******************************************************************************* 00002 * Module processes 16-bit audio samples to produces delay-based sound effects. 00003 * Bryan Wade 00004 * 27 MAR 2014 00005 ******************************************************************************/ 00006 #include "mbed.h" 00007 #include "effects.h" 00008 #include "delay.h" 00009 00010 // Delay based effects require significant RAM, so we must 00011 // scavange two banks of RAM that mbed has reserved for ethernet: 00012 // AHBSRAM0: 0x2007C000 - 0x2007FFFF (16KB) 00013 // AHBSRAM1: 0x20080000 - 0x20083FFF (16KB) 00014 // To keep the linker happy we allocate the RAM with a 16KB array in each bank, 00015 // but since they are contiguous, we can treat them as one 32KB block. 00016 static const int RAM_BANK0_SIZE = 16 * 1024; 00017 static const int RAM_BANK1_SIZE = 16 * 1024; 00018 __attribute((section("AHBSRAM0"),aligned)) char ramBank0[RAM_BANK0_SIZE]; 00019 __attribute((section("AHBSRAM1"),aligned)) char ramBank1[RAM_BANK1_SIZE]; 00020 00021 static effect_mode_t effectMode; 00022 static uint16_t effectGain; 00023 static const int MAX_DELAYS = 7; 00024 static delay_t *delay[MAX_DELAYS]; 00025 00026 static void initializeEcho(void); 00027 static void initializeReverb(void); 00028 00029 /* 00030 * Initialize module. 00031 */ 00032 void Effects_Initialize(void) 00033 { 00034 effectGain = 0; 00035 00036 // Create all the delay objects. They will be initialized and 00037 // re-initialized as needed each time the mode changes, but the 00038 // total number of delay objects is fixed. 00039 for (int i = 0; i < MAX_DELAYS; i++) 00040 { 00041 delay[i] = Delay_Create(); 00042 } 00043 Effects_SetMode(EFFECT_STRAIGHT); 00044 } 00045 00046 /* 00047 * Apply current effect to sample stream. 00048 * @return Processed sample. 00049 */ 00050 int16_t Effects_ProcessSample(int16_t dataIn) 00051 { 00052 int16_t dataOut; 00053 00054 switch (effectMode) 00055 { 00056 case EFFECT_ECHO: 00057 dataOut = Delay_WriteWithFeedback(delay[0], dataIn, effectGain); 00058 break; 00059 00060 case EFFECT_REVERB: 00061 dataOut = (Delay_WriteWithFeedback(delay[0], dataIn, effectGain) + 00062 Delay_WriteWithFeedback(delay[1], dataIn, effectGain) + 00063 Delay_WriteWithFeedback(delay[2], dataIn, effectGain) + 00064 Delay_WriteWithFeedback(delay[3], dataIn, effectGain) + 00065 Delay_WriteWithFeedback(delay[4], dataIn, effectGain) + 00066 Delay_WriteWithFeedback(delay[5], dataIn, effectGain) + 00067 Delay_WriteWithFeedback(delay[6], dataIn, effectGain)) / 7; 00068 break; 00069 00070 case EFFECT_STRAIGHT: 00071 default: 00072 dataOut = dataIn; 00073 } 00074 00075 return dataOut; 00076 } 00077 00078 /* 00079 * Getter/setters. 00080 */ 00081 void Effects_SetMode(effect_mode_t mode) 00082 { 00083 // Ignore if already in desired mode. 00084 if (effectMode == mode) return; 00085 00086 // Effects_Process() will continue to be called by an ISR while 00087 // changing modes, so first change to straight mode since this 00088 // can safely play at any time. Then change to the desired mode 00089 // once it is fully configured. 00090 effectMode = EFFECT_STRAIGHT; 00091 00092 switch (mode) 00093 { 00094 case EFFECT_ECHO: 00095 initializeEcho(); 00096 effectMode = mode; 00097 break; 00098 00099 case EFFECT_REVERB: 00100 initializeReverb(); 00101 effectMode = mode; 00102 break; 00103 00104 case EFFECT_STRAIGHT: 00105 default: 00106 effectMode = mode; 00107 } 00108 } 00109 00110 void Effects_SetGain(uint16_t gain) { effectGain = gain; } 00111 00112 /* 00113 * Configure one large delay for echo. 00114 */ 00115 void initializeEcho(void) 00116 { 00117 // The maximum echo delay is 16K samples since each sample is 2 bytes 00118 // and we have 32KB available. 00119 static const int ECHO_DELAY_SAMPLES = 12000; 00120 Delay_Configure(delay[0], (void *)ramBank0, ECHO_DELAY_SAMPLES * sizeof(int16_t)); 00121 } 00122 00123 /* 00124 * Configure all delays for reverb. 00125 */ 00126 void initializeReverb(void) 00127 { 00128 // Delay lengths are chosen as a base length times prime numbers to prevent 00129 // interfernce patterns. Total size of all delay lines must fit within 32KB. 00130 static const int REVERB_BASE_DELAY_SAMPLES = 256; 00131 static const int PRIMES[MAX_DELAYS] = {2, 3, 5, 7, 11, 13, 17}; 00132 00133 char *ram = ramBank0; // Location for first buffer. 00134 00135 for (int i = 0; i < MAX_DELAYS; i++) 00136 { 00137 // Configure each delay with proper buffer size and location 00138 int size = PRIMES[i] * REVERB_BASE_DELAY_SAMPLES * sizeof(int16_t); 00139 Delay_Configure(delay[i], (void *)ram, size); 00140 00141 // The next buffer location immediately follows this one. 00142 ram += size; 00143 } 00144 } 00145 00146 00147
Generated on Thu Jul 14 2022 01:44:22 by 1.7.2