use audio::Audio;
use instrument::{self, Instrument};
use map::{self, Map};
use pitch;
use sample::{self, Frame, Sample as PcmSample};
use std;
use time;
use Velocity;
#[derive(Clone, Debug)]
pub struct Sampler<M, NFG, A>
where NFG: instrument::NoteFreqGenerator,
A: Audio,
{
pub instrument: Instrument<M, NFG>,
pub map: Map<A>,
voices: Voices<A>,
}
#[derive(Clone)]
pub struct Voices<A>
where A: Audio,
{
map: Vec<Option<PlayingSample<A>>>,
}
#[derive(Clone)]
pub struct PlayingSample<A>
where A: Audio,
{
pub note_on_hz: pitch::Hz,
pub note_on_vel: Velocity,
base_hz: pitch::Hz,
base_vel: Velocity,
pub rate_converter: sample::rate::Converter<Playhead<A>>,
pub time_of_note_on: std::time::Instant,
}
#[derive(Clone)]
pub struct Playhead<A>
where A: Audio,
{
pub idx: usize,
audio: A,
}
pub struct Frames<'a, A: 'a, NF: 'a>
where A: Audio,
{
voices: &'a mut Voices<A>,
instrument_frames: instrument::Frames<'a, NF>,
}
impl<A> std::fmt::Debug for Voices<A>
where A: Audio,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "Voices {{ num: {:?} }}", self.map.len())
}
}
impl<NFG, A> Sampler<instrument::mode::Mono, NFG, A>
where NFG: instrument::NoteFreqGenerator,
A: Audio,
{
pub fn legato(nfg: NFG, map: Map<A>) -> Self {
Self::new(instrument::mode::Mono::legato(), nfg, map)
}
}
impl<NFG, A> Sampler<instrument::mode::Mono, NFG, A>
where NFG: instrument::NoteFreqGenerator,
A: Audio,
{
pub fn retrigger(nfg: NFG, map: Map<A>) -> Self {
Self::new(instrument::mode::Mono::retrigger(), nfg, map)
}
}
impl<NFG, A> Sampler<instrument::mode::Poly, NFG, A>
where NFG: instrument::NoteFreqGenerator,
A: Audio,
{
pub fn poly(nfg: NFG, map: Map<A>) -> Self {
Self::new(instrument::mode::Poly, nfg, map)
}
}
impl<M, NFG, A> Sampler<M, NFG, A>
where NFG: instrument::NoteFreqGenerator,
A: Audio,
{
pub fn new(mode: M, note_freq_gen: NFG, map: Map<A>) -> Self {
let instrument = Instrument::new(mode, note_freq_gen);
let n_voices = instrument.voices.len();
Sampler {
map: map,
voices: Voices { map: vec![None; n_voices] },
instrument: instrument,
}
}
#[inline]
pub fn map_instrument<Map, NewM, NewNFG>(self, f: Map) -> Sampler<NewM, NewNFG, A>
where Map: FnOnce(Instrument<M, NFG>) -> Instrument<NewM, NewNFG>,
NewNFG: instrument::NoteFreqGenerator,
{
let Sampler {
map,
voices,
instrument,
} = self;
Sampler {
map: map,
voices: voices,
instrument: f(instrument),
}
}
pub fn num_voices(mut self, n: usize) -> Self {
self.set_num_voices(n);
self
}
pub fn voice_count(&self) -> usize {
self.voices.map.len()
}
pub fn detune(self, detune: f32) -> Self {
self.map_instrument(|inst| inst.detune(detune))
}
pub fn attack<Attack>(self, attack: Attack) -> Self
where Attack: Into<time::Ms>,
{
self.map_instrument(|inst| inst.attack(attack))
}
pub fn release<Release>(self, release: Release) -> Self
where Release: Into<time::Ms>,
{
self.map_instrument(|inst| inst.release(release))
}
pub fn set_num_voices(&mut self, n: usize) {
self.instrument.set_num_voices(n);
self.voices.map.resize(n, None);
}
#[inline]
pub fn note_on<T>(&mut self, note_hz: T, note_vel: Velocity)
where M: instrument::Mode + super::Mode,
T: Into<pitch::Hz>
{
let Sampler { ref mut instrument, ref mut voices, ref map, .. } = *self;
let hz = note_hz.into();
instrument.note_on(hz, note_vel);
super::Mode::note_on(&mut instrument.mode, hz, note_vel, map, &mut voices.map);
}
#[inline]
pub fn note_off<T>(&mut self, note_hz: T)
where M: instrument::Mode + super::Mode,
T: Into<pitch::Hz>
{
let Sampler { ref mut instrument, ref mut voices, ref map, .. } = *self;
let hz = note_hz.into();
super::Mode::note_off(&mut instrument.mode, hz, map, &mut voices.map);
instrument.note_off(hz);
}
#[inline]
pub fn stop(&mut self)
where M: instrument::Mode,
{
let Sampler { ref mut instrument, ref mut voices, .. } = *self;
instrument.stop();
voices.map.clear();
}
pub fn frames(&mut self, sample_hz: f64) -> Frames<A, NFG::NoteFreq>
where A: Audio,
<A::Frame as Frame>::Sample: sample::Duplex<f64>,
<<A::Frame as Frame>::Sample as PcmSample>::Float: sample::FromSample<f32>,
{
Frames {
voices: &mut self.voices,
instrument_frames: self.instrument.frames(sample_hz),
}
}
pub fn is_active(&self) -> bool {
for voice in &self.voices.map {
if voice.is_some() {
return true;
}
}
false
}
pub fn fill_slice<F>(&mut self, output: &mut [F], sample_hz: f64)
where F: Frame,
F::Sample: sample::Duplex<f64>,
<F::Sample as PcmSample>::Float: sample::FromSample<f32>,
A: Audio<Frame=F>,
{
let mut frames = self.frames(sample_hz);
sample::slice::map_in_place(output, |f| {
f.zip_map(frames.next_frame(), |a, b| {
a.add_amp(b.to_sample::<<F::Sample as PcmSample>::Signed>())
})
});
}
}
#[cfg(feature="serde_serialization")]
pub mod private {
use audio::Audio;
use instrument::{self, Instrument};
use map::Map;
pub fn new<M, NFG, A>(instrument: Instrument<M, NFG>,
map: Map<A>,
num_voices: usize) -> super::Sampler<M, NFG, A>
where NFG: instrument::NoteFreqGenerator,
A: Audio,
{
super::Sampler {
instrument: instrument,
map: map,
voices: super::Voices { map: vec![None; num_voices] },
}
}
}
impl<A> PlayingSample<A>
where A: Audio,
{
pub fn new(hz: pitch::Hz, vel: Velocity, sample: map::Sample<A>) -> Self {
Self::from_playhead_idx(0, hz, vel, sample)
}
pub fn from_playhead_idx(idx: usize,
hz: pitch::Hz,
vel: Velocity,
sample: map::Sample<A>) -> Self
{
let map::Sample { base_hz, base_vel, audio } = sample;
let playhead = Playhead::from_idx(idx, audio);
let rate_converter = sample::rate::Converter::scale_playback_hz(playhead, 1.0);
PlayingSample {
note_on_hz: hz,
note_on_vel: vel,
base_hz: base_hz,
base_vel: base_vel,
rate_converter: rate_converter,
time_of_note_on: std::time::Instant::now(),
}
}
}
impl<A> Playhead<A>
where A: Audio,
{
pub fn new(audio: A) -> Self {
Self::from_idx(0, audio)
}
pub fn from_idx(idx: usize, audio: A) -> Self {
Playhead {
idx: idx,
audio: audio,
}
}
}
impl<A> Iterator for Playhead<A>
where A: Audio,
{
type Item = A::Frame;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let idx = self.idx;
self.idx += 1;
Audio::data(&self.audio).get(idx).map(|&f| f)
}
}
impl<'a, A, NF> Frames<'a, A, NF>
where A: Audio,
<A::Frame as Frame>::Sample: sample::Duplex<f64>,
<<A::Frame as Frame>::Sample as PcmSample>::Float: sample::FromSample<f32>,
NF: instrument::NoteFreq,
{
#[inline]
pub fn next_frame(&mut self) -> A::Frame {
let Frames {
ref mut voices,
ref mut instrument_frames,
} = *self;
let frame_per_voice = instrument_frames.next_frame_per_voice();
let equilibrium = <A::Frame as Frame>::equilibrium();
voices.map.iter_mut()
.zip(frame_per_voice)
.fold(equilibrium, |frame, (voice, amp_hz)| {
if let Some((amp, hz)) = amp_hz {
match *voice {
None => return frame,
Some(ref mut voice) => {
let playback_hz_scale = hz / voice.base_hz.hz();
voice.rate_converter.set_playback_hz_scale(playback_hz_scale as f64);
match voice.rate_converter.next_frame() {
Some(wave) => {
let amp = amp * voice.base_vel;
let scaled = wave.scale_amp(amp.to_sample());
return frame.zip_map(scaled, |f, s| {
f.add_amp(s.to_sample::<<<A::Frame as Frame>::Sample as PcmSample>::Signed>())
});
},
None => return frame,
}
},
}
}
*voice = None;
frame
})
}
}
impl<'a, A, NF> Iterator for Frames<'a, A, NF>
where A: Audio,
<A::Frame as Frame>::Sample: sample::Duplex<f64>,
<<A::Frame as Frame>::Sample as PcmSample>::Float: sample::FromSample<f32>,
NF: instrument::NoteFreq,
{
type Item = A::Frame;
fn next(&mut self) -> Option<Self::Item> {
Some(self.next_frame())
}
}