wip audio synthesizer based on the rust crate cpal
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
beeper/src/beep.rs

152 lines
4.7 KiB

use std::sync::Arc;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use std::ops::{Add, AddAssign, Sub};
use parking_lot::RwLock;
use std::time::Duration;
use std::thread;
use cpal::SampleFormat;
use crate::beep::osc::{Instrument, Oscillator};
pub mod osc;
struct AudioContext {
device: cpal::Device,
sample_format: SampleFormat,
config: cpal::StreamConfig
}
fn al_init() -> Result<AudioContext, anyhow::Error> {
let host = cpal::default_host();
let device = host.default_output_device()
.ok_or_else(|| anyhow::anyhow!("No audio output device!"))?;
let config = device.default_output_config()?;
Ok(AudioContext {
device,
sample_format: config.sample_format(),
config: config.into()
})
}
pub fn beep() -> Result<(), anyhow::Error> {
let ac = al_init()?;
match ac.sample_format {
cpal::SampleFormat::F32 => run::<f32>(&ac.device, &ac.config.into())?,
cpal::SampleFormat::I16 => run::<i16>(&ac.device, &ac.config.into())?,
cpal::SampleFormat::U16 => run::<u16>(&ac.device, &ac.config.into())?,
}
Ok(())
}
fn run<T>(device: &cpal::Device, config: &cpal::StreamConfig) -> Result<(), anyhow::Error>
where
T: cpal::Sample,
{
let sample_rate = config.sample_rate.0 as f32;
let channels = config.channels as usize;
println!("SR={}",sample_rate);
// Produce a sinusoid of maximum amplitude.
let mut ins = Instrument::new(vec![
Oscillator::new(440.0, 1.0, sample_rate),
//Oscillator::new(441.0, 1.0, sample_rate),
], sample_rate);
let instrument = Arc::new(parking_lot::RwLock::new(ins));
let err_fn = |err| eprintln!("an error occurred on stream: {}", err);
let m_instrument = instrument.clone();
let stream = device.build_output_stream(
config,
move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
write_data(data, channels, &m_instrument)
},
err_fn,
)?;
stream.play()?;
// instrument.write().normalize(false);
// instrument.write().set_amp(1.0);
// thread::sleep(Duration::from_millis(500));
//
// instrument.write().set_amp(0.0);
// thread::sleep(Duration::from_millis(250));
instrument.write().set_amp(1.0);
instrument.write().normalize(true);
thread::sleep(Duration::from_millis(500));
instrument.write().set_amp(0.0);
thread::sleep(Duration::from_millis(250));
instrument.write().set_amp(0.5);
thread::sleep(Duration::from_millis(500));
instrument.write().set_amp(0.0);
thread::sleep(Duration::from_millis(250));
instrument.write().fade_amp(1.0, Duration::from_millis(10));
instrument.write().waveforms[0].fade_balance(-1.0, Duration::from_millis(10));
thread::sleep(Duration::from_millis(500));
instrument.write().fade_amp(0.0, Duration::from_millis(10));
thread::sleep(Duration::from_millis(500));
/*
//instrument.write().set_amp_fade(0.0, 4.0);
thread::sleep(Duration::from_millis(1000));
instrument.write().waveforms[1].fade_amp(0.0, Duration::from_millis(500));
thread::sleep(Duration::from_millis(500));
instrument.write().waveforms[0].fade_balance(-1.0, Duration::from_millis(1000));
thread::sleep(Duration::from_millis(1000));
instrument.write().waveforms[0].fade_balance(1.0, Duration::from_millis(2000));
instrument.write().waveforms[0].fade_freq(880.0, Duration::from_millis(1000));
thread::sleep(Duration::from_millis(2000));
instrument.write().waveforms[0].fade_balance(-1.0, Duration::from_millis(1000));
instrument.write().waveforms[0].fade_amp(0.0, Duration::from_millis(1000));
thread::sleep(Duration::from_millis(1000));
*/
// for _ in 0..10
// {
// instrument.write().harmonics[0].set_balance_fade(-1.0, 0.1);
// thread::sleep(Duration::from_millis(100));
// instrument.write().harmonics[0].set_balance_fade(1.0, 0.1);
// thread::sleep(Duration::from_millis(100));
// }
//
// instrument.write().harmonics[0].set_balance_fade(0.0, 0.5);
// instrument.write().harmonics[0].set_amp_fade(0.0, 0.05);
// thread::sleep(Duration::from_millis(200));
Ok(())
}
fn write_data<T>(output: &mut [T], channels: usize, instrument: &Arc<RwLock<Instrument>>)
where
T: cpal::Sample,
{
let mut instrument = instrument.write();
for frame in output.chunks_mut(channels) {
let sample = instrument.sample();
if channels == 1 {
frame[0] = cpal::Sample::from::<f32>(&((sample.left + sample.right) / 2.0));
} else {
frame[0] = cpal::Sample::from::<f32>(&sample.left);
frame[1] = cpal::Sample::from::<f32>(&sample.right);
}
}
}