1 /* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
2 * Winfried Ritsch, Karl MacMillan, and others.
3 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
4 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
6 /* this file inputs and outputs audio using the ALSA API available on linux. */
8 #include <alsa/asoundlib.h>
17 #include <sys/types.h>
20 #include <sys/ioctl.h>
25 typedef int16_t t_alsa_sample16
;
26 typedef int32_t t_alsa_sample32
;
27 #define ALSA_SAMPLEWIDTH_16 sizeof(t_alsa_sample16)
28 #define ALSA_SAMPLEWIDTH_32 sizeof(t_alsa_sample32)
29 #define ALSA_XFERSIZE16 (signed int)(sizeof(t_alsa_sample16) * DEFDACBLKSIZE)
30 #define ALSA_XFERSIZE32 (signed int)(sizeof(t_alsa_sample32) * DEFDACBLKSIZE)
32 #define ALSA_JITTER 1024
33 #define ALSA_EXTRABUFFER 2048
34 #define ALSA_DEFFRAGSIZE 64
35 #define ALSA_DEFNFRAG 12
38 #define INT32_MAX 0x7fffffff
41 #if (SND_LIB_MAJOR < 1)
45 typedef struct _alsa_dev
49 int innoninterleave
; /* true if we're set for noninterleaved read */
50 int outnoninterleave
; /* same for write */
53 t_alsa_dev alsa_device
;
54 static void *alsa_snd_buf
= 0;
55 static void **alsa_buf_ptrs
;
56 static int alsa_samplewidth
;
57 static snd_pcm_status_t
* in_status
;
58 static snd_pcm_status_t
* out_status
;
61 static int alsa_buf_samps
; /* believed actual ALSA bufsize in sample frames */
62 static int alsa_inchannels
;
63 static int alsa_outchannels
;
67 #define DEBUG2(x) {x;}
69 static void alsa_checkiosync( void);
70 static void alsa_numbertoname(int devno
, char *devname
, int nchar
);
72 /* don't assume we can turn all 31 bits when doing float-to-fix;
73 otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
74 #define FMAX 0x7ffff000
75 #define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))
77 /* support for ALSA pcmv2 api by Karl MacMillan<karlmac@peabody.jhu.edu> */
79 static void check_error(int err
, const char *why
)
82 fprintf(stderr
, "%s: %s\n", why
, snd_strerror(err
));
85 /* was: alsa_open_audio(int wantinchans, int wantoutchans, int srate) */
87 int alsa_open_audio(int naudioindev
, int *audioindev
, int nchindev
,
88 int *chindev
, int naudiooutdev
, int *audiooutdev
, int nchoutdev
,
89 int *choutdev
, int rate
)
91 int err
, inchans
= 0, outchans
= 0, subunitdir
;
93 snd_pcm_hw_params_t
* hw_params
;
94 snd_pcm_sw_params_t
* sw_params
;
96 int frag_size
= (sys_blocksize
? sys_blocksize
: ALSA_DEFFRAGSIZE
);
99 unsigned int tmp_uint
;
100 snd_pcm_uframes_t tmp_snd_pcm_uframes
;
101 int wantinchans
, wantoutchans
, devno
;
103 if (naudioindev
>= 2 || naudiooutdev
>= 2)
104 post("alsa: only one input and output device allowed (extras ignored");
105 if (naudioindev
>= 1 && naudiooutdev
>= 1 &&
106 audioindev
[0] != audiooutdev
[0])
107 post("alsa: changing output device to agree with input device");
109 wantinchans
= chindev
[0];
110 else wantinchans
= (naudioindev
? 2 : 0);
112 wantoutchans
= choutdev
[0];
113 else wantoutchans
= (naudiooutdev
? 2 : 0);
114 devno
= (naudioindev
> 0 ? audioindev
[0] :
115 (naudiooutdev
> 0 ? audiooutdev
[0] : 0));
117 alsa_numbertoname(devno
, devname
, 512);
120 post("device name %s; channels in %d, out %d", devname
, wantinchans
,
123 nfrags
= sys_schedadvance
* (float)rate
/ (1e6
* frag_size
);
124 /* save our belief as to ALSA's buffer size for later */
125 alsa_buf_samps
= nfrags
* frag_size
;
128 post("audio buffer set to %d", (int)(0.001 * sys_schedadvance
));
130 alsa_device
.innoninterleave
= alsa_device
.outnoninterleave
= 0;
133 err
= snd_pcm_open(&alsa_device
.inhandle
, devname
,
134 SND_PCM_STREAM_CAPTURE
, SND_PCM_NONBLOCK
);
136 check_error(err
, "snd_pcm_open (input)");
141 inchans
= wantinchans
;
142 snd_pcm_nonblock(alsa_device
.inhandle
, 1);
147 err
= snd_pcm_open(&alsa_device
.outhandle
, devname
,
148 SND_PCM_STREAM_PLAYBACK
, SND_PCM_NONBLOCK
);
150 check_error(err
, "snd_pcm_open (output)");
155 outchans
= wantoutchans
;
156 snd_pcm_nonblock(alsa_device
.outhandle
, 1);
162 post("opening sound input...");
163 err
= snd_pcm_hw_params_malloc(&hw_params
);
164 check_error(err
, "snd_pcm_hw_params_malloc (input)");
166 // get the default params
167 err
= snd_pcm_hw_params_any(alsa_device
.inhandle
, hw_params
);
168 check_error(err
, "snd_pcm_hw_params_any (input)");
170 /* try to set interleaved access */
171 err
= snd_pcm_hw_params_set_access(alsa_device
.inhandle
,
172 hw_params
, SND_PCM_ACCESS_RW_INTERLEAVED
);
175 /* OK, so try non-interleaved */
176 err
= snd_pcm_hw_params_set_access(alsa_device
.inhandle
,
177 hw_params
, SND_PCM_ACCESS_RW_NONINTERLEAVED
);
180 post("using non-interleaved audio input");
181 alsa_device
.innoninterleave
= 1;
184 check_error(err
, "snd_pcm_hw_params_set_access (input)");
185 // Try to set 32 bit format first
186 err
= snd_pcm_hw_params_set_format(alsa_device
.inhandle
, hw_params
,
191 "PD-ALSA: 32 bit format not available - using 16\n"); */
192 err
= snd_pcm_hw_params_set_format(alsa_device
.inhandle
, hw_params
,
194 check_error(err
, "snd_pcm_hw_params_set_format (input)");
195 alsa_samplewidth
= 2;
199 alsa_samplewidth
= 4;
201 post("Sample width set to %d bytes", alsa_samplewidth
);
203 err
= snd_pcm_hw_params_set_subformat(alsa_device
.inhandle
, hw_params
,
204 SND_PCM_SUBFORMAT_STD
);
205 check_error(err
, "snd_pcm_hw_params_set_subformat (input)");
206 // set the number of channels
208 err
= snd_pcm_hw_params_set_channels_min(alsa_device
.inhandle
,
209 hw_params
, &tmp_uint
);
210 check_error(err
, "snd_pcm_hw_params_set_channels (input)");
211 if (tmp_uint
!= (unsigned)inchans
)
212 post("ALSA: set input channels to %d", tmp_uint
);
214 // set the sampling rate
215 err
= snd_pcm_hw_params_set_rate_min(alsa_device
.inhandle
, hw_params
,
217 check_error(err
, "snd_pcm_hw_params_set_rate_min (input)");
219 err
= snd_pcm_hw_params_get_rate(hw_params
, &subunitdir
);
220 post("input sample rate %d", err
);
222 // set the period - ie frag size
223 // post("fragsize a %d", frag_size);
225 /* LATER try this to get a recommended period size...
226 right now, it trips an assertion failure in ALSA lib */
228 post("input period was %d, min %d, max %d\n",
229 snd_pcm_hw_params_get_period_size(hw_params
, 0),
230 snd_pcm_hw_params_get_period_size_min(hw_params
, 0),
231 snd_pcm_hw_params_get_period_size_max(hw_params
, 0));
234 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.inhandle
,
239 tmp_snd_pcm_uframes
= frag_size
;
240 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.inhandle
,
241 hw_params
, &tmp_snd_pcm_uframes
, 0);
243 check_error(err
, "snd_pcm_hw_params_set_period_size_near (input)");
244 // post("fragsize b %d", frag_size);
245 // set the number of periods - ie numfrags
246 // post("nfrags a %d", nfrags);
248 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.inhandle
,
249 hw_params
, nfrags
, 0);
252 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.inhandle
,
253 hw_params
, &tmp_uint
, 0);
255 check_error(err
, "snd_pcm_hw_params_set_periods_near (input)");
256 // set the buffer size
258 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.inhandle
,
259 hw_params
, nfrags
* frag_size
);
261 tmp_snd_pcm_uframes
= nfrags
* frag_size
;
262 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.inhandle
,
263 hw_params
, &tmp_snd_pcm_uframes
);
265 check_error(err
, "snd_pcm_hw_params_set_buffer_size_near (input)");
267 err
= snd_pcm_hw_params(alsa_device
.inhandle
, hw_params
);
268 check_error(err
, "snd_pcm_hw_params (input)");
270 snd_pcm_hw_params_free(hw_params
);
272 err
= snd_pcm_sw_params_malloc(&sw_params
);
273 check_error(err
, "snd_pcm_sw_params_malloc (input)");
274 err
= snd_pcm_sw_params_current(alsa_device
.inhandle
, sw_params
);
275 check_error(err
, "snd_pcm_sw_params_current (input)");
276 err
= snd_pcm_sw_params_set_start_threshold(alsa_device
.inhandle
,
277 sw_params
, nfrags
* frag_size
);
278 check_error(err
, "snd_pcm_sw_params_set_start_threshold (input)");
279 err
= snd_pcm_sw_params_set_stop_threshold(alsa_device
.inhandle
,
280 sw_params
, 0x7fffffff);
281 check_error(err
, "snd_pcm_sw_params_set_stop_threshold (input)");
282 err
= snd_pcm_sw_params_set_avail_min(alsa_device
.inhandle
, sw_params
,
284 check_error(err
, "snd_pcm_sw_params_set_avail_min (input)");
285 err
= snd_pcm_sw_params(alsa_device
.inhandle
, sw_params
);
286 check_error(err
, "snd_pcm_sw_params (input)");
288 snd_pcm_sw_params_free(sw_params
);
290 snd_output_stdio_attach(&out
, stderr
, 0);
294 snd_pcm_dump_hw_setup(alsa_device
.inhandle
, out
);
295 snd_pcm_dump_sw_setup(alsa_device
.inhandle
, out
);
304 post("opening sound output...");
305 err
= snd_pcm_hw_params_malloc(&hw_params
);
306 check_error(err
, "snd_pcm_sw_params (output)");
308 // get the default params
309 err
= snd_pcm_hw_params_any(alsa_device
.outhandle
, hw_params
);
310 check_error(err
, "snd_pcm_hw_params_any (output)");
311 // set interleaved access - FIXME deal with other access types
312 err
= snd_pcm_hw_params_set_access(alsa_device
.outhandle
, hw_params
,
313 SND_PCM_ACCESS_RW_INTERLEAVED
);
314 check_error(err
, "snd_pcm_hw_params_set_access (output)");
316 /* try to set interleaved access */
317 err
= snd_pcm_hw_params_set_access(alsa_device
.outhandle
,
318 hw_params
, SND_PCM_ACCESS_RW_INTERLEAVED
);
321 /* OK, so try non-interleaved */
322 err
= snd_pcm_hw_params_set_access(alsa_device
.outhandle
,
323 hw_params
, SND_PCM_ACCESS_RW_NONINTERLEAVED
);
326 post("using non-interleaved audio");
327 alsa_device
.outnoninterleave
= 1;
330 check_error(err
, "snd_pcm_hw_params_set_access (output)");
333 // Try to set 32 bit format first
334 err
= snd_pcm_hw_params_set_format(alsa_device
.outhandle
, hw_params
,
338 err
= snd_pcm_hw_params_set_format(alsa_device
.outhandle
,
339 hw_params
,SND_PCM_FORMAT_S16
);
340 check_error(err
, "snd_pcm_hw_params_set_format (output)");
342 "PD-ALSA: 32 bit format not available - using 16\n"); */
343 alsa_samplewidth
= 2;
347 alsa_samplewidth
= 4;
350 err
= snd_pcm_hw_params_set_subformat(alsa_device
.outhandle
, hw_params
,
351 SND_PCM_SUBFORMAT_STD
);
352 check_error(err
, "snd_pcm_hw_params_set_subformat (output)");
353 // set the number of channels
355 err
= snd_pcm_hw_params_set_channels_min(alsa_device
.outhandle
,
356 hw_params
, &tmp_uint
);
357 check_error(err
, "snd_pcm_hw_params_set_channels (output)");
358 if (tmp_uint
!= (unsigned)outchans
)
359 post("alsa: set output channels to %d", tmp_uint
);
361 // set the sampling rate
362 err
= snd_pcm_hw_params_set_rate_min(alsa_device
.outhandle
, hw_params
,
364 check_error(err
, "snd_pcm_hw_params_set_rate_min (output)");
366 err
= snd_pcm_hw_params_get_rate(hw_params
, &subunitdir
);
367 post("output sample rate %d", err
);
369 // set the period - ie frag size
371 post("output period was %d, min %d, max %d\n",
372 snd_pcm_hw_params_get_period_size(hw_params
, 0),
373 snd_pcm_hw_params_get_period_size_min(hw_params
, 0),
374 snd_pcm_hw_params_get_period_size_max(hw_params
, 0));
376 // post("fragsize c %d", frag_size);
378 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.outhandle
,
383 tmp_snd_pcm_uframes
= frag_size
;
384 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.outhandle
,
385 hw_params
, &tmp_snd_pcm_uframes
, 0);
387 // post("fragsize d %d", frag_size);
388 check_error(err
, "snd_pcm_hw_params_set_period_size_near (output)");
389 // set the number of periods - ie numfrags
391 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.outhandle
,
392 hw_params
, nfrags
, 0);
395 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.outhandle
,
396 hw_params
, &tmp_uint
, 0);
398 check_error(err
, "snd_pcm_hw_params_set_periods_near (output)");
399 // set the buffer size
401 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.outhandle
,
402 hw_params
, nfrags
* frag_size
);
404 tmp_snd_pcm_uframes
= nfrags
* frag_size
;
405 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.outhandle
,
406 hw_params
, &tmp_snd_pcm_uframes
);
408 check_error(err
, "snd_pcm_hw_params_set_buffer_size_near (output)");
410 err
= snd_pcm_hw_params(alsa_device
.outhandle
, hw_params
);
411 check_error(err
, "snd_pcm_hw_params (output)");
413 snd_pcm_hw_params_free(hw_params
);
415 err
= snd_pcm_sw_params_malloc(&sw_params
);
416 check_error(err
, "snd_pcm_sw_params_malloc (output)");
417 err
= snd_pcm_sw_params_current(alsa_device
.outhandle
, sw_params
);
418 check_error(err
, "snd_pcm_sw_params_current (output)");
419 err
= snd_pcm_sw_params_set_start_threshold(alsa_device
.outhandle
,
420 sw_params
, nfrags
* frag_size
);
421 check_error(err
, "snd_pcm_sw_params_set_start_threshold (output)");
422 err
= snd_pcm_sw_params_set_stop_threshold(alsa_device
.outhandle
,
423 sw_params
, 0x7fffffff);
424 check_error(err
, "snd_pcm_sw_params_set_stop_threshold (output)");
425 err
= snd_pcm_sw_params_set_avail_min(alsa_device
.outhandle
, sw_params
,
427 check_error(err
, "snd_pcm_sw_params_set_avail_min (output)");
428 err
= snd_pcm_sw_params(alsa_device
.outhandle
, sw_params
);
429 check_error(err
, "snd_pcm_sw_params (output)");
430 snd_pcm_sw_params_free(sw_params
);
432 snd_output_stdio_attach(&out
, stderr
, 0);
436 snd_pcm_dump_hw_setup(alsa_device
.outhandle
, out
);
437 snd_pcm_dump_sw_setup(alsa_device
.outhandle
, out
);
443 snd_pcm_prepare(alsa_device
.inhandle
);
445 snd_pcm_prepare(alsa_device
.outhandle
);
447 // if duplex we can link the channels so they start together
448 if (inchans
&& outchans
)
449 snd_pcm_link(alsa_device
.inhandle
, alsa_device
.outhandle
);
451 // set up the status variables
452 err
= snd_pcm_status_malloc(&in_status
);
453 check_error(err
, "snd_pcm_status_malloc");
454 err
= snd_pcm_status_malloc(&out_status
);
455 check_error(err
, "snd_pcm_status_malloc");
460 alsa_snd_buf
= (void *)malloc(
461 sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
*
462 (outchans
> inchans
? outchans
: inchans
));
463 memset(alsa_snd_buf
, 0, sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
*
464 (outchans
> inchans
? outchans
: inchans
));
465 /* make an array of pointers too in case we need them */
468 alsa_buf_ptrs
= (void **)malloc(
469 sizeof(void *) * (outchans
> inchans
? outchans
: inchans
));
470 for (i
= 0; i
< (outchans
> inchans
? outchans
: inchans
); i
++)
471 alsa_buf_ptrs
[i
] = (t_alsa_sample32
*)alsa_snd_buf
+ i
* DEFDACBLKSIZE
;
473 // fill the buffer with silence
476 i
= (frag_size
* nfrags
)/DEFDACBLKSIZE
+ 1;
479 if (alsa_device
.outnoninterleave
)
480 snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
482 else snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
485 /* confused about this: */
486 /* if ((err = snd_pcm_start(alsa_device.outhandle) < 0))
487 check_error(err, "output start failed\n"); */
491 if (snd_pcm_start(alsa_device
.inhandle
) < 0)
492 check_error(err
, "input start failed\n");
494 alsa_outchannels
= outchans
;
495 alsa_inchannels
= inchans
;
497 return (!(inchans
|| outchans
));
500 void alsa_close_audio(void)
505 err
= snd_pcm_close(alsa_device
.inhandle
);
506 check_error(err
, "snd_pcm_close (input)");
508 if (alsa_outchannels
)
510 err
= snd_pcm_close(alsa_device
.outhandle
);
511 check_error(err
, "snd_pcm_close (output)");
515 // #define DEBUG_ALSA_XFER
517 int alsa_send_dacs(void)
520 static int xferno
= 0;
521 static int callno
= 0;
522 static double timenow
;
524 t_sample
*fp
, *fp1
, *fp2
;
525 int i
, j
, k
, err
, devno
= 0;
526 int inputcount
= 0, outputcount
= 0, inputlate
= 0, outputlate
= 0;
528 int inchannels
= (sys_inchannels
> alsa_inchannels
?
529 alsa_inchannels
: sys_inchannels
);
530 int outchannels
= (sys_outchannels
> alsa_outchannels
?
531 alsa_outchannels
: sys_outchannels
);
532 unsigned int intransfersize
= DEFDACBLKSIZE
;
533 unsigned int outtransfersize
= DEFDACBLKSIZE
;
536 if (!inchannels
&& !outchannels
)
542 timenow
= sys_getrealtime();
544 #ifdef DEBUG_ALSA_XFER
545 if (timenow
- timelast
> 0.050)
546 fprintf(stderr
, "(%d)",
547 (int)(1000 * (timenow
- timelast
))), fflush(stderr
);
552 alsa_checkiosync(); /* check I/O are in sync and data not late */
556 snd_pcm_status(alsa_device
.inhandle
, in_status
);
557 if (snd_pcm_status_get_avail(in_status
) < intransfersize
)
560 if (alsa_outchannels
)
562 snd_pcm_status(alsa_device
.outhandle
, out_status
);
563 if (snd_pcm_status_get_avail(out_status
) < outtransfersize
)
568 if (alsa_outchannels
)
571 if (alsa_samplewidth
== 4)
573 if (alsa_device
.outnoninterleave
)
575 int n
= outchannels
* DEFDACBLKSIZE
;
576 for (i
= 0, fp1
= fp
; i
< n
; i
++)
578 float s1
= *fp1
* INT32_MAX
;
579 ((t_alsa_sample32
*)alsa_snd_buf
)[i
] = CLIP32(s1
);
581 n
= alsa_outchannels
* DEFDACBLKSIZE
;
583 ((t_alsa_sample32
*)alsa_snd_buf
)[i
] = 0;
587 for (i
= 0, fp1
= fp
; i
< outchannels
; i
++,
588 fp1
+= DEFDACBLKSIZE
)
590 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
591 j
+= alsa_outchannels
, fp2
++)
593 float s1
= *fp2
* INT32_MAX
;
594 ((t_alsa_sample32
*)alsa_snd_buf
)[j
] = CLIP32(s1
);
601 for (i
= 0, fp1
= fp
; i
< outchannels
; i
++, fp1
+= DEFDACBLKSIZE
)
603 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
604 j
+= alsa_outchannels
, fp2
++)
606 int s
= *fp2
* 32767.;
611 ((t_alsa_sample16
*)alsa_snd_buf
)[j
] = s
;
616 if (alsa_device
.outnoninterleave
)
617 result
= snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
619 else result
= snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
622 if (result
!= (int)outtransfersize
)
624 #ifdef DEBUG_ALSA_XFER
625 if (result
>= 0 || errno
== EAGAIN
)
626 fprintf(stderr
, "ALSA: write returned %d of %d\n",
627 result
, outtransfersize
);
628 else fprintf(stderr
, "ALSA: write: %s\n",
629 snd_strerror(errno
));
631 "inputcount %d, outputcount %d, outbufsize %d\n",
632 inputcount
, outputcount
,
633 (ALSA_EXTRABUFFER
+ sys_advance_samples
)
634 * alsa_samplewidth
* outchannels
);
636 sys_log_error(ERR_DACSLEPT
);
637 return (SENDDACS_NO
);
640 /* zero out the output buffer */
641 memset(sys_soundout
, 0, DEFDACBLKSIZE
* sizeof(*sys_soundout
) *
643 if (sys_getrealtime() - timenow
> 0.002)
645 #ifdef DEBUG_ALSA_XFER
646 fprintf(stderr
, "output %d took %d msec\n",
647 callno
, (int)(1000 * (timenow
- timelast
))), fflush(stderr
);
649 timenow
= sys_getrealtime();
650 sys_log_error(ERR_DACSLEPT
);
656 if (alsa_device
.innoninterleave
)
657 result
= snd_pcm_readn(alsa_device
.inhandle
, alsa_buf_ptrs
,
659 else result
= snd_pcm_readi(alsa_device
.inhandle
, alsa_snd_buf
,
661 if (result
< (int)intransfersize
)
663 #ifdef DEBUG_ALSA_XFER
666 "snd_pcm_read %d %d: %s\n",
667 callno
, xferno
, snd_strerror(errno
));
669 "snd_pcm_read %d %d returned only %d\n",
670 callno
, xferno
, result
);
672 "inputcount %d, outputcount %d, inbufsize %d\n",
673 inputcount
, outputcount
,
674 (ALSA_EXTRABUFFER
+ sys_advance_samples
)
675 * alsa_samplewidth
* inchannels
);
677 sys_log_error(ERR_ADCSLEPT
);
678 return (SENDDACS_NO
);
681 if (alsa_samplewidth
== 4)
683 if (alsa_device
.innoninterleave
)
685 int n
= inchannels
* DEFDACBLKSIZE
;
686 for (i
= 0, fp1
= fp
; i
< n
; i
++)
687 *fp1
= (float) ((t_alsa_sample32
*)alsa_snd_buf
)[i
]
692 for (i
= 0, fp1
= fp
; i
< inchannels
;
693 i
++, fp1
+= DEFDACBLKSIZE
)
695 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
696 j
+= alsa_inchannels
, fp2
++)
697 *fp2
= (float) ((t_alsa_sample32
*)alsa_snd_buf
)[j
]
704 for (i
= 0, fp1
= fp
; i
< inchannels
; i
++, fp1
+= DEFDACBLKSIZE
)
706 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
707 j
+= alsa_inchannels
, fp2
++)
708 *fp2
= (float) ((t_alsa_sample16
*)alsa_snd_buf
)[j
]
714 if (sys_getrealtime() - timenow
> 0.002)
716 #ifdef DEBUG_ALSA_XFER
717 fprintf(stderr
, "routine took %d msec\n",
718 (int)(1000 * (sys_getrealtime() - timenow
)));
720 sys_log_error(ERR_ADCSLEPT
);
725 void alsa_printstate( void)
728 snd_pcm_sframes_t indelay
, outdelay
;
729 if (sys_audioapi
!= API_ALSA
)
731 error("restart-audio: implemented for ALSA only.");
736 result
= snd_pcm_delay(alsa_device
.inhandle
, &indelay
);
738 post("snd_pcm_delay 1 failed");
739 else post("in delay %d", indelay
);
743 result
= snd_pcm_delay(alsa_device
.outhandle
, &outdelay
);
745 post("snd_pcm_delay 2 failed");
746 else post("out delay %d", outdelay
);
748 post("sum %d (%d mod 64)\n", indelay
+ outdelay
, (indelay
+outdelay
)%64);
750 post("buf samples %d", alsa_buf_samps
);
754 void alsa_resync( void)
757 if (sys_audioapi
!= API_ALSA
)
759 error("restart-audio: implemented for ALSA only.");
762 memset(alsa_snd_buf
, 0,
763 sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
* sys_outchannels
);
764 for (i
= 0; i
< 1000000; i
++)
766 if (alsa_device
.outnoninterleave
)
767 result
= snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
769 else result
= snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
771 if (result
!= (int)DEFDACBLKSIZE
)
774 post("%d written", i
);
777 void alsa_putzeros(int n
)
780 memset(alsa_snd_buf
, 0,
781 sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
* alsa_outchannels
);
782 for (i
= 0; i
< n
; i
++)
784 if (alsa_device
.outnoninterleave
)
785 result
= snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
787 else result
= snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
790 if (result
!= DEFDACBLKSIZE
)
791 post("result %d", result
);
794 /* post ("putzeros %d", n); */
797 void alsa_getzeros(int n
)
800 for (i
= 0; i
< n
; i
++)
802 result
= snd_pcm_readi(alsa_device
.inhandle
, alsa_snd_buf
,
805 if (result
!= DEFDACBLKSIZE
)
806 post("result %d", result
);
809 /* post ("getzeros %d", n); */
812 /* call this only if both input and output are open */
813 static void alsa_checkiosync( void)
815 int i
, result
, checkit
= 1, giveup
= 1000, alreadylogged
= 0;
816 snd_pcm_sframes_t indelay
, outdelay
, defect
;
818 if (!(alsa_outchannels
&& alsa_inchannels
))
825 result
= snd_pcm_delay(alsa_device
.outhandle
, &outdelay
);
828 post("output snd_pcm_delay failed: %s", snd_strerror(result
));
829 if (snd_pcm_status(alsa_device
.outhandle
, out_status
) < 0)
830 post("output snd_pcm_status failed");
831 else post("astate %d",
832 snd_pcm_status_get_state(out_status
));
836 sys_log_error(ERR_DATALATE
), alreadylogged
= 1;
840 result
= snd_pcm_delay(alsa_device
.inhandle
, &indelay
);
843 post("input snd_pcm_delay failed");
846 defect
= indelay
+ outdelay
- alsa_buf_samps
;
847 if (defect
< -(3 * DEFDACBLKSIZE
/ 2) )
852 sys_log_error(ERR_RESYNC
), alreadylogged
= 1;
859 sys_log_error(ERR_RESYNC
), alreadylogged
= 1;
861 /* if (alreadylogged)
862 post("in %d out %d defect %d", indelay, outdelay, defect); */
867 static int alsa_nnames
= 0;
868 static char **alsa_names
= 0;
870 void alsa_adddev(char *name
)
873 alsa_names
= (char **)t_resizebytes(alsa_names
,
874 alsa_nnames
* sizeof(char *),
875 (alsa_nnames
+1) * sizeof(char *));
876 else alsa_names
= (char **)t_getbytes(sizeof(char *));
877 alsa_names
[alsa_nnames
] = gensym(name
)->s_name
;
881 static void alsa_numbertoname(int devno
, char *devname
, int nchar
)
883 int ndev
= 0, cardno
= -1;
884 while (!snd_card_next(&cardno
) && cardno
>= 0)
889 snprintf(devname
, nchar
, "plughw:%d", devno
/2);
890 else snprintf(devname
, nchar
, "hw:%d", devno
/2);
892 else if (devno
<2*ndev
+ alsa_nnames
)
893 snprintf(devname
, nchar
, "%s", alsa_names
[devno
- 2*ndev
]);
894 else snprintf(devname
, nchar
, "???");
897 /* For each hardware card found, we list two devices, the "hard" and
898 "plug" one. The card scan is derived from portaudio code. */
899 void alsa_getdevs(char *indevlist
, int *nindevs
,
900 char *outdevlist
, int *noutdevs
, int *canmulti
,
901 int maxndev
, int devdescsize
)
903 int ndev
= 0, cardno
= -1, i
, j
;
904 *canmulti
= 0; /* only one device; must be the same for input&output */
905 while (!snd_card_next(&cardno
) && cardno
>= 0)
908 snd_ctl_card_info_t
*info
;
911 if (2 * ndev
+ 2 > maxndev
)
913 /* apparently, "cardno" is just a counter; but check that here */
915 fprintf(stderr
, "oops: ALSA cards not reported in order?\n");
916 sprintf(devname
, "hw:%d", cardno
);
917 /* fprintf(stderr, "\ntry %s...\n", devname); */
918 if (snd_ctl_open(&ctl
, devname
, 0) >= 0)
920 snd_ctl_card_info_malloc(&info
);
921 snd_ctl_card_info(ctl
, info
);
922 desc
= snd_ctl_card_info_get_name(info
);
923 snd_ctl_card_info_free(info
);
927 fprintf(stderr
, "ALSA card scan error\n");
930 /* fprintf(stderr, "name: %s\n", snd_ctl_card_info_get_name(info)); */
931 sprintf(indevlist
+ 2*ndev
* devdescsize
, "%s (hardware)", desc
);
932 sprintf(indevlist
+ (2*ndev
+ 1) * devdescsize
, "%s (plug-in)", desc
);
933 sprintf(outdevlist
+ 2*ndev
* devdescsize
, "%s (hardware)", desc
);
934 sprintf(outdevlist
+ (2*ndev
+ 1) * devdescsize
, "%s (plug-in)", desc
);
937 for (i
= 0, j
= 2*ndev
; i
< alsa_nnames
; i
++, j
++)
941 snprintf(indevlist
+ j
* devdescsize
, devdescsize
, "%s",
944 *nindevs
= *noutdevs
= j
;
946 /* Copyright (c) 1997-2003 Guenter Geiger, Miller Puckette, Larry Troxler,
947 * Winfried Ritsch, Karl MacMillan, and others.
948 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
949 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
951 /* this file inputs and outputs audio using the ALSA API available on linux. */
953 #include <alsa/asoundlib.h>
962 #include <sys/types.h>
963 #include <sys/time.h>
964 #include <sys/stat.h>
965 #include <sys/ioctl.h>
968 #include <sys/mman.h>
970 typedef int16_t t_alsa_sample16
;
971 typedef int32_t t_alsa_sample32
;
972 #define ALSA_SAMPLEWIDTH_16 sizeof(t_alsa_sample16)
973 #define ALSA_SAMPLEWIDTH_32 sizeof(t_alsa_sample32)
974 #define ALSA_XFERSIZE16 (signed int)(sizeof(t_alsa_sample16) * DEFDACBLKSIZE)
975 #define ALSA_XFERSIZE32 (signed int)(sizeof(t_alsa_sample32) * DEFDACBLKSIZE)
976 #define ALSA_MAXDEV 1
977 #define ALSA_JITTER 1024
978 #define ALSA_EXTRABUFFER 2048
979 #define ALSA_DEFFRAGSIZE 64
980 #define ALSA_DEFNFRAG 12
983 #define INT32_MAX 0x7fffffff
986 #if (SND_LIB_MAJOR < 1)
990 typedef struct _alsa_dev
993 snd_pcm_t
*outhandle
;
994 int innoninterleave
; /* true if we're set for noninterleaved read */
995 int outnoninterleave
; /* same for write */
998 t_alsa_dev alsa_device
;
999 static void *alsa_snd_buf
= 0;
1000 static void **alsa_buf_ptrs
;
1001 static int alsa_samplewidth
;
1002 static snd_pcm_status_t
* in_status
;
1003 static snd_pcm_status_t
* out_status
;
1005 static int alsa_mode
;
1006 static int alsa_buf_samps
; /* believed actual ALSA bufsize in sample frames */
1007 static int alsa_inchannels
;
1008 static int alsa_outchannels
;
1012 #define DEBUG2(x) {x;}
1014 static void alsa_checkiosync( void);
1015 static void alsa_numbertoname(int devno
, char *devname
, int nchar
);
1017 /* don't assume we can turn all 31 bits when doing float-to-fix;
1018 otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
1019 #define FMAX 0x7ffff000
1020 #define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))
1022 /* support for ALSA pcmv2 api by Karl MacMillan<karlmac@peabody.jhu.edu> */
1024 static void check_error(int err
, const char *why
)
1027 fprintf(stderr
, "%s: %s\n", why
, snd_strerror(err
));
1030 /* was: alsa_open_audio(int wantinchans, int wantoutchans, int srate) */
1032 int alsa_open_audio(int naudioindev
, int *audioindev
, int nchindev
,
1033 int *chindev
, int naudiooutdev
, int *audiooutdev
, int nchoutdev
,
1034 int *choutdev
, int rate
)
1036 int err
, inchans
= 0, outchans
= 0, subunitdir
;
1038 snd_pcm_hw_params_t
* hw_params
;
1039 snd_pcm_sw_params_t
* sw_params
;
1041 int frag_size
= (sys_blocksize
? sys_blocksize
: ALSA_DEFFRAGSIZE
);
1044 unsigned int tmp_uint
;
1045 snd_pcm_uframes_t tmp_snd_pcm_uframes
;
1046 int wantinchans
, wantoutchans
, devno
;
1048 if (naudioindev
>= 2 || naudiooutdev
>= 2)
1049 post("alsa: only one input and output device allowed (extras ignored");
1050 if (naudioindev
>= 1 && naudiooutdev
>= 1 &&
1051 audioindev
[0] != audiooutdev
[0])
1052 post("alsa: changing output device to agree with input device");
1054 wantinchans
= chindev
[0];
1055 else wantinchans
= (naudioindev
? 2 : 0);
1057 wantoutchans
= choutdev
[0];
1058 else wantoutchans
= (naudiooutdev
? 2 : 0);
1059 devno
= (naudioindev
> 0 ? audioindev
[0] :
1060 (naudiooutdev
> 0 ? audiooutdev
[0] : 0));
1062 alsa_numbertoname(devno
, devname
, 512);
1065 post("device name %s; channels in %d, out %d", devname
, wantinchans
,
1068 nfrags
= sys_schedadvance
* (float)rate
/ (1e6
* frag_size
);
1069 /* save our belief as to ALSA's buffer size for later */
1070 alsa_buf_samps
= nfrags
* frag_size
;
1073 post("audio buffer set to %d", (int)(0.001 * sys_schedadvance
));
1075 alsa_device
.innoninterleave
= alsa_device
.outnoninterleave
= 0;
1078 err
= snd_pcm_open(&alsa_device
.inhandle
, devname
,
1079 SND_PCM_STREAM_CAPTURE
, SND_PCM_NONBLOCK
);
1081 check_error(err
, "snd_pcm_open (input)");
1086 inchans
= wantinchans
;
1087 snd_pcm_nonblock(alsa_device
.inhandle
, 1);
1092 err
= snd_pcm_open(&alsa_device
.outhandle
, devname
,
1093 SND_PCM_STREAM_PLAYBACK
, SND_PCM_NONBLOCK
);
1095 check_error(err
, "snd_pcm_open (output)");
1100 outchans
= wantoutchans
;
1101 snd_pcm_nonblock(alsa_device
.outhandle
, 1);
1107 post("opening sound input...");
1108 err
= snd_pcm_hw_params_malloc(&hw_params
);
1109 check_error(err
, "snd_pcm_hw_params_malloc (input)");
1111 // get the default params
1112 err
= snd_pcm_hw_params_any(alsa_device
.inhandle
, hw_params
);
1113 check_error(err
, "snd_pcm_hw_params_any (input)");
1115 /* try to set interleaved access */
1116 err
= snd_pcm_hw_params_set_access(alsa_device
.inhandle
,
1117 hw_params
, SND_PCM_ACCESS_RW_INTERLEAVED
);
1120 /* OK, so try non-interleaved */
1121 err
= snd_pcm_hw_params_set_access(alsa_device
.inhandle
,
1122 hw_params
, SND_PCM_ACCESS_RW_NONINTERLEAVED
);
1125 post("using non-interleaved audio input");
1126 alsa_device
.innoninterleave
= 1;
1129 check_error(err
, "snd_pcm_hw_params_set_access (input)");
1130 // Try to set 32 bit format first
1131 err
= snd_pcm_hw_params_set_format(alsa_device
.inhandle
, hw_params
,
1132 SND_PCM_FORMAT_S32
);
1136 "PD-ALSA: 32 bit format not available - using 16\n"); */
1137 err
= snd_pcm_hw_params_set_format(alsa_device
.inhandle
, hw_params
,
1138 SND_PCM_FORMAT_S16
);
1139 check_error(err
, "snd_pcm_hw_params_set_format (input)");
1140 alsa_samplewidth
= 2;
1144 alsa_samplewidth
= 4;
1146 post("Sample width set to %d bytes", alsa_samplewidth
);
1147 // set the subformat
1148 err
= snd_pcm_hw_params_set_subformat(alsa_device
.inhandle
, hw_params
,
1149 SND_PCM_SUBFORMAT_STD
);
1150 check_error(err
, "snd_pcm_hw_params_set_subformat (input)");
1151 // set the number of channels
1153 err
= snd_pcm_hw_params_set_channels_min(alsa_device
.inhandle
,
1154 hw_params
, &tmp_uint
);
1155 check_error(err
, "snd_pcm_hw_params_set_channels (input)");
1156 if (tmp_uint
!= (unsigned)inchans
)
1157 post("ALSA: set input channels to %d", tmp_uint
);
1159 // set the sampling rate
1160 err
= snd_pcm_hw_params_set_rate_min(alsa_device
.inhandle
, hw_params
,
1162 check_error(err
, "snd_pcm_hw_params_set_rate_min (input)");
1164 err
= snd_pcm_hw_params_get_rate(hw_params
, &subunitdir
);
1165 post("input sample rate %d", err
);
1167 // set the period - ie frag size
1168 // post("fragsize a %d", frag_size);
1170 /* LATER try this to get a recommended period size...
1171 right now, it trips an assertion failure in ALSA lib */
1173 post("input period was %d, min %d, max %d\n",
1174 snd_pcm_hw_params_get_period_size(hw_params
, 0),
1175 snd_pcm_hw_params_get_period_size_min(hw_params
, 0),
1176 snd_pcm_hw_params_get_period_size_max(hw_params
, 0));
1179 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.inhandle
,
1184 tmp_snd_pcm_uframes
= frag_size
;
1185 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.inhandle
,
1186 hw_params
, &tmp_snd_pcm_uframes
, 0);
1188 check_error(err
, "snd_pcm_hw_params_set_period_size_near (input)");
1189 // post("fragsize b %d", frag_size);
1190 // set the number of periods - ie numfrags
1191 // post("nfrags a %d", nfrags);
1193 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.inhandle
,
1194 hw_params
, nfrags
, 0);
1197 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.inhandle
,
1198 hw_params
, &tmp_uint
, 0);
1200 check_error(err
, "snd_pcm_hw_params_set_periods_near (input)");
1201 // set the buffer size
1203 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.inhandle
,
1204 hw_params
, nfrags
* frag_size
);
1206 tmp_snd_pcm_uframes
= nfrags
* frag_size
;
1207 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.inhandle
,
1208 hw_params
, &tmp_snd_pcm_uframes
);
1210 check_error(err
, "snd_pcm_hw_params_set_buffer_size_near (input)");
1212 err
= snd_pcm_hw_params(alsa_device
.inhandle
, hw_params
);
1213 check_error(err
, "snd_pcm_hw_params (input)");
1215 snd_pcm_hw_params_free(hw_params
);
1217 err
= snd_pcm_sw_params_malloc(&sw_params
);
1218 check_error(err
, "snd_pcm_sw_params_malloc (input)");
1219 err
= snd_pcm_sw_params_current(alsa_device
.inhandle
, sw_params
);
1220 check_error(err
, "snd_pcm_sw_params_current (input)");
1221 err
= snd_pcm_sw_params_set_start_threshold(alsa_device
.inhandle
,
1222 sw_params
, nfrags
* frag_size
);
1223 check_error(err
, "snd_pcm_sw_params_set_start_threshold (input)");
1224 err
= snd_pcm_sw_params_set_stop_threshold(alsa_device
.inhandle
,
1225 sw_params
, 0x7fffffff);
1226 check_error(err
, "snd_pcm_sw_params_set_stop_threshold (input)");
1227 err
= snd_pcm_sw_params_set_avail_min(alsa_device
.inhandle
, sw_params
,
1229 check_error(err
, "snd_pcm_sw_params_set_avail_min (input)");
1230 err
= snd_pcm_sw_params(alsa_device
.inhandle
, sw_params
);
1231 check_error(err
, "snd_pcm_sw_params (input)");
1233 snd_pcm_sw_params_free(sw_params
);
1235 snd_output_stdio_attach(&out
, stderr
, 0);
1239 snd_pcm_dump_hw_setup(alsa_device
.inhandle
, out
);
1240 snd_pcm_dump_sw_setup(alsa_device
.inhandle
, out
);
1249 post("opening sound output...");
1250 err
= snd_pcm_hw_params_malloc(&hw_params
);
1251 check_error(err
, "snd_pcm_sw_params (output)");
1253 // get the default params
1254 err
= snd_pcm_hw_params_any(alsa_device
.outhandle
, hw_params
);
1255 check_error(err
, "snd_pcm_hw_params_any (output)");
1256 // set interleaved access - FIXME deal with other access types
1257 err
= snd_pcm_hw_params_set_access(alsa_device
.outhandle
, hw_params
,
1258 SND_PCM_ACCESS_RW_INTERLEAVED
);
1259 check_error(err
, "snd_pcm_hw_params_set_access (output)");
1261 /* try to set interleaved access */
1262 err
= snd_pcm_hw_params_set_access(alsa_device
.outhandle
,
1263 hw_params
, SND_PCM_ACCESS_RW_INTERLEAVED
);
1266 /* OK, so try non-interleaved */
1267 err
= snd_pcm_hw_params_set_access(alsa_device
.outhandle
,
1268 hw_params
, SND_PCM_ACCESS_RW_NONINTERLEAVED
);
1271 post("using non-interleaved audio");
1272 alsa_device
.outnoninterleave
= 1;
1275 check_error(err
, "snd_pcm_hw_params_set_access (output)");
1278 // Try to set 32 bit format first
1279 err
= snd_pcm_hw_params_set_format(alsa_device
.outhandle
, hw_params
,
1280 SND_PCM_FORMAT_S32
);
1283 err
= snd_pcm_hw_params_set_format(alsa_device
.outhandle
,
1284 hw_params
,SND_PCM_FORMAT_S16
);
1285 check_error(err
, "snd_pcm_hw_params_set_format (output)");
1287 "PD-ALSA: 32 bit format not available - using 16\n"); */
1288 alsa_samplewidth
= 2;
1292 alsa_samplewidth
= 4;
1294 // set the subformat
1295 err
= snd_pcm_hw_params_set_subformat(alsa_device
.outhandle
, hw_params
,
1296 SND_PCM_SUBFORMAT_STD
);
1297 check_error(err
, "snd_pcm_hw_params_set_subformat (output)");
1298 // set the number of channels
1299 tmp_uint
= outchans
;
1300 err
= snd_pcm_hw_params_set_channels_min(alsa_device
.outhandle
,
1301 hw_params
, &tmp_uint
);
1302 check_error(err
, "snd_pcm_hw_params_set_channels (output)");
1303 if (tmp_uint
!= (unsigned)outchans
)
1304 post("alsa: set output channels to %d", tmp_uint
);
1305 outchans
= tmp_uint
;
1306 // set the sampling rate
1307 err
= snd_pcm_hw_params_set_rate_min(alsa_device
.outhandle
, hw_params
,
1309 check_error(err
, "snd_pcm_hw_params_set_rate_min (output)");
1311 err
= snd_pcm_hw_params_get_rate(hw_params
, &subunitdir
);
1312 post("output sample rate %d", err
);
1314 // set the period - ie frag size
1316 post("output period was %d, min %d, max %d\n",
1317 snd_pcm_hw_params_get_period_size(hw_params
, 0),
1318 snd_pcm_hw_params_get_period_size_min(hw_params
, 0),
1319 snd_pcm_hw_params_get_period_size_max(hw_params
, 0));
1321 // post("fragsize c %d", frag_size);
1323 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.outhandle
,
1328 tmp_snd_pcm_uframes
= frag_size
;
1329 err
= snd_pcm_hw_params_set_period_size_near(alsa_device
.outhandle
,
1330 hw_params
, &tmp_snd_pcm_uframes
, 0);
1332 // post("fragsize d %d", frag_size);
1333 check_error(err
, "snd_pcm_hw_params_set_period_size_near (output)");
1334 // set the number of periods - ie numfrags
1336 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.outhandle
,
1337 hw_params
, nfrags
, 0);
1340 err
= snd_pcm_hw_params_set_periods_near(alsa_device
.outhandle
,
1341 hw_params
, &tmp_uint
, 0);
1343 check_error(err
, "snd_pcm_hw_params_set_periods_near (output)");
1344 // set the buffer size
1346 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.outhandle
,
1347 hw_params
, nfrags
* frag_size
);
1349 tmp_snd_pcm_uframes
= nfrags
* frag_size
;
1350 err
= snd_pcm_hw_params_set_buffer_size_near(alsa_device
.outhandle
,
1351 hw_params
, &tmp_snd_pcm_uframes
);
1353 check_error(err
, "snd_pcm_hw_params_set_buffer_size_near (output)");
1355 err
= snd_pcm_hw_params(alsa_device
.outhandle
, hw_params
);
1356 check_error(err
, "snd_pcm_hw_params (output)");
1358 snd_pcm_hw_params_free(hw_params
);
1360 err
= snd_pcm_sw_params_malloc(&sw_params
);
1361 check_error(err
, "snd_pcm_sw_params_malloc (output)");
1362 err
= snd_pcm_sw_params_current(alsa_device
.outhandle
, sw_params
);
1363 check_error(err
, "snd_pcm_sw_params_current (output)");
1364 err
= snd_pcm_sw_params_set_start_threshold(alsa_device
.outhandle
,
1365 sw_params
, nfrags
* frag_size
);
1366 check_error(err
, "snd_pcm_sw_params_set_start_threshold (output)");
1367 err
= snd_pcm_sw_params_set_stop_threshold(alsa_device
.outhandle
,
1368 sw_params
, 0x7fffffff);
1369 check_error(err
, "snd_pcm_sw_params_set_stop_threshold (output)");
1370 err
= snd_pcm_sw_params_set_avail_min(alsa_device
.outhandle
, sw_params
,
1372 check_error(err
, "snd_pcm_sw_params_set_avail_min (output)");
1373 err
= snd_pcm_sw_params(alsa_device
.outhandle
, sw_params
);
1374 check_error(err
, "snd_pcm_sw_params (output)");
1375 snd_pcm_sw_params_free(sw_params
);
1377 snd_output_stdio_attach(&out
, stderr
, 0);
1381 snd_pcm_dump_hw_setup(alsa_device
.outhandle
, out
);
1382 snd_pcm_dump_sw_setup(alsa_device
.outhandle
, out
);
1388 snd_pcm_prepare(alsa_device
.inhandle
);
1390 snd_pcm_prepare(alsa_device
.outhandle
);
1392 // if duplex we can link the channels so they start together
1393 if (inchans
&& outchans
)
1394 snd_pcm_link(alsa_device
.inhandle
, alsa_device
.outhandle
);
1396 // set up the status variables
1397 err
= snd_pcm_status_malloc(&in_status
);
1398 check_error(err
, "snd_pcm_status_malloc");
1399 err
= snd_pcm_status_malloc(&out_status
);
1400 check_error(err
, "snd_pcm_status_malloc");
1402 // set up the buffer
1405 alsa_snd_buf
= (void *)malloc(
1406 sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
*
1407 (outchans
> inchans
? outchans
: inchans
));
1408 memset(alsa_snd_buf
, 0, sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
*
1409 (outchans
> inchans
? outchans
: inchans
));
1410 /* make an array of pointers too in case we need them */
1412 free(alsa_buf_ptrs
);
1413 alsa_buf_ptrs
= (void **)malloc(
1414 sizeof(void *) * (outchans
> inchans
? outchans
: inchans
));
1415 for (i
= 0; i
< (outchans
> inchans
? outchans
: inchans
); i
++)
1416 alsa_buf_ptrs
[i
] = (t_alsa_sample32
*)alsa_snd_buf
+ i
* DEFDACBLKSIZE
;
1418 // fill the buffer with silence
1421 i
= (frag_size
* nfrags
)/DEFDACBLKSIZE
+ 1;
1424 if (alsa_device
.outnoninterleave
)
1425 snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
1427 else snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
1430 /* confused about this: */
1431 /* if ((err = snd_pcm_start(alsa_device.outhandle) < 0))
1432 check_error(err, "output start failed\n"); */
1436 if (snd_pcm_start(alsa_device
.inhandle
) < 0)
1437 check_error(err
, "input start failed\n");
1439 alsa_outchannels
= outchans
;
1440 alsa_inchannels
= inchans
;
1442 return (!(inchans
|| outchans
));
1445 void alsa_close_audio(void)
1448 if (alsa_inchannels
)
1450 err
= snd_pcm_close(alsa_device
.inhandle
);
1451 check_error(err
, "snd_pcm_close (input)");
1453 if (alsa_outchannels
)
1455 err
= snd_pcm_close(alsa_device
.outhandle
);
1456 check_error(err
, "snd_pcm_close (output)");
1460 // #define DEBUG_ALSA_XFER
1462 int alsa_send_dacs(void)
1465 static int xferno
= 0;
1466 static int callno
= 0;
1467 static double timenow
;
1469 t_sample
*fp
, *fp1
, *fp2
;
1470 int i
, j
, k
, err
, devno
= 0;
1471 int inputcount
= 0, outputcount
= 0, inputlate
= 0, outputlate
= 0;
1473 int inchannels
= (sys_inchannels
> alsa_inchannels
?
1474 alsa_inchannels
: sys_inchannels
);
1475 int outchannels
= (sys_outchannels
> alsa_outchannels
?
1476 alsa_outchannels
: sys_outchannels
);
1477 unsigned int intransfersize
= DEFDACBLKSIZE
;
1478 unsigned int outtransfersize
= DEFDACBLKSIZE
;
1481 if (!inchannels
&& !outchannels
)
1487 timenow
= sys_getrealtime();
1489 #ifdef DEBUG_ALSA_XFER
1490 if (timenow
- timelast
> 0.050)
1491 fprintf(stderr
, "(%d)",
1492 (int)(1000 * (timenow
- timelast
))), fflush(stderr
);
1497 alsa_checkiosync(); /* check I/O are in sync and data not late */
1499 if (alsa_inchannels
)
1501 snd_pcm_status(alsa_device
.inhandle
, in_status
);
1502 if (snd_pcm_status_get_avail(in_status
) < intransfersize
)
1505 if (alsa_outchannels
)
1507 snd_pcm_status(alsa_device
.outhandle
, out_status
);
1508 if (snd_pcm_status_get_avail(out_status
) < outtransfersize
)
1513 if (alsa_outchannels
)
1516 if (alsa_samplewidth
== 4)
1518 if (alsa_device
.outnoninterleave
)
1520 int n
= outchannels
* DEFDACBLKSIZE
;
1521 for (i
= 0, fp1
= fp
; i
< n
; i
++)
1523 float s1
= *fp1
* INT32_MAX
;
1524 ((t_alsa_sample32
*)alsa_snd_buf
)[i
] = CLIP32(s1
);
1526 n
= alsa_outchannels
* DEFDACBLKSIZE
;
1528 ((t_alsa_sample32
*)alsa_snd_buf
)[i
] = 0;
1532 for (i
= 0, fp1
= fp
; i
< outchannels
; i
++,
1533 fp1
+= DEFDACBLKSIZE
)
1535 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
1536 j
+= alsa_outchannels
, fp2
++)
1538 float s1
= *fp2
* INT32_MAX
;
1539 ((t_alsa_sample32
*)alsa_snd_buf
)[j
] = CLIP32(s1
);
1546 for (i
= 0, fp1
= fp
; i
< outchannels
; i
++, fp1
+= DEFDACBLKSIZE
)
1548 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
1549 j
+= alsa_outchannels
, fp2
++)
1551 int s
= *fp2
* 32767.;
1554 else if (s
< -32767)
1556 ((t_alsa_sample16
*)alsa_snd_buf
)[j
] = s
;
1561 if (alsa_device
.outnoninterleave
)
1562 result
= snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
1564 else result
= snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
1567 if (result
!= (int)outtransfersize
)
1569 #ifdef DEBUG_ALSA_XFER
1570 if (result
>= 0 || errno
== EAGAIN
)
1571 fprintf(stderr
, "ALSA: write returned %d of %d\n",
1572 result
, outtransfersize
);
1573 else fprintf(stderr
, "ALSA: write: %s\n",
1574 snd_strerror(errno
));
1576 "inputcount %d, outputcount %d, outbufsize %d\n",
1577 inputcount
, outputcount
,
1578 (ALSA_EXTRABUFFER
+ sys_advance_samples
)
1579 * alsa_samplewidth
* outchannels
);
1581 sys_log_error(ERR_DACSLEPT
);
1582 return (SENDDACS_NO
);
1585 /* zero out the output buffer */
1586 memset(sys_soundout
, 0, DEFDACBLKSIZE
* sizeof(*sys_soundout
) *
1588 if (sys_getrealtime() - timenow
> 0.002)
1590 #ifdef DEBUG_ALSA_XFER
1591 fprintf(stderr
, "output %d took %d msec\n",
1592 callno
, (int)(1000 * (timenow
- timelast
))), fflush(stderr
);
1594 timenow
= sys_getrealtime();
1595 sys_log_error(ERR_DACSLEPT
);
1599 if (alsa_inchannels
)
1601 if (alsa_device
.innoninterleave
)
1602 result
= snd_pcm_readn(alsa_device
.inhandle
, alsa_buf_ptrs
,
1604 else result
= snd_pcm_readi(alsa_device
.inhandle
, alsa_snd_buf
,
1606 if (result
< (int)intransfersize
)
1608 #ifdef DEBUG_ALSA_XFER
1611 "snd_pcm_read %d %d: %s\n",
1612 callno
, xferno
, snd_strerror(errno
));
1613 else fprintf(stderr
,
1614 "snd_pcm_read %d %d returned only %d\n",
1615 callno
, xferno
, result
);
1617 "inputcount %d, outputcount %d, inbufsize %d\n",
1618 inputcount
, outputcount
,
1619 (ALSA_EXTRABUFFER
+ sys_advance_samples
)
1620 * alsa_samplewidth
* inchannels
);
1622 sys_log_error(ERR_ADCSLEPT
);
1623 return (SENDDACS_NO
);
1626 if (alsa_samplewidth
== 4)
1628 if (alsa_device
.innoninterleave
)
1630 int n
= inchannels
* DEFDACBLKSIZE
;
1631 for (i
= 0, fp1
= fp
; i
< n
; i
++)
1632 *fp1
= (float) ((t_alsa_sample32
*)alsa_snd_buf
)[i
]
1637 for (i
= 0, fp1
= fp
; i
< inchannels
;
1638 i
++, fp1
+= DEFDACBLKSIZE
)
1640 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
1641 j
+= alsa_inchannels
, fp2
++)
1642 *fp2
= (float) ((t_alsa_sample32
*)alsa_snd_buf
)[j
]
1649 for (i
= 0, fp1
= fp
; i
< inchannels
; i
++, fp1
+= DEFDACBLKSIZE
)
1651 for (j
= i
, k
= DEFDACBLKSIZE
, fp2
= fp1
; k
--;
1652 j
+= alsa_inchannels
, fp2
++)
1653 *fp2
= (float) ((t_alsa_sample16
*)alsa_snd_buf
)[j
]
1659 if (sys_getrealtime() - timenow
> 0.002)
1661 #ifdef DEBUG_ALSA_XFER
1662 fprintf(stderr
, "routine took %d msec\n",
1663 (int)(1000 * (sys_getrealtime() - timenow
)));
1665 sys_log_error(ERR_ADCSLEPT
);
1667 return SENDDACS_YES
;
1670 void alsa_printstate( void)
1673 snd_pcm_sframes_t indelay
, outdelay
;
1674 if (sys_audioapi
!= API_ALSA
)
1676 error("restart-audio: implemented for ALSA only.");
1681 result
= snd_pcm_delay(alsa_device
.inhandle
, &indelay
);
1683 post("snd_pcm_delay 1 failed");
1684 else post("in delay %d", indelay
);
1686 if (sys_outchannels
)
1688 result
= snd_pcm_delay(alsa_device
.outhandle
, &outdelay
);
1690 post("snd_pcm_delay 2 failed");
1691 else post("out delay %d", outdelay
);
1693 post("sum %d (%d mod 64)\n", indelay
+ outdelay
, (indelay
+outdelay
)%64);
1695 post("buf samples %d", alsa_buf_samps
);
1699 void alsa_resync( void)
1702 if (sys_audioapi
!= API_ALSA
)
1704 error("restart-audio: implemented for ALSA only.");
1707 memset(alsa_snd_buf
, 0,
1708 sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
* sys_outchannels
);
1709 for (i
= 0; i
< 1000000; i
++)
1711 if (alsa_device
.outnoninterleave
)
1712 result
= snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
1714 else result
= snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
1716 if (result
!= (int)DEFDACBLKSIZE
)
1719 post("%d written", i
);
1722 void alsa_putzeros(int n
)
1725 memset(alsa_snd_buf
, 0,
1726 sizeof(char) * alsa_samplewidth
* DEFDACBLKSIZE
* alsa_outchannels
);
1727 for (i
= 0; i
< n
; i
++)
1729 if (alsa_device
.outnoninterleave
)
1730 result
= snd_pcm_writen(alsa_device
.outhandle
, alsa_buf_ptrs
,
1732 else result
= snd_pcm_writei(alsa_device
.outhandle
, alsa_snd_buf
,
1735 if (result
!= DEFDACBLKSIZE
)
1736 post("result %d", result
);
1739 /* post ("putzeros %d", n); */
1742 void alsa_getzeros(int n
)
1745 for (i
= 0; i
< n
; i
++)
1747 result
= snd_pcm_readi(alsa_device
.inhandle
, alsa_snd_buf
,
1750 if (result
!= DEFDACBLKSIZE
)
1751 post("result %d", result
);
1754 /* post ("getzeros %d", n); */
1757 /* call this only if both input and output are open */
1758 static void alsa_checkiosync( void)
1760 int i
, result
, checkit
= 1, giveup
= 1000, alreadylogged
= 0;
1761 snd_pcm_sframes_t indelay
, outdelay
, defect
;
1763 if (!(alsa_outchannels
&& alsa_inchannels
))
1770 result
= snd_pcm_delay(alsa_device
.outhandle
, &outdelay
);
1773 post("output snd_pcm_delay failed: %s", snd_strerror(result
));
1774 if (snd_pcm_status(alsa_device
.outhandle
, out_status
) < 0)
1775 post("output snd_pcm_status failed");
1776 else post("astate %d",
1777 snd_pcm_status_get_state(out_status
));
1781 sys_log_error(ERR_DATALATE
), alreadylogged
= 1;
1785 result
= snd_pcm_delay(alsa_device
.inhandle
, &indelay
);
1788 post("input snd_pcm_delay failed");
1791 defect
= indelay
+ outdelay
- alsa_buf_samps
;
1792 if (defect
< -(3 * DEFDACBLKSIZE
/ 2) )
1797 sys_log_error(ERR_RESYNC
), alreadylogged
= 1;
1799 else if (defect
> 0)
1804 sys_log_error(ERR_RESYNC
), alreadylogged
= 1;
1806 /* if (alreadylogged)
1807 post("in %d out %d defect %d", indelay, outdelay, defect); */
1812 static int alsa_nnames
= 0;
1813 static char **alsa_names
= 0;
1815 void alsa_adddev(char *name
)
1818 alsa_names
= (char **)t_resizebytes(alsa_names
,
1819 alsa_nnames
* sizeof(char *),
1820 (alsa_nnames
+1) * sizeof(char *));
1821 else alsa_names
= (char **)t_getbytes(sizeof(char *));
1822 alsa_names
[alsa_nnames
] = gensym(name
)->s_name
;
1826 static void alsa_numbertoname(int devno
, char *devname
, int nchar
)
1828 int ndev
= 0, cardno
= -1;
1829 while (!snd_card_next(&cardno
) && cardno
>= 0)
1834 snprintf(devname
, nchar
, "plughw:%d", devno
/2);
1835 else snprintf(devname
, nchar
, "hw:%d", devno
/2);
1837 else if (devno
<2*ndev
+ alsa_nnames
)
1838 snprintf(devname
, nchar
, "%s", alsa_names
[devno
- 2*ndev
]);
1839 else snprintf(devname
, nchar
, "???");
1842 /* For each hardware card found, we list two devices, the "hard" and
1843 "plug" one. The card scan is derived from portaudio code. */
1844 void alsa_getdevs(char *indevlist
, int *nindevs
,
1845 char *outdevlist
, int *noutdevs
, int *canmulti
,
1846 int maxndev
, int devdescsize
)
1848 int ndev
= 0, cardno
= -1, i
, j
;
1849 *canmulti
= 0; /* only one device; must be the same for input&output */
1850 while (!snd_card_next(&cardno
) && cardno
>= 0)
1853 snd_ctl_card_info_t
*info
;
1856 if (2 * ndev
+ 2 > maxndev
)
1858 /* apparently, "cardno" is just a counter; but check that here */
1860 fprintf(stderr
, "oops: ALSA cards not reported in order?\n");
1861 sprintf(devname
, "hw:%d", cardno
);
1862 /* fprintf(stderr, "\ntry %s...\n", devname); */
1863 if (snd_ctl_open(&ctl
, devname
, 0) >= 0)
1865 snd_ctl_card_info_malloc(&info
);
1866 snd_ctl_card_info(ctl
, info
);
1867 desc
= snd_ctl_card_info_get_name(info
);
1868 snd_ctl_card_info_free(info
);
1872 fprintf(stderr
, "ALSA card scan error\n");
1875 /* fprintf(stderr, "name: %s\n", snd_ctl_card_info_get_name(info)); */
1876 sprintf(indevlist
+ 2*ndev
* devdescsize
, "%s (hardware)", desc
);
1877 sprintf(indevlist
+ (2*ndev
+ 1) * devdescsize
, "%s (plug-in)", desc
);
1878 sprintf(outdevlist
+ 2*ndev
* devdescsize
, "%s (hardware)", desc
);
1879 sprintf(outdevlist
+ (2*ndev
+ 1) * devdescsize
, "%s (plug-in)", desc
);
1882 for (i
= 0, j
= 2*ndev
; i
< alsa_nnames
; i
++, j
++)
1886 snprintf(indevlist
+ j
* devdescsize
, devdescsize
, "%s",
1889 *nindevs
= *noutdevs
= j
;