init
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
14
Cargo.toml
Normal file
14
Cargo.toml
Normal 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 = "*"
|
||||||
4
src/audio_engine/audio_processor.rs
Normal file
4
src/audio_engine/audio_processor.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
trait AudioProcessor {
|
||||||
|
fn process(&mut self, input: &[f32], output: &mut [f32]);
|
||||||
|
}
|
||||||
147
src/audio_engine/mod.rs
Normal file
147
src/audio_engine/mod.rs
Normal 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
6
src/main.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
mod audio_engine;
|
||||||
|
use audio_engine::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut engine = AudioEngine::new();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user