Reputation: 31
I would like to record a tone with sounddevice i created numpy and write it into a wav file. here is the code:
import numpy
import sounddevice as sd
import soundfile as sf
import sys
duration = 3
amplitude = 0.3
sampling_frequency = 44100
time = numpy.arange(int(numpy.ceil(duration * sampling_frequency))) / sampling_frequency
frequency1 = 500
tone1 = amplitude * numpy.sin(2* numpy.pi * frequency1 * time)
frequency2 = 700
tone2 = amplitude * numpy.sin(2* numpy.pi * frequency1 * time)
frequency3 = 1500
tone3 = amplitude * numpy.sin(3* numpy.pi * frequency1 * time)
frequency4 = 400
tone4 = amplitude * numpy.sin(4* numpy.pi * frequency1 * time)
result = tone1
result2 = tone2
result3 = tone3
result4 = tone4
sd.play(result + result2 + result3 + result4, sampling_frequency)
filename = 'output.wav'
mydata = sd.rec(int(result + result2 + result3 + result4),sampling_frequency,channels=2, blocking=True)
sf.write(filename, mydata, sampling_frequency)
I get this error: only length-1 arrays can be converted to Python scalars What's wrong with the code? I'm a newbie with python
Upvotes: 3
Views: 8995
Reputation: 1
Fyi, your "tone" formulas all use "frequency1" in them, instead of 1, 2, 3, & 4. This code works for me, tho I wasn't sure if you wanted to overlap the tones, or play them in sequence, so I did both:
import numpy as np
import sounddevice as sd
import soundfile as sf
import sys
duration = 3
amplitude = 0.3
sampling_frequency = 44100
frequency1 = 500
frequency2 = 700
frequency3 = 1500
frequency4 = 400
time = np.arange(int(np.ceil(duration * sampling_frequency))) / sampling_frequency
tone1 = amplitude * np.sin(2* np.pi * frequency1 * time)
tone2 = amplitude * np.sin(2* np.pi * frequency2 * time)
tone3 = amplitude * np.sin(3* np.pi * frequency3 * time)
tone4 = amplitude * np.sin(4* np.pi * frequency4 * time)
result = tone1 + tone2 + tone3 + tone4
# overlaps the tones
sd.play(result, sampling_frequency)
sd.wait()
sf.write('tone.wav', result, sampling_frequency)
sequence = np.append(tone1, [tone2, tone3, tone4])
# plays each tone in sequence
sd.play(sequence, sampling_frequency)
sd.wait()
sf.write('sequence.wav', sequence, sampling_frequency)
Upvotes: 0
Reputation: 136
sd.rec()
is used to record sound from a sound device and output an array. It expects an integer of how long the recording should be. That is why it was throwing "TypeError: 'list' object cannot be interpreted as an integer"
.
https://python-sounddevice.readthedocs.io/en/0.3.7/#recording
You don't have to record the data, because you already have the data (your result variables). So you should just replace
mydata = sd.rec(int(result + result2 + result3 + result4),sampling_frequency,channels=2, blocking=True)
with
mydata = result + result2 + result3 + result4
Upvotes: 1
Reputation: 1982
Your second-to-last line is
mydata = sd.rec(int(result + result2 + result3 + result4),sampling_frequency,channels=2, blocking=True)
Where you try to cast the sum of the result1
etc variables to an integer. However, they are actually numpy
arrays, since time
is an array. You cannot convert an array into a single integer, since it has multiple values. I'm not sure why you are trying to do that, you probably just want to remove the int()
, and change it to
mydata = sd.rec(result + result2 + result3 + result4, sampling_frequency, channels=2, blocking=True)
Upvotes: 2