Reputation: 346
I'd like to reproduce an audio signal by frames in a loop in python. In order to do that, I've tried with:
import sounddevice as sd
#Suppose:
nframes = 750
lframe = 882
fs = 44100
#Loop
for i in range(0,nframes):
sd.play(signal[i*lframe:(i+1)*lframe].astype('int16'),fs,blocking=True)
But I don't hear anything. I have checked that sd.play(signal.astype('int16'),fs,blocking=True)
works correctly.
Thank you for your help in advance
Upvotes: 2
Views: 1139
Reputation: 5939
Note that length of signal = 10000 * np.sin(2 * np.pi * fs * samples)
is the same of length samples
. In this case the most of junks signal[i:i+lframe]
are empty.
My working example is:
import numpy as np
import sounddevice as sd
lframe = 882 * 10
fs = 44100
frequency = 880
samples = np.arange(0, 1, step=1/fs)
signal = 10000 * np.sin(2 * np.pi * frequency * samples)
for i in range(0, fs, lframe):
sd.play(signal[i:i+lframe].astype('int16'), blocking=True, latency = 'low')
In this case nframes
is not needed because we can calculate it dividing fs/lframe
.
The main problem is that there is some delay after each sd.play
. If we take lframe = 882
, number of frames is 50 per second. The length of every frame is 0.02s which is shorter than delay. Hence I replace lframe = 882
with lframe = 882 * 10
.
On my laptop, the minimal multiplier so that I can hear any signal is lframe = 882 * 8
. Using latency = 'low'
helped me to reduce it to lframes = 882 * 4
to hear some signal.
Upvotes: 1
Reputation: 11443
I am assuming nframes as "number of frames" and lframe as "length of frame chunk".
In that case nframes < lframe - Do you have typo there?
Lets assume nframes = 7500
which gives 8 chunks of length 882.
What we need is to create chunks of signal array of length lframe and then play those individually. We change range to xrange as xrange is easier at handling chunks and create signal chunks in steps of lframes and then simply play those.
for i in xrange(0, len(signal),lframe):
sd.play(signal[i:i+lframe].astype('int16'),blocking=True)
Full Working Code:
import numpy as np
import sounddevice as sd
nframes = 7500
lframe = 882
fs = 44100
samples = np.arange(nframes)/float(nframes)
signal = 10000 * np.sin(2 * np.pi * fs * samples)
for i in xrange(0, len(signal),lframe):
sd.play(signal[i:i+lframe].astype('int16'),blocking=True)
Upvotes: 1