0
$\begingroup$

I'm working on a sound source localization project which needs an array of microphones. I have 4 microphones with an Audio Jack plug which is connected to a USB Audio adapter. Last I use a 4x1 USB Hub to connect all the microphone-adapter components to my PC to read the incoming signal using Python PyAudio module.

Here is my configuration:

enter image description here

Here is my Python code:

import pyaudio
import wave

CHUNK = 2
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 8900
RECORD_SECONDS = 2
WAVE_OUTPUT_FILENAME = "output.wav"
NUM_OF_MICS = 4

p = pyaudio.PyAudio()

# Create a stream for each microphone with the IDs 1,2,3,4
streams = [p.open(format=FORMAT,
                  channels=CHANNELS,
                  rate=RATE,
                  input=True,
                  frames_per_buffer=CHUNK,
                  input_device_index=idx) for idx in range(1, NUM_OF_MICS + 1)]

print("* recording")

# Record 2 seconds of Audio for each
frames = []
for j in range(NUM_OF_MICS):
    row = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        row.append(streams[j].read(CHUNK, exception_on_overflow=False))
    frames.append(row)

for stream in streams:
    stream.stop_stream()
    stream.close()

p.terminate()

print("* done recording")

# Save audio with the names {1,2,3,4}_output.wav
for j in range(NUM_OF_MICS):
    wf = wave.open(str(j) + "_" + WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames[j]))
    wf.close()

Looking at the problem, I am able to read the microphone outputs clearly when I select just one of them and start recording only using it. However, when I process the code above, the recordings with the names {0,2}_output.wav sounds okay, but the others - {1,3}_output.wav contain only messy sound (at least it is what I hear).

I have tested all the plugs and devices separately, and all of them work. I am open to suggestions.

Edit 1:

When I connect only 2 Microphones to HUB and set the variable NUM_OF_MICS = 2 I get both sounds, {0,1}_output.wav, as normal.

Edit 2

Inspired by the comment of @MarcusMüller, I recorded sound from Mics by multithreading. Again at least one of the saved sounds is just noise.

Here is the code:

# coding=utf-8
# Python3.6
# Class Record a wav in new thread
# Author:Why
# Date:2018.04.23

import threading
import pyaudio
import wave


class RecordThread(threading.Thread):
    def __init__(self, idx, audiofile='record.wav'):
        threading.Thread.__init__(self)
        self.bRecord = True
        self.audiofile = audiofile
        self.chunk = 1024
        self.format = pyaudio.paInt16
        self.channels = 1
        self.rate = 16000
        self.idx = idx

    def run(self):
        audio = pyaudio.PyAudio()
        wavfile = wave.open(self.audiofile, 'wb')
        wavfile.setnchannels(self.channels)
        wavfile.setsampwidth(audio.get_sample_size(self.format))
        wavfile.setframerate(self.rate)
        wavstream = audio.open(format=self.format,
                               channels=self.channels,
                               rate=self.rate,
                               input=True,
                               frames_per_buffer=self.chunk,
                               input_device_index=self.idx)

        while self.bRecord:
            wavfile.writeframes(wavstream.read(self.chunk))
        wavstream.stop_stream()
        wavstream.close()
        audio.terminate()

    def stoprecord(self):
        self.bRecord = False


from time import sleep

audio_record_threads = [RecordThread(idx=i, audiofile=str(i) + '_output.wav') for i in range(1, 4)]
# start
for thd in audio_record_threads:
    thd.start()
sleep(5)
for thd in audio_record_threads:
    thd.stoprecord()

$\endgroup$
5
  • $\begingroup$ Each microphone is a standalone USB device with local free-running clocks. I hope you do not expect the audio streams to stay in sync when reading audio streams from multiple separate devices. $\endgroup$
    – Justme
    Mar 30, 2021 at 15:28
  • $\begingroup$ Do you have any idea/solution? $\endgroup$ Mar 30, 2021 at 15:32
  • 1
    $\begingroup$ An audio interface device that has as many channels as you need? $\endgroup$
    – Justme
    Mar 30, 2021 at 15:34
  • $\begingroup$ Tarlan, you need to read asynchronously between these streams, i.e. one reading from one soundcard mustn't block reading from the others. You can do that with a multi-threaded architecture, or async IO calls, or you could just use JACK to convert your four streams into one, and let that take care of doing the combination. $\endgroup$ Mar 30, 2021 at 18:08
  • $\begingroup$ @MarcusMüller thanks for your answer. Please, see the updated code. $\endgroup$ Mar 31, 2021 at 5:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.