George Tian
George Tian

Reputation: 441

How to write pyaudio output into audio file?

I currently have the following code, which produces a sine wave of varying frequencies using the pyaudio module:

import pyaudio
import numpy as np

p = pyaudio.PyAudio()

volume = 0.5
fs = 44100
duration = 1

f = 440

samples = (np.sin(2 * np.pi * np.arange(fs * duration) * f / 
fs)).astype(np.float32).tobytes()

stream = p.open(format = pyaudio.paFloat32,
                channels = 1,
                rate = fs,
                output = True)

stream.write(samples)

However, instead of playing the sound, is there any way to make it so that the sound is written into an audio file?

Upvotes: 6

Views: 9597

Answers (3)

George Tian
George Tian

Reputation: 441

Using scipy.io.wavfile.write as suggested by @h lee produced the desired results:

import numpy
from scipy.io.wavfile import write

volume = 1
sample_rate = 44100
duration = 10
frequency = 1000

samples = (numpy.sin(2 * numpy.pi * numpy.arange(sample_rate * duration)
     * frequency / sample_rate)).astype(numpy.float32)

write('test.wav', sample_rate, samples)

Another example can be found on the documentation: https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.wavfile.write.html

Upvotes: 4

h Lee
h Lee

Reputation: 21

Add this code at the top of your code.

from scipy.io.wavfile import write

Also, add this code at the bottom of your code. This worked for me.

scaled = numpy.int16(s/numpy.max(numpy.abs(s)) * 32767)
write('test.wav', 44100, scaled)

Upvotes: 2

Facundo Farall
Facundo Farall

Reputation: 578

Handle your audio input as a numpy array like I did here in the second answer, but instead of just processing the frames and sending the data back to PyAudio, save each frame in a new output_array. Then when the processing is done you can use that output_array to write it to .wav or .mp3 file.

If you do that, however, the sound would still play. If you don't want to play the sound you have two options, either using the blocking mode or, if you wanna stick with the non blocking mode and the callbacks, do the following:

  • Erase output=True so that it is False as default.
  • Add a input=True parameter.
  • In your callback do not return ret_data, instead return None.
  • Keep count of the frames you've processed so that when you're done you return paComplete as second value of the returned tuple.

Upvotes: 1

Related Questions