init
This commit is contained in:
137
lib_audio_dsp/test/utils/CMakeLists.txt
Normal file
137
lib_audio_dsp/test/utils/CMakeLists.txt
Normal file
@@ -0,0 +1,137 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
include($ENV{XMOS_CMAKE_PATH}/xcommon.cmake)
|
||||
project(compressor_ratio)
|
||||
|
||||
set(APP_HW_TARGET XCORE-AI-EXPLORER)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/compressor_ratio.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
|
||||
|
||||
project(expander_ratio)
|
||||
|
||||
set(APP_HW_TARGET XCORE-AI-EXPLORER)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/expander_ratio.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
|
||||
|
||||
project(rms_threshold)
|
||||
|
||||
set(APP_HW_TARGET XCORE-AI-EXPLORER)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/rms_threshold.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
|
||||
|
||||
project(peak_threshold)
|
||||
|
||||
set(APP_HW_TARGET XCORE-AI-EXPLORER)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/peak_threshold.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
|
||||
|
||||
project(calc_alpha)
|
||||
|
||||
set(APP_HW_TARGET XCORE-AI-EXPLORER)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/calc_alpha.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
|
||||
project(db_gain)
|
||||
|
||||
set(APP_HW_TARGET XCORE-AI-EXPLORER)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/db_gain.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
|
||||
|
||||
project(time_samples)
|
||||
|
||||
set(APP_COMPILER_FLAGS
|
||||
-O3
|
||||
-g
|
||||
-report
|
||||
-Wall
|
||||
-Werror
|
||||
-fxscope)
|
||||
|
||||
set(APP_DEPENDENT_MODULES lib_audio_dsp)
|
||||
set(APP_C_SRCS src/time_samples.c)
|
||||
|
||||
set(XMOS_SANDBOX_DIR ${CMAKE_SOURCE_DIR}/../../..)
|
||||
|
||||
XMOS_REGISTER_APP()
|
||||
44
lib_audio_dsp/test/utils/src/calc_alpha.c
Normal file
44
lib_audio_dsp/test/utils/src/calc_alpha.c
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/helpers.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / sizeof(float);
|
||||
printf("inlen %d", in_len);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp = 0;
|
||||
int32_t samp_out = 0;
|
||||
fread(&samp, sizeof(float), 1, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = calc_alpha(48000.0, samp);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(int32_t), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
42
lib_audio_dsp/test/utils/src/compressor_ratio.c
Normal file
42
lib_audio_dsp/test/utils/src/compressor_ratio.c
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/helpers.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / sizeof(float);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp = 0, samp_out = 0;
|
||||
fread(&samp, sizeof(float), 1, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = rms_compressor_slope_from_ratio(samp);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(float), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
43
lib_audio_dsp/test/utils/src/db_gain.c
Normal file
43
lib_audio_dsp/test/utils/src/db_gain.c
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/signal_chain.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / sizeof(float);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp = 0;
|
||||
int32_t samp_out = 0;
|
||||
fread(&samp, sizeof(float), 1, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = adsp_dB_to_gain(samp);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(int32_t), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
42
lib_audio_dsp/test/utils/src/expander_ratio.c
Normal file
42
lib_audio_dsp/test/utils/src/expander_ratio.c
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/helpers.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / sizeof(float);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp = 0, samp_out = 0;
|
||||
fread(&samp, sizeof(float), 1, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = peak_expander_slope_from_ratio(samp);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(float), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
43
lib_audio_dsp/test/utils/src/peak_threshold.c
Normal file
43
lib_audio_dsp/test/utils/src/peak_threshold.c
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/helpers.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / sizeof(float);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp = 0;
|
||||
int32_t samp_out = 0;
|
||||
fread(&samp, sizeof(float), 1, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = calculate_peak_threshold(samp);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(int32_t), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
43
lib_audio_dsp/test/utils/src/rms_threshold.c
Normal file
43
lib_audio_dsp/test/utils/src/rms_threshold.c
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/helpers.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / sizeof(float);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp = 0;
|
||||
int32_t samp_out = 0;
|
||||
fread(&samp, sizeof(float), 1, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = calculate_rms_threshold(samp);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(int32_t), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
44
lib_audio_dsp/test/utils/src/time_samples.c
Normal file
44
lib_audio_dsp/test/utils/src/time_samples.c
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright 2024-2025 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "control/signal_chain.h"
|
||||
|
||||
FILE * _fopen(char * fname, char* mode) {
|
||||
FILE * fp = fopen(fname, mode);
|
||||
if (fp == NULL)
|
||||
{
|
||||
printf("Error opening a file\n");
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE * in = _fopen("test_vector.bin", "rb");
|
||||
FILE * out = _fopen("out_vector.bin", "wb");
|
||||
|
||||
fseek(in, 0, SEEK_END);
|
||||
int in_len = ftell(in) / (2.0f*sizeof(float));
|
||||
printf("inlen %d", in_len);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
for (unsigned i = 0; i < in_len; i++)
|
||||
{
|
||||
float samp[2] = {0};
|
||||
int32_t samp_out = 0;
|
||||
fread(&samp, sizeof(float), 2, in);
|
||||
//printf("%ld ", samp);
|
||||
samp_out = time_to_samples(48000.0, samp[0], (time_units_t)samp[1]);
|
||||
//printf("%ld ", samp_out);
|
||||
fwrite(&samp_out, sizeof(int32_t), 1, out);
|
||||
}
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
179
lib_audio_dsp/test/utils/test_control_converters_c.py
Normal file
179
lib_audio_dsp/test/utils/test_control_converters_c.py
Normal file
@@ -0,0 +1,179 @@
|
||||
# Copyright 2024-2025 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import itertools
|
||||
from enum import IntEnum
|
||||
|
||||
import audio_dsp.dsp.utils as utils
|
||||
import audio_dsp.dsp.drc.drc_utils as drcu
|
||||
import audio_dsp.dsp.signal_chain as sc
|
||||
from audio_dsp.dsp.generic import Q_SIG, HEADROOM_DB
|
||||
|
||||
bin_dir = Path(__file__).parent / "bin"
|
||||
gen_dir = Path(__file__).parent / "autogen"
|
||||
|
||||
fs=48000
|
||||
|
||||
def flt_to_bin_file(sig_fl, out_dir=bin_dir):
|
||||
sig_fl32 = np.array(sig_fl).astype(np.float32)
|
||||
name = "test_vector"
|
||||
sig_fl32.tofile(out_dir / f"{name}.bin")
|
||||
|
||||
return sig_fl
|
||||
|
||||
|
||||
def get_c_wav(dir_name, conv_name, verbose=False, sim = True, dtype=np.float32):
|
||||
app = "xsim" if sim else "xrun --io"
|
||||
run_cmd = app + " " + str(bin_dir / f"{conv_name}.xe")
|
||||
stdout = subprocess.check_output(run_cmd, cwd = dir_name, shell = True)
|
||||
if verbose: print("run msg:\n", stdout.decode())
|
||||
|
||||
sig_bin = dir_name / "out_vector.bin"
|
||||
assert sig_bin.is_file(), f"Could not find output bin {sig_bin}"
|
||||
sig_int = np.fromfile(sig_bin, dtype=dtype)
|
||||
|
||||
return sig_int
|
||||
|
||||
|
||||
def test_compressor_ratio_helper():
|
||||
test_dir = bin_dir / "compressor_ratio"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
ratios = [0, 0.9, 1, 5, 10000, 999999999999999999999999999]
|
||||
flt_to_bin_file(ratios, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "compressor_ratio")
|
||||
|
||||
slopes_python = np.zeros_like(ratios, dtype=np.float32)
|
||||
|
||||
for n in range(len(ratios)):
|
||||
slope, slopes_python[n] = drcu.rms_compressor_slope_from_ratio(ratios[n])
|
||||
|
||||
assert np.all(out_c == slopes_python)
|
||||
|
||||
|
||||
def test_expander_ratio_helper():
|
||||
test_dir = bin_dir / "expander_ratio"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
ratios = [0, 0.9, 1, 5, 10000, 999999999999999999999999999]
|
||||
flt_to_bin_file(ratios, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "expander_ratio")
|
||||
|
||||
slopes_python = np.zeros_like(ratios, dtype=np.float32)
|
||||
|
||||
for n in range(len(ratios)):
|
||||
slope, slopes_python[n] = drcu.peak_expander_slope_from_ratio(ratios[n])
|
||||
|
||||
assert np.all(out_c == slopes_python)
|
||||
|
||||
|
||||
def test_rms_threshold():
|
||||
test_dir = bin_dir / "rms_threshold"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
threshold_dbs = [-2000, 0, HEADROOM_DB/2 + 1]
|
||||
flt_to_bin_file(threshold_dbs, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "rms_threshold", dtype=np.int32)
|
||||
|
||||
thresh_python = np.zeros_like(threshold_dbs, dtype=np.int32)
|
||||
|
||||
for n in range(len(threshold_dbs)):
|
||||
_, thresh_python[n] = drcu.calculate_rms_threshold(threshold_dbs[n], Q_SIG)
|
||||
|
||||
np.testing.assert_allclose(out_c, thresh_python, rtol=2**-21, atol=1)
|
||||
|
||||
|
||||
|
||||
def test_peak_threshold():
|
||||
|
||||
test_dir = bin_dir / "peak_threshold"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
# threshold_dbs = [-2000, -0, HEADROOM_DB + 1]
|
||||
threshold_dbs = utils.db(np.logspace(np.log10(0.001), np.log10(8), 100))
|
||||
flt_to_bin_file(threshold_dbs, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "peak_threshold", dtype=np.int32)
|
||||
|
||||
thresh_python = np.zeros_like(threshold_dbs, dtype=np.int32)
|
||||
|
||||
for n in range(len(threshold_dbs)):
|
||||
_, thresh_python[n] = drcu.calculate_threshold(threshold_dbs[n], Q_SIG, power=False)
|
||||
|
||||
np.testing.assert_allclose(out_c, thresh_python, rtol=2**-21, atol=1)
|
||||
|
||||
|
||||
def test_calc_alpha():
|
||||
|
||||
test_dir = bin_dir / "calc_alpha"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
attack_times = [-1, 0, 1/48000, 3/48000, 1, 1000, (4/48000)*(2**31)]
|
||||
flt_to_bin_file(attack_times, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "calc_alpha", dtype=np.int32)
|
||||
|
||||
alphas_python = np.zeros_like(attack_times, dtype=np.int32)
|
||||
for n in range(len(attack_times)):
|
||||
alpha, alphas_python[n] = drcu.alpha_from_time(attack_times[n], 48000)
|
||||
|
||||
# not exact due to float32 implementation differences
|
||||
np.testing.assert_allclose(out_c, alphas_python, rtol=2**-24, atol=0)
|
||||
|
||||
|
||||
def test_db_gain():
|
||||
|
||||
test_dir = bin_dir / "db_gain"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
gain_dbs = [-np.inf, -2000, 0, 25]
|
||||
flt_to_bin_file(gain_dbs, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "db_gain", dtype=np.int32)
|
||||
|
||||
gain_python = np.zeros_like(gain_dbs, dtype=np.int32)
|
||||
|
||||
for n in range(len(gain_dbs)):
|
||||
gain, gain_python[n] = sc.db_to_qgain(gain_dbs[n])
|
||||
|
||||
np.testing.assert_allclose(out_c, gain_python, rtol=2**-23, atol=0)
|
||||
|
||||
|
||||
class time_units_type(IntEnum):
|
||||
samples = 0
|
||||
ms = 1
|
||||
s = 2
|
||||
|
||||
|
||||
def test_time_samples():
|
||||
|
||||
test_dir = bin_dir / "time_samples"
|
||||
test_dir.mkdir(exist_ok = True, parents = True)
|
||||
|
||||
times = [10, 128, 1.7, 0.94, 2, -2]
|
||||
units = [time_units_type["samples"], time_units_type["s"], time_units_type["ms"]]
|
||||
|
||||
input_params = list(itertools.product(times, units))
|
||||
|
||||
flt_to_bin_file(input_params, test_dir)
|
||||
|
||||
out_c = get_c_wav(test_dir, "time_samples", dtype=np.int32)
|
||||
|
||||
delay_py = np.zeros(len(input_params), dtype=np.int32)
|
||||
for n in range(len(input_params)):
|
||||
delay_py[n] = utils.time_to_samples(48000, input_params[n][0], input_params[n][1].name)
|
||||
|
||||
# not exact due to float32 implementation differences
|
||||
np.testing.assert_allclose(out_c, delay_py, rtol=2**-24, atol=0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
bin_dir.mkdir(exist_ok=True, parents=True)
|
||||
gen_dir.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
test_db_gain()
|
||||
105
lib_audio_dsp/test/utils/test_control_converters_python.py
Normal file
105
lib_audio_dsp/test/utils/test_control_converters_python.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# Copyright 2024-2025 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import pytest
|
||||
|
||||
import audio_dsp.dsp.utils as utils
|
||||
import audio_dsp.dsp.drc.drc_utils as drcu
|
||||
import audio_dsp.dsp.signal_chain as sc
|
||||
from audio_dsp.dsp.generic import Q_SIG, HEADROOM_DB
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ratio, warning", [(0, UserWarning),
|
||||
(0.9, UserWarning),
|
||||
(1, None),
|
||||
(5, None),
|
||||
(10000, None),
|
||||
(999999999999999999999999999, None)])
|
||||
def test_compressor_ratio_helper(ratio, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
slope, slope_f32 = drcu.rms_compressor_slope_from_ratio(ratio)
|
||||
else:
|
||||
slope, slope_f32 = drcu.rms_compressor_slope_from_ratio(ratio)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ratio, warning", [(0, UserWarning),
|
||||
(0.9, UserWarning),
|
||||
(1, None),
|
||||
(5, None),
|
||||
(10000, None),
|
||||
(999999999999999999999999999, None)])
|
||||
def test_expander_ratio_helper(ratio, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
slope, slope_f32 = drcu.peak_expander_slope_from_ratio(ratio)
|
||||
else:
|
||||
slope, slope_f32 = drcu.peak_expander_slope_from_ratio(ratio)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("threshold_db, warning", [(-2000, None),
|
||||
(0, None),
|
||||
(HEADROOM_DB/2 + 1, UserWarning)])
|
||||
def test_rms_threshold(threshold_db, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=True)
|
||||
else:
|
||||
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("threshold_db, warning", [(-2000, None),
|
||||
(0, None),
|
||||
(HEADROOM_DB + 1, UserWarning)])
|
||||
def test_peak_threshold(threshold_db, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=False)
|
||||
else:
|
||||
thresh, thresh_int = drcu.calculate_threshold(threshold_db, Q_SIG, power=False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("time, warning", [(-1, UserWarning),
|
||||
(0, UserWarning),
|
||||
(1/48000, UserWarning),
|
||||
(3/48000, None),
|
||||
(1, None),
|
||||
(1000, None),
|
||||
((4/48000)*(2**31), UserWarning),
|
||||
])
|
||||
def test_calc_alpha(time, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
alpha, alpha_int = drcu.alpha_from_time(time, 48000)
|
||||
else:
|
||||
alpha, alpha_int = drcu.alpha_from_time(time, 48000)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("gain_db, warning", [(-2000, None),
|
||||
(0, None),
|
||||
(25, UserWarning)])
|
||||
def test_db_gain(gain_db, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
gain, gain_int = sc.db_to_qgain(gain_db)
|
||||
else:
|
||||
gain, gain_int = sc.db_to_qgain(gain_db)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("time, units, warning", [[10, "samples", None],
|
||||
[128, "samples", None],
|
||||
[1.7, "ms", None],
|
||||
[0.94, "s", None],
|
||||
[2, "s", None],
|
||||
[-2, "s", UserWarning],
|
||||
[2, "seconds", UserWarning]
|
||||
])
|
||||
def test_time_to_samples(time, units, warning):
|
||||
if warning:
|
||||
with pytest.warns(warning):
|
||||
utils.time_to_samples(48000, time, units)
|
||||
else:
|
||||
utils.time_to_samples(48000, time, units)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_peak_threshold(25)
|
||||
116
lib_audio_dsp/test/utils/test_utils_python.py
Normal file
116
lib_audio_dsp/test/utils/test_utils_python.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# Copyright 2024-2025 XMOS LIMITED.
|
||||
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
import pytest
|
||||
import numpy as np
|
||||
|
||||
import audio_dsp.dsp.utils as utils
|
||||
import audio_dsp.dsp.types as types
|
||||
|
||||
# seed RNG to avoid collection failures
|
||||
np.random.seed(0)
|
||||
|
||||
@pytest.mark.parametrize('x', (2*np.random.rand(100)-1)*2**64)
|
||||
def test_float_s32_float(x):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
x2 = float(x_s32)
|
||||
|
||||
tol = 2**x_s32.exp
|
||||
assert np.isclose(x, x2, rtol=2**-31, atol=tol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('x, Q', np.stack(((2*np.random.rand(100)-1),
|
||||
np.random.randint(0, 30, size=100)),
|
||||
axis=-1))
|
||||
def test_float_s32_float_Q(x, Q):
|
||||
x_s32 = types.float_s32(float(x), Q_sig=Q)
|
||||
x2 = float(x_s32)
|
||||
|
||||
tol = 2**-Q
|
||||
assert np.isclose(x, x2, rtol=2**-31, atol=tol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('x', (2*np.random.rand(100)-1)*2**64)
|
||||
def test_float_s32_abs(x):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
x2 = float(abs(x_s32))
|
||||
|
||||
tol = 2**x_s32.exp
|
||||
assert np.isclose(abs(x), x2, rtol=2**-31, atol=tol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
|
||||
def test_float_s32_mult(x, y):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
y_s32 = types.float_s32(float(y))
|
||||
|
||||
xy_s32 = x_s32*y_s32
|
||||
xy = float(xy_s32)
|
||||
|
||||
tol = 2**xy_s32.exp
|
||||
assert np.isclose(x*y, xy, rtol=2**-29, atol=tol)
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
|
||||
def test_float_s32_div(x, y):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
y_s32 = types.float_s32(float(y))
|
||||
|
||||
xy_s32 = x_s32/y_s32
|
||||
xy = float(xy_s32)
|
||||
|
||||
tol = 2**xy_s32.exp
|
||||
assert np.isclose(x/y, xy, rtol=2**-29, atol=tol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
|
||||
def test_float_s32_add(x, y):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
y_s32 = types.float_s32(float(y))
|
||||
|
||||
xy_s32 = x_s32 + y_s32
|
||||
xy = float(xy_s32)
|
||||
|
||||
tol = 2**(max(x_s32.exp, y_s32.exp) + 2)
|
||||
assert np.isclose(x + y, xy, rtol=2**-29, atol=tol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
|
||||
def test_float_s32_subt(x, y):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
y_s32 = types.float_s32(float(y))
|
||||
|
||||
xy_s32 = x_s32-y_s32
|
||||
xy = float(xy_s32)
|
||||
|
||||
tol = 2**(max(x_s32.exp, y_s32.exp) + 1)
|
||||
assert np.isclose(x-y, xy, rtol=2**-29, atol=tol)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
|
||||
def test_float_s32_gt(x, y):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
y_s32 = types.float_s32(float(y))
|
||||
|
||||
xy_s32 = x_s32 > y_s32
|
||||
xy = x > y
|
||||
|
||||
assert xy == xy_s32
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x, y", (2*np.random.rand(100, 2)-1)*2**30)
|
||||
def test_float_s32_lt(x, y):
|
||||
x_s32 = types.float_s32(float(x))
|
||||
y_s32 = types.float_s32(float(y))
|
||||
|
||||
xy_s32 = x_s32 < y_s32
|
||||
xy = x < y
|
||||
|
||||
assert xy == xy_s32
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
for n in range(100):
|
||||
# test_float_s32_float((2*np.random.rand(1)-1)*2**32)
|
||||
test_float_s32_add((2*np.random.rand(1)-1)*2**27,
|
||||
(2*np.random.rand(1)-1)*2**27)
|
||||
Reference in New Issue
Block a user