use crate::*; audio!(|self: Sampler, _client, scope|{ self.process_midi_in(scope); self.process_audio_out(scope); self.process_audio_in(scope); Control::Continue }); impl Sampler { pub fn process_audio_in (&mut self, scope: &ProcessScope) { self.reset_input_meters(); if self.recording.is_some() { self.record_into(scope); } else { self.update_input_meters(scope); } } /// Make sure that input meter count corresponds to input channel count fn reset_input_meters (&mut self) { let channels = self.audio_ins.len(); if self.input_meters.len() != channels { self.input_meters = vec![f32::MIN;channels]; } } /// Record from inputs to sample fn record_into (&mut self, scope: &ProcessScope) { let mut sample = self.recording .as_mut().expect("no recording sample").1 .write().unwrap(); if sample.channels.len() != self.audio_ins.len() { panic!("channel count mismatch"); } let samples_with_meters = self.audio_ins.iter() .zip(self.input_meters.iter_mut()) .zip(sample.channels.iter_mut()); let mut length = 0; for ((input, meter), channel) in samples_with_meters { let slice = input.port().as_slice(scope); length = length.max(slice.len()); *meter = to_rms(slice); channel.extend_from_slice(slice); } sample.end += length; } /// Update input meters fn update_input_meters (&mut self, scope: &ProcessScope) { for (input, meter) in self.audio_ins.iter().zip(self.input_meters.iter_mut()) { let slice = input.port().as_slice(scope); *meter = to_rms(slice); } } /// Make sure that output meter count corresponds to input channel count fn reset_output_meters (&mut self) { let channels = self.audio_outs.len(); if self.output_meters.len() != channels { self.output_meters = vec![f32::MIN;channels]; } } /// Mix all currently playing samples into the output. pub fn process_audio_out (&mut self, scope: &ProcessScope) { self.clear_output_buffer(); self.populate_output_buffer(scope.n_frames() as usize); self.write_output_buffer(scope); } /// Zero the output buffer. fn clear_output_buffer (&mut self) { for buffer in self.buffer.iter_mut() { buffer.fill(0.0); } } /// Write playing voices to output buffer fn populate_output_buffer (&mut self, frames: usize) { let Sampler { ref mut buffer, voices, output_gain, mixing_mode, .. } = self; let channel_count = buffer.len(); match mixing_mode { MixingMode::Summing => voices.write().unwrap().retain_mut(|voice|{ mix_summing(buffer.as_mut_slice(), *output_gain, frames, ||voice.next()) }), MixingMode::Average => voices.write().unwrap().retain_mut(|voice|{ mix_average(buffer.as_mut_slice(), *output_gain, frames, ||voice.next()) }), } } /// Write output buffer to output ports. fn write_output_buffer (&mut self, scope: &ProcessScope) { let Sampler { ref mut audio_outs, buffer, .. } = self; for (i, port) in audio_outs.iter_mut().enumerate() { let buffer = &buffer[i]; for (i, value) in port.port_mut().as_mut_slice(scope).iter_mut().enumerate() { *value = *buffer.get(i).unwrap_or(&0.0); } } } } impl Iterator for Voice { type Item = [f32;2]; fn next (&mut self) -> Option { if self.after > 0 { self.after -= 1; return Some([0.0, 0.0]) } let sample = self.sample.read().unwrap(); if self.position < sample.end { let position = self.position; self.position += 1; return sample.channels[0].get(position).map(|_amplitude|[ sample.channels[0][position] * self.velocity * sample.gain, sample.channels[0][position] * self.velocity * sample.gain, ]) } None } }