portaudio: In the OSS hostapi, support additional sample formats.

While here, adjust some hacks around differences between NetBSD ossaudio
and OSSv4:

It turns out the problem was Audacity attempting to initialize with
an absurdly high sample rate. When a sample rate that's outside the
range of the kernel's maximum of 192000 is passed to SNDCTL_DSP_SPEED,
-1 was returned (until my commits today).

This is a violation of the OSSv4 spec in NetBSD. The spec states that if
an unsupported sample rate is requested, a supported one should be picked
and returned.
This commit is contained in:
nia 2020-04-15 17:12:14 +00:00
parent 71513315a1
commit 869c35d13f
3 changed files with 85 additions and 33 deletions

View file

@ -1,8 +1,8 @@
# $NetBSD: Makefile,v 1.28 2019/12/02 10:08:20 nia Exp $
# $NetBSD: Makefile,v 1.29 2020/04/15 17:12:14 nia Exp $
DISTNAME= pa_stable_v190600_20161030
PKGNAME= ${DISTNAME:S/^pa_stable_v/portaudio-/1:S/_/./g}
PKGREVISION= 2
PKGREVISION= 3
CATEGORIES= audio
MASTER_SITES= http://www.portaudio.com/archives/
EXTRACT_SUFX= .tgz

View file

@ -1,4 +1,4 @@
$NetBSD: distinfo,v 1.20 2019/11/24 13:15:15 nia Exp $
$NetBSD: distinfo,v 1.21 2020/04/15 17:12:14 nia Exp $
SHA1 (pa_stable_v190600_20161030.tgz) = 56c596bba820d90df7d057d8f6a0ec6bf9ab82e8
RMD160 (pa_stable_v190600_20161030.tgz) = e6e5cd3f3cb7469aa17549c189e445d573567e13
@ -11,4 +11,4 @@ SHA1 (patch-src_common_pa__front.c) = cdddb6f537f803b55873ad6bfa936a6bff47556d
SHA1 (patch-src_common_pa__stream.c) = 58e6ab2a61957208973a59be2f1140abc922f360
SHA1 (patch-src_common_pa__stream.h) = 94781a9ae79ea1340eea8caadc106416c019cf74
SHA1 (patch-src_hostapi_alsa_pa__linux__alsa.c) = 6ddbeca36be30153f9c6c316c2fb78c06bbbf05d
SHA1 (patch-src_hostapi_oss_pa__unix__oss.c) = 47678cab04dfd5c221bd15e2c8af741bca2d843c
SHA1 (patch-src_hostapi_oss_pa__unix__oss.c) = 572c48f64104e22e7ae49acc54a26e549e381b5b

View file

@ -1,40 +1,92 @@
$NetBSD: patch-src_hostapi_oss_pa__unix__oss.c,v 1.3 2019/11/24 13:15:15 nia Exp $
$NetBSD: patch-src_hostapi_oss_pa__unix__oss.c,v 1.4 2020/04/15 17:12:14 nia Exp $
Remove some rather pointless assertions that are incompatible with NetBSD's OSS
emulation layer.
Don't write an endless stream of silence when preparing the stream and don't try to
use OSS in non-blocking mode or poll it on NetBSD, this is unsupported.
Add features needed to make portmixer work with audacity.
- Add 24-bit and 32-bit sample formats.
- NetBSD-specific changes to make this map better to the emulation layer:
We don't need to initialize the stream by writing silence, etc.
PaOssStream_WaitForFrames hangs forever unless disabled, this may be a bug.
- Add features needed to make portmixer work with audacity.
--- src/hostapi/oss/pa_unix_oss.c.orig 2016-10-30 01:23:04.000000000 +0000
+++ src/hostapi/oss/pa_unix_oss.c
@@ -1040,23 +1040,13 @@ static PaError PaOssStreamComponent_Conf
@@ -65,7 +65,7 @@
#ifdef HAVE_SYS_SOUNDCARD_H
# include <sys/soundcard.h>
-# ifdef __NetBSD__
+# if defined(__NetBSD__) || defined(__OpenBSD__)
# define DEVICE_NAME_BASE "/dev/audio"
# else
# define DEVICE_NAME_BASE "/dev/dsp"
@@ -417,7 +417,12 @@ static PaError QueryDirection( const cha
/* Get supported sample rate closest to 44100 Hz */
if( *defaultSampleRate < 0 )
{
+#ifdef __NetBSD__
+ /* Less likely to require in-kernel conversion. */
+ sr = 48000;
+#else
sr = 44100;
+#endif
ENSURE_( ioctl( devHandle, SNDCTL_DSP_SPEED, &sr ), paUnanticipatedHostError );
*defaultSampleRate = sr;
@@ -938,6 +943,16 @@ static PaError Pa2OssFormat( PaSampleFor
case paInt16:
*ossFormat = AFMT_S16_NE;
break;
+#ifdef AFMT_S24_NE
+ case paInt24:
+ *ossFormat = AFMT_S24_NE;
+ break;
+#endif
+#ifdef AFMT_S32_NE
+ case paInt32:
+ *ossFormat = AFMT_S32_NE;
+ break;
+#endif
default:
return paInternalError; /* This shouldn't happen */
}
@@ -961,6 +976,14 @@ static PaError GetAvailableFormats( PaOs
frmts |= paInt8;
if( mask & AFMT_S16_NE )
frmts |= paInt16;
+#ifdef AFMT_S24_NE
+ if( mask & AFMT_S24_NE )
+ frmts |= paInt24;
+#endif
+#ifdef AFMT_S32_NE
+ if( mask & AFMT_S32_NE )
+ frmts |= paInt32;
+#endif
else
result = paSampleFormatNotSupported;
@@ -1040,12 +1063,23 @@ static PaError PaOssStreamComponent_Conf
PA_ENSURE( Pa2OssFormat( hostFormat, &temp ) );
nativeFormat = temp;
ENSURE_( ioctl( component->fd, SNDCTL_DSP_SETFMT, &temp ), paUnanticipatedHostError );
- PA_UNLESS( temp == nativeFormat, paInternalError );
+ PA_DEBUG(("%s: Wanted %d, selected format was %d\n", __FUNCTION__, nativeFormat, temp ));
PA_UNLESS( temp == nativeFormat, paInternalError );
/* try to set the number of channels */
ENSURE_( ioctl( component->fd, SNDCTL_DSP_CHANNELS, &chans ), paSampleFormatNotSupported ); /* XXX: Should be paInvalidChannelCount? */
- /* It's possible that the minimum number of host channels is greater than what the user requested */
- PA_UNLESS( chans >= component->userChannelCount, paInvalidChannelCount );
+#ifndef __NetBSD__
/* It's possible that the minimum number of host channels is greater than what the user requested */
+ /* On NetBSD it's possible that the number is less than what the user requested, e.g. if the device is a mono mic */
PA_UNLESS( chans >= component->userChannelCount, paInvalidChannelCount );
+#endif
+
+#ifdef __NetBSD__
+ /* Make the sample rate conform to hard kernel limits */
+ /* This can likely be removed after NetBSD 10... SNDCTL_DSP_SPEED should never return an error code. */
+ sr = sr > 192000 ? 192000 : sr;
+ sr = sr < 1000 ? 1000 : sr;
+#endif
/* try to set the sample rate */
ENSURE_( ioctl( component->fd, SNDCTL_DSP_SPEED, &sr ), paInvalidSampleRate );
- /* reject if there's no sample rate within 1% of the one requested */
- if( (fabs( sampleRate - sr ) / sampleRate) > 0.01 )
- {
- PA_DEBUG(("%s: Wanted %f, closest sample rate was %d\n", __FUNCTION__, sampleRate, sr ));
- PA_ENSURE( paInvalidSampleRate );
- }
-
ENSURE_( ioctl( component->fd, streamMode == StreamMode_In ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &bufInfo ),
paUnanticipatedHostError );
component->numBufs = bufInfo.fragstotal;
@@ -1477,6 +1467,7 @@ static PaError PaOssStream_Prepare( PaOs
@@ -1477,6 +1511,7 @@ static PaError PaOssStream_Prepare( PaOs
size_t bufSz = PaOssStreamComponent_BufferSize( stream->playback );
memset( stream->playback->buffer, 0, bufSz );
@ -42,7 +94,7 @@ Add features needed to make portmixer work with audacity.
/* Looks like we have to turn off blocking before we try this, but if we don't fill the buffer
* OSS will complain. */
PA_ENSURE( ModifyBlocking( stream->playback->fd, 0 ) );
@@ -1486,6 +1477,7 @@ static PaError PaOssStream_Prepare( PaOs
@@ -1486,6 +1521,7 @@ static PaError PaOssStream_Prepare( PaOs
break;
}
PA_ENSURE( ModifyBlocking( stream->playback->fd, 1 ) );
@ -50,7 +102,7 @@ Add features needed to make portmixer work with audacity.
}
if( stream->sharedDevice )
@@ -1652,6 +1644,7 @@ static void *PaOSS_AudioThreadProc( void
@@ -1652,6 +1688,7 @@ static void *PaOSS_AudioThreadProc( void
callbackResult = paComplete;
}
@ -58,7 +110,7 @@ Add features needed to make portmixer work with audacity.
/* Aspect StreamState: Because of the messy OSS scheme we can't explicitly trigger device start unless
* the stream has been recently started, we will have to go right ahead and read/write in blocking
* fashion to trigger operation. Therefore we begin with processing one host buffer before we switch
@@ -1667,6 +1660,9 @@ static void *PaOSS_AudioThreadProc( void
@@ -1667,6 +1704,9 @@ static void *PaOSS_AudioThreadProc( void
{
framesAvail = stream->framesPerHostBuffer;
}
@ -68,7 +120,7 @@ Add features needed to make portmixer work with audacity.
while( framesAvail > 0 )
{
@@ -1749,11 +1745,13 @@ static void *PaOSS_AudioThreadProc( void
@@ -1749,11 +1789,13 @@ static void *PaOSS_AudioThreadProc( void
if( initiateProcessing || !triggered )
{
@ -82,7 +134,7 @@ Add features needed to make portmixer work with audacity.
initiateProcessing = 0;
sem_post( &stream->semaphore );
@@ -2043,3 +2041,26 @@ error:
@@ -2043,3 +2085,26 @@ error:
#endif
}