Advertisement
uaa

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

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