I am using sd.Stream to output sound and record from mic simultaneously. I need to be able to get the input and output simultaneously for audio processing in real time which is why I'm using Stream. If I'm using all files that use the same samplerate, this works fine. If I have some audio files that don't have the same samplerate, I need to be able to change the samplerate used by Stream.
try:
stream = sd.Stream(device=(args.input_device, args.output_device),
samplerate=args.samplerate, blocksize=args.blocksize,
dtype='float32', latency=(0, 0),
channels=len(args.channels), callback=callback, finished_callback=finished_callback)
with stream:
ani = FuncAnimation(fig, update_plot, interval=args.interval, blit=False, init_func=plot_init)
plt.show()
My First attempt is to close the stream in the finished_callback:
def finished_callback():
global stream
print "just closed"
stream.close()
and then reopen a stream in update_plot:
if stream.closed and callback.fs_mismatch:
args.samplerate = callback.new_fs
callback.fs_mismatch = 0
stream = sd.Stream(device=(args.input_device, args.output_device),
samplerate=args.samplerate, blocksize=args.blocksize,
dtype='float32', latency=(0, 0),
channels=len(args.channels), callback=callback, finished_callback=finished_callback)
print "stopped stream and fs mismatch!\n"
Reopening the stream does not seem to have any effect at all. I believe the reason for this is that I don't have anything blocking after the new stream like I use earlier (plt.show). I can't have anything blocking in this section because this is where I am updating my plot. Is there a way to change the samplerate of the stream after it is already open or is there another way to accomplish what I'm trying to do?
First of all, if you have files with different sampling rates, you should consider resampling (a.k.a. samling rate conversion). This is what's normally done to solve your problem.
Second, PortAudio (the C library behind the
sounddevice
module) doesn't support changing the sampling rate of an existing stream. There are other audio frameworks which theoretically support that (e.g. JACK), if you really need that.Third, if you really need streams with different sampling rate, you can of course close one stream and open another one with a different sampling rate. On some platforms you can even have multiple streams (with potentially different settings) at the same time.
You should not close the stream in the
finished_callback
, in fact you should call no functions from thesounddevice
module in there.It's probably not a good idea to create a stream in the
update_plot
callback, because it would be destroyed when the variable goes out of scope (which happens very quickly because the function is typically very short).You should probably make a separate thread for plotting and handle stopping and restarting audio streams in the main thread (or vice versa).