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