This commit is contained in:
2024-10-12 10:15:47 +08:00
commit e22127b91e
5 changed files with 172 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

14
Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "arona"
version = "0.0.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cpal = { version = "*", features = ["asio-sys", "asio", "jack"] }
iced = "*"
rayon = "*"
crossbeam = "*"
serde = { version = "*", features = ["derive"] }
serde_json = "*"

View File

@@ -0,0 +1,4 @@
trait AudioProcessor {
fn process(&mut self, input: &[f32], output: &mut [f32]);
}

147
src/audio_engine/mod.rs Normal file
View File

@@ -0,0 +1,147 @@
mod audio_processor;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct AudioConfig {
sample_rate: Option<u32>,
buffer_size: Option<u32>,
input_device: Option<String>,
output_device: Option<String>,
}
impl AudioConfig {
fn load() -> Self {
let config = std::fs::read_to_string("audio_config.json");
if config.is_err() {
AudioConfig {
sample_rate: None,
buffer_size: None,
input_device: None,
output_device: None,
}
}
else {
let result = serde_json::from_str(&config.unwrap());
if result.is_err() {
println!("failed to parse audio_config.json");
AudioConfig {
sample_rate: None,
buffer_size: None,
input_device: None,
output_device: None,
}
}
else {
result.unwrap()
}
}
}
fn save(&self) {
let config = serde_json::to_string(&self).expect("failed to serialize audio_config");
std::fs::write("audio_config.json", config).expect("failed to write audio_config.json");
}
fn get_sample_rate(&self) -> cpal::SampleRate {
cpal::SampleRate(self.sample_rate.unwrap_or(48000))
}
fn get_buffer_size(&self) -> cpal::BufferSize {
cpal::BufferSize::Fixed(self.buffer_size.unwrap_or(512))
}
fn get_input_device(&self, default: cpal::Device) -> cpal::Device {
let host = cpal::default_host();
let input_device = self.input_device.as_ref().map(|name| {
host.devices().unwrap().find(|device| {
device.name().unwrap() == *name
})
}).flatten();
input_device.unwrap_or(default)
}
fn get_output_device(&self, default: cpal::Device) -> cpal::Device {
let host = cpal::default_host();
let output_device = self.output_device.as_ref().map(|name| {
host.devices().unwrap().find(|device| {
device.name().unwrap() == *name
})
}).flatten();
output_device.unwrap_or(default)
}
}
pub struct AudioEngine {
host : cpal::Host,
input_device: cpal::Device,
output_device: cpal::Device,
sample_rate: cpal::SampleRate,
buffer_size: cpal::BufferSize,
input_stream: Option<cpal::Stream>,
output_stream: Option<cpal::Stream>,
}
impl AudioEngine {
pub fn new() -> Self {
println!("Supported hosts:\n {:?}", cpal::ALL_HOSTS);
let default_host = cpal::default_host();
let default_input_device = default_host.default_input_device().expect("no input device");
let default_output_device = default_host.default_output_device().expect("no output device");
let audio_config = AudioConfig::load();
let out = AudioEngine {
host: default_host,
input_device: audio_config.get_input_device(default_input_device),
output_device: audio_config.get_output_device(default_output_device),
sample_rate: audio_config.get_sample_rate(),
buffer_size: audio_config.get_buffer_size(),
input_stream: None,
output_stream: None,
};
out.save_config();
println!("Input device: {}", out.input_device.name().unwrap());
println!("Output device: {}", out.output_device.name().unwrap());
out
}
pub fn save_config(&self) {
let audio_config = AudioConfig {
sample_rate: Some(self.sample_rate.0),
buffer_size: Some(match self.buffer_size {
cpal::BufferSize::Default => { 0 }
cpal::BufferSize::Fixed(size) => { size }
}),
input_device: Some(self.input_device.name().unwrap()),
output_device: Some(self.output_device.name().unwrap()),
};
audio_config.save();
}
pub fn open_stream(&mut self) {
// 不要创建输入流,输入流只在需要时创建
let output_stream = self.output_device.build_output_stream(
&self.output_stream_config(),
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
self.process_output(data);
},
move |err| {
eprintln!("an error occurred on stream: {}", err);
},
None
).unwrap();
}
fn output_stream_config(&self) -> cpal::StreamConfig {
cpal::StreamConfig {
channels: 2,
buffer_size: self.buffer_size,
sample_rate: self.sample_rate,
}
}
fn process_output(&mut self, data: &mut [f32]) {
for sample in data.iter_mut() {
*sample = 0.0;
}
}
}

6
src/main.rs Normal file
View File

@@ -0,0 +1,6 @@
mod audio_engine;
use audio_engine::*;
fn main() {
let mut engine = AudioEngine::new();
}