aplay.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /*
  2. * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
  3. *
  4. * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
  5. * the the people's Republic of China and other countries.
  6. * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
  7. *
  8. * DISCLAIMER
  9. * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
  10. * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
  11. * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
  12. * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
  13. * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
  14. * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
  15. * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
  16. *
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
  19. * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
  20. * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
  21. * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
  22. * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  23. * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  28. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  30. * OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <unistd.h>
  36. #include <errno.h>
  37. #include <unistd.h>
  38. #include <fcntl.h>
  39. #include <hal_cmd.h>
  40. #include <aw-alsa-lib/pcm.h>
  41. #include <hal_timer.h>
  42. #include "common.h"
  43. #include "wav_parser.h"
  44. #include "audio_wav/audio_wav.h"
  45. static unsigned int g_playback_loop_enable = 0;
  46. static char *g_pcm_name;
  47. static char *g_hpcm_name;
  48. extern unsigned int g_verbose;
  49. #if 0
  50. static int fs_read(int fd, void *buf, size_t count)
  51. {
  52. ssize_t result = 0, res;
  53. while (count > 0) {
  54. if ((res = read(fd, buf, count)) == 0)
  55. break;
  56. if (res < 0)
  57. return result > 0 ? result : res;
  58. count -= res;
  59. result += res;
  60. buf = (char *)buf + res;
  61. }
  62. return result;
  63. }
  64. #endif
  65. static int pcm_write(snd_pcm_t *handle, char *data, snd_pcm_uframes_t frames_total, unsigned int frame_bytes)
  66. {
  67. int ret = 0;
  68. snd_pcm_sframes_t size;
  69. snd_pcm_uframes_t frames_loop = 400;
  70. snd_pcm_uframes_t frames_count = 0;
  71. snd_pcm_uframes_t frames = 0;
  72. while (1) {
  73. if ((frames_total - frames_count) < frames_loop)
  74. frames = frames_total - frames_count;
  75. if (frames == 0)
  76. frames = frames_loop;
  77. /*hal_usleep(500000);*/
  78. size = snd_pcm_writei(handle, data, frames);
  79. if (size != frames) {
  80. printf("snd_pcm_writei return %ld\n", size);
  81. }
  82. if (size == -EAGAIN) {
  83. hal_usleep(10000);
  84. continue;
  85. } else if (size == -EPIPE) {
  86. xrun(handle);
  87. continue;
  88. } else if (size == -ESTRPIPE) {
  89. continue;
  90. } else if (size < 0) {
  91. printf("-----snd_pcm_writei failed!!, return %ld\n", size);
  92. return size;
  93. }
  94. data += (size * frame_bytes);
  95. frames_count += size;
  96. frames -= size;
  97. if (frames_total == frames_count)
  98. break;
  99. /*printf("frames_count = %ld, frames_total = %ld\n", frames_count, frames_total);*/
  100. }
  101. return frames_count;
  102. }
  103. /*
  104. * arg0: aplay
  105. * arg1: card
  106. * arg2: format
  107. * arg3: rate
  108. * arg4: channels
  109. * arg5: data
  110. * arg6: len
  111. */
  112. int aplay(const char *card_name, snd_pcm_format_t format, unsigned int rate,
  113. unsigned int channels, const char *data, unsigned int datalen)
  114. {
  115. int ret = 0;
  116. snd_pcm_t *handle;
  117. int mode = 0;
  118. snd_pcm_uframes_t period_frames = 1024, buffer_frames = 4096;
  119. printf("dump args:\n");
  120. printf("card: %s\n", card_name);
  121. printf("format: %u\n", format);
  122. printf("rate: %u\n", rate);
  123. printf("channels: %u\n", channels);
  124. printf("data: %p\n", data);
  125. printf("datalen: %u\n", datalen);
  126. printf("period_size: %lu\n", period_frames);
  127. printf("buffer_size: %lu\n", buffer_frames);
  128. /* open card */
  129. ret = snd_pcm_open(&handle, card_name, SND_PCM_STREAM_PLAYBACK, mode);
  130. if (ret < 0) {
  131. printf("audio open error:%d\n", ret);
  132. return -1;
  133. }
  134. ret = set_param(handle, format, rate, channels, period_frames, buffer_frames);
  135. if (ret < 0)
  136. goto err1;
  137. ret = pcm_write(handle, (char *)data,
  138. snd_pcm_bytes_to_frames(handle, datalen),
  139. snd_pcm_frames_to_bytes(handle, 1));
  140. if (ret < 0) {
  141. printf("pcm_write error:%d\n", ret);
  142. goto err1;
  143. }
  144. ret = snd_pcm_drain(handle);
  145. /*ret = snd_pcm_drop(handle);*/
  146. if (ret < 0)
  147. printf("stop failed!, return %d\n", ret);
  148. err1:
  149. /* close card */
  150. ret = snd_pcm_close(handle);
  151. if (ret < 0) {
  152. printf("audio close error:%d\n", ret);
  153. return ret;
  154. }
  155. return 0;
  156. }
  157. static int play_builtin_music(audio_mgr_t *mgr, const char *name)
  158. {
  159. int ret = 0;
  160. wav_hw_params_t hwparams = {16000, SND_PCM_FORMAT_UNKNOWN, 2};
  161. wav_file_t *wav_file = NULL;
  162. wav_header_t *wav_header = NULL;
  163. audio_mgr_t *audio_hpcm_mgr = NULL;
  164. if (name)
  165. wav_file = find_builtin_wav_file(name);
  166. else
  167. wav_file = find_builtin_wav_file(NULL);
  168. if (!wav_file) {
  169. printf("can't find wav file\n");
  170. return -1;
  171. }
  172. wav_header = (wav_header_t *)wav_file->start;
  173. if (check_wav_header(wav_header, &hwparams) != 0) {
  174. printf("check wav header failed\n");
  175. return -1;
  176. }
  177. mgr->format = hwparams.format;
  178. mgr->rate = hwparams.rate;
  179. mgr->channels = hwparams.channels;
  180. /* open card */
  181. ret = snd_pcm_open(&mgr->handle, g_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
  182. if (ret < 0) {
  183. printf("audio open error:%d\n", ret);
  184. return -1;
  185. }
  186. ret = set_param(mgr->handle, mgr->format, mgr->rate, mgr->channels,
  187. mgr->period_size, mgr->buffer_size);
  188. if (ret < 0) {
  189. printf("audio set param error:%d\n", ret);
  190. goto err_set_pcm_param;
  191. }
  192. if (g_hpcm_name) {
  193. audio_hpcm_mgr = audio_mgr_create();
  194. if (!audio_hpcm_mgr) {
  195. printf("audio hpcm create manager failed.\n");
  196. goto err_hpcm_create_mgr;
  197. }
  198. /* open card */
  199. ret = snd_pcm_open(&audio_hpcm_mgr->handle, g_hpcm_name,
  200. SND_PCM_STREAM_PLAYBACK, 0);
  201. if (ret < 0) {
  202. printf("audio open error:%d\n", ret);
  203. goto err_pcm_open_hpcm;
  204. }
  205. audio_hpcm_mgr->format = hwparams.format;
  206. audio_hpcm_mgr->rate = hwparams.rate;
  207. audio_hpcm_mgr->channels = hwparams.channels;
  208. audio_hpcm_mgr->period_size = mgr->period_size;
  209. audio_hpcm_mgr->buffer_size = mgr->buffer_size;
  210. ret = set_param(audio_hpcm_mgr->handle,
  211. audio_hpcm_mgr->format,
  212. audio_hpcm_mgr->rate,
  213. audio_hpcm_mgr->channels,
  214. audio_hpcm_mgr->period_size,
  215. audio_hpcm_mgr->buffer_size);
  216. if (ret < 0) {
  217. printf("audio set pcm param error:%d\n", ret);
  218. goto err_set_param_hpcm;
  219. }
  220. }
  221. do {
  222. printf("pcm_write start...\n");
  223. ret = pcm_write(mgr->handle, (char *)wav_file->start + sizeof(wav_header_t),
  224. snd_pcm_bytes_to_frames(mgr->handle, wav_header->dataSize),
  225. snd_pcm_frames_to_bytes(mgr->handle, 1));
  226. if (ret < 0) {
  227. printf("pcm_write error:%d\n", ret);
  228. break;
  229. }
  230. } while (g_playback_loop_enable);
  231. ret = snd_pcm_drain(mgr->handle);
  232. if (ret < 0)
  233. printf("stop failed!, return %d\n", ret);
  234. /* close card */
  235. ret = snd_pcm_close(mgr->handle);
  236. if (ret < 0) {
  237. printf("audio close error:%d\n", ret);
  238. goto err_pcm_close;
  239. }
  240. if (audio_hpcm_mgr) {
  241. if (audio_hpcm_mgr->handle != NULL) {
  242. snd_pcm_close(audio_hpcm_mgr->handle);
  243. }
  244. audio_mgr_release(audio_hpcm_mgr);
  245. g_hpcm_name = NULL;
  246. }
  247. return 0;
  248. err_pcm_close:
  249. err_set_param_hpcm:
  250. if (audio_hpcm_mgr && (audio_hpcm_mgr->handle != NULL))
  251. snd_pcm_close(audio_hpcm_mgr->handle);
  252. err_pcm_open_hpcm:
  253. if (g_hpcm_name) {
  254. audio_mgr_release(audio_hpcm_mgr);
  255. g_hpcm_name = NULL;
  256. }
  257. err_hpcm_create_mgr:
  258. err_set_pcm_param:
  259. /* close card */
  260. ret = snd_pcm_close(mgr->handle);
  261. if (ret < 0) {
  262. printf("audio close error:%d\n", ret);
  263. return ret;
  264. }
  265. return ret;
  266. }
  267. static int play_fs_music(audio_mgr_t *mgr, const char *path)
  268. {
  269. int ret = 0, fd = 0;
  270. wav_header_t wav_header;
  271. wav_hw_params_t wav_hwparams = {16000, SND_PCM_FORMAT_UNKNOWN, 2};
  272. unsigned int c, written = 0, count;
  273. unsigned int chunk_bytes, frame_bytes = 0;
  274. ssize_t r = 0;
  275. audio_mgr_t *audio_hpcm_mgr = NULL;
  276. char *audiobuf = NULL;
  277. fd = open(path, O_RDONLY);
  278. if (fd < 0) {
  279. printf("no such wav file\n");
  280. return -1;
  281. }
  282. r = read(fd, &wav_header, sizeof(wav_header_t));
  283. if (r != sizeof(wav_header_t)) {
  284. printf("read wav file header failed, return %ld\n",(long int)r);
  285. goto err_fread_wav_header;
  286. }
  287. if (check_wav_header(&wav_header, &wav_hwparams) != 0) {
  288. printf("check wav header failed\n");
  289. goto err_check_wav_header;
  290. }
  291. /* open card */
  292. ret = snd_pcm_open(&mgr->handle, g_pcm_name, SND_PCM_STREAM_PLAYBACK, 0);
  293. if (ret < 0) {
  294. printf("audio open error:%d\n", ret);
  295. goto err_pcm_open_pcm;
  296. }
  297. mgr->format = wav_hwparams.format;
  298. mgr->rate = wav_hwparams.rate;
  299. mgr->channels = wav_hwparams.channels;
  300. ret = set_param(mgr->handle, mgr->format, mgr->rate, mgr->channels,
  301. mgr->period_size, mgr->buffer_size);
  302. if (ret < 0) {
  303. printf("audio set pcm param error:%d\n", ret);
  304. goto err_set_param_pcm;
  305. }
  306. if (g_hpcm_name) {
  307. audio_hpcm_mgr = audio_mgr_create();
  308. if (!audio_hpcm_mgr) {
  309. printf("audio hpcm create manager failed.\n");
  310. goto err_hpcm_create_mgr;
  311. }
  312. /* open card */
  313. ret = snd_pcm_open(&audio_hpcm_mgr->handle, g_hpcm_name,
  314. SND_PCM_STREAM_PLAYBACK, 0);
  315. if (ret < 0) {
  316. printf("audio open error:%d\n", ret);
  317. goto err_pcm_open_hpcm;
  318. }
  319. audio_hpcm_mgr->format = wav_hwparams.format;
  320. audio_hpcm_mgr->rate = wav_hwparams.rate;
  321. audio_hpcm_mgr->channels = wav_hwparams.channels;
  322. audio_hpcm_mgr->period_size = mgr->period_size;
  323. audio_hpcm_mgr->buffer_size = mgr->buffer_size;
  324. ret = set_param(audio_hpcm_mgr->handle,
  325. audio_hpcm_mgr->format,
  326. audio_hpcm_mgr->rate,
  327. audio_hpcm_mgr->channels,
  328. audio_hpcm_mgr->period_size,
  329. audio_hpcm_mgr->buffer_size);
  330. if (ret < 0) {
  331. printf("audio set pcm param error:%d\n", ret);
  332. goto err_set_param_hpcm;
  333. }
  334. }
  335. count = wav_header.dataSize;
  336. frame_bytes = snd_pcm_frames_to_bytes(mgr->handle, 1);
  337. chunk_bytes = snd_pcm_frames_to_bytes(mgr->handle, mgr->period_size);
  338. audiobuf = malloc(chunk_bytes);
  339. if (!audiobuf) {
  340. printf("no memory...\n");
  341. goto err_malloc_audiobuf;
  342. }
  343. while (written < count) {
  344. c = count - written;
  345. if (c > chunk_bytes)
  346. c = chunk_bytes;
  347. r = read(fd, audiobuf, c);
  348. if (r < 0 || r != c) {
  349. printf("read file error, r=%ld,c=%u\n", (long int)r, c);
  350. break;
  351. }
  352. r = pcm_write(mgr->handle, audiobuf, r/frame_bytes, frame_bytes);
  353. if (r != c/frame_bytes)
  354. break;
  355. written += c;
  356. }
  357. snd_pcm_drain(mgr->handle);
  358. free(audiobuf);
  359. /* close card */
  360. if (mgr->handle != NULL)
  361. snd_pcm_close(mgr->handle);
  362. if (audio_hpcm_mgr) {
  363. if (audio_hpcm_mgr->handle != NULL) {
  364. snd_pcm_close(audio_hpcm_mgr->handle);
  365. }
  366. audio_mgr_release(audio_hpcm_mgr);
  367. g_hpcm_name = NULL;
  368. }
  369. close(fd);
  370. return 0;
  371. err_malloc_audiobuf:
  372. err_set_param_hpcm:
  373. if (audio_hpcm_mgr && (audio_hpcm_mgr->handle != NULL))
  374. snd_pcm_close(audio_hpcm_mgr->handle);
  375. err_pcm_open_hpcm:
  376. if (g_hpcm_name) {
  377. audio_mgr_release(audio_hpcm_mgr);
  378. g_hpcm_name = NULL;
  379. }
  380. err_hpcm_create_mgr:
  381. err_set_param_pcm:
  382. /* close card */
  383. if (mgr->handle != NULL)
  384. snd_pcm_close(mgr->handle);
  385. err_pcm_open_pcm:
  386. err_check_wav_header:
  387. err_fread_wav_header:
  388. close(fd);
  389. return ret;
  390. }
  391. static void usage(void)
  392. {
  393. printf("Usage: aplay [option] wav_file\n");
  394. printf(" -D, pcm device name\n");
  395. printf(" -H, Hub pcm device name\n");
  396. printf(" -p, period size\n");
  397. printf(" -b, buffer size\n");
  398. printf(" -l, loop playback test\n");
  399. printf(" -s, stop loop playback test\n");
  400. printf(" -v, show pcm setup\n");
  401. printf("\n");
  402. printf("builtin wav file:\n");
  403. wav_file_list();
  404. }
  405. int cmd_aplay(int argc, char ** argv)
  406. {
  407. int i = 0, c;
  408. audio_mgr_t *audio_mgr = NULL;
  409. g_hpcm_name = NULL;//"default";
  410. g_pcm_name = "default";//"hw:snddaudio0";
  411. g_verbose = 0;
  412. audio_mgr = audio_mgr_create();
  413. if (!audio_mgr)
  414. return -1;
  415. optind = 0;
  416. while ((c = getopt(argc, argv, "D:H:p:b:hslv")) != -1) {
  417. switch (c) {
  418. case 'D':
  419. g_pcm_name = optarg;
  420. break;
  421. case 'H':
  422. g_hpcm_name = optarg;
  423. break;
  424. case 'p':
  425. audio_mgr->period_size = atoi(optarg);
  426. break;
  427. case 'b':
  428. audio_mgr->buffer_size = atoi(optarg);
  429. break;
  430. case 's':
  431. g_playback_loop_enable = 0;
  432. goto err;
  433. case 'l':
  434. g_playback_loop_enable = 1;
  435. break;
  436. case 'v':
  437. g_verbose = 1;
  438. break;
  439. default:
  440. usage();
  441. goto err;
  442. }
  443. }
  444. if (optind < argc) {
  445. if (play_fs_music(audio_mgr, argv[optind]) < 0) {
  446. play_builtin_music(audio_mgr, argv[optind]);
  447. }
  448. } else {
  449. usage();
  450. printf("\nNow Playing the Test wav file........\n\n");
  451. play_builtin_music(audio_mgr, NULL);
  452. }
  453. err:
  454. audio_mgr_release(audio_mgr);
  455. return 0;
  456. }
  457. FINSH_FUNCTION_EXPORT_CMD(cmd_aplay, aplay, Play music);