// ================================================================================================ // 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 AudioBufferConversionTest : public test::AudioEngineTest { protected: void SetUp() override { test::AudioEngineTest::SetUp(); // 准备不同格式的测试值 int16_max_ = std::numeric_limits::max(); int24_max_ = 8388607; // 2^23 - 1 int32_max_ = std::numeric_limits::max(); // 创建标准测试数据 setup_test_buffers(); } void TearDown() override { test::AudioEngineTest::TearDown(); } // 设置不同格式的测试缓冲区 void setup_test_buffers() { // 浮点数据 [-1.0, 1.0] float_buffer_ = std::make_unique(16, 2, AudioFormat::FLOAT32); float* float_data = float_buffer_->interleaved_data(); for (int i = 0; i < 32; ++i) { // 16帧 * 2通道 float_data[i] = (i % 2 == 0) ? 1.0f * i / 31.0f : -1.0f * i / 31.0f; } // INT16数据 [-32768, 32767] int16_buffer_ = std::make_unique(16, 2, AudioFormat::INT16); int16_t* int16_data = int16_buffer_->interleaved_data(); for (int i = 0; i < 32; ++i) { int16_data[i] = (i % 2 == 0) ? static_cast(int16_max_ * i / 31) : static_cast(-int16_max_ * i / 31); } // INT32数据 [-2147483648, 2147483647] int32_buffer_ = std::make_unique(16, 2, AudioFormat::INT32); int32_t* int32_data = int32_buffer_->interleaved_data(); for (int i = 0; i < 32; ++i) { int32_data[i] = (i % 2 == 0) ? static_cast(int32_max_ * i / 31) : static_cast(-int32_max_ * i / 31); } } // 测试辅助函数 // 检查Float32到Int16转换的精度 void check_float_to_int16(const AudioBuffer& source, const AudioBuffer& converted) { const float* src_data = source.interleaved_data(); const int16_t* conv_data = converted.interleaved_data(); for (size_t i = 0; i < source.frames() * source.channels(); ++i) { int16_t expected = static_cast(src_data[i] * int16_max_); EXPECT_NEAR(conv_data[i], expected, 1) << "at index " << i; } } // 检查Int16到Float32转换的精度 void check_int16_to_float(const AudioBuffer& source, const AudioBuffer& converted) { const int16_t* src_data = source.interleaved_data(); const float* conv_data = converted.interleaved_data(); for (size_t i = 0; i < source.frames() * source.channels(); ++i) { float expected = static_cast(src_data[i]) / int16_max_; EXPECT_NEAR(conv_data[i], expected, 1.0f/int16_max_) << "at index " << i; } } // 检查Float32到Int32转换的精度 void check_float_to_int32(const AudioBuffer& source, const AudioBuffer& converted) { const float* src_data = source.interleaved_data(); const int32_t* conv_data = converted.interleaved_data(); for (size_t i = 0; i < source.frames() * source.channels(); ++i) { int32_t expected = static_cast(src_data[i] * int32_max_); // 允许一定的误差范围,因为浮点转整型有精度损失 EXPECT_NEAR(conv_data[i], expected, 256) << "at index " << i; } } // 检查Int32到Float32转换的精度 void check_int32_to_float(const AudioBuffer& source, const AudioBuffer& converted) { const int32_t* src_data = source.interleaved_data(); const float* conv_data = converted.interleaved_data(); for (size_t i = 0; i < source.frames() * source.channels(); ++i) { float expected = static_cast(src_data[i]) / int32_max_; EXPECT_NEAR(conv_data[i], expected, 1.0f/int32_max_) << "at index " << i; } } protected: std::unique_ptr float_buffer_; std::unique_ptr int16_buffer_; std::unique_ptr int32_buffer_; int16_t int16_max_; int32_t int24_max_; int32_t int32_max_; }; // 测试Float32到INT16的转换 TEST_F(AudioBufferConversionTest, Float32ToInt16Conversion) { AudioBuffer converted = float_buffer_->convert_format(AudioFormat::INT16); EXPECT_EQ(converted.format(), AudioFormat::INT16); EXPECT_EQ(converted.channels(), float_buffer_->channels()); EXPECT_EQ(converted.frames(), float_buffer_->frames()); check_float_to_int16(*float_buffer_, converted); } // 测试INT16到Float32的转换 TEST_F(AudioBufferConversionTest, Int16ToFloat32Conversion) { AudioBuffer converted = int16_buffer_->convert_format(AudioFormat::FLOAT32); EXPECT_EQ(converted.format(), AudioFormat::FLOAT32); EXPECT_EQ(converted.channels(), int16_buffer_->channels()); EXPECT_EQ(converted.frames(), int16_buffer_->frames()); check_int16_to_float(*int16_buffer_, converted); } // 测试Float32到INT32的转换 TEST_F(AudioBufferConversionTest, Float32ToInt32Conversion) { AudioBuffer converted = float_buffer_->convert_format(AudioFormat::INT32); EXPECT_EQ(converted.format(), AudioFormat::INT32); EXPECT_EQ(converted.channels(), float_buffer_->channels()); EXPECT_EQ(converted.frames(), float_buffer_->frames()); check_float_to_int32(*float_buffer_, converted); } // 测试INT32到Float32的转换 TEST_F(AudioBufferConversionTest, Int32ToFloat32Conversion) { AudioBuffer converted = int32_buffer_->convert_format(AudioFormat::FLOAT32); EXPECT_EQ(converted.format(), AudioFormat::FLOAT32); EXPECT_EQ(converted.channels(), int32_buffer_->channels()); EXPECT_EQ(converted.frames(), int32_buffer_->frames()); check_int32_to_float(*int32_buffer_, converted); } // 测试INT16到INT32的转换 TEST_F(AudioBufferConversionTest, Int16ToInt32Conversion) { AudioBuffer converted = int16_buffer_->convert_format(AudioFormat::INT32); EXPECT_EQ(converted.format(), AudioFormat::INT32); EXPECT_EQ(converted.channels(), int16_buffer_->channels()); EXPECT_EQ(converted.frames(), int16_buffer_->frames()); // 验证转换 const int16_t* src_data = int16_buffer_->interleaved_data(); const int32_t* conv_data = converted.interleaved_data(); for (size_t i = 0; i < int16_buffer_->frames() * int16_buffer_->channels(); ++i) { // INT16到INT32: 左移16位 int32_t expected = static_cast(src_data[i]) << 16; EXPECT_EQ(conv_data[i], expected) << "at index " << i; } } // 测试INT32到INT16的转换 TEST_F(AudioBufferConversionTest, Int32ToInt16Conversion) { AudioBuffer converted = int32_buffer_->convert_format(AudioFormat::INT16); EXPECT_EQ(converted.format(), AudioFormat::INT16); EXPECT_EQ(converted.channels(), int32_buffer_->channels()); EXPECT_EQ(converted.frames(), int32_buffer_->frames()); // 验证转换 const int32_t* src_data = int32_buffer_->interleaved_data(); const int16_t* conv_data = converted.interleaved_data(); for (size_t i = 0; i < int32_buffer_->frames() * int32_buffer_->channels(); ++i) { // INT32到INT16: 右移16位并截断 int16_t expected = static_cast(src_data[i] >> 16); EXPECT_EQ(conv_data[i], expected) << "at index " << i; } } // 测试相同格式间的转换(应该是高效的复制) TEST_F(AudioBufferConversionTest, SameFormatConversion) { AudioBuffer converted = float_buffer_->convert_format(AudioFormat::FLOAT32); EXPECT_EQ(converted.format(), AudioFormat::FLOAT32); EXPECT_EQ(converted.channels(), float_buffer_->channels()); EXPECT_EQ(converted.frames(), float_buffer_->frames()); // 数据应该完全相同 const float* src_data = float_buffer_->interleaved_data(); const float* conv_data = converted.interleaved_data(); for (size_t i = 0; i < float_buffer_->frames() * float_buffer_->channels(); ++i) { EXPECT_FLOAT_EQ(conv_data[i], src_data[i]) << "at index " << i; } } // 测试无效格式转换 TEST_F(AudioBufferConversionTest, InvalidFormatConversion) { // 转换为未知格式应该抛出异常 EXPECT_THROW(float_buffer_->convert_format(AudioFormat::UNKNOWN), common::AudioException); } // 测试重采样功能 TEST_F(AudioBufferConversionTest, Resampling) { // 创建44.1kHz的缓冲区 AudioConfig config; config.sample_rate = 44100; config.channels = 2; config.format = AudioFormat::FLOAT32; config.frames_per_buffer = 100; AudioBuffer original(config); // 填充数据(简单的正弦波) float* data = original.interleaved_data(); for (size_t i = 0; i < config.frames_per_buffer; ++i) { float t = static_cast(i) / config.sample_rate; float sample = std::sin(2.0f * M_PI * 440.0f * t); // 440Hz正弦波 data[i * 2] = sample; data[i * 2 + 1] = sample; } // 重采样到48kHz uint32_t new_sample_rate = 48000; AudioBuffer resampled = original.resample(new_sample_rate); // 检查基本属性 EXPECT_EQ(resampled.sample_rate(), new_sample_rate); EXPECT_EQ(resampled.channels(), original.channels()); EXPECT_EQ(resampled.format(), original.format()); // 新帧数应该成比例变化 float ratio = static_cast(new_sample_rate) / original.sample_rate(); size_t expected_frames = static_cast(original.frames() * ratio); EXPECT_EQ(resampled.frames(), expected_frames); } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }