use crate::*; pub struct SamplerAudio<'a>(pub &'a mut Sampler); audio!(|self: SamplerAudio<'a>, _client, scope|{ self.0.process_midi_in(scope); self.0.clear_output_buffer(); self.0.process_audio_out(scope); self.0.write_output_buffer(scope); self.0.process_audio_in(scope); Control::Continue }); impl Sampler { pub fn process_audio_in (&mut self, scope: &ProcessScope) { let Sampler { audio_ins, input_meter, recording, .. } = self; if audio_ins.len() != input_meter.len() { *input_meter = vec![0.0;audio_ins.len()]; } if let Some((_, sample)) = recording { let mut sample = sample.write().unwrap(); if sample.channels.len() != audio_ins.len() { panic!("channel count mismatch"); } let iterator = audio_ins.iter().zip(input_meter).zip(sample.channels.iter_mut()); let mut length = 0; for ((input, meter), channel) in iterator { let slice = input.port().as_slice(scope); length = length.max(slice.len()); let total: f32 = slice.iter().map(|x|x.abs()).sum(); let count = slice.len() as f32; *meter = 10. * (total / count).log10(); channel.extend_from_slice(slice); } sample.end += length; } else { for (input, meter) in audio_ins.iter().zip(input_meter) { let slice = input.port().as_slice(scope); let total: f32 = slice.iter().map(|x|x.abs()).sum(); let count = slice.len() as f32; *meter = 10. * (total / count).log10(); } } } /// Zero the output buffer. pub fn clear_output_buffer (&mut self) { for buffer in self.buffer.iter_mut() { buffer.fill(0.0); } } /// Mix all currently playing samples into the output. pub fn process_audio_out (&mut self, scope: &ProcessScope) { let Sampler { ref mut buffer, voices, output_gain, .. } = self; let channel_count = buffer.len(); voices.write().unwrap().retain_mut(|voice|{ for index in 0..scope.n_frames() as usize { if let Some(frame) = voice.next() { for (channel, sample) in frame.iter().enumerate() { // Averaging mixer: //self.buffer[channel % channel_count][index] = ( //(self.buffer[channel % channel_count][index] + sample * self.output_gain) / 2.0 //); buffer[channel % channel_count][index] += sample * *output_gain; } } else { return false } } true }); } /// Write output buffer to output ports. pub 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 } }