From 0beae3c008219a2dba02cbc02cbe7f3ac2c43f67 Mon Sep 17 00:00:00 2001 From: Peter Sobot Date: Mon, 29 Jul 2024 09:01:44 -0400 Subject: [PATCH] Add buffered playback and recording to AudioStream. (#363) * First pass at adding buffered playback and recording to AudioStream. * Add .read() and .write() on AudioStream. * Add tests for read() and write(). * Fix Linux build? * More ifdef gating... * Skip tests on CI. * Update docstrings. --- docs/genindex.html | 40 +- docs/reference/pedalboard.io.html | 140 +++++- docs/searchindex.js | 2 +- pedalboard/io/AudioStream.h | 780 ++++++++++++++++++++++++++---- pedalboard_native/io/__init__.pyi | 159 +++++- tests/test_audio_stream.py | 107 +++- 6 files changed, 1070 insertions(+), 158 deletions(-) diff --git a/docs/genindex.html b/docs/genindex.html index f0f3c7f5..a1195df3 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -333,11 +333,15 @@

B

  • Bitcrush (class in pedalboard)
  • - - + @@ -361,9 +365,11 @@

    C

  • Clipping (class in pedalboard)
  • -
  • close() (pedalboard.io.ReadableAudioFile method) +
  • close() (pedalboard.io.AudioStream method)
  • +
  • ignore_dropped_input (pedalboard.io.AudioStream property) +
  • IIRFilter (class in pedalboard)
  • input_latency (pedalboard.io.StreamResampler property) @@ -746,10 +756,10 @@

    N

  • (pedalboard.VST3Plugin property)
  • - - + @@ -789,6 +803,8 @@

    P

  • Phaser (class in pedalboard)
  • PitchShift (class in pedalboard) +
  • +
  • play() (pedalboard.io.AudioStream static method)
  • Plugin (class in pedalboard)
  • @@ -896,9 +912,11 @@

    R

  • (pedalboard.VST3Plugin property)
  • -
  • read() (pedalboard.io.ReadableAudioFile method) +
  • read() (pedalboard.io.AudioStream method)
  • @@ -1010,6 +1028,8 @@

    R

    S

    diff --git a/docs/reference/pedalboard.io.html b/docs/reference/pedalboard.io.html index 6dd70bc0..2b3f4ba4 100644 --- a/docs/reference/pedalboard.io.html +++ b/docs/reference/pedalboard.io.html @@ -373,13 +373,31 @@

    The pedalboard.
    -class pedalboard.io.AudioStream(input_device_name: str, output_device_name: str, plugins: Optional[Chain] = None, sample_rate: Optional[float] = None, buffer_size: int = 512, allow_feedback: bool = False)#
    -

    A class that streams audio from an input audio device (i.e.: a microphone, -audio interface, etc) to an output device (speaker, headphones), -passing it through a pedalboard.Pedalboard to add effects.

    -

    AudioStream may be used as a context manager:

    -
    input_device_name = AudioStream.input_device_names[0]
    -output_device_name = AudioStream.output_device_names[0]
    +class pedalboard.io.AudioStream(input_device_name: Optional[str] = None, output_device_name: Optional[str] = None, plugins: Optional[Chain] = None, sample_rate: Optional[float] = None, buffer_size: Optional[int] = None, allow_feedback: bool = False, num_input_channels: int = 1, num_output_channels: int = 2)#
    +

    A class that allows interacting with live streams of audio from an input +audio device (i.e.: a microphone, audio interface, etc) and/or to an +output device (speaker, headphones), allowing access to the audio +stream from within Python code.

    +

    Use AudioStream.play() to play audio data to your speakers:

    +
    # Play a 10-second chunk of an audio file:
    +with AudioFile("my_audio_file.mp3") as f:
    +    chunk = f.read(f.samplerate * 10)
    +AudioStream.play(chunk, f.samplerate)
    +
    +
    +

    Or use AudioStream.write() to stream audio in chunks:

    +
    # Play an audio file by looping through it in chunks:
    +with AudioStream(output_device="default") as stream:
    +    with AudioFile("my_audio_file.mp3") as f:
    +        while f.tell() < f.frames:
    +            # Decode and play 512 samples at a time:
    +            stream.write(f.read(512))
    +
    +
    +

    AudioStream may also be used to pass live audio through a Pedalboard:

    +
    # Pass both an input and output device name to connect both ends:
    +input_device_name = AudioStream.default_input_device_name
    +output_device_name = AudioStream.default_output_device_name
     with AudioStream(input_device_name, output_device_name) as stream:
         # In this block, audio is streaming through `stream`!
         # Audio will be coming out of your speakers at this point.
    @@ -393,22 +411,13 @@ 

    The pedalboard. # Delete plugins: del stream.plugins[0] -

    -
    -

    AudioStream may also be used synchronously:

    -
    stream = AudioStream(ogg_buffer)
    +
    +# Or use AudioStream synchronously:
    +stream = AudioStream(input_device_name, output_device_name)
     stream.plugins.append(Reverb(wet_level=1.0))
     stream.run()  # Run the stream until Ctrl-C is received
     
    -
    -

    Note

    -

    This class uses C++ under the hood to ensure speed, thread safety, -and avoid any locking concerns with Python’s Global Interpreter Lock. -Audio data processed by AudioStream is not available to -Python code; the only way to interact with the audio stream is through -the plugins attribute.

    -

    Warning

    The AudioStream class implements a context manager interface @@ -417,13 +426,14 @@

    The pedalboard.

    While it is possible to call the __enter__() method directly to run an audio stream in the background, this can have some nasty side effects. If the AudioStream object is no longer reachable (not bound to a variable, -not in scope, etc), the audio stream will continue to play back forever, and +not in scope, etc), the audio stream will continue to run forever, and won’t stop until the Python interpreter exits.

    To run an AudioStream in the background, use Python’s -threading module to call the synchronous run() method on a +threading module to run the stream object method on a background thread, allowing for easier cleanup.

    Introduced in v0.7.0. Not supported on Linux.

    +

    read() and write() methods introduced in v0.9.12.

    __enter__() AudioStream#
    @@ -436,10 +446,77 @@

    The pedalboard.

    Exit the context manager, ending the audio stream. Once called, the audio stream will be stopped (i.e.: running will be False).

    +
    +
    +close() None#
    +

    Close the audio stream, stopping the audio device and releasing any resources. After calling close, this AudioStream object is no longer usable.

    +
    + +
    +
    +static play(audio: ndarray[Any, dtype[float32]], sample_rate: float, output_device_name: Optional[str] = None) None#
    +

    Play audio data to the speaker, headphones, or other output device. This method will block until the audio is finished playing.

    +
    + +
    +
    +read(num_samples: int = 0) ndarray[Any, dtype[float32]]#
    +
    +

    Warning

    +

    Recording audio is a real-time operation, so if your code doesn’t call read() quickly enough, some audio will be lost. To warn about this, read() will throw an exception if audio data is dropped. This behavior can be disabled by setting ignore_dropped_input to True. The number of dropped samples since the last call to read() can be retrieved by accessing the dropped_input_frame_count property.

    +
    +
    +
    run() None#
    -

    Start streaming audio from input to output, passing the audio stream through the plugins on this AudioStream object. This call will block the current thread until a KeyboardInterrupt (Ctrl-C) is received.

    +

    Start streaming audio from input to output, passing the audio stream through the plugins on this AudioStream object. This call will block the current thread until a KeyboardInterrupt (Ctrl-C) is received.

    +
    + +
    +
    +write(audio: ndarray[Any, dtype[float32]], sample_rate: float) None#
    +

    If the provided sample rate does not match the output device’s sample rate, an error will be thrown. In this case, you can use StreamResampler to resample the audio before calling write().

    +
    + +
    +
    +property buffer_size: int#
    +

    The size (in frames) of the buffer used between the audio hardware and Python.

    +
    + +
    +
    +property buffered_input_sample_count: Optional[int]#
    +

    The number of frames of audio that are currently in the input buffer. This number will change rapidly, and will be None if no input device is connected.

    +
    + +
    +
    +property dropped_input_frame_count: int#
    +

    The number of frames of audio that were dropped since the last call to read(). To prevent audio from being dropped during recording, ensure that you call read() as often as possible or increase your buffer size.

    +
    + +
    +
    +property ignore_dropped_input: bool#
    +

    Controls the behavior of the read() method when audio data is dropped. If this property is false (the default), the read() method will raise a RuntimeError if any audio data is dropped in between calls. If this property is true, the read() method will return the most recent audio data available, even if some audio data was dropped.

    +
    +

    Note

    +

    The dropped_input_frame_count property is unaffected by this setting.

    +
    +
    + +
    +
    +property num_input_channels: int#
    +

    The number of input channels on the input device. Will be 0 if no input device is connected.

    +
    + +
    +
    +property num_output_channels: int#
    +

    The number of output channels on the output device. Will be 0 if no output device is connected.

    @@ -451,7 +528,13 @@

    The pedalboard.
    property running: bool#
    -

    True if this stream is currently streaming live audio from input to output, False otherwise.

    +

    True if this stream is currently streaming live audio, False otherwise.

    +
    + +
    +
    +property sample_rate: float#
    +

    The sample rate that this stream is operating at.

    @@ -1118,9 +1201,20 @@

    The pedalboard.
  • AudioStream
  • ReadableAudioFile
      diff --git a/docs/searchindex.js b/docs/searchindex.js index dbbaaff4..aa71d2b5 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["compatibility", "examples", "faq", "index", "internals", "license", "reference/pedalboard", "reference/pedalboard.io"], "filenames": ["compatibility.rst", "examples.rst", "faq.rst", "index.rst", "internals.rst", "license.rst", "reference/pedalboard.rst", "reference/pedalboard.io.rst"], "titles": ["Plugin Compatibility", "Examples", "Frequently Asked Questions", "Features", "Pedalboard Internals", "License", "The pedalboard API", "The pedalboard.io API"], "terms": {"pedalboard": [0, 3, 5], "allow": [0, 1, 3, 6, 7], "load": [0, 1, 3, 4, 6], "vst3": [0, 3, 4, 5, 6], "audio": [0, 3, 4, 5, 6, 7], "unit": [0, 2, 3, 4, 6], "which": [0, 5, 6, 7], "could": [0, 6, 7], "contain": [0, 1, 6, 7], "ani": [0, 2, 4, 6, 7], "code": [0, 2, 4, 5, 7], "most": [0, 3, 4, 6, 7], "have": [0, 4, 6, 7], "been": [0, 7], "test": [0, 3, 4], "work": [0, 1, 3, 6, 7], "just": [0, 1, 4, 6, 7], "fine": [0, 6], "some": [0, 1, 4, 6, 7], "mai": [0, 4, 6, 7], "worst": [0, 7], "even": [0, 3, 7], "crash": [0, 6, 7], "python": [0, 1, 3, 4, 6, 7], "interpret": [0, 3, 7], "without": [0, 3, 6, 7], "warn": 0, "abil": [0, 6], "catch": 0, "error": [0, 6], "ar": [0, 1, 3, 4, 5, 6, 7], "well": [0, 3, 4, 6, 7], "behav": [0, 1], "conform": 0, "set": [0, 1, 2, 6, 7], "convent": 0, "how": [0, 1, 6], "suppos": 0, "mani": [0, 3, 6, 7], "do": [0, 1, 6, 7], "specif": [0, 6], "attempt": [0, 7], "detect": [0, 6], "common": [0, 3], "program": [0, 1, 6, 7], "can": [0, 1, 3, 4, 6, 7], "around": [0, 4, 6], "issu": [0, 4, 6], "includ": [0, 1, 3, 4, 5, 6], "automat": [0, 3, 6, 7], "don": [0, 1, 6, 7], "t": [0, 1, 2, 6, 7], "clear": [0, 6], "intern": [0, 3, 6, 7], "state": [0, 6, 7], "when": [0, 3, 4, 6, 7], "ask": [0, 3], "so": [0, 1, 2, 6, 7], "misbehav": 0, "notic": 0, "If": [0, 1, 3, 6, 7], "i": [0, 1, 2, 3, 4, 5, 6, 7], "being": [0, 7], "render": [0, 1, 2, 3, 6, 7], "incorrectli": 0, "leak": [0, 7], "from": [0, 1, 2, 3, 5, 6, 7], "one": [0, 1, 3, 6, 7], "process": [0, 1, 2, 3, 4, 5, 6, 7], "call": [0, 6, 7], "next": 0, "an": [0, 1, 4, 6, 7], "undesir": 0, "fashion": 0, "try": [0, 6, 7], "pass": [0, 1, 2, 6, 7], "silenc": 0, "between": [0, 2, 6, 7], "ensur": [0, 2, 4, 6, 7], "reverb": [0, 1, 2, 3, 6, 7], "tail": [0, 2, 6], "other": [0, 1, 3, 6, 7], "ha": [0, 1, 6, 7], "time": [0, 1, 3, 6, 7], "fade": 0, "reload": 0, "everi": [0, 4, 6, 7], "load_plugin": [0, 1, 3, 4, 6], "note": [1, 6, 7], "you": [1, 3, 6, 7], "d": [1, 7], "rather": [1, 7], "watch": 1, "video": 1, "instead": [1, 3, 6, 7], "read": [1, 2, 3, 6, 7], "document": [1, 6, 7], "feat": 1, "youtub": 1, "import": [1, 2, 4, 6, 7], "choru": [1, 3, 6], "io": [1, 2, 3, 6], "audiofil": [1, 2, 6, 7], "object": [1, 6, 7], "multipl": [1, 3, 6, 7], "board": [1, 2], "room_siz": [1, 6], "0": [1, 2, 6, 7], "25": [1, 6], "open": [1, 2, 4, 6, 7], "file": [1, 2, 3, 4, 6, 7], "like": [1, 3, 6, 7], "regular": [1, 6, 7], "wav": [1, 2, 3, 6, 7], "f": [1, 6, 7], "write": [1, 2, 3, 6, 7], "output": [1, 2, 6, 7], "w": [1, 2, 6, 7], "sampler": [1, 2, 6, 7], "num_channel": [1, 2, 6, 7], "o": [1, 2, 3, 6, 7], "second": [1, 6, 7], "until": [1, 6, 7], "empti": [1, 6], "while": [1, 2, 6, 7], "tell": [1, 7], "frame": [1, 2, 7], "chunk": [1, 2, 6, 7], "int": [6, 7], "through": [1, 2, 6, 7], "our": [1, 2], "reset": [1, 2, 6, 7], "fals": [1, 2, 6, 7], "For": [1, 6, 7], "more": [1, 2, 3, 4, 6, 7], "inform": [1, 7], "about": [1, 6, 7], "paramet": [1, 3, 6, 7], "see": [1, 2, 6, 7], "http": 6, "spotifi": [3, 5], "github": [3, 6], "refer": [], "html": 6, "_": 6, "It": [1, 3], "thi": [1, 2, 5, 6, 7], "smaller": [1, 2, 6, 7], "whole": 1, "resampl": [1, 3, 6, 7], "desir": 1, "sampl": [1, 2, 6, 7], "rate": [1, 2, 6, 7], "44100": [1, 6, 7], "input": [1, 6, 7], "resampled_to": [1, 7], "pretti": 1, "interest": 1, "sound": [1, 6], "compressor": [1, 2, 3, 6], "threshold_db": [1, 6], "50": [1, 6], "ratio": [1, 6], "gain": [1, 3, 6], "gain_db": [1, 6], "30": [1, 7], "ladderfilt": [1, 3, 6], "mode": [1, 6, 7], "hpf12": [1, 6], "cutoff_hz": [1, 6], "900": 1, "phaser": [1, 3, 6], "convolut": [1, 3, 6], "guitar_amp": 1, "1": [1, 2, 3, 6, 7], "list": [1, 6, 7], "add": [1, 3, 4, 6, 7], "append": [1, 6, 7], "10": [1, 3, 6, 7], "limit": [1, 3, 6], "chang": [1, 3, 6, 7], "easili": 1, "40": 1, "back": [1, 6, 7], "shape": [1, 2, 7], "known": 1, "path": [1, 6, 7], "disk": [1, 7], "vst": [1, 3, 5], "roughrider3": 1, "print": [1, 6, 7], "kei": [1, 6], "dict_kei": 1, "sc_hpf_hz": 1, "input_lvl_db": 1, "sensitivity_db": 1, "attack_m": [1, 6], "release_m": [1, 6], "makeup_db": 1, "mix": [1, 6], "output_lvl_db": 1, "sc_activ": 1, "full_bandwidth": 1, "bypass": 1, "15": 1, "r": 7, "put": 1, "same": [1, 4, 6, 7], "instanc": [1, 4, 6, 7], "delai": [1, 3, 6], "pitch": [1, 3, 6], "shift": [1, 6], "themselv": [1, 6], "nest": [1, 6], "them": [1, 6], "much": [1, 6, 7], "distort": [1, 3, 6], "pitchshift": [1, 3, 5, 6], "passthrough": 1, "delay_and_pitch_shift": 1, "delay_second": [1, 6], "semiton": [1, 6], "7": [1, 2, 3, 6, 7], "3": [1, 3, 6, 7], "delay_longer_and_more_pitch_shift": 1, "5": [1, 6], "12": [1, 3, 6], "6": [1, 3, 5, 6, 7], "front": 1, "all": [1, 3, 4, 6, 7], "simultan": 1, "final": 1, "On": 1, "maco": [1, 3, 4, 6, 7], "window": [1, 3, 4, 6, 7], "support": [1, 3, 4, 6, 7], "stream": [1, 3, 6, 7], "audiostream": [1, 2, 3, 7], "real": [1, 3, 6, 7], "manipul": 1, "ad": [1, 3, 6, 7], "up": [1, 3, 5, 6], "input_device_nam": [1, 7], "apoge": 1, "jam": 1, "interfac": [1, 4, 6, 7], "output_device_nam": [1, 7], "macbook": 1, "pro": 1, "speaker": [1, 6, 7], "now": [1, 7], "out": [1, 3, 6, 7], "your": [1, 7], "press": [1, 6], "enter": [1, 7], "stop": [1, 7], "The": [1, 4, 5], "close": [1, 6, 7], "folder": 1, "repositori": [1, 4], "demo": 1, "colab": 1, "notebook": 1, "peter": 1, "sobot": 1, "europython": 1, "2022": 1, "interact": [1, 6, 7], "web": 1, "hug": 1, "face": 1, "space": 1, "gradio": 1, "via": [1, 3, 6, 7], "ak391": 1, "technic": [], "ye": 2, "pull": 5, "request": [], "98": [], "experiment": 3, "written": [4, 7], "c": [4, 6, 7], "stefanobazzi": [], "guitarboard": [], "project": 5, "exampl": [3, 4, 6, 7], "sounddevic": [], "librari": [3, 4, 5, 6, 7], "howev": [2, 6, 7], "coupl": [], "big": 2, "caveat": [], "talk": [], "context": 7, "languag": [], "garbag": [], "collect": [], "mean": [], "randomli": [], "paus": [], "interv": [], "clean": [], "unus": 7, "In": 7, "result": [6, 7], "random": [1, 7], "pop": [], "click": 6, "drop": [], "veri": [], "difficult": [], "prevent": 7, "global": [3, 7], "lock": [3, 7], "also": [3, 4, 5, 6, 7], "potenti": 7, "unbound": 7, "switch": [], "thread": [3, 4, 6, 7], "oper": [6, 7], "system": [6, 7], "separ": [], "high": [6, 7], "prioriti": [], "block": [6, 7], "caus": [6, 7], "stutter": [], "access": [6, 7], "mutat": [], "applic": 4, "larg": 7, "buffer": [6, 7], "size": [2, 4, 6, 7], "soft": 6, "requir": [3, 4, 6, 7], "case": [3, 4, 6, 7], "network": [], "data": [2, 3, 6, 7], "offlin": [], "built": [2, 3, 6], "function": [2, 4, 5, 6, 7], "possibl": [2, 3, 6, 7], "vari": [2, 6], "manual": [2, 3], "tqdm": 2, "step": 2, "would": [2, 4, 6, 7], "give": [2, 6], "smoother": [2, 6], "transit": 2, "expens": [2, 6, 7], "speed": [2, 3, 4, 5, 6, 7], "step_size_in_sampl": 2, "100": [2, 6, 7], "_n_": 2, "af": 2, "we": 2, "directli": [2, 6, 7], "save": [2, 6], "memori": [2, 3, 6, 7], "creat": [2, 3, 6, 7], "progress": 2, "bar": 2, "show": [2, 4, 6], "total": [2, 7], "pbar": 2, "rang": [2, 3, 6], "wet": [2, 6], "equal": [2, 3, 6, 7], "percentag": [2, 6], "track": [2, 6], "e": [2, 6, 7], "make": [2, 3, 7], "ramp": 2, "percentage_through_track": 2, "wet_level": [2, 6, 7], "updat": 2, "number": [2, 3, 5, 6, 7], "receiv": [2, 6, 7], "aren": 2, "cut": [2, 6], "off": [2, 6], "With": 2, "techniqu": [2, 6], "autom": 2, "usual": [2, 6, 7], "somewher": 2, "000": [2, 7], "2m": 2, "22m": 2, "44": [2, 6, 7], "1khz": [2, 6], "small": 2, "enough": [2, 7], "avoid": [2, 7], "hear": 2, "artifact": [2, 6], "slow": [2, 6], "down": [2, 6], "dramat": 2, "Not": [4, 6, 7], "yet": 2, "underli": [6, 7], "framework": [], "juce": [4, 5], "au": 7, "itself": [4, 6], "modifi": [], "either": [6, 7], "although": [6, 7], "effect": [3, 4, 6, 7], "popular": 3, "format": [3, 6, 7], "box": 3, "us": [3, 4, 5, 6, 7], "third": [3, 6], "parti": [3, 6], "plugin": [3, 5, 6, 7], "wa": [3, 6, 7], "": [1, 3, 4, 6, 7], "intellig": 3, "lab": 3, "enabl": [3, 6], "studio": 3, "qualiti": [3, 6, 7], "within": [3, 4, 6], "tensorflow": [1, 3], "augment": 3, "improv": 3, "machin": [3, 4], "learn": [3, 4], "model": [1, 3, 6], "help": 3, "power": [3, 6], "ai": 3, "dj": 3, "content": [3, 7], "creation": 3, "digit": [3, 4, 6], "workstat": 3, "util": [3, 6], "aiff": [3, 7], "flac": [3, 7], "mp3": [3, 6, 7], "ogg": [3, 7], "platform": [3, 4, 6, 7], "depend": [3, 4, 6, 7], "addit": [3, 4, 6, 7], "aac": [3, 7], "ac3": [3, 7], "wma": [3, 7], "fly": [3, 7], "usag": [3, 6], "live": [3, 7], "basic": [3, 6, 7], "transform": [3, 6], "guitar": [3, 6], "style": 3, "clip": [3, 6], "loud": [3, 6], "dynam": [3, 6], "filter": [3, 6], "highpassfilt": [3, 6], "lowpassfilt": [3, 6], "spatial": 3, "lossi": [3, 6], "compress": [3, 6, 7], "gsmfullratecompressor": [3, 5, 6], "mp3compressor": [3, 5, 6], "reduct": [3, 6], "bitcrush": [3, 6], "linux": [3, 4, 6, 7], "strong": 3, "safeti": [3, 7], "guarante": [3, 7], "releas": [3, 6, 7], "gil": [3, 7], "cpu": [3, 6], "core": [3, 5], "No": [3, 6], "need": [3, 4, 7], "multiprocess": 3, "onli": [3, 6, 7], "300x": 3, "faster": 3, "than": [3, 4, 6, 7], "pysox": 3, "singl": [3, 6], "2": [3, 6, 7], "5x": 3, "soxbind": 3, "icorv": 3, "4x": 3, "librosa": 3, "tf": 3, "pipelin": 3, "avail": [3, 4, 6, 7], "pypi": 3, "wheel": [3, 4], "pip": 3, "That": 3, "new": [3, 7], "follow": [3, 4, 5, 6, 7], "md": 3, "robust": 3, "guid": 3, "thoroughli": 3, "8": [3, 6], "9": [3, 6], "11": 3, "heavili": 3, "product": 3, "manylinux": 3, "x86_64": 3, "intel": 3, "amd": 3, "aarch64": 3, "arm": 3, "appl": [3, 6], "silicon": 3, "rel": 3, "modern": 3, "glibc": 3, "27": 3, "both": [2, 3, 6], "wide": [3, 6], "api": [3, 4], "quick": 3, "start": [3, 6, 7], "parallel": [3, 6], "chain": [3, 6, 7], "run": [3, 6, 7], "frequent": [3, 6], "question": 3, "doe": [3, 4, 6, 7], "over": [3, 6], "instrument": [3, 6], "accept": [3, 6, 7], "midi": [1, 3, 6], "design": [3, 6], "consider": 3, "licens": [3, 4], "cite": [], "repo": 3, "wrapper": [4, 6], "sourc": [4, 7], "cross": [4, 6], "develop": 4, "pybind11": 4, "bind": 4, "goal": [4, 7], "expos": [4, 6], "signal": [4, 6], "idiomat": 4, "wai": [4, 7], "provid": [4, 6, 7], "raw": [4, 6, 7], "perform": [4, 7], "dsp": 4, "hide": 4, "complex": 4, "programm": 4, "intuit": 4, "varieti": 4, "reason": 4, "wider": 4, "compat": [4, 5, 6], "notabl": 4, "rare": [4, 6], "fewer": [4, 6], "simpler": 4, "remov": [4, 6], "copi": 4, "associ": 4, "resourc": [4, 6, 7], "option": [4, 6, 7], "might": 4, "meant": 4, "music": 4, "appropri": [4, 6], "vice": 4, "versa": 4, "stabil": 4, "environ": 4, "where": [1, 4, 6, 7], "implement": [4, 6, 7], "logic": 4, "portabl": 4, "safe": [4, 7], "constraint": 4, "should": [4, 6, 7], "consid": [4, 6, 7], "gplv3": [4, 5], "static": [4, 5, 6, 7], "link": 4, "vendor": 4, "git": 4, "submodul": 4, "binari": [4, 6, 7], "distribut": 4, "Will": [4, 7], "increas": [4, 6, 7], "amount": [4, 6, 7], "compil": [1, 4, 5], "runtim": 4, "cannot": [2, 4, 6, 7], "user": 4, "instal": [4, 6, 7], "softwar": [3, 4], "complic": 4, "simplic": 4, "packag": [4, 6], "To": [6, 7], "academ": [], "its": [6, 7], "entri": [], "zenodo": [], "imag": [], "org": [], "badg": [], "doi": [], "5281": [], "7817838": [], "svg": [], "target": [6, 7], "alt": [], "bibtex": [], "tex": [], "sobot_peter_2023_7817838": [], "author": [], "titl": [], "modul": [6, 7], "class": [2, 6, 7], "subclass": 6, "each": [6, 7], "appli": [1, 6], "name": [6, 7], "after": [6, 7], "concept": 6, "musician": 6, "variou": 6, "pedal": 6, "togeth": 6, "complet": [6, 7], "control": 6, "main": 6, "my_pedalboard": 6, "treat": 6, "output_audio": 6, "input_audio": 6, "input_audio_sampler": 6, "zero": [6, 7], "composit": 6, "type": [6, 7], "none": [6, 7], "A": [6, 7], "seri": [6, 7], "act": 6, "come": [6, 7], "method": [6, 7], "alias": 6, "__call__": 6, "entir": [6, 7], "input_arrai": 6, "numpi": [6, 7], "ndarrai": [6, 7], "sample_r": [1, 6, 7], "float": [6, 7], "buffer_s": [6, 7], "8192": 6, "bool": [6, 7], "true": [6, 7], "dtype": [6, 7], "float32": [1, 6, 7], "alia": 6, "end": [6, 7], "insert": 6, "index": 6, "specifi": [6, 7], "properti": [6, 7], "is_effect": 6, "iff": [6, 7], "is_instru": 6, "32": [6, 7], "bit": [6, 7], "64": [3, 6], "point": [6, 7], "return": [6, 7], "arrai": [6, 7], "were": 6, "expect": [6, 7], "insid": 6, "remain": [6, 7], "anoth": 6, "datatyp": [6, 7], "convert": [6, 7], "argument": [6, 7], "higher": 6, "flag": 6, "determin": [6, 7], "befor": [6, 7], "begin": [6, 7], "previou": 6, "my_plugin": 6, "invok": 6, "valu": [6, 7], "store": [6, 7], "g": 6, "line": [6, 7], "lfo": 6, "etc": [6, 7], "unchang": 6, "path_to_plugin_fil": 6, "str": [6, 7], "parameter_valu": 6, "dict": 6, "union": [6, 7], "plugin_nam": 6, "externalplugin": 6, "two": 6, "bundl": [5, 6], "dictionari": 6, "initi": [6, 7], "match": [6, 7], "report": 6, "normal": 6, "string": [6, 7], "identifi": 6, "These": 6, "multi": [6, 7], "except": [6, 7], "thrown": [6, 7], "vst3plugin": [2, 6], "audiounitplugin": [2, 6], "throw": [6, 7], "importerror": 6, "found": [6, 7], "runtimeerror": [6, 7], "audioprocessorparamet": 6, "parameter_nam": 6, "search_step": 6, "1000": 6, "differ": [6, 7], "implicit": 6, "my": 6, "cool": 6, "delay_time_m": 6, "foobar": 6, "attribut": [6, 7], "400": 6, "tri": 6, "guess": 6, "valid": 6, "instanti": 6, "alwai": [6, 7], "accur": [6, 7], "had": 6, "raw_valu": 6, "bound": [6, 7], "label": 6, "hz": [6, 7], "db": 6, "fail": 6, "midi_messag": 6, "durat": [1, 6, 7], "messag": [1, 2, 6], "sequenc": [], "must": [6, 7], "byte": [6, 7], "mido": [1, 6], "tupl": 6, "look": 6, "midi_byt": 6, "timestamp_in_second": 6, "worth": 6, "sent": 6, "timestamp": 6, "indic": [6, 7], "whose": 6, "greater": 6, "ignor": 6, "held": [], "decai": [], "non": [6, 7], "unavail": 6, "loadabl": 6, "plug": [6, 7], "Ins": 6, "compon": 6, "helper": [], "overload": [], "rais": [6, 7], "get_plugin_names_for_fil": 6, "filenam": [6, 7], "given": [6, 7], "scan": [6, 7], "present": [6, 7], "what": 6, "show_editor": 6, "ui": 6, "nativ": [6, 7], "keyboardinterrupt": [6, 7], "bit_depth": [6, 7], "reduc": 6, "depth": [6, 7], "lo": 6, "fi": 6, "vertic": 6, "resolut": 6, "uniqu": 6, "repres": [6, 7], "horizont": 6, "per": [6, 7], "quantiz": 6, "integ": [6, 7], "decim": 6, "onto": 6, "pedalboard_n": 6, "rate_hz": 6, "centre_delay_m": 6, "feedback": 6, "frequenc": 6, "respons": 6, "centr": 6, "get": 6, "classic": 6, "m": 6, "low": 6, "feeback": 6, "volum": 6, "flanger": 6, "lower": 6, "lot": 6, "vibrato": 6, "oscil": 6, "hertz": 6, "hard": [6, 7], "threshold": 6, "decibel": 6, "algorithm": [6, 7], "introduc": [6, 7], "nois": [1, 6], "gsmcompressor": 6, "impulse_response_filenam": 6, "suitabl": 6, "thing": 6, "simul": 6, "dry": 6, "drive_db": 6, "linear": [6, 7], "tanh": 6, "hyperbol": 6, "tangent": 6, "waveshap": 6, "harmon": 6, "pleas": 6, "produc": [6, 7], "roughli": 6, "equival": 6, "def": 6, "x": 6, "db_to_gain": 6, "windowedsinc": [6, 7], "degrad": 6, "gsm": 6, "full": 6, "emul": 6, "2g": 6, "cellular": 6, "phone": 6, "connect": 6, "fix": 6, "8khz": 6, "codec": [6, 7], "decreas": [6, 7], "amplifi": 6, "attenu": 6, "think": 6, "highshelffilt": 6, "cutoff_frequency_hz": 6, "440": 6, "q": 6, "7071067690849304": 6, "shelf": 6, "variabl": [6, 7], "abov": [6, 7], "cutoff": 6, "boost": 6, "first": [6, 7], "order": 6, "roll": 6, "6db": 6, "octav": 6, "3db": 6, "frac": 6, "sqrt": 6, "express": 6, "factor": 6, "further": [6, 7], "iirfilt": 6, "abstract": 6, "kind": 6, "infinit": 6, "impuls": 6, "iir": 6, "lowshelffilt": 6, "peakfilt": 6, "invert": 6, "flip": 6, "polar": 6, "audibl": 6, "own": [5, 6], "take": 6, "mathemat": 6, "ident": [6, 7], "cancel": 6, "origin": [6, 7], "lpf12": 6, "200": 6, "reson": 6, "drive": 6, "base": [6, 7], "moog": 6, "synthes": 6, "ladder": 6, "invent": 6, "dr": 6, "bob": 6, "1968": 6, "below": [6, 7], "side": [6, 7], "peak": 6, "architectur": 6, "bpf12": 6, "band": [5, 6], "lpf24": 6, "24": 6, "hpf24": 6, "4": [2, 6], "bpf24": 6, "simpl": 6, "standard": 6, "featur": 6, "clipper": 6, "707x": 6, "vbr_qualiti": 6, "lame": [5, 6, 7], "encod": [6, 7], "current": [6, 7], "vbr": 6, "better": 6, "32khz": 6, "48khz": 6, "unsupport": [6, 7], "noiseg": 6, "gate": 6, "attack": 6, "expand": 6, "notch": 6, "centre_frequency_hz": 6, "1300": 6, "stage": 6, "sweep": 6, "magnitud": [6, 7], "affect": 6, "chri": 6, "cannam": 6, "wonder": 6, "rubber": [5, 6], "stretch": 6, "gener": [5, 6], "plugincontain": 6, "intend": 6, "direct": [6, 7], "target_sample_r": [6, 7], "8000": 6, "downsampl": 6, "upsampl": 6, "zeroorderhold": 6, "lowest": 6, "fastest": [6, 7], "slightli": 6, "less": [6, 7], "noisi": 6, "simplest": 6, "catmullrom": 6, "moder": 6, "good": 6, "fast": 6, "lagrang": 6, "highest": 6, "slowest": [6, 7], "still": [6, 7], "mere": 6, "damp": 6, "33": 6, "dry_level": 6, "width": 6, "freeze_mod": 6, "stereo": [6, 7], "tune": 6, "freeverb": 6, "ccrma": 6, "stanford": 6, "edu": 6, "jo": 6, "pasp": 6, "steinberg": [5, 6], "gmbh": [5, 6], "build": 6, "arg0": [6, 7], "load_preset": 6, "preset_file_path": 6, "preset": 6, "vstpreset": 6, "decod": [6, 7], "handl": 7, "behind": 7, "scene": 7, "my_filenam": 7, "441_000": 7, "necessari": 7, "accomplish": 7, "readableaudiofil": 7, "find": [6, 7], "yourself": 7, "writeableaudiofil": 7, "resampledreadableaudiofil": 7, "probabl": 7, "cover": 7, "file_lik": 7, "binaryio": 7, "liter": 7, "16": 7, "readabl": 7, "writeabl": 7, "default": [6, 7], "unlik": 7, "typic": 7, "trail": 7, "b": 7, "redund": 7, "exist": 7, "seekabl": 7, "stringio": 7, "my_fil": 7, "first_ten_second": 7, "ogg_buff": 7, "bytesio": 7, "get_audio_buff": 7, "22_050": 7, "white_nois": 7, "np": [1, 7], "rand": [1, 7], "wav_buff": 7, "getvalu": 7, "someth": [6, 7], "160": 7, "kilobit": 7, "re": 7, "four": 7, "1024": 7, "constructor": 7, "actual": 7, "those": [6, 7], "512": 7, "allow_feedback": 7, "devic": 7, "microphon": 7, "headphon": 7, "manag": 7, "delet": 7, "del": 7, "synchron": 7, "ctrl": [6, 7], "under": [5, 7], "hood": 7, "concern": 7, "never": 7, "left": 7, "dangl": 7, "background": [6, 7], "__enter__": 7, "nasti": 7, "longer": 7, "reachabl": 7, "scope": 7, "continu": 7, "plai": 7, "forev": 7, "won": 7, "exit": 7, "easier": 7, "cleanup": 7, "v0": [6, 7], "immedi": 7, "send": 7, "__exit__": 7, "arg1": 7, "arg2": 7, "onc": [6, 7], "otherwis": 7, "wrap": 7, "vorbi": 7, "3g2": 7, "3gp": 7, "adt": 7, "aif": 7, "aifc": 7, "amr": 7, "bwf": 7, "caf": 7, "ec3": 7, "latm": 7, "loa": 7, "m4a": 7, "m4b": 7, "m4r": 7, "mov": 7, "mp1": 7, "mp2": 7, "mp4": 7, "mpa": 7, "mpeg": 7, "qt": 7, "sd2": 7, "snd": 7, "w64": 7, "xhe": 7, "get_supported_read_format": 7, "extens": 7, "certain": 7, "want": [1, 7], "too": 7, "num_fram": 7, "channel": 7, "posit": 7, "decept": 7, "hour": 7, "long": 7, "hand": 7, "megabyt": 7, "decompress": 7, "nearli": 7, "gigabyt": 7, "debug": 7, "problem": 7, "dimension": 7, "length": [6, 7], "fill": 7, "exact_duration_known": 7, "situat": [6, 7], "occur": 7, "minimum": 7, "0f": 7, "maximum": 7, "read_raw": 7, "int8": 7, "int16": 7, "int32": 7, "constant": 7, "seek": 7, "locat": 7, "futur": 7, "pointer": 7, "usabl": 7, "divid": 7, "overestim": 7, "detail": [2, 7], "exact": 7, "estim": 7, "bitrat": 7, "ever": 7, "file_dtyp": 7, "regardless": 7, "441": 7, "discrep": 7, "due": 7, "fact": 7, "header": [6, 7], "xing": 7, "info": 7, "finish": 7, "forc": 7, "pars": 7, "correct": 7, "60": [1, 6, 7], "assert": [6, 7], "num_sampl": 7, "behaviour": 7, "later": 7, "prior": 7, "version": [2, 6, 7], "lack": 7, "audio_fil": 7, "resampling_qu": 7, "22050": 7, "fraction": 7, "streamresampl": 7, "obtain": 7, "benefit": 7, "respect": 7, "push": 7, "optim": 7, "retain": 7, "accuraci": 7, "22": 7, "050": 7, "source_sample_r": 7, "flush": 7, "input_lat": 7, "suppli": 7, "get_supported_write_format": 7, "filename_or_file_lik": 7, "assum": 7, "level": 7, "numer": 7, "128": 7, "256": 7, "advanc": 7, "v2": 7, "best": 7, "happen": [6, 7], "reliabl": 7, "float64": [6, 7], "typeerror": 7, "far": 7, "increment": 7, "kbp": 7, "v9": 7, "arg": [], "kwarg": [], "self": [], "kwd": [], "extern": 6, "part": [1, 6, 7], "conveni": [1, 6, 7], "note_on": [1, 6], "note_off": [1, 6], "magical8bitplug2": 1, "As": 2, "amd64": 3, "x86": 3, "contribut": [], "copyright": 5, "2021": 5, "2023": [], "ab": 5, "gnu": 5, "public": 5, "v3": 5, "carri": 5, "dual": 5, "commerci": 5, "sdk": 5, "media": 5, "technologi": 5, "gplv2": 5, "newer": 5, "libmp3lam": 5, "lgplv2": 5, "upgrad": 5, "inclus": 5, "permit": 5, "libgsm": 5, "isc": 5, "regist": 5, "trademark": 5, "e4m3t": [], "precis": 6, "expon": [], "e4m3": [], "from_char": [], "mantissa": [], "sign": [], "setview": [], "unord": [], "map": 1, "search": [], "member": [], "euclidean": [], "cosin": [], "innerproduct": [], "storagedatatyp": [], "vector": [], "float8": [], "448": [], "inspir": [], "paper": [], "fp8": [], "deep": [], "micikeviciu": [], "et": [], "al": [], "arxiv": [], "2209": [], "05433": [], "musllinux": 3, "initialization_timeout": 6, "spend": 6, "asynchron": 6, "startup": 6, "larger": 6, "properli": 6, "01": 7, "00": 7, "time_stretch": [5, 6], "stretch_factor": 6, "pitch_shift_in_semiton": 6, "shorten": 6, "doubl": 6, "_speed_": [], "halv": 6, "_length_": [], "fo": [], "dure": [6, 7], "independ": 6, "worri": 6, "thei": 6, "transient_mod": 6, "crisp": 6, "transient_detector": 6, "compound": 6, "retain_phase_continu": 6, "use_long_fft_window": 6, "use_time_domain_smooth": 6, "preserve_form": 6, "behavior": 6, "stretcher": 6, "transient": 6, "percuss": 6, "smooth": 6, "phase": 6, "adjac": 6, "bin": 6, "kept": 6, "similar": 6, "softer": 6, "phasier": 6, "fourier": 6, "clariti": 6, "crisper": 6, "sharp": 6, "substanti": 6, "profil": 6, "formant": 6, "voic": [3, 6], "grain": 6, "high_qual": 6, "translat": 3, "close_ev": 6, "event": 6, "editor": 6, "programmat": 6, "button": 6, "keyboard": 6, "shortcut": 6, "close_window_ev": 6, "other_thread": 6, "should_close_window_ev": [], "should_close_window": 6, "sr": [1, 7], "48000": 1, "welcom": [], "whatev": 1, "here": 1, "dataset": 1, "train": 1, "somehow": 1, "from_tensor_slic": 1, "lambda": 1, "numpy_funct": 1, "dummi": 1, "ml": 1, "kera": 1, "sequenti": 1, "layer": 1, "inputlay": 1, "input_shap": 1, "dens": 1, "loss": 1, "mse": 1, "fit": 1, "batch": 1, "epoch": 1, "hang": 6, "incorrect": 6, "outright": 6, "incompat": 6, "externalpluginreloadtyp": [], "unknown": [], "reinstanti": [], "clearsaudioonreset": [], "correctli": [], "persistsaudioonreset": [], "memoryview": 7, "py": [], "effici": 7, "consum": 7, "arbitrari": 7, "recommend": 7, "buf": 7, "mp3_buffer": 7, "flac_buff": 7, "categori": 6, "fall": 6, "descriptive_nam": 6, "descript": 6, "field": 6, "altern": 6, "has_shared_contain": 6, "again": 6, "manufacturer_nam": 6, "manufactur": 6, "auv3": 6, "appex": 6, "2024": 5, "raw_stat": 6, "plistlib": 6, "invalid": 6, "xml": 6, "prefix": 6, "suffix": 6, "null": 6, "squar": [], "abl": 7, "infer": 7, "dimens": 7, "correspond": 7, "layout": 7, "previous": [], "cach": 7, "writableaudiofil": 7, "recent": 7, "disambigu": 7, "But": 7, "And": 7, "hint": 7, "noth": 7, "anyth": 7, "slower": 6, "024": 6, "23": 6, "millisecond": 6, "fftw": 5, "11025hz": 6, "12khz": 6, "16khz": 6, "22050hz": 6, "24khz": 6}, "objects": {"": [[6, 0, 0, "-", "pedalboard"]], "pedalboard": [[6, 1, 1, "", "AudioProcessorParameter"], [6, 1, 1, "", "AudioUnitPlugin"], [6, 1, 1, "", "Bitcrush"], [6, 1, 1, "", "Chain"], [6, 1, 1, "", "Chorus"], [6, 1, 1, "", "Clipping"], [6, 1, 1, "", "Compressor"], [6, 1, 1, "", "Convolution"], [6, 1, 1, "", "Delay"], [6, 1, 1, "", "Distortion"], [6, 1, 1, "", "ExternalPlugin"], [6, 1, 1, "", "GSMFullRateCompressor"], [6, 1, 1, "", "Gain"], [6, 1, 1, "", "HighShelfFilter"], [6, 1, 1, "", "HighpassFilter"], [6, 1, 1, "", "IIRFilter"], [6, 1, 1, "", "Invert"], [6, 1, 1, "", "LadderFilter"], [6, 1, 1, "", "Limiter"], [6, 1, 1, "", "LowShelfFilter"], [6, 1, 1, "", "LowpassFilter"], [6, 1, 1, "", "MP3Compressor"], [6, 1, 1, "", "Mix"], [6, 1, 1, "", "NoiseGate"], [6, 1, 1, "", "PeakFilter"], [6, 1, 1, "", "Pedalboard"], [6, 1, 1, "", "Phaser"], [6, 1, 1, "", "PitchShift"], [6, 1, 1, "", "Plugin"], [6, 1, 1, "", "PluginContainer"], [6, 1, 1, "", "Resample"], [6, 1, 1, "", "Reverb"], [6, 1, 1, "", "VST3Plugin"], [7, 0, 0, "-", "io"], [6, 5, 1, "", "load_plugin"], [6, 5, 1, "", "time_stretch"]], "pedalboard.AudioProcessorParameter": [[6, 2, 1, "", "label"], [6, 2, 1, "", "units"]], "pedalboard.AudioUnitPlugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "category"], [6, 2, 1, "", "descriptive_name"], [6, 3, 1, "", "get_plugin_names_for_file"], [6, 2, 1, "", "has_shared_container"], [6, 2, 1, "", "identifier"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 2, 1, "", "manufacturer_name"], [6, 2, 1, "", "name"], [6, 3, 1, "", "process"], [6, 2, 1, "", "raw_state"], [6, 3, 1, "", "reset"], [6, 3, 1, "", "show_editor"], [6, 2, 1, "", "version"]], "pedalboard.Bitcrush": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "bit_depth"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Chain": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.Chorus": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 2, 1, "", "rate_hz"], [6, 3, 1, "", "reset"]], "pedalboard.Clipping": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Compressor": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Convolution": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Delay": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Distortion": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.ExternalPlugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.GSMFullRateCompressor": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Gain": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.HighShelfFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.HighpassFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.IIRFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Invert": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LadderFilter": [[6, 1, 1, "", "Mode"], [6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LadderFilter.Mode": [[6, 4, 1, "", "BPF12"], [6, 4, 1, "", "BPF24"], [6, 4, 1, "", "HPF12"], [6, 4, 1, "", "HPF24"], [6, 4, 1, "", "LPF12"], [6, 4, 1, "", "LPF24"]], "pedalboard.Limiter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LowShelfFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LowpassFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.MP3Compressor": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Mix": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.NoiseGate": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.PeakFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Pedalboard": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.Phaser": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.PitchShift": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Plugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.PluginContainer": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.Resample": [[6, 1, 1, "", "Quality"], [6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 2, 1, "", "quality"], [6, 3, 1, "", "reset"], [6, 2, 1, "", "target_sample_rate"]], "pedalboard.Resample.Quality": [[6, 4, 1, "", "CatmullRom"], [6, 4, 1, "", "Lagrange"], [6, 4, 1, "", "Linear"], [6, 4, 1, "", "WindowedSinc"], [6, 4, 1, "", "ZeroOrderHold"]], "pedalboard.Reverb": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.VST3Plugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "category"], [6, 2, 1, "", "descriptive_name"], [6, 3, 1, "", "get_plugin_names_for_file"], [6, 2, 1, "", "has_shared_container"], [6, 2, 1, "", "identifier"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "load_preset"], [6, 2, 1, "", "manufacturer_name"], [6, 2, 1, "", "name"], [6, 3, 1, "", "process"], [6, 2, 1, "", "raw_state"], [6, 3, 1, "", "reset"], [6, 3, 1, "", "show_editor"], [6, 2, 1, "", "version"]], "pedalboard.io": [[7, 1, 1, "", "AudioFile"], [7, 1, 1, "", "AudioStream"], [7, 1, 1, "", "ReadableAudioFile"], [7, 1, 1, "", "ResampledReadableAudioFile"], [7, 1, 1, "", "StreamResampler"], [7, 1, 1, "", "WriteableAudioFile"]], "pedalboard.io.AudioFile": [[7, 3, 1, "", "encode"]], "pedalboard.io.AudioStream": [[7, 3, 1, "", "__enter__"], [7, 3, 1, "", "__exit__"], [7, 2, 1, "", "plugins"], [7, 3, 1, "", "run"], [7, 2, 1, "", "running"]], "pedalboard.io.ReadableAudioFile": [[7, 3, 1, "", "__enter__"], [7, 3, 1, "", "__exit__"], [7, 3, 1, "", "close"], [7, 2, 1, "", "closed"], [7, 2, 1, "", "duration"], [7, 2, 1, "", "exact_duration_known"], [7, 2, 1, "", "file_dtype"], [7, 2, 1, "", "frames"], [7, 2, 1, "", "name"], [7, 2, 1, "", "num_channels"], [7, 3, 1, "", "read"], [7, 3, 1, "", "read_raw"], [7, 3, 1, "", "resampled_to"], [7, 2, 1, "", "samplerate"], [7, 3, 1, "", "seek"], [7, 3, 1, "", "seekable"], [7, 3, 1, "", "tell"]], "pedalboard.io.ResampledReadableAudioFile": [[7, 3, 1, "", "__enter__"], [7, 3, 1, "", "__exit__"], [7, 3, 1, "", "close"], [7, 2, 1, "", "closed"], [7, 2, 1, "", "duration"], [7, 2, 1, "", "exact_duration_known"], [7, 2, 1, "", "file_dtype"], [7, 2, 1, "", "frames"], [7, 2, 1, "", "name"], [7, 2, 1, "", "num_channels"], [7, 3, 1, "", "read"], [7, 2, 1, "", "resampling_quality"], [7, 2, 1, "", "samplerate"], [7, 3, 1, "", "seek"], [7, 3, 1, "", "seekable"], [7, 3, 1, "", "tell"]], "pedalboard.io.StreamResampler": [[7, 2, 1, "", "input_latency"], [7, 2, 1, "", "num_channels"], [7, 3, 1, "", "process"], [7, 2, 1, "", "quality"], [7, 3, 1, "", "reset"], [7, 2, 1, "", "source_sample_rate"], [7, 2, 1, "", "target_sample_rate"]], "pedalboard.io.WriteableAudioFile": [[7, 3, 1, "", "close"], [7, 2, 1, "", "closed"], [7, 2, 1, "", "file_dtype"], [7, 3, 1, "", "flush"], [7, 2, 1, "", "frames"], [7, 2, 1, "", "num_channels"], [7, 2, 1, "", "quality"], [7, 2, 1, "", "samplerate"], [7, 3, 1, "", "tell"], [7, 3, 1, "", "write"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:property", "3": "py:method", "4": "py:attribute", "5": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "property", "Python property"], "3": ["py", "method", "Python method"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"]}, "titleterms": {"plugin": [0, 1, 2, 4], "compat": [0, 3], "exampl": 1, "quick": 1, "start": 1, "make": 1, "guitar": 1, "style": 1, "pedalboard": [1, 2, 4, 6, 7], "us": [1, 2], "vst3": 1, "audio": [1, 2], "unit": 1, "creat": 1, "parallel": 1, "effect": [1, 2], "chain": 1, "run": 1, "live": [1, 2], "frequent": 2, "ask": 2, "question": 2, "can": 2, "real": 2, "time": 2, "doe": 2, "support": 2, "chang": 2, "": 2, "paramet": 2, "over": 2, "vst": 2, "instrument": [1, 2], "instead": 2, "accept": 2, "midi": 2, "featur": 3, "instal": 3, "refer": 3, "document": 3, "intern": 4, "ad": 4, "new": 4, "built": 4, "design": 4, "consider": 4, "licens": 5, "cite": [], "The": [6, 7], "api": [6, 7], "io": 7, "process": [], "other": [], "argument": [], "contribut": [], "voyag": [], "tf": 1, "data": 1, "pipelin": 1}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"Plugin Compatibility": [[0, "plugin-compatibility"]], "Examples": [[1, "examples"]], "Quick start": [[1, "quick-start"]], "Making a guitar-style pedalboard": [[1, "making-a-guitar-style-pedalboard"]], "Using VST3\u00ae or Audio Unit instrument and effect plugins": [[1, "using-vst3-or-audio-unit-instrument-and-effect-plugins"]], "Creating parallel effects chains": [[1, "creating-parallel-effects-chains"]], "Running Pedalboard on Live Audio": [[1, "running-pedalboard-on-live-audio"]], "Using Pedalboard in tf.data Pipelines": [[1, "using-pedalboard-in-tf-data-pipelines"]], "Frequently Asked Questions": [[2, "frequently-asked-questions"]], "Can Pedalboard be used with live (real-time) audio?": [[2, "can-pedalboard-be-used-with-live-real-time-audio"]], "Does Pedalboard support changing a plugin\u2019s parameters over time?": [[2, "does-pedalboard-support-changing-a-plugin-s-parameters-over-time"]], "Can Pedalboard be used with VST instruments, instead of effects?": [[2, "can-pedalboard-be-used-with-vst-instruments-instead-of-effects"]], "Can Pedalboard plugins accept MIDI?": [[2, "can-pedalboard-plugins-accept-midi"]], "Features": [[3, "features"]], "Installation": [[3, "installation"]], "Compatibility": [[3, "compatibility"]], "Reference": [[3, "reference"]], "Documentation": [[3, "documentation"]], "Pedalboard Internals": [[4, "pedalboard-internals"]], "Adding new built-in Pedalboard plugins": [[4, "adding-new-built-in-pedalboard-plugins"]], "Design considerations": [[4, "design-considerations"]], "License": [[5, "license"]], "The pedalboard API": [[6, "the-pedalboard-api"]], "The pedalboard.io API": [[7, "the-pedalboard-io-api"]]}, "indexentries": {"audioprocessorparameter (class in pedalboard)": [[6, "pedalboard.AudioProcessorParameter"]], "audiounitplugin (class in pedalboard)": [[6, "pedalboard.AudioUnitPlugin"]], "bpf12 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.BPF12"]], "bpf24 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.BPF24"]], "bitcrush (class in pedalboard)": [[6, "pedalboard.Bitcrush"]], "catmullrom (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.CatmullRom"]], "chain (class in pedalboard)": [[6, "pedalboard.Chain"]], "chorus (class in pedalboard)": [[6, "pedalboard.Chorus"]], "clipping (class in pedalboard)": [[6, "pedalboard.Clipping"]], "compressor (class in pedalboard)": [[6, "pedalboard.Compressor"]], "convolution (class in pedalboard)": [[6, "pedalboard.Convolution"]], "delay (class in pedalboard)": [[6, "pedalboard.Delay"]], "distortion (class in pedalboard)": [[6, "pedalboard.Distortion"]], "externalplugin (class in pedalboard)": [[6, "pedalboard.ExternalPlugin"]], "gsmfullratecompressor (class in pedalboard)": [[6, "pedalboard.GSMFullRateCompressor"]], "gain (class in pedalboard)": [[6, "pedalboard.Gain"]], "hpf12 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.HPF12"]], "hpf24 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.HPF24"]], "highshelffilter (class in pedalboard)": [[6, "pedalboard.HighShelfFilter"]], "highpassfilter (class in pedalboard)": [[6, "pedalboard.HighpassFilter"]], "iirfilter (class in pedalboard)": [[6, "pedalboard.IIRFilter"]], "invert (class in pedalboard)": [[6, "pedalboard.Invert"]], "lpf12 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.LPF12"]], "lpf24 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.LPF24"]], "ladderfilter (class in pedalboard)": [[6, "pedalboard.LadderFilter"]], "ladderfilter.mode (class in pedalboard)": [[6, "pedalboard.LadderFilter.Mode"]], "lagrange (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.Lagrange"]], "limiter (class in pedalboard)": [[6, "pedalboard.Limiter"]], "linear (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.Linear"]], "lowshelffilter (class in pedalboard)": [[6, "pedalboard.LowShelfFilter"]], "lowpassfilter (class in pedalboard)": [[6, "pedalboard.LowpassFilter"]], "mp3compressor (class in pedalboard)": [[6, "pedalboard.MP3Compressor"]], "mix (class in pedalboard)": [[6, "pedalboard.Mix"]], "noisegate (class in pedalboard)": [[6, "pedalboard.NoiseGate"]], "peakfilter (class in pedalboard)": [[6, "pedalboard.PeakFilter"]], "pedalboard (class in pedalboard)": [[6, "pedalboard.Pedalboard"]], "phaser (class in pedalboard)": [[6, "pedalboard.Phaser"]], "pitchshift (class in pedalboard)": [[6, "pedalboard.PitchShift"]], "plugin (class in pedalboard)": [[6, "pedalboard.Plugin"]], "plugincontainer (class in pedalboard)": [[6, "pedalboard.PluginContainer"]], "resample (class in pedalboard)": [[6, "pedalboard.Resample"]], "resample.quality (class in pedalboard)": [[6, "pedalboard.Resample.Quality"]], "reverb (class in pedalboard)": [[6, "pedalboard.Reverb"]], "vst3plugin (class in pedalboard)": [[6, "pedalboard.VST3Plugin"]], "windowedsinc (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.WindowedSinc"]], "zeroorderhold (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.ZeroOrderHold"]], "__call__() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.__call__"]], "__call__() (pedalboard.bitcrush method)": [[6, "pedalboard.Bitcrush.__call__"]], "__call__() (pedalboard.chain method)": [[6, "pedalboard.Chain.__call__"]], "__call__() (pedalboard.chorus method)": [[6, "pedalboard.Chorus.__call__"]], "__call__() (pedalboard.clipping method)": [[6, "pedalboard.Clipping.__call__"]], "__call__() (pedalboard.compressor method)": [[6, "pedalboard.Compressor.__call__"]], "__call__() (pedalboard.convolution method)": [[6, "pedalboard.Convolution.__call__"]], "__call__() (pedalboard.delay method)": [[6, "pedalboard.Delay.__call__"]], "__call__() (pedalboard.distortion method)": [[6, "pedalboard.Distortion.__call__"]], "__call__() (pedalboard.externalplugin method)": [[6, "pedalboard.ExternalPlugin.__call__"]], "__call__() (pedalboard.gsmfullratecompressor method)": [[6, "pedalboard.GSMFullRateCompressor.__call__"]], "__call__() (pedalboard.gain method)": [[6, "pedalboard.Gain.__call__"]], "__call__() (pedalboard.highshelffilter method)": [[6, "pedalboard.HighShelfFilter.__call__"]], "__call__() (pedalboard.highpassfilter method)": [[6, "pedalboard.HighpassFilter.__call__"]], "__call__() (pedalboard.iirfilter method)": [[6, "pedalboard.IIRFilter.__call__"]], "__call__() (pedalboard.invert method)": [[6, "pedalboard.Invert.__call__"]], "__call__() (pedalboard.ladderfilter method)": [[6, "pedalboard.LadderFilter.__call__"]], "__call__() (pedalboard.limiter method)": [[6, "pedalboard.Limiter.__call__"]], "__call__() (pedalboard.lowshelffilter method)": [[6, "pedalboard.LowShelfFilter.__call__"]], "__call__() (pedalboard.lowpassfilter method)": [[6, "pedalboard.LowpassFilter.__call__"]], "__call__() (pedalboard.mp3compressor method)": [[6, "pedalboard.MP3Compressor.__call__"]], "__call__() (pedalboard.mix method)": [[6, "pedalboard.Mix.__call__"]], "__call__() (pedalboard.noisegate method)": [[6, "pedalboard.NoiseGate.__call__"]], "__call__() (pedalboard.peakfilter method)": [[6, "pedalboard.PeakFilter.__call__"]], "__call__() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.__call__"]], "__call__() (pedalboard.phaser method)": [[6, "pedalboard.Phaser.__call__"]], "__call__() (pedalboard.pitchshift method)": [[6, "pedalboard.PitchShift.__call__"]], "__call__() (pedalboard.plugin method)": [[6, "pedalboard.Plugin.__call__"]], "__call__() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.__call__"]], "__call__() (pedalboard.resample method)": [[6, "pedalboard.Resample.__call__"]], "__call__() (pedalboard.reverb method)": [[6, "pedalboard.Reverb.__call__"]], "__call__() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.__call__"]], "append() (pedalboard.chain method)": [[6, "pedalboard.Chain.append"]], "append() (pedalboard.mix method)": [[6, "pedalboard.Mix.append"]], "append() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.append"]], "append() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.append"]], "bit_depth (pedalboard.bitcrush property)": [[6, "pedalboard.Bitcrush.bit_depth"]], "category (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.category"]], "category (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.category"]], "descriptive_name (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.descriptive_name"]], "descriptive_name (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.descriptive_name"]], "get_plugin_names_for_file() (pedalboard.audiounitplugin static method)": [[6, "pedalboard.AudioUnitPlugin.get_plugin_names_for_file"]], "get_plugin_names_for_file() (pedalboard.vst3plugin static method)": [[6, "pedalboard.VST3Plugin.get_plugin_names_for_file"]], "has_shared_container (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.has_shared_container"]], "has_shared_container (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.has_shared_container"]], "identifier (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.identifier"]], "identifier (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.identifier"]], "insert() (pedalboard.chain method)": [[6, "pedalboard.Chain.insert"]], "insert() (pedalboard.mix method)": [[6, "pedalboard.Mix.insert"]], "insert() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.insert"]], "insert() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.insert"]], "is_effect (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.is_effect"]], "is_effect (pedalboard.bitcrush property)": [[6, "pedalboard.Bitcrush.is_effect"]], "is_effect (pedalboard.chain property)": [[6, "pedalboard.Chain.is_effect"]], "is_effect (pedalboard.chorus property)": [[6, "pedalboard.Chorus.is_effect"]], "is_effect (pedalboard.clipping property)": [[6, "pedalboard.Clipping.is_effect"]], "is_effect (pedalboard.compressor property)": [[6, "pedalboard.Compressor.is_effect"]], "is_effect (pedalboard.convolution property)": [[6, "pedalboard.Convolution.is_effect"]], "is_effect (pedalboard.delay property)": [[6, "pedalboard.Delay.is_effect"]], "is_effect (pedalboard.distortion property)": [[6, "pedalboard.Distortion.is_effect"]], "is_effect (pedalboard.externalplugin property)": [[6, "pedalboard.ExternalPlugin.is_effect"]], "is_effect (pedalboard.gsmfullratecompressor property)": [[6, "pedalboard.GSMFullRateCompressor.is_effect"]], "is_effect (pedalboard.gain property)": [[6, "pedalboard.Gain.is_effect"]], "is_effect (pedalboard.highshelffilter property)": [[6, "pedalboard.HighShelfFilter.is_effect"]], "is_effect (pedalboard.highpassfilter property)": [[6, "pedalboard.HighpassFilter.is_effect"]], "is_effect (pedalboard.iirfilter property)": [[6, "pedalboard.IIRFilter.is_effect"]], "is_effect (pedalboard.invert property)": [[6, "pedalboard.Invert.is_effect"]], "is_effect (pedalboard.ladderfilter property)": [[6, "pedalboard.LadderFilter.is_effect"]], "is_effect (pedalboard.limiter property)": [[6, "pedalboard.Limiter.is_effect"]], "is_effect (pedalboard.lowshelffilter property)": [[6, "pedalboard.LowShelfFilter.is_effect"]], "is_effect (pedalboard.lowpassfilter property)": [[6, "pedalboard.LowpassFilter.is_effect"]], "is_effect (pedalboard.mp3compressor property)": [[6, "pedalboard.MP3Compressor.is_effect"]], "is_effect (pedalboard.mix property)": [[6, "pedalboard.Mix.is_effect"]], "is_effect (pedalboard.noisegate property)": [[6, "pedalboard.NoiseGate.is_effect"]], "is_effect (pedalboard.peakfilter property)": [[6, "pedalboard.PeakFilter.is_effect"]], "is_effect (pedalboard.pedalboard property)": [[6, "pedalboard.Pedalboard.is_effect"]], "is_effect (pedalboard.phaser property)": [[6, "pedalboard.Phaser.is_effect"]], "is_effect (pedalboard.pitchshift property)": [[6, "pedalboard.PitchShift.is_effect"]], "is_effect (pedalboard.plugin property)": [[6, "pedalboard.Plugin.is_effect"]], "is_effect (pedalboard.plugincontainer property)": [[6, "pedalboard.PluginContainer.is_effect"]], "is_effect (pedalboard.resample property)": [[6, "pedalboard.Resample.is_effect"]], "is_effect (pedalboard.reverb property)": [[6, "pedalboard.Reverb.is_effect"]], "is_effect (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.is_effect"]], "is_instrument (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.is_instrument"]], "is_instrument (pedalboard.bitcrush property)": [[6, "pedalboard.Bitcrush.is_instrument"]], "is_instrument (pedalboard.chain property)": [[6, "pedalboard.Chain.is_instrument"]], "is_instrument (pedalboard.chorus property)": [[6, "pedalboard.Chorus.is_instrument"]], "is_instrument (pedalboard.clipping property)": [[6, "pedalboard.Clipping.is_instrument"]], "is_instrument (pedalboard.compressor property)": [[6, "pedalboard.Compressor.is_instrument"]], "is_instrument (pedalboard.convolution property)": [[6, "pedalboard.Convolution.is_instrument"]], "is_instrument (pedalboard.delay property)": [[6, "pedalboard.Delay.is_instrument"]], "is_instrument (pedalboard.distortion property)": [[6, "pedalboard.Distortion.is_instrument"]], "is_instrument (pedalboard.externalplugin property)": [[6, "pedalboard.ExternalPlugin.is_instrument"]], "is_instrument (pedalboard.gsmfullratecompressor property)": [[6, "pedalboard.GSMFullRateCompressor.is_instrument"]], "is_instrument (pedalboard.gain property)": [[6, "pedalboard.Gain.is_instrument"]], "is_instrument (pedalboard.highshelffilter property)": [[6, "pedalboard.HighShelfFilter.is_instrument"]], "is_instrument (pedalboard.highpassfilter property)": [[6, "pedalboard.HighpassFilter.is_instrument"]], "is_instrument (pedalboard.iirfilter property)": [[6, "pedalboard.IIRFilter.is_instrument"]], "is_instrument (pedalboard.invert property)": [[6, "pedalboard.Invert.is_instrument"]], "is_instrument (pedalboard.ladderfilter property)": [[6, "pedalboard.LadderFilter.is_instrument"]], "is_instrument (pedalboard.limiter property)": [[6, "pedalboard.Limiter.is_instrument"]], "is_instrument (pedalboard.lowshelffilter property)": [[6, "pedalboard.LowShelfFilter.is_instrument"]], "is_instrument (pedalboard.lowpassfilter property)": [[6, "pedalboard.LowpassFilter.is_instrument"]], "is_instrument (pedalboard.mp3compressor property)": [[6, "pedalboard.MP3Compressor.is_instrument"]], "is_instrument (pedalboard.mix property)": [[6, "pedalboard.Mix.is_instrument"]], "is_instrument (pedalboard.noisegate property)": [[6, "pedalboard.NoiseGate.is_instrument"]], "is_instrument (pedalboard.peakfilter property)": [[6, "pedalboard.PeakFilter.is_instrument"]], "is_instrument (pedalboard.pedalboard property)": [[6, "pedalboard.Pedalboard.is_instrument"]], "is_instrument (pedalboard.phaser property)": [[6, "pedalboard.Phaser.is_instrument"]], "is_instrument (pedalboard.pitchshift property)": [[6, "pedalboard.PitchShift.is_instrument"]], "is_instrument (pedalboard.plugin property)": [[6, "pedalboard.Plugin.is_instrument"]], "is_instrument (pedalboard.plugincontainer property)": [[6, "pedalboard.PluginContainer.is_instrument"]], "is_instrument (pedalboard.resample property)": [[6, "pedalboard.Resample.is_instrument"]], "is_instrument (pedalboard.reverb property)": [[6, "pedalboard.Reverb.is_instrument"]], "is_instrument (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.is_instrument"]], "label (pedalboard.audioprocessorparameter property)": [[6, "pedalboard.AudioProcessorParameter.label"]], "load_plugin() (in module pedalboard)": [[6, "pedalboard.load_plugin"]], "load_preset() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.load_preset"]], "manufacturer_name (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.manufacturer_name"]], "manufacturer_name (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.manufacturer_name"]], "module": [[6, "module-pedalboard"], [7, "module-pedalboard.io"]], "name (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.name"]], "name (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.name"]], "pedalboard": [[6, "module-pedalboard"]], "process() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.process"]], "process() (pedalboard.bitcrush method)": [[6, "pedalboard.Bitcrush.process"]], "process() (pedalboard.chain method)": [[6, "pedalboard.Chain.process"]], "process() (pedalboard.chorus method)": [[6, "pedalboard.Chorus.process"]], "process() (pedalboard.clipping method)": [[6, "pedalboard.Clipping.process"]], "process() (pedalboard.compressor method)": [[6, "pedalboard.Compressor.process"]], "process() (pedalboard.convolution method)": [[6, "pedalboard.Convolution.process"]], "process() (pedalboard.delay method)": [[6, "pedalboard.Delay.process"]], "process() (pedalboard.distortion method)": [[6, "pedalboard.Distortion.process"]], "process() (pedalboard.externalplugin method)": [[6, "pedalboard.ExternalPlugin.process"]], "process() (pedalboard.gsmfullratecompressor method)": [[6, "pedalboard.GSMFullRateCompressor.process"]], "process() (pedalboard.gain method)": [[6, "pedalboard.Gain.process"]], "process() (pedalboard.highshelffilter method)": [[6, "pedalboard.HighShelfFilter.process"]], "process() (pedalboard.highpassfilter method)": [[6, "pedalboard.HighpassFilter.process"]], "process() (pedalboard.iirfilter method)": [[6, "pedalboard.IIRFilter.process"]], "process() (pedalboard.invert method)": [[6, "pedalboard.Invert.process"]], "process() (pedalboard.ladderfilter method)": [[6, "pedalboard.LadderFilter.process"]], "process() (pedalboard.limiter method)": [[6, "pedalboard.Limiter.process"]], "process() (pedalboard.lowshelffilter method)": [[6, "pedalboard.LowShelfFilter.process"]], "process() (pedalboard.lowpassfilter method)": [[6, "pedalboard.LowpassFilter.process"]], "process() (pedalboard.mp3compressor method)": [[6, "pedalboard.MP3Compressor.process"]], "process() (pedalboard.mix method)": [[6, "pedalboard.Mix.process"]], "process() (pedalboard.noisegate method)": [[6, "pedalboard.NoiseGate.process"]], "process() (pedalboard.peakfilter method)": [[6, "pedalboard.PeakFilter.process"]], "process() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.process"]], "process() (pedalboard.phaser method)": [[6, "pedalboard.Phaser.process"]], "process() (pedalboard.pitchshift method)": [[6, "pedalboard.PitchShift.process"]], "process() (pedalboard.plugin method)": [[6, "pedalboard.Plugin.process"]], "process() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.process"]], "process() (pedalboard.resample method)": [[6, "pedalboard.Resample.process"]], "process() (pedalboard.reverb method)": [[6, "pedalboard.Reverb.process"]], "process() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.process"]], "quality (pedalboard.resample property)": [[6, "pedalboard.Resample.quality"]], "rate_hz (pedalboard.chorus property)": [[6, "pedalboard.Chorus.rate_hz"]], "raw_state (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.raw_state"]], "raw_state (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.raw_state"]], "remove() (pedalboard.chain method)": [[6, "pedalboard.Chain.remove"]], "remove() (pedalboard.mix method)": [[6, "pedalboard.Mix.remove"]], "remove() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.remove"]], "remove() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.remove"]], "reset() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.reset"]], "reset() (pedalboard.bitcrush method)": [[6, "pedalboard.Bitcrush.reset"]], "reset() (pedalboard.chain method)": [[6, "pedalboard.Chain.reset"]], "reset() (pedalboard.chorus method)": [[6, "pedalboard.Chorus.reset"]], "reset() (pedalboard.clipping method)": [[6, "pedalboard.Clipping.reset"]], "reset() (pedalboard.compressor method)": [[6, "pedalboard.Compressor.reset"]], "reset() (pedalboard.convolution method)": [[6, "pedalboard.Convolution.reset"]], "reset() (pedalboard.delay method)": [[6, "pedalboard.Delay.reset"]], "reset() (pedalboard.distortion method)": [[6, "pedalboard.Distortion.reset"]], "reset() (pedalboard.externalplugin method)": [[6, "pedalboard.ExternalPlugin.reset"]], "reset() (pedalboard.gsmfullratecompressor method)": [[6, "pedalboard.GSMFullRateCompressor.reset"]], "reset() (pedalboard.gain method)": [[6, "pedalboard.Gain.reset"]], "reset() (pedalboard.highshelffilter method)": [[6, "pedalboard.HighShelfFilter.reset"]], "reset() (pedalboard.highpassfilter method)": [[6, "pedalboard.HighpassFilter.reset"]], "reset() (pedalboard.iirfilter method)": [[6, "pedalboard.IIRFilter.reset"]], "reset() (pedalboard.invert method)": [[6, "pedalboard.Invert.reset"]], "reset() (pedalboard.ladderfilter method)": [[6, "pedalboard.LadderFilter.reset"]], "reset() (pedalboard.limiter method)": [[6, "pedalboard.Limiter.reset"]], "reset() (pedalboard.lowshelffilter method)": [[6, "pedalboard.LowShelfFilter.reset"]], "reset() (pedalboard.lowpassfilter method)": [[6, "pedalboard.LowpassFilter.reset"]], "reset() (pedalboard.mp3compressor method)": [[6, "pedalboard.MP3Compressor.reset"]], "reset() (pedalboard.mix method)": [[6, "pedalboard.Mix.reset"]], "reset() (pedalboard.noisegate method)": [[6, "pedalboard.NoiseGate.reset"]], "reset() (pedalboard.peakfilter method)": [[6, "pedalboard.PeakFilter.reset"]], "reset() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.reset"]], "reset() (pedalboard.phaser method)": [[6, "pedalboard.Phaser.reset"]], "reset() (pedalboard.pitchshift method)": [[6, "pedalboard.PitchShift.reset"]], "reset() (pedalboard.plugin method)": [[6, "pedalboard.Plugin.reset"]], "reset() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.reset"]], "reset() (pedalboard.resample method)": [[6, "pedalboard.Resample.reset"]], "reset() (pedalboard.reverb method)": [[6, "pedalboard.Reverb.reset"]], "reset() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.reset"]], "show_editor() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.show_editor"]], "show_editor() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.show_editor"]], "target_sample_rate (pedalboard.resample property)": [[6, "pedalboard.Resample.target_sample_rate"]], "time_stretch() (in module pedalboard)": [[6, "pedalboard.time_stretch"]], "units (pedalboard.audioprocessorparameter property)": [[6, "pedalboard.AudioProcessorParameter.units"]], "version (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.version"]], "version (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.version"]], "audiofile (class in pedalboard.io)": [[7, "pedalboard.io.AudioFile"]], "audiostream (class in pedalboard.io)": [[7, "pedalboard.io.AudioStream"]], "readableaudiofile (class in pedalboard.io)": [[7, "pedalboard.io.ReadableAudioFile"]], "resampledreadableaudiofile (class in pedalboard.io)": [[7, "pedalboard.io.ResampledReadableAudioFile"]], "streamresampler (class in pedalboard.io)": [[7, "pedalboard.io.StreamResampler"]], "writeableaudiofile (class in pedalboard.io)": [[7, "pedalboard.io.WriteableAudioFile"]], "__enter__() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.__enter__"]], "__enter__() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.__enter__"]], "__enter__() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.__enter__"]], "__exit__() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.__exit__"]], "__exit__() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.__exit__"]], "__exit__() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.__exit__"]], "close() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.close"]], "close() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.close"]], "close() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.close"]], "closed (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.closed"]], "closed (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.closed"]], "closed (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.closed"]], "duration (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.duration"]], "duration (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.duration"]], "encode() (pedalboard.io.audiofile static method)": [[7, "pedalboard.io.AudioFile.encode"]], "exact_duration_known (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.exact_duration_known"]], "exact_duration_known (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.exact_duration_known"]], "file_dtype (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.file_dtype"]], "file_dtype (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.file_dtype"]], "file_dtype (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.file_dtype"]], "flush() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.flush"]], "frames (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.frames"]], "frames (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.frames"]], "frames (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.frames"]], "input_latency (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.input_latency"]], "name (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.name"]], "name (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.name"]], "num_channels (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.num_channels"]], "num_channels (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.num_channels"]], "num_channels (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.num_channels"]], "num_channels (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.num_channels"]], "pedalboard.io": [[7, "module-pedalboard.io"]], "plugins (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.plugins"]], "process() (pedalboard.io.streamresampler method)": [[7, "pedalboard.io.StreamResampler.process"]], "quality (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.quality"]], "quality (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.quality"]], "read() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.read"]], "read() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.read"]], "read_raw() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.read_raw"]], "resampled_to() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.resampled_to"]], "resampling_quality (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.resampling_quality"]], "reset() (pedalboard.io.streamresampler method)": [[7, "pedalboard.io.StreamResampler.reset"]], "run() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.run"]], "running (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.running"]], "samplerate (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.samplerate"]], "samplerate (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.samplerate"]], "samplerate (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.samplerate"]], "seek() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.seek"]], "seek() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.seek"]], "seekable() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.seekable"]], "seekable() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.seekable"]], "source_sample_rate (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.source_sample_rate"]], "target_sample_rate (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.target_sample_rate"]], "tell() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.tell"]], "tell() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.tell"]], "tell() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.tell"]], "write() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.write"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["compatibility", "examples", "faq", "index", "internals", "license", "reference/pedalboard", "reference/pedalboard.io"], "filenames": ["compatibility.rst", "examples.rst", "faq.rst", "index.rst", "internals.rst", "license.rst", "reference/pedalboard.rst", "reference/pedalboard.io.rst"], "titles": ["Plugin Compatibility", "Examples", "Frequently Asked Questions", "Features", "Pedalboard Internals", "License", "The pedalboard API", "The pedalboard.io API"], "terms": {"pedalboard": [0, 3, 5], "allow": [0, 1, 3, 6, 7], "load": [0, 1, 3, 4, 6], "vst3": [0, 3, 4, 5, 6], "audio": [0, 3, 4, 5, 6, 7], "unit": [0, 2, 3, 4, 6], "which": [0, 5, 6, 7], "could": [0, 6, 7], "contain": [0, 1, 6, 7], "ani": [0, 2, 4, 6, 7], "code": [0, 2, 4, 5, 7], "most": [0, 3, 4, 6, 7], "have": [0, 4, 6, 7], "been": [0, 7], "test": [0, 3, 4], "work": [0, 1, 3, 6, 7], "just": [0, 1, 4, 6, 7], "fine": [0, 6], "some": [0, 1, 4, 6, 7], "mai": [0, 4, 6, 7], "worst": [0, 7], "even": [0, 3, 7], "crash": [0, 6, 7], "python": [0, 1, 3, 4, 6, 7], "interpret": [0, 3, 7], "without": [0, 3, 6, 7], "warn": [0, 7], "abil": [0, 6], "catch": 0, "error": [0, 6, 7], "ar": [0, 1, 3, 4, 5, 6, 7], "well": [0, 3, 4, 6, 7], "behav": [0, 1], "conform": 0, "set": [0, 1, 2, 6, 7], "convent": 0, "how": [0, 1, 6], "suppos": 0, "mani": [0, 3, 6, 7], "do": [0, 1, 6, 7], "specif": [0, 6], "attempt": [0, 7], "detect": [0, 6], "common": [0, 3], "program": [0, 1, 6, 7], "can": [0, 1, 3, 4, 6, 7], "around": [0, 4, 6], "issu": [0, 4, 6], "includ": [0, 1, 3, 4, 5, 6], "automat": [0, 3, 6, 7], "don": [0, 1, 6, 7], "t": [0, 1, 2, 6, 7], "clear": [0, 6], "intern": [0, 3, 6, 7], "state": [0, 6, 7], "when": [0, 3, 4, 6, 7], "ask": [0, 3], "so": [0, 1, 2, 6, 7], "misbehav": 0, "notic": 0, "If": [0, 1, 3, 6, 7], "i": [0, 1, 2, 3, 4, 5, 6, 7], "being": [0, 7], "render": [0, 1, 2, 3, 6, 7], "incorrectli": 0, "leak": [0, 7], "from": [0, 1, 2, 3, 5, 6, 7], "one": [0, 1, 3, 6, 7], "process": [0, 1, 2, 3, 4, 5, 6, 7], "call": [0, 6, 7], "next": 0, "an": [0, 1, 4, 6, 7], "undesir": 0, "fashion": 0, "try": [0, 6, 7], "pass": [0, 1, 2, 6, 7], "silenc": 0, "between": [0, 2, 6, 7], "ensur": [0, 2, 4, 6, 7], "reverb": [0, 1, 2, 3, 6, 7], "tail": [0, 2, 6], "other": [0, 1, 3, 6, 7], "ha": [0, 1, 6, 7], "time": [0, 1, 3, 6, 7], "fade": 0, "reload": 0, "everi": [0, 4, 6, 7], "load_plugin": [0, 1, 3, 4, 6], "note": [1, 6, 7], "you": [1, 3, 6, 7], "d": [1, 7], "rather": [1, 7], "watch": 1, "video": 1, "instead": [1, 3, 6, 7], "read": [1, 2, 3, 6, 7], "document": [1, 6, 7], "feat": 1, "youtub": 1, "import": [1, 2, 4, 6, 7], "choru": [1, 3, 6], "io": [1, 2, 3, 6], "audiofil": [1, 2, 6, 7], "object": [1, 6, 7], "multipl": [1, 3, 6, 7], "board": [1, 2], "room_siz": [1, 6], "0": [1, 2, 6, 7], "25": [1, 6], "open": [1, 2, 4, 6, 7], "file": [1, 2, 3, 4, 6, 7], "like": [1, 3, 6, 7], "regular": [1, 6, 7], "wav": [1, 2, 3, 6, 7], "f": [1, 6, 7], "write": [1, 2, 3, 6, 7], "output": [1, 2, 6, 7], "w": [1, 2, 6, 7], "sampler": [1, 2, 6, 7], "num_channel": [1, 2, 6, 7], "o": [1, 2, 3, 6, 7], "second": [1, 6, 7], "until": [1, 6, 7], "empti": [1, 6], "while": [1, 2, 6, 7], "tell": [1, 7], "frame": [1, 2, 7], "chunk": [1, 2, 6, 7], "int": [6, 7], "through": [1, 2, 6, 7], "our": [1, 2], "reset": [1, 2, 6, 7], "fals": [1, 2, 6, 7], "For": [1, 6, 7], "more": [1, 2, 3, 4, 6, 7], "inform": [1, 7], "about": [1, 6, 7], "paramet": [1, 3, 6, 7], "see": [1, 2, 6, 7], "http": 6, "spotifi": [3, 5], "github": [3, 6], "refer": [], "html": 6, "_": 6, "It": [1, 3], "thi": [1, 2, 5, 6, 7], "smaller": [1, 2, 6, 7], "whole": 1, "resampl": [1, 3, 6, 7], "desir": 1, "sampl": [1, 2, 6, 7], "rate": [1, 2, 6, 7], "44100": [1, 6, 7], "input": [1, 6, 7], "resampled_to": [1, 7], "pretti": 1, "interest": 1, "sound": [1, 6], "compressor": [1, 2, 3, 6], "threshold_db": [1, 6], "50": [1, 6], "ratio": [1, 6], "gain": [1, 3, 6], "gain_db": [1, 6], "30": [1, 7], "ladderfilt": [1, 3, 6], "mode": [1, 6, 7], "hpf12": [1, 6], "cutoff_hz": [1, 6], "900": 1, "phaser": [1, 3, 6], "convolut": [1, 3, 6], "guitar_amp": 1, "1": [1, 2, 3, 6, 7], "list": [1, 6, 7], "add": [1, 3, 4, 6, 7], "append": [1, 6, 7], "10": [1, 3, 6, 7], "limit": [1, 3, 6], "chang": [1, 3, 6, 7], "easili": 1, "40": 1, "back": [1, 6, 7], "shape": [1, 2, 7], "known": 1, "path": [1, 6, 7], "disk": [1, 7], "vst": [1, 3, 5], "roughrider3": 1, "print": [1, 6, 7], "kei": [1, 6], "dict_kei": 1, "sc_hpf_hz": 1, "input_lvl_db": 1, "sensitivity_db": 1, "attack_m": [1, 6], "release_m": [1, 6], "makeup_db": 1, "mix": [1, 6], "output_lvl_db": 1, "sc_activ": 1, "full_bandwidth": 1, "bypass": 1, "15": 1, "r": 7, "put": 1, "same": [1, 4, 6, 7], "instanc": [1, 4, 6, 7], "delai": [1, 3, 6], "pitch": [1, 3, 6], "shift": [1, 6], "themselv": [1, 6], "nest": [1, 6], "them": [1, 6], "much": [1, 6, 7], "distort": [1, 3, 6], "pitchshift": [1, 3, 5, 6], "passthrough": 1, "delay_and_pitch_shift": 1, "delay_second": [1, 6], "semiton": [1, 6], "7": [1, 2, 3, 6, 7], "3": [1, 3, 6, 7], "delay_longer_and_more_pitch_shift": 1, "5": [1, 6], "12": [1, 3, 6, 7], "6": [1, 3, 5, 6, 7], "front": 1, "all": [1, 3, 4, 6, 7], "simultan": 1, "final": 1, "On": 1, "maco": [1, 3, 4, 6, 7], "window": [1, 3, 4, 6, 7], "support": [1, 3, 4, 6, 7], "stream": [1, 3, 6, 7], "audiostream": [1, 2, 3, 7], "real": [1, 3, 6, 7], "manipul": 1, "ad": [1, 3, 6, 7], "up": [1, 3, 5, 6], "input_device_nam": [1, 7], "apoge": 1, "jam": 1, "interfac": [1, 4, 6, 7], "output_device_nam": [1, 7], "macbook": 1, "pro": 1, "speaker": [1, 6, 7], "now": [1, 7], "out": [1, 3, 6, 7], "your": [1, 7], "press": [1, 6], "enter": [1, 7], "stop": [1, 7], "The": [1, 4, 5], "close": [1, 6, 7], "folder": 1, "repositori": [1, 4], "demo": 1, "colab": 1, "notebook": 1, "peter": 1, "sobot": 1, "europython": 1, "2022": 1, "interact": [1, 6, 7], "web": 1, "hug": 1, "face": 1, "space": 1, "gradio": 1, "via": [1, 3, 6, 7], "ak391": 1, "technic": [], "ye": 2, "pull": 5, "request": [], "98": [], "experiment": 3, "written": [4, 7], "c": [4, 6, 7], "stefanobazzi": [], "guitarboard": [], "project": 5, "exampl": [3, 4, 6, 7], "sounddevic": [], "librari": [3, 4, 5, 6, 7], "howev": [2, 6, 7], "coupl": [], "big": 2, "caveat": [], "talk": [], "context": 7, "languag": [], "garbag": [], "collect": [], "mean": [], "randomli": [], "paus": [], "interv": [], "clean": [], "unus": 7, "In": 7, "result": [6, 7], "random": [1, 7], "pop": [], "click": 6, "drop": 7, "veri": [], "difficult": [], "prevent": 7, "global": [3, 7], "lock": [3, 7], "also": [3, 4, 5, 6, 7], "potenti": 7, "unbound": 7, "switch": [], "thread": [3, 4, 6, 7], "oper": [6, 7], "system": [6, 7], "separ": [], "high": [6, 7], "prioriti": [], "block": [6, 7], "caus": [6, 7], "stutter": [], "access": [6, 7], "mutat": [], "applic": 4, "larg": 7, "buffer": [6, 7], "size": [2, 4, 6, 7], "soft": 6, "requir": [3, 4, 6, 7], "case": [3, 4, 6, 7], "network": [], "data": [2, 3, 6, 7], "offlin": [], "built": [2, 3, 6], "function": [2, 4, 5, 6, 7], "possibl": [2, 3, 6, 7], "vari": [2, 6], "manual": [2, 3], "tqdm": 2, "step": 2, "would": [2, 4, 6, 7], "give": [2, 6], "smoother": [2, 6], "transit": 2, "expens": [2, 6, 7], "speed": [2, 3, 4, 5, 6], "step_size_in_sampl": 2, "100": [2, 6, 7], "_n_": 2, "af": 2, "we": 2, "directli": [2, 6, 7], "save": [2, 6], "memori": [2, 3, 6, 7], "creat": [2, 3, 6, 7], "progress": 2, "bar": 2, "show": [2, 4, 6], "total": [2, 7], "pbar": 2, "rang": [2, 3, 6], "wet": [2, 6], "equal": [2, 3, 6, 7], "percentag": [2, 6], "track": [2, 6], "e": [2, 6, 7], "make": [2, 3, 7], "ramp": 2, "percentage_through_track": 2, "wet_level": [2, 6, 7], "updat": 2, "number": [2, 3, 5, 6, 7], "receiv": [2, 6, 7], "aren": 2, "cut": [2, 6], "off": [2, 6], "With": 2, "techniqu": [2, 6], "autom": 2, "usual": [2, 6, 7], "somewher": 2, "000": [2, 7], "2m": 2, "22m": 2, "44": [2, 6, 7], "1khz": [2, 6], "small": 2, "enough": [2, 7], "avoid": [2, 7], "hear": 2, "artifact": [2, 6], "slow": [2, 6], "down": [2, 6], "dramat": 2, "Not": [4, 6, 7], "yet": 2, "underli": [6, 7], "framework": [], "juce": [4, 5], "au": 7, "itself": [4, 6], "modifi": [], "either": [6, 7], "although": [6, 7], "effect": [3, 4, 6, 7], "popular": 3, "format": [3, 6, 7], "box": 3, "us": [3, 4, 5, 6, 7], "third": [3, 6], "parti": [3, 6], "plugin": [3, 5, 6, 7], "wa": [3, 6, 7], "": [1, 3, 4, 6, 7], "intellig": 3, "lab": 3, "enabl": [3, 6], "studio": 3, "qualiti": [3, 6, 7], "within": [3, 4, 6, 7], "tensorflow": [1, 3], "augment": 3, "improv": 3, "machin": [3, 4], "learn": [3, 4], "model": [1, 3, 6], "help": 3, "power": [3, 6], "ai": 3, "dj": 3, "content": [3, 7], "creation": 3, "digit": [3, 4, 6], "workstat": 3, "util": [3, 6], "aiff": [3, 7], "flac": [3, 7], "mp3": [3, 6, 7], "ogg": [3, 7], "platform": [3, 4, 6, 7], "depend": [3, 4, 6, 7], "addit": [3, 4, 6, 7], "aac": [3, 7], "ac3": [3, 7], "wma": [3, 7], "fly": [3, 7], "usag": [3, 6], "live": [3, 7], "basic": [3, 6, 7], "transform": [3, 6], "guitar": [3, 6], "style": 3, "clip": [3, 6], "loud": [3, 6], "dynam": [3, 6], "filter": [3, 6], "highpassfilt": [3, 6], "lowpassfilt": [3, 6], "spatial": 3, "lossi": [3, 6], "compress": [3, 6, 7], "gsmfullratecompressor": [3, 5, 6], "mp3compressor": [3, 5, 6], "reduct": [3, 6], "bitcrush": [3, 6], "linux": [3, 4, 6, 7], "strong": 3, "safeti": 3, "guarante": [3, 7], "releas": [3, 6, 7], "gil": [3, 7], "cpu": [3, 6], "core": [3, 5], "No": [3, 6], "need": [3, 4, 7], "multiprocess": 3, "onli": [3, 6, 7], "300x": 3, "faster": 3, "than": [3, 4, 6, 7], "pysox": 3, "singl": [3, 6], "2": [3, 6, 7], "5x": 3, "soxbind": 3, "icorv": 3, "4x": 3, "librosa": 3, "tf": 3, "pipelin": 3, "avail": [3, 4, 6, 7], "pypi": 3, "wheel": [3, 4], "pip": 3, "That": 3, "new": [3, 7], "follow": [3, 4, 5, 6, 7], "md": 3, "robust": 3, "guid": 3, "thoroughli": 3, "8": [3, 6], "9": [3, 6, 7], "11": 3, "heavili": 3, "product": 3, "manylinux": 3, "x86_64": 3, "intel": 3, "amd": 3, "aarch64": 3, "arm": 3, "appl": [3, 6], "silicon": 3, "rel": 3, "modern": 3, "glibc": 3, "27": 3, "both": [2, 3, 6, 7], "wide": [3, 6], "api": [3, 4], "quick": 3, "start": [3, 6, 7], "parallel": [3, 6], "chain": [3, 6, 7], "run": [3, 6, 7], "frequent": [3, 6], "question": 3, "doe": [3, 4, 6, 7], "over": [3, 6], "instrument": [3, 6], "accept": [3, 6, 7], "midi": [1, 3, 6], "design": [3, 6], "consider": 3, "licens": [3, 4], "cite": [], "repo": 3, "wrapper": [4, 6], "sourc": [4, 7], "cross": [4, 6], "develop": 4, "pybind11": 4, "bind": 4, "goal": [4, 7], "expos": [4, 6], "signal": [4, 6], "idiomat": 4, "wai": 4, "provid": [4, 6, 7], "raw": [4, 6, 7], "perform": [4, 7], "dsp": 4, "hide": 4, "complex": 4, "programm": 4, "intuit": 4, "varieti": 4, "reason": 4, "wider": 4, "compat": [4, 5, 6], "notabl": 4, "rare": [4, 6], "fewer": [4, 6], "simpler": 4, "remov": [4, 6], "copi": 4, "associ": 4, "resourc": [4, 6, 7], "option": [4, 6, 7], "might": 4, "meant": 4, "music": 4, "appropri": [4, 6], "vice": 4, "versa": 4, "stabil": 4, "environ": 4, "where": [1, 4, 6, 7], "implement": [4, 6, 7], "logic": 4, "portabl": 4, "safe": [4, 7], "constraint": 4, "should": [4, 6, 7], "consid": [4, 6, 7], "gplv3": [4, 5], "static": [4, 5, 6, 7], "link": 4, "vendor": 4, "git": 4, "submodul": 4, "binari": [4, 6, 7], "distribut": 4, "Will": [4, 7], "increas": [4, 6, 7], "amount": [4, 6, 7], "compil": [1, 4, 5], "runtim": 4, "cannot": [2, 4, 6, 7], "user": 4, "instal": [4, 6, 7], "softwar": [3, 4], "complic": 4, "simplic": 4, "packag": [4, 6], "To": [6, 7], "academ": [], "its": [6, 7], "entri": [], "zenodo": [], "imag": [], "org": [], "badg": [], "doi": [], "5281": [], "7817838": [], "svg": [], "target": [6, 7], "alt": [], "bibtex": [], "tex": [], "sobot_peter_2023_7817838": [], "author": [], "titl": [], "modul": [6, 7], "class": [2, 6, 7], "subclass": 6, "each": [6, 7], "appli": [1, 6], "name": [6, 7], "after": [6, 7], "concept": 6, "musician": 6, "variou": 6, "pedal": 6, "togeth": 6, "complet": [6, 7], "control": [6, 7], "main": 6, "my_pedalboard": 6, "treat": 6, "output_audio": 6, "input_audio": 6, "input_audio_sampler": 6, "zero": [6, 7], "composit": 6, "type": [6, 7], "none": [6, 7], "A": [6, 7], "seri": [6, 7], "act": 6, "come": [6, 7], "method": [6, 7], "alias": 6, "__call__": 6, "entir": [6, 7], "input_arrai": 6, "numpi": [6, 7], "ndarrai": [6, 7], "sample_r": [1, 6, 7], "float": [6, 7], "buffer_s": [6, 7], "8192": 6, "bool": [6, 7], "true": [6, 7], "dtype": [6, 7], "float32": [1, 6, 7], "alia": 6, "end": [6, 7], "insert": 6, "index": 6, "specifi": [6, 7], "properti": [6, 7], "is_effect": 6, "iff": [6, 7], "is_instru": 6, "32": [6, 7], "bit": [6, 7], "64": [3, 6], "point": [6, 7], "return": [6, 7], "arrai": [6, 7], "were": [6, 7], "expect": [6, 7], "insid": 6, "remain": [6, 7], "anoth": 6, "datatyp": [6, 7], "convert": [6, 7], "argument": [6, 7], "higher": 6, "flag": 6, "determin": [6, 7], "befor": [6, 7], "begin": [6, 7], "previou": 6, "my_plugin": 6, "invok": 6, "valu": [6, 7], "store": [6, 7], "g": 6, "line": [6, 7], "lfo": 6, "etc": [6, 7], "unchang": 6, "path_to_plugin_fil": 6, "str": [6, 7], "parameter_valu": 6, "dict": 6, "union": [6, 7], "plugin_nam": 6, "externalplugin": 6, "two": 6, "bundl": [5, 6], "dictionari": 6, "initi": [6, 7], "match": [6, 7], "report": 6, "normal": 6, "string": [6, 7], "identifi": 6, "These": 6, "multi": [6, 7], "except": [6, 7], "thrown": [6, 7], "vst3plugin": [2, 6], "audiounitplugin": [2, 6], "throw": [6, 7], "importerror": 6, "found": [6, 7], "runtimeerror": [6, 7], "audioprocessorparamet": 6, "parameter_nam": 6, "search_step": 6, "1000": 6, "differ": [6, 7], "implicit": 6, "my": 6, "cool": 6, "delay_time_m": 6, "foobar": 6, "attribut": [6, 7], "400": 6, "tri": 6, "guess": 6, "valid": 6, "instanti": 6, "alwai": [6, 7], "accur": [6, 7], "had": 6, "raw_valu": 6, "bound": [6, 7], "label": 6, "hz": [6, 7], "db": 6, "fail": 6, "midi_messag": 6, "durat": [1, 6, 7], "messag": [1, 2, 6], "sequenc": [], "must": [6, 7], "byte": [6, 7], "mido": [1, 6], "tupl": 6, "look": 6, "midi_byt": 6, "timestamp_in_second": 6, "worth": 6, "sent": 6, "timestamp": 6, "indic": [6, 7], "whose": 6, "greater": 6, "ignor": 6, "held": [], "decai": [], "non": [6, 7], "unavail": 6, "loadabl": 6, "plug": [6, 7], "Ins": 6, "compon": 6, "helper": [], "overload": [], "rais": [6, 7], "get_plugin_names_for_fil": 6, "filenam": [6, 7], "given": [6, 7], "scan": [6, 7], "present": [6, 7], "what": 6, "show_editor": 6, "ui": 6, "nativ": [6, 7], "keyboardinterrupt": [6, 7], "bit_depth": [6, 7], "reduc": 6, "depth": [6, 7], "lo": 6, "fi": 6, "vertic": 6, "resolut": 6, "uniqu": 6, "repres": [6, 7], "horizont": 6, "per": [6, 7], "quantiz": 6, "integ": [6, 7], "decim": 6, "onto": 6, "pedalboard_n": 6, "rate_hz": 6, "centre_delay_m": 6, "feedback": 6, "frequenc": 6, "respons": 6, "centr": 6, "get": 6, "classic": 6, "m": 6, "low": 6, "feeback": 6, "volum": 6, "flanger": 6, "lower": 6, "lot": 6, "vibrato": 6, "oscil": 6, "hertz": 6, "hard": [6, 7], "threshold": 6, "decibel": 6, "algorithm": [6, 7], "introduc": [6, 7], "nois": [1, 6], "gsmcompressor": 6, "impulse_response_filenam": 6, "suitabl": 6, "thing": 6, "simul": 6, "dry": 6, "drive_db": 6, "linear": [6, 7], "tanh": 6, "hyperbol": 6, "tangent": 6, "waveshap": 6, "harmon": 6, "pleas": 6, "produc": [6, 7], "roughli": 6, "equival": 6, "def": 6, "x": 6, "db_to_gain": 6, "windowedsinc": [6, 7], "degrad": 6, "gsm": 6, "full": 6, "emul": 6, "2g": 6, "cellular": 6, "phone": 6, "connect": [6, 7], "fix": 6, "8khz": 6, "codec": [6, 7], "decreas": [6, 7], "amplifi": 6, "attenu": 6, "think": 6, "highshelffilt": 6, "cutoff_frequency_hz": 6, "440": 6, "q": 6, "7071067690849304": 6, "shelf": 6, "variabl": [6, 7], "abov": [6, 7], "cutoff": 6, "boost": 6, "first": [6, 7], "order": 6, "roll": 6, "6db": 6, "octav": 6, "3db": 6, "frac": 6, "sqrt": 6, "express": 6, "factor": 6, "further": [6, 7], "iirfilt": 6, "abstract": 6, "kind": 6, "infinit": 6, "impuls": 6, "iir": 6, "lowshelffilt": 6, "peakfilt": 6, "invert": 6, "flip": 6, "polar": 6, "audibl": 6, "own": [5, 6], "take": 6, "mathemat": 6, "ident": [6, 7], "cancel": 6, "origin": [6, 7], "lpf12": 6, "200": 6, "reson": 6, "drive": 6, "base": [6, 7], "moog": 6, "synthes": 6, "ladder": 6, "invent": 6, "dr": 6, "bob": 6, "1968": 6, "below": [6, 7], "side": [6, 7], "peak": 6, "architectur": 6, "bpf12": 6, "band": [5, 6], "lpf24": 6, "24": 6, "hpf24": 6, "4": [2, 6], "bpf24": 6, "simpl": 6, "standard": 6, "featur": 6, "clipper": 6, "707x": 6, "vbr_qualiti": 6, "lame": [5, 6, 7], "encod": [6, 7], "current": [6, 7], "vbr": 6, "better": 6, "32khz": 6, "48khz": 6, "unsupport": [6, 7], "noiseg": 6, "gate": 6, "attack": 6, "expand": 6, "notch": 6, "centre_frequency_hz": 6, "1300": 6, "stage": 6, "sweep": 6, "magnitud": [6, 7], "affect": 6, "chri": 6, "cannam": 6, "wonder": 6, "rubber": [5, 6], "stretch": 6, "gener": [5, 6], "plugincontain": 6, "intend": 6, "direct": [6, 7], "target_sample_r": [6, 7], "8000": 6, "downsampl": 6, "upsampl": 6, "zeroorderhold": 6, "lowest": 6, "fastest": [6, 7], "slightli": 6, "less": [6, 7], "noisi": 6, "simplest": 6, "catmullrom": 6, "moder": 6, "good": 6, "fast": 6, "lagrang": 6, "highest": 6, "slowest": [6, 7], "still": [6, 7], "mere": 6, "damp": 6, "33": 6, "dry_level": 6, "width": 6, "freeze_mod": 6, "stereo": [6, 7], "tune": 6, "freeverb": 6, "ccrma": 6, "stanford": 6, "edu": 6, "jo": 6, "pasp": 6, "steinberg": [5, 6], "gmbh": [5, 6], "build": 6, "arg0": [6, 7], "load_preset": 6, "preset_file_path": 6, "preset": 6, "vstpreset": 6, "decod": [6, 7], "handl": 7, "behind": 7, "scene": 7, "my_filenam": 7, "441_000": 7, "necessari": 7, "accomplish": 7, "readableaudiofil": 7, "find": [6, 7], "yourself": 7, "writeableaudiofil": 7, "resampledreadableaudiofil": 7, "probabl": 7, "cover": 7, "file_lik": 7, "binaryio": 7, "liter": 7, "16": 7, "readabl": 7, "writeabl": 7, "default": [6, 7], "unlik": 7, "typic": 7, "trail": 7, "b": 7, "redund": 7, "exist": 7, "seekabl": 7, "stringio": 7, "my_fil": 7, "first_ten_second": 7, "ogg_buff": 7, "bytesio": 7, "get_audio_buff": 7, "22_050": 7, "white_nois": 7, "np": [1, 7], "rand": [1, 7], "wav_buff": 7, "getvalu": 7, "someth": [6, 7], "160": 7, "kilobit": 7, "re": 7, "four": 7, "1024": 7, "constructor": 7, "actual": 7, "those": [6, 7], "512": 7, "allow_feedback": 7, "devic": 7, "microphon": 7, "headphon": 7, "manag": 7, "delet": 7, "del": 7, "synchron": 7, "ctrl": [6, 7], "under": [5, 7], "hood": 7, "concern": [], "never": 7, "left": 7, "dangl": 7, "background": [6, 7], "__enter__": 7, "nasti": 7, "longer": 7, "reachabl": 7, "scope": 7, "continu": 7, "plai": 7, "forev": 7, "won": 7, "exit": 7, "easier": 7, "cleanup": 7, "v0": [6, 7], "immedi": 7, "send": 7, "__exit__": 7, "arg1": 7, "arg2": 7, "onc": [6, 7], "otherwis": 7, "wrap": 7, "vorbi": 7, "3g2": 7, "3gp": 7, "adt": 7, "aif": 7, "aifc": 7, "amr": 7, "bwf": 7, "caf": 7, "ec3": 7, "latm": 7, "loa": 7, "m4a": 7, "m4b": 7, "m4r": 7, "mov": 7, "mp1": 7, "mp2": 7, "mp4": 7, "mpa": 7, "mpeg": 7, "qt": 7, "sd2": 7, "snd": 7, "w64": 7, "xhe": 7, "get_supported_read_format": 7, "extens": 7, "certain": 7, "want": [1, 7], "too": 7, "num_fram": 7, "channel": 7, "posit": 7, "decept": 7, "hour": 7, "long": 7, "hand": 7, "megabyt": 7, "decompress": 7, "nearli": 7, "gigabyt": 7, "debug": 7, "problem": 7, "dimension": 7, "length": [6, 7], "fill": 7, "exact_duration_known": 7, "situat": [6, 7], "occur": 7, "minimum": 7, "0f": 7, "maximum": 7, "read_raw": 7, "int8": 7, "int16": 7, "int32": 7, "constant": 7, "seek": 7, "locat": 7, "futur": 7, "pointer": 7, "usabl": 7, "divid": 7, "overestim": 7, "detail": [2, 7], "exact": 7, "estim": 7, "bitrat": 7, "ever": 7, "file_dtyp": 7, "regardless": 7, "441": 7, "discrep": 7, "due": 7, "fact": 7, "header": [6, 7], "xing": 7, "info": 7, "finish": 7, "forc": 7, "pars": 7, "correct": 7, "60": [1, 6, 7], "assert": [6, 7], "num_sampl": 7, "behaviour": 7, "later": 7, "prior": 7, "version": [2, 6, 7], "lack": 7, "audio_fil": 7, "resampling_qu": 7, "22050": 7, "fraction": 7, "streamresampl": 7, "obtain": 7, "benefit": 7, "respect": 7, "push": 7, "optim": 7, "retain": 7, "accuraci": 7, "22": 7, "050": 7, "source_sample_r": 7, "flush": 7, "input_lat": 7, "suppli": 7, "get_supported_write_format": 7, "filename_or_file_lik": 7, "assum": 7, "level": 7, "numer": 7, "128": 7, "256": 7, "advanc": 7, "v2": 7, "best": 7, "happen": [6, 7], "reliabl": 7, "float64": [6, 7], "typeerror": 7, "far": 7, "increment": 7, "kbp": 7, "v9": 7, "arg": [], "kwarg": [], "self": [], "kwd": [], "extern": 6, "part": [1, 6, 7], "conveni": [1, 6, 7], "note_on": [1, 6], "note_off": [1, 6], "magical8bitplug2": 1, "As": 2, "amd64": 3, "x86": 3, "contribut": [], "copyright": 5, "2021": 5, "2023": [], "ab": 5, "gnu": 5, "public": 5, "v3": 5, "carri": 5, "dual": 5, "commerci": 5, "sdk": 5, "media": 5, "technologi": 5, "gplv2": 5, "newer": 5, "libmp3lam": 5, "lgplv2": 5, "upgrad": 5, "inclus": 5, "permit": 5, "libgsm": 5, "isc": 5, "regist": 5, "trademark": 5, "e4m3t": [], "precis": 6, "expon": [], "e4m3": [], "from_char": [], "mantissa": [], "sign": [], "setview": [], "unord": [], "map": 1, "search": [], "member": [], "euclidean": [], "cosin": [], "innerproduct": [], "storagedatatyp": [], "vector": [], "float8": [], "448": [], "inspir": [], "paper": [], "fp8": [], "deep": [], "micikeviciu": [], "et": [], "al": [], "arxiv": [], "2209": [], "05433": [], "musllinux": 3, "initialization_timeout": 6, "spend": 6, "asynchron": 6, "startup": 6, "larger": 6, "properli": 6, "01": 7, "00": 7, "time_stretch": [5, 6], "stretch_factor": 6, "pitch_shift_in_semiton": 6, "shorten": 6, "doubl": 6, "_speed_": [], "halv": 6, "_length_": [], "fo": [], "dure": [6, 7], "independ": 6, "worri": 6, "thei": 6, "transient_mod": 6, "crisp": 6, "transient_detector": 6, "compound": 6, "retain_phase_continu": 6, "use_long_fft_window": 6, "use_time_domain_smooth": 6, "preserve_form": 6, "behavior": [6, 7], "stretcher": 6, "transient": 6, "percuss": 6, "smooth": 6, "phase": 6, "adjac": 6, "bin": 6, "kept": 6, "similar": 6, "softer": 6, "phasier": 6, "fourier": 6, "clariti": 6, "crisper": 6, "sharp": 6, "substanti": 6, "profil": 6, "formant": 6, "voic": [3, 6], "grain": 6, "high_qual": 6, "translat": 3, "close_ev": 6, "event": 6, "editor": 6, "programmat": 6, "button": 6, "keyboard": 6, "shortcut": 6, "close_window_ev": 6, "other_thread": 6, "should_close_window_ev": [], "should_close_window": 6, "sr": [1, 7], "48000": 1, "welcom": [], "whatev": 1, "here": 1, "dataset": 1, "train": 1, "somehow": 1, "from_tensor_slic": 1, "lambda": 1, "numpy_funct": 1, "dummi": 1, "ml": 1, "kera": 1, "sequenti": 1, "layer": 1, "inputlay": 1, "input_shap": 1, "dens": 1, "loss": 1, "mse": 1, "fit": 1, "batch": 1, "epoch": 1, "hang": 6, "incorrect": 6, "outright": 6, "incompat": 6, "externalpluginreloadtyp": [], "unknown": [], "reinstanti": [], "clearsaudioonreset": [], "correctli": [], "persistsaudioonreset": [], "memoryview": 7, "py": [], "effici": 7, "consum": 7, "arbitrari": 7, "recommend": 7, "buf": 7, "mp3_buffer": 7, "flac_buff": 7, "categori": 6, "fall": 6, "descriptive_nam": 6, "descript": 6, "field": 6, "altern": 6, "has_shared_contain": 6, "again": 6, "manufacturer_nam": 6, "manufactur": 6, "auv3": 6, "appex": 6, "2024": 5, "raw_stat": 6, "plistlib": 6, "invalid": 6, "xml": 6, "prefix": 6, "suffix": 6, "null": 6, "squar": [], "abl": 7, "infer": 7, "dimens": 7, "correspond": 7, "layout": 7, "previous": [], "cach": 7, "writableaudiofil": 7, "recent": 7, "disambigu": 7, "But": 7, "And": 7, "hint": 7, "noth": 7, "anyth": 7, "slower": 6, "024": 6, "23": 6, "millisecond": 6, "fftw": 5, "11025hz": 6, "12khz": 6, "16khz": 6, "22050hz": 6, "24khz": 6, "my_audio_fil": 7, "Or": 7, "loop": 7, "meth": [], "dropped_input_frame_count": 7, "sinc": 7, "last": 7, "record": 7, "often": 7, "ignore_dropped_input": 7, "unaffect": 7, "doesn": 7, "quickli": 7, "lost": 7, "deault": [], "disabl": 7, "retriev": 7, "entireti": [], "num_input_channel": 7, "num_output_channel": 7, "output_devic": 7, "default_input_device_nam": 7, "default_output_device_nam": 7, "buffered_input_sample_count": 7, "rapidli": 7, "hardwar": 7}, "objects": {"": [[6, 0, 0, "-", "pedalboard"]], "pedalboard": [[6, 1, 1, "", "AudioProcessorParameter"], [6, 1, 1, "", "AudioUnitPlugin"], [6, 1, 1, "", "Bitcrush"], [6, 1, 1, "", "Chain"], [6, 1, 1, "", "Chorus"], [6, 1, 1, "", "Clipping"], [6, 1, 1, "", "Compressor"], [6, 1, 1, "", "Convolution"], [6, 1, 1, "", "Delay"], [6, 1, 1, "", "Distortion"], [6, 1, 1, "", "ExternalPlugin"], [6, 1, 1, "", "GSMFullRateCompressor"], [6, 1, 1, "", "Gain"], [6, 1, 1, "", "HighShelfFilter"], [6, 1, 1, "", "HighpassFilter"], [6, 1, 1, "", "IIRFilter"], [6, 1, 1, "", "Invert"], [6, 1, 1, "", "LadderFilter"], [6, 1, 1, "", "Limiter"], [6, 1, 1, "", "LowShelfFilter"], [6, 1, 1, "", "LowpassFilter"], [6, 1, 1, "", "MP3Compressor"], [6, 1, 1, "", "Mix"], [6, 1, 1, "", "NoiseGate"], [6, 1, 1, "", "PeakFilter"], [6, 1, 1, "", "Pedalboard"], [6, 1, 1, "", "Phaser"], [6, 1, 1, "", "PitchShift"], [6, 1, 1, "", "Plugin"], [6, 1, 1, "", "PluginContainer"], [6, 1, 1, "", "Resample"], [6, 1, 1, "", "Reverb"], [6, 1, 1, "", "VST3Plugin"], [7, 0, 0, "-", "io"], [6, 5, 1, "", "load_plugin"], [6, 5, 1, "", "time_stretch"]], "pedalboard.AudioProcessorParameter": [[6, 2, 1, "", "label"], [6, 2, 1, "", "units"]], "pedalboard.AudioUnitPlugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "category"], [6, 2, 1, "", "descriptive_name"], [6, 3, 1, "", "get_plugin_names_for_file"], [6, 2, 1, "", "has_shared_container"], [6, 2, 1, "", "identifier"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 2, 1, "", "manufacturer_name"], [6, 2, 1, "", "name"], [6, 3, 1, "", "process"], [6, 2, 1, "", "raw_state"], [6, 3, 1, "", "reset"], [6, 3, 1, "", "show_editor"], [6, 2, 1, "", "version"]], "pedalboard.Bitcrush": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "bit_depth"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Chain": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.Chorus": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 2, 1, "", "rate_hz"], [6, 3, 1, "", "reset"]], "pedalboard.Clipping": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Compressor": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Convolution": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Delay": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Distortion": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.ExternalPlugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.GSMFullRateCompressor": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Gain": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.HighShelfFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.HighpassFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.IIRFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Invert": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LadderFilter": [[6, 1, 1, "", "Mode"], [6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LadderFilter.Mode": [[6, 4, 1, "", "BPF12"], [6, 4, 1, "", "BPF24"], [6, 4, 1, "", "HPF12"], [6, 4, 1, "", "HPF24"], [6, 4, 1, "", "LPF12"], [6, 4, 1, "", "LPF24"]], "pedalboard.Limiter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LowShelfFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.LowpassFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.MP3Compressor": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Mix": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.NoiseGate": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.PeakFilter": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Pedalboard": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.Phaser": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.PitchShift": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.Plugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.PluginContainer": [[6, 3, 1, "", "__call__"], [6, 3, 1, "", "append"], [6, 3, 1, "", "insert"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "remove"], [6, 3, 1, "", "reset"]], "pedalboard.Resample": [[6, 1, 1, "", "Quality"], [6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 2, 1, "", "quality"], [6, 3, 1, "", "reset"], [6, 2, 1, "", "target_sample_rate"]], "pedalboard.Resample.Quality": [[6, 4, 1, "", "CatmullRom"], [6, 4, 1, "", "Lagrange"], [6, 4, 1, "", "Linear"], [6, 4, 1, "", "WindowedSinc"], [6, 4, 1, "", "ZeroOrderHold"]], "pedalboard.Reverb": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "process"], [6, 3, 1, "", "reset"]], "pedalboard.VST3Plugin": [[6, 3, 1, "", "__call__"], [6, 2, 1, "", "category"], [6, 2, 1, "", "descriptive_name"], [6, 3, 1, "", "get_plugin_names_for_file"], [6, 2, 1, "", "has_shared_container"], [6, 2, 1, "", "identifier"], [6, 2, 1, "", "is_effect"], [6, 2, 1, "", "is_instrument"], [6, 3, 1, "", "load_preset"], [6, 2, 1, "", "manufacturer_name"], [6, 2, 1, "", "name"], [6, 3, 1, "", "process"], [6, 2, 1, "", "raw_state"], [6, 3, 1, "", "reset"], [6, 3, 1, "", "show_editor"], [6, 2, 1, "", "version"]], "pedalboard.io": [[7, 1, 1, "", "AudioFile"], [7, 1, 1, "", "AudioStream"], [7, 1, 1, "", "ReadableAudioFile"], [7, 1, 1, "", "ResampledReadableAudioFile"], [7, 1, 1, "", "StreamResampler"], [7, 1, 1, "", "WriteableAudioFile"]], "pedalboard.io.AudioFile": [[7, 3, 1, "", "encode"]], "pedalboard.io.AudioStream": [[7, 3, 1, "", "__enter__"], [7, 3, 1, "", "__exit__"], [7, 2, 1, "", "buffer_size"], [7, 2, 1, "", "buffered_input_sample_count"], [7, 3, 1, "", "close"], [7, 2, 1, "", "dropped_input_frame_count"], [7, 2, 1, "", "ignore_dropped_input"], [7, 2, 1, "", "num_input_channels"], [7, 2, 1, "", "num_output_channels"], [7, 3, 1, "", "play"], [7, 2, 1, "", "plugins"], [7, 3, 1, "", "read"], [7, 3, 1, "", "run"], [7, 2, 1, "", "running"], [7, 2, 1, "", "sample_rate"], [7, 3, 1, "", "write"]], "pedalboard.io.ReadableAudioFile": [[7, 3, 1, "", "__enter__"], [7, 3, 1, "", "__exit__"], [7, 3, 1, "", "close"], [7, 2, 1, "", "closed"], [7, 2, 1, "", "duration"], [7, 2, 1, "", "exact_duration_known"], [7, 2, 1, "", "file_dtype"], [7, 2, 1, "", "frames"], [7, 2, 1, "", "name"], [7, 2, 1, "", "num_channels"], [7, 3, 1, "", "read"], [7, 3, 1, "", "read_raw"], [7, 3, 1, "", "resampled_to"], [7, 2, 1, "", "samplerate"], [7, 3, 1, "", "seek"], [7, 3, 1, "", "seekable"], [7, 3, 1, "", "tell"]], "pedalboard.io.ResampledReadableAudioFile": [[7, 3, 1, "", "__enter__"], [7, 3, 1, "", "__exit__"], [7, 3, 1, "", "close"], [7, 2, 1, "", "closed"], [7, 2, 1, "", "duration"], [7, 2, 1, "", "exact_duration_known"], [7, 2, 1, "", "file_dtype"], [7, 2, 1, "", "frames"], [7, 2, 1, "", "name"], [7, 2, 1, "", "num_channels"], [7, 3, 1, "", "read"], [7, 2, 1, "", "resampling_quality"], [7, 2, 1, "", "samplerate"], [7, 3, 1, "", "seek"], [7, 3, 1, "", "seekable"], [7, 3, 1, "", "tell"]], "pedalboard.io.StreamResampler": [[7, 2, 1, "", "input_latency"], [7, 2, 1, "", "num_channels"], [7, 3, 1, "", "process"], [7, 2, 1, "", "quality"], [7, 3, 1, "", "reset"], [7, 2, 1, "", "source_sample_rate"], [7, 2, 1, "", "target_sample_rate"]], "pedalboard.io.WriteableAudioFile": [[7, 3, 1, "", "close"], [7, 2, 1, "", "closed"], [7, 2, 1, "", "file_dtype"], [7, 3, 1, "", "flush"], [7, 2, 1, "", "frames"], [7, 2, 1, "", "num_channels"], [7, 2, 1, "", "quality"], [7, 2, 1, "", "samplerate"], [7, 3, 1, "", "tell"], [7, 3, 1, "", "write"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:property", "3": "py:method", "4": "py:attribute", "5": "py:function"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "property", "Python property"], "3": ["py", "method", "Python method"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "function", "Python function"]}, "titleterms": {"plugin": [0, 1, 2, 4], "compat": [0, 3], "exampl": 1, "quick": 1, "start": 1, "make": 1, "guitar": 1, "style": 1, "pedalboard": [1, 2, 4, 6, 7], "us": [1, 2], "vst3": 1, "audio": [1, 2], "unit": 1, "creat": 1, "parallel": 1, "effect": [1, 2], "chain": 1, "run": 1, "live": [1, 2], "frequent": 2, "ask": 2, "question": 2, "can": 2, "real": 2, "time": 2, "doe": 2, "support": 2, "chang": 2, "": 2, "paramet": 2, "over": 2, "vst": 2, "instrument": [1, 2], "instead": 2, "accept": 2, "midi": 2, "featur": 3, "instal": 3, "refer": 3, "document": 3, "intern": 4, "ad": 4, "new": 4, "built": 4, "design": 4, "consider": 4, "licens": 5, "cite": [], "The": [6, 7], "api": [6, 7], "io": 7, "process": [], "other": [], "argument": [], "contribut": [], "voyag": [], "tf": 1, "data": 1, "pipelin": 1}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.intersphinx": 1, "sphinx": 57}, "alltitles": {"Plugin Compatibility": [[0, "plugin-compatibility"]], "Examples": [[1, "examples"]], "Quick start": [[1, "quick-start"]], "Making a guitar-style pedalboard": [[1, "making-a-guitar-style-pedalboard"]], "Using VST3\u00ae or Audio Unit instrument and effect plugins": [[1, "using-vst3-or-audio-unit-instrument-and-effect-plugins"]], "Creating parallel effects chains": [[1, "creating-parallel-effects-chains"]], "Running Pedalboard on Live Audio": [[1, "running-pedalboard-on-live-audio"]], "Using Pedalboard in tf.data Pipelines": [[1, "using-pedalboard-in-tf-data-pipelines"]], "Frequently Asked Questions": [[2, "frequently-asked-questions"]], "Can Pedalboard be used with live (real-time) audio?": [[2, "can-pedalboard-be-used-with-live-real-time-audio"]], "Does Pedalboard support changing a plugin\u2019s parameters over time?": [[2, "does-pedalboard-support-changing-a-plugin-s-parameters-over-time"]], "Can Pedalboard be used with VST instruments, instead of effects?": [[2, "can-pedalboard-be-used-with-vst-instruments-instead-of-effects"]], "Can Pedalboard plugins accept MIDI?": [[2, "can-pedalboard-plugins-accept-midi"]], "Features": [[3, "features"]], "Installation": [[3, "installation"]], "Compatibility": [[3, "compatibility"]], "Reference": [[3, "reference"]], "Documentation": [[3, "documentation"]], "Pedalboard Internals": [[4, "pedalboard-internals"]], "Adding new built-in Pedalboard plugins": [[4, "adding-new-built-in-pedalboard-plugins"]], "Design considerations": [[4, "design-considerations"]], "License": [[5, "license"]], "The pedalboard API": [[6, "the-pedalboard-api"]], "The pedalboard.io API": [[7, "the-pedalboard-io-api"]]}, "indexentries": {"audioprocessorparameter (class in pedalboard)": [[6, "pedalboard.AudioProcessorParameter"]], "audiounitplugin (class in pedalboard)": [[6, "pedalboard.AudioUnitPlugin"]], "bpf12 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.BPF12"]], "bpf24 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.BPF24"]], "bitcrush (class in pedalboard)": [[6, "pedalboard.Bitcrush"]], "catmullrom (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.CatmullRom"]], "chain (class in pedalboard)": [[6, "pedalboard.Chain"]], "chorus (class in pedalboard)": [[6, "pedalboard.Chorus"]], "clipping (class in pedalboard)": [[6, "pedalboard.Clipping"]], "compressor (class in pedalboard)": [[6, "pedalboard.Compressor"]], "convolution (class in pedalboard)": [[6, "pedalboard.Convolution"]], "delay (class in pedalboard)": [[6, "pedalboard.Delay"]], "distortion (class in pedalboard)": [[6, "pedalboard.Distortion"]], "externalplugin (class in pedalboard)": [[6, "pedalboard.ExternalPlugin"]], "gsmfullratecompressor (class in pedalboard)": [[6, "pedalboard.GSMFullRateCompressor"]], "gain (class in pedalboard)": [[6, "pedalboard.Gain"]], "hpf12 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.HPF12"]], "hpf24 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.HPF24"]], "highshelffilter (class in pedalboard)": [[6, "pedalboard.HighShelfFilter"]], "highpassfilter (class in pedalboard)": [[6, "pedalboard.HighpassFilter"]], "iirfilter (class in pedalboard)": [[6, "pedalboard.IIRFilter"]], "invert (class in pedalboard)": [[6, "pedalboard.Invert"]], "lpf12 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.LPF12"]], "lpf24 (pedalboard.ladderfilter.mode attribute)": [[6, "pedalboard.LadderFilter.Mode.LPF24"]], "ladderfilter (class in pedalboard)": [[6, "pedalboard.LadderFilter"]], "ladderfilter.mode (class in pedalboard)": [[6, "pedalboard.LadderFilter.Mode"]], "lagrange (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.Lagrange"]], "limiter (class in pedalboard)": [[6, "pedalboard.Limiter"]], "linear (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.Linear"]], "lowshelffilter (class in pedalboard)": [[6, "pedalboard.LowShelfFilter"]], "lowpassfilter (class in pedalboard)": [[6, "pedalboard.LowpassFilter"]], "mp3compressor (class in pedalboard)": [[6, "pedalboard.MP3Compressor"]], "mix (class in pedalboard)": [[6, "pedalboard.Mix"]], "noisegate (class in pedalboard)": [[6, "pedalboard.NoiseGate"]], "peakfilter (class in pedalboard)": [[6, "pedalboard.PeakFilter"]], "pedalboard (class in pedalboard)": [[6, "pedalboard.Pedalboard"]], "phaser (class in pedalboard)": [[6, "pedalboard.Phaser"]], "pitchshift (class in pedalboard)": [[6, "pedalboard.PitchShift"]], "plugin (class in pedalboard)": [[6, "pedalboard.Plugin"]], "plugincontainer (class in pedalboard)": [[6, "pedalboard.PluginContainer"]], "resample (class in pedalboard)": [[6, "pedalboard.Resample"]], "resample.quality (class in pedalboard)": [[6, "pedalboard.Resample.Quality"]], "reverb (class in pedalboard)": [[6, "pedalboard.Reverb"]], "vst3plugin (class in pedalboard)": [[6, "pedalboard.VST3Plugin"]], "windowedsinc (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.WindowedSinc"]], "zeroorderhold (pedalboard.resample.quality attribute)": [[6, "pedalboard.Resample.Quality.ZeroOrderHold"]], "__call__() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.__call__"]], "__call__() (pedalboard.bitcrush method)": [[6, "pedalboard.Bitcrush.__call__"]], "__call__() (pedalboard.chain method)": [[6, "pedalboard.Chain.__call__"]], "__call__() (pedalboard.chorus method)": [[6, "pedalboard.Chorus.__call__"]], "__call__() (pedalboard.clipping method)": [[6, "pedalboard.Clipping.__call__"]], "__call__() (pedalboard.compressor method)": [[6, "pedalboard.Compressor.__call__"]], "__call__() (pedalboard.convolution method)": [[6, "pedalboard.Convolution.__call__"]], "__call__() (pedalboard.delay method)": [[6, "pedalboard.Delay.__call__"]], "__call__() (pedalboard.distortion method)": [[6, "pedalboard.Distortion.__call__"]], "__call__() (pedalboard.externalplugin method)": [[6, "pedalboard.ExternalPlugin.__call__"]], "__call__() (pedalboard.gsmfullratecompressor method)": [[6, "pedalboard.GSMFullRateCompressor.__call__"]], "__call__() (pedalboard.gain method)": [[6, "pedalboard.Gain.__call__"]], "__call__() (pedalboard.highshelffilter method)": [[6, "pedalboard.HighShelfFilter.__call__"]], "__call__() (pedalboard.highpassfilter method)": [[6, "pedalboard.HighpassFilter.__call__"]], "__call__() (pedalboard.iirfilter method)": [[6, "pedalboard.IIRFilter.__call__"]], "__call__() (pedalboard.invert method)": [[6, "pedalboard.Invert.__call__"]], "__call__() (pedalboard.ladderfilter method)": [[6, "pedalboard.LadderFilter.__call__"]], "__call__() (pedalboard.limiter method)": [[6, "pedalboard.Limiter.__call__"]], "__call__() (pedalboard.lowshelffilter method)": [[6, "pedalboard.LowShelfFilter.__call__"]], "__call__() (pedalboard.lowpassfilter method)": [[6, "pedalboard.LowpassFilter.__call__"]], "__call__() (pedalboard.mp3compressor method)": [[6, "pedalboard.MP3Compressor.__call__"]], "__call__() (pedalboard.mix method)": [[6, "pedalboard.Mix.__call__"]], "__call__() (pedalboard.noisegate method)": [[6, "pedalboard.NoiseGate.__call__"]], "__call__() (pedalboard.peakfilter method)": [[6, "pedalboard.PeakFilter.__call__"]], "__call__() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.__call__"]], "__call__() (pedalboard.phaser method)": [[6, "pedalboard.Phaser.__call__"]], "__call__() (pedalboard.pitchshift method)": [[6, "pedalboard.PitchShift.__call__"]], "__call__() (pedalboard.plugin method)": [[6, "pedalboard.Plugin.__call__"]], "__call__() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.__call__"]], "__call__() (pedalboard.resample method)": [[6, "pedalboard.Resample.__call__"]], "__call__() (pedalboard.reverb method)": [[6, "pedalboard.Reverb.__call__"]], "__call__() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.__call__"]], "append() (pedalboard.chain method)": [[6, "pedalboard.Chain.append"]], "append() (pedalboard.mix method)": [[6, "pedalboard.Mix.append"]], "append() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.append"]], "append() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.append"]], "bit_depth (pedalboard.bitcrush property)": [[6, "pedalboard.Bitcrush.bit_depth"]], "category (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.category"]], "category (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.category"]], "descriptive_name (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.descriptive_name"]], "descriptive_name (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.descriptive_name"]], "get_plugin_names_for_file() (pedalboard.audiounitplugin static method)": [[6, "pedalboard.AudioUnitPlugin.get_plugin_names_for_file"]], "get_plugin_names_for_file() (pedalboard.vst3plugin static method)": [[6, "pedalboard.VST3Plugin.get_plugin_names_for_file"]], "has_shared_container (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.has_shared_container"]], "has_shared_container (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.has_shared_container"]], "identifier (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.identifier"]], "identifier (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.identifier"]], "insert() (pedalboard.chain method)": [[6, "pedalboard.Chain.insert"]], "insert() (pedalboard.mix method)": [[6, "pedalboard.Mix.insert"]], "insert() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.insert"]], "insert() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.insert"]], "is_effect (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.is_effect"]], "is_effect (pedalboard.bitcrush property)": [[6, "pedalboard.Bitcrush.is_effect"]], "is_effect (pedalboard.chain property)": [[6, "pedalboard.Chain.is_effect"]], "is_effect (pedalboard.chorus property)": [[6, "pedalboard.Chorus.is_effect"]], "is_effect (pedalboard.clipping property)": [[6, "pedalboard.Clipping.is_effect"]], "is_effect (pedalboard.compressor property)": [[6, "pedalboard.Compressor.is_effect"]], "is_effect (pedalboard.convolution property)": [[6, "pedalboard.Convolution.is_effect"]], "is_effect (pedalboard.delay property)": [[6, "pedalboard.Delay.is_effect"]], "is_effect (pedalboard.distortion property)": [[6, "pedalboard.Distortion.is_effect"]], "is_effect (pedalboard.externalplugin property)": [[6, "pedalboard.ExternalPlugin.is_effect"]], "is_effect (pedalboard.gsmfullratecompressor property)": [[6, "pedalboard.GSMFullRateCompressor.is_effect"]], "is_effect (pedalboard.gain property)": [[6, "pedalboard.Gain.is_effect"]], "is_effect (pedalboard.highshelffilter property)": [[6, "pedalboard.HighShelfFilter.is_effect"]], "is_effect (pedalboard.highpassfilter property)": [[6, "pedalboard.HighpassFilter.is_effect"]], "is_effect (pedalboard.iirfilter property)": [[6, "pedalboard.IIRFilter.is_effect"]], "is_effect (pedalboard.invert property)": [[6, "pedalboard.Invert.is_effect"]], "is_effect (pedalboard.ladderfilter property)": [[6, "pedalboard.LadderFilter.is_effect"]], "is_effect (pedalboard.limiter property)": [[6, "pedalboard.Limiter.is_effect"]], "is_effect (pedalboard.lowshelffilter property)": [[6, "pedalboard.LowShelfFilter.is_effect"]], "is_effect (pedalboard.lowpassfilter property)": [[6, "pedalboard.LowpassFilter.is_effect"]], "is_effect (pedalboard.mp3compressor property)": [[6, "pedalboard.MP3Compressor.is_effect"]], "is_effect (pedalboard.mix property)": [[6, "pedalboard.Mix.is_effect"]], "is_effect (pedalboard.noisegate property)": [[6, "pedalboard.NoiseGate.is_effect"]], "is_effect (pedalboard.peakfilter property)": [[6, "pedalboard.PeakFilter.is_effect"]], "is_effect (pedalboard.pedalboard property)": [[6, "pedalboard.Pedalboard.is_effect"]], "is_effect (pedalboard.phaser property)": [[6, "pedalboard.Phaser.is_effect"]], "is_effect (pedalboard.pitchshift property)": [[6, "pedalboard.PitchShift.is_effect"]], "is_effect (pedalboard.plugin property)": [[6, "pedalboard.Plugin.is_effect"]], "is_effect (pedalboard.plugincontainer property)": [[6, "pedalboard.PluginContainer.is_effect"]], "is_effect (pedalboard.resample property)": [[6, "pedalboard.Resample.is_effect"]], "is_effect (pedalboard.reverb property)": [[6, "pedalboard.Reverb.is_effect"]], "is_effect (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.is_effect"]], "is_instrument (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.is_instrument"]], "is_instrument (pedalboard.bitcrush property)": [[6, "pedalboard.Bitcrush.is_instrument"]], "is_instrument (pedalboard.chain property)": [[6, "pedalboard.Chain.is_instrument"]], "is_instrument (pedalboard.chorus property)": [[6, "pedalboard.Chorus.is_instrument"]], "is_instrument (pedalboard.clipping property)": [[6, "pedalboard.Clipping.is_instrument"]], "is_instrument (pedalboard.compressor property)": [[6, "pedalboard.Compressor.is_instrument"]], "is_instrument (pedalboard.convolution property)": [[6, "pedalboard.Convolution.is_instrument"]], "is_instrument (pedalboard.delay property)": [[6, "pedalboard.Delay.is_instrument"]], "is_instrument (pedalboard.distortion property)": [[6, "pedalboard.Distortion.is_instrument"]], "is_instrument (pedalboard.externalplugin property)": [[6, "pedalboard.ExternalPlugin.is_instrument"]], "is_instrument (pedalboard.gsmfullratecompressor property)": [[6, "pedalboard.GSMFullRateCompressor.is_instrument"]], "is_instrument (pedalboard.gain property)": [[6, "pedalboard.Gain.is_instrument"]], "is_instrument (pedalboard.highshelffilter property)": [[6, "pedalboard.HighShelfFilter.is_instrument"]], "is_instrument (pedalboard.highpassfilter property)": [[6, "pedalboard.HighpassFilter.is_instrument"]], "is_instrument (pedalboard.iirfilter property)": [[6, "pedalboard.IIRFilter.is_instrument"]], "is_instrument (pedalboard.invert property)": [[6, "pedalboard.Invert.is_instrument"]], "is_instrument (pedalboard.ladderfilter property)": [[6, "pedalboard.LadderFilter.is_instrument"]], "is_instrument (pedalboard.limiter property)": [[6, "pedalboard.Limiter.is_instrument"]], "is_instrument (pedalboard.lowshelffilter property)": [[6, "pedalboard.LowShelfFilter.is_instrument"]], "is_instrument (pedalboard.lowpassfilter property)": [[6, "pedalboard.LowpassFilter.is_instrument"]], "is_instrument (pedalboard.mp3compressor property)": [[6, "pedalboard.MP3Compressor.is_instrument"]], "is_instrument (pedalboard.mix property)": [[6, "pedalboard.Mix.is_instrument"]], "is_instrument (pedalboard.noisegate property)": [[6, "pedalboard.NoiseGate.is_instrument"]], "is_instrument (pedalboard.peakfilter property)": [[6, "pedalboard.PeakFilter.is_instrument"]], "is_instrument (pedalboard.pedalboard property)": [[6, "pedalboard.Pedalboard.is_instrument"]], "is_instrument (pedalboard.phaser property)": [[6, "pedalboard.Phaser.is_instrument"]], "is_instrument (pedalboard.pitchshift property)": [[6, "pedalboard.PitchShift.is_instrument"]], "is_instrument (pedalboard.plugin property)": [[6, "pedalboard.Plugin.is_instrument"]], "is_instrument (pedalboard.plugincontainer property)": [[6, "pedalboard.PluginContainer.is_instrument"]], "is_instrument (pedalboard.resample property)": [[6, "pedalboard.Resample.is_instrument"]], "is_instrument (pedalboard.reverb property)": [[6, "pedalboard.Reverb.is_instrument"]], "is_instrument (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.is_instrument"]], "label (pedalboard.audioprocessorparameter property)": [[6, "pedalboard.AudioProcessorParameter.label"]], "load_plugin() (in module pedalboard)": [[6, "pedalboard.load_plugin"]], "load_preset() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.load_preset"]], "manufacturer_name (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.manufacturer_name"]], "manufacturer_name (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.manufacturer_name"]], "module": [[6, "module-pedalboard"], [7, "module-pedalboard.io"]], "name (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.name"]], "name (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.name"]], "pedalboard": [[6, "module-pedalboard"]], "process() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.process"]], "process() (pedalboard.bitcrush method)": [[6, "pedalboard.Bitcrush.process"]], "process() (pedalboard.chain method)": [[6, "pedalboard.Chain.process"]], "process() (pedalboard.chorus method)": [[6, "pedalboard.Chorus.process"]], "process() (pedalboard.clipping method)": [[6, "pedalboard.Clipping.process"]], "process() (pedalboard.compressor method)": [[6, "pedalboard.Compressor.process"]], "process() (pedalboard.convolution method)": [[6, "pedalboard.Convolution.process"]], "process() (pedalboard.delay method)": [[6, "pedalboard.Delay.process"]], "process() (pedalboard.distortion method)": [[6, "pedalboard.Distortion.process"]], "process() (pedalboard.externalplugin method)": [[6, "pedalboard.ExternalPlugin.process"]], "process() (pedalboard.gsmfullratecompressor method)": [[6, "pedalboard.GSMFullRateCompressor.process"]], "process() (pedalboard.gain method)": [[6, "pedalboard.Gain.process"]], "process() (pedalboard.highshelffilter method)": [[6, "pedalboard.HighShelfFilter.process"]], "process() (pedalboard.highpassfilter method)": [[6, "pedalboard.HighpassFilter.process"]], "process() (pedalboard.iirfilter method)": [[6, "pedalboard.IIRFilter.process"]], "process() (pedalboard.invert method)": [[6, "pedalboard.Invert.process"]], "process() (pedalboard.ladderfilter method)": [[6, "pedalboard.LadderFilter.process"]], "process() (pedalboard.limiter method)": [[6, "pedalboard.Limiter.process"]], "process() (pedalboard.lowshelffilter method)": [[6, "pedalboard.LowShelfFilter.process"]], "process() (pedalboard.lowpassfilter method)": [[6, "pedalboard.LowpassFilter.process"]], "process() (pedalboard.mp3compressor method)": [[6, "pedalboard.MP3Compressor.process"]], "process() (pedalboard.mix method)": [[6, "pedalboard.Mix.process"]], "process() (pedalboard.noisegate method)": [[6, "pedalboard.NoiseGate.process"]], "process() (pedalboard.peakfilter method)": [[6, "pedalboard.PeakFilter.process"]], "process() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.process"]], "process() (pedalboard.phaser method)": [[6, "pedalboard.Phaser.process"]], "process() (pedalboard.pitchshift method)": [[6, "pedalboard.PitchShift.process"]], "process() (pedalboard.plugin method)": [[6, "pedalboard.Plugin.process"]], "process() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.process"]], "process() (pedalboard.resample method)": [[6, "pedalboard.Resample.process"]], "process() (pedalboard.reverb method)": [[6, "pedalboard.Reverb.process"]], "process() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.process"]], "quality (pedalboard.resample property)": [[6, "pedalboard.Resample.quality"]], "rate_hz (pedalboard.chorus property)": [[6, "pedalboard.Chorus.rate_hz"]], "raw_state (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.raw_state"]], "raw_state (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.raw_state"]], "remove() (pedalboard.chain method)": [[6, "pedalboard.Chain.remove"]], "remove() (pedalboard.mix method)": [[6, "pedalboard.Mix.remove"]], "remove() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.remove"]], "remove() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.remove"]], "reset() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.reset"]], "reset() (pedalboard.bitcrush method)": [[6, "pedalboard.Bitcrush.reset"]], "reset() (pedalboard.chain method)": [[6, "pedalboard.Chain.reset"]], "reset() (pedalboard.chorus method)": [[6, "pedalboard.Chorus.reset"]], "reset() (pedalboard.clipping method)": [[6, "pedalboard.Clipping.reset"]], "reset() (pedalboard.compressor method)": [[6, "pedalboard.Compressor.reset"]], "reset() (pedalboard.convolution method)": [[6, "pedalboard.Convolution.reset"]], "reset() (pedalboard.delay method)": [[6, "pedalboard.Delay.reset"]], "reset() (pedalboard.distortion method)": [[6, "pedalboard.Distortion.reset"]], "reset() (pedalboard.externalplugin method)": [[6, "pedalboard.ExternalPlugin.reset"]], "reset() (pedalboard.gsmfullratecompressor method)": [[6, "pedalboard.GSMFullRateCompressor.reset"]], "reset() (pedalboard.gain method)": [[6, "pedalboard.Gain.reset"]], "reset() (pedalboard.highshelffilter method)": [[6, "pedalboard.HighShelfFilter.reset"]], "reset() (pedalboard.highpassfilter method)": [[6, "pedalboard.HighpassFilter.reset"]], "reset() (pedalboard.iirfilter method)": [[6, "pedalboard.IIRFilter.reset"]], "reset() (pedalboard.invert method)": [[6, "pedalboard.Invert.reset"]], "reset() (pedalboard.ladderfilter method)": [[6, "pedalboard.LadderFilter.reset"]], "reset() (pedalboard.limiter method)": [[6, "pedalboard.Limiter.reset"]], "reset() (pedalboard.lowshelffilter method)": [[6, "pedalboard.LowShelfFilter.reset"]], "reset() (pedalboard.lowpassfilter method)": [[6, "pedalboard.LowpassFilter.reset"]], "reset() (pedalboard.mp3compressor method)": [[6, "pedalboard.MP3Compressor.reset"]], "reset() (pedalboard.mix method)": [[6, "pedalboard.Mix.reset"]], "reset() (pedalboard.noisegate method)": [[6, "pedalboard.NoiseGate.reset"]], "reset() (pedalboard.peakfilter method)": [[6, "pedalboard.PeakFilter.reset"]], "reset() (pedalboard.pedalboard method)": [[6, "pedalboard.Pedalboard.reset"]], "reset() (pedalboard.phaser method)": [[6, "pedalboard.Phaser.reset"]], "reset() (pedalboard.pitchshift method)": [[6, "pedalboard.PitchShift.reset"]], "reset() (pedalboard.plugin method)": [[6, "pedalboard.Plugin.reset"]], "reset() (pedalboard.plugincontainer method)": [[6, "pedalboard.PluginContainer.reset"]], "reset() (pedalboard.resample method)": [[6, "pedalboard.Resample.reset"]], "reset() (pedalboard.reverb method)": [[6, "pedalboard.Reverb.reset"]], "reset() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.reset"]], "show_editor() (pedalboard.audiounitplugin method)": [[6, "pedalboard.AudioUnitPlugin.show_editor"]], "show_editor() (pedalboard.vst3plugin method)": [[6, "pedalboard.VST3Plugin.show_editor"]], "target_sample_rate (pedalboard.resample property)": [[6, "pedalboard.Resample.target_sample_rate"]], "time_stretch() (in module pedalboard)": [[6, "pedalboard.time_stretch"]], "units (pedalboard.audioprocessorparameter property)": [[6, "pedalboard.AudioProcessorParameter.units"]], "version (pedalboard.audiounitplugin property)": [[6, "pedalboard.AudioUnitPlugin.version"]], "version (pedalboard.vst3plugin property)": [[6, "pedalboard.VST3Plugin.version"]], "audiofile (class in pedalboard.io)": [[7, "pedalboard.io.AudioFile"]], "audiostream (class in pedalboard.io)": [[7, "pedalboard.io.AudioStream"]], "readableaudiofile (class in pedalboard.io)": [[7, "pedalboard.io.ReadableAudioFile"]], "resampledreadableaudiofile (class in pedalboard.io)": [[7, "pedalboard.io.ResampledReadableAudioFile"]], "streamresampler (class in pedalboard.io)": [[7, "pedalboard.io.StreamResampler"]], "writeableaudiofile (class in pedalboard.io)": [[7, "pedalboard.io.WriteableAudioFile"]], "__enter__() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.__enter__"]], "__enter__() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.__enter__"]], "__enter__() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.__enter__"]], "__exit__() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.__exit__"]], "__exit__() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.__exit__"]], "__exit__() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.__exit__"]], "buffer_size (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.buffer_size"]], "buffered_input_sample_count (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.buffered_input_sample_count"]], "close() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.close"]], "close() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.close"]], "close() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.close"]], "close() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.close"]], "closed (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.closed"]], "closed (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.closed"]], "closed (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.closed"]], "dropped_input_frame_count (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.dropped_input_frame_count"]], "duration (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.duration"]], "duration (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.duration"]], "encode() (pedalboard.io.audiofile static method)": [[7, "pedalboard.io.AudioFile.encode"]], "exact_duration_known (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.exact_duration_known"]], "exact_duration_known (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.exact_duration_known"]], "file_dtype (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.file_dtype"]], "file_dtype (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.file_dtype"]], "file_dtype (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.file_dtype"]], "flush() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.flush"]], "frames (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.frames"]], "frames (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.frames"]], "frames (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.frames"]], "ignore_dropped_input (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.ignore_dropped_input"]], "input_latency (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.input_latency"]], "name (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.name"]], "name (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.name"]], "num_channels (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.num_channels"]], "num_channels (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.num_channels"]], "num_channels (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.num_channels"]], "num_channels (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.num_channels"]], "num_input_channels (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.num_input_channels"]], "num_output_channels (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.num_output_channels"]], "pedalboard.io": [[7, "module-pedalboard.io"]], "play() (pedalboard.io.audiostream static method)": [[7, "pedalboard.io.AudioStream.play"]], "plugins (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.plugins"]], "process() (pedalboard.io.streamresampler method)": [[7, "pedalboard.io.StreamResampler.process"]], "quality (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.quality"]], "quality (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.quality"]], "read() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.read"]], "read() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.read"]], "read() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.read"]], "read_raw() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.read_raw"]], "resampled_to() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.resampled_to"]], "resampling_quality (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.resampling_quality"]], "reset() (pedalboard.io.streamresampler method)": [[7, "pedalboard.io.StreamResampler.reset"]], "run() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.run"]], "running (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.running"]], "sample_rate (pedalboard.io.audiostream property)": [[7, "pedalboard.io.AudioStream.sample_rate"]], "samplerate (pedalboard.io.readableaudiofile property)": [[7, "pedalboard.io.ReadableAudioFile.samplerate"]], "samplerate (pedalboard.io.resampledreadableaudiofile property)": [[7, "pedalboard.io.ResampledReadableAudioFile.samplerate"]], "samplerate (pedalboard.io.writeableaudiofile property)": [[7, "pedalboard.io.WriteableAudioFile.samplerate"]], "seek() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.seek"]], "seek() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.seek"]], "seekable() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.seekable"]], "seekable() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.seekable"]], "source_sample_rate (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.source_sample_rate"]], "target_sample_rate (pedalboard.io.streamresampler property)": [[7, "pedalboard.io.StreamResampler.target_sample_rate"]], "tell() (pedalboard.io.readableaudiofile method)": [[7, "pedalboard.io.ReadableAudioFile.tell"]], "tell() (pedalboard.io.resampledreadableaudiofile method)": [[7, "pedalboard.io.ResampledReadableAudioFile.tell"]], "tell() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.tell"]], "write() (pedalboard.io.audiostream method)": [[7, "pedalboard.io.AudioStream.write"]], "write() (pedalboard.io.writeableaudiofile method)": [[7, "pedalboard.io.WriteableAudioFile.write"]]}}) \ No newline at end of file diff --git a/pedalboard/io/AudioStream.h b/pedalboard/io/AudioStream.h index e62d2741..e2c8fe4d 100644 --- a/pedalboard/io/AudioStream.h +++ b/pedalboard/io/AudioStream.h @@ -41,28 +41,39 @@ class AudioStream : public std::enable_shared_from_this #endif { public: - AudioStream(std::string inputDeviceName, std::string outputDeviceName, + AudioStream(std::optional inputDeviceName, + std::optional outputDeviceName, std::optional> pedalboard, - std::optional sampleRate, int bufferSize, - bool allowFeedback) -#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + std::optional sampleRate, std::optional bufferSize, + bool allowFeedback, int numInputChannels, int numOutputChannels) : pedalboard(pedalboard ? *pedalboard : std::make_shared( std::vector>())), - livePedalboard(std::vector>()) -#endif - { + livePedalboard(std::vector>()) { #ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices juce::AudioDeviceManager::AudioDeviceSetup setup; - setup.inputDeviceName = inputDeviceName; - setup.outputDeviceName = outputDeviceName; + if (inputDeviceName) { + setup.inputDeviceName = *inputDeviceName; + } else { + numInputChannels = 0; + } + + if (outputDeviceName) { + setup.outputDeviceName = *outputDeviceName; + } else { + numOutputChannels = 0; + } + // A value of 0 indicates we want to use whatever the device default is: setup.sampleRate = sampleRate ? *sampleRate : 0; - setup.bufferSize = bufferSize; - if (!allowFeedback && - juce::String(inputDeviceName).containsIgnoreCase("microphone") && - juce::String(outputDeviceName).containsIgnoreCase("speaker")) { + // This is our buffer between the audio hardware and the audio thread, + // so this can be a lot smaller: + setup.bufferSize = bufferSize ? *bufferSize : 512; + + if (inputDeviceName && outputDeviceName && !allowFeedback && + juce::String(*inputDeviceName).containsIgnoreCase("microphone") && + juce::String(*outputDeviceName).containsIgnoreCase("speaker")) { throw std::runtime_error( "The audio input device passed to AudioStream looks like a " "microphone, and the output device looks like a speaker. This setup " @@ -70,18 +81,40 @@ class AudioStream : public std::enable_shared_from_this "`allow_feedback=True` to the AudioStream constructor."); } + if (!inputDeviceName && !outputDeviceName) { + throw std::runtime_error("At least one of `input_device_name` or " + "`output_device_name` must be provided."); + } + + if (inputDeviceName) { + recordBufferFifo = + std::make_unique(setup.bufferSize + 1); + recordBuffer = std::make_unique>( + numInputChannels, setup.bufferSize + 1); + } + + if (outputDeviceName) { + playBufferFifo = + std::make_unique(setup.bufferSize + 1); + playBuffer = std::make_unique>( + numOutputChannels, setup.bufferSize + 1); + } + juce::String defaultDeviceName; - juce::String error = deviceManager.initialise(2, 2, nullptr, true, - defaultDeviceName, &setup); + juce::String error = + deviceManager.initialise(numInputChannels, numOutputChannels, nullptr, + true, defaultDeviceName, &setup); if (!error.isEmpty()) { throw std::domain_error(error.toStdString()); } + + // We'll re-open the audio device when we need it + deviceManager.closeAudioDevice(); #else throw std::runtime_error("AudioStream is not supported on this platform."); #endif } -#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices ~AudioStream() { stop(); close(); @@ -91,26 +124,48 @@ class AudioStream : public std::enable_shared_from_this void setPedalboard(std::shared_ptr chain) { pedalboard = chain; } - void close() { deviceManager.closeAudioDevice(); } + void close() { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + deviceManager.closeAudioDevice(); +#endif + } void start() { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + if (isRunning) { + throw std::runtime_error("This AudioStream is already running."); + } + + deviceManager.restartLastAudioDevice(); + isRunning = true; + numDroppedInputFrames = 0; changeObserverThread = std::thread(&AudioStream::propagateChangesToAudioThread, this); deviceManager.addAudioCallback(this); +#endif } void stop() { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices deviceManager.removeAudioCallback(this); isRunning = false; if (changeObserverThread.joinable()) { changeObserverThread.join(); } + if (recordBufferFifo) { + recordBufferFifo->reset(); + } + if (playBufferFifo) { + playBufferFifo->reset(); + } + close(); +#endif } void propagateChangesToAudioThread() { while (isRunning) { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); // Make sure nobody modifies the Python-side object while we're reading // it (without taking the GIL, which would be expensive) @@ -135,6 +190,12 @@ class AudioStream : public std::enable_shared_from_this } void stream() { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + if (!getNumInputChannels() || !getNumOutputChannels()) + throw std::runtime_error( + "This AudioStream object was not created with both an input and an " + "output device, so calling run() would do nothing."); + start(); while (isRunning) { if (PyErr_CheckSignals() != 0) { @@ -150,6 +211,9 @@ class AudioStream : public std::enable_shared_from_this } stop(); throw py::error_already_set(); +#else + throw std::runtime_error("AudioStream is not supported on this platform."); +#endif } std::shared_ptr enter() { @@ -161,12 +225,14 @@ class AudioStream : public std::enable_shared_from_this const py::object &traceback) { bool shouldThrow = PythonException::isPending(); stop(); + close(); if (shouldThrow || PythonException::isPending()) throw py::error_already_set(); } static std::vector getDeviceNames(bool isInput) { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices juce::AudioDeviceManager deviceManager; std::vector names; @@ -176,34 +242,143 @@ class AudioStream : public std::enable_shared_from_this } } return names; +#else + return {}; +#endif } +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + template static auto getSetupInfo(Setup &s, bool isInput) { + struct SetupInfo { + // double brackets so that we get the expression type, i.e. a (possibly + // const) reference + decltype((s.inputDeviceName)) name; + decltype((s.inputChannels)) channels; + decltype((s.useDefaultInputChannels)) useDefault; + }; + + return isInput ? SetupInfo{s.inputDeviceName, s.inputChannels, + s.useDefaultInputChannels} + : SetupInfo{s.outputDeviceName, s.outputChannels, + s.useDefaultOutputChannels}; + } +#endif + + static std::optional + getDefaultDeviceName(bool isInput, int numChannelsNeeded) { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + juce::AudioDeviceManager deviceManager; + deviceManager.getAvailableDeviceTypes(); + + juce::AudioDeviceManager::AudioDeviceSetup setup; + + if (auto *type = deviceManager.getCurrentDeviceTypeObject()) { + const auto info = getSetupInfo(setup, isInput); + + if (numChannelsNeeded > 0 && info.name.isEmpty()) + return { + type->getDeviceNames(isInput)[type->getDefaultDeviceIndex(isInput)] + .toStdString()}; + } +#endif + return {}; + } + +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices virtual void audioDeviceIOCallback(const float **inputChannelData, int numInputChannels, float **outputChannelData, int numOutputChannels, int numSamples) { - for (int i = 0; i < numOutputChannels; i++) { - const float *inputChannel = inputChannelData[i % numInputChannels]; - std::memcpy((char *)outputChannelData[i], (char *)inputChannel, - numSamples * sizeof(float)); - } - - auto ioBlock = juce::dsp::AudioBlock( - outputChannelData, numOutputChannels, 0, numSamples); - juce::dsp::ProcessContextReplacing context(ioBlock); - - juce::SpinLock::ScopedTryLockType tryLock(livePedalboardMutex); - if (tryLock.isLocked()) { - for (auto plugin : livePedalboard.getPlugins()) { - std::unique_lock lock(pedalboard->mutex, std::try_to_lock); - // If someone's running audio through this plugin in parallel (offline, - // or in a different AudioStream object) then don't corrupt its state by - // calling it here too; instead, just skip it: - if (lock.owns_lock()) { - plugin->process(context); + // Live processing mode: run the input audio through a Pedalboard object. + if (!playBufferFifo && !recordBufferFifo) { + for (int i = 0; i < numOutputChannels; i++) { + const float *inputChannel = inputChannelData[i % numInputChannels]; + std::memcpy((char *)outputChannelData[i], (char *)inputChannel, + numSamples * sizeof(float)); + } + + auto ioBlock = juce::dsp::AudioBlock( + outputChannelData, numOutputChannels, 0, numSamples); + juce::dsp::ProcessContextReplacing context(ioBlock); + + juce::SpinLock::ScopedTryLockType tryLock(livePedalboardMutex); + if (tryLock.isLocked()) { + for (auto plugin : livePedalboard.getPlugins()) { + std::unique_lock lock(pedalboard->mutex, + std::try_to_lock); + // If someone's running audio through this plugin in parallel + // (offline, or in a different AudioStream object) then don't corrupt + // its state by calling it here too; instead, just skip it: + if (lock.owns_lock()) { + plugin->process(context); + } + } + } + } + + if (recordBufferFifo) { + // If Python wants audio input, then copy the audio into the record + // buffer: + for (int attempt = 0; attempt < 2; attempt++) { + int samplesWritten = 0; + { + const auto scope = recordBufferFifo->write(numSamples); + + if (scope.blockSize1 > 0) + for (int i = 0; i < numInputChannels; i++) { + std::memcpy( + (char *)recordBuffer->getWritePointer(i, scope.startIndex1), + (char *)inputChannelData[i], + scope.blockSize1 * sizeof(float)); + } + + if (scope.blockSize2 > 0) + for (int i = 0; i < numInputChannels; i++) { + std::memcpy( + (char *)recordBuffer->getWritePointer(i, scope.startIndex2), + (char *)(inputChannelData[i] + scope.blockSize1), + scope.blockSize2 * sizeof(float)); + } + + samplesWritten = scope.blockSize1 + scope.blockSize2; + } + + if (samplesWritten < numSamples) { + numDroppedInputFrames += numSamples - samplesWritten; + // We've dropped some frames during recording; not great. + // Favour capturing more recent audio instead, so clear out enough + // space in the buffer to keep up and retry: + const auto scope = recordBufferFifo->read(numSamples); + + // Do nothing here; as soon as `scope` goes out of scope, + // the buffer will now allow us to append `numSamples`. + } else { + break; } } } + + for (int i = 0; i < numOutputChannels; i++) { + std::memset((char *)outputChannelData[i], 0, numSamples * sizeof(float)); + } + + if (playBufferFifo) { + const auto scope = playBufferFifo->read(numSamples); + + if (scope.blockSize1 > 0) + for (int i = 0; i < numOutputChannels; i++) { + std::memcpy((char *)outputChannelData[i], + (char *)playBuffer->getReadPointer(i, scope.startIndex1), + scope.blockSize1 * sizeof(float)); + } + + if (scope.blockSize2 > 0) + for (int i = 0; i < numOutputChannels; i++) { + std::memcpy((char *)(outputChannelData[i] + scope.blockSize1), + (char *)playBuffer->getReadPointer(i, scope.startIndex2), + scope.blockSize2 * sizeof(float)); + } + } } virtual void audioDeviceAboutToStart(juce::AudioIODevice *device) { @@ -226,15 +401,262 @@ class AudioStream : public std::enable_shared_from_this plugin->reset(); } } +#endif bool getIsRunning() const { return isRunning; } + int getDroppedInputFrameCount() const { return numDroppedInputFrames; } + + bool getIgnoreDroppedInput() const { return ignoreDroppedInput; } + + void setIgnoreDroppedInput(bool ignore) { ignoreDroppedInput = ignore; } + +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices juce::AudioDeviceManager::AudioDeviceSetup getAudioDeviceSetup() const { return deviceManager.getAudioDeviceSetup(); } +#endif + + int writeIntoBuffer(const juce::AbstractFifo::ScopedWrite &scope, int offset, + juce::AudioBuffer &from, + juce::AudioBuffer &to) { + bool inputIsMono = from.getNumChannels() == 1; + int numChannels = inputIsMono ? to.getNumChannels() : from.getNumChannels(); + + if (scope.blockSize1 > 0) { + for (int c = 0; c < numChannels; c++) { + to.copyFrom(c, scope.startIndex1, from, inputIsMono ? 0 : c, offset, + scope.blockSize1); + } + } + + if (scope.blockSize2 > 0) { + for (int c = 0; c < numChannels; c++) { + to.copyFrom(c, scope.startIndex2, from, inputIsMono ? 0 : c, + offset + scope.blockSize1, scope.blockSize2); + } + } + return scope.blockSize1 + scope.blockSize2; + } + + void writeAllAtOnce(juce::AudioBuffer buffer) { + if (!playBufferFifo) { + throw std::runtime_error( + "This AudioStream object was not created with an output device, so " + "it cannot write audio data."); + } + + if (isRunning) { + throw std::runtime_error( + "writeAllAtOnce() called when the stream is already running. " + "This is an internal Pedalboard error and should be reported."); + } + + start(); + // Write this audio buffer to the output device, via the FIFO, checking + // for Python signals along the way (as this method is usually called + // by passing the audio all at once from Python): + + bool errorSet = false; + for (int i = 0; i < buffer.getNumSamples();) { + errorSet = PyErr_CheckSignals() != 0; + if (errorSet) { + break; + } + + py::gil_scoped_release release; + + int numSamplesToWrite = + std::min(playBufferFifo->getFreeSpace(), buffer.getNumSamples() - i); + + const auto scope = playBufferFifo->write(numSamplesToWrite); + i += writeIntoBuffer(scope, i, buffer, *playBuffer); + } + + stop(); + + if (errorSet) { + throw py::error_already_set(); + } + } + + int getNumInputChannels() const { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + return deviceManager.getAudioDeviceSetup() + .inputChannels.countNumberOfSetBits(); +#else + return 0; +#endif + } + + int getNumOutputChannels() const { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + return deviceManager.getAudioDeviceSetup() + .outputChannels.countNumberOfSetBits(); +#else + return 0; +#endif + } + + void write(juce::AudioBuffer buffer) { + if (!playBufferFifo) { + throw std::runtime_error( + "This AudioStream object was not created with an output device, so " + "it cannot write audio data."); + } + + if (!isRunning) { + writeAllAtOnce(buffer); + return; + } + + py::gil_scoped_release release; + + // Write this audio buffer to the output device, via the FIFO: + for (int i = 0; i < buffer.getNumSamples();) { + int numSamplesToWrite = + std::min(playBufferFifo->getFreeSpace(), buffer.getNumSamples() - i); + + const auto scope = playBufferFifo->write(numSamplesToWrite); + i += writeIntoBuffer(scope, i, buffer, *playBuffer); + } + } + + juce::AudioBuffer readAllAtOnce(int numSamples) { + // Read this number of samples from the audio device, via its FIFO: + if (!recordBufferFifo) { + throw std::runtime_error( + "This AudioStream object was not created with an input device, so " + "it cannot read audio data."); + } + + if (isRunning) { + throw std::runtime_error( + "readAllAtOnce() called when the stream is already running. " + "This is an internal Pedalboard error and should be reported."); + } + + juce::AudioBuffer returnBuffer(getNumInputChannels(), numSamples); + + start(); + bool errorSet = false; + // Read the desired number of samples from the output device, via the FIFO: + for (int i = 0; i < returnBuffer.getNumSamples();) { + errorSet = PyErr_CheckSignals() != 0; + if (errorSet) { + break; + } + + py::gil_scoped_release release; + + int numSamplesToRead = std::min(recordBufferFifo->getNumReady(), + returnBuffer.getNumSamples() - i); + + const auto scope = recordBufferFifo->read(numSamplesToRead); + if (scope.blockSize1 > 0) { + for (int c = 0; c < returnBuffer.getNumChannels(); c++) { + returnBuffer.copyFrom(c, i, *recordBuffer, c, scope.startIndex1, + scope.blockSize1); + } + } + + if (scope.blockSize2 > 0) { + for (int c = 0; c < returnBuffer.getNumChannels(); c++) { + returnBuffer.copyFrom(c, i + scope.blockSize1, *recordBuffer, c, + scope.startIndex2, scope.blockSize2); + } + } + + i += scope.blockSize1 + scope.blockSize2; + } + stop(); + + numDroppedInputFrames = 0; + + // Always return the buffer, even if an error was set: + if (errorSet) { + throw py::error_already_set(); + } + return returnBuffer; + } + + juce::AudioBuffer read(int numSamples) { + // Read this number of samples from the audio device, via its FIFO: + if (!recordBufferFifo) { + throw std::runtime_error( + "This AudioStream object was not created with an input device, so " + "it cannot read audio data."); + } + + if (!isRunning) { + return readAllAtOnce(numSamples); + } + + if (numSamples == 0) { + numSamples = recordBufferFifo->getNumReady(); + } + + if (numDroppedInputFrames && !ignoreDroppedInput) { + int numDropped = numDroppedInputFrames; + numDroppedInputFrames = 0; + throw std::runtime_error( + std::to_string(numDropped) + + " frames of audio data were dropped since the last call to read(). " + "To prevent audio from being lost during recording, ensure that you " + "call read() as quickly as possible or increase your buffer size."); + } + + py::gil_scoped_release release; + + juce::AudioBuffer returnBuffer(getNumInputChannels(), numSamples); + + // Read the desired number of samples from the output device, via the FIFO: + for (int i = 0; i < returnBuffer.getNumSamples();) { + int numSamplesToRead = std::min(recordBufferFifo->getNumReady(), + returnBuffer.getNumSamples() - i); + + const auto scope = recordBufferFifo->read(numSamplesToRead); + if (scope.blockSize1 > 0) { + for (int c = 0; c < returnBuffer.getNumChannels(); c++) { + returnBuffer.copyFrom(c, i, *recordBuffer, c, scope.startIndex1, + scope.blockSize1); + } + } + + if (scope.blockSize2 > 0) { + for (int c = 0; c < returnBuffer.getNumChannels(); c++) { + returnBuffer.copyFrom(c, i + scope.blockSize1, *recordBuffer, c, + scope.startIndex2, scope.blockSize2); + } + } + + i += scope.blockSize1 + scope.blockSize2; + } + + numDroppedInputFrames = 0; + + return returnBuffer; + } + + double getSampleRate() const { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + return deviceManager.getAudioDeviceSetup().sampleRate; +#else + return 0; +#endif + } + + std::optional getNumBufferedInputFrames() const { + if (!recordBufferFifo) { + return {}; + } + return {recordBufferFifo->getNumReady()}; + } private: +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices juce::AudioDeviceManager deviceManager; +#endif juce::dsp::ProcessSpec spec; bool isRunning = false; @@ -245,7 +667,7 @@ class AudioStream : public std::enable_shared_from_this // currently being used for rendering. // The `livePedalboard` object already has a std::mutex on it, // but we want something that's faster and callable from the - // dudio thread. + // audio thread. juce::SpinLock livePedalboardMutex; // A "live" pedalboard, called from the audio thread. @@ -257,21 +679,46 @@ class AudioStream : public std::enable_shared_from_this // happen in Python) and copies those changes over to data // structures used by the audio thread. std::thread changeObserverThread; -#endif -}; -inline void init_audio_stream(py::module &m) { - auto audioStream = - py::class_>(m, "AudioStream", - R"( -A class that streams audio from an input audio device (i.e.: a microphone, -audio interface, etc) to an output device (speaker, headphones), -passing it through a :class:`pedalboard.Pedalboard` to add effects. + // Two buffers that can be written to by the audio thread: + std::unique_ptr recordBufferFifo; + std::unique_ptr playBufferFifo; + std::unique_ptr> recordBuffer; + std::unique_ptr> playBuffer; -:class:`AudioStream` may be used as a context manager:: + std::atomic numDroppedInputFrames{0}; + bool ignoreDroppedInput = false; +}; - input_device_name = AudioStream.input_device_names[0] - output_device_name = AudioStream.output_device_names[0] +inline void init_audio_stream(py::module &m) { + py::class_>(m, "AudioStream", + R"( +A class that allows interacting with live streams of audio from an input +audio device (i.e.: a microphone, audio interface, etc) and/or to an +output device (speaker, headphones), allowing access to the audio +stream from within Python code. + +Use :py:meth:`AudioStream.play` to play audio data to your speakers:: + + # Play a 10-second chunk of an audio file: + with AudioFile("my_audio_file.mp3") as f: + chunk = f.read(f.samplerate * 10) + AudioStream.play(chunk, f.samplerate) + +Or use :py:meth:`AudioStream.write` to stream audio in chunks:: + + # Play an audio file by looping through it in chunks: + with AudioStream(output_device="default") as stream: + with AudioFile("my_audio_file.mp3") as f: + while f.tell() < f.frames: + # Decode and play 512 samples at a time: + stream.write(f.read(512)) + +:class:`AudioStream` may also be used to pass live audio through a :class:`Pedalboard`:: + + # Pass both an input and output device name to connect both ends: + input_device_name = AudioStream.default_input_device_name + output_device_name = AudioStream.default_output_device_name with AudioStream(input_device_name, output_device_name) as stream: # In this block, audio is streaming through `stream`! # Audio will be coming out of your speakers at this point. @@ -286,20 +733,11 @@ passing it through a :class:`pedalboard.Pedalboard` to add effects. # Delete plugins: del stream.plugins[0] - -:class:`AudioStream` may also be used synchronously:: - - stream = AudioStream(ogg_buffer) + # Or use AudioStream synchronously: + stream = AudioStream(input_device_name, output_device_name) stream.plugins.append(Reverb(wet_level=1.0)) stream.run() # Run the stream until Ctrl-C is received -.. note:: - This class uses C++ under the hood to ensure speed, thread safety, - and avoid any locking concerns with Python's Global Interpreter Lock. - Audio data processed by :class:`AudioStream` is not available to - Python code; the only way to interact with the audio stream is through - the :py:attr:`plugins` attribute. - .. warning:: The :class:`AudioStream` class implements a context manager interface to ensure that audio streams are never left "dangling" (i.e.: running in @@ -308,56 +746,73 @@ passing it through a :class:`pedalboard.Pedalboard` to add effects. While it is possible to call the :meth:`__enter__` method directly to run an audio stream in the background, this can have some nasty side effects. If the :class:`AudioStream` object is no longer reachable (not bound to a variable, - not in scope, etc), the audio stream will continue to play back forever, and + not in scope, etc), the audio stream will continue to run forever, and won't stop until the Python interpreter exits. To run an :class:`AudioStream` in the background, use Python's - :py:mod:`threading` module to call the synchronous :meth:`run` method on a + :py:mod:`threading` module to run the stream object method on a background thread, allowing for easier cleanup. *Introduced in v0.7.0. Not supported on Linux.* + +:py:meth:`read` *and* :py:meth:`write` *methods introduced in v0.9.12.* )") - .def(py::init([](std::string inputDeviceName, - std::string outputDeviceName, - std::optional> pedalboard, - std::optional sampleRate, int bufferSize, - bool allowFeedback) { - return std::make_shared( - inputDeviceName, outputDeviceName, pedalboard, sampleRate, - bufferSize, allowFeedback); - }), - py::arg("input_device_name"), py::arg("output_device_name"), - py::arg("plugins") = py::none(), - py::arg("sample_rate") = py::none(), - py::arg("buffer_size") = 512, py::arg("allow_feedback") = false); -#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices - audioStream + .def(py::init([](std::optional inputDeviceName, + std::optional outputDeviceName, + std::optional> pedalboard, + std::optional sampleRate, + std::optional bufferSize, bool allowFeedback, + int numInputChannels, int numOutputChannels) { + return std::make_shared( + inputDeviceName, outputDeviceName, pedalboard, sampleRate, + bufferSize, allowFeedback, numInputChannels, + numOutputChannels); + }), + py::arg("input_device_name") = py::none(), + py::arg("output_device_name") = py::none(), + py::arg("plugins") = py::none(), py::arg("sample_rate") = py::none(), + py::arg("buffer_size") = py::none(), + py::arg("allow_feedback") = false, py::arg("num_input_channels") = 1, + py::arg("num_output_channels") = 2) .def("run", &AudioStream::stream, "Start streaming audio from input to output, passing the audio " - "stream through the :py:attr:`plugins` on this AudioStream object. " + "stream through the :py:attr:`plugins` on this AudioStream object. " "This call will block the current thread until a " ":py:exc:`KeyboardInterrupt` (``Ctrl-C``) is received.") - .def_property_readonly( - "running", &AudioStream::getIsRunning, - ":py:const:`True` if this stream is currently streaming live " - "audio from input to output, :py:const:`False` otherwise.") + .def_property_readonly("running", &AudioStream::getIsRunning, + ":py:const:`True` if this stream is currently " + "streaming live " + "audio, :py:const:`False` otherwise.") .def("__enter__", &AudioStream::enter, "Use this :class:`AudioStream` as a context manager. Entering the " "context manager will immediately start the audio stream, sending " "audio through to the output device.") .def("__exit__", &AudioStream::exit, "Exit the context manager, ending the audio stream. Once called, " - "the audio stream will be stopped (i.e.: :py:attr:`running` will be " + "the audio stream will be stopped (i.e.: :py:attr:`running` will " + "be " ":py:const:`False`).") .def("__repr__", [](const AudioStream &stream) { std::ostringstream ss; ss << " 0) { + ss << " output_device_name=\"" + << audioDeviceSetup.outputDeviceName.toStdString() << "\""; + } else { + ss << " output_device_name=None"; + } + ss << " sample_rate=" << juce::String(audioDeviceSetup.sampleRate, 2).toStdString(); ss << " buffer_size=" << audioDeviceSetup.bufferSize; @@ -366,37 +821,162 @@ passing it through a :class:`pedalboard.Pedalboard` to add effects. } else { ss << " not running"; } +#endif ss << " at " << &stream; ss << ">"; return ss.str(); }) + .def_property_readonly( + "buffer_size", + [](AudioStream &stream) { +#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices + return stream.getAudioDeviceSetup().bufferSize; +#else + return 0; +#endif + }, + "The size (in frames) of the buffer used between the audio " + "hardware " + "and Python.") .def_property("plugins", &AudioStream::getPedalboard, &AudioStream::setPedalboard, "The Pedalboard object that this AudioStream will use to " - "process audio."); -#endif - audioStream + "process audio.") + .def_property_readonly( + "dropped_input_frame_count", &AudioStream::getDroppedInputFrameCount, + "The number of frames of audio that were dropped since the last " + "call " + "to :py:meth:`read`. To prevent audio from being dropped during " + "recording, ensure that you call :py:meth:`read` as often as " + "possible or increase your buffer size.") + .def_property_readonly( + "sample_rate", &AudioStream::getSampleRate, + "The sample rate that this stream is operating at.") + .def_property_readonly("num_input_channels", + &AudioStream::getNumInputChannels, + "The number of input channels on the input " + "device. Will be ``0`` if " + "no input device is connected.") + .def_property_readonly( + "num_output_channels", &AudioStream::getNumOutputChannels, + "The number of output channels on the output " + "device. Will be ``0`` if no output device is connected.") + .def_property( + "ignore_dropped_input", &AudioStream::getIgnoreDroppedInput, + &AudioStream::setIgnoreDroppedInput, + "Controls the behavior of the :py:meth:`read` method when audio " + "data " + "is dropped. If this property is false (the default), the " + ":py:meth:`read` method will raise a :py:exc:`RuntimeError` if any " + "audio data is dropped in between calls. If this property is true, " + "the :py:meth:`read` method will return the most recent audio data " + "available, even if some audio data was dropped.\n\n.. note::\n " + "The :py:attr:`dropped_input_frame_count` property is unaffected " + "by " + "this setting.") + .def( + "write", + [](AudioStream &stream, + const py::array_t inputArray, + float sampleRate) { + if (sampleRate != stream.getSampleRate()) { + throw std::runtime_error( + "The sample rate provided to `write` (" + + std::to_string(sampleRate) + + " Hz) does not match the output device's sample rate (" + + std::to_string(stream.getSampleRate()) + + " Hz). To write audio data to the output device, the " + "sample " + "rate of the audio must match the output device's sample " + "rate."); + } + stream.write(copyPyArrayIntoJuceBuffer(inputArray)); + }, + py::arg("audio"), py::arg("sample_rate"), + "Write (play) audio data to the output device. This method will " + "block until the provided audio buffer is played in its " + "entirety.\n\nIf the provided sample rate does not match the " + "output " + "device's sample rate, an error will be thrown. In this case, you " + "can use :py:class:`StreamResampler` to resample the audio before " + "calling :py:meth:`write`.") + .def( + "read", + [](AudioStream &stream, int numSamples) { + return copyJuceBufferIntoPyArray(stream.read(numSamples), + ChannelLayout::NotInterleaved, 0); + }, + py::arg("num_samples") = 0, + "Read (record) audio data from the input device. When called with " + "no " + "arguments, this method returns all of the available audio data in " + "the buffer. If `num_samples` is provided, this method will block " + "until the desired number of samples have been received. The audio " + "is recorded at the :py:attr:`sample_rate` of this stream.\n\n.. " + "warning::\n Recording audio is a **real-time** operation, so " + "if " + "your code doesn't call :py:meth:`read` quickly enough, some audio " + "will be lost. To warn about this, :py:meth:`read` will throw an " + "exception if audio data is dropped. This behavior can be disabled " + "by setting :py:attr:`ignore_dropped_input` to :py:const:`True`. " + "The " + "number of dropped samples since the last call to :py:meth:`read` " + "can be retrieved by accessing the " + ":py:attr:`dropped_input_frame_count` property.") + .def_property_readonly( + "buffered_input_sample_count", + &AudioStream::getNumBufferedInputFrames, + "The number of frames of audio that are currently in the input " + "buffer. This number will change rapidly, and will be " + ":py:const:`None` if no input device is connected.") + .def("close", &AudioStream::close, + "Close the audio stream, stopping the audio device and releasing " + "any resources. After calling close, this AudioStream object is no " + "longer usable.") + .def_static( + "play", + [](const py::array_t audio, + float sampleRate, std::optional outputDeviceName) { + juce::AudioBuffer buffer = copyPyArrayIntoJuceBuffer(audio); + AudioStream(std::nullopt, outputDeviceName ? *outputDeviceName : "", + std::nullopt, {sampleRate}, std::nullopt, false, 0, + buffer.getNumChannels()) + .write(buffer); + }, + py::arg("audio"), py::arg("sample_rate"), + py::arg("output_device_name") = py::none(), + "Play audio data to the speaker, headphones, or other output " + "device. " + "This method will block until the audio is finished playing.") .def_property_readonly_static( "input_device_names", [](py::object *obj) -> std::vector { -#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices return AudioStream::getDeviceNames(true); -#else - return {}; -#endif }, "The input devices (i.e.: microphones, audio interfaces, etc.) " "currently available on the current machine.") .def_property_readonly_static( "output_device_names", [](py::object *obj) -> std::vector { -#ifdef JUCE_MODULE_AVAILABLE_juce_audio_devices return AudioStream::getDeviceNames(false); -#else - return {}; -#endif }, "The output devices (i.e.: speakers, headphones, etc.) currently " - "available on the current machine."); + "available on the current machine.") + .def_property_readonly_static( + "default_input_device_name", + [](py::object *obj) -> std::optional { + return AudioStream::getDefaultDeviceName(true, 1); + }, + "The name of the default input device (i.e.: microphone, audio " + "interface, etc.) currently available on the current machine. May " + "be :py:const:`None` if no input devices are present.") + .def_property_readonly_static( + "default_output_device_name", + [](py::object *obj) -> std::optional { + return AudioStream::getDefaultDeviceName(false, 2); + }, + "The name of the default output device (i.e.: speakers, " + "headphones, etc.) currently available on the current machine. May " + "be :py:const:`None` if no output devices are present."); } } // namespace Pedalboard \ No newline at end of file diff --git a/pedalboard_native/io/__init__.pyi b/pedalboard_native/io/__init__.pyi index 5bf794a9..6243d95e 100644 --- a/pedalboard_native/io/__init__.pyi +++ b/pedalboard_native/io/__init__.pyi @@ -218,14 +218,32 @@ class AudioFile: class AudioStream: """ - A class that streams audio from an input audio device (i.e.: a microphone, - audio interface, etc) to an output device (speaker, headphones), - passing it through a :class:`pedalboard.Pedalboard` to add effects. + A class that allows interacting with live streams of audio from an input + audio device (i.e.: a microphone, audio interface, etc) and/or to an + output device (speaker, headphones), allowing access to the audio + stream from within Python code. - :class:`AudioStream` may be used as a context manager:: + Use :py:meth:`AudioStream.play` to play audio data to your speakers:: - input_device_name = AudioStream.input_device_names[0] - output_device_name = AudioStream.output_device_names[0] + # Play a 10-second chunk of an audio file: + with AudioFile("my_audio_file.mp3") as f: + chunk = f.read(f.samplerate * 10) + AudioStream.play(chunk, f.samplerate) + + Or use :py:meth:`AudioStream.write` to stream audio in chunks:: + + # Play an audio file by looping through it in chunks: + with AudioStream(output_device="default") as stream: + with AudioFile("my_audio_file.mp3") as f: + while f.tell() < f.frames: + # Decode and play 512 samples at a time: + stream.write(f.read(512)) + + :class:`AudioStream` may also be used to pass live audio through a :class:`Pedalboard`:: + + # Pass both an input and output device name to connect both ends: + input_device_name = AudioStream.default_input_device_name + output_device_name = AudioStream.default_output_device_name with AudioStream(input_device_name, output_device_name) as stream: # In this block, audio is streaming through `stream`! # Audio will be coming out of your speakers at this point. @@ -240,20 +258,11 @@ class AudioStream: # Delete plugins: del stream.plugins[0] - - :class:`AudioStream` may also be used synchronously:: - - stream = AudioStream(ogg_buffer) + # Or use AudioStream synchronously: + stream = AudioStream(input_device_name, output_device_name) stream.plugins.append(Reverb(wet_level=1.0)) stream.run() # Run the stream until Ctrl-C is received - .. note:: - This class uses C++ under the hood to ensure speed, thread safety, - and avoid any locking concerns with Python's Global Interpreter Lock. - Audio data processed by :class:`AudioStream` is not available to - Python code; the only way to interact with the audio stream is through - the :py:attr:`plugins` attribute. - .. warning:: The :class:`AudioStream` class implements a context manager interface to ensure that audio streams are never left "dangling" (i.e.: running in @@ -262,14 +271,16 @@ class AudioStream: While it is possible to call the :meth:`__enter__` method directly to run an audio stream in the background, this can have some nasty side effects. If the :class:`AudioStream` object is no longer reachable (not bound to a variable, - not in scope, etc), the audio stream will continue to play back forever, and + not in scope, etc), the audio stream will continue to run forever, and won't stop until the Python interpreter exits. To run an :class:`AudioStream` in the background, use Python's - :py:mod:`threading` module to call the synchronous :meth:`run` method on a + :py:mod:`threading` module to run the stream object method on a background thread, allowing for easier cleanup. *Introduced in v0.7.0. Not supported on Linux.* + + :py:meth:`read` *and* :py:meth:`write` *methods introduced in v0.9.12.* """ def __enter__(self) -> AudioStream: @@ -284,17 +295,107 @@ class AudioStream: def __init__( self, - input_device_name: str, - output_device_name: str, + input_device_name: typing.Optional[str] = None, + output_device_name: typing.Optional[str] = None, plugins: typing.Optional[pedalboard_native.utils.Chain] = None, sample_rate: typing.Optional[float] = None, - buffer_size: int = 512, + buffer_size: typing.Optional[int] = None, allow_feedback: bool = False, + num_input_channels: int = 1, + num_output_channels: int = 2, ) -> None: ... def __repr__(self) -> str: ... + def close(self) -> None: + """ + Close the audio stream, stopping the audio device and releasing any resources. After calling close, this AudioStream object is no longer usable. + """ + + @staticmethod + def play( + audio: numpy.ndarray[typing.Any, numpy.dtype[numpy.float32]], + sample_rate: float, + output_device_name: typing.Optional[str] = None, + ) -> None: + """ + Play audio data to the speaker, headphones, or other output device. This method will block until the audio is finished playing. + """ + + def read(self, num_samples: int = 0) -> numpy.ndarray[typing.Any, numpy.dtype[numpy.float32]]: + """ + .. warning:: + Recording audio is a **real-time** operation, so if your code doesn't call :py:meth:`read` quickly enough, some audio will be lost. To warn about this, :py:meth:`read` will throw an exception if audio data is dropped. This behavior can be disabled by setting :py:attr:`ignore_dropped_input` to :py:const:`True`. The number of dropped samples since the last call to :py:meth:`read` can be retrieved by accessing the :py:attr:`dropped_input_frame_count` property. + """ + def run(self) -> None: """ - Start streaming audio from input to output, passing the audio stream through the :py:attr:`plugins` on this AudioStream object. This call will block the current thread until a :py:exc:`KeyboardInterrupt` (``Ctrl-C``) is received. + Start streaming audio from input to output, passing the audio stream through the :py:attr:`plugins` on this AudioStream object. This call will block the current thread until a :py:exc:`KeyboardInterrupt` (``Ctrl-C``) is received. + """ + + def write( + self, audio: numpy.ndarray[typing.Any, numpy.dtype[numpy.float32]], sample_rate: float + ) -> None: + """ + If the provided sample rate does not match the output device's sample rate, an error will be thrown. In this case, you can use :py:class:`StreamResampler` to resample the audio before calling :py:meth:`write`. + """ + + @property + def buffer_size(self) -> int: + """ + The size (in frames) of the buffer used between the audio hardware and Python. + + + """ + + @property + def buffered_input_sample_count(self) -> typing.Optional[int]: + """ + The number of frames of audio that are currently in the input buffer. This number will change rapidly, and will be :py:const:`None` if no input device is connected. + + + """ + + @property + def dropped_input_frame_count(self) -> int: + """ + The number of frames of audio that were dropped since the last call to :py:meth:`read`. To prevent audio from being dropped during recording, ensure that you call :py:meth:`read` as often as possible or increase your buffer size. + + + """ + + @property + def ignore_dropped_input(self) -> bool: + """ + Controls the behavior of the :py:meth:`read` method when audio data is dropped. If this property is false (the default), the :py:meth:`read` method will raise a :py:exc:`RuntimeError` if any audio data is dropped in between calls. If this property is true, the :py:meth:`read` method will return the most recent audio data available, even if some audio data was dropped. + + .. note:: + The :py:attr:`dropped_input_frame_count` property is unaffected by this setting. + + + """ + + @ignore_dropped_input.setter + def ignore_dropped_input(self, arg1: bool) -> None: + """ + Controls the behavior of the :py:meth:`read` method when audio data is dropped. If this property is false (the default), the :py:meth:`read` method will raise a :py:exc:`RuntimeError` if any audio data is dropped in between calls. If this property is true, the :py:meth:`read` method will return the most recent audio data available, even if some audio data was dropped. + + .. note:: + The :py:attr:`dropped_input_frame_count` property is unaffected by this setting. + """ + + @property + def num_input_channels(self) -> int: + """ + The number of input channels on the input device. Will be ``0`` if no input device is connected. + + + """ + + @property + def num_output_channels(self) -> int: + """ + The number of output channels on the output device. Will be ``0`` if no output device is connected. + + """ @property @@ -314,10 +415,20 @@ class AudioStream: @property def running(self) -> bool: """ - :py:const:`True` if this stream is currently streaming live audio from input to output, :py:const:`False` otherwise. + :py:const:`True` if this stream is currently streaming live audio, :py:const:`False` otherwise. + + + """ + + @property + def sample_rate(self) -> float: + """ + The sample rate that this stream is operating at. """ + default_input_device_name = "MacBook Pro Microphone" + default_output_device_name = "MacBook Pro Speakers" input_device_names: typing.List[str] = [] output_device_names: typing.List[str] = [] pass diff --git a/tests/test_audio_stream.py b/tests/test_audio_stream.py index 1ffe90a2..3a5bb7e4 100644 --- a/tests/test_audio_stream.py +++ b/tests/test_audio_stream.py @@ -14,9 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. - import platform +import time +import numpy as np import pytest import pedalboard @@ -46,7 +47,7 @@ def test_create_stream(input_device_name: str, output_device_name: str): ) except Exception as e: if any(substr in str(e) for substr in ACCEPTABLE_ERRORS_ON_CI): - return + raise pytest.skip(str(e)) raise assert stream is not None @@ -67,6 +68,108 @@ def test_create_stream(input_device_name: str, output_device_name: str): assert not stream.running +# Note: this test may do nothing on CI, because we don't have mock audio devices available. +# This will run on macOS and probably Windows as long as at least one audio device is available. +@pytest.mark.skipif(platform.system() == "Linux", reason="AudioStream not supported on Linux yet.") +@pytest.mark.skipif( + pedalboard.io.AudioStream.default_output_device_name == "Null Audio Device", + reason="Tests do not work with a null audio device.", +) +def test_write_to_stream(): + try: + stream = pedalboard.io.AudioStream( + None, pedalboard.io.AudioStream.default_output_device_name + ) + except Exception as e: + if any(substr in str(e) for substr in ACCEPTABLE_ERRORS_ON_CI): + raise pytest.skip(str(e)) + raise + + assert stream is not None + assert not stream.running + with stream: + assert stream.running + stream.write(np.zeros((2, 1024), dtype=np.float32), stream.sample_rate) + assert not stream.running + + +# Note: this test may do nothing on CI, because we don't have mock audio devices available. +# This will run on macOS and probably Windows as long as at least one audio device is available. +@pytest.mark.skipif(platform.system() == "Linux", reason="AudioStream not supported on Linux yet.") +@pytest.mark.skipif( + pedalboard.io.AudioStream.default_output_device_name == "Null Audio Device", + reason="Tests do not work with a null audio device.", +) +def test_write_to_stream_without_opening(): + try: + stream = pedalboard.io.AudioStream( + None, pedalboard.io.AudioStream.default_output_device_name + ) + except Exception as e: + if any(substr in str(e) for substr in ACCEPTABLE_ERRORS_ON_CI): + raise pytest.skip(str(e)) + raise + + assert stream is not None + assert not stream.running + stream.write(np.zeros((2, 1024), dtype=np.float32), stream.sample_rate) + assert not stream.running + assert stream.buffered_input_sample_count is None + + +# Note: this test may do nothing on CI, because we don't have mock audio devices available. +# This will run on macOS and probably Windows as long as at least one audio device is available. +@pytest.mark.skipif(platform.system() == "Linux", reason="AudioStream not supported on Linux yet.") +@pytest.mark.skipif( + pedalboard.io.AudioStream.default_output_device_name == "Null Audio Device", + reason="Tests do not work with a null audio device.", +) +def test_read_from_stream(): + try: + stream = pedalboard.io.AudioStream(pedalboard.io.AudioStream.default_input_device_name) + except Exception as e: + if any(substr in str(e) for substr in ACCEPTABLE_ERRORS_ON_CI): + raise pytest.skip(str(e)) + raise + + assert stream is not None + assert not stream.running + result = stream.read(1) + assert result.shape == (stream.num_input_channels, 1) + assert not stream.running + assert stream.buffered_input_sample_count == 0 + + +# Note: this test may do nothing on CI, because we don't have mock audio devices available. +# This will run on macOS and probably Windows as long as at least one audio device is available. +@pytest.mark.skipif(platform.system() == "Linux", reason="AudioStream not supported on Linux yet.") +@pytest.mark.skipif( + pedalboard.io.AudioStream.default_output_device_name == "Null Audio Device", + reason="Tests do not work with a null audio device.", +) +def test_read_from_stream_measures_dropped_frames(): + try: + stream = pedalboard.io.AudioStream(pedalboard.io.AudioStream.default_input_device_name) + except Exception as e: + if any(substr in str(e) for substr in ACCEPTABLE_ERRORS_ON_CI): + raise pytest.skip(str(e)) + raise + + assert stream is not None + with stream: + assert stream.running + assert stream.dropped_input_frame_count == 0 + time.sleep(5 * stream.buffer_size / stream.sample_rate) + assert stream.buffered_input_sample_count > 0 + dropped_count = stream.dropped_input_frame_count + assert dropped_count > 0 + # The input buffer was cleared on __exit__, so the buffer count should be zero: + assert stream.buffered_input_sample_count == 0 + + # ...but we should still know how many frames were dropped: + assert stream.dropped_input_frame_count == dropped_count + + @pytest.mark.skipif(platform.system() != "Linux", reason="Test platform is not Linux.") def test_create_stream_fails_on_linux(): with pytest.raises(RuntimeError):