Module rsynth::utilities::polyphony

source ·
👎Deprecated since 0.1.1: Deprecated in favour of the dedicated polyphony crate.
Expand description

Utility to facilitate genarating different sounds at the same time (polyphony).

Polyphony consists of different steps:

  1. Classify how the event should be dispatched. How exactly it should be classified, is defined by the EventDispatchClass enum. The dispatching itself is done by a type that implements the EventDispatchClassifier trait.
  2. Next, a voice should be assigned to the event. The VoiceAssigner trait defines this action.
  3. Then, the event can be dispatched. The EventDispatcher trait and the ContextualEventDispatcher trait define methods for doing this.

Example of using polyphony

The following example illustrates a plugin (or application) that has multiple voices that correspond to different tones.

use rsynth::utilities::polyphony::{Voice, EventDispatchClassifier, ToneIdentifier,
    RawMidiEventToneIdentifierDispatchClassifier, ContextualEventDispatcher};
use rsynth::utilities::polyphony::simple_event_dispatching::SimpleVoiceState;
use rsynth::utilities::polyphony::simple_event_dispatching::SimpleEventDispatcher;
use rsynth::event::{ContextualEventHandler, Indexed, Timed, RawMidiEvent};
use rsynth::ContextualAudioRenderer;
use rsynth::buffer::AudioBufferInOut;

struct MyVoice {
    // ...
}

impl Voice<SimpleVoiceState<ToneIdentifier>> for MyVoice {
    fn state(&self) -> SimpleVoiceState<ToneIdentifier> {
        // Let the event dispatcher know what state this voice is in.
        unimplemented!();
    }
}

impl<Context> ContextualEventHandler<Timed<RawMidiEvent>, Context> for MyVoice {
    fn handle_event(&mut self, event: Timed<RawMidiEvent>, context: &mut Context) {
        // Here you typically change the state of the voice.
        unimplemented!()
    }
}

impl<Context> ContextualAudioRenderer<f32, Context> for MyVoice {
    fn render_buffer(&mut self, buffer: &mut AudioBufferInOut<f32>, context: &mut Context) {
        // Render one voice.
        unimplemented!()
    }
}

struct MyPlugin {
    voices: Vec<MyVoice>,
    // ...
}

impl<Context> ContextualEventHandler<Indexed<Timed<RawMidiEvent>>, Context> for MyPlugin
{
    fn handle_event(&mut self, event: Indexed<Timed<RawMidiEvent>>, context: &mut Context) {
        let mut dispatcher = SimpleEventDispatcher::new(RawMidiEventToneIdentifierDispatchClassifier);
        // Here we simply pass the context that we're given, but you can also pass a custom
        // context that uses shared data that is stored in `self`.
        dispatcher.dispatch_contextual_event(event.event, &mut self.voices, context);
    }
}

impl<Context> ContextualAudioRenderer<f32, Context> for MyPlugin
{
    fn render_buffer(&mut self, buffer: &mut AudioBufferInOut<f32>, context: &mut Context) {
        for voice in self.voices.iter_mut() {
            // Here we simply pass the context that we're given, but you can also pass a custom
            // context that uses shared data that is stored in `self`.
            voice.render_buffer(buffer, context);
        }
    }
}

Modules

Structs

Enums

Traits