Files
Alicho/tests/unit/engine/audio_format_conversion_test.cpp
2025-10-28 10:27:49 +08:00

272 lines
9.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ================================================================================================
// 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();
}