From: Lyude Paul <lyude@redhat.com>
To: Paul Kocialkowski <paul.kocialkowski@linux.intel.com>,
intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH i-g-t 1/3] lib: Add audio library with dedicated helpers
Date: Fri, 18 Aug 2017 12:16:18 -0400 [thread overview]
Message-ID: <1503072978.3702.3.camel@redhat.com> (raw)
In-Reply-To: <20170817160557.14238-1-paul.kocialkowski@linux.intel.com>
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@linux.intel.com>
> ---
> .../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@linux.intel.com>
> + */
> +
> +#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.
> + 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@linux.intel.com>
> + */
> +
> +#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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2017-08-18 16:16 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-17 16:05 [PATCH i-g-t 1/3] lib: Add audio library with dedicated helpers Paul Kocialkowski
2017-08-17 16:05 ` [PATCH i-g-t 2/3] lib: Add ALSA " Paul Kocialkowski
2017-08-18 9:46 ` Arkadiusz Hiler
2017-08-21 7:25 ` Arkadiusz Hiler
2017-08-21 9:39 ` Paul Kocialkowski
2017-08-21 9:45 ` Arkadiusz Hiler
2017-08-18 16:20 ` Lyude Paul
2017-08-21 15:11 ` Paul Kocialkowski
2017-08-17 16:05 ` [PATCH i-g-t 3/3] tests: Introduce audio tests, starting with HDMI signal integrity Paul Kocialkowski
2017-08-18 16:15 ` Lyude Paul
2017-08-21 15:14 ` Paul Kocialkowski
2017-08-21 15:26 ` Lyude Paul
2017-08-17 16:24 ` ✓ Fi.CI.BAT: success for series starting with [1/3] lib: Add audio library with dedicated helpers Patchwork
2017-08-18 9:59 ` Petri Latvala
2017-08-18 16:16 ` Lyude Paul [this message]
2017-08-21 15:27 ` [PATCH i-g-t 1/3] " Paul Kocialkowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1503072978.3702.3.camel@redhat.com \
--to=lyude@redhat.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=paul.kocialkowski@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.