1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! This is a stand-alone MIDI host with helpers for doing real-time handling of MIDI messages in
//! the audio-thread and to integrate with VST plugins.
//!
//! This is part of https://github.com/yamadapc/augmented-audio.
//!
//! ## Usage
//! To use this crate:
//!
//! * [`basedrop::Collector`] You'll need to set-up `basedrop` or `audio-garbage-collector`
//! * [`host::MidiHost`] should be created
//!   - This will connect to inputs & push messages to a queue
//! * [`audio_thread::MidiAudioThreadHandler`] On your audio thread you should pop from the queue
//!   - This is enough to add MIDI to a standalone [`audio_processor_traits::MidiEventHandler`]
//! * [`vst::MidiVSTConverter`] If you're implementing a host, you'll have to convert messages onto
//!   the VST API
//!
//! ```
//! use audio_processor_standalone_midi::audio_thread::MidiAudioThreadHandler;
//! use audio_processor_standalone_midi::host::MidiHost;
//! use audio_processor_standalone_midi::vst::MidiVSTConverter;
//! use basedrop::Collector;
//!
//! fn main() {
//!     // GC ======================================================================================
//!     // See `audio-garbage-collector` for an easier to use wrapper on top of this.
//!     //
//!     // `Collector` will let us use reference counted values on the audio-thread, which will be
//!     // pushed to a queue for de-allocation. You must set-up a background thread that forces it
//!     // to actually collect garbage from the queue.
//!     let gc = Collector::new();
//!     let handle = gc.handle();
//!
//!     // Host ====================================================================================
//!     // A host may be created with `new` or `default_with_handle`.
//!     let mut host = MidiHost::default_with_handle(&handle);
//!     // It'll connect to all MIDI input ports when started
//!     host.start().expect("Failed to connect");
//!     // The host will push messages onto a lock-free queue. This is a reference counted value.
//!     let midi_messages_queue = host.messages().clone();
//!
//!     // Audio-thread ============================================================================
//!     // ...
//!     // Within your audio-thread
//!     // ...
//!     // You'll want to share a `MidiAudioThreadHandler` between process calls as it pre-allocates
//!     // buffers.
//!     let mut midi_audio_thread_handler = MidiAudioThreadHandler::default();
//!
//!     // On each tick you'll call collect
//!     midi_audio_thread_handler.collect_midi_messages(&midi_messages_queue);
//!     // You'll get the MIDI message buffer
//!     let midi_messages = midi_audio_thread_handler.buffer();
//!     // ^ This is a `&Vec<MidiMessageEntry>`. If you're using `audio-processor-traits`, you can
//!     //   pass this into any `MidiEventHandler` implementor.
//!
//!     // VST interop =============================================================================
//!     // If you want to interface with a VST plugin, you'll need to convert messages into the
//!     // C-api.
//!     // ...
//!     // You'll want to share this between process calls as it pre-allocates buffers.
//!     let mut midi_vst_converter = MidiVSTConverter::default();
//!     midi_vst_converter.accept(&midi_messages);
//!     // This can be passed into VST plugins.
//!     let events: &vst::api::Events = midi_vst_converter.events();
//! }
//! ```

/// Audio-thread handling of messages
pub mod audio_thread;
/// Defaults
pub mod constants;
/// Hosting of MIDI
pub mod host;
/// VST API conversion
pub mod vst;