1
0
Fork 0
wip audio synthesizer based on the rust crate cpal
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
beeper/src/beep.rs

152 Zeilen
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);
}
}
}