spotify/pedalboard

Question: Is it possible to write the output of an AudioStream to a .wav file as it's streaming?

rohancherukuri14 opened this issue · 5 comments

I want to be able to write the audio that is being sent to my output device from an AudioStream to a .wav file in real-time, or somehow record the audio and write it after. I've been looking online and don't see any clear way to do this. Thanks!

Hi @rohancherukuri14!

You're correct, there isn't currently a way to do this with Pedalboard alone. I've proposed a potential change to the AudioStream class (see #317 (comment)) that would allow AudioStream to buffer audio in-memory, which could then be written to a file; but this hasn't been built yet.

If you need this functionality, I'd recommend using pyAudio and streaming the results into a buffer that you can then write with AudioFile.

Hi! Thank you for the quick response! How exactly would I do this? Would I specify the audio buffer as the output to the buffer? Or just append stream to the buffer?

For context, I'm using a pretty simple example:

input_device_name = 'External Microphone'
output_device_name = 'External Headphones'
start_time = time.time()

while True:
    with AudioStream(input_device_name, output_device_name, allow_feedback=True) as stream:

        stream.plugins.append(Chorus())
        stream.plugins.append(Distortion())
        stream.plugins.append(Reverb())
        
        while len(stream.plugins) > 0:
            del stream.plugins[0]

I also tried using the .process() method to write to an ndarray, but the buffer still has all zeroes after recording:

from pedalboard.io import AudioStream
from pedalboard import Reverb, Chorus, Distortion
import soundcard as sc
import soundfile as sf
import time
import pyaudio
import numpy as np

input_device_name = 'External Microphone'
output_device_name = 'External Headphones'
start_time = time.time()

SAMPLE_RATE = 48000  # Hz
DURATION = 10  # seconds

start_time = time.time()
# Calculate the total number of samples
total_samples = int(SAMPLE_RATE * DURATION)

# Initialize a 32-bit floating point audio buffer for stereo (2 channels)
audio_buffer = np.zeros((total_samples, 2), dtype=np.float32)


while time.time() - start_time < DURATION:
    with AudioStream(input_device_name, output_device_name, allow_feedback=True) as stream:

        stream.plugins.append(Chorus())
        stream.plugins.append(Distortion())
        stream.plugins.append(Reverb())

        audio_buffer = stream.plugins.process(audio_buffer, SAMPLE_RATE, buffer_size=len(audio_buffer), reset=False)

        while len(stream.plugins) > 0:
            del stream.plugins[0]



print(audio_buffer[audio_buffer != 0])

FYI, #317 was superseded by #363, which will be released with Pedalboard v0.9.12:

Thanks @0xdevalias - yup, this functionality is now part of v0.9.12:

from pedalboard.io import AudioStream, AudioFile
from pedalboard import Reverb, Chorus, Distortion, Pedalboard

input_device_name = AudioStream.default_input_device_name

DURATION = 10  # seconds

# Make a Pedalboard:
board = Pedalboard([Chorus(), Distortion(), Reverb()])

CHUNK_SIZE = 512
with AudioStream(input_device_name) as stream:
    with AudioFile("output.wav", "w", stream.sample_rate, stream.num_input_channels) as f:
        while f.frames < (f.samplerate * DURATION):
            f.write(board.process(stream.read(CHUNK_SIZE), stream.sample_rate, reset=False))