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.
152 lines
4.7 KiB
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);
|
|
}
|
|
}
|
|
}
|
|
|