use { cxx_juce::{ juce_audio_devices::{ AudioDeviceManager, AudioIODevice, AudioIODeviceCallback, InputAudioSampleBuffer, OutputAudioSampleBuffer, }, Result, JUCE, }, std::{iter::successors, thread::sleep, time::Duration}, }; #[derive(Debug, Default, Copy, Clone)] struct ToneGenerator { amplitude: f64, frequency: f64, phase: f64, increment: f64, } impl Iterator for ToneGenerator { type Item = f64; fn next(&mut self) -> Option { let sample = self.phase.sin() * self.amplitude; self.phase += self.increment; Some(sample) } } #[derive(Default)] struct AudioCallback { tones: Vec, } impl AudioIODeviceCallback for AudioCallback { fn about_to_start(&mut self, device: &mut dyn AudioIODevice) { const STARTING_FREQUENCY: f64 = 1024.0; let output_channels = device.output_channels() as usize; self.tones = successors( Some(ToneGenerator { amplitude: 0.25, frequency: STARTING_FREQUENCY, phase: 0.0, increment: STARTING_FREQUENCY / device.sample_rate(), }), |prev| { let frequency = prev.frequency * 2.5; Some(ToneGenerator { frequency, increment: frequency / device.sample_rate(), ..*prev }) }, ) .take(output_channels) .collect(); } fn process_block( &mut self, _input: &InputAudioSampleBuffer<'_>, output: &mut OutputAudioSampleBuffer<'_>, ) { for channel in 0..output.channels() { let samples = &mut output[channel]; let tone = &mut self.tones[channel]; for (sample, tone) in samples.iter_mut().zip(tone) { *sample = tone as f32; } } } fn stopped(&mut self) {} } fn main() -> Result<()> { let juce = JUCE::initialise(); let mut device_manager = AudioDeviceManager::new(&juce); device_manager.initialise(0, 2)?; let handle = device_manager.add_audio_callback(AudioCallback::default()); sleep(Duration::from_secs(2)); device_manager.remove_audio_callback(handle); Ok(()) }