Issue with Higher Sampling Rates than 16 kHz in PyAudio on Raspberry Pi

Hello Community,

I’m encountering an issue while using PyAudio on my Raspberry Pi 4 in conjunction with the ReSpeaker Mic Array v2.0. I’m trying to record audio with a sampling rate higher than 16 kHz, but I’m facing an error. Despite the specifications of the reSpeaker Mic Array v2.0 stating 16 kHz as the maximum sample rate, I can achieve this without any issues using arecord in the terminal.

“Here’s an excerpt from my PyAudio code, followed by the error message encountered when executing the script in the Raspberry Pi Terminal:”

# (...)

# Setting the configuration for the reSpeaker MicArry v2.0
RESPEAKER_RATE = 44100
RESPEAKER_CHANNELS = 6 # change base on firmwares, 1_channel_firmware.bin as 1 or 6_channels_firmware.bin as 6
RESPEAKER_WIDTH = 2
RESPEAKER_INDEX = get_device_api_index(HOST_API_INDEX, 'ReSpeaker')

# Setting the configuration fpr the recording
CHUNK = 1024
RECORD_SECONDS = 5
TIMESTAMP = datetime.datetime.utcnow()

# Creating a PyAudio-object ('p') to manage the audio recording and playback

# Open an audio stream for recording
p = pyaudio.PyAudio()
stream = p.open(
        rate=RESPEAKER_RATE,
        format=p.get_format_from_width(RESPEAKER_WIDTH),
        channels=RESPEAKER_CHANNELS,
        input=True,
        input_device_index=RESPEAKER_INDEX,)
print('****recording***')

frames = [] # A list for collecting the recording data in chunks

# Recording the audio data in chunks
for i in range(0, int(RESPEAKER_RATE / CHUNK * RECORD_SECONDS)): # It is iterated over the necessary number of chunks for the specified recording time
    data = stream.read(CHUNK)
    
    # Extract the data of the first channel from the 6 channels, if you want to extract channel 1, please change to [1::6]
    a = np.frombuffer(data, dtype=np.int16)
    frames.append(a.tobytes())
# (...)

And the corresponding error message:

 # (...)
Traceback (most recent call last):
  File "/home/pi/Codes/pyaudio-test/single_recording.py", line 53, in <module>
    stream = p.open(
  File "/usr/local/lib/python3.9/dist-packages/pyaudio/__init__.py", line 639, in open
    stream = PyAudio.Stream(self, *args, **kwargs)
  File "/usr/local/lib/python3.9/dist-packages/pyaudio/__init__.py", line 441, in __init__
    self._stream = pa.open(**arguments)
OSError: [Errno -9997] Invalid sample rate

Interestingly, recording with these sampling rates works seamlessly when using the arecord command in the terminal, like this:

arecord -d 5 -f S16_LE -r 44100 -t wav output_44100.wav

To the best of my understanding, arecord uses ALSA as the API interface. When searching for ALSA-driven devices after the respeaker, the defaultSampleRate is listed as 16 kHz, indicating that this is the maximum achievable sampling rate through ALSA.

Code searching for ALSA-driven devices

import pyaudio

def get_device_api_index(host_api_index, name):
    p = pyaudio.PyAudio()
    info = p.get_host_api_info_by_index(host_api_index)
    deviceCount = info.get('deviceCount')

    for i in range(deviceCount):
        device_info = p.get_device_info_by_host_api_device_index(host_api_index, i)
        print(device_info)
        device_name = device_info['name']
        if name in device_name:
            p.terminate()
            return i
    p.terminate()
    raise ValueError(f'No device found containing {name}')

ALSA_INFO = get_device_api_index(0, 'ReSpeaker')

Output of the search code:

'index': 2, 'structVersion': 2, 'name': 'ReSpeaker 4 Mic Array (UAC1.0): USB Audio (hw:3,0)', 'hostApi': 0, 'maxInputChannels': 6, 'maxOutputChannels': 2, 'defaultLowInputLatency': 0.0239375, 'defaultLowOutputLatency': 0.0239375, 'defaultHighInputLatency': 0.096, 'defaultHighOutputLatency': 0.096, **'defaultSampleRate': 16000.0**}

Has anyone had similar experiences or any ideas on how I can get PyAudio to accept higher sampling rates? Thank you in advance for your assistance!