H.e
H.e

Reputation: 31

Writing a wav file using sounddevice and numpy in python3

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

Answers (3)

Nik
Nik

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

Jakob Drusany
Jakob Drusany

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

Coolness
Coolness

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

Related Questions