Rust音频处理库objc2-audio-toolbox的使用,objc2-audio-toolbox提供Objective-C桥接和音频工具箱功能
Rust音频处理库objc2-audio-toolbox的使用
objc2-audio-toolbox
是Rust绑定到Apple的AudioToolbox框架的库,提供了Objective-C桥接和音频工具箱功能。
安装
在项目目录中运行以下Cargo命令:
cargo add objc2-audio-toolbox
或者在Cargo.toml中添加:
objc2-audio-toolbox = "0.3.1"
示例代码
以下是内容中提供的初始化音频会话示例:
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2::runtime::Class;
use objc2_audio_toolbox::{
AudioSessionInitialize,
AudioSessionSetActive,
kAudioSessionCategory_PlayAndRecord,
};
fn main() {
unsafe {
// 初始化音频会话
let result = AudioSessionInitialize(
std::ptr::null(),
std::ptr::null(),
std::ptr::null(),
std::ptr::null_mut()
);
assert_eq!(result, 0, "Failed to initialize audio session");
// 设置音频会话类别
let category = kAudioSessionCategory_PlayAndRecord;
let result = AudioSessionSetActive(true);
assert_eq!(result, 0, "Failed to set audio session active");
println!("Audio session initialized successfully");
}
}
完整示例demo
下面是一个更完整的示例,展示如何设置音频会话并处理音频输入/输出:
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2_audio_toolbox::{
AudioSessionInitialize,
AudioSessionSetActive,
AudioSessionSetProperty,
kAudioSessionProperty_AudioCategory,
kAudioSessionCategory_PlayAndRecord,
kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
};
fn main() {
unsafe {
// 1. 初始化音频会话
let init_result = AudioSessionInitialize(
std::ptr::null(), // 不使用运行循环
std::ptr::null(), // 不使用运行循环模式
std::ptr::null(), // 不使用中断回调
std::ptr::null_mut() // 不使用用户数据
);
assert_eq!(init_result, 0, "音频会话初始化失败");
// 2. 设置音频会话类别为播放和录制
let mut category = kAudioSessionCategory_PlayAndRecord;
let set_category_result = AudioSessionSetProperty(
kAudioSessionProperty_AudioCategory,
std::mem::size_of_val(&category) as u32,
&category as *const _ as *const _
);
assert_eq!(set_category_result, 0, "设置音频类别失败");
// 3. 设置默认输出为扬声器
let mut default_to_speaker: u32 = 1; // 1表示true
let speaker_result = AudioSessionSetProperty(
kAudioSessionProperty_OverrideCategoryDefaultToSpeaker,
std::mem::size_of_val(&default_to_speaker) as u32,
&default_to_speaker as *const _ as *const _
);
assert_eq!(speaker_result, 0, "设置扬声器输出失败");
// 4. 激活音频会话
let activate_result = AudioSessionSetActive(true);
assert_eq!(activate_result, 0, "激活音频会话失败");
println!("音频会话配置成功!");
// 这里可以添加实际的音频处理逻辑...
// 5. 结束时停用音频会话
let deactivate_result = AudioSessionSetActive(false);
assert_eq!(deactivate_result, 0, "停用音频会话失败");
}
}
功能特性
- 提供了对Apple AudioToolbox框架的Rust绑定
- 支持Objective-C桥接功能
- 包含音频处理相关API
许可证
该项目采用以下许可证之一:
- Zlib
- Apache-2.0
- MIT
项目信息
- 最低支持的Rust版本:v1.71.0
- 大小:174 KiB
- 维护者:Mads Marquart等
1 回复
以下是基于您提供的objc2-audio-toolbox
库内容整理的完整示例demo,包含音频播放和录制功能:
基础示例回顾(来自原内容)
1. 初始化音频会话
use objc2_audio_toolbox::audio_session::{AudioSession, AudioSessionCategory};
fn setup_audio_session() {
let session = AudioSession::new();
session.set_category(AudioSessionCategory::PlayAndRecord).unwrap();
session.set_active(true).unwrap();
}
2. 音频播放基础
use objc2_audio_toolbox::audio_queue::{AudioQueue, AudioQueueOutputCallback};
use std::path::Path;
struct PlaybackState {
// 自定义播放状态
}
fn play_audio_file(path: &Path) {
let queue = AudioQueue::new_output(
AudioQueueOutputCallback::new(|_, buffer| {
// 填充音频数据到缓冲区
}),
PlaybackState {
// 初始化状态
}
).unwrap();
queue.start().unwrap();
}
3. 音频录制基础
use objc2_audio_toolbox::audio_queue::{AudioQueue, AudioQueueInputCallback};
struct RecordingState {
// 自定义录制状态
}
fn record_audio() {
let queue = AudioQueue::new_input(
AudioQueueInputCallback::new(|_, buffer, _| {
// 处理录制的音频数据
}),
RecordingState {
// 初始化状态
}
).unwrap();
queue.start().unwrap();
}
完整示例Demo
音频播放器实现
use objc2_audio_toolbox::audio_queue::{AudioQueue, AudioQueueOutputCallback};
use objc2_audio_toolbox::audio_session::{AudioSession, AudioSessionCategory};
use std::path::Path;
use std::fs::File;
use std::io::Read;
struct PlayerState {
file_data: Vec<u8>,
position: usize,
}
fn play_audio_file(path: &Path) -> Result<(), Box<dyn std::error::Error>> {
// 1. 初始化音频会话
let session = AudioSession::new();
session.set_category(AudioSessionCategory::Playback)?;
session.set_active(true)?;
// 2. 加载音频文件
let mut file = File::open(path)?;
let mut file_data = Vec::new();
file.read_to_end(&mut file_data)?;
// 3. 创建播放状态
let state = PlayerState {
file_data,
position: 0,
};
// 4. 创建音频队列
let queue = AudioQueue::new_output(
AudioQueueOutputCallback::new(|state: &mut PlayerState, buffer| {
// 计算剩余数据量
let remaining = state.file_data.len() - state.position;
let to_copy = remaining.min(buffer.len());
// 填充缓冲区
buffer[..to_copy].copy_from_slice(
&state.file_data[state.position..state.position + to_copy]
);
// 更新位置
state.position += to_copy;
// 如果数据已全部写入,设置结束标志
if to_copy < buffer.len() {
buffer[to_copy..].fill(0);
}
}),
state,
)?;
// 5. 开始播放
queue.start()?;
// 保持线程运行直到播放完成
while queue.is_running() {
std::thread::sleep(std::time::Duration::from_millis(100));
}
Ok(())
}
音频录制器实现
use objc2_audio_toolbox::audio_queue::{AudioQueue, AudioQueueInputCallback};
use objc2_audio_toolbox::audio_session::{AudioSession, AudioSessionCategory};
use std::fs::File;
use std::io::Write;
struct RecorderState {
output_file: File,
}
fn record_audio(output_path: &str) -> Result<(), Box<dyn std::error::Error>> {
// 1. 初始化音频会话
let session = AudioSession::new();
session.set_category(AudioSessionCategory::Record)?;
session.set_active(true)?;
// 2. 创建输出文件
let file = File::create(output_path)?;
// 3. 创建录制状态
let state = RecorderState {
output_file: file,
};
// 4. 创建音频队列
let queue = AudioQueue::new_input(
AudioQueueInputCallback::new(|state: &mut RecorderState, buffer, _| {
// 将录制的PCM数据写入文件
state.output_file.write_all(buffer)?;
Ok(())
}),
state,
)?;
// 5. 开始录制
queue.start()?;
println!("Recording... Press Enter to stop");
let _ = std::io::stdin().read_line(&mut String::new());
// 停止录制
queue.stop(false)?;
Ok(())
}
主程序示例
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 示例使用
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
println!("Usage: {} <play|record> [file]", args[0]);
return Ok(());
}
match args[1].as_str() {
"play" => {
if args.len() < 3 {
eprintln!("Please specify audio file to play");
return Ok(());
}
play_audio_file(Path::new(&args[2]))?;
}
"record" => {
let output = if args.len() > 2 {
&args[2]
} else {
"output.pcm"
};
record_audio(output)?;
}
_ => {
eprintln!("Invalid command");
}
}
Ok(())
}
使用说明
- 播放音频:
cargo run -- play example.wav
- 录制音频:
cargo run -- record output.pcm
关键点说明
- 音频会话管理:必须正确设置音频会话类别(Playback/Record)
- 实时处理:回调函数中避免耗时操作
- 错误处理:所有操作都应检查Result
- 平台限制:仅适用于macOS/iOS平台
- 权限要求:录制需要麦克风访问权限
注意事项
- 示例中使用的是原始PCM数据,实际应用中可能需要添加WAV头等格式处理
- 录制得到的PCM文件需要知道采样率、位深等参数才能正确播放
- 生产环境需要添加更完善的错误处理和状态管理