audio_test_demo.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #include "test_demo.h"
  2. #include "ff_stdio.h"
  3. #include "board.h"
  4. #include "audio/audio.h"
  5. #include "romfile.h"
  6. #ifdef AUDIO_REPLAY
  7. #if REPLAY_TEST
  8. #define ROMFILE_ADUIO
  9. #define BUFSZ 4096
  10. struct RIFF_HEADER_DEF
  11. {
  12. char riff_id[4]; // 'R','I','F','F'
  13. uint32_t riff_size;
  14. char riff_format[4]; // 'W','A','V','E'
  15. };
  16. struct WAVE_FORMAT_DEF
  17. {
  18. uint16_t FormatTag;
  19. uint16_t Channels;
  20. uint32_t SamplesPerSec;
  21. uint32_t AvgBytesPerSec;
  22. uint16_t BlockAlign;
  23. uint16_t BitsPerSample;
  24. };
  25. struct FMT_BLOCK_DEF
  26. {
  27. char fmt_id[4]; // 'f','m','t',' '
  28. uint32_t fmt_size;
  29. struct WAVE_FORMAT_DEF wav_format;
  30. };
  31. struct DATA_BLOCK_DEF
  32. {
  33. char data_id[4]; // 'R','I','F','F'
  34. uint32_t data_size;
  35. };
  36. struct wav_info
  37. {
  38. struct RIFF_HEADER_DEF header;
  39. struct FMT_BLOCK_DEF fmt_block;
  40. struct DATA_BLOCK_DEF data_block;
  41. };
  42. /* Parse wav file header info */
  43. static int wavplay_parse_header(void *file, struct wav_info *info)
  44. {
  45. int max_sub_chunk = 8;
  46. #ifdef ROMFILE_ADUIO
  47. if (RomFileRead((RomFile *)file, &(info->header), sizeof(struct RIFF_HEADER_DEF)) <= 0)
  48. goto __exit;
  49. /* seek to fmt sub-chunk(Drop other sub-chunk in front of fmt chunk) */
  50. while(1)
  51. {
  52. if (RomFileRead((RomFile *)file, &(info->fmt_block), sizeof(struct FMT_BLOCK_DEF)) <= 0)
  53. goto __exit;
  54. if(memcmp(info->fmt_block.fmt_id, "fmt ", 4) == 0)
  55. break; /* "fmt " sub-chunk fond */
  56. /* sub-chunk "fmt " not fond, seek to the next sub-chunk */
  57. RomFileSeek((RomFile *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), SEEK_CUR);
  58. /* timeout */
  59. if(max_sub_chunk-- <= 0)
  60. goto __exit;
  61. };
  62. if (info->fmt_block.fmt_size > sizeof(struct WAVE_FORMAT_DEF))
  63. RomFileSeek((RomFile *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), SEEK_CUR);
  64. if (RomFileRead((RomFile *)file, &(info->data_block), sizeof(struct DATA_BLOCK_DEF)) <= 0)
  65. goto __exit;
  66. #else
  67. if (ff_fread(&(info->header), sizeof(struct RIFF_HEADER_DEF), 1, (FF_FILE *)file) <= 0)
  68. goto __exit;
  69. /* seek to fmt sub-chunk(Drop other sub-chunk in front of fmt chunk) */
  70. while(1)
  71. {
  72. if (ff_fread(&(info->fmt_block), sizeof(struct FMT_BLOCK_DEF), 1, (FF_FILE *)file) <= 0)
  73. goto __exit;
  74. if(memcmp(info->fmt_block.fmt_id, "fmt ", 4) == 0)
  75. break; // "fmt " sub-chunk fond.
  76. /* sub-chunk "fmt " not fond, seek to the next sub-chunk */
  77. ff_fseek((FF_FILE *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), FF_SEEK_CUR);
  78. /* timeout */
  79. if(max_sub_chunk-- <= 0)
  80. goto __exit;
  81. };
  82. if (info->fmt_block.fmt_size > sizeof(struct WAVE_FORMAT_DEF))
  83. ff_fseek((FF_FILE *)file, info->fmt_block.fmt_size - sizeof(struct WAVE_FORMAT_DEF), FF_SEEK_CUR);
  84. if (ff_fread(&(info->data_block), sizeof(struct DATA_BLOCK_DEF), 1, (FF_FILE *)file) <= 0)
  85. goto __exit;
  86. #endif
  87. return 0;
  88. __exit:
  89. printf("%s fail.\n", __func__);
  90. return -1;
  91. }
  92. static void wavplay_thread(void *para)
  93. {
  94. #ifdef ROMFILE_ADUIO
  95. RomFile *file = NULL;
  96. #else
  97. FF_FILE *file = NULL;
  98. #endif
  99. uint8_t *buffer = NULL;
  100. struct wav_info *info = NULL;
  101. struct audio_caps caps = {0};
  102. struct audio_device *audio;
  103. int data_size;
  104. #ifdef ROMFILE_ADUIO
  105. file = RomFileOpen("audio/sin1K.wav");
  106. #else
  107. file = ff_fopen("/sd/sin1K.wav", "rb");
  108. #endif
  109. if (!file)
  110. {
  111. printf("open file failed!\n");
  112. goto __exit;
  113. }
  114. buffer = pvPortMalloc(BUFSZ);
  115. if (buffer == NULL)
  116. goto __exit;
  117. info = (struct wav_info *) pvPortMalloc(sizeof(*info));
  118. if (info == NULL)
  119. goto __exit;
  120. if(wavplay_parse_header((void *)file, info) < 0)
  121. goto __exit;
  122. printf("wav information:\n");
  123. printf("samplerate %d\n", info->fmt_block.wav_format.SamplesPerSec);
  124. printf("channel %d\n", info->fmt_block.wav_format.Channels);
  125. audio = audio_dev_open(AUDIO_REPLAY_I2S, AUDIO_FLAG_REPLAY);
  126. if (!audio)
  127. {
  128. printf("Open audio device fail.\n");
  129. goto __exit;
  130. }
  131. caps.main_type = AUDIO_TYPE_OUTPUT; /* 输出类型(播放设备 )*/
  132. caps.sub_type = AUDIO_DSP_PARAM; /* 设置所有音频参数信息 */
  133. caps.udata.config.samplerate = info->fmt_block.wav_format.SamplesPerSec; /* 采样率 */
  134. caps.udata.config.channels = info->fmt_block.wav_format.Channels; /* 采样通道 */
  135. caps.udata.config.samplebits = 16; /* 采样位数 */
  136. audio_dev_configure(audio, &caps);
  137. data_size = info->data_block.data_size;
  138. while (data_size > 0)
  139. {
  140. int length;
  141. /* 从文件系统读取 wav 文件的音频数据 */
  142. #ifdef ROMFILE_ADUIO
  143. length = RomFileRead(file, buffer, BUFSZ);
  144. #else
  145. length = ff_fread(buffer, 1, BUFSZ, file);
  146. #endif
  147. if(length > data_size)
  148. length = data_size;
  149. if (length <= 0)
  150. break;
  151. audio_dev_write(audio, buffer, length);
  152. data_size -= length;
  153. }
  154. audio_dev_close(audio, AUDIO_FLAG_REPLAY);
  155. __exit:
  156. if(file)
  157. #ifdef ROMFILE_ADUIO
  158. RomFileClose(file);
  159. #else
  160. ff_fclose(file);
  161. #endif
  162. if(buffer)
  163. vPortFree(buffer);
  164. if (info)
  165. vPortFree(info);
  166. while(1)
  167. vTaskDelay(portMAX_DELAY);
  168. }
  169. void wavplay_demo(void)
  170. {
  171. if (xTaskCreate(wavplay_thread, "wavplay", configMINIMAL_STACK_SIZE*10, NULL,
  172. configMAX_PRIORITIES - 3, NULL) != pdPASS) {
  173. printf("create wavplay task fail.\n");
  174. }
  175. }
  176. #endif
  177. #endif
  178. #ifdef AUDIO_RECORD
  179. #if RECORD_TEST
  180. #define RECORD_BUF_SIZE 1024*1024
  181. #define RECORD_REQ_SIZE 1024
  182. static uint8_t *wavrecord_buffer = NULL;
  183. static uint8_t *waverecord_get_a_new_buffer(int size)
  184. {
  185. static int waverecord_index = 0;
  186. uint8_t *buffer = NULL;
  187. if(!wavrecord_buffer)
  188. {
  189. wavrecord_buffer = pvPortMalloc(RECORD_BUF_SIZE);
  190. if(!wavrecord_buffer)
  191. return NULL;
  192. waverecord_index = 0;
  193. }
  194. if(waverecord_index + size < RECORD_BUF_SIZE)
  195. {
  196. buffer = wavrecord_buffer + waverecord_index;
  197. waverecord_index += size;
  198. }
  199. else
  200. {
  201. printf("record done, start_addr:0x%x, size:0x%x\n", (uint32_t)wavrecord_buffer, RECORD_BUF_SIZE);
  202. //CP15_clean_dcache_for_dma((uint32_t)wavrecord_buffer, (uint32_t)wavrecord_buffer + RECORD_BUF_SIZE);
  203. buffer = wavrecord_buffer;
  204. waverecord_index = 0;
  205. }
  206. return buffer;
  207. }
  208. static int wavrecord_callback(struct audio_device *audio)
  209. {
  210. int ret = -1;
  211. /* save record data */
  212. if(audio && audio->record)
  213. {
  214. int size = audio->record->buf_info.total_size;
  215. if(size == RECORD_REQ_SIZE)
  216. {
  217. uint8_t *buffer = waverecord_get_a_new_buffer(size);
  218. if(buffer)
  219. {
  220. /* clear buffer */
  221. //memset(buffer, 0, size);
  222. #if 1 /* method 1: use dynamic buffer to receive record data(without copy data). [Recommend this method] */
  223. audio_dev_record_set_param(audio, buffer, size); //Set a new buffer to receive the next frame.
  224. #else /* method 2: use one buffer to receive record data(should copy data) */
  225. if(audio->record->buf_info.buffer)
  226. memcpy(buffer, audio->record->buf_info.buffer, size); //Copy the record data to a destnation buffer.
  227. #endif
  228. ret = 0;
  229. }
  230. }
  231. else
  232. {
  233. printf("%s() Invalid size:%d\n", __func__, size);
  234. }
  235. }
  236. return ret;
  237. }
  238. static void wavrecord_thread(void *para)
  239. {
  240. uint8_t *buffer = NULL;
  241. struct audio_device *audio;
  242. int ret;
  243. audio = audio_dev_open(AUDIO_RECORD_I2S, AUDIO_FLAG_RECORD);
  244. if(audio)
  245. {
  246. /* set record sample information */
  247. struct audio_caps caps = {0};
  248. caps.main_type = AUDIO_TYPE_INPUT; /* 输入类型(录音设备 )*/
  249. caps.sub_type = AUDIO_DSP_PARAM; /* 设置所有音频参数信息 */
  250. caps.udata.config.samplerate = 16000; /* 采样率 */
  251. caps.udata.config.channels = 2; /* 采样通道 */
  252. caps.udata.config.samplebits = 16; /* 采样位数 */
  253. audio_dev_configure(audio, &caps);
  254. /* register record complete callback */
  255. audio_dev_register_record_callback(audio, wavrecord_callback);
  256. /* set record buffer and size */
  257. buffer = waverecord_get_a_new_buffer(RECORD_REQ_SIZE);
  258. ret = audio_dev_record_set_param(audio, buffer, RECORD_REQ_SIZE);
  259. if(ret)
  260. {
  261. printf("%s() audio_dev_record_set_param failed \n", __func__);
  262. goto exit;
  263. }
  264. /* start recording */
  265. audio_dev_record_start(audio);
  266. printf("wav record information:\n");
  267. printf("samplerate %d\n", caps.udata.config.samplerate);
  268. printf("channel %d\n", caps.udata.config.channels);
  269. printf("samplebits %d\n", caps.udata.config.samplebits);
  270. }
  271. while(1)
  272. vTaskDelay(portMAX_DELAY);
  273. exit:
  274. if(audio)
  275. {
  276. /* stop record */
  277. audio_dev_record_stop(audio);
  278. /* 关闭 Audio 设备 */
  279. audio_dev_close(audio, AUDIO_FLAG_REPLAY);
  280. }
  281. if (wavrecord_buffer)
  282. vPortFree(wavrecord_buffer);
  283. }
  284. void wavrecord_demo(void)
  285. {
  286. if (xTaskCreate(wavrecord_thread, "wavrecord", configMINIMAL_STACK_SIZE, NULL,
  287. configMAX_PRIORITIES - 3, NULL) != pdPASS) {
  288. printf("create waverecord task fail.\n");
  289. }
  290. }
  291. #endif
  292. #endif