[igt-dev] [PATCH i-g-t] tests/kms_chamelium: check audio signal amplitude

Simon Ser
2019-05-14T12:25:01Z

This patch adds amplitude checks to Chamelium audio tests. It fails if the
amplitude of the received signal isn't close enough to the amplitude we send.

The igt_audio library has been expanded to be able to support such a check. A
new function audio_amplitude computes the amplitude of a buffer of audio
samples. A new function audio_signal_amplitude returns the amplitude of an
audio_signal. audio_signal_fill has been refactored to accomodate for this new
function.

Signed-off-by: Simon Ser <simon.ser@intel.com>
---

This patch depends on two other patches:
- lib/igt_audio: use double instead of int16_t
- lib/igt_audio: normalize samples when extracting channel

It's submitted separately because:
- These two required patches are unrelated to each other
- These two required patches haven't been written for this patch (but rather
for the upcoming series testing more audio formats)
- This patch can be reviewed even if these two patches haven't landed yet

lib/igt_audio.c | 86 ++++++++++++++++++++++++++++---------------
lib/igt_audio.h | 2 +
tests/kms_chamelium.c | 15 ++++++++
3 files changed, 74 insertions(+), 29 deletions(-)

diff --git a/lib/igt_audio.c b/lib/igt_audio.c
index c991f52754fa..0e042fd6f2bf 100644
--- a/lib/igt_audio.c
+++ b/lib/igt_audio.c
@@ -195,36 +195,25 @@ void audio_signal_reset(struct audio_signal *signal)
signal->freqs_count = 0;
}

-/**
- * audio_signal_fill:
- * @signal: The target signal structure
- * @buffer: The target buffer to fill
- * @samples: The number of samples to fill
- *
- * Fill the requested number of samples to the target buffer with the audio
- * signal data (in interleaved double format), at the requested sampling rate
- * and number of channels.
- */
-void audio_signal_fill(struct audio_signal *signal, double *buffer,
- size_t samples)
+static void audio_signal_add_channel(struct audio_signal *signal, int channel,
+ double *buffer, size_t samples,
+ size_t stride)
{
double *destination, *source;
struct audio_signal_freq *freq;
- int total;
- int count;
- int i, j, k;
-
- memset(buffer, 0, sizeof(double) * signal->channels * samples);
+ int total, count;
+ int i, j;

for (i = 0; i < signal->freqs_count; i++) {
freq = &signal->freqs[i];
- total = 0;
-
igt_assert(freq->period);

- while (total < samples) {
+ if (freq->channel >= 0 && freq->channel != channel)
+ continue;
+
+ for (total = 0; total < samples; total += count) {
source = freq->period + freq->offset;
- destination = buffer + total * signal->channels;
+ destination = buffer + total * stride;

count = freq->period_len - freq->offset;
if (count > samples - total)
@@ -234,19 +223,44 @@ void audio_signal_fill(struct audio_signal *signal, double *buffer,
freq->offset %= freq->period_len;

for (j = 0; j < count; j++) {
- for (k = 0; k < signal->channels; k++) {
- if (freq->channel >= 0 &&
- freq->channel != k)
- continue;
- destination[j * signal->channels + k] += source[j];
- }
+ destination[j * stride + channel] += source[j];
}
-
- total += count;
}
}
}

+double audio_signal_amplitude(struct audio_signal *signal, int channel)
+{
+ double buf[512] = {0};
+
+ audio_signal_add_channel(signal, channel, buf,
+ sizeof(buf) / sizeof(buf[0]), 1);
+ return audio_amplitude(buf, sizeof(buf) / sizeof(buf[0]));
+}
+
+/**
+ * audio_signal_fill:
+ * @signal: The target signal structure
+ * @buffer: The target buffer to fill
+ * @samples: The number of samples to fill
+ *
+ * Fill the requested number of samples to the target buffer with the audio
+ * signal data (in interleaved double format), at the requested sampling rate
+ * and number of channels.
+ */
+void audio_signal_fill(struct audio_signal *signal, double *buffer,
+ size_t samples)
+{
+ int i;
+
+ memset(buffer, 0, sizeof(double) * signal->channels * samples);
+
+ for (i = 0; i < signal->channels; i++) {
+ audio_signal_add_channel(signal, i, buffer, samples,
+ signal->channels);
+ }
+}
+
void audio_signal_fill_s16_le(struct audio_signal *signal, int16_t *buffer,
size_t samples)
{
@@ -409,6 +423,20 @@ size_t audio_extract_channel_s32_le(double *dst, size_t dst_cap,
return dst_len;
}

+double audio_amplitude(const double *buf, size_t buf_len)
+{
+ size_t i;
+ double max;
+
+ max = 0;
+ for (i = 0; i < buf_len; i++) {
+ if (fabs(buf[i]) > max)
+ max = fabs(buf[i]);
+ }
+
+ return max;
+}
+
#define RIFF_TAG "RIFF"
#define WAVE_TAG "WAVE"
#define FMT_TAG "fmt "
diff --git a/lib/igt_audio.h b/lib/igt_audio.h
index 56e080c87848..eb9dd7f1a502 100644
--- a/lib/igt_audio.h
+++ b/lib/igt_audio.h
@@ -40,6 +40,7 @@ int audio_signal_add_frequency(struct audio_signal *signal, int frequency,
int channel);
void audio_signal_synthesize(struct audio_signal *signal);
void audio_signal_reset(struct audio_signal *signal);
+double audio_signal_amplitude(struct audio_signal *signal, int channel);
void audio_signal_fill(struct audio_signal *signal, double *buffer,
size_t buffer_len);
void audio_signal_fill_s16_le(struct audio_signal *signal, int16_t *buffer,
@@ -51,5 +52,6 @@ size_t audio_extract_channel_s32_le(double *dst, size_t dst_cap,
int n_channels, int channel);
int audio_create_wav_file_s32_le(const char *qualifier, uint32_t sample_rate,
uint16_t channels, char **path);
+double audio_amplitude(const double *buf, size_t buf_len);

#endif
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 1b1d554b70a0..8d5e16cc07e9 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -757,6 +757,7 @@ test_display_frame_dump(data_t *data, struct chamelium_port *port)
#define AUDIO_TIMEOUT 2000 /* ms */
/* A streak of 3 gives confidence that the signal is good. */
#define MIN_STREAK 3
+#define AMPLITUDE_ACCURACY 0.15

static int sampling_rates[] = {
32000,
@@ -825,6 +826,8 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
pthread_t thread;
struct audio_state state = {};
int channel_mapping[8], capture_chan;
+ double channel_amplitudes[8];
+ double amplitude;

if (!alsa_test_output_configuration(alsa, playback_channels,
playback_rate)) {
@@ -871,6 +874,9 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
}
audio_signal_synthesize(signal);

+ for (i = 0; i < playback_channels; i++)
+ channel_amplitudes[i] = audio_signal_amplitude(signal, i);
+
state.signal = signal;
state.run = true;
alsa_register_output_callback(alsa, audio_output_callback, &state,
@@ -965,6 +971,15 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
capture_channels,
capture_chan);

+ amplitude = audio_amplitude(channel, channel_len);
+ if (fabs(channel_amplitudes[j] - amplitude) >
+ AMPLITUDE_ACCURACY) {
+ igt_debug("Amplitude mismatch for channel %zu: "
+ "sent %f, received %f\n", j,
+ channel_amplitudes[j], amplitude);
+ streak = 0;
+ }
+
if (audio_signal_detect(signal, capture_rate, j,
channel, channel_len))
streak++;
--
2.21.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org