Files
Alicho/tests/simd/test_simd_audio_processing.cpp

800 lines
30 KiB
C++
Raw 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.
/**
* @file test_audio_processing_comprehensive.cpp
* @brief 音频处理函数综合测试套件
*
* 测试覆盖:
* - 9个音频处理函数确性测试
* - 标量与SIMD版本的一致性测试
* - 边界条件和错误处理测试
* - 性能对比测试
* - 跨平台兼容性测试
*/
#include <gtest/gtest.h>
#include <vector>
#include <cmath>
#include <random>
#include <chrono>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <functional>
// 确保M_PI定义可用
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// 音频处理函数头文件
#include "aligned_allocator.h"
#include "simd_func_dispatcher.h"
#include "audio_processing/scalar_audio_processing_func.h"
#include "audio_processing/simd_audio_processing.h"
#if ALICHO_PLATFORM_X86
#include "audio_processing/x86_simd_audio_processing_func.h"
#endif
#if ALICHO_PLATFORM_ARM
#include "audio_processing/arm_simd_audio_processing_func.h"
#endif
// 测试容差设置
constexpr float FLOAT_TOLERANCE = 1e-6f;
constexpr float RMS_TOLERANCE = 1e-5f;
constexpr float PEAK_TOLERANCE = 1e-6f;
// 性能测试设置
constexpr size_t PERF_TEST_SIZE = 1024 * 1024; // 1M samples
constexpr int PERF_TEST_ITERATIONS = 100;
using aligned_audio_buffer = std::vector<float, avx512_aligned_allocator<float>>;
/**
* 浮点数比较函数
*/
bool float_equal(float a, float b, float tolerance = FLOAT_TOLERANCE) {
if (std::isnan(a) && std::isnan(b))
return true;
if (std::isinf(a) && std::isinf(b))
return (a > 0) == (b > 0);
return std::abs(a - b) <= tolerance;
}
/**
* 数组比较函数
*/
bool arrays_equal(const float* arr1, const float* arr2, size_t size, float tolerance = FLOAT_TOLERANCE) {
for (size_t i = 0; i < size; ++i) {
if (!float_equal(arr1[i], arr2[i], tolerance)) {
std::cout << " 差异在位置 " << i << ": " << arr1[i] << " vs " << arr2[i]
<< " (差值: " << std::abs(arr1[i] - arr2[i]) << ")" << std::endl;
return false;
}
}
return true;
}
/**
* 测试数据生成器
*/
class AudioDataGenerator {
private:
mutable std::mt19937 rng_{std::random_device{}()};
public:
// 生成正弦波
auto generate_sine_wave(size_t num_samples, float frequency = 440.0f,
float sample_rate = 44100.0f, float amplitude = 1.0f) const {
std::vector<float, aligned_allocator<float, ALIGNMENT_AVX512>> data(num_samples);
for (size_t i = 0; i < num_samples; ++i) {
data[i] = amplitude * std::sin(2.0f * M_PI * frequency * i / sample_rate);
}
return data;
}
// 生成白噪声
auto generate_white_noise(size_t num_samples, float amplitude = 1.0f) const {
std::vector<float, aligned_allocator<float, ALIGNMENT_AVX512>> data(num_samples);
std::uniform_real_distribution<float> dist(-amplitude, amplitude);
for (size_t i = 0; i < num_samples; ++i) {
data[i] = dist(rng_);
}
return data;
}
// 生成脉冲信号
auto generate_impulse(size_t num_samples, size_t impulse_pos = 0, float amplitude = 1.0f) const {
std::vector<float, aligned_allocator<float, ALIGNMENT_AVX512>> data(num_samples, 0.0f);
if (impulse_pos < num_samples) {
data[impulse_pos] = amplitude;
}
return data;
}
// 生成直流信号
aligned_audio_buffer generate_dc(size_t num_samples, float value = 1.0f) const {
return aligned_audio_buffer(num_samples, value);
}
// 生成立体声测试数据
aligned_audio_buffer generate_stereo_test_data(size_t num_stereo_samples) const {
aligned_audio_buffer data(num_stereo_samples * 2);
for (size_t i = 0; i < num_stereo_samples; ++i) {
data[i * 2] = std::sin(2.0f * M_PI * 440.0f * i / 44100.0f); // 左声道: 440Hz
data[i * 2 + 1] = std::sin(2.0f * M_PI * 880.0f * i / 44100.0f); // 右声道: 880Hz
}
return data;
}
// 生成边界测试数据
aligned_audio_buffer generate_boundary_data(size_t num_samples) const {
aligned_audio_buffer data;
data.reserve(num_samples);
// 添加各种边界值
if (num_samples > 0)
data.push_back(0.0f);
if (num_samples > 1)
data.push_back(1.0f);
if (num_samples > 2)
data.push_back(-1.0f);
if (num_samples > 3)
data.push_back(std::numeric_limits<float>::min());
if (num_samples > 4)
data.push_back(std::numeric_limits<float>::max());
if (num_samples > 5)
data.push_back(std::numeric_limits<float>::epsilon());
if (num_samples > 6)
data.push_back(-std::numeric_limits<float>::epsilon());
// 填充剩余位置
std::uniform_real_distribution<float> dist(-1.0f, 1.0f);
while (data.size() < num_samples) {
data.push_back(dist(rng_));
}
return data;
}
};
/**
* 性能测试辅助类
*/
class PerformanceTester {
public:
template <typename Func>
double measure_execution_time(Func&& func, int iterations = PERF_TEST_ITERATIONS) {
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
func();
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
return duration.count() / 1e6 / iterations; // 返回平均毫秒数
}
void print_performance_comparison(const std::string& test_name,
double scalar_time,
double simd_time) {
double speedup = scalar_time / simd_time;
std::cout << "[PERF] " << test_name << std::endl;
std::cout << " 标量版本: " << std::fixed << std::setprecision(3) << scalar_time << "ms" << std::endl;
std::cout << " SIMD版本: " << std::fixed << std::setprecision(3) << simd_time << "ms" << std::endl;
std::cout << " 加速比: " << std::fixed << std::setprecision(2) << speedup << "x" << std::endl;
}
};
// 音频处理函数测试类
class AudioProcessingTest : public ::testing::Test {
protected:
void SetUp() override {
// 初始化测试环境
audio_processing_registry::register_all_functions();
}
void TearDown() override {
// 清理测试环境
}
// 全局实例
AudioDataGenerator data_gen;
PerformanceTester perf_tester;
};
/**
* ========================================
* 基础功能测试
* ========================================
*/
// 测试 simd_audio_processing_registry 注册功能
TEST_F(AudioProcessingTest, RegistryRegistration) {
// 打印已注册的函数以供调试
audio_processing_registry::print_available_functions();
// 验证关键函数已注册
auto& dispatcher = simd_func_dispatcher::instance();
EXPECT_NO_THROW({
dispatcher.get_function<void(const float*, const float*, float*, size_t)>("mix_audio");
}) << "函数 mix_audio 未正确注册";
EXPECT_NO_THROW({
dispatcher.get_function<void(const float*, float*, float, size_t)>("apply_gain");
}) << "函数 apply_gain 未正确注册";
EXPECT_NO_THROW({
dispatcher.get_function<float(const float*, size_t)>("calculate_rms");
}) << "函数 calculate_rms 未正确注册";
EXPECT_NO_THROW({
dispatcher.get_function<float(const float*, size_t)>("calculate_peak");
}) << "函数 calculate_peak 未正确注册";
EXPECT_NO_THROW({
dispatcher.get_function<void(const float*, float*, float, size_t)>("normalize_audio");
}) << "函数 normalize_audio 未正确注册";
EXPECT_NO_THROW({
dispatcher.get_function<void(const float*, float*, size_t)>("stereo_to_mono");
}) << "函数 stereo_to_mono 未正确注册";
}
// 测试 mix_audio 函数
TEST_F(AudioProcessingTest, MixAudioBasic) {
const size_t num_samples = 16;
auto src1 = data_gen.generate_sine_wave(num_samples, 440.0f);
auto src2 = data_gen.generate_sine_wave(num_samples, 880.0f);
aligned_audio_buffer result(num_samples);
aligned_audio_buffer expected(num_samples);
// 计算期望结果
for (size_t i = 0; i < num_samples; ++i) {
expected[i] = src1[i] + src2[i];
}
// 测试标量版本
scalar_audio_processing_func::mix_audio(src1.data(), src2.data(), result.data(), num_samples);
EXPECT_TRUE(arrays_equal(result.data(), expected.data(), num_samples))
<< "混合音频结果与期望不符";
}
// 测试 apply_gain 函数
TEST_F(AudioProcessingTest, ApplyGainBasic) {
const size_t num_samples = 16;
const float gain = 0.5f;
auto src = data_gen.generate_sine_wave(num_samples);
std::vector<float, avx512_aligned_allocator<float>> result(num_samples);
std::vector<float, avx512_aligned_allocator<float>> expected(num_samples);
// 计算期望结果
for (size_t i = 0; i < num_samples; ++i) {
expected[i] = src[i] * gain;
}
// 测试标量版本
scalar_audio_processing_func::apply_gain(src.data(), result.data(), gain, num_samples);
EXPECT_TRUE(arrays_equal(result.data(), expected.data(), num_samples))
<< "增益应用结果与期望不符";
}
// 测试 calculate_rms 函数
TEST_F(AudioProcessingTest, CalculateRmsBasic) {
const size_t num_samples = 1024;
auto src = data_gen.generate_sine_wave(num_samples);
// 计算期望的RMS值
double sum_squares = 0.0;
for (size_t i = 0; i < num_samples; ++i) {
sum_squares += src[i] * src[i];
}
float expected_rms = std::sqrt(sum_squares / num_samples);
// 测试标量版本
float result_rms = scalar_audio_processing_func::calculate_rms(src.data(), num_samples);
EXPECT_TRUE(float_equal(result_rms, expected_rms, RMS_TOLERANCE))
<< "期望 RMS: " << expected_rms << ", 得到: " << result_rms;
}
// 测试 calculate_peak 函数
TEST_F(AudioProcessingTest, CalculatePeakBasic) {
const size_t num_samples = 1024;
auto src = data_gen.generate_boundary_data(num_samples);
// 计算期望的峰值
float expected_peak = 0.0f;
for (size_t i = 0; i < num_samples; ++i) {
expected_peak = std::max(expected_peak, std::abs(src[i]));
}
// 测试标量版本
float result_peak = scalar_audio_processing_func::calculate_peak(src.data(), num_samples);
EXPECT_TRUE(float_equal(result_peak, expected_peak, PEAK_TOLERANCE))
<< "期望峰值: " << expected_peak << ", 得到: " << result_peak;
}
/**
* ========================================
* 新增功能测试
* ========================================
*/
// 测试 normalize_audio 函数
TEST_F(AudioProcessingTest, NormalizeAudioBasic) {
const size_t num_samples = 1024;
const float target_peak = 0.8f;
auto src = data_gen.generate_sine_wave(num_samples, 440.0f, 44100.0f, 2.0f); // 超过1.0的幅度
aligned_audio_buffer result(num_samples);
// 测试标量版本
scalar_audio_processing_func::normalize_audio(src.data(), result.data(), target_peak, num_samples);
// 验证归一化后的峰值
float actual_peak = scalar_audio_processing_func::calculate_peak(result.data(), num_samples);
EXPECT_TRUE(float_equal(actual_peak, target_peak, PEAK_TOLERANCE))
<< "期望峰值: " << target_peak << ", 实际峰值: " << actual_peak;
}
// 测试 stereo_to_mono 函数
TEST_F(AudioProcessingTest, StereoToMonoBasic) {
const size_t num_stereo_samples = 512;
auto stereo_src = data_gen.generate_stereo_test_data(num_stereo_samples);
aligned_audio_buffer mono_result(num_stereo_samples);
aligned_audio_buffer expected_mono(num_stereo_samples);
// 计算期望结果
for (size_t i = 0; i < num_stereo_samples; ++i) {
expected_mono[i] = (stereo_src[i * 2] + stereo_src[i * 2 + 1]) * 0.5f;
}
// 测试标量版本
scalar_audio_processing_func::stereo_to_mono(stereo_src.data(), mono_result.data(), num_stereo_samples);
EXPECT_TRUE(arrays_equal(mono_result.data(), expected_mono.data(), num_stereo_samples))
<< "立体声转单声道果与期望不符";
}
// 测试 limit_audio 函数
TEST_F(AudioProcessingTest, LimitAudioBasic) {
const size_t num_samples = 1024;
const float threshold = 0.5f;
auto src = data_gen.generate_sine_wave(num_samples, 440.0f, 44100.0f, 1.0f);
aligned_audio_buffer result(num_samples);
float limiter_state = 1.0f;
// 测试标量版本
scalar_audio_processing_func::limit_audio(src.data(), result.data(), threshold, &limiter_state, 44100.f,
num_samples);
// 验证没有样本超过阈值
bool all_samples_limited = true;
size_t violation_index = 0;
float violation_value = 0.0f;
for (size_t i = 0; i < num_samples; ++i) {
if (std::abs(result[i]) > threshold + FLOAT_TOLERANCE) {
all_samples_limited = false;
violation_index = i;
violation_value = result[i];
break;
}
}
EXPECT_TRUE(all_samples_limited)
<< "样本 " << violation_index << " 超过阈值: " << violation_value;
}
// 测试 fade_audio 函数
TEST_F(AudioProcessingTest, FadeAudioBasic) {
const size_t num_samples = 1024;
const size_t fade_in_samples = 100;
const size_t fade_out_samples = 100;
auto src = data_gen.generate_dc(num_samples, 1.0f);
aligned_audio_buffer result(num_samples);
// 测试标量版本
scalar_audio_processing_func::fade_audio(src.data(), result.data(), fade_in_samples, fade_out_samples, num_samples);
// 验证淡入淡出效果
// 检查淡入部分
EXPECT_FLOAT_EQ(result[0], 0.0f)
<< "淡入开始应为0实际为: " << result[0];
// 检查中间部分应该是1.0
EXPECT_FLOAT_EQ(result[num_samples / 2], 1.0f)
<< "中间部分应保持原始值1.0,实际为: " << result[num_samples / 2];
// 检查淡出部分
EXPECT_TRUE(float_equal(result[num_samples - 1], 0.0f, FLOAT_TOLERANCE))
<< "淡出结束应为0实际为: " << result[num_samples - 1];
}
// 测试 simple_eq 函数
TEST_F(AudioProcessingTest, SimpleEqBasic) {
const size_t num_samples = 1024;
const float low_gain = 1.2f;
const float mid_gain = 1.0f;
const float high_gain = 0.8f;
auto src = data_gen.generate_white_noise(num_samples, 0.5f);
aligned_audio_buffer result(num_samples);
aligned_audio_buffer eq_state(2, 0.0f); // 低通和高通滤波器状态
// 测试标量版本
scalar_audio_processing_func::simple_eq(src.data(), result.data(), low_gain, mid_gain, high_gain, eq_state.data(),
num_samples);
// 基本验证:结果不应该全为零(除非输入全为零)
bool has_nonzero = false;
for (size_t i = 0; i < num_samples; ++i) {
if (result[i] != 0.0f) {
has_nonzero = true;
break;
}
}
EXPECT_TRUE(has_nonzero)
<< "EQ处理后的结果全为零可能存在处理错误";
}
/**
* ========================================
* 边界条件测试
* ========================================
*/
// 测试零长度输入
TEST_F(AudioProcessingTest, ZeroLengthInput) {
const size_t num_samples = 0;
aligned_audio_buffer dummy(1, 0.0f);
aligned_audio_buffer result(1, 0.0f);
float state = 1.0f;
// 这些函数应该能安全处理零长度输入
EXPECT_NO_THROW({
scalar_audio_processing_func::mix_audio(dummy.data(), dummy.data(), result.data(), num_samples);
scalar_audio_processing_func::apply_gain(dummy.data(), result.data(), 1.0f, num_samples);
scalar_audio_processing_func::normalize_audio(dummy.data(), result.data(), 1.0f, num_samples);
scalar_audio_processing_func::stereo_to_mono(dummy.data(), result.data(), num_samples);
scalar_audio_processing_func::limit_audio(dummy.data(), result.data(), 1.0f, &state, 44100.f, num_samples);
scalar_audio_processing_func::fade_audio(dummy.data(), result.data(), 0, 0, num_samples);
scalar_audio_processing_func::simple_eq(dummy.data(), result.data(), 1.0f, 1.0f, 1.0f, &state, num_samples);
});
}
// 测试单样本输入
TEST_F(AudioProcessingTest, SingleSampleInput) {
const size_t num_samples = 1;
aligned_audio_buffer src1{0.5f};
aligned_audio_buffer src2{0.3f};
aligned_audio_buffer result(1);
float state = 1.0f;
// 测试混合
scalar_audio_processing_func::mix_audio(src1.data(), src2.data(), result.data(), num_samples);
EXPECT_TRUE(float_equal(result[0], 0.8f))
<< "混合单样本: 期望0.8,实际" << result[0];
// 测试增益
scalar_audio_processing_func::apply_gain(src1.data(), result.data(), 2.0f, num_samples);
EXPECT_TRUE(float_equal(result[0], 1.0f))
<< "应用增益: 期望1.0,实际" << result[0];
// 测试RMS
float rms = scalar_audio_processing_func::calculate_rms(src1.data(), num_samples);
EXPECT_TRUE(float_equal(rms, 0.5f))
<< "单样本RMS: 期望0.5,实际" << rms;
// 测试峰值
float peak = scalar_audio_processing_func::calculate_peak(src1.data(), num_samples);
EXPECT_TRUE(float_equal(peak, 0.5f))
<< "单样本峰值: 期望0.5,实际" << peak;
}
// 测试极值处理
TEST_F(AudioProcessingTest, ExtremeValues) {
const size_t num_samples = 8;
aligned_audio_buffer extreme_values = {
0.0f,
1.0f,
-1.0f,
std::numeric_limits<float>::max(),
-std::numeric_limits<float>::max(),
std::numeric_limits<float>::min(),
std::numeric_limits<float>::epsilon(),
-std::numeric_limits<float>::epsilon()
};
aligned_audio_buffer result(num_samples);
// 测试峰值计算对极值的处理
float peak = scalar_audio_processing_func::calculate_peak(extreme_values.data(), num_samples);
EXPECT_EQ(peak, std::numeric_limits<float>::max())
<< "极值峰值检测失败,期望" << std::numeric_limits<float>::max() << ",实际" << peak;
// 测试增益对极值的处理
scalar_audio_processing_func::apply_gain(extreme_values.data(), result.data(), 0.5f, num_samples);
bool all_finite = true;
size_t nan_inf_index = 0;
for (size_t i = 0; i < num_samples; ++i) {
if (std::isnan(result[i]) || std::isinf(result[i])) {
all_finite = false;
nan_inf_index = i;
break;
}
}
EXPECT_TRUE(all_finite)
<< "增益处理后在位置" << nan_inf_index << "存在NaN或Inf";
}
/**
* ========================================
* 一致性测试(标量 vs SIMD
* ========================================
*/
#if ALICHO_PLATFORM_X86
// 测试x86 SIMD版本与标量版的一致性
TEST_F(AudioProcessingTest, X86SimdConsistency) {
const size_t num_samples = 1024;
auto src1 = data_gen.generate_sine_wave(num_samples, 440.0f);
auto src2 = data_gen.generate_sine_wave(num_samples, 880.0f);
auto stereo_src = data_gen.generate_stereo_test_data(num_samples);
aligned_audio_buffer scalar_result(num_samples);
aligned_audio_buffer sse_result(num_samples);
aligned_audio_buffer avx_result(num_samples);
std::vector<float, aligned_allocator<float, ALIGNMENT_AVX512>> avx512_result(num_samples);
// 测试 mix_audio 一致性
scalar_audio_processing_func::mix_audio(src1.data(), src2.data(), scalar_result.data(), num_samples);
x86_simd_audio_processing_func::mix_audio_sse(src1.data(), src2.data(), sse_result.data(), num_samples);
x86_simd_audio_processing_func::mix_audio_avx(src1.data(), src2.data(), avx_result.data(), num_samples);
x86_simd_audio_processing_func::mix_audio_avx512(src1.data(), src2.data(), avx512_result.data(), num_samples);
EXPECT_TRUE(arrays_equal(scalar_result.data(), sse_result.data(), num_samples))
<< "mix_audio SSE版本与标量版本不一致";
EXPECT_TRUE(arrays_equal(scalar_result.data(), avx_result.data(), num_samples))
<< "mix_audio AVX版本与标量版本不一致";
EXPECT_TRUE(arrays_equal(scalar_result.data(), avx512_result.data(), num_samples))
<< "mix_audio AVX512版本与标量版本不一致";
// 测试 apply_gain 一致性
const float gain = 0.75f;
scalar_audio_processing_func::apply_gain(src1.data(), scalar_result.data(), gain, num_samples);
x86_simd_audio_processing_func::apply_gain_sse(src1.data(), sse_result.data(), gain, num_samples);
x86_simd_audio_processing_func::apply_gain_avx(src1.data(), avx_result.data(), gain, num_samples);
x86_simd_audio_processing_func::apply_gain_avx512(src1.data(), avx512_result.data(), gain, num_samples);
EXPECT_TRUE(arrays_equal(scalar_result.data(), sse_result.data(), num_samples))
<< "apply_gain SSE版本与标量版本不一致";
EXPECT_TRUE(arrays_equal(scalar_result.data(), avx_result.data(), num_samples))
<< "apply_gain AVX版本与标量版本不一致";
EXPECT_TRUE(arrays_equal(scalar_result.data(), avx512_result.data(), num_samples))
<< "apply_gain AVX512版本与标量版本不一致";
// 测试 calculate_rms 一致性
float scalar_rms = scalar_audio_processing_func::calculate_rms(src1.data(), num_samples);
float sse_rms = x86_simd_audio_processing_func::calculate_rms_sse(src1.data(), num_samples);
float avx_rms = x86_simd_audio_processing_func::calculate_rms_avx(src1.data(), num_samples);
float avx512_rms = x86_simd_audio_processing_func::calculate_rms_avx512(src1.data(), num_samples);
EXPECT_TRUE(float_equal(scalar_rms, sse_rms, RMS_TOLERANCE))
<< "calculate_rms SSE版本与标量版本不一致: " << scalar_rms << " vs " << sse_rms;
EXPECT_TRUE(float_equal(scalar_rms, avx_rms, RMS_TOLERANCE))
<< "calculate_rms AVX版本与标量版本不一致: " << scalar_rms << " vs " << avx_rms;
EXPECT_TRUE(float_equal(scalar_rms, avx512_rms, RMS_TOLERANCE))
<< "calculate_rms AVX512版本与标量版本不一致: " << scalar_rms << " vs " << avx512_rms;
// 测试 calculate_peak 一致性
float scalar_peak = scalar_audio_processing_func::calculate_peak(src1.data(), num_samples);
float sse_peak = x86_simd_audio_processing_func::calculate_peak_sse(src1.data(), num_samples);
float avx_peak = x86_simd_audio_processing_func::calculate_peak_avx(src1.data(), num_samples);
float avx512_peak = x86_simd_audio_processing_func::calculate_peak_avx512(src1.data(), num_samples);
EXPECT_TRUE(float_equal(scalar_peak, sse_peak, PEAK_TOLERANCE))
<< "calculate_peak SSE版本与标量版本不一致: " << scalar_peak << " vs " << sse_peak;
EXPECT_TRUE(float_equal(scalar_peak, avx_peak, PEAK_TOLERANCE))
<< "calculate_peak AVX版本与标量版本不一致: " << scalar_peak << " vs " << avx_peak;
EXPECT_TRUE(float_equal(scalar_peak, avx512_peak, PEAK_TOLERANCE))
<< "calculate_peak AVX512版本与标量版本不一致: " << scalar_peak << " vs " << avx512_peak;
}
#endif // ALICHO_PLATFORM_X86
#if ALICHO_PLATFORM_ARM
// 测试ARM NEON版本与标量版的一致性
TEST_F(AudioProcessingTest, ArmSimdConsistency) {
const size_t num_samples = 1024;
auto src1 = data_gen.generate_sine_wave(num_samples, 440.0f);
auto src2 = data_gen.generate_sine_wave(num_samples, 880.0f);
aligned_audio_buffer scalar_result(num_samples);
aligned_audio_buffer neon_result(num_samples);
// 测试 mix_audio 一致性
scalar_audio_processing_func::mix_audio(src1.data(), src2.data(), scalar_result.data(), num_samples);
arm_simd_audio_processing_func::mix_audio_neon(src1.data(), src2.data(), neon_result.data(), num_samples);
EXPECT_TRUE(arrays_equal(scalar_result.data(), neon_result.data(), num_samples))
<< "mix_audio NEON版本与标量版不一致";
// 测试 apply_gain 一致性
const float gain = 0.75f;
scalar_audio_processing_func::apply_gain(src1.data(), scalar_result.data(), gain, num_samples);
arm_simd_audio_processing_func::apply_gain_neon(src1.data(), neon_result.data(), gain, num_samples);
EXPECT_TRUE(arrays_equal(scalar_result.data(), neon_result.data(), num_samples))
<< "apply_gain NEON版本与标量版不一致";
// 测试 calculate_rms 一致性
float scalar_rms = scalar_audio_processing_func::calculate_rms(src1.data(), num_samples);
float neon_rms = arm_simd_audio_processing_func::calculate_rms_neon(src1.data(), num_samples);
EXPECT_TRUE(float_equal(scalar_rms, neon_rms, RMS_TOLERANCE))
<< "calculate_rms NEON版本与标量版不一致: " << scalar_rms << " vs " << neon_rms;
// 测试 calculate_peak 一致性
float scalar_peak = scalar_audio_processing_func::calculate_peak(src1.data(), num_samples);
float neon_peak = arm_simd_audio_processing_func::calculate_peak_neon(src1.data(), num_samples);
EXPECT_TRUE(float_equal(scalar_peak, neon_peak, PEAK_TOLERANCE))
<< "calculate_peak NEON版本与标量版不一致: " << scalar_peak << " vs " << neon_peak;
}
#endif // ALICHO_PLATFORM_ARM
/**
* ========================================
* 性能测试
* ========================================
*/
// 性能测试运行为 TEST_F 测试,但不使用 EXPECT/ASSERT
TEST_F(AudioProcessingTest, PerformanceTests) {
std::cout << "\n=== 性能测试 ===" << std::endl;
// 生成大量测试数据
auto src1 = data_gen.generate_sine_wave(PERF_TEST_SIZE, 440.0f);
auto src2 = data_gen.generate_sine_wave(PERF_TEST_SIZE, 880.0f);
aligned_audio_buffer result(PERF_TEST_SIZE);
// 性能测试mix_audio
{
double scalar_time = perf_tester.measure_execution_time([&]() {
scalar_audio_processing_func::mix_audio(src1.data(), src2.data(), result.data(), PERF_TEST_SIZE);
});
#if ALICHO_PLATFORM_X86
double sse_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::mix_audio_sse(src1.data(), src2.data(), result.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("mix_audio (SSE vs Scalar)", scalar_time, sse_time);
double avx_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::mix_audio_avx(src1.data(), src2.data(), result.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("mix_audio (AVX vs Scalar)", scalar_time, avx_time);
double avx512_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::mix_audio_avx512(src1.data(), src2.data(), result.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("mix_audio (AVX512 vs Scalar)", scalar_time, avx512_time);
#endif
#if ALICHO_PLATFORM_ARM
double neon_time = perf_tester.measure_execution_time([&]() {
arm_simd_audio_processing_func::mix_audio_neon(src1.data(), src2.data(), result.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("mix_audio (NEON vs Scalar)", scalar_time, neon_time);
#endif
}
// 性能测试apply_gain
{
const float gain = 0.5f;
double scalar_time = perf_tester.measure_execution_time([&]() {
scalar_audio_processing_func::apply_gain(src1.data(), result.data(), gain, PERF_TEST_SIZE);
});
#if ALICHO_PLATFORM_X86
double sse_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::apply_gain_sse(src1.data(), result.data(), gain, PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("apply_gain (SSE vs Scalar)", scalar_time, sse_time);
double avx_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::apply_gain_avx(src1.data(), result.data(), gain, PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("apply_gain (AVX vs Scalar)", scalar_time, avx_time);
double avx512_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::apply_gain_avx512(src1.data(), result.data(), gain, PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("apply_gain (AVX512 vs Scalar)", scalar_time, avx512_time);
#endif
#if ALICHO_PLATFORM_ARM
double neon_time = perf_tester.measure_execution_time([&]() {
arm_simd_audio_processing_func::apply_gain_neon(src1.data(), result.data(), gain, PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("apply_gain (NEON vs Scalar)", scalar_time, neon_time);
#endif
}
// 性能测试calculate_rms
{
double scalar_time = perf_tester.measure_execution_time([&]() {
scalar_audio_processing_func::calculate_rms(src1.data(), PERF_TEST_SIZE);
});
#if ALICHO_PLATFORM_X86
double sse_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::calculate_rms_sse(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_rms (SSE vs Scalar)", scalar_time, sse_time);
double avx_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::calculate_rms_avx(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_rms (AVX vs Scalar)", scalar_time, avx_time);
double avx512_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::calculate_rms_avx512(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_rms (AVX512 vs Scalar)", scalar_time, avx512_time);
#endif
#if ALICHO_PLATFORM_ARM
double neon_time = perf_tester.measure_execution_time([&]() {
arm_simd_audio_processing_func::calculate_rms_neon(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_rms (NEON vs Scalar)", scalar_time, neon_time);
#endif
}
// 性能测试calculate_peak
{
double scalar_time = perf_tester.measure_execution_time([&]() {
scalar_audio_processing_func::calculate_peak(src1.data(), PERF_TEST_SIZE);
});
#if ALICHO_PLATFORM_X86
double sse_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::calculate_peak_sse(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_peak (SSE vs Scalar)", scalar_time, sse_time);
double avx_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::calculate_peak_avx(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_peak (AVX vs Scalar)", scalar_time, avx_time);
double avx512_time = perf_tester.measure_execution_time([&]() {
x86_simd_audio_processing_func::calculate_peak_avx512(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_peak (AVX512 vs Scalar)", scalar_time, avx512_time);
#endif
#if ALICHO_PLATFORM_ARM
double neon_time = perf_tester.measure_execution_time([&]() {
arm_simd_audio_processing_func::calculate_peak_neon(src1.data(), PERF_TEST_SIZE);
});
perf_tester.print_performance_comparison("calculate_peak (NEON vs Scalar)", scalar_time, neon_time);
#endif
}
}