I have to record 3 microphones simultaneously with as little delay between them as possible. This will then allow me to calculate the TDOA of sound between the microphones, so that I can pinpoint the source location.
However, I keep on getting a Input Overflow error thrown by PulseAudio, which makes the data unusable as the frames in that chunk captured by the microphone are discarded.
So far, I have attempted to fix the problem by changing the chunk size, even setting it to 2x my rate at one point. Initially I was using PyAudio, but the current version of my code runs sounddevice.
In order to start all three recordings at the same time I've been using multiprocessing, with each process containing its own input stream, but even running all 3 streams in one process caused the overflow(s).
I've also tried running the stream with or without callbacks, but that made no difference. Same with writing the data to memory or directly to disk.
CHUNK = 48000*2 #Chunk sizes varied from 5 up to 96000, both didn't work
RATE = 48000
CHANNELS = 1
FILE_NAME = 'recording'
def recorder(start, mic_num, file_name):
running = False
q = Queue()
file = sf.SoundFile(f'./recordings/{file_name}_{mic_num}.wav', mode = 'w', samplerate = RATE, channels = CHANNELS)
print('Created', mic_num)
def mic_processor(data, frames, time, status):
if(status):
#RIP recording :/
print(status) #Only status ever thrown is input overflow
global running
running = False
sys.exit()
q.put(data)
while not running:
if(datetime.datetime.now() >= start):
stream = sd.InputStream(samplerate = RATE, blocksize = CHUNK, device = mic_num, channels = CHANNELS, callback = mic_processor)
stream.start()
print('Microphone', mic_num, 'recording')
running = True
while running:
try:
file.write(q.get())
except KeyboardInterrupt:
stream.stop()
file.flush()
file.close()
running = False
if __name__ == '__main__':
start = datetime.timedelta(seconds=5)+datetime.datetime.now()
p1 = Process(target = recorder, args = (start, 2, FILE_NAME))
p2 = Process(target = recorder, args = (start, 3, FILE_NAME))
p3 = Process(target = recorder, args = (start, 4, FILE_NAME))
p1.start()
p2.start()
p3.start()
while True:
try:
time.sleep(0.0001)
if not p1.is_alive() or not p2.is_alive() or not p3.is_alive():
print('Something went wrong with one of the processes, gotta exit :/')
p1.terminate()
p2.terminate()
p3.terminate()
sys.exit()
except KeyboardInterrupt:
print('Writing to file')
time.sleep(0.5)
while p1.is_alive() or p2.is_alive() or p3.is_alive():
time.sleep(0.1)
break
Ideally, I'd hope to have no input overflows anymore, but at this point I'm completely stumped as to how to prevent them. Should I maybe just switch to ALSA instead of PulseAudio?
I'd really appreciate any help I can get with this :)