1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2018 Intel Corporation. All rights reserved.
4 //
5 // Author: Slawomir Blauciak <slawomir.blauciak@linux.intel.com>
6
7 #include <stdarg.h>
8 #include <stddef.h>
9 #include <math.h>
10 #include <setjmp.h>
11 #include <stdint.h>
12 #include <cmocka.h>
13 #include <sof/list.h>
14 #include <sof/ipc/driver.h>
15 #include <sof/ipc/msg.h>
16 #include <sof/ipc/topology.h>
17 #include <sof/ipc/schedule.h>
18 #include <sof/audio/buffer.h>
19 #include <sof/audio/component.h>
20 #include <sof/audio/format.h>
21 #include <sof/audio/mixer.h>
22 #include <sof/audio/module_adapter/module/generic.h>
23 #include "../module_adapter.h"
24
25 #ifdef HAVE_MALLOC_H
26 #include <malloc.h>
27 #else
28 #include <stdlib.h>
29 #endif
30
31 #include "comp_mock.h"
32
33 #define MIX_TEST_SAMPLES 32
34
35 struct mix_test_case {
36 int num_sources;
37 int num_chans;
38 const char *name;
39 };
40
41 #define TEST_CASE(_num_sources, _num_chans) \
42 { \
43 .num_sources = (_num_sources), \
44 .num_chans = (_num_chans), \
45 .name = ("test_audio_mixer_copy_" \
46 #_num_sources "_srcs_" \
47 #_num_chans "ch"), \
48 }
49
50 static struct mix_test_case mix_test_cases[] = {
51 TEST_CASE(1, 2),
52 TEST_CASE(1, 4),
53 TEST_CASE(1, 8),
54 TEST_CASE(2, 2),
55 TEST_CASE(2, 4),
56 TEST_CASE(2, 8),
57 TEST_CASE(3, 2),
58 TEST_CASE(4, 2),
59 TEST_CASE(6, 2),
60 TEST_CASE(8, 2)
61 };
62
test_setup(void ** state)63 static int test_setup(void **state)
64 {
65 struct mix_test_case *tc = *((struct mix_test_case **)state);
66 struct processing_module_test_parameters test_parameters = {
67 tc->num_chans, 48, 1, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, NULL
68 };
69 struct processing_module_test_data *test_data;
70 struct module_data *mod_data;
71 struct mixer_data *md;
72
73
74 /* allocate and set new processing module, device and mixer data */
75 test_data = test_malloc(sizeof(*test_data));
76 test_data->parameters = test_parameters;
77 test_data->num_sources = tc->num_sources;
78 test_data->num_sinks = 1;
79 module_adapter_test_setup(test_data);
80
81 mod_data = &test_data->mod->priv;
82 md = test_malloc(sizeof(*md));
83 mod_data->private = md;
84
85 md->mix_func = mixer_get_processing_function(test_data->mod->dev, test_data->sinks[0]);
86
87 *state = test_data;
88
89 return 0;
90 }
91
test_teardown(void ** state)92 static int test_teardown(void **state)
93 {
94 struct processing_module_test_data *test_data = *state;
95 struct mixer_data *md = module_get_private_data(test_data->mod);
96
97 test_free(md);
98 module_adapter_test_free(test_data);
99 test_free(test_data);
100
101 return 0;
102 }
103
test_audio_mixer_copy(void ** state)104 static void test_audio_mixer_copy(void **state)
105 {
106 int src_idx;
107 int smp;
108 struct processing_module_test_data *tc = *state;
109 struct processing_module *mod = tc->mod;
110 struct mixer_data *md = module_get_private_data(tc->mod);
111 const struct audio_stream *sources_stream[PLATFORM_MAX_STREAMS];
112
113 for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) {
114 uint32_t *samples = tc->sources[src_idx]->stream.addr;
115
116 for (smp = 0; smp < tc->sources[src_idx]->stream.size / sizeof(int32_t); ++smp) {
117 double rad = M_PI / (180.0 / (smp * (src_idx + 1)));
118
119 samples[smp] = ((sin(rad) + 1) / 2) * (0xFFFFFFFF / 2);
120 }
121
122 audio_stream_produce(&tc->sources[src_idx]->stream,
123 tc->sources[src_idx]->stream.size / sizeof(int32_t));
124
125 sources_stream[src_idx] = &tc->sources[src_idx]->stream;
126 }
127
128 md->mix_func(mod->dev, &tc->sinks[0]->stream, sources_stream, tc->num_sources,
129 mod->dev->frames);
130
131 for (smp = 0; smp < tc->sinks[0]->stream.size / sizeof(int32_t); ++smp) {
132 uint64_t sum = 0;
133
134 for (src_idx = 0; src_idx < tc->num_sources; ++src_idx) {
135 assert_non_null(tc->sources[src_idx]);
136
137 uint32_t *samples = tc->sources[src_idx]->stream.addr;
138
139 sum += samples[smp];
140 }
141
142 sum = sat_int32(sum);
143
144 uint32_t *out_samples = tc->sinks[0]->stream.addr;
145
146 assert_int_equal(out_samples[smp], sum);
147 }
148 }
149
main(void)150 int main(void)
151 {
152 struct CMUnitTest tests[ARRAY_SIZE(mix_test_cases)];
153
154 int i;
155 int cur_test_case = 0;
156
157 for (i = 0; i < ARRAY_SIZE(tests); (++i, ++cur_test_case)) {
158 tests[i].test_func = test_audio_mixer_copy;
159 tests[i].initial_state = &mix_test_cases[cur_test_case];
160 tests[i].setup_func = test_setup;
161 tests[i].teardown_func = test_teardown;
162 tests[i].name = mix_test_cases[cur_test_case].name;
163 }
164
165 cmocka_set_message_output(CM_OUTPUT_TAP);
166
167 return cmocka_run_group_tests(tests, NULL, NULL);
168 }
169