Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test: Cmocka: Add unit test for function drc_inv_fixed() #9649

Merged
merged 2 commits into from
Nov 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/run-mocks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ EOF
parse_opts()
{
# default config if none supplied
CONFIG="imx8_defconfig"
CONFIG="unit_test_defconfig"
VALGRIND_CMD=""

while getopts "vc:" flag; do
Expand Down
2 changes: 2 additions & 0 deletions src/arch/xtensa/configs/unit_test_defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_METEORLAKE=y
CONFIG_COMP_DRC=y
3 changes: 3 additions & 0 deletions test/cmocka/src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ endif()
if(CONFIG_COMP_FIR)
add_subdirectory(eq_fir)
endif()
if(CONFIG_COMP_DRC)
add_subdirectory(drc)
endif()
12 changes: 12 additions & 0 deletions test/cmocka/src/audio/drc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-License-Identifier: BSD-3-Clause

cmocka_test(drc_math_test
drc_math_test.c
${PROJECT_SOURCE_DIR}/src/audio/drc/drc_math_generic.c
${PROJECT_SOURCE_DIR}/src/audio/drc/drc_math_hifi3.c
${PROJECT_SOURCE_DIR}/src/math/numbers.c
${PROJECT_SOURCE_DIR}/src/math/exp_fcn.c
${PROJECT_SOURCE_DIR}/src/math/exp_fcn_hifi.c
)

target_include_directories(drc_math_test PRIVATE ${PROJECT_SOURCE_DIR}/src/audio)
148 changes: 148 additions & 0 deletions test/cmocka/src/audio/drc/drc_math_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2024 Intel Corporation.

#include <math.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <stdio.h>
#include <cmocka.h>

#include <drc/drc_math.h>

#define TEST_POINTS 500

#define ABS_DELTA_TOLERANCE_T1 1.0e-9
#define REL_DELTA_TOLERANCE_T1 1.4e-4
#define ABS_DELTA_TOLERANCE_T2 7.4e-7
#define REL_DELTA_TOLERANCE_T2 7.5e-6
#define ABS_DELTA_TOLERANCE_T3 3.8e-4
#define REL_DELTA_TOLERANCE_T3 1.9e-6

static int32_t drc_inv_ref(int32_t x, int32_t precision_x, int32_t precision_y)
{
double xf, yf, ys;

xf = (double)x / ((int64_t)1 << precision_x);
yf = 1 / xf;
ys = round(yf * ((int64_t)1 << precision_y));
if (ys > INT32_MAX)
ys = INT32_MAX;

if (ys < INT32_MIN)
ys = INT32_MIN;

return (int32_t)ys;
}

static void drc_math_inv_fixed_test_helper(int32_t x_start, int32_t x_end,
int32_t x_step, int q_in, int q_out,
double abs_delta_tolerance, double rel_delta_tolerance)
{
double fx, fy1, fy2;
double abs_delta, rel_delta;
int64_t x1;
int32_t x, y1, y2;
int32_t differences = 0;
double abs_delta_max = 0;
double rel_delta_max = 0;

printf("%s: Testing q_in = %d q_out = %d in = %d:%d:%d\n", __func__,
q_in, q_out, x_start, x_step, x_end);

x1 = x_start;
while (x1 <= x_end) {
x = (int32_t)x1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would

for (x = x_start; x <= x_end; x += x_step)

also work? Maybe making x 64 bits to avoid wrapping around

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Packs three lines into one ... but as you prefer. The loop variable is 64 bits to avoid it to wrap if max int32_t value is not hit exactly. So why not have the above simple type cast code line. I like simple not very packed coding style while I see that you prefer more compact code. Since this is test code I want it to be clear, no worry about performance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I agree - need to be readable by the folks working on these features.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like simple not very packed coding style while I see that you prefer more compact code. Since this is test code I want it to be clear, no worry about performance.

@singalsu sure, if that's your preference - fine this me. This is by no means critical. I just like to fit as much code as possible onto the screen at once, while still keeping some sane restrictions like 1 command per line and single empty lines between blocks. And without making the font too small :-) But - again - that's just my personal preference

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was starting to change it but it got merged, next time then!

y1 = drc_inv_ref(x, q_in, q_out);
y2 = drc_inv_fixed(x, q_in, q_out);
if (y1 != y2)
differences++;

fx = (double)x / (1 << q_in);
fy1 = (double)y1 / (1 << q_out);
fy2 = (double)y2 / (1 << q_out);
abs_delta = fabs(fy1 - fy2);
rel_delta = abs_delta / fy1;
if (rel_delta > rel_delta_max)
rel_delta_max = rel_delta;

if (abs_delta > abs_delta_max)
abs_delta_max = abs_delta;

if (rel_delta > rel_delta_tolerance) {
printf("%s: Relative error %g exceeds limit %g, input %g output %g ref %g.\n",
__func__, rel_delta, rel_delta_tolerance, fx, fy2, fy1);
assert_true(false);
}

if (abs_delta > abs_delta_tolerance) {
printf("%s: Absolute error %g exceeds limit %g, input %g output %g ref %g.\n",
__func__, abs_delta, abs_delta_tolerance, fx, fy2, fy1);
assert_true(false);
}

x1 += x_step;
}

printf("%s: bit exact differences count = %d\n", __func__, differences);
printf("%s: Absolute max error was %.6e.\n", __func__, abs_delta_max);
printf("%s: Relative max error was %.6e.\n", __func__, rel_delta_max);
}

static void test_function_drc_inv_fixed_q12_q30(void **state)
{
(void)state;

int32_t x_start = 1;
int32_t x_end = INT32_MAX;
int32_t x_step = (int32_t)(((int64_t)x_end - (int64_t)x_start) / (TEST_POINTS - 1));
int q_in = 12;
int q_out = 30;

drc_math_inv_fixed_test_helper(x_start, x_end, x_step, q_in, q_out,
ABS_DELTA_TOLERANCE_T1, REL_DELTA_TOLERANCE_T1);
}

static void test_function_drc_inv_fixed_q22_q26(void **state)
{
(void)state;

int32_t x_start = 1;
int32_t x_end = INT32_MAX;
int32_t x_step = (int32_t)(((int64_t)x_end - (int64_t)x_start) / TEST_POINTS);
int q_in = 22;
int q_out = 26;

drc_math_inv_fixed_test_helper(x_start, x_end, x_step, q_in, q_out,
ABS_DELTA_TOLERANCE_T2, REL_DELTA_TOLERANCE_T2);
}

static void test_function_drc_inv_fixed_q31_q20(void **state)
{
(void)state;

int32_t x_start = 1;
int32_t x_end = INT32_MAX;
int32_t x_step = (int32_t)(((int64_t)x_end - (int64_t)x_start) / TEST_POINTS);
int q_in = 31;
int q_out = 20;

drc_math_inv_fixed_test_helper(x_start, x_end, x_step, q_in, q_out,
ABS_DELTA_TOLERANCE_T3, REL_DELTA_TOLERANCE_T3);
}

int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_function_drc_inv_fixed_q12_q30),
cmocka_unit_test(test_function_drc_inv_fixed_q22_q26),
cmocka_unit_test(test_function_drc_inv_fixed_q31_q20),
};

cmocka_set_message_output(CM_OUTPUT_TAP);

return cmocka_run_group_tests(tests, NULL, NULL);
}
Loading