VST 2.4 API implementation in rust. Create plugins or hosts.

Overview

rust-vst2

Travis Build Appveyor Build crates.io

A library to help facilitate creating VST plugins in rust.

This library is a work in progress and as such does not yet implement all opcodes. It is enough to create basic VST plugins without an editor interface.

Please note: This api may be subject to rapid changes and the current state of this library is not final.

Library Documentation

TODO

  • Implement all opcodes
  • Proper editor support (possibly conrod + sdl2?)
  • Write more tests
  • Provide better examples

Usage

To create a plugin, simply create a type which implements plugin::Plugin and std::default::Default. Then call the macro plugin_main!, which will export the necessary functions and handle dealing with the rest of the API.

Example Plugin

A simple plugin that bears no functionality. The provided Cargo.toml has a crate-type directive which builds a dynamic library, usable by any VST host.

src/lib.rs

#[macro_use]
extern crate vst2;

use vst2::plugin::{Info, Plugin};

#[derive(Default)]
struct BasicPlugin;

impl Plugin for BasicPlugin {
    fn get_info(&self) -> Info {
        Info {
            name: "Basic Plugin".to_string(),
            unique_id: 1357, // Used by hosts to differentiate between plugins.

            ..Default::default()
        }
    }
}

plugin_main!(BasicPlugin); // Important!

Cargo.toml

[package]
name = "basic_vst"
version = "0.0.1"
authors = ["Author <[email protected]>"]

[dependencies]
vst2 = "0.0.1"

[lib]
name = "basicvst"
crate-type = ["dylib"]

Packaging on OS X

On OS X VST plugins are packaged inside of loadable bundles. To package your VST as a loadable bundle you may use the osx_vst_bundler.sh script this library provides. 

Example: 

./osx_vst_bundler.sh Plugin target/release/plugin.dylib
Creates a Plugin.vst bundle
Comments
  • Added process_events() to Host for sending MIDI output to Host

    Added process_events() to Host for sending MIDI output to Host

    As requested: https://github.com/overdrivenpotato/rust-vst2/issues/18 I haven't tested it yet but I implemented it because @suhr needed it, and he is gonna test it with his plugin. So we should wait for his confirmation before merging this. (I basically copy-pasted from Plugin to Host, maybe we should factor out the commonalities..)

    opened by Boscop 18
  • Installing the VST in Mac?

    Installing the VST in Mac?

    Hi,

    how do install the VST plugin on my Mac? I did a cargo build in the example from the README, and it generated a .dylib file, but my DAW isn't able to find it.

    Thanks!

    opened by betodealmeida 8
  • Use types from std::os::raw instead of libc where possible

    Use types from std::os::raw instead of libc where possible

    Now plugins don't need to depend on libc for Plugin::open().

    I also made load_pointer uppercase (LOAD_POINTER) because it's a global var and caused a warning.

    opened by Boscop 5
  • fixed HostCallback.get_info(), increased MAX_PARAM_STR_LEN to 64

    fixed HostCallback.get_info(), increased MAX_PARAM_STR_LEN to 64

    While using rust-vst2 I noticed that a lot of my VST's parameter names were displayed truncated in the VST host because MAX_PARAM_STR_LEN was only 8. I increased it to 64 (MAX_LABEL, MAX_PRODUCT_STR_LEN and MAX_VENDOR_STR_LEN are also 64). Also I noticed that HostCallback.get_info() returned the default Host.get_info(), instead of calling into the actual VST host to get its info, so I fixed that.

    opened by Boscop 4
  • Segfaulting when creating an instrument plugin.

    Segfaulting when creating an instrument plugin.

    I'm looking to contrib to rust-vst2 by providing a simple sinewave instrument example.

    I've gotten fairly far, having daws recognise the plugin as an instrument and everything is compiling okay, however, when any midi signals are sent to the plugin, it crashes.

    Using mrswatson yields the following output:

    rob@Robs-MacBook ~/P/vst-simplesynth> mrswatson64 --verbose -p "simplesynth" -m bass.mid -o "out.wav"
    - 00000000 000001 MrsWatson version 0.9.8 initialized, build 20150122
    D 00000000 000009 Host platform is Mac OS X (Mac OS XVersion 10.12.4 (Build 16E195))
    D 00000000 000009 Application is 32-bit
    D 00000000 000009 Launched with options: --verbose -p simplesynth -m bass.mid -o out.wav
    D 00000000 000009 Trying to find plugin 'simplesynth'
    D 00000000 000009 Looking for plugin 'simplesynth' in '/Users/rob/Projects/vst-simplesynth'
    D 00000000 000011 Looking for plugin 'simplesynth' in '/Library/Audio/Plug-Ins/VST'
    D 00000000 000012 Looking for plugin 'simplesynth' in '/Users/rob/Library/Audio/Plug-Ins/VST'
    - 00000000 000013 Plugin 'simplesynth' is of type VST2.x
    D 00000000 000013 Looking for plugin 'simplesynth' in '/Users/rob/Projects/vst-simplesynth'
    D 00000000 000014 Looking for plugin 'simplesynth' in '/Library/Audio/Plug-Ins/VST'
    D 00000000 000015 Looking for plugin 'simplesynth' in '/Users/rob/Library/Audio/Plug-Ins/VST'
    - 00000000 000016 Opening VST2.x plugin 'simplesynth'
    D 00000000 000017 Plugin location is '/Users/rob/Library/Audio/Plug-Ins/VST/simplesynth.vst'
    D 00000000 000022 Plugin '' called host dispatcher with 1, 0, 0
    D 00000000 000023 Initializing VST2.x plugin 'simplesynth'
    D 00000000 000025 Time division is 96
    D 00000000 000025 MIDI file is type 0, has 1 tracks, and time division 96 (type 1)
    D 00000000 000025 Ignoring MIDI meta event of type 0x3 at 0
    D 00000000 000025 Parsed MIDI meta event of type 0x58 at 0
    D 00000000 000025 Parsed MIDI meta event of type 0x58 at 0
    D 00000000 000025 MIDI event of type 0x90 parsed at 0
    D 00000000 000025 MIDI event of type 0x80 parsed at 11025
    D 00000000 000025 MIDI event of type 0x90 parsed at 11025
    D 00000000 000025 MIDI event of type 0x80 parsed at 22050
    ...
    00000000 000026 MIDI event of type 0x80 parsed at 352800
    D 00000000 000026 Parsed MIDI meta event of type 0x2f at 352800
    D 00000000 000027 Opened audiofile 16-bit, little-endian for writing
    D 00000000 000027 Resuming plugin 'simplesynth'
    - 00000000 000027 Starting processing input source
    D 00000000 000027 Sample rate: 44100
    D 00000000 000027 Blocksize: 512
    D 00000000 000027 Channels: 2
    D 00000000 000027 Tempo: 120.00
    D 00000000 000030 Processing delay frames: 0
    D 00000000 000030 Time signature: 4/4
    D 00000000 000030 Read 1024 samples from silence source
    D 00000000 000030 Scheduling MIDI event 0x58 (0, 0) in 0 frames
    D 00000000 000030 Scheduling MIDI event 0x58 (0, 0) in 0 frames
    D 00000000 000030 Scheduling MIDI event 0x90 (3d, 62) in 0 frames
    D 00000000 000030 Processing plugin chain MIDI events
    ERROR: Sent signal 11, exiting
    MrsWatson (or one of its hosted plugins) has encountered a serious error and
    crashed.
    If you believe this to be a bug in MrsWatson, please re-run the program with
    the --error-report option to generate a diagnostic report to send to support.
    

    I can upload the entire source if required, but so far my lib.rs is as follows:

    #[macro_use]
    extern crate vst2;
    
    use vst2::buffer::AudioBuffer;
    use vst2::plugin::{Category, Plugin, Info};
    use vst2::event::{Event};
    
    struct SimpleSynth {
        delta: f32
    }
    
    impl Default for SimpleSynth {
        fn default() -> SimpleSynth {
            SimpleSynth {
                delta: 0.0
            }
        }
    }
    
    impl Plugin for SimpleSynth {
    
        fn get_info(&self) -> Info {
            Info {
                name: "SimpleSynth".to_string(),
                vendor: "DeathDisco".to_string(),
                unique_id: 6667,
                category: Category::Synth,
                // inputs: 0,
                // outputs: 2,
                parameters: 0,
                ..Default::default()
            }
        }
    
        fn process_events(&mut self, events: Vec<Event>) {
            for event in events {
                match event {
                    Event::Midi { .. } => println!("midi"),
                    _ => println!("sysex"),
                }
            }
        }
    
        fn process(&mut self, buffer: AudioBuffer<f32>) {
            // Split out the input and output buffers into two vectors
            let (inputs, outputs) = buffer.split();
    
            // For each buffer, transform the samples
            for (input_buffer, output_buffer) in inputs.iter().zip(outputs) {
                for (input_sample, output_sample) in input_buffer.iter().zip(output_buffer) {
                    *output_sample = 0.5
                }
            }
        }
    }
    
    plugin_main!(SimpleSynth);
    

    Is there something obvious I'm missing, or is rust-vst2 not properly supporting Instruments yet?

    opened by monomadic 2
  • Unable to extract audio from an output

    Unable to extract audio from an output

    Hi - I'm afraid I'm very new to rust, so this problem is almost certainly with my understanding rather than the library. But just in case I have identified a genuine issue, here's a ticket.

    I'm attempting to pass a midi note to an instrument VST, and get the audio out of that VST (with the hopes of eventually playing it ;))

    
    extern crate vst2;
    
    use std::sync::{Arc, Mutex};
    use std::path::Path;
    
    use vst2::host::{Host, PluginLoader};
    use vst2::plugin::Plugin;
    use vst2::event::Event;
    use vst2::buffer::AudioBuffer;
    
    struct SampleHost;
    
    impl Host for SampleHost {
        fn automate(&mut self, index: i32, value: f32) {
            println!("Parameter {} had its value changed to {}", index, value);
        }
    }
    
    fn main() {
        let host = Arc::new(Mutex::new(SampleHost));
        let path = Path::new("/Library/Audio/Plug-Ins/VST/helm.vst/Contents/MacOS/helm");
    
        let mut loader = PluginLoader::load(path, host.clone()).unwrap();
        let mut instance = loader.instance().unwrap();
    
        instance.init();
        let note = Event::Midi {
            data: [0, 60, 127],
            delta_frames: 0,
            detune: 0,
            live: false,
            note_length: Some(100),
            note_off_velocity: 10,
            note_offset: None
        };
    
        instance.process_events(vec![note]);
    
        let mut in1 = vec![0.0; 1024]; // just to make the frame length right
        let mut out1 = in1.clone();
        let mut out2 = in1.clone();
    
        let buffer = AudioBuffer::new(vec![&mut in1], vec![&mut out1, &mut out2]);
        instance.process(buffer);
    
        // ...
    }
    
    

    The way I think rust-vst2 wants me to do this is to process the buffer using the plugin instance, and then at some later point to inspect the AudioBuffer I sent into it. However, if I attempt to access the AudioBuffer (buffer) or the one mutable vectors (in1, out1 or out2) that make it up after instance.process(buffer);, I get a borrower check error.

    I can understand from the rust docs that this is expected behaviour, but does that then render it impossible to get audio data out of the VST?

    opened by hughfdjackson 2
  • Version 2.x without VSTPluginMain

    Version 2.x without VSTPluginMain

    I tried to create host, but it can't open external VST plugin. Host fails with:

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NotAPlugin', C:\bot\slave\nightly-dist-rustc-win-gnu-64\build\src\libcore\result.rs:837
    

    because it can't find VSTPluginMain.

    Actually method doesn't exist:

    :\Program Files\VSTPlugins\SONiVOX>dumpbin /EXPORTS "OrchestralCompanionStrings_x64.dll"
    Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
    Dump of file OrchestralCompanionStrings_x64.dll
    
    File Type: DLL
    
      Section contains the following exports for VSTGUI36_XC5.dll
    
        00000000 characteristics
        55E62579 time date stamp Wed Sep  2 01:23:53 2015
            0.00 version
               1 ordinal base
               8 number of functions
               8 number of names
    
        ordinal hint RVA      name
    
              1    0 0002AAA0 ACFCanUnloadNow
              2    1 0002AAC0 ACFGetClassFactory
              3    2 0002AAE0 ACFGetSDKVersion
              4    3 0002AB00 ACFRegisterComponent
              5    4 0002AB20 ACFRegisterPlugin
              6    5 0002AB40 ACFShutdown
              7    6 0002AB60 ACFStartup
              8    7 001338D0 main
    
      Summary
    
           40000 .data
           15000 .pdata
           7A000 .rdata
            5000 .reloc
          17A000 .rsrc
          1AA000 .text
            4000 _RDATA
    

    This plugin looks like VST 3.x (RegisterComponent, VSTGUI36_XC5.dll dependency). But other software shows me that plugin is VST 2.x. Why? Is it possible to open it?

    opened by DenisKolodin 2
  • Added support for CanDo strings for querying host capabilities.

    Added support for CanDo strings for querying host capabilities.

    While I was implementing a Host, I saw the need to reply to CanDo requests from plugins, therefore I added support for them in the host. This required using the function read_string() which was previously only defined in the scope of the dispatch() function of plugins, so I pulled it out of that scope into the module scope, so both plugin and host dispatchers can use it to read strings from ptr.

    For more info on CanDo strings, see this. They don't just apply to querying plugins, also hosts.

    opened by Boscop 2
  • fix compiler errors with rust 1.5 windows MSVC

    fix compiler errors with rust 1.5 windows MSVC

    This hasn't been thoroughly tested, but this actually makes this project work on Windows with Rust 1.5. It currently uses my own fork of dylib with these issues changed, though if the dylib developer merges in my pull request, then I'll of course change it back to the regular dylib.

    Also fixes compiler errors in the new host implementation with Rust 1.5

    opened by Earlz 2
  • preset_chunks not working in some DAWs

    preset_chunks not working in some DAWs

    Anybody tried to use preset_chunks before?

    Update: It's working in ableton but not bitwig... weird...

    I am setting preset_chunks: true but get_preset_data(), get_bank_data(), load_preset_data(), or load_bank_data() are never called.

    I'll dig more into it but was hoping someone had insight or experience with it.

    Additional info: can confirm it's working in ableton and renoise, but bitwig will not call those functions even in the lib itself. Putting breaks inside any of the functions doesn't trigger anything in bitwig but does in other daws.

    OpCode::GetData => {} is never called.

    It's likely that either vst2 or bitwig isnt' following the spec correctly but bitwig is usually very tolerant. Also, it goes without saying there are many many plugins which use this feature and work fine, so the bug is likely within rust-vst2 somewhere, any help in determining how to diagnose this would be super useful.

    opened by monomadic 1
  • Add write access contributors to help maintain rust-vst2

    Add write access contributors to help maintain rust-vst2

    This is an awesome repo for developing VSTs with Rust. However, the last merged PR was 1 month ago despite fairly active development on forks. I understand that other work often comes up, and it's hard to get to everything in a short period of time.

    To help with that, I would ask that you give someone like @Boscop or @zyvitski write access to the repository so merges and issues can be resolved more quickly.

    opened by piedoom 1
  • Plug-In doesn't open in VST-host in OSX 10.12.1

    Plug-In doesn't open in VST-host in OSX 10.12.1

    After building the plug-in and bundling it with osx_vst_bunder.sh script and copying it to the VST directory Ableton Live and Audacity cannot find the plug-in.

    opened by PhilStem 1
  • Hard Fork

    Hard Fork

    Due to lack of maintainer activity (#38), we've decided to make a hard fork of this repo so we can continue active development: https://github.com/rust-dsp/rust-vst

    opened by conundrumer 0
  • Chunk data is broken.

    Chunk data is broken.

    Chunk data looks like it was never tested. Have been trying for a few hours now and it absolutely is broken, and even older revisions did not work, I have written some isolated examples to prove it.

    Here's a simple extraction of the code used to set and restore the vec from the preset data, clearly showing the references point off into space.

    use std::os::raw::c_void;
    
    fn main() {
        let chunks = vec![11_u8, 22_u8, 33_u8];
        println!("chunks = {:?}", chunks);
        let len = chunks.len() as isize;
        let ptr: *mut *mut c_void = &mut (chunks.into_boxed_slice().as_ptr() as *mut c_void);
        println!("reading back..");
        let new_chunks = unsafe { std::slice::from_raw_parts(ptr as *mut u8, len as usize) };
        println!("new_chunks = {:?}", new_chunks);
    }
    

    This tries to transmute and recover the data from the raw pointer using the same functionality as the code, and I'm getting the same kind of output in the plugin. The size of the array is correct (send independently of ptr) but it points to nothing. example output:

    rob@tato ~/P/dd-plugs> rustc test.rs & ./test
    chunks = [11, 22, 33]
    reading back..
    new_chunks = [8, 80, 33]
    
    rob@tato ~/P/dd-plugs> rustc test.rs & ./test
    chunks = [11, 22, 33]
    reading back..
    new_chunks = [8, 80, 129]
    
    

    Each time returning different numbers (eg. pointers off to random data). Looking at it, I'm not sure how it was supposed to work to begin with, I mean, it seems to be stored as a *mut *mut c_void pointer to a Box, and recovered as an unboxed slice...?

    opened by monomadic 2
Owner
Marko Mijalkovic
Marko Mijalkovic
Easy Api in Rust to play Sounds

ears ears is a simple library to play sounds and music in Rust. Provides an access to the OpenAL spatialization functionality in a simple way. Accepts

Jan Niklas Hasse 82 Jan 1, 2023
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
This crate is an implementation of Sonic, a protocol for quickly verifiable, compact zero-knowledge proofs of arbitrary computations

Sonic This crate is an implementation of Sonic, a protocol for quickly verifiable, compact zero-knowledge proofs of arbitrary computations. Sonic is i

null 75 Jul 4, 2022
Spotify for the terminal written in Rust 🚀

Spotify TUI A Spotify client for the terminal written in Rust. The terminal in the demo above is using the Rigel theme. Spotify TUI Installation Homeb

Alexander Keliris 14.1k Jan 1, 2023
A rust binding for the FMOD library

rust-fmod This is a rust binding for FMOD, the library developped by FIRELIGHT TECHNOLOGIES. FMOD website : www.fmod.org You can also find it on crate

Guillaume Gomez 55 Nov 2, 2022
Idiomatic Rust bindings for OpenAL 1.1 and extensions (including EFX).

alto alto provides idiomatic Rust bindings for OpenAL 1.1 and extensions (including EFX). WARNING Because Alto interacts with global C state via dynam

null 80 Aug 7, 2022
High-level PortMidi bindings and wrappers for Rust

portmidi-rs High-level PortMidi bindings for Rust. PortMidi website: http://portmedia.sourceforge.net/portmidi/ Installation Add this to your Cargo.to

Philippe Delrieu 69 Dec 1, 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
PortAudio bindings and wrappers for Rust.

rust-portaudio PortAudio bindings and wrappers for Rust. PortAudio is a free, cross-platform, open-source, audio I/O library. rust-portaudio is still

null 331 Dec 23, 2022
A music theory guide written in Rust.

Rust Music Theory A library and executable that provides programmatic implementation of the basis of the music theory. Table of Contents Overview Usag

Ozan Kaşıkçı 551 Dec 21, 2022
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 Rust environment for sound synthesis and algorithmic composition.

Sorceress A Rust environment for sound synthesis and algorithmic composition, powered by SuperCollider. Overview Sorceress is a Rust crate that provid

Wesley Merkel 82 Dec 26, 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
Gtk/Rust native Spotify client for the GNOME desktop.

Gtk/Rust native Spotify client for the GNOME desktop.

Alexandre Trendel 1.7k Jan 1, 2023
mpc, but implemented in Rust.

rsmpc mpc, but implemented in Rust. Note: This is not meant to be a direct implementation, there will be some differences. For example: I moved the op

Cpt.Howdy 7 Jun 8, 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
A music bot build in Serenity/Rust.

Sunny Flowers is a Discord bot to play media in voice channels. It uses Serenity and Songbird to accomplish this.

Sophie 11 Nov 5, 2022
musify is a simple discord bot to play music within a voice channel, written in the rust programming language.

musify-rs musify is a simple discord bot to play music within a voice channel, written in the rust programming language. Features A simple song queue

NV6 5 Aug 14, 2022