├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── assets └── thumbpiano A#3.wav ├── examples └── wav.rs └── src ├── audio.rs ├── dynamic.rs ├── lib.rs ├── map.rs ├── mode.rs ├── sampler.rs └── serde.rs /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *~ 3 | *# 4 | *.o 5 | *.so 6 | *.swp 7 | *.dylib 8 | *.dSYM 9 | *.dll 10 | *.rlib 11 | *.dummy 12 | *.exe 13 | *-test 14 | /bin/main 15 | /bin/test-internal 16 | /bin/test-external 17 | /doc/ 18 | /target/ 19 | /build/ 20 | /.rust/ 21 | rusti.sh 22 | /examples/**/target 23 | 24 | Cargo.lock 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | rust: 4 | - stable 5 | - nightly 6 | 7 | os: 8 | - linux 9 | 10 | script: 11 | - cargo build --verbose 12 | - cargo build --no-default-features 13 | - cargo test --verbose 14 | - cargo test --features="serde_serialization" --verbose 15 | - cargo doc --verbose 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sampler" 3 | version = "0.2.0" 4 | authors = ["mitchmindtree "] 5 | description = "A polyphonic audio sampler instrument that supports unique sample mappings across both frequency and velocity ranges." 6 | readme = "README.md" 7 | keywords = ["sample", "dsp", "audio", "music", "instrument"] 8 | license = "MIT OR Apache-2.0" 9 | repository = "https://github.com/RustAudio/sampler.git" 10 | homepage = "https://github.com/RustAudio/sampler" 11 | 12 | [dependencies] 13 | instrument = "0.2.0" 14 | pitch_calc = "0.11.0" 15 | time_calc = "0.11.0" 16 | sample = "0.6.0" 17 | 18 | # optional dependencies 19 | hound = { optional = true, version = "2.0.0" } 20 | serde = { optional = true, version = "0.7.0" } 21 | serde_json = { optional = true, version = "0.7.0" } 22 | find_folder = { optional = true, version = "0.3.0" } 23 | 24 | [features] 25 | default = ["wav"] 26 | wav = ["hound"] 27 | serde_serialization = [ 28 | "serde", 29 | "serde_json", 30 | "time_calc/serde_serialization", 31 | "pitch_calc/serde_serialization", 32 | "instrument/serde_serialization", 33 | "find_folder", 34 | ] 35 | 36 | [dev-dependencies] 37 | find_folder = "0.3.0" 38 | portaudio = "0.6.4" 39 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Mitchell Nordine 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Mitchell Nordine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sampler [![Build Status](https://travis-ci.org/RustAudio/sampler.svg?branch=master)](https://travis-ci.org/RustAudio/sampler) [![Crates.io](https://img.shields.io/crates/v/sampler.svg)](https://crates.io/crates/sampler) [![Crates.io](https://img.shields.io/crates/l/sampler.svg)](https://github.com/RustAudio/sampler/blob/master/LICENSE) 2 | -------------------------------------------------------------------------------- /assets/thumbpiano A#3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RustAudio/sampler/18d3af63411e8cf3aedf04501342c10cba2a5190/assets/thumbpiano A#3.wav -------------------------------------------------------------------------------- /examples/wav.rs: -------------------------------------------------------------------------------- 1 | extern crate find_folder; // For easily finding the assets folder. 2 | extern crate portaudio as pa; // For audio I/O 3 | extern crate pitch_calc as pitch; // To work with musical notes. 4 | extern crate sample; // To convert portaudio sample buffers to frames. 5 | extern crate sampler; 6 | 7 | use sampler::Sampler; 8 | 9 | const CHANNELS: i32 = 2; 10 | const SAMPLE_RATE: f64 = 44_100.0; 11 | const FRAMES_PER_BUFFER: u32 = 64; 12 | const THUMB_PIANO: &'static str = "thumbpiano A#3.wav"; 13 | 14 | 15 | fn main() { 16 | run().unwrap(); 17 | } 18 | 19 | fn run() -> Result<(), pa::Error> { 20 | 21 | // We'll create a sample map that maps a single sample to the entire note range. 22 | let assets = find_folder::Search::ParentsThenKids(5, 5).for_folder("assets").unwrap(); 23 | let sample = sampler::Sample::from_wav_file(assets.join(THUMB_PIANO), SAMPLE_RATE).unwrap(); 24 | let sample_map = sampler::Map::from_single_sample(sample); 25 | 26 | // Create a polyphonic sampler. 27 | let mut sampler = Sampler::poly((), sample_map).num_voices(4); 28 | 29 | // Initialise PortAudio and create an output stream. 30 | let pa = try!(pa::PortAudio::new()); 31 | let settings = 32 | try!(pa.default_output_stream_settings::(CHANNELS, SAMPLE_RATE, FRAMES_PER_BUFFER)); 33 | 34 | let callback = move |pa::OutputStreamCallbackArgs { buffer, .. }| { 35 | let buffer: &mut [[f32; CHANNELS as usize]] = 36 | sample::slice::to_frame_slice_mut(buffer).unwrap(); 37 | sample::slice::equilibrium(buffer); 38 | 39 | // If the sampler is not currently active, play a note. 40 | if !sampler.is_active() { 41 | let vel = 0.3; 42 | sampler.note_on(pitch::LetterOctave(pitch::Letter::Ash, 3).to_hz(), vel); 43 | sampler.note_on(pitch::LetterOctave(pitch::Letter::Dsh, 3).to_hz(), vel); 44 | sampler.note_on(pitch::LetterOctave(pitch::Letter::Gsh, 1).to_hz(), vel); 45 | } 46 | 47 | sampler.fill_slice(buffer, SAMPLE_RATE); 48 | 49 | pa::Continue 50 | }; 51 | 52 | let mut stream = try!(pa.open_non_blocking_stream(settings, callback)); 53 | 54 | try!(stream.start()); 55 | 56 | while let Ok(true) = stream.is_active() { 57 | std::thread::sleep(std::time::Duration::from_millis(16)); 58 | } 59 | 60 | try!(stream.stop()); 61 | try!(stream.close()); 62 | 63 | Ok(()) 64 | } 65 | -------------------------------------------------------------------------------- /src/audio.rs: -------------------------------------------------------------------------------- 1 | use sample; 2 | use std; 3 | 4 | 5 | /// The audio data that provides the slice of frames that are to be rendered. 6 | /// 7 | /// By making this a trait instead of a hard type, we can allow users to use their own `Audio` 8 | /// types which might require other data (i.e. file paths, names, etc) for unique serialization 9 | /// implementations. 10 | pub trait Audio: Clone { 11 | /// The type of `Frame` data associated with the audio. 12 | type Frame: sample::Frame; 13 | /// A reference to the slice of frames used to play the audio. 14 | fn data(&self) -> &[Self::Frame]; 15 | } 16 | 17 | /// A wrapper around `sampler::map::Audio` types that slices a specific range of frames. 18 | #[derive(Clone, Debug, PartialEq)] 19 | pub struct Range { 20 | /// The start index of the range. 21 | pub start: usize, 22 | /// The end index of the range. 23 | pub end: usize, 24 | /// Some audio type that implements `Audio` and can yield a slice of frames. 25 | pub audio: A, 26 | } 27 | 28 | 29 | impl Range { 30 | /// Construct a new `Range` with a max playback range. 31 | pub fn new(audio: A) -> Self 32 | where A: Audio, 33 | { 34 | Range { 35 | start: 0, 36 | end: audio.data().len(), 37 | audio: audio, 38 | } 39 | } 40 | } 41 | 42 | impl Audio for std::sync::Arc 43 | where A: Audio, 44 | { 45 | type Frame = A::Frame; 46 | #[inline] 47 | fn data(&self) -> &[Self::Frame] { 48 | A::data(self) 49 | } 50 | } 51 | 52 | impl Audio for Range 53 | where A: Audio, 54 | { 55 | type Frame = A::Frame; 56 | #[inline] 57 | fn data(&self) -> &[Self::Frame] { 58 | let slice = self.audio.data(); 59 | let len = slice.len(); 60 | if self.start < len && self.end <= len { 61 | &slice[self.start..self.end] 62 | } else { 63 | &[] 64 | } 65 | } 66 | } 67 | 68 | 69 | #[cfg(feature="wav")] 70 | pub mod wav { 71 | use hound; 72 | use sample; 73 | use std; 74 | 75 | 76 | /// WAV data loaded into memory as a single contiguous slice of PCM frames. 77 | #[derive(Clone, Debug, PartialEq)] 78 | pub struct Audio { 79 | pub path: std::path::PathBuf, 80 | pub data: Box<[F]>, 81 | pub sample_hz: f64, 82 | } 83 | 84 | /// Errors that may occur during `WAV` loading 85 | #[derive(Debug)] 86 | pub enum Error { 87 | /// Some error returned from the `hound` crate during sample loading. 88 | Hound(hound::Error), 89 | /// The bit depth of the given WAV file is unsupported. 90 | UnsupportedBitsPerSample(u16), 91 | /// There is no obvious way to map the given channels described in the WAV spec to the 92 | /// number of channels in the `Frame` type. 93 | /// 94 | /// Contains the source number of channels and the target number of channels. 95 | UnsupportedChannelMapping(u16, u16), 96 | } 97 | 98 | 99 | impl super::Audio for Audio 100 | where F: sample::Frame, 101 | { 102 | type Frame = F; 103 | fn data(&self) -> &[Self::Frame] { 104 | &self.data[..] 105 | } 106 | } 107 | 108 | impl Audio 109 | where F: sample::Frame, 110 | F::Sample: sample::Duplex + sample::Duplex, 111 | Box<[F::Sample]>: sample::ToBoxedFrameSlice, 112 | { 113 | 114 | /// Loads a `Sample` from the `.wav` file at the given `path`. 115 | /// 116 | /// The PCM data retrieved from the file will be: 117 | /// - re-sized from its source bit rate to that of the target and 118 | /// - re-sampled upon loading (rather than at playback) to the given target sample rate for 119 | /// efficiency. 120 | pub fn from_file

(path: P, target_sample_hz: f64) -> Result 121 | where P: AsRef, 122 | { 123 | use sample::{Frame, Sample, Signal}; 124 | 125 | let path = path.as_ref(); 126 | let mut wav_reader = try!(hound::WavReader::open(path)); 127 | 128 | let spec = wav_reader.spec(); 129 | 130 | // Collect the samples in a loop so that we may handle any errors if necessary. 131 | let mut samples: Vec = Vec::new(); 132 | 133 | // Reads the samples to their correct format type, and then converts them to the target 134 | // `F::Sample` type. 135 | type WavReader = hound::WavReader>; 136 | fn fill_samples(samples: &mut Vec, mut wav_reader: WavReader) 137 | -> Result<(), hound::Error> 138 | where S: sample::FromSample, 139 | H: sample::Sample + sample::ToSample + hound::Sample, 140 | { 141 | for sample in wav_reader.samples() { 142 | let read_sample: H = try!(sample); 143 | let i32_sample: i32 = sample::Sample::to_sample(read_sample); 144 | samples.push(sample::Sample::to_sample(i32_sample)); 145 | } 146 | Ok(()) 147 | } 148 | 149 | match spec.sample_format { 150 | hound::SampleFormat::Float => match spec.bits_per_sample { 151 | 32 => try!(fill_samples::<_, f32>(&mut samples, wav_reader)), 152 | n => return Err(Error::UnsupportedBitsPerSample(n)), 153 | }, 154 | hound::SampleFormat::Int => match spec.bits_per_sample { 155 | 8 => try!(fill_samples::<_, i8>(&mut samples, wav_reader)), 156 | 16 => try!(fill_samples::<_, i16>(&mut samples, wav_reader)), 157 | 32 => try!(fill_samples::<_, i32>(&mut samples, wav_reader)), 158 | // The sample crate uses a specific type for 24 bit samples, so this 24-bit sample 159 | // conversion requires this special case. 160 | 24 => { 161 | for sample in wav_reader.samples() { 162 | let read_sample: i32 = try!(sample); 163 | let i24_sample = try!(sample::I24::new(read_sample) 164 | .ok_or(hound::Error::FormatError("Incorrectly formatted 24-bit sample \ 165 | received from hound::read::WavSamples"))); 166 | let i32_sample: i32 = sample::Sample::to_sample(i24_sample); 167 | samples.push(sample::Sample::to_sample(i32_sample)); 168 | } 169 | }, 170 | n => return Err(Error::UnsupportedBitsPerSample(n)), 171 | }, 172 | } 173 | 174 | let boxed_samples = samples.into_boxed_slice(); 175 | let boxed_frames: Box<[F]> = match (spec.channels, F::n_channels() as u16) { 176 | 177 | // In the case that the `spec` has a different number of channels to the actual 178 | // slice, just collect as many valid frames as we can and discard the final 179 | // mismatching frame. 180 | (source, target) if source == target => { 181 | let samples = boxed_samples.iter().cloned(); 182 | let vec: Vec = sample::signal::from_interleaved_samples(samples) 183 | .collect(); 184 | vec.into_boxed_slice() 185 | }, 186 | 187 | // Sum the left and right channels together when mapping to a mono signal. 188 | (2, 1) => { 189 | let samples = boxed_samples.iter().cloned(); 190 | let vec: Vec = 191 | sample::signal::from_interleaved_samples::<_, [F::Sample; 2]>(samples) 192 | .filter_map(|f| { 193 | let mut channels = f.channels(); 194 | channels.next() 195 | .and_then(|l| channels.next().map(|r| (l, r))) 196 | .map(|(l, r)| { 197 | let sum = l.add_amp(r.to_signed_sample()); 198 | F::from_fn(|_| sum) 199 | }) 200 | }) 201 | .collect(); 202 | vec.into_boxed_slice() 203 | }, 204 | 205 | // Simply copy the single mono channel to both channels in the output stereo 206 | // signal. 207 | (1, 2) => { 208 | let samples = boxed_samples.iter().cloned(); 209 | let vec: Vec = samples.map(|s| F::from_fn(|_| s)).collect(); 210 | vec.into_boxed_slice() 211 | }, 212 | 213 | (source, target) => { 214 | return Err(Error::UnsupportedChannelMapping(source, target)) 215 | }, 216 | 217 | }; 218 | 219 | // Convert the sample rate to our target sample rate. 220 | let frames: Vec = boxed_frames.iter().cloned() 221 | .from_hz_to_hz(spec.sample_rate as f64, target_sample_hz) 222 | .collect(); 223 | 224 | Ok(Audio { 225 | path: path.to_path_buf(), 226 | sample_hz: target_sample_hz, 227 | data: frames.into_boxed_slice(), 228 | }) 229 | } 230 | 231 | } 232 | 233 | impl From for Error { 234 | fn from(err: hound::Error) -> Self { 235 | Error::Hound(err) 236 | } 237 | } 238 | 239 | impl std::error::Error for Error { 240 | fn description(&self) -> &str { 241 | match *self { 242 | Error::Hound(ref hound) => std::error::Error::description(hound), 243 | Error::UnsupportedBitsPerSample(_n_bits) => "unsupported bits per sample", 244 | Error::UnsupportedChannelMapping(_source, _target) => "unsupported channel mapping", 245 | } 246 | } 247 | } 248 | 249 | impl std::fmt::Display for Error { 250 | fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 251 | std::fmt::Debug::fmt(self, f) 252 | } 253 | } 254 | 255 | } 256 | -------------------------------------------------------------------------------- /src/dynamic.rs: -------------------------------------------------------------------------------- 1 | use audio; 2 | use instrument; 3 | use map; 4 | use sampler; 5 | 6 | /// An alias for a dynamic `Mode` type. 7 | pub type Mode = instrument::mode::Dynamic; 8 | 9 | /// An alias for a dynamic `NoteFreqGenerator` type. 10 | pub type NoteFreqGenerator = instrument::note_freq::DynamicGenerator; 11 | 12 | /// An alias for a `Sampler` type that uses a dynamic instrument and note frequency mode. 13 | pub type Sampler = sampler::Sampler; 14 | 15 | impl Sampler 16 | where A: audio::Audio, 17 | { 18 | 19 | /// Construct a dynamic `Sampler`. 20 | pub fn dynamic(mode: instrument::mode::Dynamic, map: map::Map) -> Self { 21 | let nfg = instrument::note_freq::DynamicGenerator::Constant; 22 | Self::new(mode, nfg, map) 23 | } 24 | 25 | /// Construct a dynamic `Sampler` initialised with a `Mono::Legato` playback mode. 26 | pub fn dynamic_legato(map: map::Map) -> Self { 27 | Self::dynamic(instrument::mode::Dynamic::legato(), map) 28 | } 29 | 30 | /// Construct a dynamic `Sampler` initialised with a `Mono::Retrigger` playback mode. 31 | pub fn dynamic_retrigger(map: map::Map) -> Self { 32 | Self::dynamic(instrument::mode::Dynamic::retrigger(), map) 33 | } 34 | 35 | /// Construct a dynamic `Sampler` initialised with a `Poly` playback mode. 36 | pub fn dynamic_poly(map: map::Map) -> Self { 37 | Self::dynamic(instrument::mode::Dynamic::poly(), map) 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature="wav")] extern crate hound; 2 | pub extern crate instrument; 3 | pub extern crate sample; 4 | extern crate pitch_calc as pitch; 5 | extern crate time_calc as time; 6 | 7 | pub use audio::Audio; 8 | pub use map::{Map, Sample}; 9 | pub use mode::Mode; 10 | pub use sampler::{Frames, Sampler}; 11 | 12 | pub mod audio; 13 | pub mod dynamic; 14 | pub mod map; 15 | mod mode; 16 | mod sampler; 17 | 18 | #[cfg(feature="serde_serialization")] 19 | mod serde; 20 | 21 | /// `pitch::Step` represented in discretes intervals, useful for range mapping. 22 | pub type Step = i16; 23 | /// The force with which a note was pressed on a keyboard. 24 | pub type Velocity = f32; 25 | 26 | pub const MIN_STEP: Step = 0; 27 | pub const MAX_STEP: Step = 127; 28 | -------------------------------------------------------------------------------- /src/map.rs: -------------------------------------------------------------------------------- 1 | use {Step, Velocity, MIN_STEP, MAX_STEP}; 2 | use audio::Audio; 3 | use pitch; 4 | 5 | 6 | /// A type that maps frequncy and velocity ranges to audio samples. 7 | #[derive(Clone, Debug, PartialEq)] 8 | pub struct Map { 9 | pub pairs: Vec>, 10 | } 11 | 12 | /// A performable `Sample` with some base playback Hz and Velocity. 13 | #[derive(Clone, Debug, PartialEq)] 14 | pub struct Sample { 15 | pub base_hz: pitch::Hz, 16 | pub base_vel: Velocity, 17 | pub audio: A, 18 | } 19 | 20 | /// A 2-dimensional space, represented as a frequency range and a velocity range. 21 | #[derive(Clone, Debug, PartialEq, PartialOrd)] 22 | pub struct StepVelRange { 23 | pub step: Range, 24 | pub vel: Range, 25 | } 26 | 27 | /// A range paired with a specific sample. 28 | #[derive(Clone, Debug, PartialEq)] 29 | pub struct SampleOverRange { 30 | pub range: StepVelRange, 31 | pub sample: Sample, 32 | } 33 | 34 | /// A continuous range of `T` from the `min` to the `max`. 35 | #[derive(Clone, Debug, PartialEq, PartialOrd)] 36 | pub struct Range { 37 | pub min: T, 38 | pub max: T, 39 | } 40 | 41 | 42 | impl Range { 43 | /// Is the given step greater than or equal to the `min` and smaller than the `max`. 44 | pub fn is_over(&self, step: Step) -> bool { 45 | self.min <= step && step <= self.max 46 | } 47 | } 48 | 49 | impl Range { 50 | /// Is the given velocity greater than or equal to the `min` and smaller than the `max`. 51 | pub fn is_over(&self, vel: Velocity) -> bool { 52 | self.min <= vel && vel <= self.max 53 | } 54 | } 55 | 56 | impl Sample { 57 | 58 | /// Constructor for a new `Sample` with the given base Hz and Velocity. 59 | pub fn new(base_hz: pitch::Hz, base_vel: Velocity, audio: A) -> Self { 60 | Sample { 61 | base_hz: base_hz, 62 | base_vel: base_vel, 63 | audio: audio, 64 | } 65 | } 66 | 67 | /// Maps the `Sample` with some `Audio` type `A` to a `Sample` with some `Audio` type `B`. 68 | pub fn map_audio(self, map: F) -> Sample 69 | where F: FnOnce(A) -> B, 70 | { 71 | let Sample { base_hz, base_vel, audio } = self; 72 | Sample { 73 | base_hz: base_hz, 74 | base_vel: base_vel, 75 | audio: map(audio), 76 | } 77 | } 78 | 79 | } 80 | 81 | impl Map 82 | where A: Audio, 83 | { 84 | 85 | /// Construct an empty `Map`. 86 | pub fn empty() -> Self { 87 | Map { pairs: vec![] } 88 | } 89 | 90 | /// Construct a `Map` from a series of mappings, starting from (-C2, 1.0). 91 | pub fn from_sequential_steps(mappings: I) -> Self 92 | where I: IntoIterator)>, 93 | { 94 | let (mut last_step, mut last_vel) = (0, 1.0); 95 | let pairs = mappings.into_iter().map(|(step, vel, sample)| { 96 | let range = StepVelRange { 97 | step: Range { min: last_step, max: step }, 98 | vel: Range { min: last_vel, max: vel }, 99 | }; 100 | last_step = step; 101 | last_vel = vel; 102 | SampleOverRange { range: range, sample: sample } 103 | }).collect(); 104 | Map { pairs: pairs } 105 | } 106 | 107 | /// Creates a `Map` with a single sample mapped to the entire Step and Velocity range. 108 | pub fn from_single_sample(sample: Sample) -> Self { 109 | let range = StepVelRange { 110 | step: Range { min: MIN_STEP, max: MAX_STEP }, 111 | vel: Range { min: 0.0, max: 1.0 }, 112 | }; 113 | let pairs = vec![SampleOverRange { range: range, sample: sample }]; 114 | Map { pairs: pairs } 115 | } 116 | 117 | /// Inserts a range -> audio mapping into the Map. 118 | pub fn insert(&mut self, range: StepVelRange, sample: Sample) { 119 | for i in 0..self.pairs.len() { 120 | if self.pairs[i].range > range { 121 | self.pairs.insert(i, SampleOverRange { range: range, sample: sample }); 122 | return; 123 | } 124 | } 125 | self.pairs.push(SampleOverRange { range: range, sample: sample }); 126 | } 127 | 128 | /// Returns the `Audio` associated with the range within which the given hz and velocity exist. 129 | /// 130 | /// TODO: This would probably be quicker with some sort of specialised RangeMap. 131 | pub fn sample(&self, hz: pitch::Hz, vel: Velocity) -> Option> { 132 | let step = hz.step().round() as Step; 133 | for &SampleOverRange { ref range, ref sample } in &self.pairs { 134 | if range.step.is_over(step) && range.vel.is_over(vel) { 135 | return Some(sample.clone()); 136 | } 137 | } 138 | None 139 | } 140 | 141 | } 142 | 143 | 144 | #[cfg(feature="wav")] 145 | pub mod wav { 146 | use audio; 147 | use map; 148 | use pitch; 149 | use sample; 150 | use std; 151 | 152 | 153 | /// An alias for the `wav` `Sample` type. 154 | pub type Sample = super::Sample>>; 155 | 156 | 157 | impl Sample 158 | where F: sample::Frame, 159 | F::Sample: sample::Duplex + sample::Duplex, 160 | Box<[F::Sample]>: sample::ToBoxedFrameSlice, 161 | { 162 | 163 | /// Loads a `Sample` from the `.wav` file at the given `path`. 164 | /// 165 | /// If the `.wav` file has a musical note in the file name, that note's playback frequency in 166 | /// `hz` will be used as the `base_hz`. 167 | /// 168 | /// If a musical note cannot be determined automatically, a default `C1` will be used. 169 | /// 170 | /// The PCM data retrieved from the file will be re-sampled upon loading (rather than at 171 | /// playback) to the given target sample rate for efficiency. 172 | pub fn from_wav_file

(path: P, target_sample_hz: f64) -> Result 173 | where P: AsRef, 174 | { 175 | let path = path.as_ref(); 176 | 177 | const DEFAULT_LETTER_OCTAVE: pitch::LetterOctave = pitch::LetterOctave(pitch::Letter::C, 1); 178 | let base_letter_octave = read_base_letter_octave(path).unwrap_or(DEFAULT_LETTER_OCTAVE); 179 | let base_hz = base_letter_octave.to_hz(); 180 | let base_vel = 1.0; 181 | 182 | let audio = std::sync::Arc::new(try!(audio::wav::Audio::from_file(path, target_sample_hz))); 183 | 184 | Ok(map::Sample::new(base_hz, base_vel, audio)) 185 | } 186 | } 187 | 188 | 189 | /// Scans the given path for an indication of its pitch. 190 | fn read_base_letter_octave(path: &std::path::Path) -> Option { 191 | use pitch::Letter::*; 192 | use std::ascii::AsciiExt; 193 | 194 | let s = path.to_str().map_or("".into(), |s| s.to_ascii_lowercase()); 195 | 196 | // Check to see if the path contains a note for the given `letter` for any octave 197 | // between -8 and 24. If so, return the `LetterOctave`. 198 | let contains_letter = |letter: &str| -> Option { 199 | for i in -8i8..24 { 200 | let pattern = format!("{}{}", letter, i); 201 | if s.contains(&pattern) { 202 | let letter = match letter { 203 | "c" => C, 204 | "c#" | "csh" => Csh, 205 | "d" => D, 206 | "d#" | "dsh" => Dsh, 207 | "e" => E, 208 | "f" => F, 209 | "f#" | "fsh" => Fsh, 210 | "g" => G, 211 | "g#" | "gsh" => Gsh, 212 | "a" => A, 213 | "a#" | "ash" => Ash, 214 | "b" => B, 215 | _ => unreachable!(), 216 | }; 217 | return Some(pitch::LetterOctave(letter, i as pitch::Octave)); 218 | } 219 | } 220 | None 221 | }; 222 | 223 | let list = [ 224 | "c", "c#", "csh", "d", "d#", "dsh", "e", "f", "f#", "fsh", "g", "g#", "gsh", 225 | "a", "a#", "ash", "b", 226 | ]; 227 | 228 | for letter in &list[..] { 229 | if let Some(letter_octave) = contains_letter(letter) { 230 | return Some(letter_octave); 231 | } 232 | } 233 | 234 | None 235 | } 236 | 237 | } 238 | -------------------------------------------------------------------------------- /src/mode.rs: -------------------------------------------------------------------------------- 1 | use audio::Audio; 2 | use instrument; 3 | use map::Map; 4 | use pitch; 5 | use sampler::PlayingSample; 6 | use std; 7 | use Velocity; 8 | 9 | pub use instrument::mode::{Mono, MonoKind, Poly, Dynamic}; 10 | 11 | /// The "mode" with which the Sampler will handle notes. 12 | pub trait Mode { 13 | 14 | /// Handle a `note_on` event. 15 | /// 16 | /// Is called immediately following `instrument::Mode::note_on`. 17 | fn note_on(&self, 18 | note_hz: pitch::Hz, 19 | note_velocity: Velocity, 20 | map: &Map, 21 | voices: &mut [Option>]) 22 | where A: Audio; 23 | 24 | /// Handle a `note_off` event. 25 | fn note_off(&self, 26 | note_hz: pitch::Hz, 27 | map: &Map, 28 | voices: &mut [Option>]) 29 | where A: Audio; 30 | } 31 | 32 | 33 | // Helper function for constructing a `PlayingSample`. 34 | fn play_sample(hz: pitch::Hz, vel: Velocity, map: &Map) -> Option> 35 | where A: Audio, 36 | { 37 | play_sample_from_playhead_idx(0, hz, vel, map) 38 | } 39 | 40 | // Helper function for constructing a `PlayingSample` with a given playhead index. 41 | fn play_sample_from_playhead_idx(idx: usize, 42 | hz: pitch::Hz, 43 | vel: Velocity, 44 | map: &Map) -> Option> 45 | where A: Audio, 46 | { 47 | map.sample(hz, vel).map(|sample| PlayingSample::from_playhead_idx(idx, hz, vel, sample)) 48 | } 49 | 50 | 51 | impl Mode for Mono { 52 | 53 | fn note_on(&self, 54 | note_hz: pitch::Hz, 55 | note_vel: Velocity, 56 | map: &Map, 57 | voices: &mut [Option>]) 58 | where A: Audio, 59 | { 60 | let Mono(ref kind, ref note_stack) = *self; 61 | 62 | // If we're in `Legato` mode, begin the note from the same index as the previous note's 63 | // current state if there is one. 64 | let sample = if let instrument::mode::MonoKind::Legato = *kind { 65 | note_stack.last() 66 | .and_then(|&last_hz| { 67 | voices.iter() 68 | .filter_map(|v| v.as_ref()) 69 | .find(|sample| instrument::mode::does_hz_match(sample.note_on_hz.hz(), last_hz)) 70 | .and_then(|sample| { 71 | let idx = sample.rate_converter.source().idx; 72 | play_sample_from_playhead_idx(idx, note_hz, note_vel, map) 73 | }) 74 | }) 75 | .or_else(|| play_sample(note_hz, note_vel, map)) 76 | // Otherwise, we're in `Retrigger` mode, so start from the beginning of the sample. 77 | } else { 78 | play_sample(note_hz, note_vel, map) 79 | }; 80 | 81 | if let Some(sample) = sample { 82 | for voice in voices { 83 | *voice = Some(sample.clone()); 84 | } 85 | } 86 | } 87 | 88 | fn note_off(&self, 89 | note_hz: pitch::Hz, 90 | map: &Map, 91 | voices: &mut [Option>]) 92 | where A: Audio, 93 | { 94 | let Mono(kind, ref note_stack) = *self; 95 | 96 | let should_reset = voices.iter() 97 | .filter_map(|v| v.as_ref()) 98 | .any(|v| instrument::mode::does_hz_match(v.note_on_hz.hz(), note_hz.hz())); 99 | 100 | if !should_reset { 101 | return; 102 | } 103 | 104 | // If there is some note to fall back to, do so. 105 | if let Some(&fallback_note_hz) = note_stack.last() { 106 | let hz = fallback_note_hz.into(); 107 | for voice in voices { 108 | if let Some(ref mut playing_sample) = *voice { 109 | let idx = match kind { 110 | MonoKind::Retrigger => 0, 111 | MonoKind::Legato => playing_sample.rate_converter.source().idx, 112 | }; 113 | let vel = playing_sample.note_on_vel; 114 | if let Some(sample) = play_sample_from_playhead_idx(idx, hz, vel, map) { 115 | *playing_sample = sample; 116 | } 117 | } 118 | } 119 | } 120 | 121 | // No need to manually set voices to `None` as this will be done when frames yielded by 122 | // `instrument` run out. 123 | } 124 | 125 | } 126 | 127 | impl Mode for Poly { 128 | 129 | fn note_on(&self, 130 | note_hz: pitch::Hz, 131 | note_vel: Velocity, 132 | map: &Map, 133 | voices: &mut [Option>]) 134 | where A: Audio, 135 | { 136 | let sample = match play_sample(note_hz, note_vel, map) { 137 | Some(sample) => sample, 138 | None => return, 139 | }; 140 | 141 | // Find the right voice to play the note. 142 | let mut oldest = None; 143 | let mut oldest_time_of_note_on = std::time::Instant::now(); 144 | for voice in voices.iter_mut() { 145 | if let None = *voice { 146 | *voice = Some(sample); 147 | return; 148 | } 149 | let time_of_note_on = voice.as_ref().unwrap().time_of_note_on; 150 | if time_of_note_on < oldest_time_of_note_on { 151 | oldest_time_of_note_on = time_of_note_on; 152 | oldest = voice.as_mut(); 153 | } 154 | } 155 | if let Some(voice) = oldest { 156 | *voice = sample; 157 | } 158 | } 159 | 160 | fn note_off(&self, 161 | _note_hz: pitch::Hz, 162 | _map: &Map, 163 | _voices: &mut [Option>]) 164 | where A: Audio, 165 | { 166 | // No need to do anything here as voices will be set to `None` when frames yielded by 167 | // `instrument` run out. 168 | } 169 | 170 | } 171 | 172 | impl Mode for Dynamic { 173 | 174 | fn note_on(&self, 175 | note_hz: pitch::Hz, 176 | note_vel: Velocity, 177 | map: &Map, 178 | voices: &mut [Option>]) 179 | where A: Audio, 180 | { 181 | match *self { 182 | Dynamic::Mono(ref mono) => mono.note_on(note_hz, note_vel, map, voices), 183 | Dynamic::Poly(ref poly) => poly.note_on(note_hz, note_vel, map, voices), 184 | } 185 | } 186 | 187 | fn note_off(&self, 188 | note_hz: pitch::Hz, 189 | map: &Map, 190 | voices: &mut [Option>]) 191 | where A: Audio, 192 | { 193 | match *self { 194 | Dynamic::Mono(ref mono) => mono.note_off(note_hz, map, voices), 195 | Dynamic::Poly(ref poly) => poly.note_off(note_hz, map, voices), 196 | } 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /src/sampler.rs: -------------------------------------------------------------------------------- 1 | use audio::Audio; 2 | use instrument::{self, Instrument}; 3 | use map::{self, Map}; 4 | use pitch; 5 | use sample::{self, Frame, Sample as PcmSample}; 6 | use std; 7 | use time; 8 | use Velocity; 9 | 10 | /// A Sampler instrument. 11 | #[derive(Clone, Debug)] 12 | pub struct Sampler 13 | where NFG: instrument::NoteFreqGenerator, 14 | A: Audio, 15 | { 16 | pub instrument: Instrument, 17 | pub map: Map, 18 | voices: Voices, 19 | } 20 | 21 | /// Samples that are currently active along with the `Hz` with which they were triggered. 22 | /// 23 | /// A new pair is pushed on each `note_on`, and pairs are removed on their associated `note_off`. 24 | /// 25 | /// In `Mono` mode, the sampler always fills the buffer using the last pair on the stack. 26 | /// 27 | /// In `Poly` mode, each pair is mapped directly to each of the `Instrument`'s `voices` via their 28 | /// `Vec` indices. 29 | #[derive(Clone)] 30 | pub struct Voices 31 | where A: Audio, 32 | { 33 | map: Vec>>, 34 | } 35 | 36 | /// A sample that is currently being played back. 37 | #[derive(Clone)] 38 | pub struct PlayingSample 39 | where A: Audio, 40 | { 41 | /// The pitch in hz at which the `note_on` was triggered. 42 | pub note_on_hz: pitch::Hz, 43 | pub note_on_vel: Velocity, 44 | base_hz: pitch::Hz, 45 | base_vel: Velocity, 46 | /// Rate-adjustable interpolation of audio. 47 | pub rate_converter: sample::rate::Converter>, 48 | /// The time at which the `PlayingSample` was constructed. 49 | pub time_of_note_on: std::time::Instant, 50 | } 51 | 52 | /// An owned iterator that wraps an audio file but does not 53 | #[derive(Clone)] 54 | pub struct Playhead 55 | where A: Audio, 56 | { 57 | /// The position of the playhead over the `Sample`. 58 | pub idx: usize, 59 | audio: A, 60 | } 61 | 62 | /// An iterator yielding one frame from the `Sampler` at a time. 63 | pub struct Frames<'a, A: 'a, NF: 'a> 64 | where A: Audio, 65 | { 66 | voices: &'a mut Voices, 67 | instrument_frames: instrument::Frames<'a, NF>, 68 | } 69 | 70 | 71 | impl std::fmt::Debug for Voices 72 | where A: Audio, 73 | { 74 | fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 75 | write!(f, "Voices {{ num: {:?} }}", self.map.len()) 76 | } 77 | } 78 | 79 | impl Sampler 80 | where NFG: instrument::NoteFreqGenerator, 81 | A: Audio, 82 | { 83 | /// Construct a `Sampler` with a `Mono::Legato` playback mode. 84 | pub fn legato(nfg: NFG, map: Map) -> Self { 85 | Self::new(instrument::mode::Mono::legato(), nfg, map) 86 | } 87 | } 88 | 89 | impl Sampler 90 | where NFG: instrument::NoteFreqGenerator, 91 | A: Audio, 92 | { 93 | /// Construct a `Sampler` with a `Mono::Retrigger` playback mode. 94 | pub fn retrigger(nfg: NFG, map: Map) -> Self { 95 | Self::new(instrument::mode::Mono::retrigger(), nfg, map) 96 | } 97 | } 98 | 99 | impl Sampler 100 | where NFG: instrument::NoteFreqGenerator, 101 | A: Audio, 102 | { 103 | /// Construct a `Sampler` with a `Poly` playback mode. 104 | pub fn poly(nfg: NFG, map: Map) -> Self { 105 | Self::new(instrument::mode::Poly, nfg, map) 106 | } 107 | } 108 | 109 | 110 | impl Sampler 111 | where NFG: instrument::NoteFreqGenerator, 112 | A: Audio, 113 | { 114 | 115 | /// Construct a new `Sampler`. 116 | pub fn new(mode: M, note_freq_gen: NFG, map: Map) -> Self { 117 | let instrument = Instrument::new(mode, note_freq_gen); 118 | let n_voices = instrument.voices.len(); 119 | Sampler { 120 | map: map, 121 | voices: Voices { map: vec![None; n_voices] }, 122 | instrument: instrument, 123 | } 124 | } 125 | 126 | /// Map the `Instrument` to a new `Instrument` in place. 127 | /// 128 | /// This is useful for providing wrapper builder methods for the Synth. 129 | #[inline] 130 | pub fn map_instrument(self, f: Map) -> Sampler 131 | where Map: FnOnce(Instrument) -> Instrument, 132 | NewNFG: instrument::NoteFreqGenerator, 133 | { 134 | let Sampler { 135 | map, 136 | voices, 137 | instrument, 138 | } = self; 139 | 140 | Sampler { 141 | map: map, 142 | voices: voices, 143 | instrument: f(instrument), 144 | } 145 | } 146 | 147 | /// Build the `Sampler` with the given number of voices. 148 | pub fn num_voices(mut self, n: usize) -> Self { 149 | self.set_num_voices(n); 150 | self 151 | } 152 | 153 | /// Return the number of voices for use within the `Sampler`. 154 | pub fn voice_count(&self) -> usize { 155 | self.voices.map.len() 156 | } 157 | 158 | /// Detune the `note_on` hz by the given amount. 159 | pub fn detune(self, detune: f32) -> Self { 160 | self.map_instrument(|inst| inst.detune(detune)) 161 | } 162 | 163 | /// Set the attack. 164 | pub fn attack(self, attack: Attack) -> Self 165 | where Attack: Into, 166 | { 167 | self.map_instrument(|inst| inst.attack(attack)) 168 | } 169 | 170 | /// Set the release. 171 | pub fn release(self, release: Release) -> Self 172 | where Release: Into, 173 | { 174 | self.map_instrument(|inst| inst.release(release)) 175 | } 176 | 177 | /// Set the number of voices to use for 178 | pub fn set_num_voices(&mut self, n: usize) { 179 | self.instrument.set_num_voices(n); 180 | self.voices.map.resize(n, None); 181 | } 182 | 183 | /// Begin playback of a note. 184 | #[inline] 185 | pub fn note_on(&mut self, note_hz: T, note_vel: Velocity) 186 | where M: instrument::Mode + super::Mode, 187 | T: Into 188 | { 189 | let Sampler { ref mut instrument, ref mut voices, ref map, .. } = *self; 190 | let hz = note_hz.into(); 191 | instrument.note_on(hz, note_vel); 192 | super::Mode::note_on(&mut instrument.mode, hz, note_vel, map, &mut voices.map); 193 | } 194 | 195 | /// Stop playback of the note that was triggered with the matching frequency. 196 | #[inline] 197 | pub fn note_off(&mut self, note_hz: T) 198 | where M: instrument::Mode + super::Mode, 199 | T: Into 200 | { 201 | let Sampler { ref mut instrument, ref mut voices, ref map, .. } = *self; 202 | let hz = note_hz.into(); 203 | super::Mode::note_off(&mut instrument.mode, hz, map, &mut voices.map); 204 | instrument.note_off(hz); 205 | } 206 | 207 | /// Stop playback and clear the current notes. 208 | #[inline] 209 | pub fn stop(&mut self) 210 | where M: instrument::Mode, 211 | { 212 | let Sampler { ref mut instrument, ref mut voices, .. } = *self; 213 | instrument.stop(); 214 | voices.map.clear(); 215 | } 216 | 217 | /// Produces an iterator that yields `Frame`s of audio data. 218 | pub fn frames(&mut self, sample_hz: f64) -> Frames 219 | where A: Audio, 220 | ::Sample: sample::Duplex, 221 | <::Sample as PcmSample>::Float: sample::FromSample, 222 | { 223 | Frames { 224 | voices: &mut self.voices, 225 | instrument_frames: self.instrument.frames(sample_hz), 226 | } 227 | } 228 | 229 | /// Returns whether or not the `Sampler` is currently playing any notes. 230 | pub fn is_active(&self) -> bool { 231 | for voice in &self.voices.map { 232 | if voice.is_some() { 233 | return true; 234 | } 235 | } 236 | false 237 | } 238 | 239 | /// Fills the given slice of frames with the `Sampler::frames` iterator. 240 | pub fn fill_slice(&mut self, output: &mut [F], sample_hz: f64) 241 | where F: Frame, 242 | F::Sample: sample::Duplex, 243 | ::Float: sample::FromSample, 244 | A: Audio, 245 | { 246 | let mut frames = self.frames(sample_hz); 247 | sample::slice::map_in_place(output, |f| { 248 | f.zip_map(frames.next_frame(), |a, b| { 249 | a.add_amp(b.to_sample::<::Signed>()) 250 | }) 251 | }); 252 | } 253 | 254 | } 255 | 256 | 257 | #[cfg(feature="serde_serialization")] 258 | pub mod private { 259 | use audio::Audio; 260 | use instrument::{self, Instrument}; 261 | use map::Map; 262 | 263 | /// A private constructor for use within serde.rs. 264 | pub fn new(instrument: Instrument, 265 | map: Map, 266 | num_voices: usize) -> super::Sampler 267 | where NFG: instrument::NoteFreqGenerator, 268 | A: Audio, 269 | { 270 | super::Sampler { 271 | instrument: instrument, 272 | map: map, 273 | voices: super::Voices { map: vec![None; num_voices] }, 274 | } 275 | } 276 | } 277 | 278 | 279 | impl PlayingSample 280 | where A: Audio, 281 | { 282 | 283 | /// Construct a new `PlayingSample` from the given note hz, velocity and the associated 284 | /// `Sample` from the `Map`. 285 | pub fn new(hz: pitch::Hz, vel: Velocity, sample: map::Sample) -> Self { 286 | Self::from_playhead_idx(0, hz, vel, sample) 287 | } 288 | 289 | /// Construct a new `PlayingSample` from the given note hz, velocity and the associated 290 | /// `Sample` from the `Map`. 291 | /// 292 | /// The given `Sample`'s audio will begin playing from the given `idx`. 293 | pub fn from_playhead_idx(idx: usize, 294 | hz: pitch::Hz, 295 | vel: Velocity, 296 | sample: map::Sample) -> Self 297 | { 298 | let map::Sample { base_hz, base_vel, audio } = sample; 299 | let playhead = Playhead::from_idx(idx, audio); 300 | let rate_converter = sample::rate::Converter::scale_playback_hz(playhead, 1.0); 301 | PlayingSample { 302 | note_on_hz: hz, 303 | note_on_vel: vel, 304 | base_hz: base_hz, 305 | base_vel: base_vel, 306 | rate_converter: rate_converter, 307 | time_of_note_on: std::time::Instant::now(), 308 | } 309 | } 310 | 311 | } 312 | 313 | 314 | impl Playhead 315 | where A: Audio, 316 | { 317 | /// Wrap the given `Audio` with a `Playhead` starting from 0. 318 | pub fn new(audio: A) -> Self { 319 | Self::from_idx(0, audio) 320 | } 321 | 322 | /// Wrap the given `Audio` with a `Playhead` starting from the given playhead index. 323 | pub fn from_idx(idx: usize, audio: A) -> Self { 324 | Playhead { 325 | idx: idx, 326 | audio: audio, 327 | } 328 | } 329 | } 330 | 331 | impl Iterator for Playhead 332 | where A: Audio, 333 | { 334 | type Item = A::Frame; 335 | #[inline] 336 | fn next(&mut self) -> Option { 337 | let idx = self.idx; 338 | self.idx += 1; 339 | Audio::data(&self.audio).get(idx).map(|&f| f) 340 | } 341 | } 342 | 343 | 344 | impl<'a, A, NF> Frames<'a, A, NF> 345 | where A: Audio, 346 | ::Sample: sample::Duplex, 347 | <::Sample as PcmSample>::Float: sample::FromSample, 348 | NF: instrument::NoteFreq, 349 | { 350 | /// Yields the next audio `Frame`. 351 | #[inline] 352 | pub fn next_frame(&mut self) -> A::Frame { 353 | let Frames { 354 | ref mut voices, 355 | ref mut instrument_frames, 356 | } = *self; 357 | 358 | let frame_per_voice = instrument_frames.next_frame_per_voice(); 359 | let equilibrium = ::equilibrium(); 360 | voices.map.iter_mut() 361 | .zip(frame_per_voice) 362 | .fold(equilibrium, |frame, (voice, amp_hz)| { 363 | if let Some((amp, hz)) = amp_hz { 364 | match *voice { 365 | None => return frame, 366 | Some(ref mut voice) => { 367 | let playback_hz_scale = hz / voice.base_hz.hz(); 368 | voice.rate_converter.set_playback_hz_scale(playback_hz_scale as f64); 369 | match voice.rate_converter.next_frame() { 370 | Some(wave) => { 371 | let amp = amp * voice.base_vel; 372 | let scaled = wave.scale_amp(amp.to_sample()); 373 | return frame.zip_map(scaled, |f, s| { 374 | f.add_amp(s.to_sample::<<::Sample as PcmSample>::Signed>()) 375 | }); 376 | }, 377 | None => return frame, 378 | } 379 | }, 380 | } 381 | } 382 | 383 | // If we made it this far, the voice has finished playback of the note. 384 | *voice = None; 385 | frame 386 | }) 387 | } 388 | } 389 | 390 | impl<'a, A, NF> Iterator for Frames<'a, A, NF> 391 | where A: Audio, 392 | ::Sample: sample::Duplex, 393 | <::Sample as PcmSample>::Float: sample::FromSample, 394 | NF: instrument::NoteFreq, 395 | { 396 | type Item = A::Frame; 397 | fn next(&mut self) -> Option { 398 | Some(self.next_frame()) 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /src/serde.rs: -------------------------------------------------------------------------------- 1 | extern crate serde; 2 | 3 | 4 | mod audio_range { 5 | use audio::Range; 6 | use super::serde; 7 | use std; 8 | 9 | impl serde::Serialize for Range 10 | where T: serde::Serialize, 11 | { 12 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 13 | where S: serde::Serializer, 14 | { 15 | struct Visitor<'a, T: 'a> { 16 | t: &'a Range, 17 | field_idx: u8, 18 | } 19 | 20 | impl<'a, T> serde::ser::MapVisitor for Visitor<'a, T> 21 | where T: serde::Serialize, 22 | { 23 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 24 | where S: serde::Serializer, 25 | { 26 | match self.field_idx { 27 | 0 => { 28 | self.field_idx += 1; 29 | Ok(Some(try!(serializer.serialize_struct_elt("start", &self.t.start)))) 30 | }, 31 | 1 => { 32 | self.field_idx += 1; 33 | Ok(Some(try!(serializer.serialize_struct_elt("end", &self.t.end)))) 34 | }, 35 | 2 => { 36 | self.field_idx += 1; 37 | Ok(Some(try!(serializer.serialize_struct_elt("audio", &self.t.audio)))) 38 | }, 39 | _ => Ok(None), 40 | } 41 | } 42 | 43 | fn len(&self) -> Option { 44 | Some(3) 45 | } 46 | } 47 | 48 | serializer.serialize_struct("Range", Visitor { t: self, field_idx: 0 }) 49 | } 50 | } 51 | 52 | impl serde::Deserialize for Range 53 | where T: serde::Deserialize, 54 | { 55 | fn deserialize(deserializer: &mut D) -> Result 56 | where D: serde::Deserializer, 57 | { 58 | struct Visitor { 59 | t: std::marker::PhantomData, 60 | }; 61 | 62 | impl serde::de::Visitor for Visitor 63 | where T: serde::Deserialize, 64 | { 65 | type Value = Range; 66 | 67 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 68 | where V: serde::de::MapVisitor, 69 | { 70 | let mut start = None; 71 | let mut end = None; 72 | let mut audio = None; 73 | 74 | enum Field { Start, End, Audio } 75 | 76 | impl serde::Deserialize for Field { 77 | fn deserialize(deserializer: &mut D) -> Result 78 | where D: serde::de::Deserializer, 79 | { 80 | struct FieldVisitor; 81 | 82 | impl serde::de::Visitor for FieldVisitor { 83 | type Value = Field; 84 | 85 | fn visit_str(&mut self, value: &str) -> Result 86 | where E: serde::de::Error, 87 | { 88 | match value { 89 | "start" => Ok(Field::Start), 90 | "end" => Ok(Field::End), 91 | "audio" => Ok(Field::Audio), 92 | _ => Err(serde::de::Error::custom("expected start, end or audio")), 93 | } 94 | } 95 | } 96 | 97 | deserializer.deserialize(FieldVisitor) 98 | } 99 | } 100 | 101 | loop { 102 | match try!(visitor.visit_key()) { 103 | Some(Field::Start) => { start = Some(try!(visitor.visit_value())); }, 104 | Some(Field::End) => { end = Some(try!(visitor.visit_value())); }, 105 | Some(Field::Audio) => { audio = Some(try!(visitor.visit_value())); }, 106 | None => { break; } 107 | } 108 | } 109 | 110 | let start = match start { 111 | Some(start) => start, 112 | None => return Err(serde::de::Error::missing_field("start")), 113 | }; 114 | 115 | let end = match end { 116 | Some(end) => end, 117 | None => return Err(serde::de::Error::missing_field("end")), 118 | }; 119 | 120 | let audio = match audio { 121 | Some(audio) => audio, 122 | None => return Err(serde::de::Error::missing_field("audio")), 123 | }; 124 | 125 | try!(visitor.end()); 126 | 127 | Ok(Range { 128 | start: start, 129 | end: end, 130 | audio: audio, 131 | }) 132 | } 133 | } 134 | 135 | static FIELDS: &'static [&'static str] = &["start", "end", "audio"]; 136 | 137 | let visitor = Visitor { t: std::marker::PhantomData }; 138 | 139 | deserializer.deserialize_struct("Range", FIELDS, visitor) 140 | } 141 | } 142 | 143 | #[test] 144 | fn test() { 145 | extern crate serde_json; 146 | 147 | use audio::Audio; 148 | 149 | impl Audio for () { 150 | type Frame = [f32; 2]; 151 | fn data(&self) -> &[Self::Frame] { &[] } 152 | } 153 | 154 | let range = Range { start: 0, end: 0, audio: () }; 155 | let serialized = serde_json::to_string(&range).unwrap(); 156 | 157 | println!("{}", serialized); 158 | assert_eq!("{\"start\":0,\"end\":0,\"audio\":null}", serialized); 159 | 160 | let deserialized: Range<()> = serde_json::from_str(&serialized).unwrap(); 161 | 162 | println!("{:?}", deserialized); 163 | assert_eq!(range, deserialized); 164 | } 165 | 166 | 167 | } 168 | 169 | mod range { 170 | use super::serde; 171 | use map::Range; 172 | use std; 173 | 174 | impl serde::Serialize for Range 175 | where T: serde::Serialize, 176 | { 177 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 178 | where S: serde::Serializer, 179 | { 180 | struct Visitor<'a, T: 'a> { 181 | t: &'a Range, 182 | field_idx: u8, 183 | } 184 | 185 | impl<'a, T> serde::ser::MapVisitor for Visitor<'a, T> 186 | where T: serde::Serialize, 187 | { 188 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 189 | where S: serde::Serializer, 190 | { 191 | match self.field_idx { 192 | 0 => { 193 | self.field_idx += 1; 194 | Ok(Some(try!(serializer.serialize_struct_elt("min", &self.t.min)))) 195 | }, 196 | 1 => { 197 | self.field_idx += 1; 198 | Ok(Some(try!(serializer.serialize_struct_elt("max", &self.t.max)))) 199 | }, 200 | _ => Ok(None), 201 | } 202 | } 203 | 204 | fn len(&self) -> Option { 205 | Some(2) 206 | } 207 | } 208 | 209 | serializer.serialize_struct("Range", Visitor { t: self, field_idx: 0 }) 210 | } 211 | } 212 | 213 | impl serde::Deserialize for Range 214 | where T: serde::Deserialize, 215 | { 216 | fn deserialize(deserializer: &mut D) -> Result 217 | where D: serde::Deserializer, 218 | { 219 | struct Visitor { 220 | t: std::marker::PhantomData, 221 | }; 222 | 223 | impl serde::de::Visitor for Visitor 224 | where T: serde::Deserialize, 225 | { 226 | type Value = Range; 227 | 228 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 229 | where V: serde::de::MapVisitor, 230 | { 231 | let mut min = None; 232 | let mut max = None; 233 | 234 | enum Field { Min, Max } 235 | 236 | impl serde::Deserialize for Field { 237 | fn deserialize(deserializer: &mut D) -> Result 238 | where D: serde::de::Deserializer, 239 | { 240 | struct FieldVisitor; 241 | 242 | impl serde::de::Visitor for FieldVisitor { 243 | type Value = Field; 244 | 245 | fn visit_str(&mut self, value: &str) -> Result 246 | where E: serde::de::Error, 247 | { 248 | match value { 249 | "min" => Ok(Field::Min), 250 | "max" => Ok(Field::Max), 251 | _ => Err(serde::de::Error::custom("expected min or max")), 252 | } 253 | } 254 | } 255 | 256 | deserializer.deserialize(FieldVisitor) 257 | } 258 | } 259 | 260 | loop { 261 | match try!(visitor.visit_key()) { 262 | Some(Field::Min) => { min = Some(try!(visitor.visit_value())); }, 263 | Some(Field::Max) => { max = Some(try!(visitor.visit_value())); }, 264 | None => { break; } 265 | } 266 | } 267 | 268 | let min = match min { 269 | Some(min) => min, 270 | None => return Err(serde::de::Error::missing_field("min")), 271 | }; 272 | 273 | let max = match max { 274 | Some(max) => max, 275 | None => return Err(serde::de::Error::missing_field("max")), 276 | }; 277 | 278 | try!(visitor.end()); 279 | 280 | Ok(Range { min: min, max: max }) 281 | } 282 | } 283 | 284 | static FIELDS: &'static [&'static str] = &["min", "max"]; 285 | 286 | let visitor = Visitor { t: std::marker::PhantomData }; 287 | 288 | deserializer.deserialize_struct("Range", FIELDS, visitor) 289 | } 290 | } 291 | 292 | #[test] 293 | fn test() { 294 | extern crate serde_json; 295 | 296 | let range = Range { min: 220.0, max: 440.0 }; 297 | let serialized = serde_json::to_string(&range).unwrap(); 298 | 299 | println!("{}", serialized); 300 | assert_eq!("{\"min\":220,\"max\":440}", serialized); 301 | 302 | let deserialized: Range = serde_json::from_str(&serialized).unwrap(); 303 | 304 | println!("{:?}", deserialized); 305 | assert_eq!(range, deserialized); 306 | } 307 | 308 | } 309 | 310 | 311 | mod sample { 312 | use super::serde; 313 | use map::Sample; 314 | use std; 315 | 316 | impl serde::Serialize for Sample 317 | where A: serde::Serialize, 318 | { 319 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 320 | where S: serde::Serializer, 321 | { 322 | struct Visitor<'a, A: 'a> { 323 | t: &'a Sample, 324 | field_idx: u8, 325 | } 326 | 327 | impl<'a, A> serde::ser::MapVisitor for Visitor<'a, A> 328 | where A: serde::Serialize, 329 | { 330 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 331 | where S: serde::Serializer, 332 | { 333 | match self.field_idx { 334 | 0 => { 335 | self.field_idx += 1; 336 | Ok(Some(try!(serializer.serialize_struct_elt("base_hz", &self.t.base_hz)))) 337 | }, 338 | 1 => { 339 | self.field_idx += 1; 340 | Ok(Some(try!(serializer.serialize_struct_elt("base_vel", &self.t.base_vel)))) 341 | }, 342 | 2 => { 343 | self.field_idx += 1; 344 | Ok(Some(try!(serializer.serialize_struct_elt("audio", &self.t.audio)))) 345 | }, 346 | _ => Ok(None), 347 | } 348 | } 349 | 350 | fn len(&self) -> Option { 351 | Some(3) 352 | } 353 | } 354 | 355 | serializer.serialize_struct("Sample", Visitor { t: self, field_idx: 0 }) 356 | } 357 | } 358 | 359 | impl serde::Deserialize for Sample 360 | where A: serde::Deserialize, 361 | { 362 | fn deserialize(deserializer: &mut D) -> Result 363 | where D: serde::Deserializer, 364 | { 365 | struct Visitor { 366 | t: std::marker::PhantomData, 367 | }; 368 | 369 | impl serde::de::Visitor for Visitor 370 | where A: serde::Deserialize, 371 | { 372 | type Value = Sample; 373 | 374 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 375 | where V: serde::de::MapVisitor, 376 | { 377 | let mut base_hz = None; 378 | let mut base_vel = None; 379 | let mut audio = None; 380 | 381 | enum Field { BaseHz, BaseVel, Audio } 382 | 383 | impl serde::Deserialize for Field { 384 | fn deserialize(deserializer: &mut D) -> Result 385 | where D: serde::de::Deserializer, 386 | { 387 | struct FieldVisitor; 388 | 389 | impl serde::de::Visitor for FieldVisitor { 390 | type Value = Field; 391 | 392 | fn visit_str(&mut self, value: &str) -> Result 393 | where E: serde::de::Error, 394 | { 395 | match value { 396 | "base_hz" => Ok(Field::BaseHz), 397 | "base_vel" => Ok(Field::BaseVel), 398 | "audio" => Ok(Field::Audio), 399 | _ => Err(serde::de::Error::custom("expected base_hz, base_vel or audio")), 400 | } 401 | } 402 | } 403 | 404 | deserializer.deserialize(FieldVisitor) 405 | } 406 | } 407 | 408 | loop { 409 | match try!(visitor.visit_key()) { 410 | Some(Field::BaseHz) => { base_hz = Some(try!(visitor.visit_value())); }, 411 | Some(Field::BaseVel) => { base_vel = Some(try!(visitor.visit_value())); }, 412 | Some(Field::Audio) => { audio = Some(try!(visitor.visit_value())); }, 413 | None => { break; } 414 | } 415 | } 416 | 417 | let base_hz = match base_hz { 418 | Some(base_hz) => base_hz, 419 | None => return Err(serde::de::Error::missing_field("base_hz")), 420 | }; 421 | 422 | let base_vel = match base_vel { 423 | Some(base_vel) => base_vel, 424 | None => return Err(serde::de::Error::missing_field("base_vel")), 425 | }; 426 | 427 | let audio = match audio { 428 | Some(audio) => audio, 429 | None => return Err(serde::de::Error::missing_field("audio")), 430 | }; 431 | 432 | try!(visitor.end()); 433 | 434 | Ok(Sample { 435 | base_hz: base_hz, 436 | base_vel: base_vel, 437 | audio: audio, 438 | }) 439 | } 440 | } 441 | 442 | static FIELDS: &'static [&'static str] = &["base_hz", "base_vel", "audio"]; 443 | 444 | let visitor = Visitor { t: std::marker::PhantomData }; 445 | 446 | deserializer.deserialize_struct("Sample", FIELDS, visitor) 447 | } 448 | } 449 | 450 | #[test] 451 | fn test() { 452 | extern crate serde_json; 453 | 454 | let sample = Sample { base_hz: 440.0.into(), base_vel: 1.0, audio: () }; 455 | let serialized = serde_json::to_string(&sample).unwrap(); 456 | 457 | println!("{}", serialized); 458 | assert_eq!("{\"base_hz\":440,\"base_vel\":1,\"audio\":null}", serialized); 459 | 460 | let deserialized: Sample<()> = serde_json::from_str(&serialized).unwrap(); 461 | 462 | println!("{:?}", deserialized); 463 | assert_eq!(sample, deserialized); 464 | } 465 | 466 | } 467 | 468 | mod sample_over_range { 469 | use super::serde; 470 | use map::SampleOverRange; 471 | use std; 472 | 473 | impl serde::Serialize for SampleOverRange 474 | where A: serde::Serialize, 475 | { 476 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 477 | where S: serde::Serializer, 478 | { 479 | struct Visitor<'a, A: 'a> { 480 | t: &'a SampleOverRange, 481 | field_idx: u8, 482 | } 483 | 484 | impl<'a, A> serde::ser::MapVisitor for Visitor<'a, A> 485 | where A: serde::Serialize, 486 | { 487 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 488 | where S: serde::Serializer, 489 | { 490 | match self.field_idx { 491 | 0 => { 492 | self.field_idx += 1; 493 | Ok(Some(try!(serializer.serialize_struct_elt("range", &self.t.range)))) 494 | }, 495 | 1 => { 496 | self.field_idx += 1; 497 | Ok(Some(try!(serializer.serialize_struct_elt("sample", &self.t.sample)))) 498 | }, 499 | _ => Ok(None), 500 | } 501 | } 502 | 503 | fn len(&self) -> Option { 504 | Some(2) 505 | } 506 | } 507 | 508 | serializer.serialize_struct("SampleOverRange", Visitor { t: self, field_idx: 0 }) 509 | } 510 | } 511 | 512 | impl serde::Deserialize for SampleOverRange 513 | where A: serde::Deserialize, 514 | { 515 | fn deserialize(deserializer: &mut D) -> Result 516 | where D: serde::Deserializer, 517 | { 518 | struct Visitor { 519 | t: std::marker::PhantomData, 520 | }; 521 | 522 | impl serde::de::Visitor for Visitor 523 | where A: serde::Deserialize, 524 | { 525 | type Value = SampleOverRange; 526 | 527 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 528 | where V: serde::de::MapVisitor, 529 | { 530 | let mut range = None; 531 | let mut sample = None; 532 | 533 | enum Field { Range, Sample } 534 | 535 | impl serde::Deserialize for Field { 536 | fn deserialize(deserializer: &mut D) -> Result 537 | where D: serde::de::Deserializer, 538 | { 539 | struct FieldVisitor; 540 | 541 | impl serde::de::Visitor for FieldVisitor { 542 | type Value = Field; 543 | 544 | fn visit_str(&mut self, value: &str) -> Result 545 | where E: serde::de::Error, 546 | { 547 | match value { 548 | "range" => Ok(Field::Range), 549 | "sample" => Ok(Field::Sample), 550 | _ => Err(serde::de::Error::custom("expected range or sample")), 551 | } 552 | } 553 | } 554 | 555 | deserializer.deserialize(FieldVisitor) 556 | } 557 | } 558 | 559 | loop { 560 | match try!(visitor.visit_key()) { 561 | Some(Field::Range) => { range = Some(try!(visitor.visit_value())); }, 562 | Some(Field::Sample) => { sample = Some(try!(visitor.visit_value())); }, 563 | None => { break; } 564 | } 565 | } 566 | 567 | let range = match range { 568 | Some(range) => range, 569 | None => return Err(serde::de::Error::missing_field("range")), 570 | }; 571 | 572 | let sample = match sample { 573 | Some(sample) => sample, 574 | None => return Err(serde::de::Error::missing_field("sample")), 575 | }; 576 | 577 | try!(visitor.end()); 578 | 579 | Ok(SampleOverRange { range: range, sample: sample }) 580 | } 581 | } 582 | 583 | static FIELDS: &'static [&'static str] = &["range", "sample"]; 584 | 585 | let visitor = Visitor { t: std::marker::PhantomData }; 586 | 587 | deserializer.deserialize_struct("Range", FIELDS, visitor) 588 | } 589 | } 590 | 591 | #[test] 592 | fn test() { 593 | extern crate serde_json; 594 | 595 | use map; 596 | 597 | // impl Audio for () { 598 | // type Frame = [f32; 2]; 599 | // fn data(&self) -> &[Self::Frame] { &[] } 600 | // } 601 | 602 | let sample = map::Sample { base_hz: 440.0.into(), base_vel: 1.0, audio: () }; 603 | let range = map::StepVelRange { 604 | step: map::Range { min: 0, max: 127 }, 605 | vel: map::Range { min: 0.0, max: 1.0 }, 606 | }; 607 | 608 | let sample_over_range = SampleOverRange { range: range, sample: sample }; 609 | let serialized = serde_json::to_string(&sample_over_range).unwrap(); 610 | 611 | println!("{}", serialized); 612 | assert_eq!("{\"range\":{\"step\":{\"min\":0,\"max\":127},\"vel\":{\"min\":0,\"max\":1}},\"sample\":{\"base_hz\":440,\"base_vel\":1,\"audio\":null}}", serialized); 613 | 614 | let deserialized: SampleOverRange<()> = serde_json::from_str(&serialized).unwrap(); 615 | 616 | println!("{:?}", deserialized); 617 | assert_eq!(sample_over_range, deserialized); 618 | } 619 | 620 | } 621 | 622 | 623 | mod step_vel_range { 624 | use super::serde; 625 | use map::StepVelRange; 626 | 627 | impl serde::Serialize for StepVelRange { 628 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 629 | where S: serde::Serializer, 630 | { 631 | struct Visitor<'a> { 632 | t: &'a StepVelRange, 633 | field_idx: u8, 634 | } 635 | 636 | impl<'a> serde::ser::MapVisitor for Visitor<'a> { 637 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 638 | where S: serde::Serializer, 639 | { 640 | match self.field_idx { 641 | 0 => { 642 | self.field_idx += 1; 643 | Ok(Some(try!(serializer.serialize_struct_elt("step", &self.t.step)))) 644 | }, 645 | 1 => { 646 | self.field_idx += 1; 647 | Ok(Some(try!(serializer.serialize_struct_elt("vel", &self.t.vel)))) 648 | }, 649 | _ => Ok(None), 650 | } 651 | } 652 | 653 | fn len(&self) -> Option { 654 | Some(2) 655 | } 656 | } 657 | 658 | serializer.serialize_struct("StepVelRange", Visitor { t: self, field_idx: 0 }) 659 | } 660 | } 661 | 662 | impl serde::Deserialize for StepVelRange { 663 | fn deserialize(deserializer: &mut D) -> Result 664 | where D: serde::Deserializer, 665 | { 666 | struct Visitor; 667 | 668 | impl serde::de::Visitor for Visitor { 669 | type Value = StepVelRange; 670 | 671 | fn visit_map(&mut self, mut visitor: V) -> Result 672 | where V: serde::de::MapVisitor, 673 | { 674 | let mut step = None; 675 | let mut vel = None; 676 | 677 | enum Field { Step, Vel } 678 | 679 | impl serde::Deserialize for Field { 680 | fn deserialize(deserializer: &mut D) -> Result 681 | where D: serde::de::Deserializer, 682 | { 683 | struct FieldVisitor; 684 | 685 | impl serde::de::Visitor for FieldVisitor { 686 | type Value = Field; 687 | 688 | fn visit_str(&mut self, value: &str) -> Result 689 | where E: serde::de::Error, 690 | { 691 | match value { 692 | "step" => Ok(Field::Step), 693 | "vel" => Ok(Field::Vel), 694 | _ => Err(serde::de::Error::custom("expected step or vel")), 695 | } 696 | } 697 | } 698 | 699 | deserializer.deserialize(FieldVisitor) 700 | } 701 | } 702 | 703 | loop { 704 | match try!(visitor.visit_key()) { 705 | Some(Field::Step) => { step = Some(try!(visitor.visit_value())); }, 706 | Some(Field::Vel) => { vel = Some(try!(visitor.visit_value())); }, 707 | None => { break; } 708 | } 709 | } 710 | 711 | let step = match step { 712 | Some(step) => step, 713 | None => return Err(serde::de::Error::missing_field("step")), 714 | }; 715 | 716 | let vel = match vel { 717 | Some(vel) => vel, 718 | None => return Err(serde::de::Error::missing_field("vel")), 719 | }; 720 | 721 | try!(visitor.end()); 722 | 723 | Ok(StepVelRange { step: step, vel: vel }) 724 | } 725 | } 726 | 727 | static FIELDS: &'static [&'static str] = &["step", "vel"]; 728 | 729 | let visitor = Visitor; 730 | 731 | deserializer.deserialize_struct("StepVelRange", FIELDS, visitor) 732 | } 733 | } 734 | 735 | #[test] 736 | fn test() { 737 | extern crate serde_json; 738 | use map; 739 | 740 | let range = StepVelRange { 741 | step: map::Range { min: 0, max: 127 }, 742 | vel: map::Range { min: 0.0, max: 1.0 }, 743 | }; 744 | let serialized = serde_json::to_string(&range).unwrap(); 745 | 746 | println!("{}", serialized); 747 | assert_eq!("{\"step\":{\"min\":0,\"max\":127},\"vel\":{\"min\":0,\"max\":1}}", serialized); 748 | 749 | let deserialized: StepVelRange = serde_json::from_str(&serialized).unwrap(); 750 | 751 | println!("{:?}", deserialized); 752 | assert_eq!(range, deserialized); 753 | } 754 | 755 | } 756 | 757 | 758 | mod map { 759 | use super::serde; 760 | use map::Map; 761 | use std; 762 | 763 | impl serde::Serialize for Map 764 | where A: serde::Serialize, 765 | { 766 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 767 | where S: serde::Serializer, 768 | { 769 | struct Visitor<'a, A: 'a> { 770 | t: &'a Map, 771 | field_idx: u8, 772 | } 773 | 774 | impl<'a, A> serde::ser::MapVisitor for Visitor<'a, A> 775 | where A: serde::Serialize, 776 | { 777 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 778 | where S: serde::Serializer, 779 | { 780 | match self.field_idx { 781 | 0 => { 782 | self.field_idx += 1; 783 | Ok(Some(try!(serializer.serialize_struct_elt("pairs", &self.t.pairs)))) 784 | }, 785 | _ => Ok(None), 786 | } 787 | } 788 | 789 | fn len(&self) -> Option { 790 | Some(1) 791 | } 792 | } 793 | 794 | serializer.serialize_struct("Map", Visitor { t: self, field_idx: 0 }) 795 | } 796 | } 797 | 798 | impl serde::Deserialize for Map 799 | where A: serde::Deserialize, 800 | { 801 | fn deserialize(deserializer: &mut D) -> Result 802 | where D: serde::Deserializer, 803 | { 804 | struct Visitor { 805 | t: std::marker::PhantomData, 806 | }; 807 | 808 | impl serde::de::Visitor for Visitor 809 | where A: serde::Deserialize, 810 | { 811 | type Value = Map; 812 | 813 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 814 | where V: serde::de::MapVisitor, 815 | { 816 | let mut pairs = None; 817 | 818 | enum Field { Pairs } 819 | 820 | impl serde::Deserialize for Field { 821 | fn deserialize(deserializer: &mut D) -> Result 822 | where D: serde::de::Deserializer, 823 | { 824 | struct FieldVisitor; 825 | 826 | impl serde::de::Visitor for FieldVisitor { 827 | type Value = Field; 828 | 829 | fn visit_str(&mut self, value: &str) -> Result 830 | where E: serde::de::Error, 831 | { 832 | match value { 833 | "pairs" => Ok(Field::Pairs), 834 | _ => Err(serde::de::Error::custom("expected pairs")), 835 | } 836 | } 837 | } 838 | 839 | deserializer.deserialize(FieldVisitor) 840 | } 841 | } 842 | 843 | loop { 844 | match try!(visitor.visit_key()) { 845 | Some(Field::Pairs) => { pairs = Some(try!(visitor.visit_value())); }, 846 | None => { break; } 847 | } 848 | } 849 | 850 | let pairs = match pairs { 851 | Some(pairs) => pairs, 852 | None => return Err(serde::de::Error::missing_field("pairs")), 853 | }; 854 | 855 | try!(visitor.end()); 856 | 857 | Ok(Map { pairs: pairs }) 858 | } 859 | } 860 | 861 | static FIELDS: &'static [&'static str] = &["pairs"]; 862 | 863 | let visitor = Visitor { t: std::marker::PhantomData }; 864 | 865 | deserializer.deserialize_struct("Map", FIELDS, visitor) 866 | } 867 | } 868 | 869 | #[test] 870 | fn test() { 871 | extern crate serde_json; 872 | 873 | let map: Map<()> = Map::empty(); 874 | let serialized = serde_json::to_string(&map).unwrap(); 875 | 876 | println!("{}", serialized); 877 | assert_eq!("{\"pairs\":[]}", serialized); 878 | 879 | let deserialized: Map<()> = serde_json::from_str(&serialized).unwrap(); 880 | 881 | println!("{:?}", deserialized); 882 | assert_eq!(map, deserialized); 883 | } 884 | 885 | } 886 | 887 | 888 | mod sampler { 889 | use audio::Audio; 890 | use instrument; 891 | use super::serde; 892 | use sampler::{self, Sampler}; 893 | use std; 894 | 895 | impl serde::Serialize for Sampler 896 | where M: serde::Serialize, 897 | NFG: serde::Serialize + instrument::NoteFreqGenerator, 898 | NFG::NoteFreq: serde::Serialize, 899 | A: serde::Serialize + Audio, 900 | { 901 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 902 | where S: serde::Serializer, 903 | { 904 | struct Visitor<'a, M: 'a, NFG: 'a, A: 'a> 905 | where NFG: instrument::NoteFreqGenerator, 906 | A: Audio, 907 | { 908 | t: &'a Sampler, 909 | field_idx: u8, 910 | } 911 | 912 | impl<'a, M, NFG, A> serde::ser::MapVisitor for Visitor<'a, M, NFG, A> 913 | where M: serde::Serialize, 914 | NFG: serde::Serialize + instrument::NoteFreqGenerator, 915 | NFG::NoteFreq: serde::Serialize, 916 | A: serde::Serialize + Audio, 917 | { 918 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 919 | where S: serde::Serializer, 920 | { 921 | match self.field_idx { 922 | 0 => { 923 | self.field_idx += 1; 924 | Ok(Some(try!(serializer.serialize_struct_elt("instrument", &self.t.instrument)))) 925 | }, 926 | 1 => { 927 | self.field_idx += 1; 928 | Ok(Some(try!(serializer.serialize_struct_elt("map", &self.t.map)))) 929 | }, 930 | 2 => { 931 | self.field_idx += 1; 932 | let num_voices = self.t.voice_count(); 933 | Ok(Some(try!(serializer.serialize_struct_elt("voices", num_voices)))) 934 | }, 935 | _ => Ok(None), 936 | } 937 | } 938 | 939 | fn len(&self) -> Option { 940 | Some(3) 941 | } 942 | } 943 | 944 | serializer.serialize_struct("Sampler", Visitor { t: self, field_idx: 0 }) 945 | } 946 | } 947 | 948 | impl serde::Deserialize for Sampler 949 | where M: serde::Deserialize, 950 | NFG: serde::Deserialize + instrument::NoteFreqGenerator, 951 | NFG::NoteFreq: serde::Deserialize, 952 | A: serde::Deserialize + Audio, 953 | { 954 | fn deserialize(deserializer: &mut D) -> Result 955 | where D: serde::Deserializer, 956 | { 957 | struct Visitor { 958 | m: std::marker::PhantomData, 959 | nfg: std::marker::PhantomData, 960 | a: std::marker::PhantomData, 961 | }; 962 | 963 | impl serde::de::Visitor for Visitor 964 | where M: serde::Deserialize, 965 | NFG: serde::Deserialize + instrument::NoteFreqGenerator, 966 | NFG::NoteFreq: serde::Deserialize, 967 | A: serde::Deserialize + Audio, 968 | { 969 | type Value = Sampler; 970 | 971 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 972 | where V: serde::de::MapVisitor, 973 | { 974 | let mut instrument = None; 975 | let mut map = None; 976 | let mut num_voices = None; 977 | 978 | enum Field { Instrument, Map, Voices } 979 | 980 | impl serde::Deserialize for Field { 981 | fn deserialize(deserializer: &mut D) -> Result 982 | where D: serde::de::Deserializer, 983 | { 984 | struct FieldVisitor; 985 | 986 | impl serde::de::Visitor for FieldVisitor { 987 | type Value = Field; 988 | 989 | fn visit_str(&mut self, value: &str) -> Result 990 | where E: serde::de::Error, 991 | { 992 | match value { 993 | "instrument" => Ok(Field::Instrument), 994 | "map" => Ok(Field::Map), 995 | "voices" => Ok(Field::Voices), 996 | _ => Err(serde::de::Error::custom("expected instrument, map or voices")), 997 | } 998 | } 999 | } 1000 | 1001 | deserializer.deserialize(FieldVisitor) 1002 | } 1003 | } 1004 | 1005 | loop { 1006 | match try!(visitor.visit_key()) { 1007 | Some(Field::Instrument) => { instrument = Some(try!(visitor.visit_value())); }, 1008 | Some(Field::Map) => { map = Some(try!(visitor.visit_value())); }, 1009 | Some(Field::Voices) => { num_voices = Some(try!(visitor.visit_value())); }, 1010 | None => { break; } 1011 | } 1012 | } 1013 | 1014 | let instrument = match instrument { 1015 | Some(instrument) => instrument, 1016 | None => return Err(serde::de::Error::missing_field("instrument")), 1017 | }; 1018 | 1019 | let map = match map { 1020 | Some(map) => map, 1021 | None => return Err(serde::de::Error::missing_field("map")), 1022 | }; 1023 | 1024 | let num_voices = match num_voices { 1025 | Some(num_voices) => num_voices, 1026 | None => return Err(serde::de::Error::missing_field("voices")), 1027 | }; 1028 | 1029 | try!(visitor.end()); 1030 | 1031 | Ok(sampler::private::new(instrument, map, num_voices)) 1032 | } 1033 | } 1034 | 1035 | static FIELDS: &'static [&'static str] = &["instrument", "map", "voices"]; 1036 | 1037 | let visitor = Visitor { 1038 | m: std::marker::PhantomData, 1039 | nfg: std::marker::PhantomData, 1040 | a: std::marker::PhantomData, 1041 | }; 1042 | 1043 | deserializer.deserialize_struct("Sampler", FIELDS, visitor) 1044 | } 1045 | } 1046 | 1047 | #[test] 1048 | fn test() { 1049 | extern crate serde_json; 1050 | use instrument; 1051 | use map; 1052 | 1053 | let map: map::Map<()> = map::Map::empty(); 1054 | let sampler = Sampler::legato((), map); 1055 | let serialized = serde_json::to_string(&sampler).unwrap(); 1056 | 1057 | println!("{}", serialized); 1058 | 1059 | let deserialized: Sampler = 1060 | serde_json::from_str(&serialized).unwrap(); 1061 | 1062 | println!("{:?}", deserialized); 1063 | assert_eq!(&sampler.instrument, &deserialized.instrument); 1064 | assert_eq!(&sampler.map, &deserialized.map); 1065 | assert_eq!(sampler.voice_count(), deserialized.voice_count()); 1066 | } 1067 | 1068 | } 1069 | 1070 | 1071 | #[cfg(feature="wav")] 1072 | mod wav_audio { 1073 | extern crate find_folder; 1074 | 1075 | use audio::wav; 1076 | use sample; 1077 | use super::serde; 1078 | use std; 1079 | 1080 | impl serde::Serialize for wav::Audio { 1081 | fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> 1082 | where S: serde::Serializer, 1083 | { 1084 | struct Visitor<'a, F: 'a> { 1085 | t: &'a wav::Audio, 1086 | field_idx: u8, 1087 | } 1088 | 1089 | impl<'a, F> serde::ser::MapVisitor for Visitor<'a, F> { 1090 | fn visit(&mut self, serializer: &mut S) -> Result, S::Error> 1091 | where S: serde::Serializer, 1092 | { 1093 | match self.field_idx { 1094 | 0 => { 1095 | self.field_idx += 1; 1096 | Ok(Some(try!(serializer.serialize_struct_elt("path", &self.t.path)))) 1097 | }, 1098 | 1 => { 1099 | self.field_idx += 1; 1100 | Ok(Some(try!(serializer.serialize_struct_elt("sample_hz", &self.t.sample_hz)))) 1101 | }, 1102 | _ => Ok(None), 1103 | } 1104 | } 1105 | 1106 | fn len(&self) -> Option { 1107 | Some(2) 1108 | } 1109 | } 1110 | 1111 | serializer.serialize_struct("Audio", Visitor { t: self, field_idx: 0 }) 1112 | } 1113 | } 1114 | 1115 | impl serde::Deserialize for wav::Audio 1116 | where F: sample::Frame + serde::Deserialize, 1117 | F::Sample: sample::Duplex + sample::Duplex, 1118 | Box<[F::Sample]>: sample::ToBoxedFrameSlice, 1119 | { 1120 | fn deserialize(deserializer: &mut D) -> Result 1121 | where D: serde::Deserializer, 1122 | { 1123 | struct Visitor { 1124 | f: std::marker::PhantomData, 1125 | }; 1126 | 1127 | impl serde::de::Visitor for Visitor 1128 | where F: sample::Frame + serde::Deserialize, 1129 | F::Sample: sample::Duplex + sample::Duplex, 1130 | Box<[F::Sample]>: sample::ToBoxedFrameSlice, 1131 | { 1132 | type Value = wav::Audio; 1133 | 1134 | fn visit_map(&mut self, mut visitor: V) -> Result, V::Error> 1135 | where V: serde::de::MapVisitor, 1136 | { 1137 | let mut path = None; 1138 | let mut sample_hz = None; 1139 | 1140 | enum Field { Path, SampleHz } 1141 | 1142 | impl serde::Deserialize for Field { 1143 | fn deserialize(deserializer: &mut D) -> Result 1144 | where D: serde::de::Deserializer, 1145 | { 1146 | struct FieldVisitor; 1147 | 1148 | impl serde::de::Visitor for FieldVisitor { 1149 | type Value = Field; 1150 | 1151 | fn visit_str(&mut self, value: &str) -> Result 1152 | where E: serde::de::Error, 1153 | { 1154 | match value { 1155 | "path" => Ok(Field::Path), 1156 | "sample_hz" => Ok(Field::SampleHz), 1157 | _ => Err(serde::de::Error::custom("expected path or sample_hz")), 1158 | } 1159 | } 1160 | } 1161 | 1162 | deserializer.deserialize(FieldVisitor) 1163 | } 1164 | } 1165 | 1166 | loop { 1167 | match try!(visitor.visit_key()) { 1168 | Some(Field::Path) => { path = Some(try!(visitor.visit_value())); }, 1169 | Some(Field::SampleHz) => { sample_hz = Some(try!(visitor.visit_value())); }, 1170 | None => { break; } 1171 | } 1172 | } 1173 | 1174 | let path: std::path::PathBuf = match path { 1175 | Some(path) => path, 1176 | None => return Err(serde::de::Error::missing_field("path")), 1177 | }; 1178 | 1179 | let sample_hz = match sample_hz { 1180 | Some(sample_hz) => sample_hz, 1181 | None => return Err(serde::de::Error::missing_field("sample_hz")), 1182 | }; 1183 | 1184 | try!(visitor.end()); 1185 | 1186 | wav::Audio::from_file(path, sample_hz).map_err(|e| { 1187 | serde::de::Error::custom(std::error::Error::description(&e)) 1188 | }) 1189 | } 1190 | } 1191 | 1192 | static FIELDS: &'static [&'static str] = &["path", "sample_hz"]; 1193 | 1194 | let visitor = Visitor { f: std::marker::PhantomData }; 1195 | 1196 | deserializer.deserialize_struct("Audio", FIELDS, visitor) 1197 | } 1198 | } 1199 | 1200 | #[test] 1201 | fn test() { 1202 | extern crate serde_json; 1203 | 1204 | const THUMB_PIANO: &'static str = "thumbpiano A#3.wav"; 1205 | const SAMPLE_HZ: f64 = 44_100.0; 1206 | 1207 | let assets = find_folder::Search::ParentsThenKids(5, 5).for_folder("assets").unwrap(); 1208 | let path = assets.join(THUMB_PIANO); 1209 | let audio = wav::Audio::<[i16; 2]>::from_file(path, SAMPLE_HZ).unwrap(); 1210 | 1211 | let serialized = serde_json::to_string(&audio).unwrap(); 1212 | 1213 | println!("{}", serialized); 1214 | 1215 | let deserialized: wav::Audio<[i16; 2]> = serde_json::from_str(&serialized).unwrap(); 1216 | 1217 | assert_eq!(audio, deserialized); 1218 | } 1219 | } 1220 | --------------------------------------------------------------------------------