1use anyhow::{anyhow, Result};
3use cpal::{
4 traits::{DeviceTrait, HostTrait},
5 Device, SampleRate, SupportedStreamConfig,
6};
7use log::error;
8
9const SAMPLE_RATE: u32 = 16000;
10
11pub(crate) struct StreamConfig {
16 device: Device,
17 config: SupportedStreamConfig,
18 silence_level: i32,
19}
20
21#[cfg(test)]
22mod tests {
23 use crate::config::get_config;
24 use cpal::traits::HostTrait;
25
26 #[test]
27 fn supported_device() {
28 let host = cpal::default_host();
29 let device = host.default_input_device().expect("no input device found");
30 assert_eq!(1, get_config(&device).unwrap().channels());
31 }
32}
33
34impl StreamConfig {
35 pub fn new(silence_level: i32) -> Result<Self> {
37 let device = get_default_device()?;
38 match get_config(&device) {
39 Ok(config) => Ok(StreamConfig {
40 config,
41 device,
42 silence_level,
43 }),
44 Err(e) => {
45 error!("{}", e);
46 Err(anyhow!(e))
47 }
48 }
49 }
50
51 pub fn device(&self) -> &Device {
53 &self.device
54 }
55
56 pub fn supported_config(&self) -> &SupportedStreamConfig {
58 &self.config
59 }
60
61 pub fn silence_level(&self) -> i32 {
63 self.silence_level
64 }
65}
66
67fn get_config(device: &Device) -> Result<SupportedStreamConfig> {
69 let mut config = device.default_input_config()?;
70 if config.channels() != 1 {
71 let mut supported_configs_range = device.supported_input_configs()?;
72 config = match supported_configs_range.next() {
73 Some(conf) => {
74 conf.with_sample_rate(SampleRate(SAMPLE_RATE)) }
76 None => config,
77 };
78 }
79 Ok(config)
80}
81fn get_default_device() -> Result<Device> {
82 let host = cpal::default_host();
83 match host.default_input_device() {
84 Some(device) => Ok(device),
85 None => Err(anyhow!("no input device found")),
86 }
87}