Advertisement
uaa

[wip-20201212] direwolf: audio.c for sndio

uaa
Dec 11th, 2020
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.45 KB | None | 0 0
  1.  
  2.  
  3. //
  4. // This file is part of Dire Wolf, an amateur radio packet TNC.
  5. //
  6. // Copyright (C) 2011, 2012, 2013, 2014, 2015 John Langner, WB2OSZ
  7. //
  8. // This program is free software: you can redistribute it and/or modify
  9. // it under the terms of the GNU General Public License as published by
  10. // the Free Software Foundation, either version 2 of the License, or
  11. // (at your option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License
  19. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. //
  21.  
  22.  
  23. /*------------------------------------------------------------------
  24. *
  25. * Module: audio.c
  26. *
  27. * Purpose: Interface to audio device commonly called a "sound card" for
  28. * historical reasons.
  29. *
  30. * This version is for Linux and Cygwin.
  31. *
  32. * Two different types of sound interfaces are supported:
  33. *
  34. * * OSS - For Cygwin or Linux versions with /dev/dsp.
  35. *
  36. * * ALSA - For Linux versions without /dev/dsp.
  37. * In this case, define preprocessor symbol USE_ALSA.
  38. *
  39. * References: Some tips on on using Linux sound devices.
  40. *
  41. * http://www.oreilly.de/catalog/multilinux/excerpt/ch14-05.htm
  42. * http://cygwin.com/ml/cygwin-patches/2004-q1/msg00116/devdsp.c
  43. * http://manuals.opensound.com/developer/fulldup.c.html
  44. *
  45. * "Introduction to Sound Programming with ALSA"
  46. * http://www.linuxjournal.com/article/6735?page=0,1
  47. *
  48. * http://www.alsa-project.org/main/index.php/Asoundrc
  49. *
  50. * Credits: Release 1.0: Fabrice FAURE contributed code for the SDR UDP interface.
  51. *
  52. * Discussion here: http://gqrx.dk/doc/streaming-audio-over-udp
  53. *
  54. * Release 1.1: Gabor Berczi provided fixes for the OSS code
  55. * which had fallen into decay.
  56. *
  57. * Major Revisions:
  58. *
  59. * 1.2 - Add ability to use more than one audio device.
  60. *
  61. *---------------------------------------------------------------*/
  62.  
  63. #include "direwolf.h"
  64.  
  65. #include <stdio.h>
  66. #include <unistd.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <sys/types.h>
  70. #include <sys/stat.h>
  71. #include <sys/ioctl.h>
  72. #include <fcntl.h>
  73. #include <assert.h>
  74.  
  75. #include <sys/socket.h>
  76. #include <arpa/inet.h>
  77. #include <netinet/in.h>
  78. #include <errno.h>
  79.  
  80.  
  81. #if USE_ALSA
  82. #include <alsa/asoundlib.h>
  83. #elif USE_SNDIO
  84. #include <sndio.h>
  85. #include <poll.h>
  86. #else
  87. #include <sys/soundcard.h>
  88. #endif
  89.  
  90.  
  91. #include "audio.h"
  92. #include "audio_stats.h"
  93. #include "textcolor.h"
  94. #include "dtime_now.h"
  95. #include "demod.h" /* for alevel_t & demod_get_audio_level() */
  96.  
  97.  
  98. /* Audio configuration. */
  99.  
  100. static struct audio_s *save_audio_config_p;
  101.  
  102.  
  103. /* Current state for each of the audio devices. */
  104.  
  105. static struct adev_s {
  106.  
  107. #if USE_ALSA
  108. snd_pcm_t *audio_in_handle;
  109. snd_pcm_t *audio_out_handle;
  110.  
  111. int bytes_per_frame; /* number of bytes for a sample from all channels. */
  112. /* e.g. 4 for stereo 16 bit. */
  113. #elif USE_SNDIO
  114. struct sio_hdl *sndio_handle; /* Single device, both directions. */
  115.  
  116. #else
  117. int oss_audio_device_fd; /* Single device, both directions. */
  118.  
  119. #endif
  120.  
  121. int inbuf_size_in_bytes; /* number of bytes allocated */
  122. unsigned char *inbuf_ptr;
  123. int inbuf_len; /* number byte of actual data available. */
  124. int inbuf_next; /* index of next to remove. */
  125.  
  126. int outbuf_size_in_bytes;
  127. unsigned char *outbuf_ptr;
  128. int outbuf_len;
  129.  
  130. enum audio_in_type_e g_audio_in_type;
  131.  
  132. int udp_sock; /* UDP socket for receiving data */
  133.  
  134. } adev[MAX_ADEVS];
  135.  
  136.  
  137. // Originally 40. Version 1.2, try 10 for lower latency.
  138.  
  139. #define ONE_BUF_TIME 10
  140.  
  141.  
  142. #if USE_ALSA
  143. static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *name, char *dir);
  144. //static void alsa_select_device (char *pick_dev, int direction, char *result);
  145. #elif USE_SNDIO
  146. static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname);
  147. #else
  148. static int set_oss_params (int a, int fd, struct audio_s *pa);
  149. #endif
  150.  
  151.  
  152. #define roundup1k(n) (((n) + 0x3ff) & ~0x3ff)
  153.  
  154. static int calcbufsize(int rate, int chans, int bits)
  155. {
  156. int size1 = (rate * chans * bits / 8 * ONE_BUF_TIME) / 1000;
  157. int size2 = roundup1k(size1);
  158. #if DEBUG
  159. text_color_set(DW_COLOR_DEBUG);
  160. dw_printf ("audio_open: calcbufsize (rate=%d, chans=%d, bits=%d) calc size=%d, round up to %d\n",
  161. rate, chans, bits, size1, size2);
  162. #endif
  163. return (size2);
  164. }
  165.  
  166.  
  167. /*------------------------------------------------------------------
  168. *
  169. * Name: audio_open
  170. *
  171. * Purpose: Open the digital audio device.
  172. * For "OSS", the device name is typically "/dev/dsp".
  173. * For "ALSA", it's a lot more complicated. See User Guide.
  174. *
  175. * New in version 1.0, we recognize "udp:" optionally
  176. * followed by a port number.
  177. *
  178. * Inputs: pa - Address of structure of type audio_s.
  179. *
  180. * Using a structure, rather than separate arguments
  181. * seemed to make sense because we often pass around
  182. * the same set of parameters various places.
  183. *
  184. * The fields that we care about are:
  185. * num_channels
  186. * samples_per_sec
  187. * bits_per_sample
  188. * If zero, reasonable defaults will be provided.
  189. *
  190. * The device names are in adevice_in and adevice_out.
  191. * - For "OSS", the device name is typically "/dev/dsp".
  192. * - For "ALSA", the device names are hw:c,d
  193. * where c is the "card" (for historical purposes)
  194. * and d is the "device" within the "card."
  195. *
  196. *
  197. * Outputs: pa - The ACTUAL values are returned here.
  198. *
  199. * These might not be exactly the same as what was requested.
  200. *
  201. * Example: ask for stereo, 16 bits, 22050 per second.
  202. * An ordinary desktop/laptop PC should be able to handle this.
  203. * However, some other sort of smaller device might be
  204. * more restrictive in its capabilities.
  205. * It might say, the best I can do is mono, 8 bit, 8000/sec.
  206. *
  207. * The sofware modem must use this ACTUAL information
  208. * that the device is supplying, that could be different
  209. * than what the user specified.
  210. *
  211. * Returns: 0 for success, -1 for failure.
  212. *
  213. *
  214. *----------------------------------------------------------------*/
  215.  
  216. int audio_open (struct audio_s *pa)
  217. {
  218. #ifndef USE_SNDIO
  219. int err;
  220. #endif
  221. int chan;
  222. int a;
  223. char audio_in_name[30];
  224. char audio_out_name[30];
  225.  
  226.  
  227. save_audio_config_p = pa;
  228.  
  229. memset (adev, 0, sizeof(adev));
  230.  
  231. for (a=0; a<MAX_ADEVS; a++) {
  232. #ifdef USE_ALSA
  233. adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
  234. #elif USE_SNDIO
  235. adev[a].sndio_handle = NULL;
  236. #else
  237. adev[a].oss_audio_device_fd = -1;
  238. #endif
  239. adev[a].udp_sock = -1;
  240. }
  241.  
  242.  
  243. /*
  244. * Fill in defaults for any missing values.
  245. */
  246.  
  247. for (a=0; a<MAX_ADEVS; a++) {
  248.  
  249. if (pa->adev[a].num_channels == 0)
  250. pa->adev[a].num_channels = DEFAULT_NUM_CHANNELS;
  251.  
  252. if (pa->adev[a].samples_per_sec == 0)
  253. pa->adev[a].samples_per_sec = DEFAULT_SAMPLES_PER_SEC;
  254.  
  255. if (pa->adev[a].bits_per_sample == 0)
  256. pa->adev[a].bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
  257.  
  258. for (chan=0; chan<MAX_CHANS; chan++) {
  259. if (pa->achan[chan].mark_freq == 0)
  260. pa->achan[chan].mark_freq = DEFAULT_MARK_FREQ;
  261.  
  262. if (pa->achan[chan].space_freq == 0)
  263. pa->achan[chan].space_freq = DEFAULT_SPACE_FREQ;
  264.  
  265. if (pa->achan[chan].baud == 0)
  266. pa->achan[chan].baud = DEFAULT_BAUD;
  267.  
  268. if (pa->achan[chan].num_subchan == 0)
  269. pa->achan[chan].num_subchan = 1;
  270. }
  271. }
  272.  
  273. /*
  274. * Open audio device(s).
  275. */
  276.  
  277. for (a=0; a<MAX_ADEVS; a++) {
  278. if (pa->adev[a].defined) {
  279.  
  280. adev[a].inbuf_size_in_bytes = 0;
  281. adev[a].inbuf_ptr = NULL;
  282. adev[a].inbuf_len = 0;
  283. adev[a].inbuf_next = 0;
  284.  
  285. adev[a].outbuf_size_in_bytes = 0;
  286. adev[a].outbuf_ptr = NULL;
  287. adev[a].outbuf_len = 0;
  288.  
  289. /*
  290. * Determine the type of audio input.
  291. */
  292.  
  293. adev[a].g_audio_in_type = AUDIO_IN_TYPE_SOUNDCARD;
  294.  
  295. if (strcasecmp(pa->adev[a].adevice_in, "stdin") == 0 || strcmp(pa->adev[a].adevice_in, "-") == 0) {
  296. adev[a].g_audio_in_type = AUDIO_IN_TYPE_STDIN;
  297. /* Change "-" to stdin for readability. */
  298. strlcpy (pa->adev[a].adevice_in, "stdin", sizeof(pa->adev[a].adevice_in));
  299. }
  300. if (strncasecmp(pa->adev[a].adevice_in, "udp:", 4) == 0) {
  301. adev[a].g_audio_in_type = AUDIO_IN_TYPE_SDR_UDP;
  302. /* Supply default port if none specified. */
  303. if (strcasecmp(pa->adev[a].adevice_in,"udp") == 0 ||
  304. strcasecmp(pa->adev[a].adevice_in,"udp:") == 0) {
  305. snprintf (pa->adev[a].adevice_in, sizeof(pa->adev[a].adevice_in), "udp:%d", DEFAULT_UDP_AUDIO_PORT);
  306. }
  307. }
  308.  
  309. /* Let user know what is going on. */
  310.  
  311. /* If not specified, the device names should be "default". */
  312.  
  313. strlcpy (audio_in_name, pa->adev[a].adevice_in, sizeof(audio_in_name));
  314. strlcpy (audio_out_name, pa->adev[a].adevice_out, sizeof(audio_out_name));
  315.  
  316. char ctemp[40];
  317.  
  318. if (pa->adev[a].num_channels == 2) {
  319. snprintf (ctemp, sizeof(ctemp), " (channels %d & %d)", ADEVFIRSTCHAN(a), ADEVFIRSTCHAN(a)+1);
  320. }
  321. else {
  322. snprintf (ctemp, sizeof(ctemp), " (channel %d)", ADEVFIRSTCHAN(a));
  323. }
  324.  
  325. text_color_set(DW_COLOR_INFO);
  326.  
  327. if (strcmp(audio_in_name,audio_out_name) == 0) {
  328. dw_printf ("Audio device for both receive and transmit: %s %s\n", audio_in_name, ctemp);
  329. }
  330. else {
  331. dw_printf ("Audio input device for receive: %s %s\n", audio_in_name, ctemp);
  332. dw_printf ("Audio out device for transmit: %s %s\n", audio_out_name, ctemp);
  333. }
  334.  
  335. /*
  336. * Now attempt actual opens.
  337. */
  338.  
  339. /*
  340. * Input device.
  341. */
  342.  
  343. switch (adev[a].g_audio_in_type) {
  344.  
  345. /*
  346. * Soundcard - ALSA.
  347. */
  348. case AUDIO_IN_TYPE_SOUNDCARD:
  349. #if USE_ALSA
  350. err = snd_pcm_open (&(adev[a].audio_in_handle), audio_in_name, SND_PCM_STREAM_CAPTURE, 0);
  351. if (err < 0) {
  352. text_color_set(DW_COLOR_ERROR);
  353. dw_printf ("Could not open audio device %s for input\n%s\n",
  354. audio_in_name, snd_strerror(err));
  355. return (-1);
  356. }
  357.  
  358. adev[a].inbuf_size_in_bytes = set_alsa_params (a, adev[a].audio_in_handle, pa, audio_in_name, "input");
  359.  
  360. #elif USE_SNDIO
  361. adev[a].sndio_handle = sio_open (audio_in_name, SIO_PLAY | SIO_REC, 1);
  362. if (adev[a].sndio_handle == NULL) {
  363. text_color_set(DW_COLOR_ERROR);
  364. dw_printf ("Could not open audio device %s for input/output\n",
  365. audio_in_name);
  366. return (-1);
  367. }
  368.  
  369. adev[a].outbuf_size_in_bytes = adev[a].inbuf_size_in_bytes = set_sndio_params (a, adev[a].sndio_handle, pa, audio_in_name);
  370.  
  371. if (adev[a].inbuf_size_in_bytes <= 0 || adev[a].outbuf_size_in_bytes <= 0) {
  372. return (-1);
  373. }
  374.  
  375. if (!sio_start (adev[a].sndio_handle)) {
  376. text_color_set(DW_COLOR_ERROR);
  377. dw_printf ("Could not start audio device %s for input/output\n",
  378. audio_in_name);
  379. sio_close(adev[a].sndio_handle);
  380. adev[a].sndio_handle = NULL;
  381. return (-1);
  382. }
  383.  
  384. #else // OSS
  385. adev[a].oss_audio_device_fd = open (pa->adev[a].adevice_in, O_RDWR);
  386.  
  387. if (adev[a].oss_audio_device_fd < 0) {
  388. text_color_set(DW_COLOR_ERROR);
  389. dw_printf ("%s:\n", pa->adev[a].adevice_in);
  390. // snprintf (message, sizeof(message), "Could not open audio device %s", pa->adev[a].adevice_in);
  391. // perror (message);
  392. return (-1);
  393. }
  394.  
  395. adev[a].outbuf_size_in_bytes = adev[a].inbuf_size_in_bytes = set_oss_params (a, adev[a].oss_audio_device_fd, pa);
  396.  
  397. if (adev[a].inbuf_size_in_bytes <= 0 || adev[a].outbuf_size_in_bytes <= 0) {
  398. return (-1);
  399. }
  400. #endif
  401. break;
  402. /*
  403. * UDP.
  404. */
  405. case AUDIO_IN_TYPE_SDR_UDP:
  406.  
  407. //Create socket and bind socket
  408.  
  409. {
  410. struct sockaddr_in si_me;
  411. //int slen=sizeof(si_me);
  412. //int data_size = 0;
  413.  
  414. //Create UDP Socket
  415. if ((adev[a].udp_sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1) {
  416. text_color_set(DW_COLOR_ERROR);
  417. dw_printf ("Couldn't create socket, errno %d\n", errno);
  418. return -1;
  419. }
  420.  
  421. memset((char *) &si_me, 0, sizeof(si_me));
  422. si_me.sin_family = AF_INET;
  423. si_me.sin_port = htons((short)atoi(audio_in_name+4));
  424. si_me.sin_addr.s_addr = htonl(INADDR_ANY);
  425.  
  426. //Bind to the socket
  427. if (bind(adev[a].udp_sock, (const struct sockaddr *) &si_me, sizeof(si_me))==-1) {
  428. text_color_set(DW_COLOR_ERROR);
  429. dw_printf ("Couldn't bind socket, errno %d\n", errno);
  430. return -1;
  431. }
  432. }
  433. adev[a].inbuf_size_in_bytes = SDR_UDP_BUF_MAXLEN;
  434.  
  435. break;
  436.  
  437. /*
  438. * stdin.
  439. */
  440. case AUDIO_IN_TYPE_STDIN:
  441.  
  442. /* Do we need to adjust any properties of stdin? */
  443.  
  444. adev[a].inbuf_size_in_bytes = 1024;
  445.  
  446. break;
  447.  
  448. default:
  449.  
  450. text_color_set(DW_COLOR_ERROR);
  451. dw_printf ("Internal error, invalid audio_in_type\n");
  452. return (-1);
  453. }
  454.  
  455. /*
  456. * Output device. Only "soundcard" is supported at this time.
  457. */
  458.  
  459. #if USE_ALSA
  460. err = snd_pcm_open (&(adev[a].audio_out_handle), audio_out_name, SND_PCM_STREAM_PLAYBACK, 0);
  461.  
  462. if (err < 0) {
  463. text_color_set(DW_COLOR_ERROR);
  464. dw_printf ("Could not open audio device %s for output\n%s\n",
  465. audio_out_name, snd_strerror(err));
  466. return (-1);
  467. }
  468.  
  469. adev[a].outbuf_size_in_bytes = set_alsa_params (a, adev[a].audio_out_handle, pa, audio_out_name, "output");
  470.  
  471. if (adev[a].inbuf_size_in_bytes <= 0 || adev[a].outbuf_size_in_bytes <= 0) {
  472. return (-1);
  473. }
  474.  
  475. #endif
  476.  
  477. /*
  478. * Finally allocate buffer for each direction.
  479. */
  480. adev[a].inbuf_ptr = malloc(adev[a].inbuf_size_in_bytes);
  481. assert (adev[a].inbuf_ptr != NULL);
  482. adev[a].inbuf_len = 0;
  483. adev[a].inbuf_next = 0;
  484.  
  485. adev[a].outbuf_ptr = malloc(adev[a].outbuf_size_in_bytes);
  486. assert (adev[a].outbuf_ptr != NULL);
  487. adev[a].outbuf_len = 0;
  488.  
  489. } /* end of audio device defined */
  490.  
  491. } /* end of for each audio device */
  492.  
  493. return (0);
  494.  
  495. } /* end audio_open */
  496.  
  497.  
  498.  
  499.  
  500. #if USE_ALSA
  501.  
  502. /*
  503. * Set parameters for sound card.
  504. *
  505. * See ?? for details.
  506. */
  507. /*
  508. * Terminology:
  509. * Sample - for one channel. e.g. 2 bytes for 16 bit.
  510. * Frame - one sample for all channels. e.g. 4 bytes for 16 bit stereo
  511. * Period - size of one transfer.
  512. */
  513.  
  514. static int set_alsa_params (int a, snd_pcm_t *handle, struct audio_s *pa, char *devname, char *inout)
  515. {
  516.  
  517. snd_pcm_hw_params_t *hw_params;
  518. snd_pcm_uframes_t fpp; /* Frames per period. */
  519.  
  520. unsigned int val;
  521.  
  522. int dir;
  523. int err;
  524.  
  525. int buf_size_in_bytes; /* result, number of bytes per transfer. */
  526.  
  527.  
  528. err = snd_pcm_hw_params_malloc (&hw_params);
  529. if (err < 0) {
  530. text_color_set(DW_COLOR_ERROR);
  531. dw_printf ("Could not alloc hw param structure.\n%s\n",
  532. snd_strerror(err));
  533. dw_printf ("for %s %s.\n", devname, inout);
  534. return (-1);
  535. }
  536.  
  537. err = snd_pcm_hw_params_any (handle, hw_params);
  538. if (err < 0) {
  539. text_color_set(DW_COLOR_ERROR);
  540. dw_printf ("Could not init hw param structure.\n%s\n",
  541. snd_strerror(err));
  542. dw_printf ("for %s %s.\n", devname, inout);
  543. return (-1);
  544. }
  545.  
  546. /* Interleaved data: L, R, L, R, ... */
  547.  
  548. err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  549.  
  550. if (err < 0) {
  551. text_color_set(DW_COLOR_ERROR);
  552. dw_printf ("Could not set interleaved mode.\n%s\n",
  553. snd_strerror(err));
  554. dw_printf ("for %s %s.\n", devname, inout);
  555. return (-1);
  556. }
  557.  
  558. /* Signed 16 bit little endian or unsigned 8 bit. */
  559.  
  560.  
  561. err = snd_pcm_hw_params_set_format (handle, hw_params,
  562. pa->adev[a].bits_per_sample == 8 ? SND_PCM_FORMAT_U8 : SND_PCM_FORMAT_S16_LE);
  563. if (err < 0) {
  564. text_color_set(DW_COLOR_ERROR);
  565. dw_printf ("Could not set bits per sample.\n%s\n",
  566. snd_strerror(err));
  567. dw_printf ("for %s %s.\n", devname, inout);
  568. return (-1);
  569. }
  570.  
  571. /* Number of audio channels. */
  572.  
  573.  
  574. err = snd_pcm_hw_params_set_channels (handle, hw_params, pa->adev[a].num_channels);
  575. if (err < 0) {
  576. text_color_set(DW_COLOR_ERROR);
  577. dw_printf ("Could not set number of audio channels.\n%s\n",
  578. snd_strerror(err));
  579. dw_printf ("for %s %s.\n", devname, inout);
  580. return (-1);
  581. }
  582.  
  583. /* Audio sample rate. */
  584.  
  585.  
  586. val = pa->adev[a].samples_per_sec;
  587.  
  588. dir = 0;
  589.  
  590.  
  591. err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &val, &dir);
  592. if (err < 0) {
  593. text_color_set(DW_COLOR_ERROR);
  594. dw_printf ("Could not set audio sample rate.\n%s\n",
  595. snd_strerror(err));
  596. dw_printf ("for %s %s.\n", devname, inout);
  597. return (-1);
  598. }
  599.  
  600. if (val != pa->adev[a].samples_per_sec) {
  601.  
  602. text_color_set(DW_COLOR_INFO);
  603. dw_printf ("Asked for %d samples/sec but got %d.\n",
  604.  
  605. pa->adev[a].samples_per_sec, val);
  606. dw_printf ("for %s %s.\n", devname, inout);
  607.  
  608. pa->adev[a].samples_per_sec = val;
  609.  
  610. }
  611.  
  612. /* Original: */
  613. /* Guessed around 20 reads/sec might be good. */
  614. /* Period too long = too much latency. */
  615. /* Period too short = more overhead of many small transfers. */
  616.  
  617. /* fpp = pa->adev[a].samples_per_sec / 20; */
  618.  
  619. /* The suggested period size was 2205 frames. */
  620. /* I thought the later "...set_period_size_near" might adjust it to be */
  621. /* some more optimal nearby value based hardware buffer sizes but */
  622. /* that didn't happen. We ended up with a buffer size of 4410 bytes. */
  623.  
  624. /* In version 1.2, let's take a different approach. */
  625. /* Reduce the latency and round up to a multiple of 1 Kbyte. */
  626.  
  627. /* For the typical case of 44100 sample rate, 1 channel, 16 bits, we calculate */
  628. /* a buffer size of 882 and round it up to 1k. This results in 512 frames per period. */
  629. /* A period comes out to be about 80 periods per second or about 12.5 mSec each. */
  630.  
  631. buf_size_in_bytes = calcbufsize(pa->adev[a].samples_per_sec, pa->adev[a].num_channels, pa->adev[a].bits_per_sample);
  632.  
  633. #if __arm__
  634. /* Ugly hack for RPi. */
  635. /* Reducing buffer size is fine for input but not so good for output. */
  636.  
  637. if (*inout == 'o') {
  638. buf_size_in_bytes = buf_size_in_bytes * 4;
  639. }
  640. #endif
  641.  
  642. fpp = buf_size_in_bytes / (pa->adev[a].num_channels * pa->adev[a].bits_per_sample / 8);
  643.  
  644. #if DEBUG
  645. text_color_set(DW_COLOR_DEBUG);
  646.  
  647. dw_printf ("suggest period size of %d frames\n", (int)fpp);
  648. #endif
  649. dir = 0;
  650. err = snd_pcm_hw_params_set_period_size_near (handle, hw_params, &fpp, &dir);
  651.  
  652. if (err < 0) {
  653. text_color_set(DW_COLOR_ERROR);
  654. dw_printf ("Could not set period size\n%s\n", snd_strerror(err));
  655. dw_printf ("for %s %s.\n", devname, inout);
  656. return (-1);
  657. }
  658.  
  659. err = snd_pcm_hw_params (handle, hw_params);
  660. if (err < 0) {
  661. text_color_set(DW_COLOR_ERROR);
  662. dw_printf ("Could not set hw params\n%s\n", snd_strerror(err));
  663. dw_printf ("for %s %s.\n", devname, inout);
  664. return (-1);
  665. }
  666.  
  667. /* Driver might not like our suggested period size */
  668. /* and might have another idea. */
  669.  
  670. err = snd_pcm_hw_params_get_period_size (hw_params, &fpp, NULL);
  671. if (err < 0) {
  672. text_color_set(DW_COLOR_ERROR);
  673. dw_printf ("Could not get audio period size.\n%s\n", snd_strerror(err));
  674. dw_printf ("for %s %s.\n", devname, inout);
  675. return (-1);
  676. }
  677.  
  678. snd_pcm_hw_params_free (hw_params);
  679.  
  680. /* A "frame" is one sample for all channels. */
  681.  
  682. /* The read and write use units of frames, not bytes. */
  683.  
  684. adev[a].bytes_per_frame = snd_pcm_frames_to_bytes (handle, 1);
  685.  
  686. assert (adev[a].bytes_per_frame == pa->adev[a].num_channels * pa->adev[a].bits_per_sample / 8);
  687.  
  688. buf_size_in_bytes = fpp * adev[a].bytes_per_frame;
  689.  
  690. #if DEBUG
  691. text_color_set(DW_COLOR_DEBUG);
  692. dw_printf ("audio buffer size = %d (bytes per frame) x %d (frames per period) = %d \n", adev[a].bytes_per_frame, (int)fpp, buf_size_in_bytes);
  693. #endif
  694.  
  695. /* Version 1.3 - after a report of this situation for Mac OSX version. */
  696. if (buf_size_in_bytes < 256 || buf_size_in_bytes > 32768) {
  697. text_color_set(DW_COLOR_ERROR);
  698. dw_printf ("Audio buffer has unexpected extreme size of %d bytes.\n", buf_size_in_bytes);
  699. dw_printf ("Detected at %s, line %d.\n", __FILE__, __LINE__);
  700. dw_printf ("This might be caused by unusual audio device configuration values.\n");
  701. buf_size_in_bytes = 2048;
  702. dw_printf ("Using %d to attempt recovery.\n", buf_size_in_bytes);
  703. }
  704.  
  705. return (buf_size_in_bytes);
  706.  
  707.  
  708. } /* end alsa_set_params */
  709.  
  710.  
  711. #elif USE_SNDIO
  712.  
  713. /*
  714. * Set parameters for sound card. (sndio)
  715. *
  716. * See /usr/include/sndio.h for details.
  717. */
  718.  
  719. static int set_sndio_params (int a, struct sio_hdl *handle, struct audio_s *pa, char *devname)
  720. {
  721.  
  722. struct sio_par q, r;
  723.  
  724. /* Signed 16bit little endian or unsigned 8 bit. */
  725. sio_initpar (&q);
  726. q.bits = pa->adev[a].bits_per_sample;
  727. q.bps = (q.bits + 7) / 8;
  728. q.sig = (q.bits == 8) ? 0 : 1;
  729. q.le = 1; /* always little endian */
  730. q.msb = 0; /* LSB aligned */
  731. q.rchan = q.pchan = pa->adev[a].num_channels;
  732. q.rate = pa->adev[a].samples_per_sec;
  733. q.xrun = SIO_IGNORE;
  734. q.appbufsz = calcbufsize(pa->adev[a].samples_per_sec, pa->adev[a].num_channels, pa->adev[a].bits_per_sample);
  735.  
  736.  
  737. #if DEBUG
  738. text_color_set(DW_COLOR_DEBUG);
  739. dw_printf ("suggest buffer size %d bytes\n", q.appbufsz);
  740. #endif
  741.  
  742. /* challenge new setting */
  743. if (!sio_setpar (handle, &q)) {
  744. text_color_set(DW_COLOR_ERROR);
  745. dw_printf ("Could not set hardware parameter.\n");
  746. dw_printf ("for %s.\n", devname);
  747. return (-1);
  748. }
  749.  
  750. /* get response */
  751. if (!sio_getpar (handle, &r)) {
  752. text_color_set(DW_COLOR_ERROR);
  753. dw_printf ("Could not obtain current hardware setting.\n");
  754. dw_printf ("for %s.\n", devname);
  755. return (-1);
  756. }
  757.  
  758. #if DEBUG
  759. text_color_set(DW_COLOR_DEBUG);
  760. dw_printf ("audio buffer size %d bytes\n", r.appbufsz);
  761. #endif
  762. if (q.rate != r.rate) {
  763. text_color_set(DW_COLOR_INFO);
  764. dw_printf ("Asked for %d samples/sec but got %d.\n",
  765. pa->adev[a].samples_per_sec, r.rate);
  766. dw_printf ("for %s.\n", devname);
  767. pa->adev[a].samples_per_sec = r.rate;
  768. }
  769.  
  770. /* not supported */
  771. if (q.bits != r.bits || q.bps != r.bps || q.sig != r.sig ||
  772. (q.bits > 8 && q.le != r.le) ||
  773. q.rchan != r.rchan || q.pchan != r.pchan) {
  774. text_color_set(DW_COLOR_ERROR);
  775. dw_printf ("Unsupported format.\n");
  776. dw_printf ("for %s.\n", devname);
  777. return (-1);
  778. }
  779.  
  780. return r.appbufsz;
  781.  
  782. } /* end set_sndio_params */
  783.  
  784. #else
  785.  
  786.  
  787. /*
  788. * Set parameters for sound card. (OSS only)
  789. *
  790. * See /usr/include/sys/soundcard.h for details.
  791. */
  792.  
  793. static int set_oss_params (int a, int fd, struct audio_s *pa)
  794. {
  795. int err;
  796. int devcaps;
  797. int asked_for;
  798. char message[100];
  799. int ossbuf_size_in_bytes;
  800.  
  801.  
  802. err = ioctl (fd, SNDCTL_DSP_CHANNELS, &(pa->adev[a].num_channels));
  803. if (err == -1) {
  804. text_color_set(DW_COLOR_ERROR);
  805. perror("Not able to set audio device number of channels");
  806. return (-1);
  807. }
  808.  
  809. asked_for = pa->adev[a].samples_per_sec;
  810.  
  811. err = ioctl (fd, SNDCTL_DSP_SPEED, &(pa->adev[a].samples_per_sec));
  812. if (err == -1) {
  813. text_color_set(DW_COLOR_ERROR);
  814. perror("Not able to set audio device sample rate");
  815. return (-1);
  816. }
  817.  
  818. if (pa->adev[a].samples_per_sec != asked_for) {
  819. text_color_set(DW_COLOR_INFO);
  820. dw_printf ("Asked for %d samples/sec but actually using %d.\n",
  821. asked_for, pa->adev[a].samples_per_sec);
  822. }
  823.  
  824. /* This is actually a bit mask but it happens that */
  825. /* 0x8 is unsigned 8 bit samples and */
  826. /* 0x10 is signed 16 bit little endian. */
  827.  
  828. err = ioctl (fd, SNDCTL_DSP_SETFMT, &(pa->adev[a].bits_per_sample));
  829. if (err == -1) {
  830. text_color_set(DW_COLOR_ERROR);
  831. perror("Not able to set audio device sample size");
  832. return (-1);
  833. }
  834.  
  835. /*
  836. * Determine capabilities.
  837. */
  838. err = ioctl (fd, SNDCTL_DSP_GETCAPS, &devcaps);
  839. if (err == -1) {
  840. text_color_set(DW_COLOR_ERROR);
  841. perror("Not able to get audio device capabilities");
  842. // Is this fatal? // return (-1);
  843. }
  844.  
  845. #if DEBUG
  846. text_color_set(DW_COLOR_DEBUG);
  847. dw_printf ("audio_open(): devcaps = %08x\n", devcaps);
  848. if (devcaps & DSP_CAP_DUPLEX) dw_printf ("Full duplex record/playback.\n");
  849. if (devcaps & DSP_CAP_BATCH) dw_printf ("Device has some kind of internal buffers which may cause delays.\n");
  850. if (devcaps & ~ (DSP_CAP_DUPLEX | DSP_CAP_BATCH)) dw_printf ("Others...\n");
  851. #endif
  852.  
  853. if (!(devcaps & DSP_CAP_DUPLEX)) {
  854. text_color_set(DW_COLOR_ERROR);
  855. dw_printf ("Audio device does not support full duplex\n");
  856. // Do we care? // return (-1);
  857. }
  858.  
  859. err = ioctl (fd, SNDCTL_DSP_SETDUPLEX, NULL);
  860. if (err == -1) {
  861. // text_color_set(DW_COLOR_ERROR);
  862. // perror("Not able to set audio full duplex mode");
  863. // Unfortunate but not a disaster.
  864. }
  865.  
  866. /*
  867. * Get preferred block size.
  868. * Presumably this will provide the most efficient transfer.
  869. *
  870. * In my particular situation, this turned out to be
  871. * 2816 for 11025 Hz 16 bit mono
  872. * 5568 for 11025 Hz 16 bit stereo
  873. * 11072 for 44100 Hz 16 bit mono
  874. *
  875. * This was long ago under different conditions.
  876. * Should study this again some day.
  877. *
  878. * Your milage may vary.
  879. */
  880. err = ioctl (fd, SNDCTL_DSP_GETBLKSIZE, &ossbuf_size_in_bytes);
  881. if (err == -1) {
  882. text_color_set(DW_COLOR_ERROR);
  883. perror("Not able to get audio block size");
  884. ossbuf_size_in_bytes = 2048; /* pick something reasonable */
  885. }
  886.  
  887. #if DEBUG
  888. text_color_set(DW_COLOR_DEBUG);
  889. dw_printf ("audio_open(): suggestd block size is %d\n", ossbuf_size_in_bytes);
  890. #endif
  891.  
  892. /*
  893. * That's 1/8 of a second which seems rather long if we want to
  894. * respond quickly.
  895. */
  896.  
  897. ossbuf_size_in_bytes = calcbufsize(pa->adev[a].samples_per_sec, pa->adev[a].num_channels, pa->adev[a].bits_per_sample);
  898.  
  899. #if DEBUG
  900. text_color_set(DW_COLOR_DEBUG);
  901. dw_printf ("audio_open(): using block size of %d\n", ossbuf_size_in_bytes);
  902. #endif
  903.  
  904. #if 0
  905. /* Original - dies without good explanation. */
  906. assert (ossbuf_size_in_bytes >= 256 && ossbuf_size_in_bytes <= 32768);
  907. #else
  908. /* Version 1.3 - after a report of this situation for Mac OSX version. */
  909. if (ossbuf_size_in_bytes < 256 || ossbuf_size_in_bytes > 32768) {
  910. text_color_set(DW_COLOR_ERROR);
  911. dw_printf ("Audio buffer has unexpected extreme size of %d bytes.\n", ossbuf_size_in_bytes);
  912. dw_printf ("Detected at %s, line %d.\n", __FILE__, __LINE__);
  913. dw_printf ("This might be caused by unusual audio device configuration values.\n");
  914. ossbuf_size_in_bytes = 2048;
  915. dw_printf ("Using %d to attempt recovery.\n", ossbuf_size_in_bytes);
  916. }
  917. #endif
  918. return (ossbuf_size_in_bytes);
  919.  
  920. } /* end set_oss_params */
  921.  
  922.  
  923. #endif
  924.  
  925.  
  926.  
  927. /*------------------------------------------------------------------
  928. *
  929. * Name: audio_get
  930. *
  931. * Purpose: Get one byte from the audio device.
  932. *
  933. * Inputs: a - Our number for audio device.
  934. *
  935. * Returns: 0 - 255 for a valid sample.
  936. * -1 for any type of error.
  937. *
  938. * Description: The caller must deal with the details of mono/stereo
  939. * and number of bytes per sample.
  940. *
  941. * This will wait if no data is currently available.
  942. *
  943. *----------------------------------------------------------------*/
  944.  
  945. // Use hot attribute for all functions called for every audio sample.
  946.  
  947. __attribute__((hot))
  948. int audio_get (int a)
  949. {
  950. int n;
  951. #if USE_ALSA
  952. int retries = 0;
  953. #endif
  954.  
  955. #if STATISTICS
  956. /* Gather numbers for read from audio device. */
  957.  
  958. #define duration 100 /* report every 100 seconds. */
  959. static time_t last_time[MAX_ADEVS];
  960. time_t this_time[MAX_ADEVS];
  961. static int sample_count[MAX_ADEVS];
  962. static int error_count[MAX_ADEVS];
  963. #endif
  964.  
  965. #if DEBUGx
  966. text_color_set(DW_COLOR_DEBUG);
  967.  
  968. dw_printf ("audio_get():\n");
  969.  
  970. #endif
  971.  
  972. assert (adev[a].inbuf_size_in_bytes >= 100 && adev[a].inbuf_size_in_bytes <= 32768);
  973.  
  974.  
  975.  
  976. switch (adev[a].g_audio_in_type) {
  977.  
  978. /*
  979. * Soundcard - ALSA
  980. */
  981. case AUDIO_IN_TYPE_SOUNDCARD:
  982.  
  983.  
  984. #if USE_ALSA
  985.  
  986.  
  987. while (adev[a].inbuf_next >= adev[a].inbuf_len) {
  988.  
  989. assert (adev[a].audio_in_handle != NULL);
  990. #if DEBUGx
  991. text_color_set(DW_COLOR_DEBUG);
  992. dw_printf ("audio_get(): readi asking for %d frames\n", adev[a].inbuf_size_in_bytes / adev[a].bytes_per_frame);
  993. #endif
  994. n = snd_pcm_readi (adev[a].audio_in_handle, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes / adev[a].bytes_per_frame);
  995.  
  996. #if DEBUGx
  997. text_color_set(DW_COLOR_DEBUG);
  998. dw_printf ("audio_get(): readi asked for %d and got %d frames\n",
  999. adev[a].inbuf_size_in_bytes / adev[a].bytes_per_frame, n);
  1000. #endif
  1001.  
  1002.  
  1003. if (n > 0) {
  1004.  
  1005. /* Success */
  1006.  
  1007. adev[a].inbuf_len = n * adev[a].bytes_per_frame; /* convert to number of bytes */
  1008. adev[a].inbuf_next = 0;
  1009.  
  1010. audio_stats (a,
  1011. save_audio_config_p->adev[a].num_channels,
  1012. n,
  1013. save_audio_config_p->statistics_interval);
  1014.  
  1015. }
  1016. else if (n == 0) {
  1017.  
  1018. /* Didn't expect this, but it's not a problem. */
  1019. /* Wait a little while and try again. */
  1020.  
  1021. text_color_set(DW_COLOR_ERROR);
  1022. dw_printf ("Audio input got zero bytes: %s\n", snd_strerror(n));
  1023. SLEEP_MS(10);
  1024.  
  1025. adev[a].inbuf_len = 0;
  1026. adev[a].inbuf_next = 0;
  1027. }
  1028. else {
  1029. /* Error */
  1030. // TODO: Needs more study and testing.
  1031.  
  1032. // Only expected error conditions:
  1033. // -EBADFD PCM is not in the right state (SND_PCM_STATE_PREPARED or SND_PCM_STATE_RUNNING)
  1034. // -EPIPE an overrun occurred
  1035. // -ESTRPIPE a suspend event occurred (stream is suspended and waiting for an application recovery)
  1036.  
  1037. // Data overrun is displayed as "broken pipe" which seems a little misleading.
  1038. // Add our own message which says something about CPU being too slow.
  1039.  
  1040. text_color_set(DW_COLOR_ERROR);
  1041. dw_printf ("Audio input device %d error code %d: %s\n", a, n, snd_strerror(n));
  1042.  
  1043. if (n == (-EPIPE)) {
  1044. dw_printf ("This is most likely caused by the CPU being too slow to keep up with the audio stream.\n");
  1045. dw_printf ("Use the \"top\" command, in another command window, to look at CPU usage.\n");
  1046. dw_printf ("This might be a temporary condition so we will attempt to recover a few times before giving up.\n");
  1047. }
  1048.  
  1049. audio_stats (a,
  1050. save_audio_config_p->adev[a].num_channels,
  1051. 0,
  1052. save_audio_config_p->statistics_interval);
  1053.  
  1054. /* Try to recover a few times and eventually give up. */
  1055. if (++retries > 10) {
  1056. adev[a].inbuf_len = 0;
  1057. adev[a].inbuf_next = 0;
  1058. return (-1);
  1059. }
  1060.  
  1061. if (n == -EPIPE) {
  1062.  
  1063. /* EPIPE means overrun */
  1064.  
  1065. snd_pcm_recover (adev[a].audio_in_handle, n, 1);
  1066.  
  1067. }
  1068. else {
  1069. /* Could be some temporary condition. */
  1070. /* Wait a little then try again. */
  1071. /* Sometimes I get "Resource temporarily available" */
  1072. /* when the Update Manager decides to run. */
  1073.  
  1074. SLEEP_MS (250);
  1075. snd_pcm_recover (adev[a].audio_in_handle, n, 1);
  1076. }
  1077. }
  1078. }
  1079.  
  1080.  
  1081. #elif USE_SNDIO
  1082.  
  1083. while (adev[a].inbuf_next >= adev[a].inbuf_len) {
  1084.  
  1085. assert (adev[a].sndio_handle != NULL);
  1086. n = sio_read (adev[a].sndio_handle, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes);
  1087. adev[a].inbuf_len = n;
  1088. adev[a].inbuf_next = 0;
  1089.  
  1090. audio_stats (a,
  1091. save_audio_config_p->adev[a].num_channels,
  1092. n / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
  1093. save_audio_config_p->statistics_interval);
  1094. }
  1095.  
  1096. #else /* end ALSA, begin OSS */
  1097.  
  1098. /* Fixed in 1.2. This was formerly outside of the switch */
  1099. /* so the OSS version did not process stdin or UDP. */
  1100.  
  1101. while (adev[a].g_audio_in_type == AUDIO_IN_TYPE_SOUNDCARD && adev[a].inbuf_next >= adev[a].inbuf_len) {
  1102. assert (adev[a].oss_audio_device_fd > 0);
  1103. n = read (adev[a].oss_audio_device_fd, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes);
  1104. //text_color_set(DW_COLOR_DEBUG);
  1105. // dw_printf ("audio_get(): read %d returns %d\n", adev[a].inbuf_size_in_bytes, n);
  1106. if (n < 0) {
  1107. text_color_set(DW_COLOR_ERROR);
  1108. perror("Can't read from audio device");
  1109. adev[a].inbuf_len = 0;
  1110. adev[a].inbuf_next = 0;
  1111.  
  1112. audio_stats (a,
  1113. save_audio_config_p->adev[a].num_channels,
  1114. 0,
  1115. save_audio_config_p->statistics_interval);
  1116.  
  1117. return (-1);
  1118. }
  1119. adev[a].inbuf_len = n;
  1120. adev[a].inbuf_next = 0;
  1121.  
  1122. audio_stats (a,
  1123. save_audio_config_p->adev[a].num_channels,
  1124. n / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
  1125. save_audio_config_p->statistics_interval);
  1126. }
  1127.  
  1128. #endif /* USE_ALSA */
  1129.  
  1130.  
  1131. break;
  1132.  
  1133. /*
  1134. * UDP.
  1135. */
  1136.  
  1137. case AUDIO_IN_TYPE_SDR_UDP:
  1138.  
  1139. while (adev[a].inbuf_next >= adev[a].inbuf_len) {
  1140. int res;
  1141.  
  1142. assert (adev[a].udp_sock > 0);
  1143. res = recv(adev[a].udp_sock, adev[a].inbuf_ptr, adev[a].inbuf_size_in_bytes, 0);
  1144. if (res < 0) {
  1145. text_color_set(DW_COLOR_ERROR);
  1146. dw_printf ("Can't read from udp socket, res=%d", res);
  1147. adev[a].inbuf_len = 0;
  1148. adev[a].inbuf_next = 0;
  1149.  
  1150. audio_stats (a,
  1151. save_audio_config_p->adev[a].num_channels,
  1152. 0,
  1153. save_audio_config_p->statistics_interval);
  1154.  
  1155. return (-1);
  1156. }
  1157.  
  1158. adev[a].inbuf_len = res;
  1159. adev[a].inbuf_next = 0;
  1160.  
  1161. audio_stats (a,
  1162. save_audio_config_p->adev[a].num_channels,
  1163. res / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
  1164. save_audio_config_p->statistics_interval);
  1165.  
  1166. }
  1167. break;
  1168.  
  1169. /*
  1170. * stdin.
  1171. */
  1172. case AUDIO_IN_TYPE_STDIN:
  1173.  
  1174. while (adev[a].inbuf_next >= adev[a].inbuf_len) {
  1175. //int ch, res,i;
  1176. int res;
  1177.  
  1178. res = read(STDIN_FILENO, adev[a].inbuf_ptr, (size_t)adev[a].inbuf_size_in_bytes);
  1179. if (res <= 0) {
  1180. text_color_set(DW_COLOR_INFO);
  1181. dw_printf ("\nEnd of file on stdin. Exiting.\n");
  1182. exit (0);
  1183. }
  1184.  
  1185. audio_stats (a,
  1186. save_audio_config_p->adev[a].num_channels,
  1187. res / (save_audio_config_p->adev[a].num_channels * save_audio_config_p->adev[a].bits_per_sample / 8),
  1188. save_audio_config_p->statistics_interval);
  1189.  
  1190. adev[a].inbuf_len = res;
  1191. adev[a].inbuf_next = 0;
  1192. }
  1193.  
  1194. break;
  1195. }
  1196.  
  1197.  
  1198. if (adev[a].inbuf_next < adev[a].inbuf_len)
  1199. n = adev[a].inbuf_ptr[adev[a].inbuf_next++];
  1200. //No data to read, avoid reading outside buffer
  1201. else
  1202. n = 0;
  1203.  
  1204. #if DEBUGx
  1205.  
  1206. text_color_set(DW_COLOR_DEBUG);
  1207. dw_printf ("audio_get(): returns %d\n", n);
  1208.  
  1209. #endif
  1210.  
  1211.  
  1212. return (n);
  1213.  
  1214. } /* end audio_get */
  1215.  
  1216.  
  1217. /*------------------------------------------------------------------
  1218. *
  1219. * Name: audio_put
  1220. *
  1221. * Purpose: Send one byte to the audio device.
  1222. *
  1223. * Inputs: a
  1224. *
  1225. * c - One byte in range of 0 - 255.
  1226. *
  1227. * Returns: Normally non-negative.
  1228. * -1 for any type of error.
  1229. *
  1230. * Description: The caller must deal with the details of mono/stereo
  1231. * and number of bytes per sample.
  1232. *
  1233. * See Also: audio_flush
  1234. * audio_wait
  1235. *
  1236. *----------------------------------------------------------------*/
  1237.  
  1238. int audio_put (int a, int c)
  1239. {
  1240. /* Should never be full at this point. */
  1241. assert (adev[a].outbuf_len < adev[a].outbuf_size_in_bytes);
  1242.  
  1243. adev[a].outbuf_ptr[adev[a].outbuf_len++] = c;
  1244.  
  1245. if (adev[a].outbuf_len == adev[a].outbuf_size_in_bytes) {
  1246. return (audio_flush(a));
  1247. }
  1248.  
  1249. return (0);
  1250.  
  1251. } /* end audio_put */
  1252.  
  1253.  
  1254. /*------------------------------------------------------------------
  1255. *
  1256. * Name: audio_flush
  1257. *
  1258. * Purpose: Push out any partially filled output buffer.
  1259. *
  1260. * Returns: Normally non-negative.
  1261. * -1 for any type of error.
  1262. *
  1263. * See Also: audio_flush
  1264. * audio_wait
  1265. *
  1266. *----------------------------------------------------------------*/
  1267.  
  1268. int audio_flush (int a)
  1269. {
  1270. #if USE_ALSA
  1271. int k;
  1272. unsigned char *psound;
  1273. int retries = 10;
  1274. snd_pcm_status_t *status;
  1275.  
  1276. assert (adev[a].audio_out_handle != NULL);
  1277.  
  1278.  
  1279. /*
  1280. * Trying to set the automatic start threshold didn't have the desired
  1281. * effect. After the first transmitted packet, they are saved up
  1282. * for a few minutes and then all come out together.
  1283. *
  1284. * "Prepare" it if not already in the running state.
  1285. * We stop it at the end of each transmitted packet.
  1286. */
  1287.  
  1288.  
  1289. snd_pcm_status_alloca(&status);
  1290.  
  1291. k = snd_pcm_status (adev[a].audio_out_handle, status);
  1292. if (k != 0) {
  1293. text_color_set(DW_COLOR_ERROR);
  1294. dw_printf ("Audio output get status error.\n%s\n", snd_strerror(k));
  1295. }
  1296.  
  1297. if ((k = snd_pcm_status_get_state(status)) != SND_PCM_STATE_RUNNING) {
  1298.  
  1299. //text_color_set(DW_COLOR_DEBUG);
  1300. //dw_printf ("Audio output state = %d. Try to start.\n", k);
  1301.  
  1302. k = snd_pcm_prepare (adev[a].audio_out_handle);
  1303.  
  1304. if (k != 0) {
  1305. text_color_set(DW_COLOR_ERROR);
  1306. dw_printf ("Audio output start error.\n%s\n", snd_strerror(k));
  1307. }
  1308. }
  1309.  
  1310.  
  1311. psound = adev[a].outbuf_ptr;
  1312.  
  1313. while (retries-- > 0) {
  1314.  
  1315. k = snd_pcm_writei (adev[a].audio_out_handle, psound, adev[a].outbuf_len / adev[a].bytes_per_frame);
  1316. #if DEBUGx
  1317. text_color_set(DW_COLOR_DEBUG);
  1318. dw_printf ("audio_flush(): snd_pcm_writei %d frames returns %d\n",
  1319. adev[a].outbuf_len / adev[a].bytes_per_frame, k);
  1320. fflush (stdout);
  1321. #endif
  1322. if (k == -EPIPE) {
  1323. text_color_set(DW_COLOR_ERROR);
  1324. dw_printf ("Audio output data underrun.\n");
  1325.  
  1326. /* No problemo. Recover and go around again. */
  1327.  
  1328. snd_pcm_recover (adev[a].audio_out_handle, k, 1);
  1329. }
  1330. else if (k == -ESTRPIPE) {
  1331. text_color_set(DW_COLOR_ERROR);
  1332. dw_printf ("Driver suspended, recovering\n");
  1333. snd_pcm_recover(adev[a].audio_out_handle, k, 1);
  1334. }
  1335. else if (k == -EBADFD) {
  1336. k = snd_pcm_prepare (adev[a].audio_out_handle);
  1337. if(k < 0) {
  1338. dw_printf ("Error preparing after bad state: %s\n", snd_strerror(k));
  1339. }
  1340. }
  1341. else if (k < 0) {
  1342. text_color_set(DW_COLOR_ERROR);
  1343. dw_printf ("Audio write error: %s\n", snd_strerror(k));
  1344.  
  1345. /* Some other error condition. */
  1346. /* Try again. What do we have to lose? */
  1347.  
  1348. k = snd_pcm_prepare (adev[a].audio_out_handle);
  1349. if(k < 0) {
  1350. dw_printf ("Error preparing after error: %s\n", snd_strerror(k));
  1351. }
  1352. }
  1353. else if (k != adev[a].outbuf_len / adev[a].bytes_per_frame) {
  1354. text_color_set(DW_COLOR_ERROR);
  1355. dw_printf ("Audio write took %d frames rather than %d.\n",
  1356. k, adev[a].outbuf_len / adev[a].bytes_per_frame);
  1357.  
  1358. /* Go around again with the rest of it. */
  1359.  
  1360. psound += k * adev[a].bytes_per_frame;
  1361. adev[a].outbuf_len -= k * adev[a].bytes_per_frame;
  1362. }
  1363. else {
  1364. /* Success! */
  1365. adev[a].outbuf_len = 0;
  1366. return (0);
  1367. }
  1368. }
  1369.  
  1370. text_color_set(DW_COLOR_ERROR);
  1371. dw_printf ("Audio write error retry count exceeded.\n");
  1372.  
  1373. adev[a].outbuf_len = 0;
  1374. return (-1);
  1375.  
  1376. #elif USE_SNDIO
  1377.  
  1378. int k;
  1379. unsigned char *ptr;
  1380. int len;
  1381.  
  1382. ptr = adev[a].outbuf_ptr;
  1383. len = adev[a].outbuf_len;
  1384.  
  1385. while (len > 0) {
  1386. assert (adev[a].sndio_handle != NULL);
  1387. k = sio_write (adev[a].sndio_handle, ptr, len);
  1388. #if DEBUGx
  1389. text_color_set(DW_COLOR_DEBUG);
  1390. dw_printf ("audio_flush(): write %d returns %d\n", len, k);
  1391. fflush (stdout);
  1392. #endif
  1393. ptr += k;
  1394. len -= k;
  1395. }
  1396.  
  1397. adev[a].outbuf_len = 0;
  1398. return (0);
  1399.  
  1400. #else /* OSS */
  1401.  
  1402. int k;
  1403. unsigned char *ptr;
  1404. int len;
  1405.  
  1406. ptr = adev[a].outbuf_ptr;
  1407. len = adev[a].outbuf_len;
  1408.  
  1409. while (len > 0) {
  1410. assert (adev[a].oss_audio_device_fd > 0);
  1411. k = write (adev[a].oss_audio_device_fd, ptr, len);
  1412. #if DEBUGx
  1413. text_color_set(DW_COLOR_DEBUG);
  1414. dw_printf ("audio_flush(): write %d returns %d\n", len, k);
  1415. fflush (stdout);
  1416. #endif
  1417. if (k < 0) {
  1418. text_color_set(DW_COLOR_ERROR);
  1419. perror("Can't write to audio device");
  1420. adev[a].outbuf_len = 0;
  1421. return (-1);
  1422. }
  1423. if (k < len) {
  1424. /* presumably full but didn't block. */
  1425. usleep (10000);
  1426. }
  1427. ptr += k;
  1428. len -= k;
  1429. }
  1430.  
  1431. adev[a].outbuf_len = 0;
  1432. return (0);
  1433. #endif
  1434.  
  1435. } /* end audio_flush */
  1436.  
  1437.  
  1438. /*------------------------------------------------------------------
  1439. *
  1440. * Name: audio_wait
  1441. *
  1442. * Purpose: Finish up audio output before turning PTT off.
  1443. *
  1444. * Inputs: a - Index for audio device (not channel!)
  1445. *
  1446. * Returns: None.
  1447. *
  1448. * Description: Flush out any partially filled audio output buffer.
  1449. * Wait until all the queued up audio out has been played.
  1450. * Take any other necessary actions to stop audio output.
  1451. *
  1452. * In an ideal world:
  1453. *
  1454. * We would like to ask the hardware when all the queued
  1455. * up sound has actually come out the speaker.
  1456. *
  1457. * In reality:
  1458. *
  1459. * This has been found to be less than reliable in practice.
  1460. *
  1461. * Caller does the following:
  1462. *
  1463. * (1) Make note of when PTT is turned on.
  1464. * (2) Calculate how long it will take to transmit the
  1465. * frame including TXDELAY, frame (including
  1466. * "flags", data, FCS and bit stuffing), and TXTAIL.
  1467. * (3) Call this function, which might or might not wait long enough.
  1468. * (4) Add (1) and (2) resulting in when PTT should be turned off.
  1469. * (5) Take difference between current time and desired PPT off time
  1470. * and wait for additoinal time if required.
  1471. *
  1472. *----------------------------------------------------------------*/
  1473.  
  1474. void audio_wait (int a)
  1475. {
  1476.  
  1477. audio_flush (a);
  1478.  
  1479. #if USE_ALSA
  1480.  
  1481. /* For playback, this should wait for all pending frames */
  1482. /* to be played and then stop. */
  1483.  
  1484. snd_pcm_drain (adev[a].audio_out_handle);
  1485.  
  1486. /*
  1487. * When this was first implemented, I observed:
  1488. *
  1489. * "Experimentation reveals that snd_pcm_drain doesn't
  1490. * actually wait. It returns immediately.
  1491. * However it does serve a useful purpose of stopping
  1492. * the playback after all the queued up data is used."
  1493. *
  1494. *
  1495. * Now that I take a closer look at the transmit timing, for
  1496. * version 1.2, it seems that snd_pcm_drain DOES wait until all
  1497. * all pending frames have been played.
  1498. * Either way, the caller will now compensate for it.
  1499. */
  1500.  
  1501. #elif USE_SNDIO
  1502.  
  1503. struct pollfd *pfds;
  1504. int nfds, revents;
  1505.  
  1506. nfds = sio_nfds (adev[a].sndio_handle);
  1507. pfds = alloca (nfds * sizeof(struct pollfd));
  1508.  
  1509. do {
  1510. nfds = sio_pollfd (adev[a].sndio_handle, pfds, POLLOUT);
  1511. if (nfds < 1) {
  1512. /* no need to wait */
  1513. break;
  1514. }
  1515. if (poll (pfds, nfds, -1) < 0) {
  1516. text_color_set(DW_COLOR_ERROR);
  1517. dw_printf ("poll %d\n", errno);
  1518. break;
  1519. }
  1520. revents = sio_revents(adev[a].sndio_handle, pfds);
  1521. } while (!(revents & (POLLHUP | POLLOUT)));
  1522.  
  1523. #else
  1524.  
  1525. assert (adev[a].oss_audio_device_fd > 0);
  1526.  
  1527. // This caused a crash later on Cygwin.
  1528. // Haven't tried it on other (non-Linux) Unix yet.
  1529.  
  1530. // err = ioctl (adev[a].oss_audio_device_fd, SNDCTL_DSP_SYNC, NULL);
  1531.  
  1532. #endif
  1533.  
  1534. #if DEBUG
  1535. text_color_set(DW_COLOR_DEBUG);
  1536. dw_printf ("audio_wait(): after sync, status=%d\n", err);
  1537. #endif
  1538.  
  1539. } /* end audio_wait */
  1540.  
  1541.  
  1542. /*------------------------------------------------------------------
  1543. *
  1544. * Name: audio_close
  1545. *
  1546. * Purpose: Close the audio device(s).
  1547. *
  1548. * Returns: Normally non-negative.
  1549. * -1 for any type of error.
  1550. *
  1551. *
  1552. *----------------------------------------------------------------*/
  1553.  
  1554. int audio_close (void)
  1555. {
  1556. int err = 0;
  1557. int a;
  1558.  
  1559. for (a = 0; a < MAX_ADEVS; a++) {
  1560.  
  1561. #if USE_ALSA
  1562. if (adev[a].audio_in_handle != NULL && adev[a].audio_out_handle != NULL) {
  1563.  
  1564. audio_wait (a);
  1565.  
  1566. snd_pcm_close (adev[a].audio_in_handle);
  1567. snd_pcm_close (adev[a].audio_out_handle);
  1568.  
  1569. adev[a].audio_in_handle = adev[a].audio_out_handle = NULL;
  1570.  
  1571. #elif USE_SNDIO
  1572. if (adev[a].sndio_handle != NULL) {
  1573.  
  1574. audio_wait (a);
  1575.  
  1576. sio_stop (adev[a].sndio_handle);
  1577. sio_close (adev[a].sndio_handle);
  1578.  
  1579. adev[a].sndio_handle = NULL;
  1580.  
  1581. #else
  1582.  
  1583. if (adev[a].oss_audio_device_fd > 0) {
  1584.  
  1585. audio_wait (a);
  1586.  
  1587. close (adev[a].oss_audio_device_fd);
  1588.  
  1589. adev[a].oss_audio_device_fd = -1;
  1590. #endif
  1591.  
  1592. free (adev[a].inbuf_ptr);
  1593. free (adev[a].outbuf_ptr);
  1594.  
  1595. adev[a].inbuf_size_in_bytes = 0;
  1596. adev[a].inbuf_ptr = NULL;
  1597. adev[a].inbuf_len = 0;
  1598. adev[a].inbuf_next = 0;
  1599.  
  1600. adev[a].outbuf_size_in_bytes = 0;
  1601. adev[a].outbuf_ptr = NULL;
  1602. adev[a].outbuf_len = 0;
  1603. }
  1604. }
  1605.  
  1606. return (err);
  1607.  
  1608. } /* end audio_close */
  1609.  
  1610.  
  1611. /* end audio.c */
  1612.  
  1613.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement