generated from tversteeg/library-github-template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcpal.rs
102 lines (83 loc) · 2.77 KB
/
cpal.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{SampleFormat, SampleRate, Stream, SupportedStreamConfig};
use std::{
sync::{Arc, Mutex},
thread,
time::Duration,
};
const SAMPLE_RATE: u32 = 44_100;
/// Manages the audio.
pub struct Audio {
mixer: Arc<Mutex<usfx::Mixer>>,
stream: Stream,
}
impl Audio {
/// Instantiate a new audio object without a generator.
#[allow(clippy::new_without_default)] //stream doesn't support default
pub fn new() -> Self {
let mixer = Arc::new(Mutex::new(usfx::Mixer::new(SAMPLE_RATE as usize)));
// Setup the audio system
let host = cpal::default_host();
let device = host
.default_output_device()
.expect("no output device available");
let config = device
.supported_output_configs()
.expect("no output configs available")
.find(|config| config.sample_format() == SampleFormat::F32);
if config.is_none() {
panic!("no F32 config available");
}
let config = config.unwrap();
if config.min_sample_rate() > SampleRate(SAMPLE_RATE)
|| config.max_sample_rate() < SampleRate(SAMPLE_RATE)
{
panic!("44100 Hz not supported");
}
let format = SupportedStreamConfig::new(
config.channels(),
SampleRate(SAMPLE_RATE),
config.buffer_size().clone(),
SampleFormat::F32,
);
let stream_mixer = mixer.clone();
let stream = device
.build_output_stream::<f32, _, _>(
&format.config(),
move |data, _| stream_mixer.lock().unwrap().generate(data),
|err| eprintln!("cpal error: {:?}", err),
None,
)
.expect("could not build output stream");
let struct_mixer = mixer;
Self {
mixer: struct_mixer,
stream,
}
}
/// Play samples.
pub fn play(&mut self, sample: usfx::Sample) {
// Add the sample to the mixer
self.mixer.lock().unwrap().play(sample);
}
/// Start a thread which will emit the audio.
pub fn run(&mut self) {
self.stream.play().expect("unable to start stream");
}
}
fn main() {
let mut audio = Audio::new();
let mut sample = usfx::Sample::default();
sample.osc_frequency(1000);
sample.osc_type(usfx::OscillatorType::Sine);
sample.env_attack(0.1);
sample.env_decay(0.1);
sample.env_sustain(0.5);
sample.env_release(0.5);
sample.dis_crunch(0.2);
// Play a low sample with a square wave
audio.play(sample);
// Spawn a background thread where an audio device is opened with cpal
audio.run();
thread::sleep(Duration::from_millis(3_000));
}