Daiki Kato
/
GR-Boards_Audio_Recoder
Sample program for audio recording and playback.
Revision 0:61014bfdf244, committed 2018-04-19
- Comitter:
- dkato
- Date:
- Thu Apr 19 09:29:26 2018 +0000
- Commit message:
- first commit
Changed in this revision
diff -r 000000000000 -r 61014bfdf244 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Apr 19 09:29:26 2018 +0000 @@ -0,0 +1,309 @@ +#include "mbed.h" +#include "SdUsbConnect.h" +#include "AUDIO_GRBoard.h" + +#define MOUNT_NAME "storage" +#define FINE_PATH "/"MOUNT_NAME"/wav_rec.wav" + +#define SAMPLE_RATE (8000) +#define AUDIO_IN_BUF_SIZE (2048) +#define AUDIO_IN_BUF_NUM (16) +#define AUDIO_OUT_BUF_SIZE (2048) +#define AUDIO_OUT_BUF_NUM (8) +#define AUDIO_OUT_WAIT ((AUDIO_OUT_BUF_SIZE * AUDIO_OUT_BUF_NUM / 4) * 1000 / SAMPLE_RATE) + +#define INFO_TYPE_OPEN (0) +#define INFO_TYPE_CLOSE (1) +#define INFO_TYPE_WRITE_DATA (2) + +AUDIO_GRBoard audio(0x80, AUDIO_OUT_BUF_NUM - 1, AUDIO_IN_BUF_NUM); // I2S Codec +DigitalOut led_rec(LED_RED); +DigitalOut led_play(LED_GREEN); +InterruptIn button_0(USER_BUTTON0); +#if defined(TARGET_GR_LYCHEE) +InterruptIn button_1(USER_BUTTON1); +#endif +static bool play_req = false; + +typedef struct { + uint32_t info_type; + void * p_data; + int32_t result; +} mail_t; +Mail<mail_t, (AUDIO_IN_BUF_NUM + 2)> mail_box; + +static Thread audioInTask(osPriorityNormal, 1024 * 8); +//4 bytes aligned! No cache memory +#if defined(__ICCARM__) +#pragma data_alignment=4 +static uint8_t audio_in_buf[AUDIO_IN_BUF_NUM][AUDIO_IN_BUF_SIZE]@ ".mirrorram"; +#pragma data_alignment=4 +static uint8_t audio_out_buf[AUDIO_OUT_BUF_NUM][AUDIO_OUT_BUF_SIZE]@ ".mirrorram"; +#else +static uint8_t audio_in_buf[AUDIO_IN_BUF_NUM][AUDIO_IN_BUF_SIZE]__attribute((section("NC_BSS"),aligned(4))); +static uint8_t audio_out_buf[AUDIO_OUT_BUF_NUM][AUDIO_OUT_BUF_SIZE]__attribute((section("NC_BSS"),aligned(4))); +#endif + +// wav file header +static const char wav_header_tbl[] = { + 0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20, + 0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x80,0xBB,0x00,0x00,0x00,0xEE,0x02,0x00, + 0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00 +}; + +#if MBED_CONF_APP_LCD +#include "EasyAttach_CameraAndLCD.h" + +#define FRAME_BUFFER_STRIDE (((LCD_PIXEL_WIDTH * 2) + 31u) & ~31u) +#define FRAME_BUFFER_HEIGHT (LCD_PIXEL_HEIGHT) +#if defined(__ICCARM__) +#pragma data_alignment=32 +static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram"; +#else +static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32))); +#endif +DisplayBase Display; + +static void Start_LCD_Display(void) { + DisplayBase::rect_t rect; + + memset(user_frame_buffer0, 0xFF, sizeof(user_frame_buffer0)); + + rect.vs = 0; + rect.vw = LCD_PIXEL_HEIGHT; + rect.hs = 0; + rect.hw = LCD_PIXEL_WIDTH; + Display.Graphics_Read_Setting( + DisplayBase::GRAPHICS_LAYER_0, + (void *)user_frame_buffer0, + FRAME_BUFFER_STRIDE, + DisplayBase::GRAPHICS_FORMAT_RGB565, + DisplayBase::WR_RD_WRSWA_32_16BIT, + &rect + ); + Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0); + + Thread::wait(50); + EasyAttach_LcdBacklight(true); +} + +static void disp_audio_wave(int16_t * p_data, int32_t size, uint32_t color) { + uint16_t * p_bottom_left_pos = (uint16_t *)&user_frame_buffer0[FRAME_BUFFER_STRIDE * (FRAME_BUFFER_HEIGHT - 1)]; + uint16_t * p_frame_buf; + uint32_t x = 0; + uint32_t data_pos; + uint32_t data_pos_last = ((p_data[0] + 0x8000ul) >> 8) + 8; + int loop_num; + + if (size < 0) { + return; + } + + memset(user_frame_buffer0, 0xFF, sizeof(user_frame_buffer0)); + for (int i = 0; i < size; i += 2) { + data_pos = ((p_data[i] + 0x8000ul) >> 8) + 8; + p_frame_buf = &p_bottom_left_pos[x]; + + if (data_pos == data_pos_last) { + loop_num = 3; + p_frame_buf -= ((data_pos - 1) * LCD_PIXEL_WIDTH); + } else if (data_pos > data_pos_last) { + loop_num = data_pos - data_pos_last + 2; + p_frame_buf -= (data_pos_last * LCD_PIXEL_WIDTH); + } else { + loop_num = data_pos_last - data_pos + 2; + p_frame_buf -= ((data_pos - 1) * LCD_PIXEL_WIDTH); + } + + for (int j = 0; j < loop_num; j++) { + *p_frame_buf = color; + p_frame_buf -= LCD_PIXEL_WIDTH; + } + data_pos_last = data_pos; + + x++; + if (x >= LCD_PIXEL_WIDTH) { + break; + } + } +} + +static void callback_audio_write_end(void * p_data, int32_t result, void * p_app_data) { + disp_audio_wave((int16_t *)p_data, result / 2, 0x07E0); // Green +} +#endif // MBED_CONF_APP_LCD + +static void send_mail(uint32_t info_type, void * p_data, int32_t result) { + mail_t *mail = mail_box.alloc(); + + if (mail != NULL) { + mail->info_type = info_type; + mail->p_data = p_data; + mail->result = result; + mail_box.put(mail); + } +} + +static void rec_start(void) { + send_mail(INFO_TYPE_OPEN, NULL, 0); +} + +static void rec_stop(void) { + send_mail(INFO_TYPE_CLOSE, NULL, 0); +} + +static void play_start(void) { + play_req = true; +} + +static void callback_audio_read_end(void * p_data, int32_t result, void * p_app_data) { +#if MBED_CONF_APP_LCD + if (led_play == 0) { + uint32_t color; + + if (led_rec == 0) { + color = 0x001F; // Blue + } else { + color = 0xF800; // Red + } + disp_audio_wave((int16_t *)p_data, result / 2, color); + } +#endif + send_mail(INFO_TYPE_WRITE_DATA, p_data, result); +} + +static void wire_data_4byte(uint32_t data, FILE * fp) { + char work_buf[4]; + + work_buf[0] = (uint8_t)(data >> 0); + work_buf[1] = (uint8_t)(data >> 8); + work_buf[2] = (uint8_t)(data >> 16); + work_buf[3] = (uint8_t)(data >> 24); + fwrite(work_buf, sizeof(char), 4, fp); +} + +void audio_in_task(void) { + FILE * wav_fp = NULL; + uint32_t pcm_size = 0; + rbsp_data_conf_t audio_read_data = {&callback_audio_read_end, NULL}; + + // Read buffer setting + for (uint32_t i = 0; i < AUDIO_IN_BUF_NUM; i++) { + if (audio.read(audio_in_buf[i], AUDIO_IN_BUF_SIZE, &audio_read_data) < 0) { + printf("read error\n"); + } + } + + while (1) { + osEvent evt = mail_box.get(); + if (evt.status == osEventMail) { + mail_t *mail = (mail_t *)evt.value.p; + + switch (mail->info_type) { + case INFO_TYPE_OPEN: + wav_fp = fopen(FINE_PATH, "wb"); + if (wav_fp != NULL) { + led_rec = 1; // REC start + pcm_size = 0; + fwrite(wav_header_tbl, sizeof(char), sizeof(wav_header_tbl), wav_fp); + } + break; + + case INFO_TYPE_CLOSE: + if (wav_fp != NULL) { + // Set "RIFF" ChunkSize + fseek(wav_fp, 4, SEEK_SET); + wire_data_4byte(sizeof(wav_header_tbl) - 8 + pcm_size, wav_fp); + // Set SampleRate + fseek(wav_fp, 24, SEEK_SET); + wire_data_4byte(SAMPLE_RATE, wav_fp); + // Set ByteRate + wire_data_4byte(SAMPLE_RATE * 2 * 2, wav_fp); + // Set "data" ChunkSize + fseek(wav_fp, 40, SEEK_SET); + wire_data_4byte(pcm_size, wav_fp); + fclose(wav_fp); + wav_fp = NULL; + led_rec = 0; // REC end +#if !defined(TARGET_GR_LYCHEE) + play_start(); +#endif + } + break; + + case INFO_TYPE_WRITE_DATA: + if ((mail->result > 0) && (wav_fp != NULL)) { + pcm_size += mail->result; + fwrite(mail->p_data, sizeof(char), mail->result, wav_fp); + } + audio.read(mail->p_data, AUDIO_IN_BUF_SIZE, &audio_read_data); // Resetting read buffer + break; + + default: + // do nothing + break; + } + mail_box.free(mail); + } + } +} + +int main() { +#if MBED_CONF_APP_LCD + rbsp_data_conf_t audio_write_data = {&callback_audio_write_end, NULL}; + + EasyAttach_Init(Display); + Start_LCD_Display(); +#else + rbsp_data_conf_t audio_write_data = {NULL, NULL}; +#endif + + // Microphone + audio.micVolume(0.50); + audio.outputVolume(0.50, 0.50); + audio.power(true); + audio.frequency(SAMPLE_RATE); + + SdUsbConnect storage(MOUNT_NAME); + audioInTask.start(callback(audio_in_task)); + + // button setting + button_0.fall(&rec_start); + button_0.rise(&rec_stop); +#if defined(TARGET_GR_LYCHEE) + button_1.fall(&play_start); +#endif + + while (1) { + storage.wait_connect(); + + // Audio playback + if (play_req != false) { + while (led_rec == 1) { + Thread::wait(10); // Wait write end + } + + size_t read_size = AUDIO_OUT_BUF_SIZE; + uint32_t index = 0; + + play_req = false; + led_play = 1; + FILE * fp_rb = fopen(FINE_PATH, "rb"); + if (fp_rb != NULL) { + fseek(fp_rb, sizeof(wav_header_tbl), SEEK_SET); + while (read_size == AUDIO_OUT_BUF_SIZE) { + read_size = fread(audio_out_buf[index], sizeof(char), AUDIO_OUT_BUF_SIZE, fp_rb); + audio.write(audio_out_buf[index], read_size, &audio_write_data); + index++; + if (index >= AUDIO_OUT_BUF_NUM) { + index = 0; + } + } + fclose(fp_rb); + Thread::wait(AUDIO_OUT_WAIT); + } + led_play = 0; + } + Thread::wait(100); + } +}
diff -r 000000000000 -r 61014bfdf244 mbed-gr-libs.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-gr-libs.lib Thu Apr 19 09:29:26 2018 +0000 @@ -0,0 +1,1 @@ +https://github.com/d-kato/mbed-gr-libs/#ab3c9adbc449c4ac541ca38ebee8dd7a4f87ddb8
diff -r 000000000000 -r 61014bfdf244 mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Thu Apr 19 09:29:26 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/dkato/code/mbed-os-lychee/#f782d9c66c49
diff -r 000000000000 -r 61014bfdf244 mbed_app.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed_app.json Thu Apr 19 09:29:26 2018 +0000 @@ -0,0 +1,20 @@ +{ + "config": { + "camera":{ + "help": "0:disable 1:enable", + "value": "0" + }, + "lcd":{ + "help": "0:disable 1:enable", + "value": "1" + }, + "usb-host-ch":{ + "help": "(for GR-PEACH) 0:ch0 1:ch1", + "value": "1" + }, + "audio-camera-shield":{ + "help": "(for GR-PEACH) 0:not use 1:use", + "value": "1" + } + } +}