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, "停用音频会话失败");
    }
}

功能特性

  1. 提供了对Apple AudioToolbox框架的Rust绑定
  2. 支持Objective-C桥接功能
  3. 包含音频处理相关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(())
}

使用说明

  1. 播放音频
cargo run -- play example.wav
  1. 录制音频
cargo run -- record output.pcm

关键点说明

  1. 音频会话管理:必须正确设置音频会话类别(Playback/Record)
  2. 实时处理:回调函数中避免耗时操作
  3. 错误处理:所有操作都应检查Result
  4. 平台限制:仅适用于macOS/iOS平台
  5. 权限要求:录制需要麦克风访问权限

注意事项

  1. 示例中使用的是原始PCM数据,实际应用中可能需要添加WAV头等格式处理
  2. 录制得到的PCM文件需要知道采样率、位深等参数才能正确播放
  3. 生产环境需要添加更完善的错误处理和状态管理
回到顶部