Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to extract audio from an output #23

Closed
hughfdjackson opened this issue Mar 4, 2017 · 2 comments
Closed

Unable to extract audio from an output #23

hughfdjackson opened this issue Mar 4, 2017 · 2 comments

Comments

@hughfdjackson
Copy link

hughfdjackson commented Mar 4, 2017

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?

@Boscop
Copy link
Contributor

Boscop commented Mar 4, 2017

What's the error?
I think you have to drop buffer to be able to access out1 and out2 afterwards.
Because it holds references to them.
Maybe do this instead:

    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);
    } // buffer gets dropped here
    // read from out1, out2

And I think you should tell the plugin the sample rate and block size before you process().
https://github.com/overdrivenpotato/rust-vst2/blob/master/src/plugin.rs#L546
https://github.com/overdrivenpotato/rust-vst2/blob/master/src/plugin.rs#L549
And everytime you change the buffer size or sample rate, call suspend() on the plugin, then change them, then resume().
If you want to know exactly what you should do on a plugin before processing, see what other hosts do: Write a plugin that just logs the calls that the host does, to a file using log4rs, and then do the same. I did that a while ago but I don't remember everything they do, but they usually call can_do(), e.g. with CanDo::ReceiveEvents if they want to send midi to it.

@hughfdjackson
Copy link
Author

@Boscop : thanks a lot for that. I was getting errors like:

error[E0499]: cannot borrow `out1` as mutable more than once at a time
  --> src/main.rs:85:28
   |
80 |     let buffer = AudioBuffer::new(vec![&mut in1], vec![&mut out1, &mut out2]);
   |                                                             ---- first mutable borrow occurs here
...
85 |     println!("{:#?}", &mut out1);
   |                            ^^^^ second mutable borrow occurs here
...
92 | }
   | - first borrow ends here

As you explained, it was because the buffer had not yet been dropped. Once I limited the scope of the buffer, and only accessed out1, out2 or in1 after that, the borrower was happy again :)

I've also taken your advice about setting up the plugin with the sample rate and block size - will take a look at loading a 'debugging-based' plugin for use in other hosts. I think that will help me also know what midi events I need to send to my current plugin to get it to work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants