272 lines
9.5 KiB
C++
272 lines
9.5 KiB
C++
// ================================================================================================
|
||
// Audio Backend - 音频格式转换测试
|
||
// ================================================================================================
|
||
|
||
#include <gtest/gtest.h>
|
||
#include "engine/audio_buffer.h"
|
||
#include "simd/audio_processing.h"
|
||
#include "tests/common/test_fixtures.h"
|
||
#include "tests/common/test_utils.h"
|
||
#include <vector>
|
||
#include <limits>
|
||
|
||
using namespace audio_backend;
|
||
using namespace audio_backend::engine;
|
||
using namespace audio_backend::simd;
|
||
|
||
// 音频格式转换测试固定装置
|
||
class AudioFormatConversionTest : public test::AudioEngineTest {
|
||
protected:
|
||
void SetUp() override {
|
||
test::AudioEngineTest::SetUp();
|
||
|
||
// 设置最大值常量
|
||
int16_max_ = std::numeric_limits<int16_t>::max();
|
||
int32_max_ = std::numeric_limits<int32_t>::max();
|
||
|
||
// 准备测试数据
|
||
setup_test_data();
|
||
}
|
||
|
||
void TearDown() override {
|
||
test::AudioEngineTest::TearDown();
|
||
}
|
||
|
||
// 准备各种格式的测试数据
|
||
void setup_test_data() {
|
||
// 创建测试样本(包含正负值和特殊值)
|
||
float_samples_ = {
|
||
0.0f, 0.5f, -0.5f, 1.0f, -1.0f,
|
||
0.25f, -0.25f, 0.75f, -0.75f,
|
||
0.1f, -0.1f, 0.01f, -0.01f,
|
||
0.99f, -0.99f, 0.999f, -0.999f
|
||
};
|
||
|
||
// 从float生成对应的int16数据
|
||
int16_samples_.resize(float_samples_.size());
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
int16_samples_[i] = static_cast<int16_t>(float_samples_[i] * int16_max_);
|
||
}
|
||
|
||
// 从float生成对应的int24数据(存储在int32中)
|
||
int32_samples_.resize(float_samples_.size());
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
int32_samples_[i] = static_cast<int32_t>(float_samples_[i] * 8388607.0f); // 2^23 - 1
|
||
}
|
||
}
|
||
|
||
protected:
|
||
std::vector<float> float_samples_;
|
||
std::vector<int16_t> int16_samples_;
|
||
std::vector<int32_t> int32_samples_;
|
||
|
||
int16_t int16_max_;
|
||
int32_t int32_max_;
|
||
};
|
||
|
||
// 测试FLOAT32 -> INT16转换
|
||
TEST_F(AudioFormatConversionTest, FloatToInt16Conversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<int16_t> output(float_samples_.size());
|
||
|
||
// 转换
|
||
convert_float_to_int16(float_samples_.data(), output.data(), float_samples_.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
int16_t expected = static_cast<int16_t>(float_samples_[i] * int16_max_);
|
||
EXPECT_NEAR(output[i], expected, 1) << "at index " << i; // 允许±1的误差
|
||
}
|
||
|
||
// 测试特殊情况: 大于1.0的值应该被限幅为最大值
|
||
float large_value = 1.5f;
|
||
int16_t clipped_output;
|
||
convert_float_to_int16(&large_value, &clipped_output, 1);
|
||
EXPECT_EQ(clipped_output, int16_max_);
|
||
|
||
// 测试特殊情况: 小于-1.0的值应该被限幅为最小值
|
||
float small_value = -1.5f;
|
||
convert_float_to_int16(&small_value, &clipped_output, 1);
|
||
EXPECT_EQ(clipped_output, -int16_max_ - 1); // -32768
|
||
}
|
||
|
||
// 测试INT16 -> FLOAT32转换
|
||
TEST_F(AudioFormatConversionTest, Int16ToFloatConversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<float> output(int16_samples_.size());
|
||
|
||
// 转换
|
||
convert_int16_to_float(int16_samples_.data(), output.data(), int16_samples_.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < int16_samples_.size(); ++i) {
|
||
float expected = static_cast<float>(int16_samples_[i]) / int16_max_;
|
||
EXPECT_NEAR(output[i], expected, 1.0f / int16_max_) << "at index " << i;
|
||
}
|
||
|
||
// 测试特殊情况: 最大值应该转换为接近1.0
|
||
int16_t max_value = int16_max_;
|
||
float max_output;
|
||
convert_int16_to_float(&max_value, &max_output, 1);
|
||
EXPECT_NEAR(max_output, 1.0f, 1.0f / int16_max_);
|
||
|
||
// 测试特殊情况: 最小值应该转换为接近-1.0
|
||
int16_t min_value = -int16_max_ - 1; // -32768
|
||
float min_output;
|
||
convert_int16_to_float(&min_value, &min_output, 1);
|
||
EXPECT_NEAR(min_output, -1.0f, 1.0f / int16_max_);
|
||
}
|
||
|
||
// 测试FLOAT32 -> INT32转换
|
||
TEST_F(AudioFormatConversionTest, FloatToInt32Conversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<int32_t> output(float_samples_.size());
|
||
|
||
// 转换
|
||
convert_float_to_int32(float_samples_.data(), output.data(), float_samples_.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
int32_t expected = static_cast<int32_t>(float_samples_[i] * int32_max_);
|
||
// int32转换精度较高,但仍允许小的误差
|
||
EXPECT_NEAR(output[i], expected, 256) << "at index " << i;
|
||
}
|
||
|
||
// 测试特殊情况: 大于1.0的值应该被限幅
|
||
float large_value = 1.5f;
|
||
int32_t clipped_output;
|
||
convert_float_to_int32(&large_value, &clipped_output, 1);
|
||
EXPECT_EQ(clipped_output, int32_max_);
|
||
}
|
||
|
||
// 测试INT32 -> FLOAT32转换
|
||
TEST_F(AudioFormatConversionTest, Int32ToFloatConversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<float> output(int32_samples_.size());
|
||
|
||
// 转换
|
||
convert_int32_to_float(int32_samples_.data(), output.data(), int32_samples_.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < int32_samples_.size(); ++i) {
|
||
float expected = static_cast<float>(int32_samples_[i]) / 8388607.0f; // 2^23 - 1 (24位有效位)
|
||
EXPECT_NEAR(output[i], expected, 1.0f / 8388607.0f) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
// 测试FLOAT32 -> INT24转换
|
||
TEST_F(AudioFormatConversionTest, FloatToInt24Conversion) {
|
||
// 创建输出缓冲区 (INT24存储在INT32中)
|
||
std::vector<int32_t> output(float_samples_.size());
|
||
|
||
// 转换
|
||
convert_float_to_int24(float_samples_.data(), output.data(), float_samples_.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
int32_t expected = static_cast<int32_t>(float_samples_[i] * 8388607.0f); // 2^23 - 1
|
||
// 确保值在24位范围内
|
||
expected &= 0x00FFFFFF;
|
||
if (expected & 0x00800000) { // 负值处理
|
||
expected |= 0xFF000000;
|
||
}
|
||
|
||
// 24位转换允许小的误差
|
||
EXPECT_NEAR(output[i], expected, 2) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
// 测试INT24 -> FLOAT32转换
|
||
TEST_F(AudioFormatConversionTest, Int24ToFloatConversion) {
|
||
// 准备24位整数样本(在int32中存储)
|
||
std::vector<int32_t> int24_samples(float_samples_.size());
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
int24_samples[i] = static_cast<int32_t>(float_samples_[i] * 8388607.0f) & 0x00FFFFFF;
|
||
if (int24_samples[i] & 0x00800000) { // 负值处理
|
||
int24_samples[i] |= 0xFF000000;
|
||
}
|
||
}
|
||
|
||
// 创建输出缓冲区
|
||
std::vector<float> output(int24_samples.size());
|
||
|
||
// 转换
|
||
convert_int24_to_float(int24_samples.data(), output.data(), int24_samples.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < int24_samples.size(); ++i) {
|
||
float expected = static_cast<float>(int24_samples[i]) / 8388607.0f; // 2^23 - 1
|
||
EXPECT_NEAR(output[i], expected, 1.0f / 8388607.0f) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
// 测试FLOAT32 -> FLOAT64转换
|
||
TEST_F(AudioFormatConversionTest, FloatToDoubleConversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<double> output(float_samples_.size());
|
||
|
||
// 转换
|
||
convert_float_to_double(float_samples_.data(), output.data(), float_samples_.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
double expected = static_cast<double>(float_samples_[i]);
|
||
EXPECT_DOUBLE_EQ(output[i], expected) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
// 测试FLOAT64 -> FLOAT32转换
|
||
TEST_F(AudioFormatConversionTest, DoubleToFloatConversion) {
|
||
// 准备双精度浮点样本
|
||
std::vector<double> double_samples(float_samples_.size());
|
||
for (size_t i = 0; i < float_samples_.size(); ++i) {
|
||
double_samples[i] = static_cast<double>(float_samples_[i]);
|
||
}
|
||
|
||
// 创建输出缓冲区
|
||
std::vector<float> output(double_samples.size());
|
||
|
||
// 转换
|
||
convert_double_to_float(double_samples.data(), output.data(), double_samples.size());
|
||
|
||
// 验证
|
||
for (size_t i = 0; i < double_samples.size(); ++i) {
|
||
float expected = static_cast<float>(double_samples[i]);
|
||
EXPECT_FLOAT_EQ(output[i], expected) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
// 测试INT16 -> INT32转换
|
||
TEST_F(AudioFormatConversionTest, Int16ToInt32Conversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<int32_t> output(int16_samples_.size());
|
||
|
||
// 转换
|
||
convert_int16_to_int32(int16_samples_.data(), output.data(), int16_samples_.size());
|
||
|
||
// 验证 (16位转32位应该是左移16位)
|
||
for (size_t i = 0; i < int16_samples_.size(); ++i) {
|
||
int32_t expected = static_cast<int32_t>(int16_samples_[i]) << 16;
|
||
EXPECT_EQ(output[i], expected) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
// 测试INT32 -> INT16转换
|
||
TEST_F(AudioFormatConversionTest, Int32ToInt16Conversion) {
|
||
// 创建输出缓冲区
|
||
std::vector<int16_t> output(int32_samples_.size());
|
||
|
||
// 转换
|
||
convert_int32_to_int16(int32_samples_.data(), output.data(), int32_samples_.size());
|
||
|
||
// 验证 (32位转16位应该是右移16位,可能会有截断)
|
||
for (size_t i = 0; i < int32_samples_.size(); ++i) {
|
||
int16_t expected = static_cast<int16_t>(int32_samples_[i] >> 8); // 从24位转16位
|
||
EXPECT_NEAR(output[i], expected, 1) << "at index " << i;
|
||
}
|
||
}
|
||
|
||
int main(int argc, char** argv) {
|
||
::testing::InitGoogleTest(&argc, argv);
|
||
return RUN_ALL_TESTS();
|
||
} |