Files
Alicho/examples/frontend_demo.cpp
2025-10-28 10:27:49 +08:00

459 lines
17 KiB
C++

// ================================================================================================
// Audio Backend - 前端通信接口示例
// ================================================================================================
// 描述: 演示前端通信模块的使用方法
// 功能: 引擎连接、设备管理、网络发现、音频传输
// ================================================================================================
#include "audio_backend/frontend.h"
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <atomic>
#include <csignal>
using namespace audio_backend;
using namespace audio_backend::frontend;
// 全局退出标志
std::atomic<bool> g_running{true};
// 信号处理器
void signal_handler(int signal) {
std::cout << "接收到信号: " << signal << ", 准备退出..." << std::endl;
g_running = false;
}
// 事件监听器
class DemoEventListener : public IFrontendEventListener {
public:
void on_frontend_event(FrontendEvent event, const std::string& data) override {
std::cout << "[事件] ";
switch (event) {
case FrontendEvent::EngineConnected:
std::cout << "引擎已连接";
break;
case FrontendEvent::EngineDisconnected:
std::cout << "引擎已断开";
break;
case FrontendEvent::DeviceAdded:
std::cout << "设备已添加";
break;
case FrontendEvent::DeviceRemoved:
std::cout << "设备已移除";
break;
case FrontendEvent::NetworkServiceFound:
std::cout << "发现网络服务";
break;
case FrontendEvent::NetworkServiceLost:
std::cout << "丢失网络服务";
break;
case FrontendEvent::AudioStreamStarted:
std::cout << "音频流已开始";
break;
case FrontendEvent::AudioStreamStopped:
std::cout << "音频流已停止";
break;
case 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 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(common::ErrorCode error, const std::string& message) override {
std::cout << "[错误] 代码: " << static_cast<int>(error)
<< " 消息: " << message << std::endl;
}
};
// ================================================================================================
// 本地音频引擎连接示例
// ================================================================================================
void local_engine_demo() {
std::cout << "\n=== 本地音频引擎连接示例 ===\n" << std::endl;
// 创建前端管理器
auto frontend = create_frontend_manager("demo_frontend");
if (!frontend) {
std::cerr << "无法创建前端管理器" << std::endl;
return;
}
// 添加事件监听器
auto listener = std::make_shared<DemoEventListener>();
frontend->add_event_listener(listener);
// 初始化前端
auto result = frontend->initialize();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "前端初始化失败: " << static_cast<int>(result) << std::endl;
return;
}
std::cout << "前端初始化成功" << std::endl;
// 连接到音频引擎
std::cout << "连接到本地音频引擎..." << std::endl;
result = frontend->connect_to_engine("tcp://localhost:5555");
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "无法连接到音频引擎: " << static_cast<int>(result) << std::endl;
std::cout << "请确保音频引擎正在运行,继续演示其他功能..." << std::endl;
} else {
std::cout << "成功连接到音频引擎" << std::endl;
}
// 获取音频设备
std::cout << "\n获取音频设备列表..." << std::endl;
auto devices = frontend->get_audio_devices();
if (devices.empty()) {
std::cout << "未找到音频设备" << std::endl;
} else {
std::cout << "找到 " << devices.size() << " 个音频设备:" << std::endl;
for (const auto& device : devices) {
std::cout << " - " << device.name
<< " (ID: " << device.id << ")"
<< " [" << (device.is_input ? "输入" : "")
<< (device.is_output ? "输出" : "") << "]"
<< (device.is_default ? " 默认" : "") << std::endl;
}
// 如果找到默认输出设备,设置它
for (const auto& device : devices) {
if (device.is_output && device.is_default) {
std::cout << "\n设置默认输出设备: " << device.name << std::endl;
frontend->set_output_device(device.id);
break;
}
}
}
// 启动音频流(在实际环境中可能会开始播放声音)
std::cout << "\n尝试启动音频..." << std::endl;
result = frontend->start_audio_stream();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "无法启动音频流: " << static_cast<int>(result) << std::endl;
} else {
std::cout << "音频流已启动" << std::endl;
// 保持音频流一小段时间
std::cout << "音频流运行中..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "停止音频流..." << std::endl;
frontend->stop_audio_stream();
}
// 断开音频引擎
std::cout << "\n断开音频引擎..." << std::endl;
frontend->disconnect_from_engine();
// 关闭前端
std::cout << "关闭前端..." << std::endl;
frontend->shutdown();
std::cout << "本地音频引擎示例完成" << std::endl;
}
// ================================================================================================
// 网络服务发现示例
// ================================================================================================
void network_discovery_demo() {
std::cout << "\n=== 网络服务发现示例 ===\n" << std::endl;
// 创建前端管理器
auto frontend = create_frontend_manager("discovery_demo");
if (!frontend) {
std::cerr << "无法创建前端管理器" << std::endl;
return;
}
// 添加事件监听器
auto listener = std::make_shared<DemoEventListener>();
frontend->add_event_listener(listener);
// 初始化前端
auto result = frontend->initialize();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "前端初始化失败: " << static_cast<int>(result) << std::endl;
return;
}
// 启动网络发现
std::cout << "启动网络服务发现..." << std::endl;
result = frontend->start_network_discovery();
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "无法启动网络发现: " << static_cast<int>(result) << std::endl;
frontend->shutdown();
return;
}
// 等待并显示发现的服务
std::cout << "搜索网络音频服务 (5秒)..." << 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.service_type << ")"
<< " 地址: " << service.address
<< " 端口: " << service.port << std::endl;
}
// 如果发现了服务,尝试连接第一个服务
if (!services.empty()) {
const auto& first_service = services[0];
std::cout << "\n尝试连接到服务: " << first_service.service_name << std::endl;
result = frontend->connect_to_network_service(first_service.service_id);
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "无法连接到服务: " << static_cast<int>(result) << std::endl;
} else {
std::cout << "成功连接到服务" << std::endl;
// 在实际应用中,此处可以开始音频流传输
// frontend->start_network_audio_stream(...);
std::cout << "断开服务连接..." << std::endl;
frontend->disconnect_from_network_service(first_service.service_id);
}
}
}
// 停止网络发现
std::cout << "\n停止网络发现..." << std::endl;
frontend->stop_network_discovery();
// 关闭前端
frontend->shutdown();
std::cout << "网络服务发现示例完成" << std::endl;
}
// ================================================================================================
// 音频流传输示例
// ================================================================================================
void audio_streaming_demo() {
std::cout << "\n=== 音频流传输示例 ===\n" << std::endl;
// 创建音频流发送器
auto sender_config = network::create_balanced_config();
auto sender = network::create_audio_stream_sender(sender_config);
if (!sender) {
std::cerr << "无法创建音频流发送器" << std::endl;
return;
}
// 创建音频流接收器
auto receiver_config = network::create_balanced_config();
auto receiver = network::create_audio_stream_receiver(receiver_config);
if (!receiver) {
std::cerr << "无法创建音频流接收器" << std::endl;
return;
}
// 创建UDP传输
auto transport_config = network::transport_factory::get_recommended_udp_config();
transport_config.local_port = 12345; // 发送端端口
auto transport = network::transport_factory::create_udp_transport();
if (!transport) {
std::cerr << "无法创建UDP传输" << std::endl;
return;
}
// 初始化传输
if (transport->initialize(transport_config) != common::ErrorCode::SUCCESS) {
std::cerr << "无法初始化UDP传输" << std::endl;
return;
}
// 绑定到本地端口
network::NetworkEndpoint local_endpoint("127.0.0.1", 12345, network::TransportProtocol::UDP);
if (transport->bind(local_endpoint) != common::ErrorCode::SUCCESS) {
std::cerr << "无法绑定到本地端口" << std::endl;
return;
}
// 接收器的传输(在实际应用中,这会在不同机器上)
auto receiver_transport = network::transport_factory::create_udp_transport();
transport_config.local_port = 12346; // 接收端端口
receiver_transport->initialize(transport_config);
network::NetworkEndpoint receiver_endpoint("127.0.0.1", 12346, network::TransportProtocol::UDP);
receiver_transport->bind(receiver_endpoint);
// 初始化发送器和接收器
sender->initialize(transport);
receiver->initialize(receiver_transport);
std::cout << "音频流传输已设置,实际应用中会传输音频数据" << std::endl;
std::cout << "发送器 -> 127.0.0.1:12345" << std::endl;
std::cout << "接收器 <- 127.0.0.1:12346" << std::endl;
// 在实际应用中,此处会有一个循环发送音频数据
/*
// 示例代码(不会执行)
engine::AudioConfig config;
config.sample_rate = 48000;
config.channels = 2;
config.format = engine::AudioFormat::FLOAT32;
config.frames_per_buffer = 480; // 10ms @ 48kHz
engine::AudioBuffer buffer(config);
while (running) {
// 获取音频数据到buffer
sender->send_audio(buffer);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
*/
// 关闭发送器和接收器
std::cout << "\n关闭音频流..." << std::endl;
sender->shutdown();
receiver->shutdown();
transport->shutdown();
receiver_transport->shutdown();
std::cout << "音频流传输示例成" << std::endl;
}
// ================================================================================================
// 编解码示例
// ================================================================================================
void codec_demo() {
std::cout << "\n=== 音频编解码示例 ===\n" << std::endl;
// 创建Opus编解码器
codec::CodecConfig opus_config;
opus_config.codec_type = codec::CodecType::OPUS;
opus_config.sample_rate = 48000;
opus_config.channels = 2;
opus_config.bitrate = 128000; // 128 kbps
auto encoder = codec::create_codec(opus_config);
if (!encoder) {
std::cerr << "无法创建Opus编解码器" << std::endl;
return;
}
// 初始化编码器
encoder->initialize();
// 创建测试音频缓冲区
engine::AudioConfig audio_config;
audio_config.sample_rate = 48000;
audio_config.channels = 2;
audio_config.format = engine::AudioFormat::FLOAT32;
audio_config.frames_per_buffer = 960; // 20ms @ 48kHz
engine::AudioBuffer test_buffer(audio_config);
// 生成正弦波测试数据
float* data = test_buffer.interleaved_data<float>();
for (uint32_t i = 0; i < test_buffer.frames(); i++) {
for (uint16_t c = 0; c < test_buffer.channels(); c++) {
// 生成一个440Hz的正弦波
float sample = std::sin(2.0f * 3.14159f * 440.0f * i / 48000.0f);
data[i * test_buffer.channels() + c] = sample * 0.5f; // 半音量
}
}
// 编码测试数据
std::vector<uint8_t> encoded_data;
auto result = encoder->encode(test_buffer, encoded_data);
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "编码失败: " << static_cast<int>(result) << std::endl;
encoder->shutdown();
return;
}
std::cout << "音频编码结果:" << std::endl;
std::cout << " - 原始大小: " << test_buffer.size_bytes() << " 字节" << std::endl;
std::cout << " - 编码大小: " << encoded_data.size() << " 字节" << std::endl;
std::cout << " - 压缩率: " << (100.0 * encoded_data.size() / test_buffer.size_bytes()) << "%" << std::endl;
// 解码测试数据
engine::AudioBuffer decoded_buffer;
result = encoder->decode(encoded_data, decoded_buffer);
if (result != common::ErrorCode::SUCCESS) {
std::cerr << "解码失败: " << static_cast<int>(result) << std::endl;
encoder->shutdown();
return;
}
std::cout << "音频解码结果:" << std::endl;
std::cout << " - 解码后大小: " << decoded_buffer.size_bytes() << " 字节" << std::endl;
std::cout << " - 帧数: " << decoded_buffer.frames() << std::endl;
std::cout << " - 声道数: " << decoded_buffer.channels() << std::endl;
// 关闭编解码器
encoder->shutdown();
std::cout << "音频编解码示例完成" << std::endl;
}
// ================================================================================================
// 主函数
// ================================================================================================
int main() {
std::cout << "====================================\n";
std::cout << "Audio Backend 前端通信示例\n";
std::cout << "====================================\n";
// 设置信号处理
std::signal(SIGINT, signal_handler); // Ctrl+C
std::signal(SIGTERM, signal_handler); // 终止信号
try {
// 初始化前端系统
frontend::initialize_frontend();
// 运行各个示例
local_engine_demo();
network_discovery_demo();
audio_streaming_demo();
codec_demo();
// 关闭前端系统
frontend::shutdown_frontend();
std::cout << "\n====================================\n";
std::cout << "演示完成\n";
std::cout << "====================================\n";
} catch (const std::exception& e) {
std::cerr << "演示过程中发生错误: " << e.what() << "\n";
return 1;
}
return 0;
}