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 OSS API available on linux. */
10 #include <linux/soundcard.h>
19 #include <sys/types.h>
22 #include <sys/ioctl.h>
30 #define DEBUG2(x) {x;}
32 #define OSS_MAXCHPERDEV 32 /* max channels per OSS device */
33 #define OSS_MAXDEV 4 /* maximum number of input or output devices */
34 #define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */
35 #define OSS_DEFAUDIOBUF 40000 /* default audiobuffer, microseconds */
36 #define OSS_DEFAULTCH 2
37 #define RME_DEFAULTCH 8 /* need this even if RME undefined */
38 typedef int16_t t_oss_int16
;
39 typedef int32_t t_oss_int32
;
40 #define OSS_MAXSAMPLEWIDTH sizeof(t_oss_int32)
41 #define OSS_BYTESPERCHAN(width) (DEFDACBLKSIZE * (width))
42 #define OSS_XFERSAMPS(chans) (DEFDACBLKSIZE* (chans))
43 #define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
46 static int linux_meters
; /* true if we're metering */
47 static float linux_inmax
; /* max input amplitude */
48 static float linux_outmax
; /* max output amplitude */
49 static int linux_fragsize
= 0; /* for block mode; block size (sample frames) */
51 /* our device handles */
53 typedef struct _oss_dev
56 unsigned int d_space
; /* bytes available for writing/reading */
57 int d_bufsize
; /* total buffer size in blocks for this device */
58 int d_dropcount
; /* # of buffers to drop for resync (output only) */
59 unsigned int d_nchannels
; /* number of channels for this device */
60 unsigned int d_bytespersamp
; /* bytes per sample (2 for 16 bit, 4 for 32) */
63 static t_oss_dev linux_dacs
[OSS_MAXDEV
];
64 static t_oss_dev linux_adcs
[OSS_MAXDEV
];
65 static int linux_noutdevs
= 0;
66 static int linux_nindevs
= 0;
68 /* exported variables */
70 t_sample
*sys_soundout
;
71 t_sample
*sys_soundin
;
73 /* OSS-specific private variables */
74 static int oss_blockmode
= 1; /* flag to use "blockmode" */
75 static int oss_32bit
= 0; /* allow 23 bit transfers in OSS */
76 static char ossdsp
[] = "/dev/dsp%d";
78 /* don't assume we can turn all 31 bits when doing float-to-fix;
79 otherwise some audio drivers (e.g. Midiman/ALSA) wrap around. */
80 #define FMAX 0x7ffff000
81 #define CLIP32(x) (((x)>FMAX)?FMAX:((x) < -FMAX)?-FMAX:(x))
84 /* ------------- private routines for all APIS ------------------- */
86 static void linux_flush_all_underflows_to_zero(void)
89 TODO: Implement similar thing for linux (GGeiger)
91 One day we will figure this out, I hope, because it
92 costs CPU time dearly on Intel - LT
95 f.fc_word = get_fpc_csr();
96 f.fc_struct.flush = 1;
97 set_fpc_csr(f.fc_word);
101 static int oss_ndev
= 0;
103 /* find out how many OSS devices we have. Since this has to
104 open the devices to find out if they're there, we have
105 to be called before audio is actually started up. So we
106 cache the results, which in effect are the number of available
111 static int countedthem
= 0;
114 for (i
= 0; i
< 10; i
++)
118 strcpy(devname
, "/dev/dsp");
119 else sprintf(devname
, "/dev/dsp%d", i
);
120 if ( (fd
= open(devname
, O_WRONLY
|O_NONBLOCK
)) != -1)
131 void oss_set32bit( void)
137 typedef struct _multidev
{
143 int oss_reset(int fd
) {
145 if ((err
= ioctl(fd
,SNDCTL_DSP_RESET
)) < 0)
146 error("OSS: Could not reset");
150 /* The AFMT_S32_BLOCKED format is not defined in standard linux kernels
151 but is proposed by Guenter Geiger to support extending OSS to handle
152 32 bit sample. This is user in Geiger's OSS driver for RME Hammerfall.
153 I'm not clear why this isn't called AFMT_S32_[SLN]E... */
155 #ifndef AFMT_S32_BLOCKED
156 #define AFMT_S32_BLOCKED 0x0000400
159 void oss_configure(t_oss_dev
*dev
, int srate
, int dac
, int skipblocksize
)
161 int orig
, param
, nblk
, fd
= dev
->d_fd
, wantformat
;
162 int nchannels
= dev
->d_nchannels
;
163 int advwas
= sys_schedadvance
;
165 audio_buf_info ainfo
;
168 * pd is very likely to crash if different formats are used on
172 /* set resolution - first try 4 byte samples */
173 if (oss_32bit
&& (ioctl(fd
,SNDCTL_DSP_GETFMTS
,¶m
) >= 0) &&
174 (param
& AFMT_S32_BLOCKED
))
176 wantformat
= AFMT_S32_BLOCKED
;
177 dev
->d_bytespersamp
= 4;
181 wantformat
= AFMT_S16_NE
;
182 dev
->d_bytespersamp
= 2;
187 post("bytes per sample = %d", dev
->d_bytespersamp
);
188 if (ioctl(fd
, SNDCTL_DSP_SETFMT
, ¶m
) == -1)
189 fprintf(stderr
,"OSS: Could not set DSP format\n");
190 else if (wantformat
!= param
)
191 fprintf(stderr
,"OSS: DSP format: wanted %d, got %d\n",
195 orig
= param
= srate
;
196 if (ioctl(fd
, SNDCTL_DSP_SPEED
, ¶m
) == -1)
197 fprintf(stderr
,"OSS: Could not set sampling rate for device\n");
198 else if( orig
!= param
)
199 fprintf(stderr
,"OSS: sampling rate: wanted %d, got %d\n",
202 if (oss_blockmode
&& !skipblocksize
)
204 int fragbytes
, logfragsize
, nfragment
;
205 /* setting fragment count and size. */
208 linux_fragsize
= OSS_DEFFRAGSIZE
;
209 while (linux_fragsize
> DEFDACBLKSIZE
210 && linux_fragsize
* 4 > sys_advance_samples
)
211 linux_fragsize
= linux_fragsize
/2;
214 /* post("adv_samples %d", sys_advance_samples); */
215 nfragment
= (sys_schedadvance
* (44100. * 1.e
-6)) / linux_fragsize
;
217 fragbytes
= linux_fragsize
* (dev
->d_bytespersamp
* nchannels
);
218 logfragsize
= ilog2(fragbytes
);
220 if (fragbytes
!= (1 << logfragsize
))
221 post("warning: OSS takes only power of 2 blocksize; using %d",
222 (1 << logfragsize
)/(dev
->d_bytespersamp
* nchannels
));
224 post("setting nfrags = %d, fragsize %d\n", nfragment
, fragbytes
);
226 param
= orig
= (nfragment
<<16) + logfragsize
;
227 if (ioctl(fd
,SNDCTL_DSP_SETFRAGMENT
, ¶m
) == -1)
228 error("OSS: Could not set or read fragment size\n");
231 nfragment
= ((param
>> 16) & 0xffff);
232 logfragsize
= (param
& 0xffff);
233 post("warning: actual fragments %d, blocksize %d",
234 nfragment
, (1 << logfragsize
));
237 post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance
));
241 /* use "free space" to learn the buffer size. Normally you
242 should set this to your own desired value; but this seems not
243 to be implemented uniformly across different sound cards. LATER
244 we should figure out what to do if the requested scheduler advance
245 is greater than this buffer size; for now, we just print something
249 if (ioctl(fd
, SOUND_PCM_GETOSPACE
,&ainfo
) < 0)
250 fprintf(stderr
,"OSS: ioctl on output device failed");
251 dev
->d_bufsize
= ainfo
.bytes
;
253 defect
= sys_advance_samples
* (dev
->d_bytespersamp
* nchannels
)
254 - dev
->d_bufsize
- OSS_XFERSIZE(nchannels
, dev
->d_bytespersamp
);
257 if (sys_verbose
|| defect
> (dev
->d_bufsize
>> 2))
259 "OSS: requested audio buffer size %d limited to %d\n",
260 sys_advance_samples
* (dev
->d_bytespersamp
* nchannels
),
262 sys_advance_samples
=
263 (dev
->d_bufsize
- OSS_XFERSAMPS(nchannels
)) /
264 (dev
->d_bytespersamp
*nchannels
);
269 static int oss_setchannels(int fd
, int wantchannels
, char *devname
)
271 int param
= wantchannels
;
275 if (ioctl(fd
, SNDCTL_DSP_CHANNELS
, ¶m
) == -1) {
276 error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname
);
278 if (param
== save
) return (param
);
286 #define O_AUDIOFLAG 0 /* O_NDELAY */
288 int oss_open_audio(int nindev
, int *indev
, int nchin
, int *chin
,
289 int noutdev
, int *outdev
, int nchout
, int *chout
, int rate
)
291 int capabilities
= 0;
292 int inchannels
= 0, outchannels
= 0;
295 char buf
[OSS_MAXSAMPLEWIDTH
* DEFDACBLKSIZE
* OSS_MAXCHPERDEV
];
299 audio_buf_info ainfo
;
301 linux_nindevs
= linux_noutdevs
= 0;
304 /* mark input devices unopened */
305 for (i
= 0; i
< OSS_MAXDEV
; i
++)
306 linux_adcs
[i
].d_fd
= -1;
308 /* open output devices */
310 if (noutdev
< 0 || nindev
< 0)
311 bug("linux_open_audio");
313 for (n
= 0; n
< noutdev
; n
++)
315 int gotchans
, j
, inindex
= -1;
316 int thisdevice
= (outdev
[n
] >= 0 ? outdev
[n
] : n
-1);
317 int wantchannels
= (nchout
>n
) ? chout
[n
] : wantmore
;
323 sprintf(devname
, "/dev/dsp%d", thisdevice
-1);
324 else sprintf(devname
, "/dev/dsp");
326 /* search for input request for same device. Succeed only
327 if the number of channels matches. */
328 for (j
= 0; j
< nindev
; j
++)
329 if (indev
[j
] == thisdevice
&& chin
[j
] == wantchannels
)
332 /* if the same device is requested for input and output,
333 try to open it read/write */
336 sys_setalarm(1000000);
337 if ((fd
= open(devname
, O_RDWR
| O_AUDIOFLAG
)) == -1)
339 post("%s (read/write): %s", devname
, strerror(errno
));
340 post("(now will try write-only...)");
345 post("opened %s for reading and writing\n", devname
);
346 linux_adcs
[inindex
].d_fd
= fd
;
349 /* if that didn't happen or if it failed, try write-only */
352 sys_setalarm(1000000);
353 if ((fd
= open(devname
, O_WRONLY
| O_AUDIOFLAG
)) == -1)
355 post("%s (writeonly): %s",
356 devname
, strerror(errno
));
360 post("opened %s for writing only\n", devname
);
362 if (ioctl(fd
, SNDCTL_DSP_GETCAPS
, &capabilities
) == -1)
363 error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname
);
365 gotchans
= oss_setchannels(fd
,
366 (wantchannels
>OSS_MAXCHPERDEV
)?OSS_MAXCHPERDEV
:wantchannels
,
370 post("opened audio output on %s; got %d channels",
375 /* can't even do stereo? just give up. */
380 linux_dacs
[linux_noutdevs
].d_nchannels
= gotchans
;
381 linux_dacs
[linux_noutdevs
].d_fd
= fd
;
382 oss_configure(linux_dacs
+linux_noutdevs
, rate
, 1, 0);
385 outchannels
+= gotchans
;
388 linux_adcs
[inindex
].d_nchannels
= gotchans
;
389 chin
[inindex
] = gotchans
;
392 /* LATER think about spreading large numbers of channels over
393 various dsp's and vice-versa */
394 wantmore
= wantchannels
- gotchans
;
398 /* open input devices */
400 for (n
= 0; n
< nindev
; n
++)
403 int thisdevice
= (indev
[n
] >= 0 ? indev
[n
] : n
-1);
404 int wantchannels
= (nchin
>n
)?chin
[n
]:wantmore
;
405 int alreadyopened
= 0;
410 sprintf(devname
, "/dev/dsp%d", thisdevice
- 1);
411 else sprintf(devname
, "/dev/dsp");
413 sys_setalarm(1000000);
415 /* perhaps it's already open from the above? */
416 if (linux_dacs
[n
].d_fd
>= 0)
418 fd
= linux_dacs
[n
].d_fd
;
423 /* otherwise try to open it here. */
424 if ((fd
= open(devname
, O_RDONLY
| O_AUDIOFLAG
)) == -1)
426 post("%s (readonly): %s", devname
, strerror(errno
));
430 post("opened %s for reading only\n", devname
);
432 linux_adcs
[linux_nindevs
].d_fd
= fd
;
433 gotchans
= oss_setchannels(fd
,
434 (wantchannels
>OSS_MAXCHPERDEV
)?OSS_MAXCHPERDEV
:wantchannels
,
437 post("opened audio input device %s; got %d channels",
446 linux_adcs
[linux_nindevs
].d_nchannels
= gotchans
;
448 oss_configure(linux_adcs
+linux_nindevs
, rate
, 0, alreadyopened
);
450 inchannels
+= gotchans
;
453 wantmore
= wantchannels
-gotchans
;
454 /* LATER think about spreading large numbers of channels over
455 various dsp's and vice-versa */
459 /* We have to do a read to start the engine. This is
460 necessary because sys_send_dacs waits until the input
461 buffer is filled and only reads on a filled buffer.
462 This is good, because it's a way to make sure that we
463 will not block. But I wonder why we only have to read
464 from one of the devices and not all of them??? */
469 fprintf(stderr
,("OSS: issuing first ADC 'read' ... "));
470 read(linux_adcs
[0].d_fd
, buf
,
471 linux_adcs
[0].d_bytespersamp
*
472 linux_adcs
[0].d_nchannels
* DEFDACBLKSIZE
);
474 fprintf(stderr
, "...done.\n");
480 void oss_close_audio( void)
483 for (i
=0;i
<linux_nindevs
;i
++)
484 close(linux_adcs
[i
].d_fd
);
486 for (i
=0;i
<linux_noutdevs
;i
++)
487 close(linux_dacs
[i
].d_fd
);
489 linux_nindevs
= linux_noutdevs
= 0;
492 static int linux_dacs_write(int fd
,void* buf
,long bytes
)
494 return write(fd
, buf
, bytes
);
497 static int linux_adcs_read(int fd
,void* buf
,long bytes
)
499 return read(fd
, buf
, bytes
);
502 /* query audio devices for "available" data size. */
503 static void oss_calcspace(void)
506 audio_buf_info ainfo
;
507 for (dev
=0; dev
< linux_noutdevs
; dev
++)
509 if (ioctl(linux_dacs
[dev
].d_fd
, SOUND_PCM_GETOSPACE
, &ainfo
) < 0)
510 fprintf(stderr
,"OSS: ioctl on output device %d failed",dev
);
511 linux_dacs
[dev
].d_space
= ainfo
.bytes
;
514 for (dev
= 0; dev
< linux_nindevs
; dev
++)
516 if (ioctl(linux_adcs
[dev
].d_fd
, SOUND_PCM_GETISPACE
,&ainfo
) < 0)
517 fprintf(stderr
, "OSS: ioctl on input device %d, fd %d failed",
518 dev
, linux_adcs
[dev
].d_fd
);
519 linux_adcs
[dev
].d_space
= ainfo
.bytes
;
523 void linux_audiostatus(void)
529 for (dev
=0; dev
< linux_noutdevs
; dev
++)
530 fprintf(stderr
, "dac %d space %d\n", dev
, linux_dacs
[dev
].d_space
);
532 for (dev
= 0; dev
< linux_nindevs
; dev
++)
533 fprintf(stderr
, "adc %d space %d\n", dev
, linux_adcs
[dev
].d_space
);
538 /* this call resyncs audio output and input which will cause discontinuities
539 in audio output and/or input. */
541 static void oss_doresync( void)
543 int dev
, zeroed
= 0, wantsize
;
544 char buf
[OSS_MAXSAMPLEWIDTH
* DEFDACBLKSIZE
* OSS_MAXCHPERDEV
];
545 audio_buf_info ainfo
;
547 /* 1. if any input devices are ahead (have more than 1 buffer stored),
548 drop one or more buffers worth */
549 for (dev
= 0; dev
< linux_nindevs
; dev
++)
551 if (linux_adcs
[dev
].d_space
== 0)
553 linux_adcs_read(linux_adcs
[dev
].d_fd
, buf
,
554 OSS_XFERSIZE(linux_adcs
[dev
].d_nchannels
,
555 linux_adcs
[dev
].d_bytespersamp
));
557 else while (linux_adcs
[dev
].d_space
>
558 OSS_XFERSIZE(linux_adcs
[dev
].d_nchannels
,
559 linux_adcs
[dev
].d_bytespersamp
))
561 linux_adcs_read(linux_adcs
[dev
].d_fd
, buf
,
562 OSS_XFERSIZE(linux_adcs
[dev
].d_nchannels
,
563 linux_adcs
[dev
].d_bytespersamp
));
564 if (ioctl(linux_adcs
[dev
].d_fd
, SOUND_PCM_GETISPACE
, &ainfo
) < 0)
566 fprintf(stderr
, "OSS: ioctl on input device %d, fd %d failed",
567 dev
, linux_adcs
[dev
].d_fd
);
570 linux_adcs
[dev
].d_space
= ainfo
.bytes
;
574 /* 2. if any output devices are behind, feed them zeros to catch them
576 for (dev
= 0; dev
< linux_noutdevs
; dev
++)
578 while (linux_dacs
[dev
].d_space
> linux_dacs
[dev
].d_bufsize
-
579 sys_advance_samples
* (linux_dacs
[dev
].d_nchannels
*
580 linux_dacs
[dev
].d_bytespersamp
))
585 for (i
= 0; i
< OSS_XFERSAMPS(linux_dacs
[dev
].d_nchannels
);
590 linux_dacs_write(linux_dacs
[dev
].d_fd
, buf
,
591 OSS_XFERSIZE(linux_dacs
[dev
].d_nchannels
,
592 linux_dacs
[dev
].d_bytespersamp
));
593 if (ioctl(linux_dacs
[dev
].d_fd
, SOUND_PCM_GETOSPACE
, &ainfo
) < 0)
595 fprintf(stderr
, "OSS: ioctl on output device %d, fd %d failed",
596 dev
, linux_dacs
[dev
].d_fd
);
599 linux_dacs
[dev
].d_space
= ainfo
.bytes
;
602 /* 3. if any DAC devices are too far ahead, plan to drop the
603 number of frames which will let the others catch up. */
604 for (dev
= 0; dev
< linux_noutdevs
; dev
++)
606 if (linux_dacs
[dev
].d_space
> linux_dacs
[dev
].d_bufsize
-
607 (sys_advance_samples
- 1) * linux_dacs
[dev
].d_nchannels
*
608 linux_dacs
[dev
].d_bytespersamp
)
610 linux_dacs
[dev
].d_dropcount
= sys_advance_samples
- 1 -
611 (linux_dacs
[dev
].d_space
- linux_dacs
[dev
].d_bufsize
) /
612 (linux_dacs
[dev
].d_nchannels
*
613 linux_dacs
[dev
].d_bytespersamp
) ;
615 else linux_dacs
[dev
].d_dropcount
= 0;
619 int oss_send_dacs(void)
623 int i
, j
, dev
, rtnval
= SENDDACS_YES
;
624 char buf
[OSS_MAXSAMPLEWIDTH
* DEFDACBLKSIZE
* OSS_MAXCHPERDEV
];
627 /* the maximum number of samples we should have in the ADC buffer */
630 t_time timeref
, timenow
;
632 if (!linux_nindevs
&& !linux_noutdevs
)
633 return (SENDDACS_NO
);
637 /* determine whether we're idle. This is true if either (1)
638 some input device has less than one buffer to read or (2) some
639 output device has fewer than (sys_advance_samples) blocks buffered
643 for (dev
=0; dev
< linux_noutdevs
; dev
++)
644 if (linux_dacs
[dev
].d_dropcount
||
645 (linux_dacs
[dev
].d_bufsize
- linux_dacs
[dev
].d_space
>
646 sys_advance_samples
* linux_dacs
[dev
].d_bytespersamp
*
647 linux_dacs
[dev
].d_nchannels
))
649 for (dev
=0; dev
< linux_nindevs
; dev
++)
650 if (linux_adcs
[dev
].d_space
<
651 OSS_XFERSIZE(linux_adcs
[dev
].d_nchannels
,
652 linux_adcs
[dev
].d_bytespersamp
))
656 if (idle
&& !oss_blockmode
)
658 /* sometimes---rarely---when the ADC available-byte-count is
659 zero, it's genuine, but usually it's because we're so
660 late that the ADC has overrun its entire kernel buffer. We
661 distinguish between the two by waiting 2 msec and asking again.
662 There should be an error flag we could check instead; look for this
664 for (dev
= 0;dev
< linux_nindevs
; dev
++)
665 if (linux_adcs
[dev
].d_space
== 0)
667 audio_buf_info ainfo
;
668 sys_microsleep(2000);
670 if (linux_adcs
[dev
].d_space
!= 0) continue;
672 /* here's the bad case. Give up and resync. */
673 sys_log_error(ERR_DATALATE
);
675 return (SENDDACS_NO
);
677 /* check for slippage between devices, either because
678 data got lost in the driver from a previous late condition, or
679 because the devices aren't synced. When we're idle, no
680 input device should have more than one buffer readable and
681 no output device should have less than sys_advance_samples-1
684 for (dev
=0; dev
< linux_noutdevs
; dev
++)
685 if (!linux_dacs
[dev
].d_dropcount
&&
686 (linux_dacs
[dev
].d_bufsize
- linux_dacs
[dev
].d_space
<
687 (sys_advance_samples
- 2) *
688 (linux_dacs
[dev
].d_bytespersamp
*
689 linux_dacs
[dev
].d_nchannels
)))
691 for (dev
=0; dev
< linux_nindevs
; dev
++)
692 if (linux_adcs
[dev
].d_space
> 3 *
693 OSS_XFERSIZE(linux_adcs
[dev
].d_nchannels
,
694 linux_adcs
[dev
].d_bytespersamp
))
697 /* return zero to tell the scheduler we're idle. */
698 return (SENDDACS_NO
);
700 sys_log_error(ERR_RESYNC
);
702 return (SENDDACS_NO
);
709 timeref
= sys_getrealtime();
710 for (dev
=0, thischan
= 0; dev
< linux_noutdevs
; dev
++)
712 int nchannels
= linux_dacs
[dev
].d_nchannels
;
713 if (linux_dacs
[dev
].d_dropcount
)
714 linux_dacs
[dev
].d_dropcount
--;
717 if (linux_dacs
[dev
].d_bytespersamp
== 4)
719 for (i
= DEFDACBLKSIZE
* nchannels
, fp1
= sys_soundout
+
720 DEFDACBLKSIZE
*thischan
,
721 lp
= (t_oss_int32
*)buf
; i
--; fp1
++, lp
++)
723 t_sample f
= SCALE32(*fp1
);
724 *lp
= (f
>= 2147483647 ? 2147483647 :
725 (f
< -2147483647 ? -2147483647 : f
));
730 for (i
= DEFDACBLKSIZE
, fp1
= sys_soundout
+
731 DEFDACBLKSIZE
*thischan
,
732 sp
= (t_oss_int16
*)buf
; i
--; fp1
++, sp
+= nchannels
)
734 for (j
=0, fp2
= fp1
; j
<nchannels
; j
++, fp2
+= DEFDACBLKSIZE
)
736 int s
= SCALE16(*fp2
);
737 if (s
> 32767) s
= 32767;
738 else if (s
< -32767) s
= -32767;
753 post(PR_S PR_S PR_S PR_S PR_S PR_S PR_S PR_S
,
754 sp1
[0], sp1
[1], sp1
[2], sp1
[3], sp1
[4], sp1
[5], sp1
[6], sp1
[7]);
760 linux_dacs_write(linux_dacs
[dev
].d_fd
, buf
,
761 OSS_XFERSIZE(nchannels
, linux_dacs
[dev
].d_bytespersamp
));
764 if ((timenow
= sys_getrealtime()) - timeref
> 200)
766 post("dacslept %d",sys_getrealtime() - timeref
);
768 sys_log_error(ERR_DACSLEPT
);
769 else rtnval
= SENDDACS_SLEPT
;
774 thischan
+= nchannels
;
776 memset(sys_soundout
, 0,
777 sys_outchannels
* (sizeof(float) * DEFDACBLKSIZE
));
781 for (dev
= 0, thischan
= 0; dev
< linux_nindevs
; dev
++)
783 int nchannels
= linux_adcs
[dev
].d_nchannels
;
784 linux_adcs_read(linux_adcs
[dev
].d_fd
, buf
,
785 OSS_XFERSIZE(nchannels
, linux_adcs
[dev
].d_bytespersamp
));
788 if ((timenow
= sys_getrealtime()) - timeref
> 200)
791 sys_log_error(ERR_ADCSLEPT
);
793 rtnval
= SENDDACS_SLEPT
;
798 if (linux_adcs
[dev
].d_bytespersamp
== 4)
800 for (i
= DEFDACBLKSIZE
*nchannels
,
801 fp1
= sys_soundin
+ thischan
*DEFDACBLKSIZE
,
802 lp
= (t_oss_int32
*)buf
; i
--; fp1
++, lp
++)
804 *fp1
= ((t_sample
)(*lp
))*(t_sample
)(1./2147483648.);
809 for (i
= DEFDACBLKSIZE
,fp1
= sys_soundin
+ thischan
*DEFDACBLKSIZE
,
810 sp
= (t_oss_int16
*)buf
; i
--; fp1
++, sp
+= nchannels
)
812 for (j
=0;j
<sys_inchannels
;j
++)
813 fp1
[j
*DEFDACBLKSIZE
] = INVSCALE16(sp
[j
]);
816 thischan
+= nchannels
;
818 if (thischan
!= sys_inchannels
)
823 void oss_listdevs( void)
825 post("device listing not implemented in OSS yet\n");
828 void oss_getdevs(char *indevlist
, int *nindevs
,
829 char *outdevlist
, int *noutdevs
, int *canmulti
,
830 int maxndev
, int devdescsize
)
833 *canmulti
= 2; /* supports multiple devices */
834 if ((ndev
= oss_ndev
) > maxndev
)
836 for (i
= 0; i
< ndev
; i
++)
838 sprintf(indevlist
+ i
* devdescsize
, "OSS device #%d", i
+1);
839 sprintf(outdevlist
+ i
* devdescsize
, "OSS device #%d", i
+1);
841 *nindevs
= *noutdevs
= ndev
;