Cross-platform audio I/O library in pure Rust

Overview

CPAL - Cross-Platform Audio Library

Actions Status Crates.io docs.rs

Low-level library for audio input and output in pure Rust.

This library currently supports the following:

  • Enumerate supported audio hosts.
  • Enumerate all available audio devices.
  • Get the current default input and output devices.
  • Enumerate known supported input and output stream formats for a device.
  • Get the current default input and output stream formats for a device.
  • Build and run input and output PCM streams on a chosen device with a given stream format.

Currently supported hosts include:

  • Linux (via ALSA)
  • Windows (via WASAPI by default, see ASIO instructions below)
  • macOS (via CoreAudio)
  • iOS (via CoreAudio)
  • Android (via Oboe)
  • Emscripten

Note that on Linux, the ALSA development files are required. These are provided as part of the libasound2-dev package on Debian and Ubuntu distributions and alsa-lib-devel on Fedora.

Compiling for Web Assembly

If you are interested in using CPAL with WASM, please see this guide in our Wiki which walks through setting up a new project from scratch.

ASIO on Windows

ASIO is an audio driver protocol by Steinberg. While it is available on multiple operating systems, it is most commonly used on Windows to work around limitations of WASAPI including access to large numbers of channels and lower-latency audio processing.

CPAL allows for using the ASIO SDK as the audio host on Windows instead of WASAPI. To do so, follow these steps:

  1. Download the ASIO SDK .zip from this link. The version as of writing this is 2.3.1.

  2. Extract the files and place the directory somewhere you are happy for it to stay (e.g. ~/.asio).

  3. Assign the full path of the directory (that contains the readme, changes, ASIO SDK 2.3 pdf, etc) to the CPAL_ASIO_DIR environment variable. This is necessary for the asio-sys build script to build and bind to the SDK.

  4. bindgen, the library used to generate bindings to the C++ SDK, requires clang. Download and install LLVM from here under the "Pre-Built Binaries" section. The version as of writing this is 7.0.0.

  5. Add the LLVM bin directory to a LIBCLANG_PATH environment variable. If you installed LLVM to the default directory, this should work in the command prompt:

    setx LIBCLANG_PATH "C:\Program Files\LLVM\bin"
    
  6. If you don't have any ASIO devices or drivers available, you can download and install ASIO4ALL. Be sure to enable the "offline" feature during installation despite what the installer says about it being useless.

  7. Loading VCVARS. rust-bindgen uses the C++ tool-chain when generating bindings to the ASIO SDK. As a result, it is necessary to load some environment variables in the command prompt that we use to build our project. On 64-bit machines run:

    "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
    

    On 32-bit machines run:

    "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
    

    Note that, depending on your version of Visual Studio, this script might be in a slightly different location.

  8. Select the ASIO host at the start of our program with the following code:

    let host;
    #[cfg(target_os = "windows")]
    {
        host = cpal::host_from_id(cpal::HostId::Asio).expect("failed to initialise ASIO host");
    }

    If you run into compilations errors produced by asio-sys or bindgen, make sure that CPAL_ASIO_DIR is set correctly and try cargo clean.

  9. Make sure to enable the asio feature when building CPAL:

    cargo build --features "asio"
    

    or if you are using CPAL as a dependency in a downstream project, enable the feature like this:

    cpal = { version = "*", features = ["asio"] }

In the future we would like to work on automating this process to make it easier, but we are not familiar enough with the ASIO license to do so yet.

Updated as of ASIO version 2.3.3.

Comments
  • JACK Host

    JACK Host

    Pull request to track the JACK Host implementation.

    Major TODOs:

    • [x] Store the data callback in the LocalProcessHandler for invocation from the audio thread
    • [x] Process data from input ports
    • [x] Accurately report if JACK is available
    • [x] Use the error callback
    • [x] Implement listing devices
    • [x] Remove Arc Mutex wrapper around process callback when Sync requirement removal PR is merged in rust-jack (see https://github.com/RustAudio/rust-jack/pull/127)
    opened by ErikNatanael 33
  • Getting rid of the EventLoop

    Getting rid of the EventLoop

    More and more platforms are running audio with synchronous callback in a high-priority thread. That means that thread management should happen inside cpal, not in user code.

    The blocking design of EventLoop should be replaced by some interface of registering callback. What's unfortunate is that we would need not only Send but also the 'static bound on the callback if it's implemented naively. Do we have anything more Rust-ic than callbacks (which is C-ish and often messy)?

    It's obvious that we need different callbacks for different Hosts (assuming it get implemented), but should we support driving multiple streams with the same callback?

    opened by ishitatsuyuki 29
  • Getting rid of the EventLoop

    Getting rid of the EventLoop

    Close #278. I rushed for a buildable version so you can see it, there's still a lot of thing to do.

    • [ ] Check for can_pause and optionally return an error
    • [ ] Polymorphic struct versions of Traits will be explicitly !Sync, !Send
    • [x] Take an additional error callback as described in https://github.com/tomaka/cpal/issues/268#issuecomment-508905225
    • [ ] Update documentation
    • [ ] Checkbox for ASIO backend so I don't miss it because it's without CI
    opened by ishitatsuyuki 25
  • Don't fail if CoInitializeEx returns RPC_E_CHANGED_MODE. It's OK.

    Don't fail if CoInitializeEx returns RPC_E_CHANGED_MODE. It's OK.

    As far as I can tell, cpal relies on no way on the COM mode being COINIT_MULTITHREADED.

    So let's survive even if COM was already initialized in apartment-threaded mode (there is no such thing as single-threaded mode).

    opened by hrydgard 23
  • Add ASIO Host for Windows (rebase and refactor of #221)

    Add ASIO Host for Windows (rebase and refactor of #221)

    The refactor includes:

    • The removal of most global state.
    • Uses RAII for cleaner management of state transitions.
    • Removes the hefty macros throughout the asio implementation.
    • Adapts to the newly introduced Host API.

    Support for ASIO has been gated behind an asio feature which is disabled by default. This is because the setup required for ASIO is fairly non-trivial and as it requires bindgen it introduces quite a few more dependencies.

    A section has been added to the README describing in detail how to download, install and build CPAL with support for an ASIO host. Please see the more recent commit messages below for more details.

    Closes #221.

    cc @freesig cc @Boscop this is related to #156

    Edit: Oh also, I've only been able to confirm the enumerate and beep examples work, though the beep example would distort heavily and cause my VM to crash. Originally I thought this might be my implementation, but I noticed this same behaviour happened in other software when running ASIO streams too. If anyone reading happens to have ASIO installed on a native system who could test the beep, record_wav and feedback examples that would be greatly appreciated!

    opened by mitchmindtree 23
  • Add a wasm-bindgen based generic WebAudio backend.

    Add a wasm-bindgen based generic WebAudio backend.

    Add a generic wasm-bindgen based WebAudio backend. Uses a sample scheduling strategy based on a set of interleaved AudioBufferSourceNode's which are rotated in and out as they finish playback. A quick port of the beep example appears to play stutter free on Firefox and Chrome.

    opened by dpeckett 22
  • Switch from vendored alsa-sys to alsa crate

    Switch from vendored alsa-sys to alsa crate

    This is another attempt to switch to the alsa crate fixing #346 (see also #308). I've attempted to change as little code as possible and keep consistency with the calls to the underlying library.

    This change removes a lot of unsafe from cpal (though it still exists in the alsa crate itself) and enables RAII for the ALSA resources. It also fixes #377, allowing the use of the alsa crate and cpal in the same program.

    opened by alexmoon 18
  • Removing the `EventLoop` - rebased

    Removing the `EventLoop` - rebased

    This PR is a rebase of @ishitatsuyuki's work in #301. Originally opened at ishitatsuyuki/cpal#3 but closed in favour opening a new PR here.

    Backends

    • [x] null
    • [x] ALSA
    • [x] CoreAudio
    • [x] WASAPI
    • [x] Emscripten
    • [x] ASIO

    Other TODO

    • [x] Polymorphic struct versions of Traits will be explicitly !Sync, !Send
    • [x] Docs

    ALSA multiple streams bug

    Edit: This bug seems to have been addressed in the rebase.

    After testing each of the examples with the ALSA backend on my Arch Linux system, I noticed that the feedback.rs example no longer works. No audio output was occurring and after some investigation it seems the output stream callback only seems to get called once. beep.rs and record_wav.rs both work fine, which leads me to wonder if there's an issue with the way multiple streams are being handled. feedback.rs also works fine on master, so this has likely been introduced in this PR.

    @ishitatsuyuki does anything come to mind as a potential cause for this? I did notice that we're now spawning a whole OS thread per stream. I wonder if there's some kind of race going on in the stream loop? I might see if I can find anything about thread safety in the ALSA docs. I also wonder if we can reduce the number of threads necessary by just using a single thread on which all of the streams run, similar to the old EventLoop::run impl. If there is some race going on, maybe using a single thread for all streams would help to avoid this.

    Also, I was reading through PortAudio's non-blocking ALSA code and noticed that, when spinning up a thread for a new stream, they also attempt to set the thread's priority to the highest possible. It might be worth seeing if there is some way we can do this too, though this work can probably wait for a follow-up PR.

    opened by mitchmindtree 18
  • support wasm32-unknown-unknown target

    support wasm32-unknown-unknown target

    This compile and runs fine with wasm32-unknown-unknown target, but doesn't produce any sound. Are you planning to support this target? Any idea why it doesn't work right now ?

    enhancement question feature request 
    opened by jice-nospam 18
  • Remove `UnknownTypeBuffer` in favour of specifying sample type.

    Remove `UnknownTypeBuffer` in favour of specifying sample type.

    This is an implementation of the planned changes described in #119.

    For a quick overview of how the API has changed, check out the updated examples.

    TODO:

    • [x] Update API.
    • [x] Update examples.
    • ~Remove data_type field from Format? See here.~
    • [x] Update docs.
    • Update backends:
      • [x] null
      • [x] ALSA
      • [x] ASIO
      • [x] WASAPI
      • [x] CoreAudio
      • [x] Emscripten

    Closes #119 Closes #260

    opened by mitchmindtree 17
  • Prototyping an API for getting the supported min and max buffersizes

    Prototyping an API for getting the supported min and max buffersizes

    This PR proposes an API for querying the supported min and max buffersizes of the device. I have managed to write successful test cases for ALSA, WASAPI, ASIO, CoreAudio, and Emscripten. I wanted to put this API out there for feedback before I start implementing all of the specific backends.

    Note, the current version of winapi currently has no ability to query min/max buffersizes when using WASAPI. I have an open PR on winapi that can be found here that first needs to land until we can merge this work into CPAL.

    This PR also removes the fn from(format: SupportedStreamConfig) -> SupportedStreamConfigRange function. Currently, it's only being used in wasapi/device line 529. I think we should aim to provide a better way of handling the supported formats returned by WASAPI rather than continue to modify this function to handle buffersizes.

    Looking forward to hearing your feedback!

    opened by JoshuaBatty 16
  • Add (more clear?) information to the docs on how channels work in terms of streams.

    Add (more clear?) information to the docs on how channels work in terms of streams.

    This is something that I've been struggling with because I'm used to working with audio streams broken by channels and sets of samples for each frame that represent a sample for each channel. With CPAL though, all that you get is a callback that effectively gives an array for individual samples devoid of any notion of channels save the number you have from the StreamConfig you used. At time of writing, I'm still not quite sure how to do multichannel audio. My best guess is that channel samples are interleaved but even if that's correct, the fact that I had to scour the docs and came back absolutely no wiser to this than when I went in is a major indication that this needs to be clarified in the docs if not for the audio pros who could assume how it works, than for the people like me who know a bit about low-level audio but are trying to learn to use an even more bare-metal library like this one.

    opened by ConveyorBusBuilder 0
  • Android: Device build_output_stream eventually stops working.

    Android: Device build_output_stream eventually stops working.

    While testing on Android, I ran into an issue with calling build_output_stream. In my project, I use symphonia to decode audio files and cpal to produce sound. Every time I played a new file, I would call build_output_stream.

    This would stop working after 40 calls of the method. This error is thrown.

    I have created a workaround fix where I call build_output_stream only once. However, I am concerned with the StreamConfig changing between audio files. Is there anything that can be done in cpal to fix this issue?

    I have created a project that reproduces this issue and I have included the workaround I made. You will need cargo-apk installed to run it.

    opened by erikas-taroza 2
  • ALSA: don't ignore POLLERR

    ALSA: don't ignore POLLERR

    This is a quick hack for #730.

    This way I can at least avoid worker thread busy-looping upon overrun condition (in general it's enough for me to teardown the stream in such case).

    I believe a proper fix would require to:

    • report this very condition as XRun
    • let the user decide hwo to handle it
    opened by codepainters 0
  • ALSA: invalid handling of capture overruns

    ALSA: invalid handling of capture overruns

    I'm working on an application using cpal over ALSA to continuously capture audio stream on Raspberry Pi. I use both RPI and PC for testing. Note: I'm using a version from master branch, as I need both i16 and i32 sample formats, with i32 not being supported in stable version.

    Unfortunately I'm experiencing odd behavior upon capture overruns (which I trigger setting buffer size too low).

    1. The most severe case is when poll() return EPOLERR which is not handled properly.
    476794 1669022562.665530 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5, revents=POLLIN}])
    476794 1669022562.666440 ioctl(5, SNDRV_PCM_IOCTL_STATUS_EXT,      0x7f6b10495f88) = 0
    476794 1669022562.666532 ioctl(5, SNDRV_PCM_IOCTL_HWSYNC, 0x98) =      0
    476794 1669022562.666577 ioctl(5, SNDRV_PCM_IOCTL_READI_FRAMES,      0x7f6b10496760) = 0
    476794 1669022562.666707 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5, revents=POLLIN|POLLERR}])
    476794 1669022562.669590 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5, revents=POLLIN|POLLERR}])
    476794 1669022562.669765 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5, revents=POLLIN|POLLERR}])
    

    And then I no longer get any more callbacks from cpal, but my application is eating up 100% of CPU core, as poll() is executed in a tight loop.

    The problem is here:

    https://github.com/RustAudio/cpal/blob/7776c6634a8e21e2a585358545141fe091c38320/src/host/alsa/mod.rs#L746-L753

    This match doesn't recognize POLLIN|POLLERR and returns PollDescriptorsFlow::Continue, causing the worker thread to poll() again immediately, leading to a tight loop.

    The problem seems obvious, I'll try to come with a pull request.

    1. Another scenario is when the second ioctl call fails.
    476936 1669022662.246764 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5, revents=POLLIN}])
    476936 1669022662.247721 ioctl(5, SNDRV_PCM_IOCTL_STATUS_EXT, 0x7f70e2810f88) = 0
    476936 1669022662.247884 ioctl(5, SNDRV_PCM_IOCTL_HWSYNC, 0x98) = -1 EPIPE (Broken pipe)
    476936 1669022662.248019 ioctl(5, SNDRV_PCM_IOCTL_PREPARE, 0) = 0
    476936 1669022662.248112 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 0 (Timeout)
    476936 1669022662.448722 write(1, "Die! A backend-specific error has occurred: `alsa::poll()` spuriously returned\n", 79) = 79
    476936 1669022662.449074 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 0 (Timeout)
    476936 1669022662.649849 write(1, "Die! A backend-specific error has occurred: `alsa::poll()` spuriously returned\n", 79) = 79
    476936 1669022662.650342 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 0 (Timeout)
    476936 1669022662.851166 write(1, "Die! A backend-specific error has occurred: `alsa::poll()` spuriously returned\n", 79) = 79
    

    In this scenario I no longer get any data callbacks, instead I get error callback periodically (poll timeout).

    I believe the problem is here:

    https://github.com/RustAudio/cpal/blob/7776c6634a8e21e2a585358545141fe091c38320/src/host/alsa/mod.rs#L604-L609

    The call to prepare() passes OK, but the stream is stopped - according to ALSA, this call changes the state to SND_PCM_STATE_PREPARED, there also need to be a call to start() to transition to SND_PCM_STATE_RUNNING and re-enable data flow.

    I'm a bit confused here about what is the intended cpal behavior here:

    • should I assume that stream is broken when my error callback is called for the first time, drop the Stream and create a new one? In such case I believe cpal should do some cleanup (e.g. stop the polling loop).
    • should I assume that the error is temporary and the data flow will continue? In such case start() call is missing.
    1. The third scenario is when ioctl(SNDRV_PCM_IOCTL_READI_FRAMES) fails with EPIPE:
    476728 1669022521.635527 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5,        revents=POLLIN}])
    476728 1669022521.636362 ioctl(5, SNDRV_PCM_IOCTL_STATUS_EXT, 0x7f8b2368af88) = 0
    476728 1669022521.636521 ioctl(5, SNDRV_PCM_IOCTL_HWSYNC, 0x98) = 0
    476728 1669022521.636681 ioctl(5, SNDRV_PCM_IOCTL_READI_FRAMES, 0x7f8b2368b760) = -1 EPIPE (Broken pipe)
    476728 1669022521.636777 write(1, "Die! A backend-specific error has occurred: ALSA function 'snd_pcm_readi' failed with error 'EPIPE: Broken pipe'\n", 113) = 113
    476728 1669022521.636823 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5,        revents=POLLIN|POLLERR}])
    476728 1669022521.636860 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5,        revents=POLLIN|POLLERR}])
    476728 1669022521.636892 poll([{fd=3, events=POLLIN}, {fd=5, events=POLLIN|POLLERR|POLLNVAL}], 2, 200) = 1 ([{fd=5,        revents=POLLIN|POLLERR}])
    

    Here, the error from process_input() is properly delivered to my error callback, but then we enter the tight loop scenario, due to POLLERR not being recognized.

    opened by codepainters 0
  • record_wav example always writes very first recorded audio

    record_wav example always writes very first recorded audio

    Running the example multiple times always produces the first recording I made.

    Macbook M1, MacOS Montery, rustc v1.65

    To reproduce:

    # run the example (and say something)
    cargo run --example record_wav
    # listen to the result
    open recorded.wav
    # delete the recording
    rm recorded.wav
    # run the example again (and say something else)
    cargo run --example record_wav
    # listen to the result
    open recorded.wav
    

    No matter how many times I remove the recording and run the example, I get the very first recorded audio.

    opened by aztecrex 0
  • wasm-beep example

    wasm-beep example "can't resolve './pkg'"

    I followed the readme in the examples/wasm-beep folder, which said to run npm install then npm start. After running npm start it seems to mostly work, browser pops up to the page with the play and stop buttons, but there's an error in the terminal where I ran npm start:

    ERROR in ./index.js
    Module not found: Error: Can't resolve './pkg' in 'C:\Users\David\Projects\personal\rust-learn\cpal\examples\wasm-beep'
    

    And no sound is heard when pressing the play button. I can't tell what pkg is supposed to be, or where to get it, so maybe something missing in the instructions? Or something else changed.

    opened by adenflorian 2
Owner
Free and useful Audio, DSP and music libraries written in Rust. Discourse https://rust-audio.discourse.group/ Discord https://discord.gg/b3hjnGw
null
Cross-platform audio for Rust

quad-snd High-level, light-weight, and opinionated audio library. Web: WebAudio Android: OpenSLES Linux: Alsa macOS: CoreAudio Windows: Wasapi iOS: Co

Fedor Logachev 86 Nov 7, 2022
Symphonia is a pure Rust audio decoding and media demuxing library supporting AAC, FLAC, MP3, MP4, OGG, Vorbis, and WAV.

Pure Rust multimedia format demuxing, tag reading, and audio decoding library

Philip Deljanov 1k Jan 2, 2023
Rust audio playback library

Audio playback library Rust playback library. Playback is handled by cpal. MP3 decoding is handled by minimp3. WAV decoding is handled by hound. Vorbi

null 1.2k Jan 1, 2023
Rust bindings for the soloud audio engine library

soloud-rs A crossplatform Rust bindings for the soloud audio engine library. Supported formats: wav, mp3, ogg, flac. The library also comes with a spe

Mohammed Alyousef 38 Dec 8, 2022
A low-overhead and adaptable audio playback library for Rust

Awedio   A low-overhead and adaptable audio playback library for Rust. Examples Play a single sound file: let (mut manager, backend) = awedio::start()

10 Buttons 20 May 25, 2023
Flutter crossplatform audio playback library powered by golang beep & oto

Rowdy Pure Rust based Dart/Flutter audio playback library Installation $ flutter pub add rowdy Configuration You'll need the Rust toolchain installed

Kingkor Roy Tirtho 3 Aug 31, 2022
A library and application for lossless, format-preserving, two-pass optimization and repair of Vorbis data, reducing its size without altering any audio information.

OptiVorbis A library and application for lossless, format-preserving, two-pass optimization and repair of Vorbis data, reducing its size without alter

OptiVorbis 27 Jan 3, 2023
Auritia is a DAW coded in Rust and Vue in hopes of having cross platform compatability, while also providing enough features for anyone to use professionally

Steps Install WebView if you're not on Windows 11 Install Node deps npm i To run the dev server do npm run tauri dev Compiling Linux You will need to

Auritia 20 Aug 27, 2022
Cross-platform realtime MIDI processing in Rust.

midir Cross-platform, realtime MIDI processing in Rust. Features midir is inspired by RtMidi and supports the same features*, including virtual ports

Patrick Reisert 392 Dec 27, 2022
Implements the free and open audio codec Opus in Rust.

opus-native Overview Implements the free and open audio codec Opus in Rust. Status This crate is under heavy development. Most functionality is not wo

Nils Hasenbanck 9 Nov 28, 2022
Rust - Augmented Audio Libraries

Augmented Audio Libraries In this repository I'll push some experiments trying to use Rust for audio programming. Goals Goal 1: Learn & have fun This

Pedro Tacla Yamada 116 Dec 18, 2022
CLI Rust Audio Visualizer

crav Console-based Rust Audio Visualizer It can run in the terminal but also has a 3D accelerated backend implemented in wgpu. demo compatibility The

null 20 Oct 16, 2022
Simple examples to demonstrate full-stack Rust audio plugin dev with baseplug and iced_audio

iced baseplug examples Simple examples to demonstrate full-stack Rust audio plugin dev with baseplug and iced_audio WIP (The GUI knobs do nothing curr

Billy Messenger 10 Sep 12, 2022
MVC audio plugin framework for rust

__ __ | |--.---.-.-----.-----.-----.| |.--.--.-----. | _ | _ |__ --| -__| _ || || | | _ | |

william light 93 Dec 23, 2022
simple-eq is a crate that implements a simple audio equalizer in Rust.

simple-eq A Simple Audio Equalizer simple-eq is a crate that implements a simple audio equalizer in Rust. It supports a maximum of 32 filter bands. Us

Mike Hilgendorf 11 Sep 17, 2022
A simple GUI audio player written in Rust with egui. Inspired by foobar2000.

Music Player A simple GUI music player inspired by foobar2000 written in Rust using egui. The goal of this project is to learn about making gui/ nativ

Ryan Blecher 5 Sep 16, 2022
Rust Audio Player Daemon

Rust Audio Player Daemon Cause mpd was annoying What rapd trys to do Rapd is not a spotify client, or an advanced music player. Its an audio/music dae

ash 3 Nov 1, 2022
API-agnostic audio plugin framework written in Rust

Because everything is better when you do it yourself - Rust VST3 and CLAP framework and plugins

Robbert van der Helm 415 Dec 27, 2022
DSP real time audio synthesis, effect algorithms and utilities for Rust

synfx-dsp synfx-dsp DSP real time audio synthesis, effect algorithms and utilities for Rust Most of the algorithms and implementations in this library

Weird Constructor 8 Nov 23, 2022