Sample program for audio recording and playback.

Dependencies:   mbed-os-lychee

Committer:
dkato
Date:
Thu Apr 19 09:29:26 2018 +0000
Revision:
0:61014bfdf244
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:61014bfdf244 1 #include "mbed.h"
dkato 0:61014bfdf244 2 #include "SdUsbConnect.h"
dkato 0:61014bfdf244 3 #include "AUDIO_GRBoard.h"
dkato 0:61014bfdf244 4
dkato 0:61014bfdf244 5 #define MOUNT_NAME "storage"
dkato 0:61014bfdf244 6 #define FINE_PATH "/"MOUNT_NAME"/wav_rec.wav"
dkato 0:61014bfdf244 7
dkato 0:61014bfdf244 8 #define SAMPLE_RATE (8000)
dkato 0:61014bfdf244 9 #define AUDIO_IN_BUF_SIZE (2048)
dkato 0:61014bfdf244 10 #define AUDIO_IN_BUF_NUM (16)
dkato 0:61014bfdf244 11 #define AUDIO_OUT_BUF_SIZE (2048)
dkato 0:61014bfdf244 12 #define AUDIO_OUT_BUF_NUM (8)
dkato 0:61014bfdf244 13 #define AUDIO_OUT_WAIT ((AUDIO_OUT_BUF_SIZE * AUDIO_OUT_BUF_NUM / 4) * 1000 / SAMPLE_RATE)
dkato 0:61014bfdf244 14
dkato 0:61014bfdf244 15 #define INFO_TYPE_OPEN (0)
dkato 0:61014bfdf244 16 #define INFO_TYPE_CLOSE (1)
dkato 0:61014bfdf244 17 #define INFO_TYPE_WRITE_DATA (2)
dkato 0:61014bfdf244 18
dkato 0:61014bfdf244 19 AUDIO_GRBoard audio(0x80, AUDIO_OUT_BUF_NUM - 1, AUDIO_IN_BUF_NUM); // I2S Codec
dkato 0:61014bfdf244 20 DigitalOut led_rec(LED_RED);
dkato 0:61014bfdf244 21 DigitalOut led_play(LED_GREEN);
dkato 0:61014bfdf244 22 InterruptIn button_0(USER_BUTTON0);
dkato 0:61014bfdf244 23 #if defined(TARGET_GR_LYCHEE)
dkato 0:61014bfdf244 24 InterruptIn button_1(USER_BUTTON1);
dkato 0:61014bfdf244 25 #endif
dkato 0:61014bfdf244 26 static bool play_req = false;
dkato 0:61014bfdf244 27
dkato 0:61014bfdf244 28 typedef struct {
dkato 0:61014bfdf244 29 uint32_t info_type;
dkato 0:61014bfdf244 30 void * p_data;
dkato 0:61014bfdf244 31 int32_t result;
dkato 0:61014bfdf244 32 } mail_t;
dkato 0:61014bfdf244 33 Mail<mail_t, (AUDIO_IN_BUF_NUM + 2)> mail_box;
dkato 0:61014bfdf244 34
dkato 0:61014bfdf244 35 static Thread audioInTask(osPriorityNormal, 1024 * 8);
dkato 0:61014bfdf244 36 //4 bytes aligned! No cache memory
dkato 0:61014bfdf244 37 #if defined(__ICCARM__)
dkato 0:61014bfdf244 38 #pragma data_alignment=4
dkato 0:61014bfdf244 39 static uint8_t audio_in_buf[AUDIO_IN_BUF_NUM][AUDIO_IN_BUF_SIZE]@ ".mirrorram";
dkato 0:61014bfdf244 40 #pragma data_alignment=4
dkato 0:61014bfdf244 41 static uint8_t audio_out_buf[AUDIO_OUT_BUF_NUM][AUDIO_OUT_BUF_SIZE]@ ".mirrorram";
dkato 0:61014bfdf244 42 #else
dkato 0:61014bfdf244 43 static uint8_t audio_in_buf[AUDIO_IN_BUF_NUM][AUDIO_IN_BUF_SIZE]__attribute((section("NC_BSS"),aligned(4)));
dkato 0:61014bfdf244 44 static uint8_t audio_out_buf[AUDIO_OUT_BUF_NUM][AUDIO_OUT_BUF_SIZE]__attribute((section("NC_BSS"),aligned(4)));
dkato 0:61014bfdf244 45 #endif
dkato 0:61014bfdf244 46
dkato 0:61014bfdf244 47 // wav file header
dkato 0:61014bfdf244 48 static const char wav_header_tbl[] = {
dkato 0:61014bfdf244 49 0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
dkato 0:61014bfdf244 50 0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x80,0xBB,0x00,0x00,0x00,0xEE,0x02,0x00,
dkato 0:61014bfdf244 51 0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00
dkato 0:61014bfdf244 52 };
dkato 0:61014bfdf244 53
dkato 0:61014bfdf244 54 #if MBED_CONF_APP_LCD
dkato 0:61014bfdf244 55 #include "EasyAttach_CameraAndLCD.h"
dkato 0:61014bfdf244 56
dkato 0:61014bfdf244 57 #define FRAME_BUFFER_STRIDE (((LCD_PIXEL_WIDTH * 2) + 31u) & ~31u)
dkato 0:61014bfdf244 58 #define FRAME_BUFFER_HEIGHT (LCD_PIXEL_HEIGHT)
dkato 0:61014bfdf244 59 #if defined(__ICCARM__)
dkato 0:61014bfdf244 60 #pragma data_alignment=32
dkato 0:61014bfdf244 61 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram";
dkato 0:61014bfdf244 62 #else
dkato 0:61014bfdf244 63 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32)));
dkato 0:61014bfdf244 64 #endif
dkato 0:61014bfdf244 65 DisplayBase Display;
dkato 0:61014bfdf244 66
dkato 0:61014bfdf244 67 static void Start_LCD_Display(void) {
dkato 0:61014bfdf244 68 DisplayBase::rect_t rect;
dkato 0:61014bfdf244 69
dkato 0:61014bfdf244 70 memset(user_frame_buffer0, 0xFF, sizeof(user_frame_buffer0));
dkato 0:61014bfdf244 71
dkato 0:61014bfdf244 72 rect.vs = 0;
dkato 0:61014bfdf244 73 rect.vw = LCD_PIXEL_HEIGHT;
dkato 0:61014bfdf244 74 rect.hs = 0;
dkato 0:61014bfdf244 75 rect.hw = LCD_PIXEL_WIDTH;
dkato 0:61014bfdf244 76 Display.Graphics_Read_Setting(
dkato 0:61014bfdf244 77 DisplayBase::GRAPHICS_LAYER_0,
dkato 0:61014bfdf244 78 (void *)user_frame_buffer0,
dkato 0:61014bfdf244 79 FRAME_BUFFER_STRIDE,
dkato 0:61014bfdf244 80 DisplayBase::GRAPHICS_FORMAT_RGB565,
dkato 0:61014bfdf244 81 DisplayBase::WR_RD_WRSWA_32_16BIT,
dkato 0:61014bfdf244 82 &rect
dkato 0:61014bfdf244 83 );
dkato 0:61014bfdf244 84 Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
dkato 0:61014bfdf244 85
dkato 0:61014bfdf244 86 Thread::wait(50);
dkato 0:61014bfdf244 87 EasyAttach_LcdBacklight(true);
dkato 0:61014bfdf244 88 }
dkato 0:61014bfdf244 89
dkato 0:61014bfdf244 90 static void disp_audio_wave(int16_t * p_data, int32_t size, uint32_t color) {
dkato 0:61014bfdf244 91 uint16_t * p_bottom_left_pos = (uint16_t *)&user_frame_buffer0[FRAME_BUFFER_STRIDE * (FRAME_BUFFER_HEIGHT - 1)];
dkato 0:61014bfdf244 92 uint16_t * p_frame_buf;
dkato 0:61014bfdf244 93 uint32_t x = 0;
dkato 0:61014bfdf244 94 uint32_t data_pos;
dkato 0:61014bfdf244 95 uint32_t data_pos_last = ((p_data[0] + 0x8000ul) >> 8) + 8;
dkato 0:61014bfdf244 96 int loop_num;
dkato 0:61014bfdf244 97
dkato 0:61014bfdf244 98 if (size < 0) {
dkato 0:61014bfdf244 99 return;
dkato 0:61014bfdf244 100 }
dkato 0:61014bfdf244 101
dkato 0:61014bfdf244 102 memset(user_frame_buffer0, 0xFF, sizeof(user_frame_buffer0));
dkato 0:61014bfdf244 103 for (int i = 0; i < size; i += 2) {
dkato 0:61014bfdf244 104 data_pos = ((p_data[i] + 0x8000ul) >> 8) + 8;
dkato 0:61014bfdf244 105 p_frame_buf = &p_bottom_left_pos[x];
dkato 0:61014bfdf244 106
dkato 0:61014bfdf244 107 if (data_pos == data_pos_last) {
dkato 0:61014bfdf244 108 loop_num = 3;
dkato 0:61014bfdf244 109 p_frame_buf -= ((data_pos - 1) * LCD_PIXEL_WIDTH);
dkato 0:61014bfdf244 110 } else if (data_pos > data_pos_last) {
dkato 0:61014bfdf244 111 loop_num = data_pos - data_pos_last + 2;
dkato 0:61014bfdf244 112 p_frame_buf -= (data_pos_last * LCD_PIXEL_WIDTH);
dkato 0:61014bfdf244 113 } else {
dkato 0:61014bfdf244 114 loop_num = data_pos_last - data_pos + 2;
dkato 0:61014bfdf244 115 p_frame_buf -= ((data_pos - 1) * LCD_PIXEL_WIDTH);
dkato 0:61014bfdf244 116 }
dkato 0:61014bfdf244 117
dkato 0:61014bfdf244 118 for (int j = 0; j < loop_num; j++) {
dkato 0:61014bfdf244 119 *p_frame_buf = color;
dkato 0:61014bfdf244 120 p_frame_buf -= LCD_PIXEL_WIDTH;
dkato 0:61014bfdf244 121 }
dkato 0:61014bfdf244 122 data_pos_last = data_pos;
dkato 0:61014bfdf244 123
dkato 0:61014bfdf244 124 x++;
dkato 0:61014bfdf244 125 if (x >= LCD_PIXEL_WIDTH) {
dkato 0:61014bfdf244 126 break;
dkato 0:61014bfdf244 127 }
dkato 0:61014bfdf244 128 }
dkato 0:61014bfdf244 129 }
dkato 0:61014bfdf244 130
dkato 0:61014bfdf244 131 static void callback_audio_write_end(void * p_data, int32_t result, void * p_app_data) {
dkato 0:61014bfdf244 132 disp_audio_wave((int16_t *)p_data, result / 2, 0x07E0); // Green
dkato 0:61014bfdf244 133 }
dkato 0:61014bfdf244 134 #endif // MBED_CONF_APP_LCD
dkato 0:61014bfdf244 135
dkato 0:61014bfdf244 136 static void send_mail(uint32_t info_type, void * p_data, int32_t result) {
dkato 0:61014bfdf244 137 mail_t *mail = mail_box.alloc();
dkato 0:61014bfdf244 138
dkato 0:61014bfdf244 139 if (mail != NULL) {
dkato 0:61014bfdf244 140 mail->info_type = info_type;
dkato 0:61014bfdf244 141 mail->p_data = p_data;
dkato 0:61014bfdf244 142 mail->result = result;
dkato 0:61014bfdf244 143 mail_box.put(mail);
dkato 0:61014bfdf244 144 }
dkato 0:61014bfdf244 145 }
dkato 0:61014bfdf244 146
dkato 0:61014bfdf244 147 static void rec_start(void) {
dkato 0:61014bfdf244 148 send_mail(INFO_TYPE_OPEN, NULL, 0);
dkato 0:61014bfdf244 149 }
dkato 0:61014bfdf244 150
dkato 0:61014bfdf244 151 static void rec_stop(void) {
dkato 0:61014bfdf244 152 send_mail(INFO_TYPE_CLOSE, NULL, 0);
dkato 0:61014bfdf244 153 }
dkato 0:61014bfdf244 154
dkato 0:61014bfdf244 155 static void play_start(void) {
dkato 0:61014bfdf244 156 play_req = true;
dkato 0:61014bfdf244 157 }
dkato 0:61014bfdf244 158
dkato 0:61014bfdf244 159 static void callback_audio_read_end(void * p_data, int32_t result, void * p_app_data) {
dkato 0:61014bfdf244 160 #if MBED_CONF_APP_LCD
dkato 0:61014bfdf244 161 if (led_play == 0) {
dkato 0:61014bfdf244 162 uint32_t color;
dkato 0:61014bfdf244 163
dkato 0:61014bfdf244 164 if (led_rec == 0) {
dkato 0:61014bfdf244 165 color = 0x001F; // Blue
dkato 0:61014bfdf244 166 } else {
dkato 0:61014bfdf244 167 color = 0xF800; // Red
dkato 0:61014bfdf244 168 }
dkato 0:61014bfdf244 169 disp_audio_wave((int16_t *)p_data, result / 2, color);
dkato 0:61014bfdf244 170 }
dkato 0:61014bfdf244 171 #endif
dkato 0:61014bfdf244 172 send_mail(INFO_TYPE_WRITE_DATA, p_data, result);
dkato 0:61014bfdf244 173 }
dkato 0:61014bfdf244 174
dkato 0:61014bfdf244 175 static void wire_data_4byte(uint32_t data, FILE * fp) {
dkato 0:61014bfdf244 176 char work_buf[4];
dkato 0:61014bfdf244 177
dkato 0:61014bfdf244 178 work_buf[0] = (uint8_t)(data >> 0);
dkato 0:61014bfdf244 179 work_buf[1] = (uint8_t)(data >> 8);
dkato 0:61014bfdf244 180 work_buf[2] = (uint8_t)(data >> 16);
dkato 0:61014bfdf244 181 work_buf[3] = (uint8_t)(data >> 24);
dkato 0:61014bfdf244 182 fwrite(work_buf, sizeof(char), 4, fp);
dkato 0:61014bfdf244 183 }
dkato 0:61014bfdf244 184
dkato 0:61014bfdf244 185 void audio_in_task(void) {
dkato 0:61014bfdf244 186 FILE * wav_fp = NULL;
dkato 0:61014bfdf244 187 uint32_t pcm_size = 0;
dkato 0:61014bfdf244 188 rbsp_data_conf_t audio_read_data = {&callback_audio_read_end, NULL};
dkato 0:61014bfdf244 189
dkato 0:61014bfdf244 190 // Read buffer setting
dkato 0:61014bfdf244 191 for (uint32_t i = 0; i < AUDIO_IN_BUF_NUM; i++) {
dkato 0:61014bfdf244 192 if (audio.read(audio_in_buf[i], AUDIO_IN_BUF_SIZE, &audio_read_data) < 0) {
dkato 0:61014bfdf244 193 printf("read error\n");
dkato 0:61014bfdf244 194 }
dkato 0:61014bfdf244 195 }
dkato 0:61014bfdf244 196
dkato 0:61014bfdf244 197 while (1) {
dkato 0:61014bfdf244 198 osEvent evt = mail_box.get();
dkato 0:61014bfdf244 199 if (evt.status == osEventMail) {
dkato 0:61014bfdf244 200 mail_t *mail = (mail_t *)evt.value.p;
dkato 0:61014bfdf244 201
dkato 0:61014bfdf244 202 switch (mail->info_type) {
dkato 0:61014bfdf244 203 case INFO_TYPE_OPEN:
dkato 0:61014bfdf244 204 wav_fp = fopen(FINE_PATH, "wb");
dkato 0:61014bfdf244 205 if (wav_fp != NULL) {
dkato 0:61014bfdf244 206 led_rec = 1; // REC start
dkato 0:61014bfdf244 207 pcm_size = 0;
dkato 0:61014bfdf244 208 fwrite(wav_header_tbl, sizeof(char), sizeof(wav_header_tbl), wav_fp);
dkato 0:61014bfdf244 209 }
dkato 0:61014bfdf244 210 break;
dkato 0:61014bfdf244 211
dkato 0:61014bfdf244 212 case INFO_TYPE_CLOSE:
dkato 0:61014bfdf244 213 if (wav_fp != NULL) {
dkato 0:61014bfdf244 214 // Set "RIFF" ChunkSize
dkato 0:61014bfdf244 215 fseek(wav_fp, 4, SEEK_SET);
dkato 0:61014bfdf244 216 wire_data_4byte(sizeof(wav_header_tbl) - 8 + pcm_size, wav_fp);
dkato 0:61014bfdf244 217 // Set SampleRate
dkato 0:61014bfdf244 218 fseek(wav_fp, 24, SEEK_SET);
dkato 0:61014bfdf244 219 wire_data_4byte(SAMPLE_RATE, wav_fp);
dkato 0:61014bfdf244 220 // Set ByteRate
dkato 0:61014bfdf244 221 wire_data_4byte(SAMPLE_RATE * 2 * 2, wav_fp);
dkato 0:61014bfdf244 222 // Set "data" ChunkSize
dkato 0:61014bfdf244 223 fseek(wav_fp, 40, SEEK_SET);
dkato 0:61014bfdf244 224 wire_data_4byte(pcm_size, wav_fp);
dkato 0:61014bfdf244 225 fclose(wav_fp);
dkato 0:61014bfdf244 226 wav_fp = NULL;
dkato 0:61014bfdf244 227 led_rec = 0; // REC end
dkato 0:61014bfdf244 228 #if !defined(TARGET_GR_LYCHEE)
dkato 0:61014bfdf244 229 play_start();
dkato 0:61014bfdf244 230 #endif
dkato 0:61014bfdf244 231 }
dkato 0:61014bfdf244 232 break;
dkato 0:61014bfdf244 233
dkato 0:61014bfdf244 234 case INFO_TYPE_WRITE_DATA:
dkato 0:61014bfdf244 235 if ((mail->result > 0) && (wav_fp != NULL)) {
dkato 0:61014bfdf244 236 pcm_size += mail->result;
dkato 0:61014bfdf244 237 fwrite(mail->p_data, sizeof(char), mail->result, wav_fp);
dkato 0:61014bfdf244 238 }
dkato 0:61014bfdf244 239 audio.read(mail->p_data, AUDIO_IN_BUF_SIZE, &audio_read_data); // Resetting read buffer
dkato 0:61014bfdf244 240 break;
dkato 0:61014bfdf244 241
dkato 0:61014bfdf244 242 default:
dkato 0:61014bfdf244 243 // do nothing
dkato 0:61014bfdf244 244 break;
dkato 0:61014bfdf244 245 }
dkato 0:61014bfdf244 246 mail_box.free(mail);
dkato 0:61014bfdf244 247 }
dkato 0:61014bfdf244 248 }
dkato 0:61014bfdf244 249 }
dkato 0:61014bfdf244 250
dkato 0:61014bfdf244 251 int main() {
dkato 0:61014bfdf244 252 #if MBED_CONF_APP_LCD
dkato 0:61014bfdf244 253 rbsp_data_conf_t audio_write_data = {&callback_audio_write_end, NULL};
dkato 0:61014bfdf244 254
dkato 0:61014bfdf244 255 EasyAttach_Init(Display);
dkato 0:61014bfdf244 256 Start_LCD_Display();
dkato 0:61014bfdf244 257 #else
dkato 0:61014bfdf244 258 rbsp_data_conf_t audio_write_data = {NULL, NULL};
dkato 0:61014bfdf244 259 #endif
dkato 0:61014bfdf244 260
dkato 0:61014bfdf244 261 // Microphone
dkato 0:61014bfdf244 262 audio.micVolume(0.50);
dkato 0:61014bfdf244 263 audio.outputVolume(0.50, 0.50);
dkato 0:61014bfdf244 264 audio.power(true);
dkato 0:61014bfdf244 265 audio.frequency(SAMPLE_RATE);
dkato 0:61014bfdf244 266
dkato 0:61014bfdf244 267 SdUsbConnect storage(MOUNT_NAME);
dkato 0:61014bfdf244 268 audioInTask.start(callback(audio_in_task));
dkato 0:61014bfdf244 269
dkato 0:61014bfdf244 270 // button setting
dkato 0:61014bfdf244 271 button_0.fall(&rec_start);
dkato 0:61014bfdf244 272 button_0.rise(&rec_stop);
dkato 0:61014bfdf244 273 #if defined(TARGET_GR_LYCHEE)
dkato 0:61014bfdf244 274 button_1.fall(&play_start);
dkato 0:61014bfdf244 275 #endif
dkato 0:61014bfdf244 276
dkato 0:61014bfdf244 277 while (1) {
dkato 0:61014bfdf244 278 storage.wait_connect();
dkato 0:61014bfdf244 279
dkato 0:61014bfdf244 280 // Audio playback
dkato 0:61014bfdf244 281 if (play_req != false) {
dkato 0:61014bfdf244 282 while (led_rec == 1) {
dkato 0:61014bfdf244 283 Thread::wait(10); // Wait write end
dkato 0:61014bfdf244 284 }
dkato 0:61014bfdf244 285
dkato 0:61014bfdf244 286 size_t read_size = AUDIO_OUT_BUF_SIZE;
dkato 0:61014bfdf244 287 uint32_t index = 0;
dkato 0:61014bfdf244 288
dkato 0:61014bfdf244 289 play_req = false;
dkato 0:61014bfdf244 290 led_play = 1;
dkato 0:61014bfdf244 291 FILE * fp_rb = fopen(FINE_PATH, "rb");
dkato 0:61014bfdf244 292 if (fp_rb != NULL) {
dkato 0:61014bfdf244 293 fseek(fp_rb, sizeof(wav_header_tbl), SEEK_SET);
dkato 0:61014bfdf244 294 while (read_size == AUDIO_OUT_BUF_SIZE) {
dkato 0:61014bfdf244 295 read_size = fread(audio_out_buf[index], sizeof(char), AUDIO_OUT_BUF_SIZE, fp_rb);
dkato 0:61014bfdf244 296 audio.write(audio_out_buf[index], read_size, &audio_write_data);
dkato 0:61014bfdf244 297 index++;
dkato 0:61014bfdf244 298 if (index >= AUDIO_OUT_BUF_NUM) {
dkato 0:61014bfdf244 299 index = 0;
dkato 0:61014bfdf244 300 }
dkato 0:61014bfdf244 301 }
dkato 0:61014bfdf244 302 fclose(fp_rb);
dkato 0:61014bfdf244 303 Thread::wait(AUDIO_OUT_WAIT);
dkato 0:61014bfdf244 304 }
dkato 0:61014bfdf244 305 led_play = 0;
dkato 0:61014bfdf244 306 }
dkato 0:61014bfdf244 307 Thread::wait(100);
dkato 0:61014bfdf244 308 }
dkato 0:61014bfdf244 309 }