From ed932acb5860bf8b9296169676499562a55d139e Mon Sep 17 00:00:00 2001 From: Miller Puckette Date: Mon, 6 Sep 2004 20:20:36 +0000 Subject: checking in version 0.38test5. Oops, I realize I forgot some more nice files, will add them and re-commit. svn path=/trunk/; revision=2010 --- pd/src/s_audio_oss.c | 976 +++++++++++++++++++++++++-------------------------- 1 file changed, 488 insertions(+), 488 deletions(-) (limited to 'pd/src/s_audio_oss.c') 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,¶m) >= 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, ¶m) == -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, ¶m) == -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, ¶m) == -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, ¶m) == -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, ¶m) == -1) - error("OSS: SNDCTL_DSP_CHANNELS failed %s",devname); - else if (param == save) - return (param); + int save = param; + if (ioctl(fd, SNDCTL_DSP_CHANNELS, ¶m) == -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 - 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 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 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 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 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; } -- cgit v1.2.1