#realtime #audio #lv2 #plugins #music

livi

livi is a library for hosting LV2 plugins

21 releases (4 breaking)

0.5.3 Mar 24, 2022
0.5.0 Feb 24, 2022
0.3.8 Nov 16, 2021

#190 in Audio

Download history 19/week @ 2022-01-28 20/week @ 2022-02-04 38/week @ 2022-02-11 90/week @ 2022-02-18 15/week @ 2022-02-25 13/week @ 2022-03-04 63/week @ 2022-03-11 120/week @ 2022-03-18 24/week @ 2022-03-25 9/week @ 2022-04-01 25/week @ 2022-04-08 13/week @ 2022-04-15 23/week @ 2022-04-22 128/week @ 2022-04-29 108/week @ 2022-05-06 359/week @ 2022-05-13

619 downloads per month

MIT license

94KB
2K SLoC

Livi

crates.io docs.rs

License: MIT Tests

A library for hosting LV2 plugins.

Note: This is a work in progress and has not yet been full tested.

Supported LV2 Features

LV2 has a simple core interface but is accompanied by extensions that can add lots of functionality. This library aims to support as many features as possible out of the box.

Quickstart

Below is an example on how to run the mda EPiano plugin.

let world = livi::World::new();
const SAMPLE_RATE: f64 = 44100.0;
let worker_manager = std::sync::Arc::new(livi::WorkerManager::default());
let features = world.build_features(livi::FeaturesBuilder {
    min_block_length: 1,
    max_block_length: 4096,
    worker_manager: worker_manager.clone(),
});
let plugin = world
    // This is the URI for mda EPiano. You can use the `lv2ls` command line
    // utility to see all available LV2 plugins.
    .plugin_by_uri("http://drobilla.net/plugins/mda/EPiano")
    .expect("Plugin not found.");
let mut instance = unsafe {
    plugin
        .instantiate(features.clone(), SAMPLE_RATE)
        .expect("Could not instantiate plugin.")
};

// Where midi events will be read from.
let input = {
    let mut s = livi::event::LV2AtomSequence::new(&features, 1024);
    let play_note_data = [0x90, 0x40, 0x7f];
    s.push_midi_event::<3>(1, features.midi_urid(), &play_note_data)
        .unwrap();
    s
};

// This is where the audio data will be stored.
let mut outputs = [
    vec![0.0; features.max_block_length()], // For mda EPiano, this is the left channel.
    vec![0.0; features.max_block_length()], // For mda EPiano, this is the right channel.
];

// Set up the port configuration and run the plugin!
// The results will be stored in `outputs`.
let ports = livi::EmptyPortConnections::new()
    .with_atom_sequence_inputs(std::iter::once(&input))
    .with_audio_outputs(outputs.iter_mut().map(|output| output.as_mut_slice()));
unsafe { instance.run(features.max_block_length(), ports).unwrap() };

// Plugins may push asynchronous works to the worker. When operating in
// Realtime, `run_workers` should be run in a separate thread.
std::thread::spawn(move || {
    worker_manager.run_workers();
    std::thread::sleep(std::time::Duration::from_millis(100));
});

std::thread::park();

Building, Testing, and Running

  • Build - cargo build
  • Test - cargo test, requires mda LV2 plugins.
  • Run livi-jack - cargo run --example livi-jack --release -- --plugin-uri=http://drobilla.net/plugins/mda/EPiano.

Dependencies

~1.5MB
~33K SLoC