63 KiB
前端接口API参考
目录
概述
前端接口模块提供了应用程序与音频后端引擎通信的统一接口,支持本地和网络通信。前端接口封装了设备管理、网络发现、音频传输和编解码等复杂功能,使应用程序能够简单地集成高级音频处理能力。
核心特性:
- 本地通信: 与同一设备上运行的音频引擎通信
- 网络通信: 与远程音频引擎进行低延迟通信
- 自动发现: 通过mDNS/Bonjour自动发现网络上的音频服务
- 设备管理: 枚举、配置和监控音频设备变化
- 编解码处理: 支持多种音频编解码器,包括无损和有损压缩
- 低延迟传输: 针对实时音频优化的网络传输
- 安全连接: 支持加密的音频流和控制通道
前端接口的架构示意图:
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
│ 应用程序 │ │ 音频引擎进程 │
│ │ │ │
│ ┌─────────────────────────┐ │ │ ┌─────────────────────────┐ │
│ │ 前端管理器 │ │ │ │ 音频引擎 │ │
│ │ FrontendManager │ │ │ │ │ │
│ └───────────┬─────────────┘ │ │ └───────────┬─────────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌───────────────────────────┐ │ │ ┌───────────────────────────┐ │
│ │ 引擎代理 │ │ │ │ 通信管理器 │ │
│ │ EngineProxy │ │ │ │ CommunicationManager │ │
│ └───────────┬───────────────┘ │ │ └───────────┬───────────────┘ │
│ │ │ │ │ │
│ │ │ │ │ │
│ ┌───────────▼───────────────┐ │ │ ┌───────────▼───────────────┐ │
│ │ 通信管理器 │ │ │ │ ZeroMQ通信 │ │
│ │ (ZeroMQ/共享内存) ├──┼──────┼─►│ (控制通道) │ │
│ └───────────────────────────┘ │ │ └───────────────────────────┘ │
│ │ │ │
│ ┌───────────────────────────┐ │ │ ┌───────────────────────────┐ │
│ │ 设备管理器 │ │ │ │ 共享内存 │ │
│ │ DeviceManager ├──┼──────┼─►│ (数据通道) │ │
│ └───────────────────────────┘ │ │ └───────────────────────────┘ │
│ │ │ │
│ ┌───────────────────────────┐ │ │ │
│ │ 网络传输 │ │ │ │
│ │ NetworkTransport │ │ │ │
│ └───────────────────────────┘ │ │ │
└─────────────────────────────────┘ └─────────────────────────────────┘
│
│ ┌─────────────────────────────────┐
│ │ 远程音频引擎 │
│ │ │
│ │ ┌─────────────────────────┐ │
│ │ │ 网络服务器 │ │
└──────────────────────┼─►│ NetworkServer │ │
│ └─────────────────────────┘ │
│ │
└─────────────────────────────────┘
前端管理器
FrontendManager
FrontendManager是前端接口的核心类,负责协调所有前端组件,管理与音频引擎的通信,以及处理音频设备和网络服务。
class FrontendManager {
public:
explicit FrontendManager(const FrontendConfig& config);
~FrontendManager();
// 生命周期管理
common::ErrorCode initialize();
common::ErrorCode shutdown();
bool is_initialized() const;
bool is_engine_connected() const;
// 事件监听
void add_event_listener(std::shared_ptr<IFrontendEventListener> listener);
void remove_event_listener(std::shared_ptr<IFrontendEventListener> listener);
// 音频引擎连接
common::ErrorCode connect_to_engine(const std::string& endpoint = "");
common::ErrorCode disconnect_from_engine();
// 音频设备管理
std::vector<AudioDeviceInfo> get_audio_devices() const;
common::ErrorCode set_input_device(const std::string& device_id);
common::ErrorCode set_output_device(const std::string& device_id);
common::ErrorCode start_audio_stream();
common::ErrorCode stop_audio_stream();
// 网络服务管理
common::ErrorCode start_network_discovery();
common::ErrorCode stop_network_discovery();
std::vector<NetworkServiceInfo> get_discovered_services() const;
common::ErrorCode connect_to_network_service(const std::string& service_id);
common::ErrorCode disconnect_from_network_service(const std::string& service_id);
// 音频流控制
common::ErrorCode start_network_audio_stream(const std::string& target_address, uint16_t port);
common::ErrorCode stop_network_audio_stream();
// 配置管理
const FrontendConfig& config() const;
common::ErrorCode update_config(const FrontendConfig& new_config);
// 统计信息
const FrontendStatistics& get_statistics() const;
void reset_statistics();
void print_statistics() const;
// 音频数据处理
common::ErrorCode send_audio_data(const engine::AudioBuffer& buffer);
common::ErrorCode send_audio_data_to_network(const engine::AudioBuffer& buffer,
const std::string& target);
// 控制命令
common::ErrorCode send_control_command(const std::string& command,
const std::string& parameters = "");
};
前端配置
FrontendConfig定义了前端接口的配置选项,包括基础设置、网络设置和性能选项:
struct FrontendConfig {
// 基础配置
std::string process_name = "audio_frontend";
std::string engine_endpoint = "tcp://localhost:5555";
// 音频设备配置
bool auto_detect_devices = true;
bool enable_device_hotplug = true;
uint32_t device_poll_interval_ms = 1000;
// 网络配置
bool enable_network_discovery = true;
bool enable_network_streaming = true;
uint16_t network_discovery_port = 7777;
uint16_t audio_stream_port = 8888;
uint16_t control_port = 9999;
std::string network_interface = "0.0.0.0";
// 缓冲配置
uint32_t audio_buffer_size = 512;
uint32_t network_buffer_size = 2048;
uint32_t max_latency_ms = 50;
// 安全配置
bool require_authentication = false;
std::string certificate_path = "";
std::string private_key_path = "";
// 性能配置
uint32_t worker_thread_count = 2;
bool enable_performance_monitoring = true;
uint32_t statistics_interval_ms = 5000;
};
配置选项说明:
| 配置项 | 描述 | 默认值 | 推荐设置 |
|---|---|---|---|
| process_name | 前端进程名称,用于标识 | "audio_frontend" | 应用名称 |
| engine_endpoint | 音频引擎连接地址 | "tcp://localhost:5555" | 本地部署保持默认 |
| auto_detect_devices | 是否自动检测音频设备 | true | 通常保持启用 |
| enable_device_hotplug | 是否监控设备热插拔 | true | 通常保持启用 |
| enable_network_discovery | 是否启用网络服务发现 | true | 需要网络功能时启用 |
| enable_network_streaming | 是否启用网络音频流 | true | 需要网络功能时启用 |
| audio_buffer_size | 音频缓冲区大小(帧) | 512 | 低延迟场景: 128-256 高质量场景: 512-2048 |
| network_buffer_size | 网络缓冲区大小(字节) | 2048 | 低延迟场景: 512-1024 高带宽场景: 4096+ |
| max_latency_ms | 最大可接受延迟(毫秒) | 50 | 实时通信: 20-30 音乐制作: 30-50 流媒体: 100-300 |
生命周期管理
前端管理器的典型生命周期包括:
- 创建管理器:使用工厂函数创建前端管理器
- 初始化:调用
initialize()进行初始化 - 连接引擎:调用
connect_to_engine()连接到音频引擎 - 配置设备:枚举并设置音频设备
- 启动音频流:调用
start_audio_stream()开始音频处理 - 处理音频数据:发送/接收音频数据
- 停止音频流:调用
stop_audio_stream()停止音频处理 - 断开连接:调用
disconnect_from_engine()断开引擎连接 - 关闭:调用
shutdown()清理资源
// 示例:前端管理器基本生命周期
#include "audio_backend/frontend.h"
int main() {
// 初始化前端系统
audio_backend::frontend::initialize_frontend();
// 创建前端管理器
auto frontend = audio_backend::frontend::create_frontend_manager();
// 初始化
auto result = frontend->initialize();
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "前端初始化失败: " << audio_backend::common::error_to_string(result) << std::endl;
return 1;
}
// 连接到音频引擎
result = frontend->connect_to_engine("tcp://localhost:5555");
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "连接音频引擎失败" << std::endl;
return 1;
}
// ... 应用逻辑 ...
// 关闭前端管理器
frontend->shutdown();
// 清理前端系统
audio_backend::frontend::shutdown_frontend();
return 0;
}
音频设备管理
设备信息
AudioDeviceInfo结构提供了音频设备的详细信息:
struct AudioDeviceInfo {
std::string id; // 设备唯一标识符
std::string name; // 设备名称
std::string driver_name; // 驱动名称
bool is_input; // 是否为输入设备
bool is_output; // 是否为输出设备
bool is_default; // 是否为默认设备
std::vector<uint32_t> supported_sample_rates; // 支持的采样率
std::vector<uint16_t> supported_channel_counts; // 支持的声道数
std::vector<engine::AudioFormat> supported_formats; // 支持的音频格式
uint32_t default_buffer_size; // 默认缓冲区大小
double input_latency; // 输入延迟(毫秒)
double output_latency; // 输出延迟(毫秒)
};
枚举音频设备的示例:
void list_audio_devices(audio_backend::frontend::FrontendManager& frontend) {
auto devices = frontend.get_audio_devices();
std::cout << "发现 " << devices.size() << " 个音频设备:" << std::endl;
std::cout << "-----------------------------------------" << std::endl;
for (const auto& device : devices) {
std::cout << (device.is_default ? "* " : " ")
<< device.name << " (" << device.id << ")" << std::endl;
std::cout << " 类型: "
<< (device.is_input && device.is_output ? "输入/输出" :
(device.is_input ? "输入" : "输出")) << std::endl;
std::cout << " 驱动: " << device.driver_name << std::endl;
std::cout << " 支持的采样率: ";
for (auto rate : device.supported_sample_rates) {
std::cout << rate << " ";
}
std::cout << std::endl;
std::cout << " 支持的声道数: ";
for (auto channels : device.supported_channel_counts) {
std::cout << channels << " ";
}
std::cout << std::endl;
std::cout << " 延迟: ";
if (device.is_input) std::cout << "输入=" << device.input_latency << "ms ";
if (device.is_output) std::cout << "输出=" << device.output_latency << "ms";
std::cout << std::endl;
std::cout << "-----------------------------------------" << std::endl;
}
}
设备选择
前端管理器提供了设置输入和输出设备的方法:
common::ErrorCode set_input_device(const std::string& device_id);
common::ErrorCode set_output_device(const std::string& device_id);
设置音频设备的示例:
void configure_audio_devices(audio_backend::frontend::FrontendManager& frontend) {
// 获取所有音频设备
auto devices = frontend.get_audio_devices();
// 查找默认输入和输出设备
std::string input_device_id;
std::string output_device_id;
for (const auto& device : devices) {
if (device.is_default) {
if (device.is_input) {
input_device_id = device.id;
}
if (device.is_output) {
output_device_id = device.id;
}
}
}
// 设置输入设备
if (!input_device_id.empty()) {
auto result = frontend.set_input_device(input_device_id);
if (result == audio_backend::common::ErrorCode::SUCCESS) {
std::cout << "设置默认输入设备成功" << std::endl;
} else {
std::cerr << "设置默认输入设备失败" << std::endl;
}
}
// 设置输出设备
if (!output_device_id.empty()) {
auto result = frontend.set_output_device(output_device_id);
if (result == audio_backend::common::ErrorCode::SUCCESS) {
std::cout << "设置默认输出设备成功" << std::endl;
} else {
std::cerr << "设置默认输出设备失败" << std::endl;
}
}
}
音频流控制
前端管理器提供了启动和停止音频流的方法:
common::ErrorCode start_audio_stream();
common::ErrorCode stop_audio_stream();
音频流控制示例:
void control_audio_stream(audio_backend::frontend::FrontendManager& frontend) {
// 启动音频流
auto result = frontend.start_audio_stream();
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "启动音频流失败: "
<< audio_backend::common::error_to_string(result) << std::endl;
return;
}
std::cout << "音频流已启动,按回车键停止..." << std::endl;
std::cin.get();
// 停止音频流
result = frontend.stop_audio_stream();
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "停止音频流失败: "
<< audio_backend::common::error_to_string(result) << std::endl;
return;
}
std::cout << "音频流已停止" << std::endl;
}
网络通信
服务发现
前端接口支持通过mDNS/Bonjour协议自动发现网络上的音频服务:
common::ErrorCode start_network_discovery();
common::ErrorCode stop_network_discovery();
std::vector<NetworkServiceInfo> get_discovered_services() const;
NetworkServiceInfo结构提供了网络服务的详细信息:
struct NetworkServiceInfo {
std::string service_id; // 服务唯一标识符
std::string service_name; // 服务名称
std::string address; // IP地址
uint16_t port; // 端口
std::string service_type; // 服务类型
std::unordered_map<std::string, std::string> properties; // 服务属性
std::chrono::steady_clock::time_point last_seen; // 最后发现时间
};
服务发现示例:
void discover_audio_services(audio_backend::frontend::FrontendManager& frontend) {
// 启动网络服务发现
auto result = frontend.start_network_discovery();
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "启动网络服务发现失败" << std::endl;
return;
}
std::cout << "搜索网络音频服务中..." << std::endl;
// 等待服务发现(实际应用中可能使用事件回调)
std::this_thread::sleep_for(std::chrono::seconds(5));
// 获取已发现的服务
auto services = frontend.get_discovered_services();
if (services.empty()) {
std::cout << "未发现音频服务" << std::endl;
} else {
std::cout << "发现 " << services.size() << " 个音频服务:" << std::endl;
for (const auto& service : services) {
std::cout << "- " << service.service_name
<< " (" << service.address << ":" << service.port << ")" << std::endl;
std::cout << " 服务类型: " << service.service_type << std::endl;
std::cout << " 服务ID: " << service.service_id << std::endl;
if (!service.properties.empty()) {
std::cout << " 服务属性:" << std::endl;
for (const auto& [key, value] : service.properties) {
std::cout << " " << key << ": " << value << std::endl;
}
}
}
}
// 停止网络服务发现
frontend.stop_network_discovery();
}
会话管理
前端接口提供会话管理功能,用于建立和维护与远程服务的连接:
common::ErrorCode connect_to_network_service(const std::string& service_id);
common::ErrorCode disconnect_from_network_service(const std::string& service_id);
此外,还可以使用专用的会话管理器来管理更复杂的会话场景:
// 创建会话管理器
auto session_manager = audio_backend::frontend::create_session_manager();
// 创建会话服务器
auto session_server = audio_backend::frontend::create_session_server(9999);
会话管理示例:
void manage_network_session(audio_backend::frontend::FrontendManager& frontend) {
// 启动网络服务发现
frontend.start_network_discovery();
// 等待服务发现
std::this_thread::sleep_for(std::chrono::seconds(3));
// 获取已发现的服务
auto services = frontend.get_discovered_services();
if (services.empty()) {
std::cout << "未发现音频服务,无法建立会话" << std::endl;
return;
}
// 连接到第一个发现的服务
auto service = services[0];
std::cout << "连接到服务: " << service.service_name << std::endl;
auto result = frontend.connect_to_network_service(service.service_id);
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "连接网络服务失败" << std::endl;
return;
}
std::cout << "已连接到网络服务,按回车键断开..." << std::endl;
std::cin.get();
// 断开与服务的连接
result = frontend.disconnect_from_network_service(service.service_id);
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "断开网络服务失败" << std::endl;
return;
}
std::cout << "已断开网络服务连接" << std::endl;
// 停止网络服务发现
frontend.stop_network_discovery();
}
音频流传输
前端接口提供了网络音频流传输功能:
common::ErrorCode start_network_audio_stream(const std::string& target_address, uint16_t port);
common::ErrorCode stop_network_audio_stream();
common::ErrorCode send_audio_data_to_network(const engine::AudioBuffer& buffer, const std::string& target);
此外,还可以使用专用的音频流发送器和接收器来进行更灵活的控制:
// 创建音频流发送器
auto sender = audio_backend::frontend::create_audio_stream_sender(48000, 2);
// 创建音频流接收器
auto receiver = audio_backend::frontend::create_audio_stream_receiver(48000, 2);
音频流传输示例:
void stream_audio_over_network(audio_backend::frontend::FrontendManager& frontend,
const std::string& target_address,
uint16_t port) {
// 启动网络音频流
auto result = frontend.start_network_audio_stream(target_address, port);
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "启动网络音频流失败" << std::endl;
return;
}
std::cout << "网络音频流已启动,流向: " << target_address << ":" << port << std::endl;
std::cout << "按回车键停止..." << std::endl;
std::cin.get();
// 停止网络音频流
result = frontend.stop_network_audio_stream();
if (result != audio_backend::common::ErrorCode::SUCCESS) {
std::cerr << "停止网络音频流失败" << std::endl;
return;
}
std::cout << "网络音频流已停止" << std::endl;
}
音频编解码
编解码器接口
前端接口支持多种音频编解码器,用于网络传输时的压缩和解压缩:
namespace audio_backend::frontend::codec {
enum class CodecType {
PCM, // 无压缩PCM
OPUS, // Opus编解码器
AAC, // AAC编解码器
FLAC // FLAC编解码器
};
struct CodecConfig {
CodecType codec_type; // 编解码器类型
uint32_t sample_rate; // 采样率
uint16_t channels; // 声道数
uint32_t bitrate; // 比特率
uint32_t complexity = 10; // 复杂度 (0-10)
bool vbr = true; // 是否使用可变比特率
bool fec = true; // 是否使用前向纠错
uint32_t packet_size_ms = 20; // 数据包大小(毫秒)
};
class IAudioCodec {
public:
virtual ~IAudioCodec() = default;
// 编码音频数据
virtual std::vector<uint8_t> encode(const float* audio_data,
size_t samples_per_channel) = 0;
// 解码音频数据
virtual size_t decode(const uint8_t* encoded_data,
size_t encoded_size,
float* output_buffer,
size_t output_buffer_size) = 0;
// 获取配置
virtual CodecConfig get_config() const = 0;
// 获取延迟样本数
virtual uint32_t get_codec_delay_samples() const = 0;
};
} // namespace audio_backend::frontend::codec
缓冲区管理
前端接口提供了缓冲区管理,用于处理网络传输中的抖动和延迟:
namespace audio_backend::frontend::network {
struct BufferManagerConfig {
uint32_t initial_buffer_size_ms; // 初始缓冲区大小(毫秒)
uint32_t min_buffer_size_ms; // 最小缓冲区大小(毫秒)
uint32_t max_buffer_size_ms; // 最大缓冲区大小(毫秒)
uint32_t target_buffer_size_ms; // 目标缓冲区大小(毫秒)
uint32_t sample_rate; // 采样率
uint16_t channels; // 声道数
bool adaptive_buffering; // 是否启用自适应缓冲
uint32_t adaptation_speed; // 自适应速度 (1-10)
};
class BufferManager {
public:
virtual ~BufferManager() = default;
// 添加音频数据到缓冲区
virtual void add_audio_data(const std::vector<uint8_t>& data,
uint32_t timestamp) = 0;
// 获取可用的音频数据
virtual engine::AudioBuffer get_audio_data(uint32_t num_frames) = 0;
// 获取当前缓冲区状态
virtual uint32_t get_buffered_ms() const = 0;
virtual uint32_t get_underruns() const = 0;
virtual uint32_t get_overruns() const = 0;
// 缓冲区控制
virtual void clear() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
// 配置
virtual void set_config(const BufferManagerConfig& config) = 0;
virtual BufferManagerConfig get_config() const = 0;
};
} // namespace audio_backend::frontend::network
使用编解码器和缓冲区管理的示例:
void audio_codec_example() {
// 创建Opus编解码器
auto codec_config = audio_backend::frontend::codec::CodecConfig{
audio_backend::frontend::codec::CodecType::OPUS,
48000, // 采样率
2, // 声道数
128000 // 比特率
};
auto codec = audio_backend::frontend::codec::create_codec(codec_config);
// 创建缓冲区管理器
auto buffer_config = audio_backend::frontend::network::BufferManagerConfig{
50, // 初始缓冲50ms
20, // 最小缓冲20ms
200, // 最大缓冲200ms
50, // 目标缓冲50ms
48000, // 采样率
2, // 声道数
true, // 启用自适应缓冲
5 // 中等自适应速度
};
auto buffer_manager = audio_backend::frontend::create_buffer_manager(
buffer_config.initial_buffer_size_ms,
buffer_config.sample_rate,
buffer_config.channels);
// 模拟音频处理流程
const size_t frame_size = 480; // 10ms @ 48kHz
std::vector<float> audio_samples(frame_size * 2); // 立体声
// 生成一些示例音频数据(正弦波)
for (size_t i = 0; i < frame_size; i++) {
float sample = std::sin(2.0f * 3.14159f * 440.0f * i / 48000.0f);
audio_samples[i * 2] = sample; // 左声道
audio_samples[i * 2 + 1] = sample; // 右声道
}
// 编码音频数据
auto encoded_data = codec->encode(audio_samples.data(), frame_size);
std::cout << "原始音频大小: " << (frame_size * 2 * sizeof(float)) << " 字节" << std::endl;
std::cout << "编码后大小: " << encoded_data.size() << " 字节" << std::endl;
std::cout << "压缩率: " << ((float)encoded_data.size() / (frame_size * 2 * sizeof(float)) * 100) << "%" << std::endl;
// 将编码数据添加到缓冲区
buffer_manager->add_audio_data(encoded_data, 0);
// 获取音频数据
auto output_buffer = buffer_manager->get_audio_data(frame_size);
std::cout << "缓冲区状态: " << buffer_manager->get_buffered_ms() << "ms 已缓冲" << std::endl;
}
事件处理
事件类型
前端接口定义了多种事件类型,用于通知应用程序状态变化:
enum class FrontendEvent {
EngineConnected, // 音频引擎连接成功
EngineDisconnected, // 音频引擎断开连接
DeviceAdded, // 音频设备添加
DeviceRemoved, // 音频设备移除
NetworkServiceFound, // 发现网络服务
NetworkServiceLost, // 网络服务丢失
AudioStreamStarted, // 音频流开始
AudioStreamStopped, // 音频流停止
ConfigurationChanged // 配置变更
};
事件监听器
应用程序可以通过实现IFrontendEventListener接口来接收前端事件:
class IFrontendEventListener {
public:
virtual ~IFrontendEventListener() = default;
// 事件回调
virtual void on_frontend_event(FrontendEvent event, const std::string& data) = 0;
// 音频事件
virtual void on_audio_device_changed(const std::string& device_id, bool added) = 0;
virtual void on_audio_stream_data(const engine::AudioBuffer& buffer) = 0;
// 网络事件
virtual void on_network_service_discovered(const std::string& service_name,
const std::string& address,
uint16_t port) = 0;
// 错误事件
virtual void on_frontend_error(common::ErrorCode error, const std::string& message) = 0;
};
事件监听器示例:
class MyFrontendListener : public audio_backend::frontend::IFrontendEventListener {
public:
void on_frontend_event(audio_backend::frontend::FrontendEvent event,
const std::string& data) override {
std::cout << "前端事件: ";
switch (event) {
case audio_backend::frontend::FrontendEvent::EngineConnected:
std::cout << "引擎已连接";
break;
case audio_backend::frontend::FrontendEvent::EngineDisconnected:
std::cout << "引擎已断开";
break;
case audio_backend::frontend::FrontendEvent::DeviceAdded:
std::cout << "设备已添加";
break;
case audio_backend::frontend::FrontendEvent::DeviceRemoved:
std::cout << "设备已移除";
break;
case audio_backend::frontend::FrontendEvent::NetworkServiceFound:
std::cout << "发现网络服务";
break;
case audio_backend::frontend::FrontendEvent::NetworkServiceLost:
std::cout << "网络服务丢失";
break;
case audio_backend::frontend::FrontendEvent::AudioStreamStarted:
std::cout << "音频流已启动";
break;
case audio_backend::frontend::FrontendEvent::AudioStreamStopped:
std::cout << "音频流已停止";
break;
case audio_backend::frontend::FrontendEvent::ConfigurationChanged:
std::cout << "配置已更改";
break;
default:
std::cout << "未知事件";
break;
}
if (!data.empty()) {
std::cout << " - 数据: " << data;
}
std::cout << std::endl;
}
void on_audio_device_changed(const std::string& device_id, bool added) override {
std::cout << "音频设备" << (added ? "添加" : "移除") << ": " << device_id << std::endl;
}
void on_audio_stream_data(const audio_backend::engine::AudioBuffer& buffer) override {
// 实际应用中可能对音频数据进行处理
std::cout << "接收到音频数据: " << buffer.frames() << " 帧, "
<< buffer.channels() << " 声道" << std::endl;
}
void on_network_service_discovered(const std::string& service_name,
const std::string& address,
uint16_t port) override {
std::cout << "发现网络服务: " << service_name << " @ "
<< address << ":" << port << std::endl;
}
void on_frontend_error(audio_backend::common::ErrorCode error,
const std::string& message) override {
std::cerr << "前端错误: " << audio_backend::common::error_to_string(error)
<< " - " << message << std::endl;
}
};
// 使用事件监听器
void use_event_listener(audio_backend::frontend::FrontendManager& frontend) {
auto listener = std::make_shared<MyFrontendListener>();
frontend.add_event_listener(listener);
// 执行会触发事件的操作
// ...
// 移除事件监听器
frontend.remove_event_listener(listener);
}
工厂函数
基础工厂
前端接口提供了多种工厂函数,用于创建各种前端组件:
namespace audio_backend::frontend {
// 创建前端管理器
std::unique_ptr<Manager> create_frontend_manager(const std::string& process_name = "audio_frontend");
// 创建引擎代理
std::unique_ptr<EngineProxy> create_engine_proxy(const std::string& endpoint = "tcp://localhost:5555");
// 创建设备管理器
std::unique_ptr<DeviceManager> create_device_manager();
// 创建音频流发送器
std::unique_ptr<AudioStreamSender> create_audio_stream_sender(
uint32_t sample_rate = 48000,
uint16_t channels = 2,
frontend::network::AudioCodec codec = frontend::network::AudioCodec::OPUS);
// 创建音频流接收器
std::unique_ptr<AudioStreamReceiver> create_audio_stream_receiver(
uint32_t sample_rate = 48000,
uint16_t channels = 2,
frontend::network::AudioCodec codec = frontend::network::AudioCodec::OPUS);
// 创建服务发现
std::unique_ptr<ServiceDiscovery> create_service_discovery();
// 创建会话管理器
std::unique_ptr<SessionManager> create_session_manager();
// 创建会话服务器
std::unique_ptr<SessionServer> create_session_server(uint16_t port = 9999);
// 创建编解码器
std::unique_ptr<AudioCodec> create_audio_codec(
frontend::codec::CodecType type,
uint32_t sample_rate = 48000,
uint16_t channels = 2,
uint32_t bitrate = 128000);
// 创建缓冲管理器
std::unique_ptr<BufferManager> create_buffer_manager(
uint32_t initial_buffer_size_ms = 50,
uint32_t sample_rate = 48000,
uint16_t channels = 2);
} // namespace audio_backend::frontend
预配置组合
前端接口还提供了预配置的工厂函数,用于创建具有特定功能的前端管理器:
namespace audio_backend::frontend {
// 创建本地音频前端(无网络功能)
std::unique_ptr<Manager> create_local_frontend();
// 创建网络客户端前端(连接到远程音频引擎)
std::unique_ptr<Manager> create_network_client_frontend(
const std::string& server_address,
uint16_t port);
// 创建低延迟音频流配置
std::unique_ptr<Manager> create_low_latency_frontend();
// 创建高质量音频流配置
std::unique_ptr<Manager> create_high_quality_frontend();
// 创建平衡配置(延迟和质量的平衡)
std::unique_ptr<Manager> create_balanced_frontend();
} // namespace audio_backend::frontend
使用工厂函数示例:
void factory_functions_example() {
// 创建本地前端
auto local_frontend = audio_backend::frontend::create_local_frontend();
if (local_frontend) {
std::cout << "创建本地前端成功" << std::endl;
}
// 创建低延迟前端
auto low_latency = audio_backend::frontend::create_low_latency_frontend();
if (low_latency) {
std::cout << "创建低延迟前端成功" << std::endl;
}
// 创建高质量前端
auto high_quality = audio_backend::frontend::create_high_quality_frontend();
if (high_quality) {
std::cout << "创建高质量前端成功" << std::endl;
}
// 创建平衡前端
auto balanced = audio_backend::frontend::create_balanced_frontend();
if (balanced) {
std::cout << "创建平衡前端成功" << std::endl;
}
}
实现示例
本地音频处理
以下是使用前端接口进行本地音频处理的完整示例:
#include "audio_backend/frontend.h"
#include <iostream>
#include <thread>
#include <chrono>
using namespace audio_backend;
// 自定义音频处理回调
class MyAudioProcessor : public frontend::IFrontendEventListener {
public:
void on_frontend_event(frontend::FrontendEvent event, const std::string& data) override {
std::cout << "事件: ";
switch (event) {
case frontend::FrontendEvent::AudioStreamStarted:
std::cout << "音频流已启动" << std::endl;
break;
case frontend::FrontendEvent::AudioStreamStopped:
std::cout << "音频流已停止" << std::endl;
break;
default:
std::cout << "其他事件" << std::endl;
break;
}
}
void on_audio_device_changed(const std::string& device_id, bool added) override {
// 不处理设备变化
}
void on_network_service_discovered(const std::string& service_name,
const std::string& address,
uint16_t port) override {
// 不处理网络服务
}
void on_audio_stream_data(const engine::AudioBuffer& buffer) override {
// 处理音频数据(在本例中,简单地计算音量)
double sum = 0.0;
size_t samples = buffer.frames() * buffer.channels();
if (buffer.is_interleaved()) {
const float* data = buffer.interleaved_data<float>();
for (size_t i = 0; i < samples; i++) {
sum += std::abs(data[i]);
}
} else {
for (uint16_t ch = 0; ch < buffer.channels(); ch++) {
const float* data = buffer.channel_data<float>(ch);
for (uint32_t i = 0; i < buffer.frames(); i++) {
sum += std::abs(data[i]);
}
}
}
double average = sum / samples;
frames_processed += buffer.frames();
// 每秒更新一次统计
auto now = std::chrono::steady_clock::now();
if (now - last_update > std::chrono::seconds(1)) {
std::cout << "已处理: " << frames_processed << " 帧, 平均音量: "
<< (average * 100) << "%" << std::endl;
last_update = now;
}
}
void on_frontend_error(common::ErrorCode error, const std::string& message) override {
std::cerr << "错误: " << common::error_to_string(error) << " - " << message << std::endl;
}
private:
uint64_t frames_processed = 0;
std::chrono::steady_clock::time_point last_update = std::chrono::steady_clock::now();
};
int main() {
// 初始化前端系统
frontend::initialize_frontend();
// 创建前端管理器(本地模式)
auto frontend_manager = frontend::create_local_frontend();
if (!frontend_manager) {
std::cerr << "创建前端管理器失败" << std::endl;
return 1;
}
// 初始化前端管理器
auto result = frontend_manager->initialize();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "初始化前端管理器失败: " << common::error_to_string(result) << std::endl;
return 1;
}
// 创建并添加事件监听器
auto processor = std::make_shared<MyAudioProcessor>();
frontend_manager->add_event_listener(processor);
// 连接到本地音频引擎
result = frontend_manager->connect_to_engine("tcp://localhost:5555");
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "连接音频引擎失败: " << common::error_to_string(result) << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
// 列出可用音频设备
auto devices = frontend_manager->get_audio_devices();
std::cout << "可用音频设备:" << std::endl;
for (const auto& device : devices) {
std::cout << (device.is_default ? "* " : " ")
<< device.name << (device.is_input ? " (输入)" : " (输出)") << std::endl;
}
// 设置默认输入设备
for (const auto& device : devices) {
if (device.is_default && device.is_input) {
frontend_manager->set_input_device(device.id);
break;
}
}
// 设置默认输出设备
for (const auto& device : devices) {
if (device.is_default && device.is_output) {
frontend_manager->set_output_device(device.id);
break;
}
}
// 启动音频流
std::cout << "启动音频流..." << std::endl;
result = frontend_manager->start_audio_stream();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "启动音频流失败: " << common::error_to_string(result) << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
// 运行10秒钟
std::cout << "音频处理中,将运行10秒..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(10));
// 停止音频流
std::cout << "停止音频流..." << std::endl;
result = frontend_manager->stop_audio_stream();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "停止音频流失败: " << common::error_to_string(result) << std::endl;
}
// 断开音频引擎连接
frontend_manager->disconnect_from_engine();
// 移除事件监听器
frontend_manager->remove_event_listener(processor);
// 关闭前端管理器
frontend_manager->shutdown();
// 清理前端系统
frontend::shutdown_frontend();
std::cout << "程序已完成" << std::endl;
return 0;
}
远程音频传输
以下是使用前端接口进行远程音频传输的完整示例:
#include "audio_backend/frontend.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
using namespace audio_backend;
// 定义传输角色
enum class TransportRole {
Sender,
Receiver
};
// 网络音频监听器
class NetworkAudioListener : public frontend::IFrontendEventListener {
public:
explicit NetworkAudioListener(TransportRole role)
: role_(role), audio_frames_(0) {}
void on_frontend_event(frontend::FrontendEvent event, const std::string& data) override {
std::cout << (role_ == TransportRole::Sender ? "发送端" : "接收端")
<< " 事件: ";
switch (event) {
case frontend::FrontendEvent::EngineConnected:
std::cout << "引擎已连接" << std::endl;
break;
case frontend::FrontendEvent::NetworkServiceFound:
std::cout << "发现服务: " << data << std::endl;
services_discovered_ = true;
break;
case frontend::FrontendEvent::AudioStreamStarted:
std::cout << "音频流已启动" << std::endl;
stream_active_ = true;
break;
case frontend::FrontendEvent::AudioStreamStopped:
std::cout << "音频流已停止" << std::endl;
stream_active_ = false;
break;
default:
std::cout << "其他事件" << std::endl;
break;
}
}
void on_audio_device_changed(const std::string& device_id, bool added) override {
// 不处理设备变化
}
void on_network_service_discovered(const std::string& service_name,
const std::string& address,
uint16_t port) override {
std::cout << "发现网络服务: " << service_name
<< " @ " << address << ":" << port << std::endl;
discovered_address_ = address;
discovered_port_ = port;
services_discovered_ = true;
}
void on_audio_stream_data(const engine::AudioBuffer& buffer) override {
audio_frames_ += buffer.frames();
// 每秒报告一次
auto now = std::chrono::steady_clock::now();
if (now - last_report_ > std::chrono::seconds(1)) {
double seconds = std::chrono::duration<double>(now - last_report_).count();
double frames_per_second = audio_frames_ / seconds;
std::cout << (role_ == TransportRole::Sender ? "发送" : "接收")
<< " 速率: " << frames_per_second << " 帧/秒 ("
<< (frames_per_second / buffer.sample_rate()) << "x 实时速率)"
<< std::endl;
audio_frames_ = 0;
last_report_ = now;
}
}
void on_frontend_error(common::ErrorCode error, const std::string& message) override {
std::cerr << (role_ == TransportRole::Sender ? "发送端" : "接收端")
<< " 错误: " << common::error_to_string(error)
<< " - " << message << std::endl;
}
bool has_discovered_service() const { return services_discovered_; }
std::string get_discovered_address() const { return discovered_address_; }
uint16_t get_discovered_port() const { return discovered_port_; }
bool is_stream_active() const { return stream_active_; }
private:
TransportRole role_;
uint64_t audio_frames_;
std::chrono::steady_clock::time_point last_report_ = std::chrono::steady_clock::now();
std::atomic<bool> services_discovered_{false};
std::atomic<bool> stream_active_{false};
std::string discovered_address_;
uint16_t discovered_port_ = 0;
};
// 远程音频传输示例
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "用法: " << argv[0] << " [sender|receiver]" << std::endl;
return 1;
}
std::string mode = argv[1];
TransportRole role = (mode == "sender") ? TransportRole::Sender : TransportRole::Receiver;
// 初始化前端系统
frontend::initialize_frontend();
// 创建前端管理器
auto frontend_manager = frontend::create_frontend_manager();
if (!frontend_manager) {
std::cerr << "创建前端管理器失败" << std::endl;
return 1;
}
// 配置前端管理器
auto config = frontend_manager->config();
config.enable_network_discovery = true;
config.enable_network_streaming = true;
config.audio_stream_port = 8888;
frontend_manager->update_config(config);
// 初始化前端管理器
auto result = frontend_manager->initialize();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "初始化前端管理器失败" << std::endl;
return 1;
}
// 创建并添加事件监听器
auto listener = std::make_shared<NetworkAudioListener>(role);
frontend_manager->add_event_listener(listener);
// 连接到音频引擎
result = frontend_manager->connect_to_engine();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "连接音频引擎失败" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
if (role == TransportRole::Sender) {
// === 发送端 ===
// 配置音频设备
auto devices = frontend_manager->get_audio_devices();
// 设置默认输入设备
for (const auto& device : devices) {
if (device.is_default && device.is_input) {
frontend_manager->set_input_device(device.id);
std::cout << "使用输入设备: " << device.name << std::endl;
break;
}
}
// 启动音频流
result = frontend_manager->start_audio_stream();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "启动音频流失败" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
// 启动网络发现(可选)
frontend_manager->start_network_discovery();
// 启动网络音频流
std::cout << "启动网络音频流,监听端口: " << config.audio_stream_port << std::endl;
// 这里使用本地地址,实际应用中可能是远程地址
result = frontend_manager->start_network_audio_stream("0.0.0.0", config.audio_stream_port);
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "启动网络音频流失败" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
std::cout << "发送音频中,按回车停止..." << std::endl;
std::cin.get();
// 停止网络音频流
frontend_manager->stop_network_audio_stream();
// 停止音频流
frontend_manager->stop_audio_stream();
} else {
// === 接收端 ===
// 启动网络发现
std::cout << "启动网络服务发现..." << std::endl;
frontend_manager->start_network_discovery();
// 设置默认输出设备
auto devices = frontend_manager->get_audio_devices();
for (const auto& device : devices) {
if (device.is_default && device.is_output) {
frontend_manager->set_output_device(device.id);
std::cout << "使用输出设备: " << device.name << std::endl;
break;
}
}
// 等待发现服务
std::cout << "等待发现音频发送服务..." << std::endl;
// 在实际应用中,应该使用事件驱动方式等待服务发现
// 这里简单起见使用轮询
int timeout_seconds = 30;
for (int i = 0; i < timeout_seconds; i++) {
if (listener->has_discovered_service()) {
break;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "等待中... " << (timeout_seconds - i - 1) << " 秒" << std::endl;
}
if (!listener->has_discovered_service()) {
std::cerr << "未发现音频服务,超时" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
std::string address = listener->get_discovered_address();
uint16_t port = listener->get_discovered_port();
if (port == 0) {
port = 8888; // 使用默认端口
}
std::cout << "连接到音频服务: " << address << ":" << port << std::endl;
// 启动音频流
result = frontend_manager->start_audio_stream();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "启动音频流失败" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
// 连接到网络音频流
result = frontend_manager->start_network_audio_stream(address, port);
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "连接网络音频流失败" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
std::cout << "接收音频中,按回车停止..." << std::endl;
std::cin.get();
// 停止网络音频流
frontend_manager->stop_network_audio_stream();
// 停止音频流
frontend_manager->stop_audio_stream();
}
// 断开音频引擎连接
frontend_manager->disconnect_from_engine();
// 移除事件监听器
frontend_manager->remove_event_listener(listener);
// 关闭前端管理器
frontend_manager->shutdown();
// 清理前端系统
frontend::shutdown_frontend();
std::cout << "程序已完成" << std::endl;
return 0;
}
网络服务发现
以下是使用前端接口进行网络服务发现的示例:
#include "audio_backend/frontend.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <map>
#include <mutex>
using namespace audio_backend;
// 服务浏览器
class ServiceBrowser : public frontend::IFrontendEventListener {
public:
void on_frontend_event(frontend::FrontendEvent event, const std::string& data) override {
if (event == frontend::FrontendEvent::NetworkServiceFound) {
std::cout << "发现服务: " << data << std::endl;
} else if (event == frontend::FrontendEvent::NetworkServiceLost) {
std::cout << "丢失服务: " << data << std::endl;
}
}
void on_audio_device_changed(const std::string& device_id, bool added) override {
// 不处理设备变化
}
void on_audio_stream_data(const engine::AudioBuffer& buffer) override {
// 不处理音频数据
}
void on_network_service_discovered(const std::string& service_name,
const std::string& address,
uint16_t port) override {
std::lock_guard<std::mutex> lock(mutex_);
std::string key = service_name + "@" + address + ":" + std::to_string(port);
if (services_.find(key) == services_.end()) {
std::cout << "新服务: " << service_name << " @ " << address << ":" << port << std::endl;
services_[key] = {
service_name,
address,
port,
std::chrono::steady_clock::now()
};
} else {
// 更新最后发现时间
services_[key].last_seen = std::chrono::steady_clock::now();
}
}
void on_frontend_error(common::ErrorCode error, const std::string& message) override {
std::cerr << "错误: " << common::error_to_string(error) << " - " << message << std::endl;
}
void print_active_services() {
std::lock_guard<std::mutex> lock(mutex_);
auto now = std::chrono::steady_clock::now();
std::cout << "\n当前活动服务:" << std::endl;
std::cout << "-----------------------------------------" << std::endl;
int count = 0;
for (const auto& [key, service] : services_) {
// 检查服务是否在过去30秒内活动
auto age = std::chrono::duration_cast<std::chrono::seconds>(now - service.last_seen).count();
if (age <= 30) {
std::cout << ++count << ". " << service.name
<< " @ " << service.address << ":" << service.port
<< " (上次发现: " << age << " 秒前)" << std::endl;
}
}
if (count == 0) {
std::cout << "未发现活动服务" << std::endl;
}
std::cout << "-----------------------------------------" << std::endl;
}
private:
struct ServiceInfo {
std::string name;
std::string address;
uint16_t port;
std::chrono::steady_clock::time_point last_seen;
};
std::map<std::string, ServiceInfo> services_;
std::mutex mutex_;
};
// 网络服务发现示例
int main() {
// 初始化前端系统
frontend::initialize_frontend();
std::cout << "音频服务浏览器" << std::endl;
std::cout << "===========================================" << std::endl;
// 创建前端管理器
auto frontend_manager = frontend::create_frontend_manager();
if (!frontend_manager) {
std::cerr << "创建前端管理器失败" << std::endl;
return 1;
}
// 配置前端管理器
auto config = frontend_manager->config();
config.enable_network_discovery = true;
frontend_manager->update_config(config);
// 初始化前端管理器
auto result = frontend_manager->initialize();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "初始化前端管理器失败" << std::endl;
return 1;
}
// 创建服务浏览器
auto browser = std::make_shared<ServiceBrowser>();
frontend_manager->add_event_listener(browser);
// 启动网络服务发现
result = frontend_manager->start_network_discovery();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "启动网络服务发现失败" << std::endl;
frontend_manager->shutdown();
frontend::shutdown_frontend();
return 1;
}
std::cout << "开始浏览网络音频服务..." << std::endl;
std::cout << "每10秒打印一次活动服务列表" << std::endl;
std::cout << "按回车键退出" << std::endl;
// 创建一个独立线程来打印服务列表
std::atomic<bool> running(true);
std::thread printer_thread([&]() {
while (running) {
std::this_thread::sleep_for(std::chrono::seconds(10));
if (running) {
browser->print_active_services();
}
}
});
// 等待用户输入退出
std::cin.get();
running = false;
// 等待打印线程结束
if (printer_thread.joinable()) {
printer_thread.join();
}
// 停止网络服务发现
frontend_manager->stop_network_discovery();
// 移除事件监听器
frontend_manager->remove_event_listener(browser);
// 关闭前端管理器
frontend_manager->shutdown();
// 清理前端系统
frontend::shutdown_frontend();
std::cout << "程序已完成" << std::endl;
return 0;
}
性能优化
延迟优化
针对低延迟场景的优化策略:
-
缓冲区大小:使用小缓冲区大小(128-256帧)
// 配置低延迟前端 auto config = frontend_manager->config(); config.audio_buffer_size = 128; config.network_buffer_size = 512; config.max_latency_ms = 20; frontend_manager->update_config(config); -
编解码器设置:使用低延迟编解码器配置
// 低延迟Opus编解码器配置 auto codec_config = frontend::codec::CodecConfig{ frontend::codec::CodecType::OPUS, 48000, // 采样率 2, // 声道数 64000, // 比特率 5, // 中等复杂度 false, // 禁用VBR true, // 启用FEC 10 // 10ms包大小 }; -
网络传输优化:使用UDP传输和抖动缓冲
// 创建UDP传输 auto transport = frontend::create_udp_transport(config.audio_stream_port); // 配置抖动缓冲区 auto buffer_config = frontend::network::BufferManagerConfig{ 20, // 初始缓冲20ms 5, // 最小缓冲5ms 50, // 最大缓冲50ms 20, // 目标缓冲20ms 48000, // 采样率 2, // 声道数 true, // 启用自适应缓冲 8 // 快速自适应 };
带宽优化
针对带宽受限场景的优化策略:
-
编解码器设置:使用高压缩率配置
// 带宽优化Opus编解码器配置 auto codec_config = frontend::codec::CodecConfig{ frontend::codec::CodecType::OPUS, 48000, // 采样率 2, // 声道数 32000, // 低比特率 10, // 高复杂度 true, // 启用VBR true, // 启用FEC 40 // 40ms包大小(更大包减少带宽开销) }; -
数据压缩:对元数据进行压缩
// 启用元数据压缩 transport->enable_metadata_compression(true); -
优化采样率:根据带宽调整采样率
// 根据网络带宽动态调整音频质量 frontend_manager->set_adaptive_quality(true);
跨平台考虑
网络兼容性
不同平台的网络差异:
-
Windows:
- 使用Winsock 2 API
- mDNS实现使用Bonjour或DNS-SD
- 网络安全策略:Windows防火墙
-
Linux:
- 使用标准BSD套接字
- mDNS实现使用Avahi
- 网络安全策略:iptables或ufw
-
macOS:
- 使用标准BSD套接字
- mDNS实现使用Bonjour
- 网络安全策略:pf或应用沙盒
跨平台网络兼容性考虑:
// 检测平台特定网络功能
bool is_mdns_supported() {
#ifdef _WIN32
// Windows: 检查Bonjour或DNS-SD
return check_windows_mdns_support();
#elif defined(__APPLE__)
// macOS: 内置Bonjour支持
return true;
#elif defined(__linux__)
// Linux: 检查Avahi
return check_linux_avahi_support();
#else
// 其他平台
return false;
#endif
}
设备兼容性
不同平台的音频设备差异:
-
Windows:
- 支持WASAPI、DirectSound、ASIO
- 设备枚举通过Windows Multimedia API
- 设备格式限制与平台特定
-
Linux:
- 支持ALSA、PulseAudio、JACK
- 设备枚举因音频系统而异
- 权限问题(如对/dev/snd的访问权限)
-
macOS:
- 支持CoreAudio
- 设备枚举通过Audio Device API
- 应用沙盒限制对设备的访问
跨平台设备兼容性考虑:
// 获取平台最佳设备配置
frontend::DeviceConfiguration get_platform_optimal_config() {
frontend::DeviceConfiguration config;
#ifdef _WIN32
// Windows优化配置
config.api = "wasapi";
config.exclusive_mode = true;
config.buffer_size = 480; // 10ms @ 48kHz
#elif defined(__APPLE__)
// macOS优化配置
config.api = "coreaudio";
config.buffer_size = 256;
#elif defined(__linux__)
// Linux优化配置
// 检测是否有JACK
if (check_jack_available()) {
config.api = "jack";
config.buffer_size = 256;
} else {
config.api = "pulseaudio";
config.buffer_size = 480;
}
#endif
return config;
}