cxx-juce 0.8.0

Rust bindings for JUCE using cxx.
Documentation
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<Self::Item> {
        let sample = self.phase.sin() * self.amplitude;
        self.phase += self.increment;
        Some(sample)
    }
}

#[derive(Default)]
struct AudioCallback {
    tones: Vec<ToneGenerator>,
}

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(())
}