Hi, On Fri, 2017-08-18 at 12:16 -0400, Lyude Paul wrote: > One more small formatting change > > On Thu, 2017-08-17 at 19:05 +0300, Paul Kocialkowski wrote: > > This introduces an audio library, with dedicated helpers for both > > generating signals and detecting peak frequencies in a signal. > > > > This library paves the way for testing audio going through display > > connectors, such as HDMI. > > > > Signed-off-by: Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxxxxxx> > > --- > > .../intel-gpu-tools/intel-gpu-tools-docs.xml | 1 + > > lib/Makefile.am | 2 + > > lib/igt.h | 1 + > > lib/igt_audio.c | 326 > > +++++++++++++++++++++ > > lib/igt_audio.h | 47 +++ > > 5 files changed, 377 insertions(+) > > create mode 100644 lib/igt_audio.c > > create mode 100644 lib/igt_audio.h > > > > diff --git a/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml > > b/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml > > index f88afd2a..c77159cf 100644 > > --- a/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml > > +++ b/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml > > @@ -16,6 +16,7 @@ > > <chapter> > > <title>API Reference</title> > > <xi:include href="xml/drmtest.xml"/> > > + <xi:include href="xml/igt_audio.xml"/> > > <xi:include href="xml/igt_aux.xml"/> > > <xi:include href="xml/igt_chamelium.xml"/> > > <xi:include href="xml/igt_core.xml"/> > > diff --git a/lib/Makefile.am b/lib/Makefile.am > > index 9c932d6f..5ea08314 100644 > > --- a/lib/Makefile.am > > +++ b/lib/Makefile.am > > @@ -33,6 +33,8 @@ if HAVE_GSL > > lib_source_list += \ > > igt_frame.c \ > > igt_frame.h \ > > + igt_audio.c \ > > + igt_audio.h \ > > $(NULL) > > endif > > > > diff --git a/lib/igt.h b/lib/igt.h > > index d16a4991..a75d2db7 100644 > > --- a/lib/igt.h > > +++ b/lib/igt.h > > @@ -35,6 +35,7 @@ > > #include "igt_dummyload.h" > > #include "igt_fb.h" > > #include "igt_frame.h" > > +#include "igt_audio.h" > > #include "igt_gt.h" > > #include "igt_kms.h" > > #include "igt_pm.h" > > diff --git a/lib/igt_audio.c b/lib/igt_audio.c > > new file mode 100644 > > index 00000000..527a4930 > > --- /dev/null > > +++ b/lib/igt_audio.c > > @@ -0,0 +1,326 @@ > > +/* > > + * Copyright © 2017 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. > > + * > > + * Authors: > > + * Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxxxxxx> > > + */ > > + > > +#include "config.h" > > + > > +#include <math.h> > > +#include <gsl/gsl_fft_real.h> > > + > > +#include "igt.h" > > + > > +#define FREQS_MAX 8 > > + > > +/** > > + * SECTION:igt_audio > > + * @short_description: Library for audio-related tests > > + * @title: Audio > > + * @include: igt_audio.h > > + * > > + * This library contains helpers for audio-related tests. More > > specifically, > > + * it allows generating additions of sine signals as well as > > detecting them. > > + */ > > + > > +struct audio_signal_freq { > > + int freq; > > + > > + short *period; > > + int frames; > > + int offset; > > +}; > > + > > +struct audio_signal { > > + int channels; > > + int sampling_rate; > > + > > + struct audio_signal_freq freqs[FREQS_MAX]; > > + int freqs_count; > > +}; > > + > > +/** > > + * audio_signal_init: > > + * @channels: The number of channels to use for the signal > > + * @sampling_rate: The sampling rate to use for the signal > > + * > > + * Allocate and initialize an audio signal structure with the given > > parameters. > > + * > > + * Returns: A newly-allocated audio signal structure > > + */ > > +struct audio_signal *audio_signal_init(int channels, int > > sampling_rate) > > +{ > > + struct audio_signal *signal; > > + > > + signal = malloc(sizeof(struct audio_signal)); > > + memset(signal, 0, sizeof(struct audio_signal)); > > + > > + signal->sampling_rate = sampling_rate; > > + signal->channels = channels; > > + > > + return signal; > > +} > > + > > +/** > > + * audio_signal_add_frequency: > > + * @signal: The target signal structure > > + * @frequency: The frequency to add to the signal > > + * > > + * Add a frequency to the signal. > > + * > > + * Returns: An integer equal to zero for success and negative for > > failure > > + */ > > +int audio_signal_add_frequency(struct audio_signal *signal, int > > frequency) > > +{ > > + int index = signal->freqs_count; > > + > > + if (index == FREQS_MAX) > > + return -1; > > + > > + /* Stay within the Nyquist–Shannon sampling theorem. */ > > + if (frequency > signal->sampling_rate / 2) > > + return -1; > > + > > + /* Clip the frequency to an integer multiple of the > > sampling > > rate. > > + * This to be able to store a full period of it and use > > that > > for > > + * signal generation, instead of recurrent calls to sin(). > > + */ > > + frequency = signal->sampling_rate / (signal->sampling_rate > > / > > frequency); > > + > > + igt_debug("Adding test frequency %d\n", frequency); > > + > > + signal->freqs[index].freq = frequency; > > + signal->freqs[index].frames = 0; > > + signal->freqs[index].offset = 0; > > + signal->freqs_count++; > > + > > + return 0; > > +} > > + > > +/** > > + * audio_signal_synthesize: > > + * @signal: The target signal structure > > + * > > + * Synthesize the data tables for the audio signal, that can later > > be used > > + * to fill audio buffers. The resources allocated by this function > > must be > > + * freed with a call to audio_signal_clean when the signal is no > > longer used. > > + */ > > +void audio_signal_synthesize(struct audio_signal *signal) > > +{ > > + short *period; > > + double value; > > + int frames; > > + int freq; > > + int i, j; > > + > > + if (signal->freqs_count == 0) > > + return; > > + > > + for (i = 0; i < signal->freqs_count; i++) { > > + freq = signal->freqs[i].freq; > > + frames = signal->sampling_rate / freq; > > + > > + period = calloc(1, frames * sizeof(short)); > > + > > + for (j = 0; j < frames; j++) { > > + value = 2.0 * M_PI * freq / signal- > > > sampling_rate * j; > > > > + value = sin(value) * SHRT_MAX / signal- > > > freqs_count; > > > > + > > + period[j] = (short) value; > > + } > > + > > + signal->freqs[i].period = period; > > + signal->freqs[i].frames = frames; > > + } > > +} > > + > > +/** > > + * audio_signal_synthesize: > > + * @signal: The target signal structure > > + * > > + * Free the resources allocated by audio_signal_synthesize and > > remove > > + * the previously-added frequencies. > > + */ > > +void audio_signal_clean(struct audio_signal *signal) > > +{ > > + int i; > > + > > + for (i = 0; i < signal->freqs_count; i++) { > > + if (signal->freqs[i].period) > > + free(signal->freqs[i].period); > > + > > + memset(&signal->freqs[i], 0, sizeof(struct > > audio_signal_freq)); > > + } > > + > > + signal->freqs_count = 0; > > +} > > + > > +/** > > + * audio_signal_fill: > > + * @signal: The target signal structure > > + * @buffer: The target buffer to fill > > + * @frames: The number of frames to fill > > + * > > + * Fill the requested number of frames to the target buffer with > > the > > audio > > + * signal data (in interleaved S16_LE format), at the requested > > sampling rate > > + * and number of channels. > > + */ > > +void audio_signal_fill(struct audio_signal *signal, short *buffer, > > int frames) > > +{ > > + short *destination; > > + short *source; > > + int total; > > + int freq_frames; > > + int freq_offset; > > + int count; > > + int i, j, k; > > + > > + memset(buffer, 0, sizeof(short) * signal->channels * > > frames); > > + > > + for (i = 0; i < signal->freqs_count; i++) { > > + total = 0; > > + > > + while (total < frames) { > > + freq_frames = signal->freqs[i].frames; > > + freq_offset = signal->freqs[i].offset; > > + > > + source = signal->freqs[i].period + > > freq_offset; > > + destination = buffer + total * signal- > > > channels; > > > > + > > + count = freq_frames - freq_offset; > > + if (count > (frames - total)) > > + count = frames - total; > > + > > + freq_offset += count; > > + freq_offset %= freq_frames; > > + > > + signal->freqs[i].offset = freq_offset; > > + > > + for (j = 0; j < count; j++) { > > + for (k = 0; k < signal->channels; > > k++) { > > + destination[j * signal- > > > channels + k] += source[j]; > > > > + } > > + } > > + > > + total += count; > > + } > > + } > > +} > > + > > +/** > > + * audio_signal_detect: > > + * @signal: The target signal structure > > + * @channels: The input data's number of channels > > + * @sampling_rate: The input data's sampling rate > > + * @buffer: The input data's buffer > > + * @frames: The input data's number of frames > > + * > > + * Detect that the frequencies specified in @signal, and only > > those, > > are > > + * present in the input data. The input data's format is required > > to > > be S16_LE. > > + * > > + * Returns: A boolean indicating whether the detection was > > successful > > + */ > > +bool audio_signal_detect(struct audio_signal *signal, int channels, > > + int sampling_rate, short *buffer, int > > frames) > > +{ > > + double data[frames]; > > + int amplitude[frames / 2]; > > + bool detected[signal->freqs_count]; > > + int threshold; > > + bool above; > > + int error; > > + int freq; > > + int max; > > + int c, i, j; > > + > > + /* Allowed error in Hz due to FFT step. */ > > + error = sampling_rate / frames; > > + > > + for (c = 0; c < channels; c++) { > > + for (i = 0; i < frames; i++) > > + data[i] = (double) buffer[i * channels + > > c]; > > + > > + gsl_fft_real_radix2_transform(data, 1, frames); > > + > > + max = 0; > > + > > + for (i = 0; i < frames / 2; i++) { > > + amplitude[i] = sqrt(data[i] * data[i] + > > + data[frames - i] > > * > > + data[frames - > > i]); > > More indenting fixes? not sure if this one is just a result of it > getting formatted as an email. This one was a legit mistake, good catch! > > + if (amplitude[i] > max) > > + max = amplitude[i]; > > + } > > + > > + for (i = 0; i < signal->freqs_count; i++) > > + detected[i] = false; > > + > > + threshold = max / 2; > > + above = false; > > + max = 0; > > + > > + for (i = 0; i < frames / 2; i++) { > > + if (amplitude[i] > threshold) > > + above = true; > > + > > + if (above) { > > + if (amplitude[i] < threshold) { > > + above = false; > > + max = 0; > > + > > + for (j = 0; j < signal- > > > freqs_count; j++) { > > > > + if (signal- > > > freqs[j].freq > > > > > + freq - error && > > + signal- > > > freqs[j].freq < > > > > + freq + error) { > > + detected[j] > > = true; > > + break; > > + } > > + } > > + > > + /* Detected frequency was > > not generated. */ > > + if (j == signal- > > > freqs_count) { > > > > + igt_debug("Detected > > additional frequency: %d\n", > > + freq); > > + return false; > > + } > > + } > > + > > + if (amplitude[i] > max) { > > + max = amplitude[i]; > > + freq = sampling_rate * i / > > frames; > > + } > > + } > > + } > > + > > + for (i = 0; i < signal->freqs_count; i++) { > > + if (!detected[i]) { > > + igt_debug("Missing frequency: > > %d\n", > > + signal->freqs[i].freq); > > + return false; > > + } > > + } > > + } > > + > > + return true; > > +} > > diff --git a/lib/igt_audio.h b/lib/igt_audio.h > > new file mode 100644 > > index 00000000..507e7ab9 > > --- /dev/null > > +++ b/lib/igt_audio.h > > @@ -0,0 +1,47 @@ > > +/* > > + * Copyright © 2017 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. > > + * > > + * Authors: > > + * Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxxxxxx> > > + */ > > + > > +#ifndef IGT_AUDIO_H > > +#define IGT_AUDIO_H > > + > > +#ifdef HAVE_CONFIG_H > > +#include "config.h" > > +#endif > > + > > +#include "igt.h" > > +#include <stdbool.h> > > + > > +struct audio_signal; > > + > > +struct audio_signal *audio_signal_init(int channels, int > > sampling_rate); > > +int audio_signal_add_frequency(struct audio_signal *signal, int > > frequency); > > +void audio_signal_synthesize(struct audio_signal *signal); > > +void audio_signal_clean(struct audio_signal *signal); > > +void audio_signal_fill(struct audio_signal *signal, short *buffer, > > int frames); > > +bool audio_signal_detect(struct audio_signal *signal, int channels, > > + int sampling_rate, short *buffer, int > > frames); > > + > > +#endif -- Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxxxxxx> Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo, Finland _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx