### Clone and Install Pedalboard Source: https://github.com/spotify/pedalboard/blob/master/CONTRIBUTING.md Clone the repository with submodules and install the package. Ensure pybind11 and tox are installed first. ```shell git clone --recurse-submodules --shallow-submodules git@github.com:spotify/pedalboard.git cd pedalboard pip3 install pybind11 tox pip3 install . ``` -------------------------------- ### Install pedalboard Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Install the pedalboard package using pip after setting up your virtual environment. ```bash pip install pedalboard ``` -------------------------------- ### 2D MPI FFT Example Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/2d-MPI-example.html This C code demonstrates a 2D FFT using MPI and FFTW. It includes setup, data distribution, FFT computation, and result retrieval. Ensure MPI and FFTW are correctly installed and linked. ```c #include #include #include #include #include #define N 16 #define M 16 int main(int argc, char **argv) { int ntasks, rank; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (ntasks != 2) { if (rank == 0) fprintf(stderr, "Error: This program requires exactly 2 MPI tasks.\n"); MPI_Finalize(); return 1; } fftw_complex *in = NULL, *out = NULL; fftw_plan plan_fwd, plan_bwd; int i, j; /* Allocate memory for input and output arrays */ in = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * N * M); out = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * N * M); /* Initialize input array with some data */ for (i = 0; i < N; ++i) { for (j = 0; j < M; ++j) { in[i * M + j][0] = sin(2.0 * M_PI * i / N) * cos(2.0 * M_PI * j / M); in[i * M + j][1] = 0.0; } } /* Create FFTW plans */ plan_fwd = fftw_plan_dft_2d(N, M, in, out, FFTW_FORWARD, FFTW_ESTIMATE); plan_bwd = fftw_plan_dft_2d(N, M, out, in, FFTW_BACKWARD, FFTW_ESTIMATE); /* Execute forward FFT */ fftw_execute(plan_fwd); /* Print output (optional, for verification) */ if (rank == 0) { printf("Forward FFT Output (Rank 0):\n"); for (i = 0; i < N; ++i) { for (j = 0; j < M; ++j) { printf("%8.3f + %8.3fi ", out[i * M + j][0], out[i * M + j][1]); } printf("\n"); } } /* Execute backward FFT */ fftw_execute(plan_bwd); /* Print input (now containing backward FFT result) */ if (rank == 0) { printf("\nBackward FFT Output (Rank 0, should be close to original input):\n"); for (i = 0; i < N; ++i) { for (j = 0; j < M; ++j) { printf("%8.3f + %8.3fi ", in[i * M + j][0], in[i * M + j][1]); } printf("\n"); } } /* Clean up */ fftw_destroy_plan(plan_fwd); fftw_destroy_plan(plan_bwd); fftw_free(in); fftw_free(out); MPI_Finalize(); return 0; } ``` -------------------------------- ### Install librosa Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Install the librosa package, which is used in the pedalboard interactive demo for loading and analyzing audio files. ```bash pip install librosa ``` -------------------------------- ### Install Matplotlib Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Install the Matplotlib package for data visualization, which is referenced in the pedalboard interactive demo. ```bash pip install matplotlib ``` -------------------------------- ### 2D Real-to-Real MPI Transform Plan Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Other-Multi_002ddimensional-Real_002ddata-MPI-Transforms.html This example demonstrates creating a plan for a two-dimensional REDFT10 (DCT-II) in the first dimension and an RODFT10 (DST-II) in the second dimension using FFTW's MPI interface. It shows how to get the local data size, allocate memory for real data, and create the plan with specified transform kinds. ```c const ptrdiff_t L = ..., M = ...; fftw_plan plan; double *data; ptrdiff_t alloc_local, local_n0, local_0_start, i, j; /* get local data size and allocate */ alloc_local = fftw_mpi_local_size_2d(L, M, MPI_COMM_WORLD, &local_n0, &local_0_start); data = fftw_alloc_real(alloc_local); /* create plan for in-place REDFT10 x RODFT10 */ plan = fftw_mpi_plan_r2r_2d(L, M, data, data, MPI_COMM_WORLD, FFTW_REDFT10, FFTW_RODFT10, FFTW_MEASURE); /* initialize data to some function my_function(x,y) */ for (i = 0; i < local_n0; ++i) for (j = 0; j < M; ++j) data[i*M + j] = my_function(local_0_start + i, j); /* compute transforms, in-place, as many times as desired */ fftw_execute(plan); fftw_destroy_plan(plan); ``` -------------------------------- ### Install FFTW3 Header Files Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/CMakeLists.txt Installs the main FFTW3 header file to the include directory. This makes the library's API accessible to users. ```cmake install (FILES api/fftw3.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) ``` -------------------------------- ### Run Tests with Tox Source: https://github.com/spotify/pedalboard/blob/master/CONTRIBUTING.md Install tox and run all tests using the tox testing framework. ```shell pip3 install tox tox ``` -------------------------------- ### Install FFTW3 Main Library Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/CMakeLists.txt Installs the main FFTW3 library target, including its export configuration for dependencies. This makes the library available for other projects to link against. ```cmake install(TARGETS ${fftw3_lib} EXPORT FFTW3LibraryDepends RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ``` -------------------------------- ### Quick start audio processing with Pedalboard Source: https://github.com/spotify/pedalboard/blob/master/README.md Demonstrates basic audio processing by creating a Pedalboard with Chorus and Reverb effects, reading audio in chunks, applying effects, and writing to an output file. Ensure 'some-file.wav' exists and is readable. ```python from pedalboard import Pedalboard, Chorus, Reverb from pedalboard.io import AudioFile # Make a Pedalboard object, containing multiple audio plugins: board = Pedalboard([Chorus(), Reverb(room_size=0.25)]) # Open an audio file for reading, just like a regular file: with AudioFile('some-file.wav') as f: # Open an audio file to write to: with AudioFile('output.wav', 'w', f.samplerate, f.num_channels) as o: # Read one second of audio at a time, until the file is empty: while f.tell() < f.frames: chunk = f.read(f.samplerate) # Run the audio through our pedalboard: effected = board(chunk, f.samplerate, reset=False) # Write the output to our output file: o.write(effected) ``` -------------------------------- ### Install FFTW3 Fortran Header Files Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/CMakeLists.txt Conditionally installs FFTW3 Fortran header files if they exist. This supports users who need to interface with FFTW3 from Fortran. ```cmake if (EXISTS ${CMAKE_SOURCE_DIR}/api/fftw3.f) install (FILES api/fftw3.f api/fftw3l.f03 api/fftw3q.f03 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) ``` -------------------------------- ### Install NumPy Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Install the NumPy package, a required dependency for pedalboard that handles mathematical operations on data. ```bash pip install numpy ``` -------------------------------- ### Example Custom OpenMP Callback Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Usage-of-Multi_002dthreaded-FFTW.html An example of a custom threading callback using OpenMP. ```APIDOC void parallel_loop(void *(*work)(char *), char *jobdata, size_t elsize, int njobs, void *data) { #pragma omp parallel for for (int i = 0; i < njobs; ++i) work(jobdata + elsize * i); } // To use this callback: // fftw_threads_set_callback(parallel_loop, NULL); ``` -------------------------------- ### Generate and Install FFTW3 Fortran 03 Header Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/CMakeLists.txt Generates the `fftw3.f03` Fortran header file from a template and installs it. This is done to ensure the header is correctly formatted and includes necessary parameters. ```cmake if (EXISTS ${CMAKE_SOURCE_DIR}/api/fftw3.f03.in) file (READ api/fftw3.f03.in FFTW3_F03_IN OFFSET 42) file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/fftw3.f03 "! Generated automatically. DO NOT EDIT!\n\n") file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/fftw3.f03 " integer, parameter :: C_FFTW_R2R_KIND = ${C_FFTW_R2R_KIND}\n\n") file (APPEND ${CMAKE_CURRENT_BINARY_DIR}/fftw3.f03 "${FFTW3_F03_IN}") install (FILES ${CMAKE_CURRENT_BINARY_DIR}/fftw3.f03 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) ``` -------------------------------- ### Set FFTW3 Target Properties and Install Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/CMakeLists.txt Sets the SOVERSION and VERSION for FFTW3 subtargets and installs them to their respective destinations. This ensures proper versioning and installation paths. ```cmake set_target_properties (${subtarget} PROPERTIES SOVERSION 3.6.9 VERSION 3) install (TARGETS ${subtarget} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ``` -------------------------------- ### Pyodide Initialization and Console Setup Source: https://github.com/spotify/pedalboard/blob/master/docs/source/_static/demo/index.html Initializes Pyodide and sets up the console for interactive use. It configures stdout/stderr callbacks and handles fatal errors, providing a robust environment for running Python code in the browser. ```javascript const pyconsole = PyodideConsole(pyodide.globals); const namespace = pyodide.globals.get("dict")(); const await_fut = pyodide.runPython( ` import builtins from pyodide.ffi import to_js async def await_fut(fut): res = await fut if res is not None: builtins._ = res return to_js([res], depth=1) await_fut `, { globals: namespace } ); namespace.destroy(); pyconsole.stdout_callback = (s) => echo(s, { newline: false }); pyconsole.stderr_callback = (s) => { term.error(s.trimEnd()); }; term.ready = Promise.resolve(); pyodide._api.on_fatal = async (e) => { if (e.name === "Exit") { term.error(e); term.error("Pyodide exited and can no longer be used."); } else { term.error( "Pyodide has suffered a fatal error. Please report this to the Pyodide maintainers." ); term.error("The cause of the fatal error was:"); term.error(e); term.error("Look in the browser console for more details."); } await term.ready; term.pause(); await sleep(15); term.pause(); }; const searchParams = new URLSearchParams(window.location.search); if (searchParams.has("noblink")) { $(".cmd-cursor").addClass("noblink"); } // Check if we're on mobile (width < 768px) const isMobile = window.innerWidth < 768; if (isMobile) { // Show the initial imports to the user echo("import numpy as np"); echo("from pedalboard import *"); echo("from pedalboard.io import *"); echo(""); echo("Welcome to the Pedalboard REPL!"); echo("> Type the variable name of any NumPy array to play it."); echo("> See documentation at spotify.github.io/pedalboard.", {raw: true}); echo(""); } else { // Show the initial imports to the user echo("import numpy"); } ``` -------------------------------- ### Example OpenMP Parallel Loop Callback Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Usage-of-Multi_002dthreaded-FFTW.html An example callback function demonstrating how to use OpenMP for parallel execution of FFTW work items. The `work` function is called for each job. ```c void parallel_loop(void *(*work)(char *), char *jobdata, size_t elsize, int njobs, void *data) { #pragma omp parallel for for (int i = 0; i < njobs; ++i) work(jobdata + elsize * i); } ``` -------------------------------- ### FFTW Fortran Example Usage Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Overview-of-Fortran-interface.html Demonstrates creating a 2D DFT plan, executing it, and destroying the plan using FFTW's Fortran 2003 interface. Note the reversed dimension order for plan creation. ```fortran type(C_PTR) :: plan complex(C_DOUBLE_COMPLEX), dimension(1024,1000) :: in, out plan = fftw_plan_dft_2d(1000,1024, in,out, FFTW_FORWARD,FFTW_ESTIMATE) ... call fftw_execute_dft(plan, in, out) ... call fftw_destroy_plan(plan) ``` -------------------------------- ### Plan multiple 2D DFTs (contiguous) Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Advanced-Complex-DFTs.html Example of planning a single 2D DFT of a 5x6 array that is contiguous in memory. The `howmany` parameter is 1, and `istride`/`ostride` are 1. ```c int rank = 2; int n[] = {5, 6}; int howmany = 1; int idist = odist = 0; /* unused because howmany = 1 */ int istride = ostride = 1; /* array is contiguous in memory */ int *inembed = n, *onembed = n; ``` -------------------------------- ### Check Pip Version Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Verify that pip is installed and check its current version. ```bash python3 -m pip --version ``` -------------------------------- ### Plan multiple 2D DFTs (non-contiguous) Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Advanced-Complex-DFTs.html Example of planning DFTs for three 5x6 arrays stored sequentially in memory. The `howmany` is 3, and `idist`/`odist` are set to the total size of one array to separate them. ```c int rank = 2; int n[] = {5, 6}; int howmany = 3; int idist = odist = n[0]*n[1]; /* = 30, the distance in memory between the first element of the first array and the first element of the second array */ int istride = ostride = 1; /* array is contiguous in memory */ int *inembed = n, *onembed = n; ``` -------------------------------- ### Configure pkgconfig file for FFTW3 Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/CMakeLists.txt Configures the pkgconfig file for FFTW3, setting installation paths and version information. This is used by other projects to find and link against the FFTW3 library. ```cmake set (prefix ${CMAKE_INSTALL_PREFIX}) set (exec_prefix ${CMAKE_INSTALL_PREFIX}) set (libdir ${CMAKE_INSTALL_FULL_LIBDIR}) set (includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) set (VERSION ${FFTW_VERSION}) configure_file (fftw.pc.in fftw3${PREC_SUFFIX}.pc @ONLY) install (FILES ${CMAKE_CURRENT_BINARY_DIR}/fftw3${PREC_SUFFIX}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT Development) ``` -------------------------------- ### Create and Use a Pedalboard Source: https://github.com/spotify/pedalboard/blob/master/docs/source/reference/pedalboard.rst Demonstrates creating an empty Pedalboard, appending effect plugins like Chorus, Distortion, and Reverb, and then passing audio through the configured pedalboard. Requires importing necessary classes from the pedalboard library. ```python from pedalboard import Pedalboard, Chorus, Distortion, Reverb # Create an empty Pedalboard object: my_pedalboard = Pedalboard() # Treat this object like a Python list: my_pedalboard.append(Chorus()) my_pedalboard.append(Distortion()) my_pedalboard.append(Reverb()) # Pass audio through this pedalboard: output_audio = my_pedalboard(input_audio, input_audio_samplerate) ``` -------------------------------- ### Get local size for 3D transposed data - C Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Transposed-distributions.html Use this function to get the local data distribution for a 3D transform with transposed output or input. It returns the size and starting index for both non-transposed and transposed dimensions. ```c ptrdiff_t fftw_mpi_local_size_3d_transposed( ptrdiff_t n0, ptrdiff_t n1, ptrdiff_t n2, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start); ``` -------------------------------- ### Get Local Size for 1D MPI Transforms Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/MPI-Data-Distribution-Functions.html This function is for one-dimensional complex DFT MPI transforms. It calculates the local input and output sizes and starting positions, considering sign and flags. ```c ptrdiff_t fftw_mpi_local_size_1d( ptrdiff_t n0, MPI_Comm comm, int sign, unsigned flags, ptrdiff_t *local_ni, ptrdiff_t *local_i_start, ptrdiff_t *local_no, ptrdiff_t *local_o_start); ``` -------------------------------- ### Get Local Size for Many 1D MPI Transforms Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/MPI-Data-Distribution-Functions.html Use this function for one-dimensional MPI transforms involving multiple contiguous tuples ('howmany'). It calculates local input and output sizes and starting positions, considering sign and flags. ```c ptrdiff_t fftw_mpi_local_size_many_1d( ptrdiff_t n0, ptrdiff_t howmany, MPI_Comm comm, int sign, unsigned flags, ptrdiff_t *local_ni, ptrdiff_t *local_i_start, ptrdiff_t *local_no, ptrdiff_t *local_o_start); ``` -------------------------------- ### Get Local Size for 2D DFT (Basic) Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Basic-and-advanced-distribution-interfaces.html Use this function to determine the local data dimensions and starting index for a 2D complex DFT. It calculates the shape of the local data slice and the total number of elements to allocate for the current MPI process. ```c ptrdiff_t fftw_mpi_local_size_2d(ptrdiff_t n0, ptrdiff_t n1, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start); ``` -------------------------------- ### Load and Use VST3/AU Plugins with Pedalboard Source: https://github.com/spotify/pedalboard/blob/master/README.md Shows how to load VST3 or Audio Unit plugins using `load_plugin`, inspect their parameters, modify them, and use them in a Pedalboard chain. This example also demonstrates rendering audio by passing MIDI messages to an instrument plugin. ```python from pedalboard import Pedalboard, Reverb, load_plugin from pedalboard.io import AudioFile from mido import Message # not part of Pedalboard, but convenient! # Load a VST3 or Audio Unit plugin from a known path on disk: instrument = load_plugin("./VSTs/Magical8BitPlug2.vst3") effect = load_plugin("./VSTs/RoughRider3.vst3") print(effect.parameters.keys()) # dict_keys([ # 'sc_hpf_hz', 'input_lvl_db', 'sensitivity_db', # 'ratio', 'attack_ms', 'release_ms', 'makeup_db', # 'mix', 'output_lvl_db', 'sc_active', # 'full_bandwidth', 'bypass', 'program', # ]) # Set the "ratio" parameter to 15 effect.ratio = 15 # Render some audio by passing MIDI to an instrument: sample_rate = 44100 audio = instrument( [Message("note_on", note=60), Message("note_off", note=60, time=5)], duration=5, # seconds sample_rate=sample_rate, ) # Apply effects to this audio: effected = effect(audio, sample_rate) # ...or put the effect into a chain with other plugins: board = Pedalboard([effect, Reverb()]) # ...and run that pedalboard with the same VST instance! ``` -------------------------------- ### Create and Modify a Guitar Pedalboard Source: https://github.com/spotify/pedalboard/blob/master/README.md Demonstrates how to initialize a Pedalboard with multiple audio effects, add new plugins, and modify existing plugin parameters. The processed audio can then be saved to a file. ```python board = Pedalboard([ Compressor(threshold_db=-50, ratio=25), Gain(gain_db=30), Chorus(), LadderFilter(mode=LadderFilter.Mode.HPF12, cutoff_hz=900), Phaser(), Convolution("./guitar_amp.wav", 1.0), Reverb(room_size=0.25), ]) # Pedalboard objects behave like lists, so you can add plugins: board.append(Compressor(threshold_db=-25, ratio=10)) board.append(Gain(gain_db=10)) board.append(Limiter()) # ... or change parameters easily: board[0].threshold_db = -40 # Run the audio through this pedalboard! effected = board(audio, samplerate) # Write the audio back as a wav file: with AudioFile('processed-output.wav', 'w', samplerate, effected.shape[0]) as f: f.write(effected) ``` -------------------------------- ### Get Local Size for Multi-Dimensional DFT (Advanced) Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Basic-and-advanced-distribution-interfaces.html This advanced function allows specifying block size and handling multiple interleaved transforms for multi-dimensional DFTs. It returns the local data dimensions, starting index, and total elements to allocate, offering more control than the basic interface. ```c ptrdiff_t fftw_mpi_local_size_many(int rnk, const ptrdiff_t *n, ptrdiff_t howmany, ptrdiff_t block0, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start); ``` -------------------------------- ### Install and Update Pip Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Ensure pip is installed and up-to-date before installing packages. This command installs or upgrades pip to the latest version. ```bash python3 -m pip install --user --upgrade pip ``` -------------------------------- ### Initialize Pedalboard Environment Source: https://github.com/spotify/pedalboard/blob/master/docs/source/_static/demo/index.html Sets up the Python environment for Pedalboard, including importing necessary libraries and initializing the interactive terminal. This code should be run once to prepare the environment. ```javascript async function main() { try { // Initialize Pyodide and the terminal window.term = await loadPyodide(); // Load necessary Python packages await window.term.loadPackage('micropip'); const micropip = window.term.globals.get('micropip'); await micropip.install( 'numpy', 'pedalboard', 'soundfile' ); // Run Python code to set up the environment window.term.runPython(` import sys import numpy as np from pedalboard import * from pedalboard.io import * print("Welcome to the Pedalboard interactive Python environment!") print("> Drag any audio file (.wav, .mp3, .ogg, .flac, or .aiff) onto the page to load it.") print("> Call download() on any byte array to download it as a file.") print("> Type the variable name of any NumPy array to play it as audio in the browser.") print("> See spotify.github.io/pedalboard for documentation.", {raw: true}) print("") `); // Add handler to focus terminal when clicking on body document.body.addEventListener('click', function(e) { // Only handle clicks directly on the body if (e.target === document.body) { // Focus the terminal term.focus(); } }); // Hide the loading spinner once initialization is complete document.getElementById('loading').remove(); } catch (e) { console.error("Error initializing terminal:", e); window.term.error("Error initializing terminal:", e); // Hide the loading spinner once initialization is complete document.getElementById('loading').remove(); } } // File system management async function setupFileSystem() { const dropArea = document.getElementById('terminal-container'); // Prevent default drag behaviors ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { dropArea.addEventListener(eventName, preventDefaults, false); document.body.addEventListener(eventName, preventDefaults, false); }); // Highlight drop area when dragging over it ['dragenter', 'dragover'].forEach(eventName => { dropArea.addEventListener(eventName, highlight, false); }); ['dragleave', 'drop'].forEach(eventName => { dropArea.addEventListener(eventName, unhighlight, false); }); // Handle dropped files dropArea.addEventListener('drop', handleDrop, false); // Load existing files from IndexedDB // loadFilesFromStorage(); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } function highlight() { dropArea.classList.add('highlight'); } function unhighlight() { dropArea.classList.remove('highlight'); } async function handleDrop(e) { const dt = e.dataTransfer; const files = dt.files; for (let i = 0; i < files.length; i++) { await addFileToSystem(files[i]); } } function chooseFriendlyPythonVariableName() { // Label each dropped file with a friendly name: // - if there isn't a global variable called "f", use that first // - otherwise, use "f", "f2", etc. let i = 0; let candidate = "f"; while (pyodide.runPython(`"${candidate}" in locals()`)) { i++; candidate = `f${i}`; } return candidate; } async function addFileToSystem(file) { try { // Create a file entry in Pyodide's virtual filesystem const content = await file.arrayBuffer(); const uint8Content = new Uint8Array(content); // Create necessary directories one by one to ensure they exist try { if (!pyodide.FS.analyzePath('/home').exists) { pyodide.FS.mkdir('/home'); } if (!pyodide.FS.analyzePath('/home/pyodide').exists) { pyodide.FS.mkdir('/home/pyodide'); } } catch (e) { console.error('Error creating directories:', e); } // Write the file to the Pyodide filesystem pyodide.FS.writeFile(`/home/pyodide/${file.name}`, uint8Content); // Assign a new variable with this file's name to an AudioFile object if possible: const pythonIdentifier = chooseFriendlyPythonVariableName(); pyodide.runPython(` try: ${pythonIdentifier} = AudioFile("${file.name}") print(f"${pythonIdentifier} = {${pythonIdentifier}!r}") except Exception as e: sys.stderr.write(f"Could not read \\"${file.name}\\" as an AudioFile object:\\n\\t{e}\\n") `); } catch (error) { console.error('Error adding file:', error); window.term.error(`Failed to add file: ${file.name}`); } } } window.console_ready = main(); ``` -------------------------------- ### MPI 3D Real-to-Complex DFT Example Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Multi_002ddimensional-MPI-DFTs-of-Real-Data.html Demonstrates setting up and executing an out-of-place 3D real-to-complex DFT using FFTW's MPI interface. Ensure MPI and FFTW MPI are initialized, and data sizes are correctly calculated for distributed memory. ```c #include int main(int argc, char **argv) { const ptrdiff_t L = ..., M = ..., N = ...; fftw_plan plan; double *rin; fftw_complex *cout; ptrdiff_t alloc_local, local_n0, local_0_start, i, j, k; MPI_Init(&argc, &argv); fftw_mpi_init(); /* get local data size and allocate */ alloc_local = fftw_mpi_local_size_3d(L, M, N/2+1, MPI_COMM_WORLD, &local_n0, &local_0_start); rin = fftw_alloc_real(2 * alloc_local); cout = fftw_alloc_complex(alloc_local); /* create plan for out-of-place r2c DFT */ plan = fftw_mpi_plan_dft_r2c_3d(L, M, N, rin, cout, MPI_COMM_WORLD, FFTW_MEASURE); /* initialize rin to some function my_func(x,y,z) */ for (i = 0; i < local_n0; ++i) for (j = 0; j < M; ++j) for (k = 0; k < N; ++k) rin[(i*M + j) * (2*(N/2+1)) + k] = my_func(local_0_start+i, j, k); /* compute transforms as many times as desired */ fftw_execute(plan); fftw_destroy_plan(plan); MPI_Finalize(); } ``` -------------------------------- ### Reading Audio File Metadata and Data with AudioFile Source: https://github.com/spotify/pedalboard/blob/master/docs/source/reference/pedalboard.io.rst Demonstrates how to open an audio file, access its metadata (duration, samplerate, number of channels), and read a portion of its audio data. Requires importing AudioFile from pedalboard.io. ```python from pedalboard.io import AudioFile with AudioFile("my_filename.mp3") as f: print(f.duration) # => 30.0 print(f.samplerate) # => 44100 print(f.num_channels) # => 2 print(f.read(f.samplerate * 10)) # => returns a NumPy array of shape (2, 441_000): # [[ 0. 0. 0. ... -0. -0. -0.] # [ 0. 0. 0. ... -0. -0. -0.]] ``` -------------------------------- ### Create and Activate Virtual Environment Source: https://github.com/spotify/pedalboard/blob/master/INSTALLATION.md Use these commands to create a virtual environment for your project and activate it. This isolates project dependencies. ```bash python3 -m pip install --user virtualenv python3 -m venv .venv source .venv/bin/activate ``` -------------------------------- ### Generate Type Stubs and Docs Source: https://github.com/spotify/pedalboard/blob/master/pedalboard_native/README.md Run this command to automatically update the type hints and documentation for Pedalboard's native C++ bindings. ```bash python3 -m scripts.generate_type_stubs_and_docs ``` -------------------------------- ### Import FFTW Wisdom from File Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Words-of-Wisdom_002dSaving-Plans.html Restores FFTW wisdom from a specified file. Returns non-zero on success. Wisdom is automatically used for applicable sizes if planner flags are not more 'patient' than those used during wisdom creation. ```c int fftw_import_wisdom_from_filename(const char *filename); ``` -------------------------------- ### Initialize Git Submodules Source: https://github.com/spotify/pedalboard/blob/master/CONTRIBUTING.md Run this command to ensure all Git submodules are updated. This can resolve `fatal error: lame/include/lame.h: No such file or directory`. ```shell git submodule update --init ``` -------------------------------- ### Get Current Planner Thread Count Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Usage-of-Multi_002dthreaded-FFTW.html Retrieve the number of threads the planner is currently configured to use. ```APIDOC int fftw_planner_nthreads(void); Returns the current number of threads available to the planner. ``` -------------------------------- ### Initialize Pyodide Terminal Source: https://github.com/spotify/pedalboard/blob/master/docs/source/_static/demo/index.html Sets up the Pyodide environment and a terminal interface for interacting with Python code. It loads Pedalboard using micropip and configures input/output streams. ```javascript const { loadPyodide } = await import(indexURL + "pyodide.mjs"); // to facilitate debugging globalThis.loadPyodide = loadPyodide; let term; term = $("#terminal-container").terminal(interpreter, { greetings: "", prompt: ps1, completionEscape: false, completion: function (command, callback) { callback(pyconsole.complete(command).toJs()[0]); }, keymap: { "CTRL+C": async function (event, original) { pyconsole.buffer.clear(); term.enter(); echo("KeyboardInterrupt"); term.set_command(""); term.set_prompt(ps1); }, TAB: (event, original) => { const command = term.before_cursor(); // Disable completion for whitespaces. if (command.trim() === "") { term.insert("\t"); return false; } return original(event); }, "META+K": (event, original) => { term.clear(); return false; }, }, }); window.term = term; $.terminal.syntax('python') echo("Loading Pedalboard in-browser Python environment...", {raw: true}); globalThis.pyodide = await loadPyodide({ stdin: () => { let result = prompt(); echo(result); return result; }, }); pyodide.setStdout({ batched: (msg) => term.echo(msg) }); pyodide.setStderr({ batched: (msg) => term.error(msg) }); let { repr_shorten, BANNER, PyodideConsole } = pyodide.pyimport("pyodide.console"); let micropip; try { await pyodide.loadPackage("micropip"); micropip = pyodide.pyimport("micropip"); } catch (e) { echo("Error loading micropip: " + e.toString()); } // Get the path to the example file; should be in the same directory as the index.html file: const root = window.location.href.split("index.html")[0]; // TODO(psobot): Can we deploy this to some CDN ourselves? const absolutePath = root + "pedalboard-0.9.17-cp312-cp312-pyodide_2024_0_wasm32.whl"; try { await micropip.install(absolutePath); } catch (e) { console.error("Error installing pedalboard:"); echo("Error installing pedalboard: " + e.toString()); throw e; } // Set up the drag-and-drop file system setupFileSystem(); const path = root + "example_file.mp3"; fetch(path) .then(response => response.arrayBuffer()) .then(buffer => { const uint8Content = new Uint8Array(buffer); pyodide.FS.writeFile("/home/pyodide/example_file.mp3", uint8Content); const isMobile = window.innerWidth < 76 ``` -------------------------------- ### Get Current Planner Thread Count Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Usage-of-Multi_002dthreaded-FFTW.html Retrieves the number of threads the planner is currently configured to use. ```c int fftw_planner_nthreads(void); ``` -------------------------------- ### Upgrade Pip Source: https://github.com/spotify/pedalboard/blob/master/CONTRIBUTING.md Use this command to update your pip installation. This can resolve `ModuleNotFoundError: No module named 'pybind11'` issues. ```shell pip install --upgrade pip ``` -------------------------------- ### Get Current Planner Thread Count in Fortran Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Fortran-Examples.html Retrieves the number of threads currently being used by the FFTW planner. ```Fortran integer iret call dfftw_planner_nthreads(iret) ``` -------------------------------- ### Getting Operation Counts Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Using-Plans.html Calculates the exact number of floating-point additions, multiplications, and fused multiply-add operations for a given plan. ```APIDOC ## fftw_flops ### Description Given an FFTW plan, this function calculates and sets the exact counts of floating-point additions, multiplications, and fused multiply-add (FMA) operations involved in the plan's execution. ### Method `void fftw_flops(const fftw_plan plan, double *add, double *mul, double *fma);` ### Parameters * **plan** (`const fftw_plan`) - The plan to analyze. * **add** (`double *`) - Pointer to a double where the count of additions will be stored. * **mul** (`double *`) - Pointer to a double where the count of multiplications will be stored. * **fma** (`double *`) - Pointer to a double where the count of fused multiply-add operations will be stored. ``` -------------------------------- ### Build Debug Version with Ccache (macOS) Source: https://github.com/spotify/pedalboard/blob/master/CONTRIBUTING.md Compile a debug build faster on macOS using Ccache. Installs the package in editable mode. ```shell brew install ccache rm -rf build && CC="ccache clang" CXX="ccache clang++" DEBUG=1 python3 -j8 -m pip install -e . ``` -------------------------------- ### Importing Wisdom from a File Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Words-of-Wisdom_002dSaving-Plans.html Loads FFTW wisdom from a specified file. This wisdom can then be used by the planner to reconstruct plans. Returns non-zero on success. ```APIDOC ## fftw_import_wisdom_from_filename ### Description Imports FFTW wisdom from a file. The imported wisdom is added to the internal wisdom database and can be used by the FFTW planner to reconstruct previously computed plans. ### Function Signature ```c int fftw_import_wisdom_from_filename(const char *filename); ``` ### Parameters * **filename** (const char *) - The name of the file from which to import the wisdom. ### Return Value Returns non-zero on success, and zero on failure. ``` -------------------------------- ### Enable SSE Intrinsics for x86-64 Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/FAQ/fftw-faq.html/section2.html For x86-64 machines, use the `--enable-sse` flag during configuration to leverage SSE instructions for performance. This is recommended over `--enable-k7` on these architectures. ```bash --enable-sse ``` -------------------------------- ### One-Dimensional Transforms Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/MPI-Data-Distribution-Functions.html Routines specifically for one-dimensional transforms (currently complex DFTs), providing local size and start information for both input and output. ```APIDOC ## fftw_mpi_local_size_1d ### Description Calculates the local size and starting index for a 1D transform, including input and output details. ### Signature ```c ptrdiff_t fftw_mpi_local_size_1d( ptrdiff_t n0, MPI_Comm comm, int sign, unsigned flags, ptrdiff_t *local_ni, ptrdiff_t *local_i_start, ptrdiff_t *local_no, ptrdiff_t *local_o_start); ``` ## fftw_mpi_local_size_many_1d ### Description Calculates the local size and starting index for a 1D transform with a 'howmany' parameter, including input and output details. ### Signature ```c ptrdiff_t fftw_mpi_local_size_many_1d( ptrdiff_t n0, ptrdiff_t howmany, MPI_Comm comm, int sign, unsigned flags, ptrdiff_t *local_ni, ptrdiff_t *local_i_start, ptrdiff_t *local_no, ptrdiff_t *local_o_start); ``` ``` -------------------------------- ### Basic FFTW 1D DFT Usage Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/Complex-One_002dDimensional-DFTs.html This snippet demonstrates the fundamental steps for performing a one-dimensional DFT using FFTW. It includes memory allocation, plan creation, execution, and deallocation. Ensure you link with the fftw3 library. ```c #include ... { fftw_complex *in, *out; fftw_plan p; ... in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N); p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE); ... fftw_execute(p); /* repeat as needed */ ... fftw_destroy_plan(p); fftw_free(in); fftw_free(out); } ``` -------------------------------- ### Build Debug Version Source: https://github.com/spotify/pedalboard/blob/master/CONTRIBUTING.md Build a debug version of Pedalboard for use with debuggers like gdb or lldb. This installs a symbolic link for local development. ```shell python3 setup.py build develop ``` -------------------------------- ### Transposed Multidimensional Transforms Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/MPI-Data-Distribution-Functions.html Variants of the basic functions for calculating local sizes and starting indices for transposed multidimensional transforms, useful for FFTW_MPI_TRANSPOSED_OUT plans. ```APIDOC ## fftw_mpi_local_size_2d_transposed ### Description Calculates the local size and starting index for a 2D transposed transform. ### Signature ```c ptrdiff_t fftw_mpi_local_size_2d_transposed(ptrdiff_t n0, ptrdiff_t n1, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start); ``` ## fftw_mpi_local_size_3d_transposed ### Description Calculates the local size and starting index for a 3D transposed transform. ### Signature ```c ptrdiff_t fftw_mpi_local_size_3d_transposed(ptrdiff_t n0, ptrdiff_t n1, ptrdiff_t n2, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start); ``` ## fftw_mpi_local_size_transposed ### Description Calculates the local size and starting index for a general N-dimensional transposed transform. ### Signature ```c ptrdiff_t fftw_mpi_local_size_transposed(int rnk, const ptrdiff_t *n, MPI_Comm comm, ptrdiff_t *local_n0, ptrdiff_t *local_0_start, ptrdiff_t *local_n1, ptrdiff_t *local_1_start); ``` ``` -------------------------------- ### Import Wisdom and Broadcast in MPI Source: https://github.com/spotify/pedalboard/blob/master/vendors/fftw3/doc/html/FFTW-MPI-Wisdom.html Imports wisdom from a file on process 0 and then broadcasts it to all other processes in the communicator. Ensure fftw_mpi_init is called before importing MPI plans. ```c int rank; fftw_mpi_init(); MPI_Comm_rank(MPI_COMM_WORLD, &rank); if (rank == 0) fftw_import_wisdom_from_filename("mywisdom"); fftw_mpi_broadcast_wisdom(MPI_COMM_WORLD); ```