// ================================================================================================ // Audio Backend - 音频缓冲区测试 // ================================================================================================ #include #include "engine/audio_buffer.h" #include "tests/common/test_fixtures.h" #include "tests/common/test_utils.h" using namespace audio_backend; using namespace audio_backend::engine; // 音频缓冲区测试固定装置 class AudioBufferTest : public test::AudioEngineTest { protected: void SetUp() override { test::AudioEngineTest::SetUp(); } void TearDown() override { test::AudioEngineTest::TearDown(); } }; // 测试默认构造函数 TEST_F(AudioBufferTest, DefaultConstruction) { AudioBuffer buffer; EXPECT_TRUE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 0); EXPECT_EQ(buffer.channels(), 0); EXPECT_EQ(buffer.frames(), 0); EXPECT_EQ(buffer.format(), AudioFormat::UNKNOWN); } // 测试使用AudioConfig参数的构造 TEST_F(AudioBufferTest, ConfigConstruction) { AudioConfig config; config.sample_rate = 44100; config.channels = 2; config.format = AudioFormat::FLOAT32; config.frames_per_buffer = 256; // 交错格式 { AudioBuffer buffer(config, true); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 2048); // 256帧 * 2声道 * 4字节 EXPECT_EQ(buffer.channels(), 2); EXPECT_EQ(buffer.frames(), 256); EXPECT_EQ(buffer.format(), AudioFormat::FLOAT32); EXPECT_EQ(buffer.sample_rate(), 44100); EXPECT_TRUE(buffer.is_interleaved()); } // 非交错格式 { AudioBuffer buffer(config, false); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 2048); // 256帧 * 2声道 * 4字节 EXPECT_EQ(buffer.channels(), 2); EXPECT_EQ(buffer.frames(), 256); EXPECT_EQ(buffer.format(), AudioFormat::FLOAT32); EXPECT_EQ(buffer.sample_rate(), 44100); EXPECT_FALSE(buffer.is_interleaved()); } } // 测试使用参数列表的构造 TEST_F(AudioBufferTest, ParameterConstruction) { // 交错格式 { AudioBuffer buffer(256, 2, AudioFormat::FLOAT32, true); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 2048); // 256帧 * 2声道 * 4字节 EXPECT_EQ(buffer.channels(), 2); EXPECT_EQ(buffer.frames(), 256); EXPECT_EQ(buffer.format(), AudioFormat::FLOAT32); EXPECT_TRUE(buffer.is_interleaved()); } // 非交错格式 { AudioBuffer buffer(256, 2, AudioFormat::FLOAT32, false); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 2048); // 256帧 * 2声道 * 4字节 EXPECT_EQ(buffer.channels(), 2); EXPECT_EQ(buffer.frames(), 256); EXPECT_EQ(buffer.format(), AudioFormat::FLOAT32); EXPECT_FALSE(buffer.is_interleaved()); } } // 测试移动构造函数 TEST_F(AudioBufferTest, MoveConstruction) { AudioBuffer original(256, 2, AudioFormat::FLOAT32); // 填充一些数据 float* data = original.interleaved_data(); for (size_t i = 0; i < 256 * 2; ++i) { data[i] = static_cast(i) / 100.0f; } // 移动构造 AudioBuffer moved(std::move(original)); // 检查移动后的状态 EXPECT_FALSE(moved.empty()); EXPECT_EQ(moved.size_bytes(), 2048); EXPECT_EQ(moved.channels(), 2); EXPECT_EQ(moved.frames(), 256); EXPECT_EQ(moved.format(), AudioFormat::FLOAT32); EXPECT_TRUE(moved.is_interleaved()); // 原始缓冲区应该被清空 EXPECT_TRUE(original.empty()); EXPECT_EQ(original.size_bytes(), 0); } // 测试移动赋值操作符 TEST_F(AudioBufferTest, MoveAssignment) { AudioBuffer original(256, 2, AudioFormat::FLOAT32); AudioBuffer target; // 填充一些数据 float* data = original.interleaved_data(); for (size_t i = 0; i < 256 * 2; ++i) { data[i] = static_cast(i) / 100.0f; } // 移动赋值 target = std::move(original); // 检查移动后的状态 EXPECT_FALSE(target.empty()); EXPECT_EQ(target.size_bytes(), 2048); EXPECT_EQ(target.channels(), 2); EXPECT_EQ(target.frames(), 256); EXPECT_EQ(target.format(), AudioFormat::FLOAT32); EXPECT_TRUE(target.is_interleaved()); // 原始缓冲区应该被清空 EXPECT_TRUE(original.empty()); EXPECT_EQ(original.size_bytes(), 0); } // 测试克隆方法 TEST_F(AudioBufferTest, Clone) { AudioBuffer original(256, 2, AudioFormat::FLOAT32); // 填充一些数据 float* data = original.interleaved_data(); for (size_t i = 0; i < 256 * 2; ++i) { data[i] = static_cast(i) / 100.0f; } // 克隆 AudioBuffer cloned = original.clone(); // 检查克隆后的状态 EXPECT_FALSE(cloned.empty()); EXPECT_EQ(cloned.size_bytes(), original.size_bytes()); EXPECT_EQ(cloned.channels(), original.channels()); EXPECT_EQ(cloned.frames(), original.frames()); EXPECT_EQ(cloned.format(), original.format()); EXPECT_EQ(cloned.is_interleaved(), original.is_interleaved()); // 原始缓冲区应该保持不变 EXPECT_FALSE(original.empty()); // 数据应该一样,但地址不同 EXPECT_NE(cloned.data(), original.data()); EXPECT_EQ(memcmp(cloned.data(), original.data(), original.size_bytes()), 0); } // 测试重新分配缓冲区 TEST_F(AudioBufferTest, Allocation) { AudioBuffer buffer; // 初始状态 EXPECT_TRUE(buffer.empty()); // 第一次分配 buffer.allocate(256, 2, AudioFormat::FLOAT32); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 2048); // 再次分配(扩大) buffer.allocate(512, 2, AudioFormat::FLOAT32); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 4096); // 再次分配(缩小) buffer.allocate(128, 2, AudioFormat::FLOAT32); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 1024); // 使用配置分配 AudioConfig config; config.frames_per_buffer = 1024; config.channels = 4; config.format = AudioFormat::INT16; buffer.allocate(config); EXPECT_FALSE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 8192); // 1024帧 * 4声道 * 2字节 // 释放 buffer.release(); EXPECT_TRUE(buffer.empty()); EXPECT_EQ(buffer.size_bytes(), 0); } // 测试清空缓冲区 TEST_F(AudioBufferTest, Clear) { AudioBuffer buffer(256, 2, AudioFormat::FLOAT32); // 填充一些数据 float* data = buffer.interleaved_data(); for (size_t i = 0; i < 256 * 2; ++i) { data[i] = 1.0f; // 全部设为1.0 } // 清空 buffer.clear(); // 验证所有数据都是0 for (size_t i = 0; i < 256 * 2; ++i) { EXPECT_FLOAT_EQ(data[i], 0.0f); } } // 测试交错格式数据访问 TEST_F(AudioBufferTest, InterleavedAccess) { AudioBuffer buffer(256, 2, AudioFormat::FLOAT32, true); // 获取交错数据指针 float* data = buffer.interleaved_data(); EXPECT_NE(data, nullptr); // 填充一些数据 for (size_t i = 0; i < 256 * 2; ++i) { data[i] = static_cast(i) / 100.0f; } // 读取数据 for (size_t i = 0; i < 256 * 2; ++i) { EXPECT_FLOAT_EQ(data[i], static_cast(i) / 100.0f); } // 对于交错缓冲区,尝试访问独立通道应该抛出异常 EXPECT_THROW(buffer.channel_data(0), common::AudioException); } // 测试非交错格式数据访问 TEST_F(AudioBufferTest, NonInterleavedAccess) { AudioBuffer buffer(256, 2, AudioFormat::FLOAT32, false); // 获取各声道数据指针 float* ch0 = buffer.channel_data(0); float* ch1 = buffer.channel_data(1); EXPECT_NE(ch0, nullptr); EXPECT_NE(ch1, nullptr); EXPECT_NE(ch0, ch1); // 填充一些数据 for (size_t i = 0; i < 256; ++i) { ch0[i] = static_cast(i) / 100.0f; ch1[i] = -static_cast(i) / 100.0f; // 使第二个声道为负值 } // 读取数据 for (size_t i = 0; i < 256; ++i) { EXPECT_FLOAT_EQ(ch0[i], static_cast(i) / 100.0f); EXPECT_FLOAT_EQ(ch1[i], -static_cast(i) / 100.0f); } // 超出范围的声道访问应该抛出异常 EXPECT_THROW(buffer.channel_data(2), common::AudioException); // 对于非交错缓冲区,尝试访问交错数据应该抛出异常 EXPECT_THROW(buffer.interleaved_data(), common::AudioException); } // 测试交错/非交错格式转换 TEST_F(AudioBufferTest, FormatConversion) { // 创建交错缓冲区 AudioBuffer interleaved(256, 2, AudioFormat::FLOAT32, true); // 填充一些数据 float* data = interleaved.interleaved_data(); for (size_t i = 0; i < 256 * 2; ++i) { data[i] = static_cast(i) / 100.0f; } // 转换为非交错格式 AudioBuffer non_interleaved = interleaved.to_non_interleaved(); EXPECT_FALSE(non_interleaved.is_interleaved()); EXPECT_EQ(non_interleaved.channels(), 2); EXPECT_EQ(non_interleaved.frames(), 256); // 验证数据正确性 float* ch0 = non_interleaved.channel_data(0); float* ch1 = non_interleaved.channel_data(1); for (size_t i = 0; i < 256; ++i) { // 交错格式: [L0,R0,L1,R1,...] // 非交错格式: [L0,L1,...], [R0,R1,...] EXPECT_FLOAT_EQ(ch0[i], data[i * 2]); EXPECT_FLOAT_EQ(ch1[i], data[i * 2 + 1]); } // 转换回交错格式 AudioBuffer back_to_interleaved = non_interleaved.to_interleaved(); EXPECT_TRUE(back_to_interleaved.is_interleaved()); // 验证转换后的数据与原始数据一致 float* converted_data = back_to_interleaved.interleaved_data(); for (size_t i = 0; i < 256 * 2; ++i) { EXPECT_FLOAT_EQ(converted_data[i], data[i]); } } // 测试对齐检查 TEST_F(AudioBufferTest, Alignment) { AudioBuffer buffer(256, 2, AudioFormat::FLOAT32); // 检查缓冲区是否正确对齐 EXPECT_TRUE(buffer.is_aligned()); } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }