audio_test_demo.c 9.3 KB

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