if-audio.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. // SPDX-License-Identifier: Apache-2.0
  2. /*
  3. * Copyright (C) 2014 Intel Corporation
  4. *
  5. */
  6. #define _GNU_SOURCE
  7. #include <pthread.h>
  8. #include <unistd.h>
  9. #include <math.h>
  10. #include "if-main.h"
  11. #include "../hal-utils.h"
  12. audio_hw_device_t *if_audio = NULL;
  13. static struct audio_stream_out *stream_out = NULL;
  14. static size_t buffer_size = 0;
  15. static pthread_t play_thread = 0;
  16. static pthread_mutex_t outstream_mutex = PTHREAD_MUTEX_INITIALIZER;
  17. static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
  18. enum state {
  19. STATE_STOPPED,
  20. STATE_STOPPING,
  21. STATE_PLAYING,
  22. STATE_SUSPENDED,
  23. STATE_MAX
  24. };
  25. SINTMAP(audio_channel_mask_t, -1, "(AUDIO_CHANNEL_INVALID)")
  26. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
  27. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_RIGHT),
  28. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_CENTER),
  29. DELEMENT(AUDIO_CHANNEL_OUT_LOW_FREQUENCY),
  30. DELEMENT(AUDIO_CHANNEL_OUT_BACK_LEFT),
  31. DELEMENT(AUDIO_CHANNEL_OUT_BACK_RIGHT),
  32. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER),
  33. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
  34. DELEMENT(AUDIO_CHANNEL_OUT_BACK_CENTER),
  35. DELEMENT(AUDIO_CHANNEL_OUT_SIDE_LEFT),
  36. DELEMENT(AUDIO_CHANNEL_OUT_SIDE_RIGHT),
  37. DELEMENT(AUDIO_CHANNEL_OUT_TOP_CENTER),
  38. DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT),
  39. DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER),
  40. DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT),
  41. DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_LEFT),
  42. DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_CENTER),
  43. DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
  44. DELEMENT(AUDIO_CHANNEL_OUT_MONO),
  45. DELEMENT(AUDIO_CHANNEL_OUT_STEREO),
  46. DELEMENT(AUDIO_CHANNEL_OUT_QUAD),
  47. #if ANDROID_VERSION < PLATFORM_VER(5, 0, 0)
  48. DELEMENT(AUDIO_CHANNEL_OUT_SURROUND),
  49. #else
  50. DELEMENT(AUDIO_CHANNEL_OUT_QUAD_BACK),
  51. DELEMENT(AUDIO_CHANNEL_OUT_QUAD_SIDE),
  52. DELEMENT(AUDIO_CHANNEL_OUT_5POINT1_BACK),
  53. DELEMENT(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
  54. #endif
  55. DELEMENT(AUDIO_CHANNEL_OUT_5POINT1),
  56. DELEMENT(AUDIO_CHANNEL_OUT_7POINT1),
  57. DELEMENT(AUDIO_CHANNEL_OUT_ALL),
  58. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
  59. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
  60. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
  61. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
  62. DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
  63. ENDMAP
  64. SINTMAP(audio_format_t, -1, "(AUDIO_FORMAT_INVALID)")
  65. DELEMENT(AUDIO_FORMAT_DEFAULT),
  66. DELEMENT(AUDIO_FORMAT_PCM),
  67. DELEMENT(AUDIO_FORMAT_MP3),
  68. DELEMENT(AUDIO_FORMAT_AMR_NB),
  69. DELEMENT(AUDIO_FORMAT_AMR_WB),
  70. DELEMENT(AUDIO_FORMAT_AAC),
  71. DELEMENT(AUDIO_FORMAT_HE_AAC_V1),
  72. DELEMENT(AUDIO_FORMAT_HE_AAC_V2),
  73. DELEMENT(AUDIO_FORMAT_VORBIS),
  74. DELEMENT(AUDIO_FORMAT_MAIN_MASK),
  75. DELEMENT(AUDIO_FORMAT_SUB_MASK),
  76. DELEMENT(AUDIO_FORMAT_PCM_16_BIT),
  77. DELEMENT(AUDIO_FORMAT_PCM_8_BIT),
  78. DELEMENT(AUDIO_FORMAT_PCM_32_BIT),
  79. DELEMENT(AUDIO_FORMAT_PCM_8_24_BIT),
  80. ENDMAP
  81. static int current_state = STATE_STOPPED;
  82. #define SAMPLERATE 44100
  83. static short sample[SAMPLERATE];
  84. static uint16_t sample_pos;
  85. static void init_p(int argc, const char **argv)
  86. {
  87. int err;
  88. const hw_module_t *module;
  89. audio_hw_device_t *device;
  90. err = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID,
  91. AUDIO_HARDWARE_MODULE_ID_A2DP, &module);
  92. if (err) {
  93. haltest_error("hw_get_module_by_class returned %d\n", err);
  94. return;
  95. }
  96. err = audio_hw_device_open(module, &device);
  97. if (err) {
  98. haltest_error("audio_hw_device_open returned %d\n", err);
  99. return;
  100. }
  101. if_audio = device;
  102. }
  103. static int feed_from_file(short *buffer, void *data)
  104. {
  105. FILE *in = data;
  106. return fread(buffer, buffer_size, 1, in);
  107. }
  108. static int feed_from_generator(short *buffer, void *data)
  109. {
  110. size_t i = 0;
  111. float volume = 0.5;
  112. float *freq = data;
  113. float f = 1;
  114. if (freq)
  115. f = *freq;
  116. /* buffer_size is in bytes but we are using buffer of shorts (2 bytes)*/
  117. for (i = 0; i < buffer_size / sizeof(*buffer) - 1;) {
  118. if (sample_pos >= SAMPLERATE)
  119. sample_pos = sample_pos % SAMPLERATE;
  120. /* Use the same sample for both channels */
  121. buffer[i++] = sample[sample_pos] * volume;
  122. buffer[i++] = sample[sample_pos] * volume;
  123. sample_pos += f;
  124. }
  125. return buffer_size;
  126. }
  127. static void prepare_sample(void)
  128. {
  129. int x;
  130. double s;
  131. haltest_info("Preparing audio sample...\n");
  132. for (x = 0; x < SAMPLERATE; x++) {
  133. /* prepare sinusoidal 1Hz sample */
  134. s = (2.0 * 3.14159) * ((double)x / SAMPLERATE);
  135. s = sin(s);
  136. /* remap <-1, 1> to signed 16bit PCM range */
  137. sample[x] = s * 32767;
  138. }
  139. sample_pos = 0;
  140. }
  141. static void *playback_thread(void *data)
  142. {
  143. int (*filbuff_cb) (short*, void*);
  144. short buffer[buffer_size / sizeof(short)];
  145. size_t len = 0;
  146. ssize_t w_len = 0;
  147. FILE *in = data;
  148. void *cb_data = NULL;
  149. float freq = 440.0;
  150. /* Use file or fall back to generator */
  151. if (in) {
  152. filbuff_cb = feed_from_file;
  153. cb_data = in;
  154. } else {
  155. prepare_sample();
  156. filbuff_cb = feed_from_generator;
  157. cb_data = &freq;
  158. }
  159. pthread_mutex_lock(&state_mutex);
  160. current_state = STATE_PLAYING;
  161. pthread_mutex_unlock(&state_mutex);
  162. do {
  163. pthread_mutex_lock(&state_mutex);
  164. if (current_state == STATE_STOPPING) {
  165. pthread_mutex_unlock(&state_mutex);
  166. break;
  167. } else if (current_state == STATE_SUSPENDED) {
  168. pthread_mutex_unlock(&state_mutex);
  169. usleep(500);
  170. continue;
  171. }
  172. pthread_mutex_unlock(&state_mutex);
  173. len = filbuff_cb(buffer, cb_data);
  174. pthread_mutex_lock(&outstream_mutex);
  175. if (!stream_out) {
  176. pthread_mutex_unlock(&outstream_mutex);
  177. break;
  178. }
  179. w_len = stream_out->write(stream_out, buffer, buffer_size);
  180. pthread_mutex_unlock(&outstream_mutex);
  181. } while (len && w_len > 0);
  182. if (in)
  183. fclose(in);
  184. pthread_mutex_lock(&state_mutex);
  185. current_state = STATE_STOPPED;
  186. pthread_mutex_unlock(&state_mutex);
  187. haltest_info("Done playing.\n");
  188. return NULL;
  189. }
  190. static void play_p(int argc, const char **argv)
  191. {
  192. const char *fname = NULL;
  193. FILE *in = NULL;
  194. RETURN_IF_NULL(if_audio);
  195. RETURN_IF_NULL(stream_out);
  196. if (argc < 3) {
  197. haltest_error("Invalid audio file path.\n");
  198. haltest_info("Using sound generator.\n");
  199. } else {
  200. fname = argv[2];
  201. in = fopen(fname, "r");
  202. if (in == NULL) {
  203. haltest_error("Cannot open file: %s\n", fname);
  204. return;
  205. }
  206. haltest_info("Playing file: %s\n", fname);
  207. }
  208. if (buffer_size == 0) {
  209. haltest_error("Invalid buffer size. Was stream_out opened?\n");
  210. goto fail;
  211. }
  212. pthread_mutex_lock(&state_mutex);
  213. if (current_state != STATE_STOPPED) {
  214. haltest_error("Already playing or stream suspended!\n");
  215. pthread_mutex_unlock(&state_mutex);
  216. goto fail;
  217. }
  218. pthread_mutex_unlock(&state_mutex);
  219. if (pthread_create(&play_thread, NULL, playback_thread, in) != 0) {
  220. haltest_error("Cannot create playback thread!\n");
  221. goto fail;
  222. }
  223. return;
  224. fail:
  225. if (in)
  226. fclose(in);
  227. }
  228. static void stop_p(int argc, const char **argv)
  229. {
  230. pthread_mutex_lock(&state_mutex);
  231. if (current_state == STATE_STOPPED || current_state == STATE_STOPPING) {
  232. pthread_mutex_unlock(&state_mutex);
  233. return;
  234. }
  235. current_state = STATE_STOPPING;
  236. pthread_mutex_unlock(&state_mutex);
  237. pthread_mutex_lock(&outstream_mutex);
  238. stream_out->common.standby(&stream_out->common);
  239. pthread_mutex_unlock(&outstream_mutex);
  240. }
  241. static void open_output_stream_p(int argc, const char **argv)
  242. {
  243. int err;
  244. RETURN_IF_NULL(if_audio);
  245. pthread_mutex_lock(&state_mutex);
  246. if (current_state == STATE_PLAYING) {
  247. haltest_error("Already playing!\n");
  248. pthread_mutex_unlock(&state_mutex);
  249. return;
  250. }
  251. pthread_mutex_unlock(&state_mutex);
  252. #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
  253. err = if_audio->open_output_stream(if_audio,
  254. 0,
  255. AUDIO_DEVICE_OUT_ALL_A2DP,
  256. AUDIO_OUTPUT_FLAG_NONE,
  257. NULL,
  258. &stream_out, NULL);
  259. #else
  260. err = if_audio->open_output_stream(if_audio,
  261. 0,
  262. AUDIO_DEVICE_OUT_ALL_A2DP,
  263. AUDIO_OUTPUT_FLAG_NONE,
  264. NULL,
  265. &stream_out);
  266. #endif
  267. if (err < 0) {
  268. haltest_error("open output stream returned %d\n", err);
  269. return;
  270. }
  271. buffer_size = stream_out->common.get_buffer_size(&stream_out->common);
  272. if (buffer_size == 0)
  273. haltest_error("Invalid buffer size received!\n");
  274. else
  275. haltest_info("Using buffer size: %zu\n", buffer_size);
  276. }
  277. static void close_output_stream_p(int argc, const char **argv)
  278. {
  279. RETURN_IF_NULL(if_audio);
  280. RETURN_IF_NULL(stream_out);
  281. stop_p(argc, argv);
  282. haltest_info("Waiting for playback thread...\n");
  283. pthread_join(play_thread, NULL);
  284. if_audio->close_output_stream(if_audio, stream_out);
  285. stream_out = NULL;
  286. buffer_size = 0;
  287. }
  288. static void cleanup_p(int argc, const char **argv)
  289. {
  290. int err;
  291. RETURN_IF_NULL(if_audio);
  292. pthread_mutex_lock(&state_mutex);
  293. if (current_state != STATE_STOPPED) {
  294. pthread_mutex_unlock(&state_mutex);
  295. close_output_stream_p(0, NULL);
  296. } else {
  297. pthread_mutex_unlock(&state_mutex);
  298. }
  299. err = audio_hw_device_close(if_audio);
  300. if (err < 0) {
  301. haltest_error("audio_hw_device_close returned %d\n", err);
  302. return;
  303. }
  304. if_audio = NULL;
  305. }
  306. static void suspend_p(int argc, const char **argv)
  307. {
  308. RETURN_IF_NULL(if_audio);
  309. RETURN_IF_NULL(stream_out);
  310. pthread_mutex_lock(&state_mutex);
  311. if (current_state != STATE_PLAYING) {
  312. pthread_mutex_unlock(&state_mutex);
  313. return;
  314. }
  315. current_state = STATE_SUSPENDED;
  316. pthread_mutex_unlock(&state_mutex);
  317. pthread_mutex_lock(&outstream_mutex);
  318. stream_out->common.standby(&stream_out->common);
  319. pthread_mutex_unlock(&outstream_mutex);
  320. }
  321. static void resume_p(int argc, const char **argv)
  322. {
  323. RETURN_IF_NULL(if_audio);
  324. RETURN_IF_NULL(stream_out);
  325. pthread_mutex_lock(&state_mutex);
  326. if (current_state == STATE_SUSPENDED)
  327. current_state = STATE_PLAYING;
  328. pthread_mutex_unlock(&state_mutex);
  329. }
  330. static void get_latency_p(int argc, const char **argv)
  331. {
  332. RETURN_IF_NULL(if_audio);
  333. RETURN_IF_NULL(stream_out);
  334. haltest_info("Output audio stream latency: %d\n",
  335. stream_out->get_latency(stream_out));
  336. }
  337. static void get_buffer_size_p(int argc, const char **argv)
  338. {
  339. RETURN_IF_NULL(if_audio);
  340. RETURN_IF_NULL(stream_out);
  341. haltest_info("Current output buffer size: %zu\n",
  342. stream_out->common.get_buffer_size(&stream_out->common));
  343. }
  344. static void get_channels_p(int argc, const char **argv)
  345. {
  346. audio_channel_mask_t channels;
  347. RETURN_IF_NULL(if_audio);
  348. RETURN_IF_NULL(stream_out);
  349. channels = stream_out->common.get_channels(&stream_out->common);
  350. haltest_info("Channels: %s\n", audio_channel_mask_t2str(channels));
  351. }
  352. static void get_format_p(int argc, const char **argv)
  353. {
  354. audio_format_t format;
  355. RETURN_IF_NULL(if_audio);
  356. RETURN_IF_NULL(stream_out);
  357. format = stream_out->common.get_format(&stream_out->common);
  358. haltest_info("Format: %s\n", audio_format_t2str(format));
  359. }
  360. static void get_sample_rate_p(int argc, const char **argv)
  361. {
  362. RETURN_IF_NULL(if_audio);
  363. RETURN_IF_NULL(stream_out);
  364. haltest_info("Current sample rate: %d\n",
  365. stream_out->common.get_sample_rate(&stream_out->common));
  366. }
  367. static void get_parameters_p(int argc, const char **argv)
  368. {
  369. const char *keystr;
  370. RETURN_IF_NULL(if_audio);
  371. RETURN_IF_NULL(stream_out);
  372. if (argc < 3) {
  373. haltest_info("No keys given.\n");
  374. keystr = "";
  375. } else {
  376. keystr = argv[2];
  377. }
  378. haltest_info("Current parameters: %s\n",
  379. stream_out->common.get_parameters(&stream_out->common,
  380. keystr));
  381. }
  382. static void set_parameters_p(int argc, const char **argv)
  383. {
  384. RETURN_IF_NULL(if_audio);
  385. RETURN_IF_NULL(stream_out);
  386. if (argc < 3) {
  387. haltest_error("No key=value; pairs given.\n");
  388. return;
  389. }
  390. stream_out->common.set_parameters(&stream_out->common, argv[2]);
  391. }
  392. static void set_sample_rate_p(int argc, const char **argv)
  393. {
  394. RETURN_IF_NULL(if_audio);
  395. RETURN_IF_NULL(stream_out);
  396. if (argc < 3)
  397. return;
  398. stream_out->common.set_sample_rate(&stream_out->common, atoi(argv[2]));
  399. }
  400. static void init_check_p(int argc, const char **argv)
  401. {
  402. RETURN_IF_NULL(if_audio);
  403. haltest_info("Init check result: %d\n", if_audio->init_check(if_audio));
  404. }
  405. static struct method methods[] = {
  406. STD_METHOD(init),
  407. STD_METHOD(cleanup),
  408. STD_METHOD(open_output_stream),
  409. STD_METHOD(close_output_stream),
  410. STD_METHODH(play, "<path to pcm file>"),
  411. STD_METHOD(stop),
  412. STD_METHOD(suspend),
  413. STD_METHOD(resume),
  414. STD_METHOD(get_latency),
  415. STD_METHOD(get_buffer_size),
  416. STD_METHOD(get_channels),
  417. STD_METHOD(get_format),
  418. STD_METHOD(get_sample_rate),
  419. STD_METHODH(get_parameters, "<A2dpSuspended;closing>"),
  420. STD_METHODH(set_parameters, "<A2dpSuspended=value;closing=value>"),
  421. STD_METHODH(set_sample_rate, "<sample rate>"),
  422. STD_METHOD(init_check),
  423. END_METHOD
  424. };
  425. const struct interface audio_if = {
  426. .name = "audio",
  427. .methods = methods
  428. };