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

Simon Ser simon.ser at intel.com
Tue May 14 12:24:56 UTC 2019


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 at 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



More information about the igt-dev mailing list