/* * Copyright © 2019 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Author: Simon Ser */ #include "config.h" #include #include "igt_core.h" #include "igt_audio.h" #define SAMPLING_RATE 44100 #define CHANNELS 1 #define BUFFER_LEN 2048 /** PHASESHIFT_LEN: how many samples will be truncated from the signal */ #define PHASESHIFT_LEN 8 static const int test_freqs[] = { 300, 700, 5000 }; static const size_t test_freqs_len = sizeof(test_freqs) / sizeof(test_freqs[0]); #define TEST_EXTRA_FREQ 500 static void test_signal_detect_untampered(struct audio_signal *signal) { double buf[BUFFER_LEN]; bool ok; audio_signal_fill(signal, buf, BUFFER_LEN / CHANNELS); ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); igt_assert(ok); } static void test_signal_detect_silence(struct audio_signal *signal) { double buf[BUFFER_LEN] = {0}; bool ok; ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); igt_assert(!ok); } static void test_signal_detect_noise(struct audio_signal *signal) { double buf[BUFFER_LEN]; bool ok; size_t i; long r; /* Generate random samples between -1 and 1 */ srand(42); for (i = 0; i < BUFFER_LEN; i++) { r = random(); buf[i] = (double) r / RAND_MAX * 2 - 1; } ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); igt_assert(!ok); } static void test_signal_detect_with_missing_freq(struct audio_signal *signal) { double buf[BUFFER_LEN]; struct audio_signal *missing; bool ok; size_t i; /* Generate a signal with all the expected frequencies but the first * one */ missing = audio_signal_init(CHANNELS, SAMPLING_RATE); for (i = 1; i < test_freqs_len; i++) { audio_signal_add_frequency(missing, test_freqs[i], 0); } audio_signal_synthesize(missing); audio_signal_fill(missing, buf, BUFFER_LEN / CHANNELS); ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); igt_assert(!ok); } static void test_signal_detect_with_unexpected_freq(struct audio_signal *signal) { double buf[BUFFER_LEN]; struct audio_signal *extra; bool ok; size_t i; /* Add an extra, unexpected frequency */ extra = audio_signal_init(CHANNELS, SAMPLING_RATE); for (i = 0; i < test_freqs_len; i++) { audio_signal_add_frequency(extra, test_freqs[i], 0); } audio_signal_add_frequency(extra, TEST_EXTRA_FREQ, 0); audio_signal_synthesize(extra); audio_signal_fill(extra, buf, BUFFER_LEN / CHANNELS); ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); igt_assert(!ok); } static void test_signal_detect_held_sample(struct audio_signal *signal) { double *buf; bool ok; size_t i; double value; buf = malloc(BUFFER_LEN * sizeof(double)); audio_signal_fill(signal, buf, BUFFER_LEN / CHANNELS); /* Repeat a sample in the middle of the signal */ value = buf[BUFFER_LEN / 3]; for (i = 0; i < 5; i++) buf[BUFFER_LEN / 3 + i] = value; ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); free(buf); igt_assert_f(!ok, "Expected audio signal not to be detected\n"); } static void test_signal_detect_phaseshift(struct audio_signal *signal) { double *buf; bool ok; buf = malloc((BUFFER_LEN + PHASESHIFT_LEN) * sizeof(double)); audio_signal_fill(signal, buf, (BUFFER_LEN + PHASESHIFT_LEN) / CHANNELS); /* Perform a phaseshift (this isn't related to sirens). * * The idea is to remove a part of the signal in the middle of the * buffer: * * BUFFER_LEN/3 PHASESHIFT_LEN 2*BUFFER_LEN/3 * [--------------|################|---------------------------------] * * | * V * * [--------------|---------------------------------] */ memmove(&buf[BUFFER_LEN / 3], &buf[BUFFER_LEN / 3 + PHASESHIFT_LEN], (2 * BUFFER_LEN / 3) * sizeof(double)); ok = audio_signal_detect(signal, SAMPLING_RATE, 0, buf, BUFFER_LEN); free(buf); igt_assert(!ok); } igt_main { struct audio_signal *signal = NULL; int ret; size_t i; igt_subtest_group { igt_fixture { signal = audio_signal_init(CHANNELS, SAMPLING_RATE); for (i = 0; i < test_freqs_len; i++) { ret = audio_signal_add_frequency(signal, test_freqs[i], 0); igt_assert(ret == 0); } audio_signal_synthesize(signal); } igt_subtest("signal-detect-untampered") test_signal_detect_untampered(signal); igt_subtest("signal-detect-silence") test_signal_detect_silence(signal); igt_subtest("signal-detect-noise") test_signal_detect_noise(signal); igt_subtest("signal-detect-with-missing-freq") test_signal_detect_with_missing_freq(signal); igt_subtest("signal-detect-with-unexpected-freq") test_signal_detect_with_unexpected_freq(signal); igt_subtest("signal-detect-held-sample") test_signal_detect_held_sample(signal); igt_subtest("signal-detect-phaseshift") test_signal_detect_phaseshift(signal); igt_fixture { audio_signal_fini(signal); } } }