On Thu, Feb 04, 2010 at 08:08:32PM +0100, Alexandre Ratchov wrote: > On Thu, Feb 04, 2010 at 02:42:33PM +0000, Jacob Meuser wrote: > > On Thu, Feb 04, 2010 at 10:20:40AM +0100, Alexandre Ratchov wrote: > > > On Wed, Feb 03, 2010 at 04:10:48PM +0000, Jacob Meuser wrote: > > > > I wonder if these problems would go away if jack support were dropped > > > > from portaudio. only working with 32-bit sounds suspicious. > > > > > > > > > > that's easy to check by disabling it, I'll try it.. > > > > > > AFAIU, ALSA supports any format and seldom triggers > > > conversion code of audacity and/or portaudio. > > > > > > sndio backend uses sio_getacap() to return native parameters > > > and lets portaudio/audacity do the necessary conversions, > > > since it claims it can. As far as I understand portaudio > > > internals, this is the ``right thing''. So I bet we trigger > > > various bugs. > > > > > > I don't exclude there's a bug in sndio backend though. But, > > > I wonder whether we shouldn't just claim that any format is > > > supported and stop using sio_getcap() here. > > > > that might cause other problems if aucat isn't used? > > that shouldn't be a problem. Portaudio exposes the result of > sio_getpar() to allow the app to display a nice drop-down > list with the supported parameters. > > But if sio_setpar() fails, it will setup the appropriate > conversion layer. > > AFAIU, audacity is misusing this mechanism. Not sure yet. > I'm trying this right now... >
Indeed removing sio_getcap() fixes all these problems. If I try to record mono on a stereo only device, it just displays a pop-up with ``format not supported''. With this diff, I don't observe hangs caused by sample rate mismatch anymore. -- Alexandre Index: Makefile =================================================================== RCS file: /cvs/ports/audio/portaudio-svn/Makefile,v retrieving revision 1.6 diff -u -p -r1.6 Makefile --- Makefile 14 Mar 2009 02:31:40 -0000 1.6 +++ Makefile 4 Feb 2010 20:05:35 -0000 @@ -2,6 +2,7 @@ COMMENT= portable cross-platform audio API DISTNAME= portaudio-svn-1406 +PKGNAME= ${DISTNAME}p3 SHARED_LIBS= portaudio 0.0 Index: files/pa_sndio.c =================================================================== RCS file: /cvs/ports/audio/portaudio-svn/files/pa_sndio.c,v retrieving revision 1.1 diff -u -p -r1.1 pa_sndio.c --- files/pa_sndio.c 14 Mar 2009 02:31:40 -0000 1.1 +++ files/pa_sndio.c 4 Feb 2010 20:05:35 -0000 @@ -61,12 +61,11 @@ typedef struct PaSndioHostApiRepresentat PaUtilStreamInterface callback; PaUtilStreamInterface blocking; /* - * libsndio has no device discovery mechanism, so expose only + * sndio has no device discovery mechanism, so expose only * the default device, the user will have a chance to change it * using the environment variable */ PaDeviceInfo *infos[1], default_info; - struct sio_cap *caps[1], default_cap; } PaSndioHostApiRepresentation; /* @@ -81,7 +80,7 @@ sndioOnMove(void *addr, int delta) } /* - * convert PA encoding to libsndio encoding, retrun true on success + * convert PA encoding to sndio encoding, retrun true on success */ static int sndioSetFmt(struct sio_par *sio, PaSampleFormat fmt) @@ -118,7 +117,7 @@ sndioSetFmt(struct sio_par *sio, PaSampl } /* - * convert libsndio encoding to PA encoding, retrun true on success + * convert sndio encoding to PA encoding, retrun true on success */ static int sndioGetFmt(struct sio_par *sio, PaSampleFormat *fmt) @@ -139,7 +138,7 @@ sndioGetFmt(struct sio_par *sio, PaSampl case 24: if (!sio->sig) return 0; - *fmt = paInt24; + *fmt = (sio->bps == 3) ? paInt24 : paInt32; break; case 16: if (!sio->sig) @@ -371,8 +370,7 @@ OpenStream(struct PaUtilHostApiRepresent return paInsufficientMemory; } } - s->base.streamInfo.inputLatency = (mode & SIO_REC) ? - (double)(par.bufsz + PaUtil_GetBufferProcessorInputLatency(&s->bufproc)) / (double)par.rate : 0; + s->base.streamInfo.inputLatency = 0; s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ? (double)(par.bufsz + PaUtil_GetBufferProcessorOutputLatency(&s->bufproc)) / (double)par.rate : 0; s->base.streamInfo.sampleRate = par.rate; @@ -490,8 +488,10 @@ BlockingGetStreamWriteAvailable(PaStream static PaError BlockingWaitEmpty( PaStream *stream ) { + PaSndioStream *s = (PaSndioStream *)stream; + /* - * drain playback buffers; libsndio always does it in background + * drain playback buffers; sndio always does it in background * and there is no way to wait for completion */ DPR("BlockingWaitEmpty: s=%d, a=%d\n", s->stopped, s->active); @@ -630,61 +630,6 @@ IsFormatSupported(struct PaUtilHostApiRe const PaStreamParameters *outputPar, double sampleRate) { - PaSndioHostApiRepresentation *sndioHostApi = (PaSndioHostApiRepresentation *)hostApi; - struct sio_cap *cap = sndioHostApi->caps[0]; - struct sio_conf *cf = &cap->confs[0]; - unsigned i; - - - if (inputPar && inputPar->channelCount > 0) { - if (inputPar->device != 0) { - DPR("IsFormatSupported: %d: bad input device\n", inputPar->device); - return paInvalidDevice; - } - if (inputPar->hostApiSpecificStreamInfo) { - DPR("IsFormatSupported: input specific info\n"); - return paIncompatibleHostApiSpecificStreamInfo; - } - for (i = 0; ; i++) { - if (i == 8 * sizeof(unsigned)) { - DPR("IsFormatSupported: input channel not found\n"); - return paInvalidChannelCount; - } - if ((cf->rchan & (1 << i)) && - (cap->rchan[i] == inputPar->channelCount)) - break; - } - } - if (outputPar && outputPar->channelCount > 0) { - if (outputPar->device != 0) { - DPR("IsFormatSupported: %d: bad output device\n", outputPar->device); - return paInvalidDevice; - } - if (outputPar->hostApiSpecificStreamInfo) { - DPR("IsFormatSupported: output specific info\n"); - return paIncompatibleHostApiSpecificStreamInfo; - } - for (i = 0; ; i++) { - if (i == 8 * sizeof(unsigned)) { - DPR("IsFormatSupported: output channel not found\n"); - return paInvalidChannelCount; - } - if ((cf->pchan & (1 << i)) && - (cap->pchan[i] == outputPar->channelCount)) - break; - } - } - - for (i = 0; ; i++) { - if (i == 8 * sizeof(unsigned)) { - DPR("IsFormatSupported: rate not found\n"); - return paInvalidSampleRate; - } - if ((cf->rate & (1 << i)) && - (double)cap->rate[i] > sampleRate * 0.995 && - (double)cap->rate[i] < sampleRate * 1.005) - break; - } return paFormatIsSupported; } @@ -700,9 +645,6 @@ PaSndio_Initialize(PaUtilHostApiRepresen PaSndioHostApiRepresentation *sndioHostApi; PaDeviceInfo *info; struct sio_hdl *hdl; - struct sio_cap *cap; - struct sio_conf *cf; - unsigned i, maxpchan, maxrchan, maxrate; DPR("PaSndio_Initialize: initializing...\n"); @@ -713,47 +655,23 @@ PaSndio_Initialize(PaUtilHostApiRepresen if (sndioHostApi == NULL) return paNoError; - if (!(hdl = sio_open(NULL, SIO_PLAY | SIO_REC, 0)) && - !(hdl = sio_open(NULL, SIO_REC, 0)) && - !(hdl = sio_open(NULL, SIO_PLAY, 0))) { - PaUtil_FreeMemory(sndioHostApi); - return paNoError; - } - cap = &sndioHostApi->default_cap; - if (!sio_getcap(hdl, cap)) { - PaUtil_FreeMemory(sndioHostApi); - return paNoError; - } - cf = &cap->confs[0]; - maxpchan = maxrchan = maxrate = 0; - for (i = 0; i < 8 * sizeof(unsigned); i++) { - if ((cf->rchan & (1 << i)) && (maxrchan < cap->rchan[i])) - maxrchan = cap->rchan[i]; - if ((cf->pchan & (1 << i)) && (maxpchan < cap->pchan[i])) - maxpchan = cap->pchan[i]; - if ((cf->rate & (1 << i)) && (maxrate < cap->rate[i])) - maxrate = cap->rate[i]; - } - sio_close(hdl); - sndioHostApi->caps[0] = cap; - info = &sndioHostApi->default_info; info->structVersion = 2; info->name = "default"; info->hostApi = hostApiIndex; - info->maxInputChannels = maxrchan; - info->maxOutputChannels = maxpchan; + info->maxInputChannels = 65536; + info->maxOutputChannels = 65536; info->defaultLowInputLatency = 0.01; info->defaultLowOutputLatency = 0.01; info->defaultHighInputLatency = 0.5; info->defaultHighOutputLatency = 0.5; - info->defaultSampleRate = maxrate; + info->defaultSampleRate = 192000; sndioHostApi->infos[0] = info; *hostApi = &sndioHostApi->base; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paSndio; - (*hostApi)->info.name = "libsndio"; + (*hostApi)->info.name = "sndio"; (*hostApi)->info.deviceCount = 1; (*hostApi)->info.defaultInputDevice = 0; (*hostApi)->info.defaultOutputDevice = 0;