python-sounddevice
python-sounddevice copied to clipboard
delay at beginning of input signal
In this function, we simultaneously play a testsound (ts)
multiple times with a pause in between and record its total response sound.
The problem is that the recorded signal sound
contains unwanted zeros in the beginning. This acts as a delay because the beginning of the recording is indeed the beginning of the useful sound after the delay. Furthermore, because of the delay in the beginning, the end of the sound is also not recorded (not in the put in the queue. This is clarified in the plot (in time domain (s), the blue stripes are non important here)
How can I get rid of the delay in the beginning?
import numpy as np
import queue
import sounddevice as sd
import threading
N_ts = 20
blocksize = 8
#make quick sine signal
seconds = float(50)/1000 # put to ms
t_arr = np.linspace(0, seconds, int(44100*seconds))
ts = np.sin(2 * np.pi * 440 * t_arr)
ts = ts * (2**15 - 1) / np.max(np.abs(ts))
ts = ts.astype(np.int16)
def callback(indata, outdata, frames, time, status):
global current_frame, prerec, postrec, totalcount, cuts, total_frames
total_frames += frames
if not postrec: # time between
if status:
print(status)
#take one block of 8
chunksize = min(len(ts) - current_frame, frames)
# for different channels
outdata[:chunksize,0] = ts[current_frame:current_frame + chunksize]
outdata[:chunksize,1] = ts[current_frame:current_frame + chunksize]
if chunksize < frames:
outdata[chunksize:] = 0
postrec = True
prerec = 0
current_frame += chunksize
else:
# play nothing (zeros) (for a period of ts), then enable postrec
# to play ts again (len(self.ts) is the pause)
if prerec > len(ts):
current_frame = 0
postrec = False
prerec = 0
totalcount += 1
else:
prerec += len(indata) #mostly just the blocksize (=8)
outdata[:] = 0
#N_ts is the number of times the signal is repeated
if totalcount == N_ts:
raise sd.CallbackStop()
q.put(indata.copy()[:])
current_frame = 0
prerec = 0
totalcount = 0
total_frames = 0
cuts = []
postrec = False
event = threading.Event()
q = queue.Queue()
with sd.Stream(channels=(2,2), blocksize=blocksize, callback=callback, finished_callback=event.set):
event.wait()
sound = np.empty((total_frames, 2), dtype=np.float32)
b = 0
while not q.empty():
sound[b:b+blocksize,:] = q.get()[:,:]
b+= blocksize
Does the delay also occur when using sd.playrec()
(you will have to adapt the generation of your output signal a bit)? If not then its worth looking for the difference there, given that you want to use your own stream implementation regardless.