Discussion:
Port Audio on Linux limits application sample rate to integer ratio of underlying hardware
(too old to reply)
Michael Banther
2018-04-05 09:06:43 UTC
Permalink
Hello,

I’ve come across a sample rate restriction in Port Audio as supported on Linux using ALSA. I would like to know why Port Audio enforces this restriction and whether or not it can be relaxed or removed.

In brief:

* When .asoundrc sets the device sample rate to 44100 Hz and
* An application attempts to configure a stream on that device with a sample rate of 16000 Hz,
* The call to snd_pcm_hw_params_set_periods_integer( 
 ) in PaAlsaStreamComponent_InitialConfigure( 
 ) of pa_linux_alsa.c results in
* A later call to snd_pcm_hw_params_set_rate_near( 
 ) in SetApproximateSampleRate( 
 ) of pa_linux_alsa.c returning an error code of -22 (-EINVAL, “Invalid argument”).

According to Source Archive, the call to snd_pcm_hw_params_set_periods_integer<http://alsa-lib.sourcearchive.com/documentation/1.0.8/group__PCM__HW__Params_gb7356d30758dfcf11ff5874fd033913b.html>( 
 ) restricts “a configuration space to contain only integer periods counts” while snd_pcm_hw_params_set_rate_near<http://alsa-lib.sourcearchive.com/documentation/1.0.8/group__PCM__HW__Params_g39124280d06ce63092a77e3f25ddd6ee.html#g39124280d06ce63092a77e3f25ddd6ee>( 
 ) restricts “a configuration space to have a rate nearest to a target” and returns “a negative error code if configuration space is empty”.

Apparently, the non-integer ratio between the device and the stream sample rates results in an empty configuration space. Reducing the stream sample rate to 14700 Hz while keeping the device sample rate at 44100 Hz allows the call to snd_pcm_hw_params_set_rate_near( 
 ) to succeed. Likewise increasing the device sample rate to 48000 Hz while keeping the stream sample rate at 16000 Hz allows the call to succeed.

It’s not clear if the restriction is necessary. As I understand it, Port Audio is sample rate agnostic. ALSA includes sample rate conversion by default. Indeed I’ve removed the call to snd_pcm_hw_params_set_periods_integer( 
 ) and used a stream configured with a sample rate of 16000 Hz on a device with a sample rate of 44100 Hz. So far, very limited testing has not revealed a problem.

Can you please tell me why PaAlsaStreamComponent_InitialConfigure( 
 ) includes the call to snd_pcm_hw_params_set_periods_integer( 
 )? Is there a risk of using Port Audio with sample rates that are not integer multiples of one another? If there’s no known risk, would the Port Audio community be willing to remove the call to snd_pcm_hw_params_set_periods_integer( 
 ) either permanently or using a compile-time #ifdef?

For reference I’ve included details of my setup below:

* Application: Amazon AVS SDK<https://developer.amazon.com/alexa-voice-service/sdk> which uses the Port Audio libportaudio.la library
* Hardware: Raspberry Pi Model 3
* Operating System: Raspian Stretch
* Audio Device: XMOS VocalFusion Stereo Dev Kit for Amazon AVS<https://www.xmos.com/products/voice/vocalfusion-stereoavs>

Contents of .asoundrc:
#
# The I2S hardware device. Refer to it by name as it will not always
# be the same card number in every system.
#
pcm.i2s_44_1k {
type hw
card sndrpisimplecar
device 0

# The device has fixed 32-bit samples
format S32_LE

# The device runs at 44.1kHz
rate 44100
}

pcm.mix_i2s_44_1k {
type dmix
ipc_key 115 # Must be unique
slave {
pcm i2s_44_1k
}
}

#
# Note that the name must contain "Master" for the task bar to find it
#
pcm.mix_vol {
type softvol
slave {
pcm mix_i2s_44_1k
}
control {
name "Playback"
card 0
}
}

pcm.snoop_i2s_44_1k {
type dsnoop
ipc_key 116 # Must be unique
slave {
pcm i2s_44_1k
}
}

pcm.snoop_vol {
type softvol
slave {
pcm snoop_i2s_44_1k
}
control {
name "Record"
card 0
}
}

#
# Map the default audio playback and recording devices to the I2S device.
# - use plugs in order to support rate and format conversions.
#
pcm.!default {
type asym
playback.pcm {
type plug
slave {
pcm mix_vol
}
}
capture.pcm {
type plug
slave {
pcm snoop_vol
}
}
}

Error messages:
***@raspberrypi:~ $ alias avsrun
alias avsrun='LD_LIBRARY_PATH=/home/pi/sdk-folder/sdk-build/lib: TZ=UTC /home/pi/sdk-folder/sdk-build/SampleApp/src/SampleApp /home/pi/sdk-folder/sdk-build/Integration/AlexaClientSDKConfig.json /home/pi/sdk-folder/sdk-build/models'
***@raspberrypi:~ $ avsrun
2018-04-04 10:17:19.450 [ 1] I sdkVersion: 1.4.0
#############################
# Connecting... #
#############################

########################################
# Alexa is currently idle! #
########################################

#################################################
# NOTIFICATION INDICATOR STATE: OFF #
#################################################

Expression 'alsa_snd_pcm_hw_params_set_rate_near( pcm, hwParams, &setRate, NULL )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3196
Expression 'paUnanticipatedHostError' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2048
Expression 'PaAlsaStreamComponent_InitialConfigure( &self->capture, inParams, self->primeBuffers, hwParamsCapture, &realSr )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2714
Expression 'PaAlsaStream_Configure( stream, inputParameters, outputParameters, sampleRate, framesPerBuffer, &inputLatency, &outputLatency, &hostBufferSizeMode )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2838
Failed to open PortAudio default stream
Failed to initialize PortAudioMicrophoneWrapper
Failed to create PortAudioMicrophoneWrapper!
#####################################
# Client not connected! #
#####################################

Failed to initialize SampleApplication
Failed to create to SampleApplication!
***@raspberrypi:~ $

Thanks in advance for any help.

Sincerely,
Michael Banther
Customer Engineer
XMOS
Email: ***@xmos.com<mailto:***@xmos.com>

Loading...