MVC audio plugin framework for rust

Overview
  __                             __              
 |  |--.---.-.-----.-----.-----.|  |.--.--.-----.
 |  _  |  _  |__ --|  -__|  _  ||  ||  |  |  _  |
 |_____|___._|_____|_____|   __||__||_____|___  |
                         |__|             |_____|
 
  baseplug is a high-level model/view/controller-ish audio plugin framework.

  nightly-only right now, because of GATs and min_specialization.

  baseplug is still largely prototypal, but is maturing quickly. i highly
  encourage looking at the examples and building experiments with it. though
  there will be API breakage in the future, i do not see a significant
  divergence from the existing structures.

  with that said, baseplug is not currently in a place where you should *ship*
  any plugins built with it. as the baseplug APIs change, there is a high
  likelihood that your users' sessions will break, presets won't load
  correctly, and automation will be incorrect.

  the primary goal for the 0.1 milestone is resolving these issues of
  forward-compatibility, and at that juncture we will lift the above advisement
  against shipping plugins.

  i'm making this public in its pre-pre-alpha state to get feedback from folks.

  please file issues if things act weird or something's unclear.

  do note that, though i have extensive experience in audio dev, i am largely a
  neophyte when it comes to advanced rust usage, proper code style and best
  practices. especially when it comes to error handling in procmacros.

  best way to get in touch is to join the rust audio discord:
    https://discord.gg/8rPCp9Q

  -w
Comments
  • Implement offset_of! using MaybeUninit and addr_of! to avoid UB

    Implement offset_of! using MaybeUninit and addr_of! to avoid UB

    The existing implementation of the offset_of! macro dereferences a null pointer, which invokes undefined behavior and results in a compiler warning. Change it to use addr_of! on a MaybeUninit instead.

    Compiler Explorer shows this compiling down to a single lea instruction with optimizations on, so performance should not be an issue: https://godbolt.org/z/57deqbaM5

    opened by glowcoil 0
  • fix issue #29

    fix issue #29

    Figured out how to fix issue #29. It was a matter of figuring out where it wanted me to put the where Self: 'proc, P: 'proc, T: 'proc like it said in the error message.

    opened by BillyDM 0
  • fix for issue #29

    fix for issue #29

    Figured out how to fix issue #29. It was a matter of figuring out where it wanted me to put the where Self: 'proc, P: 'proc, T: 'proc like it said in the error message.

    I'm using the RustyDAW org account for this since I've already forked baseview with my own account.

    opened by BillyDM 0
  • Fails to compile on latest rust nightly compiler

    Fails to compile on latest rust nightly compiler

    I have updated to the latest rust nightly compiler, and baseplug now fails to compile with the following error:

    error: Missing required bounds on Process
      --> src/model.rs:11:5
       |
    11 |     type Process<'proc>;
       |     ^^^^^^^^^^^^^^^^^^^-
       |                        |
       |                        help: add the required where clauses: `where P: 'proc, Self: 'proc, T: 'proc`
    
    error: could not compile `baseplug` due to previous error
    warning: build failed, waiting for other jobs to finish...
    error: build failed
    
    opened by BillyDM 0
  • use HasRawWindowHandle instead of RawWindowHandle

    use HasRawWindowHandle instead of RawWindowHandle

    Baseview requires a struct that implements HasRawWindowHandle, which means the user must convert the RawWindowHandle given in PluginUI::ui_open() into a struct that implements that. This PR fixes that by converting it at the baseview level.

    It is called TrustedWindowHandle because of it mirrors this: https://github.com/rust-windowing/raw-window-handle/blob/master/src/lib.rs#L210. I don't believe that this is in crates.io yet, so I created a temporary one.

    Instead of the user doing this:

    fn ui_open(parent: RawWindowHandle) -> WindowOpenResult<Self::Handle> {
        let settings = iced_baseview::Settings {
            window: WindowOpenOptions {
                title: String::from("iced-baseplug-examples gain"),
                size: Size::new(Self::ui_size().0 as f64, Self::ui_size().1 as f64),
                scale: WindowScalePolicy::SystemScaleFactor,
            },
            flags: (),
        };
    
        // TODO: Fix this mess in baseplug.
        struct ParentWindow(RawWindowHandle);
        unsafe impl HasRawWindowHandle for ParentWindow {
            fn raw_window_handle(&self) -> RawWindowHandle {
                self.0
            }
        }
    
        let handle =
            iced_baseview::IcedWindow::<ui::GainUI>::open_parented(&ParentWindow(parent), settings);
    
        Ok(handle)
    }
    

    They can now do this:

    fn ui_open(parent: &impl HasRawWindowHandle) -> WindowOpenResult<Self::Handle> {
        let settings = iced_baseview::Settings {
            window: WindowOpenOptions {
                title: String::from("iced-baseplug-examples gain"),
                size: Size::new(Self::ui_size().0 as f64, Self::ui_size().1 as f64),
                scale: WindowScalePolicy::SystemScaleFactor,
            },
            flags: (),
        };
    
        let handle =
            iced_baseview::IcedWindow::<ui::GainUI>::open_parented(parent, settings);
    
        Ok(handle)
    }
    
    opened by BillyDM 0
  • Create CHECKLIST.md

    Create CHECKLIST.md

    I believe it would be massively helpful to have a checklist that highlights the differences and similarities between plugin formats. This would both inform developers who aren't that familiar with plugin APIs (like myself) on how each of these work, and it will make how to create an abstraction over them much clearer.

    I had to make assumptions on what the VST2 functions do. Feel free to add and correct me on them!

    opened by BillyDM 0
  • Impossible to create audio effects with MIDI in?

    Impossible to create audio effects with MIDI in?

    Creating a plugin implementation with:

    const INPUT_CHANNELS: usize = 2;
    const OUTPUT_CHANNELS: usize = 2;
    

    that also implements MidiReceiver creates something that is flagged by Ableton and RENoise as an instrument with sidechain, when it should be an effect with 2 input channels. Does baseplug have a manual setting for this, like JUCE? Should this be a const in the Plugin trait?

    opened by marc-weber1 0
  • Donwfall85/feature/numbers

    Donwfall85/feature/numbers

    This branch implements the Num, Real and Discrete traits to represent numbers. The main objective is to replace the Float trait which is not very well designed. I only implemented the basic operations to keep the current behaviour but it is of course possible to play others (All credit goes to SamiP for implementing these traits).

    The next step would be to allow the use of other primitive types than f32. To do this, you have to play with the Translatable <T, P: Plugin, Model> trait.

    I tried the following implementation but quickly found myself stuck:

    impl <P: Plugin, Model, T> Translatable <T, P, Model> for T
        where T: Real + AsPrimitive <f32>.
    

    This allows you to use f32 or f64. However, when we want to do the same thing for integers, we end up with a conflict:

    impl <P: Plugin, Model, T> Translatable <T, P, Model> for T
        where T: Discrete + AsPrimitive <f32>.
    

    We have two blanket implementations and this is not allowed by Rust until we can do mutual trait exclusions.

    One solution that works is to implement the Translatable <T, P: Plugin, Model> trait for each type with a macro:

    macro_rules! impl_real {
        ( $($t:ty),* ) => {
        $( impl<P: Plugin, Model> Translatable<$t, P, Model> for $t {
            fn xlate_in(param: &Param<P, Model>, normalised: f32) -> $t {
                ...
            }
        
            fn xlate_out(&self, param: &Param<P, Model>) -> f32 {
                ...
            }
        }) *
        }
    }
    impl_real! { f32, f64 }
    
    macro_rules! impl_discrete {
        ( $($t:ty),* ) => {
        $( impl<P: Plugin, Model> Translatable<$t, P, Model> for $t {
            fn xlate_in(param: &Param<P, Model>, normalised: f32) -> $t {
                .
            }
        
            fn xlate_out(&self, param: &Param<P, Model>) -> f32 {
                .
            }
        }) *
        }
    }
    impl_discrete! { i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize }
    

    With this solution, it is possible to use any scalar type to build a parameter.

    I need your vision on which solution would be most appropriate in the context of the project.

    opened by downfall85 0
  • Donwfall85/feature/enum impl

    Donwfall85/feature/enum impl

    Here is my attempt to implement enums in baseplug model. We can now write models like that:

    baseplug::model! {
        #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
        enum MyEnum {
            A,
            B,
        }
    
        #[derive(Debug, Serialize, Deserialize)]
        struct MyModel {
    
            #[parameter(name = "param")]
            param: MyEnum
        }
    }
    

    Nearly all the job is done in the proc macro.

    There is one thing that I would like to improve but I haven't any solution right now. We now need to import baseplug::Translatable and baseplug::Param in the plugin since the proc macro generates the implementation of the Translatable trait for the enum.

    Let me know what do you think and how I can improve it.

    opened by downfall85 2
  • UI Model synchronization

    UI Model synchronization

    So far this seems to work for float parameters/entries (Smooth & Unsmoothed). I haven't yet figured out how to sync Declick parameters/entries yet, but this is a huge start.

    Sorry if this PR is a bit of a mess. It took a lot of changes to get this working. :D

    opened by BillyDM 1
  • Combining baseplug with rsynth

    Combining baseplug with rsynth

    Hi, I'm the maintainer of rsynth, an "API abstraction for API's for audio plugins and applications". My "strategy" with rsynth was to stay away from UI's, hoping that others (with more expertise in UI development) would work on that. baseplug illustrates for me that this was the good strategy :-)

    I'd like developers (including me) to be able to combine rsynth with baseplug for the UI for writing their plugins. What do you think about this?

    opened by PieterPenninckx 0
Owner
william light
[audio dsp gui] dev in [c rust python]
william light
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
A low-level windowing system geared towards making audio plugin UIs.

baseview A low-level windowing system geared towards making audio plugin UIs. baseview abstracts the platform-specific windowing APIs (winapi, cocoa,

null 155 Dec 30, 2022
Cross-platform audio I/O library in pure Rust

CPAL - Cross-Platform Audio Library Low-level library for audio input and output in pure Rust. This library currently supports the following: Enumerat

null 1.8k Jan 8, 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
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
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 - 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-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
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
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
Quite OK Audio format in Rust.

QOA - The Quite Ok Audio Format This is a pure Rust (zero dependency) implementation of the QOA audio format. This code is based off the reference C i

Rafael Carício 10 Apr 16, 2023
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
Capture system output audio in rust.

RUHear A simple crate that allows you to capture system output audio (what aRe yoU HEARing). Dependencies On windows and linux: cpal On macos: screenc

Charles 3 Feb 7, 2024
Rust-crate with functions and helpers for working with music / audio, inspired by computer music languages.

music-math This crate contains common functions and helpers for working with music / audio in Rust. Most of these are inspired by similar functions fo

Mads Kjeldgaard 3 Apr 10, 2024
A collection of filters for real-time audio processing

Audio Filters A collection of filters for real-time audio processing Feature Progress #![no_std] (via libm) f32 & f64 capable (via num-traits) SIMD Do

null 42 Nov 5, 2022