AudioRecord

Dependencies:   STM32L4xx_HAL_Driver CMSIS_DSP_401

Committer:
EricLew
Date:
Mon Nov 23 19:37:13 2015 +0000
Revision:
0:d4e5ad7ad71c
Child:
1:1ae4b642c533
commit;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
EricLew 0:d4e5ad7ad71c 1
EricLew 0:d4e5ad7ad71c 2
EricLew 0:d4e5ad7ad71c 3 /* Includes ------------------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 4 #include "main.h"
EricLew 0:d4e5ad7ad71c 5
EricLew 0:d4e5ad7ad71c 6 /* Variable indicating which audio demo is currently running (playback v.s. record) */
EricLew 0:d4e5ad7ad71c 7 Audio_DemoTypeDef AudioDemo = AUDIO_DEMO_NONE;
EricLew 0:d4e5ad7ad71c 8
EricLew 0:d4e5ad7ad71c 9 /* Private typedef -----------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 10 typedef enum
EricLew 0:d4e5ad7ad71c 11 {
EricLew 0:d4e5ad7ad71c 12 BUFFER_OFFSET_NONE = 0,
EricLew 0:d4e5ad7ad71c 13 BUFFER_OFFSET_HALF,
EricLew 0:d4e5ad7ad71c 14 BUFFER_OFFSET_FULL,
EricLew 0:d4e5ad7ad71c 15 } RecordBufferOffset_Typedef;
EricLew 0:d4e5ad7ad71c 16
EricLew 0:d4e5ad7ad71c 17
EricLew 0:d4e5ad7ad71c 18 /* Private define ------------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 19 /* Size (in bytes) of the buffer containing the recorded PCM samples */
EricLew 0:d4e5ad7ad71c 20 #define RECORD_BUFFER_SIZE (uint32_t)1024
EricLew 0:d4e5ad7ad71c 21
EricLew 0:d4e5ad7ad71c 22 /* Private macro -------------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 23 /* Private variables ---------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 24 /* Buffer containing the PCM samples coming from the microphone */
EricLew 0:d4e5ad7ad71c 25 static uint16_t RecordBuffer[RECORD_BUFFER_SIZE];
EricLew 0:d4e5ad7ad71c 26
EricLew 0:d4e5ad7ad71c 27 /* Buffer used to stream the recorded PCM samples towards the audio codec. */
EricLew 0:d4e5ad7ad71c 28 static uint16_t PlaybackBuffer[RECORD_BUFFER_SIZE*2];
EricLew 0:d4e5ad7ad71c 29
EricLew 0:d4e5ad7ad71c 30
EricLew 0:d4e5ad7ad71c 31 #define NB_SAMPLES_RATE 7
EricLew 0:d4e5ad7ad71c 32 static uint32_t SamplesRates[NB_SAMPLES_RATE] = {BSP_AUDIO_FREQUENCY_48K,
EricLew 0:d4e5ad7ad71c 33 BSP_AUDIO_FREQUENCY_44K,
EricLew 0:d4e5ad7ad71c 34 BSP_AUDIO_FREQUENCY_32K,
EricLew 0:d4e5ad7ad71c 35 BSP_AUDIO_FREQUENCY_22K,
EricLew 0:d4e5ad7ad71c 36 BSP_AUDIO_FREQUENCY_16K,
EricLew 0:d4e5ad7ad71c 37 BSP_AUDIO_FREQUENCY_11K,
EricLew 0:d4e5ad7ad71c 38 BSP_AUDIO_FREQUENCY_8K};
EricLew 0:d4e5ad7ad71c 39
EricLew 0:d4e5ad7ad71c 40 /* Information indicating which part of the recorded buffer is ready for audio loopback */
EricLew 0:d4e5ad7ad71c 41 static RecordBufferOffset_Typedef RecordBufferOffset = BUFFER_OFFSET_NONE;
EricLew 0:d4e5ad7ad71c 42
EricLew 0:d4e5ad7ad71c 43 /* Private function prototypes -----------------------------------------------*/
EricLew 0:d4e5ad7ad71c 44 /* Display actuyel record sample rate */
EricLew 0:d4e5ad7ad71c 45 static void SampleRateDisplay(uint8_t SampleRate);
EricLew 0:d4e5ad7ad71c 46
EricLew 0:d4e5ad7ad71c 47 /* Record sample rate selection */
EricLew 0:d4e5ad7ad71c 48 static void SampleRateSelection(void);
EricLew 0:d4e5ad7ad71c 49
EricLew 0:d4e5ad7ad71c 50 /* Audio recorder callback functions */
EricLew 0:d4e5ad7ad71c 51 static void AudioRecord_TransferComplete_CallBack(void);
EricLew 0:d4e5ad7ad71c 52 static void AudioRecord_HalfTransfer_CallBack(void);
EricLew 0:d4e5ad7ad71c 53 static void AudioRecord_Error_CallBack(void);
EricLew 0:d4e5ad7ad71c 54
EricLew 0:d4e5ad7ad71c 55 /* Private functions ---------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 56
EricLew 0:d4e5ad7ad71c 57 /**
EricLew 0:d4e5ad7ad71c 58 * @brief Setup and start audio recording in loopback mode
EricLew 0:d4e5ad7ad71c 59 * @param None
EricLew 0:d4e5ad7ad71c 60 * @retval None
EricLew 0:d4e5ad7ad71c 61 */
EricLew 0:d4e5ad7ad71c 62 void AudioRecord_demo(void)
EricLew 0:d4e5ad7ad71c 63 {
EricLew 0:d4e5ad7ad71c 64 /* Indicates which part of the payback buffer must be updated */
EricLew 0:d4e5ad7ad71c 65 uint8_t transfer_range = 0;
EricLew 0:d4e5ad7ad71c 66
EricLew 0:d4e5ad7ad71c 67 /* Flag indicating whether the audio codec has already been initialized */
EricLew 0:d4e5ad7ad71c 68 uint32_t audio_loop_back_init = RESET ;
EricLew 0:d4e5ad7ad71c 69
EricLew 0:d4e5ad7ad71c 70 /* Audio record demo is running */
EricLew 0:d4e5ad7ad71c 71 AudioDemo = AUDIO_DEMO_RECORD;
EricLew 0:d4e5ad7ad71c 72
EricLew 0:d4e5ad7ad71c 73 /* Turn off green LED5 */
EricLew 0:d4e5ad7ad71c 74 BSP_LED_Off(LED5);
EricLew 0:d4e5ad7ad71c 75
EricLew 0:d4e5ad7ad71c 76 /* Initialize record buffer offset */
EricLew 0:d4e5ad7ad71c 77 RecordBufferOffset = BUFFER_OFFSET_NONE;
EricLew 0:d4e5ad7ad71c 78
EricLew 0:d4e5ad7ad71c 79 /* Select the audio record sample rate */
EricLew 0:d4e5ad7ad71c 80 SampleRateSelection();
EricLew 0:d4e5ad7ad71c 81
EricLew 0:d4e5ad7ad71c 82 /* Initialize audio input */
EricLew 0:d4e5ad7ad71c 83 if (BSP_AUDIO_IN_Init(SamplesRates[SampleRateIndex],
EricLew 0:d4e5ad7ad71c 84 DEFAULT_AUDIO_IN_BIT_RESOLUTION,
EricLew 0:d4e5ad7ad71c 85 DEFAULT_AUDIO_IN_CHANNEL_NBR) != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 86 {
EricLew 0:d4e5ad7ad71c 87 /* Record Error */
EricLew 0:d4e5ad7ad71c 88 Error_Handler();
EricLew 0:d4e5ad7ad71c 89 }
EricLew 0:d4e5ad7ad71c 90
EricLew 0:d4e5ad7ad71c 91 /* Set Callback function pointers */
EricLew 0:d4e5ad7ad71c 92 BSP_AUDIO_IN_RegisterCallbacks(AudioRecord_Error_CallBack,
EricLew 0:d4e5ad7ad71c 93 AudioRecord_HalfTransfer_CallBack,
EricLew 0:d4e5ad7ad71c 94 AudioRecord_TransferComplete_CallBack);
EricLew 0:d4e5ad7ad71c 95
EricLew 0:d4e5ad7ad71c 96 /* Start the audio record */
EricLew 0:d4e5ad7ad71c 97 if (BSP_AUDIO_IN_Record((uint16_t*)&RecordBuffer[0],
EricLew 0:d4e5ad7ad71c 98 RECORD_BUFFER_SIZE) != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 99 {
EricLew 0:d4e5ad7ad71c 100 Error_Handler();
EricLew 0:d4e5ad7ad71c 101 }
EricLew 0:d4e5ad7ad71c 102
EricLew 0:d4e5ad7ad71c 103 /* PCM samples recording loop */
EricLew 0:d4e5ad7ad71c 104 while (AudioRecordExit != SET)
EricLew 0:d4e5ad7ad71c 105 {
EricLew 0:d4e5ad7ad71c 106 /* 1st or 2nd half of the record buffer ready for being copied
EricLew 0:d4e5ad7ad71c 107 to the playback buffer */
EricLew 0:d4e5ad7ad71c 108 if(RecordBufferOffset != BUFFER_OFFSET_NONE)
EricLew 0:d4e5ad7ad71c 109 {
EricLew 0:d4e5ad7ad71c 110 /* Copy half of the record buffer to the playback buffer */
EricLew 0:d4e5ad7ad71c 111 if(RecordBufferOffset == BUFFER_OFFSET_HALF)
EricLew 0:d4e5ad7ad71c 112 {
EricLew 0:d4e5ad7ad71c 113 memcpy(&PlaybackBuffer[(RECORD_BUFFER_SIZE/2) * transfer_range],
EricLew 0:d4e5ad7ad71c 114 RecordBuffer,
EricLew 0:d4e5ad7ad71c 115 RECORD_BUFFER_SIZE);
EricLew 0:d4e5ad7ad71c 116
EricLew 0:d4e5ad7ad71c 117
EricLew 0:d4e5ad7ad71c 118 }
EricLew 0:d4e5ad7ad71c 119 else /* if(RecordBufferOffset == BUFFER_OFFSET_FULL)*/
EricLew 0:d4e5ad7ad71c 120 {
EricLew 0:d4e5ad7ad71c 121 memcpy(&PlaybackBuffer[(RECORD_BUFFER_SIZE/2) * transfer_range],
EricLew 0:d4e5ad7ad71c 122 &RecordBuffer[RECORD_BUFFER_SIZE/2],
EricLew 0:d4e5ad7ad71c 123 RECORD_BUFFER_SIZE);
EricLew 0:d4e5ad7ad71c 124 }
EricLew 0:d4e5ad7ad71c 125
EricLew 0:d4e5ad7ad71c 126 /* Wait for next data */
EricLew 0:d4e5ad7ad71c 127 RecordBufferOffset = BUFFER_OFFSET_NONE;
EricLew 0:d4e5ad7ad71c 128 transfer_range = (transfer_range+1) % 4;
EricLew 0:d4e5ad7ad71c 129 }
EricLew 0:d4e5ad7ad71c 130 }
EricLew 0:d4e5ad7ad71c 131
EricLew 0:d4e5ad7ad71c 132
EricLew 0:d4e5ad7ad71c 133
EricLew 0:d4e5ad7ad71c 134
EricLew 0:d4e5ad7ad71c 135
EricLew 0:d4e5ad7ad71c 136 /* Stop audio input */
EricLew 0:d4e5ad7ad71c 137 if (BSP_AUDIO_IN_Stop() != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 138 {
EricLew 0:d4e5ad7ad71c 139 Error_Handler();
EricLew 0:d4e5ad7ad71c 140 }
EricLew 0:d4e5ad7ad71c 141
EricLew 0:d4e5ad7ad71c 142 /* De-initialize audio input */
EricLew 0:d4e5ad7ad71c 143 if (BSP_AUDIO_IN_DeInit() != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 144 {
EricLew 0:d4e5ad7ad71c 145 Error_Handler();
EricLew 0:d4e5ad7ad71c 146 }
EricLew 0:d4e5ad7ad71c 147
EricLew 0:d4e5ad7ad71c 148 /* Turn OFF LED5: stop record */
EricLew 0:d4e5ad7ad71c 149 BSP_LED_Off(LED5);
EricLew 0:d4e5ad7ad71c 150
EricLew 0:d4e5ad7ad71c 151
EricLew 0:d4e5ad7ad71c 152 /* Reset AudioRecordExit flag */
EricLew 0:d4e5ad7ad71c 153 AudioRecordExit = 0;
EricLew 0:d4e5ad7ad71c 154
EricLew 0:d4e5ad7ad71c 155 /* Turn off green led */
EricLew 0:d4e5ad7ad71c 156 AudioDemo = AUDIO_DEMO_NONE;
EricLew 0:d4e5ad7ad71c 157 }
EricLew 0:d4e5ad7ad71c 158
EricLew 0:d4e5ad7ad71c 159 /**
EricLew 0:d4e5ad7ad71c 160 * @brief Display actual audio record sample rate on LCD
EricLew 0:d4e5ad7ad71c 161 * @param None
EricLew 0:d4e5ad7ad71c 162 * @retval None
EricLew 0:d4e5ad7ad71c 163 */
EricLew 0:d4e5ad7ad71c 164 static void SampleRateDisplay(uint8_t SampleRate)
EricLew 0:d4e5ad7ad71c 165 {
EricLew 0:d4e5ad7ad71c 166 /* Clear the LCD glass */
EricLew 0:d4e5ad7ad71c 167 BSP_LCD_GLASS_Clear();
EricLew 0:d4e5ad7ad71c 168
EricLew 0:d4e5ad7ad71c 169 /* Display actual audio record sample rate */
EricLew 0:d4e5ad7ad71c 170 switch (SamplesRates[SampleRate])
EricLew 0:d4e5ad7ad71c 171 {
EricLew 0:d4e5ad7ad71c 172 case BSP_AUDIO_FREQUENCY_48K:
EricLew 0:d4e5ad7ad71c 173 BSP_LCD_GLASS_DisplayString((uint8_t *)"48000");
EricLew 0:d4e5ad7ad71c 174 break;
EricLew 0:d4e5ad7ad71c 175 case BSP_AUDIO_FREQUENCY_44K:
EricLew 0:d4e5ad7ad71c 176 BSP_LCD_GLASS_DisplayString((uint8_t *)"44000");
EricLew 0:d4e5ad7ad71c 177 break;
EricLew 0:d4e5ad7ad71c 178 case BSP_AUDIO_FREQUENCY_32K:
EricLew 0:d4e5ad7ad71c 179 BSP_LCD_GLASS_DisplayString((uint8_t *)"32000");
EricLew 0:d4e5ad7ad71c 180 break;
EricLew 0:d4e5ad7ad71c 181 case BSP_AUDIO_FREQUENCY_22K:
EricLew 0:d4e5ad7ad71c 182 BSP_LCD_GLASS_DisplayString((uint8_t *)"22000");
EricLew 0:d4e5ad7ad71c 183 break;
EricLew 0:d4e5ad7ad71c 184 case BSP_AUDIO_FREQUENCY_16K:
EricLew 0:d4e5ad7ad71c 185 BSP_LCD_GLASS_DisplayString((uint8_t *)"16000");
EricLew 0:d4e5ad7ad71c 186 break;
EricLew 0:d4e5ad7ad71c 187 case BSP_AUDIO_FREQUENCY_11K:
EricLew 0:d4e5ad7ad71c 188 BSP_LCD_GLASS_DisplayString((uint8_t *)"11000");
EricLew 0:d4e5ad7ad71c 189 break;
EricLew 0:d4e5ad7ad71c 190 case BSP_AUDIO_FREQUENCY_8K:
EricLew 0:d4e5ad7ad71c 191 BSP_LCD_GLASS_DisplayString((uint8_t *)"8000");
EricLew 0:d4e5ad7ad71c 192 break;
EricLew 0:d4e5ad7ad71c 193 default:
EricLew 0:d4e5ad7ad71c 194 break;
EricLew 0:d4e5ad7ad71c 195 }
EricLew 0:d4e5ad7ad71c 196 }
EricLew 0:d4e5ad7ad71c 197
EricLew 0:d4e5ad7ad71c 198 /**
EricLew 0:d4e5ad7ad71c 199 * @brief Audio record sample rate selection
EricLew 0:d4e5ad7ad71c 200 * @param None
EricLew 0:d4e5ad7ad71c 201 * @retval None
EricLew 0:d4e5ad7ad71c 202 */
EricLew 0:d4e5ad7ad71c 203 void SampleRateSelection(void)
EricLew 0:d4e5ad7ad71c 204 {
EricLew 0:d4e5ad7ad71c 205 /* Display actual audio record sample rate */
EricLew 0:d4e5ad7ad71c 206 SampleRateDisplay(SampleRateIndex);
EricLew 0:d4e5ad7ad71c 207
EricLew 0:d4e5ad7ad71c 208 /* Select audio record sample rate */
EricLew 0:d4e5ad7ad71c 209 while (!AudioRecordSampleRateSelected)
EricLew 0:d4e5ad7ad71c 210 {
EricLew 0:d4e5ad7ad71c 211 if (AudioRecordSampleRateChange != 0)
EricLew 0:d4e5ad7ad71c 212 {
EricLew 0:d4e5ad7ad71c 213 SampleRateDisplay(SampleRateIndex);
EricLew 0:d4e5ad7ad71c 214 HAL_Delay(5);
EricLew 0:d4e5ad7ad71c 215 AudioRecordSampleRateChange = 0;
EricLew 0:d4e5ad7ad71c 216 }
EricLew 0:d4e5ad7ad71c 217 }
EricLew 0:d4e5ad7ad71c 218
EricLew 0:d4e5ad7ad71c 219 AudioRecordSampleRateSelected = 0;
EricLew 0:d4e5ad7ad71c 220 }
EricLew 0:d4e5ad7ad71c 221
EricLew 0:d4e5ad7ad71c 222 /**
EricLew 0:d4e5ad7ad71c 223 * @brief Callback function invoked when half of the PCM samples have been
EricLew 0:d4e5ad7ad71c 224 * DM Atransfered from the DFSDM channel.
EricLew 0:d4e5ad7ad71c 225 * @param None
EricLew 0:d4e5ad7ad71c 226 * @retval None
EricLew 0:d4e5ad7ad71c 227 */
EricLew 0:d4e5ad7ad71c 228 void AudioRecord_TransferComplete_CallBack(void)
EricLew 0:d4e5ad7ad71c 229 {
EricLew 0:d4e5ad7ad71c 230 /* Toggle green LED */
EricLew 0:d4e5ad7ad71c 231 BSP_LED_Toggle(LED5);
EricLew 0:d4e5ad7ad71c 232
EricLew 0:d4e5ad7ad71c 233 RecordBufferOffset = BUFFER_OFFSET_FULL;
EricLew 0:d4e5ad7ad71c 234 }
EricLew 0:d4e5ad7ad71c 235
EricLew 0:d4e5ad7ad71c 236 /**
EricLew 0:d4e5ad7ad71c 237 * @brief Callback function invoked when all the PCM samples have been
EricLew 0:d4e5ad7ad71c 238 * DMA transfered from the DFSDM channel.
EricLew 0:d4e5ad7ad71c 239 * @param None
EricLew 0:d4e5ad7ad71c 240 * @retval None
EricLew 0:d4e5ad7ad71c 241 */
EricLew 0:d4e5ad7ad71c 242 void AudioRecord_HalfTransfer_CallBack(void)
EricLew 0:d4e5ad7ad71c 243 {
EricLew 0:d4e5ad7ad71c 244 RecordBufferOffset = BUFFER_OFFSET_HALF;
EricLew 0:d4e5ad7ad71c 245 }
EricLew 0:d4e5ad7ad71c 246
EricLew 0:d4e5ad7ad71c 247 /**
EricLew 0:d4e5ad7ad71c 248 * @brief Callback function invoked when an error occured durint he DMA
EricLew 0:d4e5ad7ad71c 249 * transfer of the PCM samples from the DFSDM channel.
EricLew 0:d4e5ad7ad71c 250 * @param None
EricLew 0:d4e5ad7ad71c 251 * @retval None
EricLew 0:d4e5ad7ad71c 252 */
EricLew 0:d4e5ad7ad71c 253 void AudioRecord_Error_CallBack(void)
EricLew 0:d4e5ad7ad71c 254 {
EricLew 0:d4e5ad7ad71c 255 /* Stop the program with an infinite loop */
EricLew 0:d4e5ad7ad71c 256 Error_Handler();
EricLew 0:d4e5ad7ad71c 257 }
EricLew 0:d4e5ad7ad71c 258 /**
EricLew 0:d4e5ad7ad71c 259 * @}
EricLew 0:d4e5ad7ad71c 260 */
EricLew 0:d4e5ad7ad71c 261
EricLew 0:d4e5ad7ad71c 262
EricLew 0:d4e5ad7ad71c 263 /**
EricLew 0:d4e5ad7ad71c 264 * @}
EricLew 0:d4e5ad7ad71c 265 */
EricLew 0:d4e5ad7ad71c 266 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
EricLew 0:d4e5ad7ad71c 267