Re: [PATCH i-g-t 1/3] lib: Add audio library with dedicated helpers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.
> +			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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx




[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux