use asprim::AsPrim;
use num_traits::Float;
use rand::{thread_rng, Rng};
use rsynth::event::{
ContextualEventHandler, EventHandler, Indexed, RawMidiEvent, SysExEvent, Timed,
};
use rsynth::utilities::polyphony::{
simple_event_dispatching::{SimpleEventDispatcher, SimpleVoiceState},
EventDispatcher, RawMidiEventToneIdentifierDispatchClassifier, ToneIdentifier, Voice,
};
use rsynth::{AudioHandler, ContextualAudioRenderer};
use std::default::Default;
use midi_consts::channel_event::*;
use rsynth::buffer::AudioBufferInOut;
use rsynth::meta::{InOut, Meta, MetaData};
static SAMPLE_SIZE: usize = 65536;
static NUMBER_OF_VOICES: usize = 6;
static AMPLIFY_MULTIPLIER: f32 = 1.0 / NUMBER_OF_VOICES as f32;
pub struct Noise {
white_noise: Vec<f32>,
position: usize,
amplitude: f32,
state: SimpleVoiceState<ToneIdentifier>,
}
impl Noise {
fn new(sample_size: usize) -> Self {
let mut rng = thread_rng();
let samples: Vec<f32> = rng
.gen_iter::<f32>()
.take(sample_size)
.map(|r| {
2.0 * r - 1.0
})
.collect::<Vec<f32>>();
Noise {
white_noise: samples,
position: 0,
amplitude: 0.0,
state: SimpleVoiceState::Idle,
}
}
fn render_audio_buffer<S>(&mut self, buffer: &mut AudioBufferInOut<S>)
where
S: AsPrim + Float,
{
if self.state == SimpleVoiceState::Idle {
return;
}
let outputs = buffer.outputs();
assert_eq!(2, outputs.number_of_channels());
for output_channel in outputs.channel_iter_mut() {
for sample in output_channel.iter_mut() {
*sample =
*sample + self.white_noise[self.position].as_::<S>() * self.amplitude.as_();
self.position = (self.position + 1) % self.white_noise.len();
}
}
}
}
impl Voice<SimpleVoiceState<ToneIdentifier>> for Noise {
fn state(&self) -> SimpleVoiceState<ToneIdentifier> {
self.state
}
}
impl EventHandler<Timed<RawMidiEvent>> for Noise {
fn handle_event(&mut self, timed: Timed<RawMidiEvent>) {
let state_and_chanel = timed.event.data()[0];
if state_and_chanel & EVENT_TYPE_MASK == NOTE_ON {
self.amplitude = timed.event.data()[2] as f32 / 127.0 * AMPLIFY_MULTIPLIER;
self.state = SimpleVoiceState::Active(ToneIdentifier(timed.event.data()[1]));
}
if state_and_chanel & EVENT_TYPE_MASK == NOTE_OFF {
self.amplitude = 0.0;
self.state = SimpleVoiceState::Idle;
}
}
}
pub struct NoisePlayer {
meta_data: MetaData<&'static str, &'static str, &'static str>,
voices: Vec<Noise>,
dispatcher: SimpleEventDispatcher<RawMidiEventToneIdentifierDispatchClassifier, Noise>,
}
impl NoisePlayer {
fn meta_data() -> MetaData<&'static str, &'static str, &'static str> {
MetaData {
general_meta: "Noise generator", audio_port_meta: InOut {
inputs: Vec::new(), outputs: vec!["left", "right"], },
midi_port_meta: InOut {
inputs: vec!["midi in"], outputs: Vec::new(), },
}
}
pub fn new() -> Self {
let mut voices = Vec::new();
for _ in 0..NUMBER_OF_VOICES {
voices.push(Noise::new(SAMPLE_SIZE));
}
Self {
meta_data: Self::meta_data(),
voices: voices,
dispatcher: SimpleEventDispatcher::default(),
}
}
}
impl Meta for NoisePlayer {
type MetaData = MetaData<&'static str, &'static str, &'static str>;
fn meta(&self) -> &Self::MetaData {
&self.meta_data
}
}
impl AudioHandler for NoisePlayer {
fn set_sample_rate(&mut self, sample_rate: f64) {
trace!("set_sample_rate(sample_rate={})", sample_rate);
}
}
#[allow(unused_variables)]
impl<S, Context> ContextualAudioRenderer<S, Context> for NoisePlayer
where
S: AsPrim + Float,
{
fn render_buffer(&mut self, buffer: &mut AudioBufferInOut<S>, _context: &mut Context) {
for noise in self.voices.iter_mut() {
noise.render_audio_buffer(buffer);
}
}
}
impl<Context> ContextualEventHandler<Timed<RawMidiEvent>, Context> for NoisePlayer {
fn handle_event(&mut self, event: Timed<RawMidiEvent>, _context: &mut Context) {
self.dispatcher.dispatch_event(event, &mut self.voices)
}
}
impl<Context> ContextualEventHandler<Indexed<Timed<RawMidiEvent>>, Context> for NoisePlayer {
fn handle_event(&mut self, event: Indexed<Timed<RawMidiEvent>>, context: &mut Context) {
self.handle_event(event.event, context)
}
}
impl<'a, Context> ContextualEventHandler<Timed<SysExEvent<'a>>, Context> for NoisePlayer {
fn handle_event(&mut self, _event: Timed<SysExEvent<'a>>, _context: &mut Context) {
}
}
impl<'a, Context> ContextualEventHandler<Indexed<Timed<SysExEvent<'a>>>, Context> for NoisePlayer {
fn handle_event(&mut self, event: Indexed<Timed<SysExEvent>>, context: &mut Context) {
self.handle_event(event.event, context)
}
}