1 /*
2 * Copyright © 2019 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Author: Simon Ser <simon.ser@intel.com>
24 */
25
26 #include "config.h"
27
28 #include <stdlib.h>
29
30 #include "igt_core.h"
31 #include "igt_audio.h"
32
33 #define SAMPLING_RATE 44100
34 #define CHANNELS 1
35 #define BUFFER_LEN 2048
36 /** PHASESHIFT_LEN: how many samples will be truncated from the signal */
37 #define PHASESHIFT_LEN 8
38
39 static const int test_freqs[] = { 300, 700, 5000 };
40
41 static const size_t test_freqs_len = sizeof(test_freqs) / sizeof(test_freqs[0]);
42
43 #define TEST_EXTRA_FREQ 500
44
test_signal_detect_untampered(struct audio_signal * signal)45 static void test_signal_detect_untampered(struct audio_signal *signal)
46 {
47 double buf[BUFFER_LEN];
48 bool ok;
49
50 audio_signal_fill(signal, buf, BUFFER_LEN / CHANNELS);
51 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
52 igt_assert(ok);
53 }
54
test_signal_detect_silence(struct audio_signal * signal)55 static void test_signal_detect_silence(struct audio_signal *signal)
56 {
57 double buf[BUFFER_LEN] = {0};
58 bool ok;
59
60 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
61
62 igt_assert(!ok);
63 }
64
test_signal_detect_noise(struct audio_signal * signal)65 static void test_signal_detect_noise(struct audio_signal *signal)
66 {
67 double buf[BUFFER_LEN];
68 bool ok;
69 size_t i;
70 long r;
71
72 /* Generate random samples between -1 and 1 */
73 srand(42);
74 for (i = 0; i < BUFFER_LEN; i++) {
75 r = random();
76 buf[i] = (double) r / RAND_MAX * 2 - 1;
77 }
78
79 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
80
81 igt_assert(!ok);
82 }
83
test_signal_detect_with_missing_freq(struct audio_signal * signal)84 static void test_signal_detect_with_missing_freq(struct audio_signal *signal)
85 {
86 double buf[BUFFER_LEN];
87 struct audio_signal *missing;
88 bool ok;
89 size_t i;
90
91 /* Generate a signal with all the expected frequencies but the first
92 * one */
93 missing = audio_signal_init(CHANNELS, SAMPLING_RATE);
94 for (i = 1; i < test_freqs_len; i++) {
95 audio_signal_add_frequency(missing, test_freqs[i], 0);
96 }
97 audio_signal_synthesize(missing);
98
99 audio_signal_fill(missing, buf, BUFFER_LEN / CHANNELS);
100 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
101 igt_assert(!ok);
102 }
103
test_signal_detect_with_unexpected_freq(struct audio_signal * signal)104 static void test_signal_detect_with_unexpected_freq(struct audio_signal *signal)
105 {
106 double buf[BUFFER_LEN];
107 struct audio_signal *extra;
108 bool ok;
109 size_t i;
110
111 /* Add an extra, unexpected frequency */
112 extra = audio_signal_init(CHANNELS, SAMPLING_RATE);
113 for (i = 0; i < test_freqs_len; i++) {
114 audio_signal_add_frequency(extra, test_freqs[i], 0);
115 }
116 audio_signal_add_frequency(extra, TEST_EXTRA_FREQ, 0);
117 audio_signal_synthesize(extra);
118
119 audio_signal_fill(extra, buf, BUFFER_LEN / CHANNELS);
120 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
121 igt_assert(!ok);
122 }
123
test_signal_detect_held_sample(struct audio_signal * signal)124 static void test_signal_detect_held_sample(struct audio_signal *signal)
125 {
126 double *buf;
127 bool ok;
128 size_t i;
129 double value;
130
131 buf = malloc(BUFFER_LEN * sizeof(double));
132 audio_signal_fill(signal, buf, BUFFER_LEN / CHANNELS);
133
134 /* Repeat a sample in the middle of the signal */
135 value = buf[BUFFER_LEN / 3];
136 for (i = 0; i < 5; i++)
137 buf[BUFFER_LEN / 3 + i] = value;
138
139 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
140
141 free(buf);
142
143 igt_assert_f(!ok, "Expected audio signal not to be detected\n");
144 }
145
test_signal_detect_phaseshift(struct audio_signal * signal)146 static void test_signal_detect_phaseshift(struct audio_signal *signal)
147 {
148 double *buf;
149 bool ok;
150
151 buf = malloc((BUFFER_LEN + PHASESHIFT_LEN) * sizeof(double));
152 audio_signal_fill(signal, buf, (BUFFER_LEN + PHASESHIFT_LEN) / CHANNELS);
153
154 /* Perform a phaseshift (this isn't related to sirens).
155 *
156 * The idea is to remove a part of the signal in the middle of the
157 * buffer:
158 *
159 * BUFFER_LEN/3 PHASESHIFT_LEN 2*BUFFER_LEN/3
160 * [--------------|################|---------------------------------]
161 *
162 * |
163 * V
164 *
165 * [--------------|---------------------------------]
166 */
167 memmove(&buf[BUFFER_LEN / 3], &buf[BUFFER_LEN / 3 + PHASESHIFT_LEN],
168 (2 * BUFFER_LEN / 3) * sizeof(double));
169
170 ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN);
171
172 free(buf);
173
174 igt_assert(!ok);
175 }
176
177 igt_main
178 {
179 struct audio_signal *signal = NULL;
180 int ret;
181 size_t i;
182
183 igt_subtest_group {
184 igt_fixture {
185 signal = audio_signal_init(CHANNELS, SAMPLING_RATE);
186
187 for (i = 0; i < test_freqs_len; i++) {
188 ret = audio_signal_add_frequency(signal,
189 test_freqs[i],
190 0);
191 igt_assert(ret == 0);
192 }
193
194 audio_signal_synthesize(signal);
195 }
196
197 igt_subtest("signal-detect-untampered")
198 test_signal_detect_untampered(signal);
199
200 igt_subtest("signal-detect-silence")
201 test_signal_detect_silence(signal);
202
203 igt_subtest("signal-detect-noise")
204 test_signal_detect_noise(signal);
205
206 igt_subtest("signal-detect-with-missing-freq")
207 test_signal_detect_with_missing_freq(signal);
208
209 igt_subtest("signal-detect-with-unexpected-freq")
210 test_signal_detect_with_unexpected_freq(signal);
211
212 igt_subtest("signal-detect-held-sample")
213 test_signal_detect_held_sample(signal);
214
215 igt_subtest("signal-detect-phaseshift")
216 test_signal_detect_phaseshift(signal);
217
218 igt_fixture {
219 audio_signal_fini(signal);
220 }
221 }
222 }
223