aboutsummaryrefslogtreecommitdiff
path: root/pd/src/s_audio_oss.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/src/s_audio_oss.c')
-rw-r--r--pd/src/s_audio_oss.c976
1 files changed, 488 insertions, 488 deletions
diff --git a/pd/src/s_audio_oss.c b/pd/src/s_audio_oss.c
index f0a86a45..21927f68 100644
--- a/pd/src/s_audio_oss.c
+++ b/pd/src/s_audio_oss.c
@@ -27,9 +27,9 @@
#define DEBUG(x) x
#define DEBUG2(x) {x;}
-#define OSS_MAXCHPERDEV 32 /* max channels per OSS device */
-#define OSS_MAXDEV 4 /* maximum number of input or output devices */
-#define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */
+#define OSS_MAXCHPERDEV 32 /* max channels per OSS device */
+#define OSS_MAXDEV 4 /* maximum number of input or output devices */
+#define OSS_DEFFRAGSIZE 256 /* default log fragment size (frames) */
#define OSS_DEFAUDIOBUF 40000 /* default audiobuffer, microseconds */
#define OSS_DEFAULTCH 2
#define RME_DEFAULTCH 8 /* need this even if RME undefined */
@@ -41,10 +41,10 @@ typedef int32_t t_oss_int32;
#define OSS_XFERSIZE(chans, width) (DEFDACBLKSIZE * (chans) * (width))
/* GLOBALS */
-static int linux_meters; /* true if we're metering */
-static float linux_inmax; /* max input amplitude */
-static float linux_outmax; /* max output amplitude */
-static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
+static int linux_meters; /* true if we're metering */
+static float linux_inmax; /* max input amplitude */
+static float linux_outmax; /* max output amplitude */
+static int linux_fragsize = 0; /* for block mode; block size (sample frames) */
/* our device handles */
@@ -52,9 +52,9 @@ typedef struct _oss_dev
{
int d_fd;
unsigned int d_space; /* bytes available for writing/reading */
- int d_bufsize; /* total buffer size in blocks for this device */
- int d_dropcount; /* # of buffers to drop for resync (output only) */
- unsigned int d_nchannels; /* number of channels for this device */
+ int d_bufsize; /* total buffer size in blocks for this device */
+ int d_dropcount; /* # of buffers to drop for resync (output only) */
+ unsigned int d_nchannels; /* number of channels for this device */
unsigned int d_bytespersamp; /* bytes per sample (2 for 16 bit, 4 for 32) */
} t_oss_dev;
@@ -69,8 +69,8 @@ t_sample *sys_soundout;
t_sample *sys_soundin;
/* OSS-specific private variables */
-static int oss_blockmode = 1; /* flag to use "blockmode" */
-static int oss_32bit = 0; /* allow 23 bit transfers in OSS */
+static int oss_blockmode = 1; /* flag to use "blockmode" */
+static int oss_32bit = 0; /* allow 23 bit transfers in OSS */
static char ossdsp[] = "/dev/dsp%d";
/* don't assume we can turn all 31 bits when doing float-to-fix;
@@ -92,19 +92,19 @@ void oss_init(void)
int fd, i;
static int countedthem = 0;
if (countedthem)
- return;
+ return;
for (i = 0; i < 10; i++)
{
- char devname[100];
- if (i == 0)
- strcpy(devname, "/dev/dsp");
- else sprintf(devname, "/dev/dsp%d", i);
- if ( (fd = open(devname, O_WRONLY|O_NONBLOCK)) != -1)
- {
- oss_ndev++;
- close(fd);
- }
- else break;
+ char devname[100];
+ if (i == 0)
+ strcpy(devname, "/dev/dsp");
+ else sprintf(devname, "/dev/dsp%d", i);
+ if ( (fd = open(devname, O_WRONLY|O_NONBLOCK)) != -1)
+ {
+ oss_ndev++;
+ close(fd);
+ }
+ else break;
}
countedthem = 1;
}
@@ -124,7 +124,7 @@ typedef struct _multidev {
int oss_reset(int fd) {
int err;
if ((err = ioctl(fd,SNDCTL_DSP_RESET)) < 0)
- error("OSS: Could not reset");
+ error("OSS: Could not reset");
return err;
}
@@ -150,101 +150,101 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
multiple soundcards
*/
- /* set resolution - first try 4 byte samples */
+ /* set resolution - first try 4 byte samples */
if (oss_32bit && (ioctl(fd,SNDCTL_DSP_GETFMTS,&param) >= 0) &&
- (param & AFMT_S32_BLOCKED))
+ (param & AFMT_S32_BLOCKED))
{
- wantformat = AFMT_S32_BLOCKED;
- dev->d_bytespersamp = 4;
+ wantformat = AFMT_S32_BLOCKED;
+ dev->d_bytespersamp = 4;
}
else
{
- wantformat = AFMT_S16_NE;
- dev->d_bytespersamp = 2;
+ wantformat = AFMT_S16_NE;
+ dev->d_bytespersamp = 2;
}
param = wantformat;
if (sys_verbose)
- post("bytes per sample = %d", dev->d_bytespersamp);
+ post("bytes per sample = %d", dev->d_bytespersamp);
if (ioctl(fd, SNDCTL_DSP_SETFMT, &param) == -1)
- fprintf(stderr,"OSS: Could not set DSP format\n");
+ fprintf(stderr,"OSS: Could not set DSP format\n");
else if (wantformat != param)
- fprintf(stderr,"OSS: DSP format: wanted %d, got %d\n",
- wantformat, param);
+ fprintf(stderr,"OSS: DSP format: wanted %d, got %d\n",
+ wantformat, param);
/* sample rate */
orig = param = srate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &param) == -1)
- fprintf(stderr,"OSS: Could not set sampling rate for device\n");
+ fprintf(stderr,"OSS: Could not set sampling rate for device\n");
else if( orig != param )
- fprintf(stderr,"OSS: sampling rate: wanted %d, got %d\n",
- orig, param );
+ fprintf(stderr,"OSS: sampling rate: wanted %d, got %d\n",
+ orig, param );
if (oss_blockmode && !skipblocksize)
{
- int fragbytes, logfragsize, nfragment;
- /* setting fragment count and size. */
- linux_fragsize = sys_blocksize;
- if (!linux_fragsize)
- {
- linux_fragsize = OSS_DEFFRAGSIZE;
- while (linux_fragsize > DEFDACBLKSIZE
- && linux_fragsize * 6 > sys_advance_samples)
- linux_fragsize = linux_fragsize/2;
- }
- /* post("adv_samples %d", sys_advance_samples); */
- nfragment = (sys_schedadvance * (44100. * 1.e-6)) / linux_fragsize;
-
- fragbytes = linux_fragsize * (dev->d_bytespersamp * nchannels);
- logfragsize = ilog2(fragbytes);
-
- if (fragbytes != (1 << logfragsize))
- post("warning: OSS takes only power of 2 blocksize; using %d",
- (1 << logfragsize)/(dev->d_bytespersamp * nchannels));
- if (sys_verbose)
- post("setting nfrags = %d, fragsize %d\n", nfragment, fragbytes);
-
- param = orig = (nfragment<<16) + logfragsize;
- if (ioctl(fd,SNDCTL_DSP_SETFRAGMENT, &param) == -1)
- error("OSS: Could not set or read fragment size\n");
- if (param != orig)
- {
- nfragment = ((param >> 16) & 0xffff);
- logfragsize = (param & 0xffff);
- post("warning: actual fragments %d, blocksize %d",
- nfragment, (1 << logfragsize));
- }
- if (sys_verbose)
- post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance));
+ int fragbytes, logfragsize, nfragment;
+ /* setting fragment count and size. */
+ linux_fragsize = sys_blocksize;
+ if (!linux_fragsize)
+ {
+ linux_fragsize = OSS_DEFFRAGSIZE;
+ while (linux_fragsize > DEFDACBLKSIZE
+ && linux_fragsize * 6 > sys_advance_samples)
+ linux_fragsize = linux_fragsize/2;
+ }
+ /* post("adv_samples %d", sys_advance_samples); */
+ nfragment = (sys_schedadvance * (44100. * 1.e-6)) / linux_fragsize;
+
+ fragbytes = linux_fragsize * (dev->d_bytespersamp * nchannels);
+ logfragsize = ilog2(fragbytes);
+
+ if (fragbytes != (1 << logfragsize))
+ post("warning: OSS takes only power of 2 blocksize; using %d",
+ (1 << logfragsize)/(dev->d_bytespersamp * nchannels));
+ if (sys_verbose)
+ post("setting nfrags = %d, fragsize %d\n", nfragment, fragbytes);
+
+ param = orig = (nfragment<<16) + logfragsize;
+ if (ioctl(fd,SNDCTL_DSP_SETFRAGMENT, &param) == -1)
+ error("OSS: Could not set or read fragment size\n");
+ if (param != orig)
+ {
+ nfragment = ((param >> 16) & 0xffff);
+ logfragsize = (param & 0xffff);
+ post("warning: actual fragments %d, blocksize %d",
+ nfragment, (1 << logfragsize));
+ }
+ if (sys_verbose)
+ post("audiobuffer set to %d msec", (int)(0.001 * sys_schedadvance));
}
if (dac)
{
- /* use "free space" to learn the buffer size. Normally you
- should set this to your own desired value; but this seems not
- to be implemented uniformly across different sound cards. LATER
- we should figure out what to do if the requested scheduler advance
- is greater than this buffer size; for now, we just print something
- out. */
-
- int defect;
- if (ioctl(fd, SOUND_PCM_GETOSPACE,&ainfo) < 0)
- fprintf(stderr,"OSS: ioctl on output device failed");
- dev->d_bufsize = ainfo.bytes;
-
- defect = sys_advance_samples * (dev->d_bytespersamp * nchannels)
- - dev->d_bufsize - OSS_XFERSIZE(nchannels, dev->d_bytespersamp);
- if (defect > 0)
- {
- if (sys_verbose || defect > (dev->d_bufsize >> 2))
- fprintf(stderr,
- "OSS: requested audio buffer size %d limited to %d\n",
- sys_advance_samples * (dev->d_bytespersamp * nchannels),
- dev->d_bufsize);
- sys_advance_samples =
- (dev->d_bufsize - OSS_XFERSAMPS(nchannels)) /
- (dev->d_bytespersamp *nchannels);
- }
+ /* use "free space" to learn the buffer size. Normally you
+ should set this to your own desired value; but this seems not
+ to be implemented uniformly across different sound cards. LATER
+ we should figure out what to do if the requested scheduler advance
+ is greater than this buffer size; for now, we just print something
+ out. */
+
+ int defect;
+ if (ioctl(fd, SOUND_PCM_GETOSPACE,&ainfo) < 0)
+ fprintf(stderr,"OSS: ioctl on output device failed");
+ dev->d_bufsize = ainfo.bytes;
+
+ defect = sys_advance_samples * (dev->d_bytespersamp * nchannels)
+ - dev->d_bufsize - OSS_XFERSIZE(nchannels, dev->d_bytespersamp);
+ if (defect > 0)
+ {
+ if (sys_verbose || defect > (dev->d_bufsize >> 2))
+ fprintf(stderr,
+ "OSS: requested audio buffer size %d limited to %d\n",
+ sys_advance_samples * (dev->d_bytespersamp * nchannels),
+ dev->d_bufsize);
+ sys_advance_samples =
+ (dev->d_bufsize - OSS_XFERSAMPS(nchannels)) /
+ (dev->d_bytespersamp *nchannels);
+ }
}
}
@@ -254,11 +254,11 @@ static int oss_setchannels(int fd, int wantchannels, char *devname)
while (param > 1)
{
- int save = param;
- if (ioctl(fd, SNDCTL_DSP_CHANNELS, &param) == -1)
- error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname);
- else if (param == save)
- return (param);
+ int save = param;
+ if (ioctl(fd, SNDCTL_DSP_CHANNELS, &param) == -1)
+ error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname);
+ else if (param == save)
+ return (param);
param = save - 1;
}
@@ -281,108 +281,108 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
audio_buf_info ainfo;
linux_nindevs = linux_noutdevs = 0;
- /* mark devices unopened */
+ /* mark devices unopened */
for (i = 0; i < OSS_MAXDEV; i++)
- linux_adcs[i].d_fd = linux_dacs[i].d_fd = -1;
+ linux_adcs[i].d_fd = linux_dacs[i].d_fd = -1;
/* open output devices */
wantmore=0;
if (noutdev < 0 || nindev < 0)
- bug("linux_open_audio");
+ bug("linux_open_audio");
for (n = 0; n < noutdev; n++)
{
- int gotchans, j, inindex = -1;
- int thisdevice = (outdev[n] >= 0 ? outdev[n] : 0);
- int wantchannels = (nchout>n) ? chout[n] : wantmore;
- fd = -1;
- if (!wantchannels)
- goto end_out_loop;
-
- if (thisdevice > 0)
- sprintf(devname, "/dev/dsp%d", thisdevice);
- else sprintf(devname, "/dev/dsp");
- /* search for input request for same device. Succeed only
- if the number of channels matches. */
- for (j = 0; j < nindev; j++)
- if (indev[j] == thisdevice && chin[j] == wantchannels)
- inindex = j;
-
- /* if the same device is requested for input and output,
- try to open it read/write */
- if (inindex >= 0)
- {
- sys_setalarm(1000000);
- if ((fd = open(devname, O_RDWR | O_AUDIOFLAG)) == -1)
- {
- post("%s (read/write): %s", devname, strerror(errno));
- post("(now will try write-only...)");
- }
- else
- {
- if (fcntl(fd, F_SETFD, 1) < 0)
- post("couldn't set close-on-exec flag on audio");
- if ((flags = fcntl(fd, F_GETFL)) < 0)
- post("couldn't get audio device flags");
- else if (fcntl(fd, F_SETFL, flags & (!O_NDELAY)) < 0)
- post("couldn't set audio device flags");
- if (sys_verbose)
- post("opened %s for reading and writing\n", devname);
- linux_adcs[inindex].d_fd = fd;
- }
- }
- /* if that didn't happen or if it failed, try write-only */
- if (fd == -1)
- {
- sys_setalarm(1000000);
- if ((fd = open(devname, O_WRONLY | O_AUDIOFLAG)) == -1)
- {
- post("%s (writeonly): %s",
- devname, strerror(errno));
- break;
- }
- if (fcntl(fd, F_SETFD, 1) < 0)
- post("couldn't set close-on-exec flag on audio");
- if ((flags = fcntl(fd, F_GETFL)) < 0)
- post("couldn't get audio device flags");
- else if (fcntl(fd, F_SETFL, flags & (!O_NDELAY)) < 0)
- post("couldn't set audio device flags");
- if (sys_verbose)
- post("opened %s for writing only\n", devname);
- }
- if (ioctl(fd, SNDCTL_DSP_GETCAPS, &capabilities) == -1)
- error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname);
-
- gotchans = oss_setchannels(fd,
- (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
- devname);
-
- if (sys_verbose)
- post("opened audio output on %s; got %d channels",
- devname, gotchans);
-
- if (gotchans < 2)
- {
- /* can't even do stereo? just give up. */
- close(fd);
- }
- else
- {
- linux_dacs[linux_noutdevs].d_nchannels = gotchans;
- linux_dacs[linux_noutdevs].d_fd = fd;
- oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
-
- linux_noutdevs++;
- outchannels += gotchans;
- if (inindex >= 0)
- {
- linux_adcs[inindex].d_nchannels = gotchans;
- chin[inindex] = gotchans;
- }
- }
- /* LATER think about spreading large numbers of channels over
- various dsp's and vice-versa */
- wantmore = wantchannels - gotchans;
+ int gotchans, j, inindex = -1;
+ int thisdevice = (outdev[n] >= 0 ? outdev[n] : 0);
+ int wantchannels = (nchout>n) ? chout[n] : wantmore;
+ fd = -1;
+ if (!wantchannels)
+ goto end_out_loop;
+
+ if (thisdevice > 0)
+ sprintf(devname, "/dev/dsp%d", thisdevice);
+ else sprintf(devname, "/dev/dsp");
+ /* search for input request for same device. Succeed only
+ if the number of channels matches. */
+ for (j = 0; j < nindev; j++)
+ if (indev[j] == thisdevice && chin[j] == wantchannels)
+ inindex = j;
+
+ /* if the same device is requested for input and output,
+ try to open it read/write */
+ if (inindex >= 0)
+ {
+ sys_setalarm(1000000);
+ if ((fd = open(devname, O_RDWR | O_AUDIOFLAG)) == -1)
+ {
+ post("%s (read/write): %s", devname, strerror(errno));
+ post("(now will try write-only...)");
+ }
+ else
+ {
+ if (fcntl(fd, F_SETFD, 1) < 0)
+ post("couldn't set close-on-exec flag on audio");
+ if ((flags = fcntl(fd, F_GETFL)) < 0)
+ post("couldn't get audio device flags");
+ else if (fcntl(fd, F_SETFL, flags & (!O_NDELAY)) < 0)
+ post("couldn't set audio device flags");
+ if (sys_verbose)
+ post("opened %s for reading and writing\n", devname);
+ linux_adcs[inindex].d_fd = fd;
+ }
+ }
+ /* if that didn't happen or if it failed, try write-only */
+ if (fd == -1)
+ {
+ sys_setalarm(1000000);
+ if ((fd = open(devname, O_WRONLY | O_AUDIOFLAG)) == -1)
+ {
+ post("%s (writeonly): %s",
+ devname, strerror(errno));
+ break;
+ }
+ if (fcntl(fd, F_SETFD, 1) < 0)
+ post("couldn't set close-on-exec flag on audio");
+ if ((flags = fcntl(fd, F_GETFL)) < 0)
+ post("couldn't get audio device flags");
+ else if (fcntl(fd, F_SETFL, flags & (!O_NDELAY)) < 0)
+ post("couldn't set audio device flags");
+ if (sys_verbose)
+ post("opened %s for writing only\n", devname);
+ }
+ if (ioctl(fd, SNDCTL_DSP_GETCAPS, &capabilities) == -1)
+ error("OSS: SNDCTL_DSP_GETCAPS failed %s", devname);
+
+ gotchans = oss_setchannels(fd,
+ (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
+ devname);
+
+ if (sys_verbose)
+ post("opened audio output on %s; got %d channels",
+ devname, gotchans);
+
+ if (gotchans < 2)
+ {
+ /* can't even do stereo? just give up. */
+ close(fd);
+ }
+ else
+ {
+ linux_dacs[linux_noutdevs].d_nchannels = gotchans;
+ linux_dacs[linux_noutdevs].d_fd = fd;
+ oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
+
+ linux_noutdevs++;
+ outchannels += gotchans;
+ if (inindex >= 0)
+ {
+ linux_adcs[inindex].d_nchannels = gotchans;
+ chin[inindex] = gotchans;
+ }
+ }
+ /* LATER think about spreading large numbers of channels over
+ various dsp's and vice-versa */
+ wantmore = wantchannels - gotchans;
end_out_loop: ;
}
@@ -390,67 +390,67 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
wantmore = 0;
for (n = 0; n < nindev; n++)
{
- int gotchans=0;
- int thisdevice = (indev[n] >= 0 ? indev[n] : 0);
- int wantchannels = (nchin>n)?chin[n]:wantmore;
- int alreadyopened = 0;
- if (!wantchannels)
- goto end_in_loop;
-
- if (thisdevice > 0)
- sprintf(devname, "/dev/dsp%d", thisdevice);
- else sprintf(devname, "/dev/dsp");
-
- sys_setalarm(1000000);
-
- /* perhaps it's already open from the above? */
- if (linux_dacs[n].d_fd >= 0)
- {
- fd = linux_adcs[n].d_fd;
- alreadyopened = 1;
- }
- else
- {
- /* otherwise try to open it here. */
- if ((fd = open(devname, O_RDONLY | O_AUDIOFLAG)) == -1)
- {
- post("%s (readonly): %s", devname, strerror(errno));
- goto end_in_loop;
- }
- if (fcntl(fd, F_SETFD, 1) < 0)
- post("couldn't set close-on-exec flag on audio");
- if ((flags = fcntl(fd, F_GETFL)) < 0)
- post("couldn't get audio device flags");
- else if (fcntl(fd, F_SETFL, flags & (!O_NDELAY)) < 0)
- post("couldn't set audio device flags");
- if (sys_verbose)
- post("opened %s for reading only\n", devname);
- }
- linux_adcs[linux_nindevs].d_fd = fd;
-
- gotchans = oss_setchannels(fd,
- (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
- devname);
- if (sys_verbose)
- post("opened audio input device %s; got %d channels",
- devname, gotchans);
-
- if (gotchans < 1)
- {
- close(fd);
- goto end_in_loop;
- }
-
- linux_adcs[linux_nindevs].d_nchannels = gotchans;
-
- oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
-
- inchannels += gotchans;
- linux_nindevs++;
-
- wantmore = wantchannels-gotchans;
- /* LATER think about spreading large numbers of channels over
- various dsp's and vice-versa */
+ int gotchans=0;
+ int thisdevice = (indev[n] >= 0 ? indev[n] : 0);
+ int wantchannels = (nchin>n)?chin[n]:wantmore;
+ int alreadyopened = 0;
+ if (!wantchannels)
+ goto end_in_loop;
+
+ if (thisdevice > 0)
+ sprintf(devname, "/dev/dsp%d", thisdevice);
+ else sprintf(devname, "/dev/dsp");
+
+ sys_setalarm(1000000);
+
+ /* perhaps it's already open from the above? */
+ if (linux_dacs[n].d_fd >= 0)
+ {
+ fd = linux_adcs[n].d_fd;
+ alreadyopened = 1;
+ }
+ else
+ {
+ /* otherwise try to open it here. */
+ if ((fd = open(devname, O_RDONLY | O_AUDIOFLAG)) == -1)
+ {
+ post("%s (readonly): %s", devname, strerror(errno));
+ goto end_in_loop;
+ }
+ if (fcntl(fd, F_SETFD, 1) < 0)
+ post("couldn't set close-on-exec flag on audio");
+ if ((flags = fcntl(fd, F_GETFL)) < 0)
+ post("couldn't get audio device flags");
+ else if (fcntl(fd, F_SETFL, flags & (!O_NDELAY)) < 0)
+ post("couldn't set audio device flags");
+ if (sys_verbose)
+ post("opened %s for reading only\n", devname);
+ }
+ linux_adcs[linux_nindevs].d_fd = fd;
+
+ gotchans = oss_setchannels(fd,
+ (wantchannels>OSS_MAXCHPERDEV)?OSS_MAXCHPERDEV:wantchannels,
+ devname);
+ if (sys_verbose)
+ post("opened audio input device %s; got %d channels",
+ devname, gotchans);
+
+ if (gotchans < 1)
+ {
+ close(fd);
+ goto end_in_loop;
+ }
+
+ linux_adcs[linux_nindevs].d_nchannels = gotchans;
+
+ oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
+
+ inchannels += gotchans;
+ linux_nindevs++;
+
+ wantmore = wantchannels-gotchans;
+ /* LATER think about spreading large numbers of channels over
+ various dsp's and vice-versa */
end_in_loop: ;
}
@@ -463,24 +463,24 @@ int oss_open_audio(int nindev, int *indev, int nchin, int *chin,
if (linux_nindevs)
{
- if (sys_verbose)
- fprintf(stderr,("OSS: issuing first ADC 'read' ... "));
- read(linux_adcs[0].d_fd, buf,
- linux_adcs[0].d_bytespersamp *
- linux_adcs[0].d_nchannels * DEFDACBLKSIZE);
- if (sys_verbose)
- fprintf(stderr, "...done.\n");
+ if (sys_verbose)
+ fprintf(stderr,("OSS: issuing first ADC 'read' ... "));
+ read(linux_adcs[0].d_fd, buf,
+ linux_adcs[0].d_bytespersamp *
+ linux_adcs[0].d_nchannels * DEFDACBLKSIZE);
+ if (sys_verbose)
+ fprintf(stderr, "...done.\n");
}
- /* now go and fill all the output buffers. */
+ /* now go and fill all the output buffers. */
for (i = 0; i < linux_noutdevs; i++)
{
- int j;
- memset(buf, 0, linux_dacs[i].d_bytespersamp *
- linux_dacs[i].d_nchannels * DEFDACBLKSIZE);
- for (j = 0; j < sys_advance_samples/DEFDACBLKSIZE; j++)
- write(linux_dacs[i].d_fd, buf,
- linux_dacs[i].d_bytespersamp *
- linux_dacs[i].d_nchannels * DEFDACBLKSIZE);
+ int j;
+ memset(buf, 0, linux_dacs[i].d_bytespersamp *
+ linux_dacs[i].d_nchannels * DEFDACBLKSIZE);
+ for (j = 0; j < sys_advance_samples/DEFDACBLKSIZE; j++)
+ write(linux_dacs[i].d_fd, buf,
+ linux_dacs[i].d_bytespersamp *
+ linux_dacs[i].d_nchannels * DEFDACBLKSIZE);
}
sys_setalarm(0);
sys_inchannels = inchannels;
@@ -492,7 +492,7 @@ void oss_close_audio( void)
{
int i;
for (i=0;i<linux_nindevs;i++)
- close(linux_adcs[i].d_fd);
+ close(linux_adcs[i].d_fd);
for (i=0;i<linux_noutdevs;i++)
close(linux_dacs[i].d_fd);
@@ -517,17 +517,17 @@ static void oss_calcspace(void)
audio_buf_info ainfo;
for (dev=0; dev < linux_noutdevs; dev++)
{
- if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
- fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
- linux_dacs[dev].d_space = ainfo.bytes;
+ if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
+ fprintf(stderr,"OSS: ioctl on output device %d failed",dev);
+ linux_dacs[dev].d_space = ainfo.bytes;
}
for (dev = 0; dev < linux_nindevs; dev++)
{
- if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE,&ainfo) < 0)
- fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
- dev, linux_adcs[dev].d_fd);
- linux_adcs[dev].d_space = ainfo.bytes;
+ if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE,&ainfo) < 0)
+ fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
+ dev, linux_adcs[dev].d_fd);
+ linux_adcs[dev].d_space = ainfo.bytes;
}
}
@@ -536,12 +536,12 @@ void linux_audiostatus(void)
int dev;
if (!oss_blockmode)
{
- oss_calcspace();
- for (dev=0; dev < linux_noutdevs; dev++)
- fprintf(stderr, "dac %d space %d\n", dev, linux_dacs[dev].d_space);
+ oss_calcspace();
+ for (dev=0; dev < linux_noutdevs; dev++)
+ fprintf(stderr, "dac %d space %d\n", dev, linux_dacs[dev].d_space);
- for (dev = 0; dev < linux_nindevs; dev++)
- fprintf(stderr, "adc %d space %d\n", dev, linux_adcs[dev].d_space);
+ for (dev = 0; dev < linux_nindevs; dev++)
+ fprintf(stderr, "adc %d space %d\n", dev, linux_adcs[dev].d_space);
}
}
@@ -555,75 +555,75 @@ static void oss_doresync( void)
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
audio_buf_info ainfo;
- /* 1. if any input devices are ahead (have more than 1 buffer stored),
- drop one or more buffers worth */
+ /* 1. if any input devices are ahead (have more than 1 buffer stored),
+ drop one or more buffers worth */
for (dev = 0; dev < linux_nindevs; dev++)
{
- if (linux_adcs[dev].d_space == 0)
- {
- linux_adcs_read(linux_adcs[dev].d_fd, buf,
- OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
- linux_adcs[dev].d_bytespersamp));
- }
- else while (linux_adcs[dev].d_space >
- OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
- linux_adcs[dev].d_bytespersamp))
- {
- linux_adcs_read(linux_adcs[dev].d_fd, buf,
- OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
- linux_adcs[dev].d_bytespersamp));
- if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE, &ainfo) < 0)
- {
- fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
- dev, linux_adcs[dev].d_fd);
- break;
- }
- linux_adcs[dev].d_space = ainfo.bytes;
- }
+ if (linux_adcs[dev].d_space == 0)
+ {
+ linux_adcs_read(linux_adcs[dev].d_fd, buf,
+ OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
+ linux_adcs[dev].d_bytespersamp));
+ }
+ else while (linux_adcs[dev].d_space >
+ OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
+ linux_adcs[dev].d_bytespersamp))
+ {
+ linux_adcs_read(linux_adcs[dev].d_fd, buf,
+ OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
+ linux_adcs[dev].d_bytespersamp));
+ if (ioctl(linux_adcs[dev].d_fd, SOUND_PCM_GETISPACE, &ainfo) < 0)
+ {
+ fprintf(stderr, "OSS: ioctl on input device %d, fd %d failed",
+ dev, linux_adcs[dev].d_fd);
+ break;
+ }
+ linux_adcs[dev].d_space = ainfo.bytes;
+ }
}
- /* 2. if any output devices are behind, feed them zeros to catch them
- up */
+ /* 2. if any output devices are behind, feed them zeros to catch them
+ up */
for (dev = 0; dev < linux_noutdevs; dev++)
{
- while (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
- sys_advance_samples * (linux_dacs[dev].d_nchannels *
- linux_dacs[dev].d_bytespersamp))
- {
- if (!zeroed)
- {
- unsigned int i;
- for (i = 0; i < OSS_XFERSAMPS(linux_dacs[dev].d_nchannels);
- i++)
- buf[i] = 0;
- zeroed = 1;
- }
- linux_dacs_write(linux_dacs[dev].d_fd, buf,
- OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
- linux_dacs[dev].d_bytespersamp));
- if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
- {
- fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
- dev, linux_dacs[dev].d_fd);
- break;
- }
- linux_dacs[dev].d_space = ainfo.bytes;
- }
+ while (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
+ sys_advance_samples * (linux_dacs[dev].d_nchannels *
+ linux_dacs[dev].d_bytespersamp))
+ {
+ if (!zeroed)
+ {
+ unsigned int i;
+ for (i = 0; i < OSS_XFERSAMPS(linux_dacs[dev].d_nchannels);
+ i++)
+ buf[i] = 0;
+ zeroed = 1;
+ }
+ linux_dacs_write(linux_dacs[dev].d_fd, buf,
+ OSS_XFERSIZE(linux_dacs[dev].d_nchannels,
+ linux_dacs[dev].d_bytespersamp));
+ if (ioctl(linux_dacs[dev].d_fd, SOUND_PCM_GETOSPACE, &ainfo) < 0)
+ {
+ fprintf(stderr, "OSS: ioctl on output device %d, fd %d failed",
+ dev, linux_dacs[dev].d_fd);
+ break;
+ }
+ linux_dacs[dev].d_space = ainfo.bytes;
+ }
}
- /* 3. if any DAC devices are too far ahead, plan to drop the
- number of frames which will let the others catch up. */
+ /* 3. if any DAC devices are too far ahead, plan to drop the
+ number of frames which will let the others catch up. */
for (dev = 0; dev < linux_noutdevs; dev++)
{
- if (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
- (sys_advance_samples - 1) * linux_dacs[dev].d_nchannels *
- linux_dacs[dev].d_bytespersamp)
- {
- linux_dacs[dev].d_dropcount = sys_advance_samples - 1 -
- (linux_dacs[dev].d_space - linux_dacs[dev].d_bufsize) /
- (linux_dacs[dev].d_nchannels *
- linux_dacs[dev].d_bytespersamp) ;
- }
- else linux_dacs[dev].d_dropcount = 0;
+ if (linux_dacs[dev].d_space > linux_dacs[dev].d_bufsize -
+ (sys_advance_samples - 1) * linux_dacs[dev].d_nchannels *
+ linux_dacs[dev].d_bytespersamp)
+ {
+ linux_dacs[dev].d_dropcount = sys_advance_samples - 1 -
+ (linux_dacs[dev].d_space - linux_dacs[dev].d_bufsize) /
+ (linux_dacs[dev].d_nchannels *
+ linux_dacs[dev].d_bytespersamp) ;
+ }
+ else linux_dacs[dev].d_dropcount = 0;
}
}
@@ -635,188 +635,188 @@ int oss_send_dacs(void)
char buf[OSS_MAXSAMPLEWIDTH * DEFDACBLKSIZE * OSS_MAXCHPERDEV];
t_oss_int16 *sp;
t_oss_int32 *lp;
- /* the maximum number of samples we should have in the ADC buffer */
+ /* the maximum number of samples we should have in the ADC buffer */
int idle = 0;
int thischan;
double timeref, timenow;
if (!linux_nindevs && !linux_noutdevs)
- return (SENDDACS_NO);
+ return (SENDDACS_NO);
if (!oss_blockmode)
{
- /* determine whether we're idle. This is true if either (1)
- some input device has less than one buffer to read or (2) some
- output device has fewer than (sys_advance_samples) blocks buffered
- already. */
- oss_calcspace();
+ /* determine whether we're idle. This is true if either (1)
+ some input device has less than one buffer to read or (2) some
+ output device has fewer than (sys_advance_samples) blocks buffered
+ already. */
+ oss_calcspace();
- for (dev=0; dev < linux_noutdevs; dev++)
- if (linux_dacs[dev].d_dropcount ||
- (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space >
- sys_advance_samples * linux_dacs[dev].d_bytespersamp *
- linux_dacs[dev].d_nchannels))
- idle = 1;
- for (dev=0; dev < linux_nindevs; dev++)
- if (linux_adcs[dev].d_space <
- OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
- linux_adcs[dev].d_bytespersamp))
- idle = 1;
+ for (dev=0; dev < linux_noutdevs; dev++)
+ if (linux_dacs[dev].d_dropcount ||
+ (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space >
+ sys_advance_samples * linux_dacs[dev].d_bytespersamp *
+ linux_dacs[dev].d_nchannels))
+ idle = 1;
+ for (dev=0; dev < linux_nindevs; dev++)
+ if (linux_adcs[dev].d_space <
+ OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
+ linux_adcs[dev].d_bytespersamp))
+ idle = 1;
}
if (idle && !oss_blockmode)
{
- /* sometimes---rarely---when the ADC available-byte-count is
- zero, it's genuine, but usually it's because we're so
- late that the ADC has overrun its entire kernel buffer. We
- distinguish between the two by waiting 2 msec and asking again.
- There should be an error flag we could check instead; look for this
- someday... */
- for (dev = 0;dev < linux_nindevs; dev++)
- if (linux_adcs[dev].d_space == 0)
- {
- audio_buf_info ainfo;
- sys_microsleep(2000);
- oss_calcspace();
- if (linux_adcs[dev].d_space != 0) continue;
-
- /* here's the bad case. Give up and resync. */
- sys_log_error(ERR_DATALATE);
- oss_doresync();
- return (SENDDACS_NO);
- }
- /* check for slippage between devices, either because
- data got lost in the driver from a previous late condition, or
- because the devices aren't synced. When we're idle, no
- input device should have more than one buffer readable and
- no output device should have less than sys_advance_samples-1
- */
-
- for (dev=0; dev < linux_noutdevs; dev++)
- if (!linux_dacs[dev].d_dropcount &&
- (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space <
- (sys_advance_samples - 2) *
- (linux_dacs[dev].d_bytespersamp *
- linux_dacs[dev].d_nchannels)))
- goto badsync;
- for (dev=0; dev < linux_nindevs; dev++)
- if (linux_adcs[dev].d_space > 3 *
- OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
- linux_adcs[dev].d_bytespersamp))
- goto badsync;
-
- /* return zero to tell the scheduler we're idle. */
- return (SENDDACS_NO);
+ /* sometimes---rarely---when the ADC available-byte-count is
+ zero, it's genuine, but usually it's because we're so
+ late that the ADC has overrun its entire kernel buffer. We
+ distinguish between the two by waiting 2 msec and asking again.
+ There should be an error flag we could check instead; look for this
+ someday... */
+ for (dev = 0;dev < linux_nindevs; dev++)
+ if (linux_adcs[dev].d_space == 0)
+ {
+ audio_buf_info ainfo;
+ sys_microsleep(2000);
+ oss_calcspace();
+ if (linux_adcs[dev].d_space != 0) continue;
+
+ /* here's the bad case. Give up and resync. */
+ sys_log_error(ERR_DATALATE);
+ oss_doresync();
+ return (SENDDACS_NO);
+ }
+ /* check for slippage between devices, either because
+ data got lost in the driver from a previous late condition, or
+ because the devices aren't synced. When we're idle, no
+ input device should have more than one buffer readable and
+ no output device should have less than sys_advance_samples-1
+ */
+
+ for (dev=0; dev < linux_noutdevs; dev++)
+ if (!linux_dacs[dev].d_dropcount &&
+ (linux_dacs[dev].d_bufsize - linux_dacs[dev].d_space <
+ (sys_advance_samples - 2) *
+ (linux_dacs[dev].d_bytespersamp *
+ linux_dacs[dev].d_nchannels)))
+ goto badsync;
+ for (dev=0; dev < linux_nindevs; dev++)
+ if (linux_adcs[dev].d_space > 3 *
+ OSS_XFERSIZE(linux_adcs[dev].d_nchannels,
+ linux_adcs[dev].d_bytespersamp))
+ goto badsync;
+
+ /* return zero to tell the scheduler we're idle. */
+ return (SENDDACS_NO);
badsync:
- sys_log_error(ERR_RESYNC);
- oss_doresync();
- return (SENDDACS_NO);
-
+ sys_log_error(ERR_RESYNC);
+ oss_doresync();
+ return (SENDDACS_NO);
+
}
- /* do output */
+ /* do output */
timeref = sys_getrealtime();
for (dev=0, thischan = 0; dev < linux_noutdevs; dev++)
{
- int nchannels = linux_dacs[dev].d_nchannels;
- if (linux_dacs[dev].d_dropcount)
- linux_dacs[dev].d_dropcount--;
- else
- {
- if (linux_dacs[dev].d_bytespersamp == 4)
- {
- for (i = DEFDACBLKSIZE * nchannels, fp1 = sys_soundout +
- DEFDACBLKSIZE*thischan,
- lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
- {
- float f = *fp1 * 2147483648.;
- *lp = (f >= 2147483647. ? 2147483647. :
- (f < -2147483648. ? -2147483648. : f));
- }
- }
- else
- {
- for (i = DEFDACBLKSIZE, fp1 = sys_soundout +
- DEFDACBLKSIZE*thischan,
- sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
- {
- for (j=0, fp2 = fp1; j<nchannels; j++, fp2 += DEFDACBLKSIZE)
- {
- int s = *fp2 * 32767.;
- if (s > 32767) s = 32767;
- else if (s < -32767) s = -32767;
- sp[j] = s;
- }
- }
- }
- linux_dacs_write(linux_dacs[dev].d_fd, buf,
- OSS_XFERSIZE(nchannels, linux_dacs[dev].d_bytespersamp));
- if ((timenow = sys_getrealtime()) - timeref > 0.002)
- {
- if (!oss_blockmode)
- sys_log_error(ERR_DACSLEPT);
- else rtnval = SENDDACS_SLEPT;
- }
- timeref = timenow;
- }
- thischan += nchannels;
+ int nchannels = linux_dacs[dev].d_nchannels;
+ if (linux_dacs[dev].d_dropcount)
+ linux_dacs[dev].d_dropcount--;
+ else
+ {
+ if (linux_dacs[dev].d_bytespersamp == 4)
+ {
+ for (i = DEFDACBLKSIZE * nchannels, fp1 = sys_soundout +
+ DEFDACBLKSIZE*thischan,
+ lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
+ {
+ float f = *fp1 * 2147483648.;
+ *lp = (f >= 2147483647. ? 2147483647. :
+ (f < -2147483648. ? -2147483648. : f));
+ }
+ }
+ else
+ {
+ for (i = DEFDACBLKSIZE, fp1 = sys_soundout +
+ DEFDACBLKSIZE*thischan,
+ sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
+ {
+ for (j=0, fp2 = fp1; j<nchannels; j++, fp2 += DEFDACBLKSIZE)
+ {
+ int s = *fp2 * 32767.;
+ if (s > 32767) s = 32767;
+ else if (s < -32767) s = -32767;
+ sp[j] = s;
+ }
+ }
+ }
+ linux_dacs_write(linux_dacs[dev].d_fd, buf,
+ OSS_XFERSIZE(nchannels, linux_dacs[dev].d_bytespersamp));
+ if ((timenow = sys_getrealtime()) - timeref > 0.002)
+ {
+ if (!oss_blockmode)
+ sys_log_error(ERR_DACSLEPT);
+ else rtnval = SENDDACS_SLEPT;
+ }
+ timeref = timenow;
+ }
+ thischan += nchannels;
}
memset(sys_soundout, 0,
- sys_outchannels * (sizeof(float) * DEFDACBLKSIZE));
+ sys_outchannels * (sizeof(float) * DEFDACBLKSIZE));
- /* do input */
+ /* do input */
for (dev = 0, thischan = 0; dev < linux_nindevs; dev++)
{
- int nchannels = linux_adcs[dev].d_nchannels;
- linux_adcs_read(linux_adcs[dev].d_fd, buf,
- OSS_XFERSIZE(nchannels, linux_adcs[dev].d_bytespersamp));
-
- if ((timenow = sys_getrealtime()) - timeref > 0.002)
- {
- if (!oss_blockmode)
- sys_log_error(ERR_ADCSLEPT);
- else
- rtnval = SENDDACS_SLEPT;
- }
- timeref = timenow;
-
- if (linux_adcs[dev].d_bytespersamp == 4)
- {
- for (i = DEFDACBLKSIZE*nchannels,
- fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
- lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
- {
- *fp1 = ((float)(*lp))*(float)(1./2147483648.);
- }
- }
- else
- {
- for (i = DEFDACBLKSIZE,fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
- sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
- {
- for (j=0;j<nchannels;j++)
- fp1[j*DEFDACBLKSIZE] = (float)sp[j]*(float)3.051850e-05;
- }
- }
- thischan += nchannels;
+ int nchannels = linux_adcs[dev].d_nchannels;
+ linux_adcs_read(linux_adcs[dev].d_fd, buf,
+ OSS_XFERSIZE(nchannels, linux_adcs[dev].d_bytespersamp));
+
+ if ((timenow = sys_getrealtime()) - timeref > 0.002)
+ {
+ if (!oss_blockmode)
+ sys_log_error(ERR_ADCSLEPT);
+ else
+ rtnval = SENDDACS_SLEPT;
+ }
+ timeref = timenow;
+
+ if (linux_adcs[dev].d_bytespersamp == 4)
+ {
+ for (i = DEFDACBLKSIZE*nchannels,
+ fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
+ lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
+ {
+ *fp1 = ((float)(*lp))*(float)(1./2147483648.);
+ }
+ }
+ else
+ {
+ for (i = DEFDACBLKSIZE,fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
+ sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
+ {
+ for (j=0;j<nchannels;j++)
+ fp1[j*DEFDACBLKSIZE] = (float)sp[j]*(float)3.051850e-05;
+ }
+ }
+ thischan += nchannels;
}
return (rtnval);
}
void oss_getdevs(char *indevlist, int *nindevs,
char *outdevlist, int *noutdevs, int *canmulti,
- int maxndev, int devdescsize)
+ int maxndev, int devdescsize)
{
int i, ndev;
*canmulti = 2; /* supports multiple devices */
if ((ndev = oss_ndev) > maxndev)
- ndev = maxndev;
+ ndev = maxndev;
for (i = 0; i < ndev; i++)
{
- sprintf(indevlist + i * devdescsize, "OSS device #%d", i+1);
- sprintf(outdevlist + i * devdescsize, "OSS device #%d", i+1);
+ sprintf(indevlist + i * devdescsize, "OSS device #%d", i+1);
+ sprintf(outdevlist + i * devdescsize, "OSS device #%d", i+1);
}
*nindevs = *noutdevs = ndev;
}