340 lines
10 KiB
C++
340 lines
10 KiB
C++
// ================================================================================================
|
|
// Audio Backend - 音频缓冲区测试
|
|
// ================================================================================================
|
|
|
|
#include <gtest/gtest.h>
|
|
#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<float>();
|
|
for (size_t i = 0; i < 256 * 2; ++i) {
|
|
data[i] = static_cast<float>(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<float>();
|
|
for (size_t i = 0; i < 256 * 2; ++i) {
|
|
data[i] = static_cast<float>(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<float>();
|
|
for (size_t i = 0; i < 256 * 2; ++i) {
|
|
data[i] = static_cast<float>(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<float>();
|
|
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<float>();
|
|
EXPECT_NE(data, nullptr);
|
|
|
|
// 填充一些数据
|
|
for (size_t i = 0; i < 256 * 2; ++i) {
|
|
data[i] = static_cast<float>(i) / 100.0f;
|
|
}
|
|
|
|
// 读取数据
|
|
for (size_t i = 0; i < 256 * 2; ++i) {
|
|
EXPECT_FLOAT_EQ(data[i], static_cast<float>(i) / 100.0f);
|
|
}
|
|
|
|
// 对于交错缓冲区,尝试访问独立通道应该抛出异常
|
|
EXPECT_THROW(buffer.channel_data<float>(0), common::AudioException);
|
|
}
|
|
|
|
// 测试非交错格式数据访问
|
|
TEST_F(AudioBufferTest, NonInterleavedAccess) {
|
|
AudioBuffer buffer(256, 2, AudioFormat::FLOAT32, false);
|
|
|
|
// 获取各声道数据指针
|
|
float* ch0 = buffer.channel_data<float>(0);
|
|
float* ch1 = buffer.channel_data<float>(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<float>(i) / 100.0f;
|
|
ch1[i] = -static_cast<float>(i) / 100.0f; // 使第二个声道为负值
|
|
}
|
|
|
|
// 读取数据
|
|
for (size_t i = 0; i < 256; ++i) {
|
|
EXPECT_FLOAT_EQ(ch0[i], static_cast<float>(i) / 100.0f);
|
|
EXPECT_FLOAT_EQ(ch1[i], -static_cast<float>(i) / 100.0f);
|
|
}
|
|
|
|
// 超出范围的声道访问应该抛出异常
|
|
EXPECT_THROW(buffer.channel_data<float>(2), common::AudioException);
|
|
|
|
// 对于非交错缓冲区,尝试访问交错数据应该抛出异常
|
|
EXPECT_THROW(buffer.interleaved_data<float>(), common::AudioException);
|
|
}
|
|
|
|
// 测试交错/非交错格式转换
|
|
TEST_F(AudioBufferTest, FormatConversion) {
|
|
// 创建交错缓冲区
|
|
AudioBuffer interleaved(256, 2, AudioFormat::FLOAT32, true);
|
|
|
|
// 填充一些数据
|
|
float* data = interleaved.interleaved_data<float>();
|
|
for (size_t i = 0; i < 256 * 2; ++i) {
|
|
data[i] = static_cast<float>(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<float>(0);
|
|
float* ch1 = non_interleaved.channel_data<float>(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<float>();
|
|
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();
|
|
} |