1 /* $Id$ */
2 /*
3 * Copyright (c) 2013 Dimitri Sokolyuk <demon@dim13.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <assert.h>
19 #include <err.h>
20 #include <sndio.h>
21 #include <stdlib.h>
22
23 #include "sio.h"
24
25 #define STEREO 2
26 #define BITS 16
27 #define SIGNED 1
28 #define FPS 25
29
30 static struct sio_hdl *hdl;
31 static struct sio_par par;
32 static int16_t *buffer;
33 static unsigned int samples;
34
35 struct data {
36 int16_t left;
37 int16_t right;
38 };
39
40 int
init_sio(void)41 init_sio(void)
42 {
43 hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
44 if (!hdl)
45 errx(1, "cannot connect to sound server, is it running?");
46
47 sio_initpar(&par);
48
49 par.rchan = STEREO;
50 par.bits = BITS;
51 par.le = SIO_LE_NATIVE;
52 par.sig = SIGNED;
53
54 if (!sio_setpar(hdl, &par))
55 errx(1, "SIO set params failed");
56 if (!sio_getpar(hdl, &par))
57 errx(1, "SIO get params failed");
58
59 if (par.rchan != STEREO ||
60 par.bits != BITS ||
61 par.le != SIO_LE_NATIVE ||
62 par.sig != SIGNED)
63 errx(1, "unsupported audio params");
64
65 samples = par.rate / FPS;
66 samples -= samples % par.round - par.round;
67 buffer = calloc(samples * par.rchan, sizeof(int16_t));
68 assert(buffer);
69
70 return sio_start(hdl);
71 }
72
73 unsigned int
max_samples_sio(void)74 max_samples_sio(void)
75 {
76 /*
77 * maximal number of samples we're willing to provide
78 * with 1920 at 25 fps and 48000 Hz or
79 * with 1764 at 25 fps and 44100 Hz it shall fit on most screens
80 */
81 return samples;
82 }
83
84 void
read_sio(double * left,double * right,size_t n)85 read_sio(double *left, double *right, size_t n)
86 {
87 int done, i;
88 char *p = (char *)buffer;
89 size_t bufsz = samples * par.rchan * sizeof(int16_t);
90 size_t rndsz = n * par.rchan * sizeof(int16_t);
91 struct data *data;
92
93 if (rndsz > bufsz)
94 rndsz = bufsz;
95
96 for (done = 0; bufsz > 0; p += done, bufsz -= done) {
97 done = sio_read(hdl, p, bufsz);
98 if (sio_eof(hdl))
99 errx(1, "SIO EOF");
100 }
101
102 /*
103 * return a pointer to the latest ROUND samples (the most recent
104 * ones) to minimize latency between picture and sound
105 */
106 data = (struct data *)(p - rndsz);
107
108 for (i = 0; i < n; i++) {
109 left[i] = data[i].left;
110 right[i] = data[i].right;
111 }
112 }
113
114 void
free_sio(void)115 free_sio(void)
116 {
117 sio_stop(hdl);
118 sio_close(hdl);
119 free(buffer);
120 }
121