summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <simon.ser@intel.com>2019-04-23 16:04:56 +0300
committerArkadiusz Hiler <arkadiusz.hiler@intel.com>2019-04-25 13:07:47 +0300
commit0f39100b2c70cd251c2827aab39925f4fa298453 (patch)
treec04c4aca0ab4f30e1dc86fd374aa56ac814764f9
parentf0f0a4f5bd18657456885284c00f4bfce91007b7 (diff)
tests/kms_chamelium: test we receive a signal from both audio channels
This commit updates the audio test to make sure we receive a signal from both audio channels. However this commit doesn't check that left and right channels are not swapped. Such a check requires some more work (because the Chamelium device does swap left and right channels) and will be implemented in a future commit. This commit adds a new channel argument to audio_signal_add_frequency, to add a frequency to a single channel only. Some light refactoring has been performed: a proper audio_signal_fini function has been introduced and size_t in now used when it should be. Signed-off-by: Simon Ser <simon.ser@intel.com> Reviewed-by: Martin Peres <martin.peres@linux.intel.com>
-rw-r--r--lib/igt_audio.c114
-rw-r--r--lib/igt_audio.h11
-rw-r--r--tests/kms_chamelium.c58
3 files changed, 111 insertions, 72 deletions
diff --git a/lib/igt_audio.c b/lib/igt_audio.c
index 5822fed7..5b0860e6 100644
--- a/lib/igt_audio.c
+++ b/lib/igt_audio.c
@@ -35,7 +35,7 @@
#include "igt_audio.h"
#include "igt_core.h"
-#define FREQS_MAX 8
+#define FREQS_MAX 64
/**
* SECTION:igt_audio
@@ -49,9 +49,10 @@
struct audio_signal_freq {
int freq;
+ int channel;
- short *period;
- int frames;
+ int16_t *period;
+ size_t period_len;
int offset;
};
@@ -60,7 +61,7 @@ struct audio_signal {
int sampling_rate;
struct audio_signal_freq freqs[FREQS_MAX];
- int freqs_count;
+ size_t freqs_count;
};
/**
@@ -89,17 +90,21 @@ struct audio_signal *audio_signal_init(int channels, int sampling_rate)
* audio_signal_add_frequency:
* @signal: The target signal structure
* @frequency: The frequency to add to the signal
+ * @channel: The channel to add this frequency to, or -1 to add it to all
+ * channels
*
* 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 audio_signal_add_frequency(struct audio_signal *signal, int frequency,
+ int channel)
{
- int index = signal->freqs_count;
+ size_t index = signal->freqs_count;
+ struct audio_signal_freq *freq;
- if (index == FREQS_MAX)
- return -1;
+ igt_assert(index < FREQS_MAX);
+ igt_assert(channel < signal->channels);
/* Stay within the Nyquist–Shannon sampling theorem. */
if (frequency > signal->sampling_rate / 2) {
@@ -114,11 +119,14 @@ int audio_signal_add_frequency(struct audio_signal *signal, int frequency)
*/
frequency = signal->sampling_rate / (signal->sampling_rate / frequency);
- igt_debug("Adding test frequency %d\n", frequency);
+ igt_debug("Adding test frequency %d to channel %d\n",
+ frequency, channel);
+
+ freq = &signal->freqs[index];
+ memset(freq, 0, sizeof(*freq));
+ freq->freq = frequency;
+ freq->channel = channel;
- signal->freqs[index].freq = frequency;
- signal->freqs[index].frames = 0;
- signal->freqs[index].offset = 0;
signal->freqs_count++;
return 0;
@@ -136,20 +144,17 @@ void audio_signal_synthesize(struct audio_signal *signal)
{
int16_t *period;
double value;
- int frames;
+ size_t period_len;
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_len = signal->sampling_rate / freq;
- period = calloc(1, frames * sizeof(short));
+ period = calloc(1, period_len * sizeof(int16_t));
- for (j = 0; j < frames; j++) {
+ for (j = 0; j < period_len; j++) {
value = 2.0 * M_PI * freq / signal->sampling_rate * j;
value = sin(value) * INT16_MAX / signal->freqs_count;
@@ -157,26 +162,34 @@ void audio_signal_synthesize(struct audio_signal *signal)
}
signal->freqs[i].period = period;
- signal->freqs[i].frames = frames;
+ signal->freqs[i].period_len = period_len;
}
}
/**
- * audio_signal_synthesize:
+ * audio_signal_fini:
+ *
+ * Release the signal.
+ */
+void audio_signal_fini(struct audio_signal *signal)
+{
+ audio_signal_reset(signal);
+ free(signal);
+}
+
+/**
+ * audio_signal_reset:
* @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)
+void audio_signal_reset(struct audio_signal *signal)
{
- int i;
+ size_t 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));
+ free(signal->freqs[i].period);
}
signal->freqs_count = 0;
@@ -186,44 +199,45 @@ void audio_signal_clean(struct audio_signal *signal)
* audio_signal_fill:
* @signal: The target signal structure
* @buffer: The target buffer to fill
- * @frames: The number of frames to fill
+ * @samples: The number of samples to fill
*
- * Fill the requested number of frames to the target buffer with the audio
+ * Fill the requested number of samples 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, int16_t *buffer, int frames)
+void audio_signal_fill(struct audio_signal *signal, int16_t *buffer,
+ size_t buffer_len)
{
int16_t *destination, *source;
+ struct audio_signal_freq *freq;
int total;
- int freq_frames;
- int freq_offset;
int count;
int i, j, k;
- memset(buffer, 0, sizeof(int16_t) * signal->channels * frames);
+ memset(buffer, 0, sizeof(int16_t) * signal->channels * buffer_len);
for (i = 0; i < signal->freqs_count; i++) {
+ freq = &signal->freqs[i];
total = 0;
- while (total < frames) {
- freq_frames = signal->freqs[i].frames;
- freq_offset = signal->freqs[i].offset;
+ igt_assert(freq->period);
- source = signal->freqs[i].period + freq_offset;
+ while (total < buffer_len) {
+ source = freq->period + freq->offset;
destination = buffer + total * signal->channels;
- count = freq_frames - freq_offset;
- if (count > (frames - total))
- count = frames - total;
+ count = freq->period_len - freq->offset;
+ if (count > buffer_len - total)
+ count = buffer_len - total;
- freq_offset += count;
- freq_offset %= freq_frames;
-
- signal->freqs[i].offset = freq_offset;
+ freq->offset += count;
+ 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];
}
}
@@ -240,11 +254,11 @@ void audio_signal_fill(struct audio_signal *signal, int16_t *buffer, int frames)
* sampling_rate is given in Hz. data_len is the number of elements in data.
*/
bool audio_signal_detect(struct audio_signal *signal, int sampling_rate,
- double *data, size_t data_len)
+ int channel, double *data, size_t data_len)
{
size_t bin_power_len = data_len / 2 + 1;
double bin_power[bin_power_len];
- bool detected[signal->freqs_count];
+ bool detected[FREQS_MAX];
int ret, freq_accuracy, freq, local_max_freq;
double max, local_max, threshold;
size_t i, j;
@@ -311,6 +325,10 @@ bool audio_signal_detect(struct audio_signal *signal, int sampling_rate,
* invalid. */
if (bin_power[i] < threshold) {
for (j = 0; j < signal->freqs_count; j++) {
+ if (signal->freqs[j].channel >= 0 &&
+ signal->freqs[j].channel != channel)
+ continue;
+
if (signal->freqs[j].freq >
local_max_freq - freq_accuracy &&
signal->freqs[j].freq <
@@ -343,6 +361,10 @@ bool audio_signal_detect(struct audio_signal *signal, int sampling_rate,
/* Check that all frequencies we generated have been detected. */
for (i = 0; i < signal->freqs_count; i++) {
+ if (signal->freqs[i].channel >= 0 &&
+ signal->freqs[i].channel != channel)
+ continue;
+
if (!detected[i]) {
igt_debug("Missing frequency: %d\n",
signal->freqs[i].freq);
diff --git a/lib/igt_audio.h b/lib/igt_audio.h
index 4aa43e69..466e772a 100644
--- a/lib/igt_audio.h
+++ b/lib/igt_audio.h
@@ -35,12 +35,15 @@
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_fini(struct audio_signal *signal);
+int audio_signal_add_frequency(struct audio_signal *signal, int frequency,
+ int channel);
void audio_signal_synthesize(struct audio_signal *signal);
-void audio_signal_clean(struct audio_signal *signal);
-void audio_signal_fill(struct audio_signal *signal, int16_t *buffer, int frames);
+void audio_signal_reset(struct audio_signal *signal);
+void audio_signal_fill(struct audio_signal *signal, int16_t *buffer,
+ size_t buffer_len);
bool audio_signal_detect(struct audio_signal *signal, int sampling_rate,
- double *data, size_t data_len);
+ int channel, double *data, size_t data_len);
size_t audio_extract_channel_s32_le(double *dst, size_t dst_cap,
int32_t *src, size_t src_len,
int n_channels, int channel);
diff --git a/tests/kms_chamelium.c b/tests/kms_chamelium.c
index 014a22b3..687f64c4 100644
--- a/tests/kms_chamelium.c
+++ b/tests/kms_chamelium.c
@@ -777,16 +777,16 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
struct alsa *alsa, int playback_channels,
int playback_rate)
{
- int ret, capture_rate, capture_channels, msec;
+ int ret, capture_rate, capture_channels, msec, freq;
struct chamelium_audio_file *audio_file;
struct chamelium_stream *stream;
enum chamelium_stream_realtime_mode stream_mode;
struct audio_signal *signal;
int32_t *recv, *buf;
double *channel;
- size_t i, streak, page_count;
+ size_t i, j, streak, page_count;
size_t recv_len, buf_len, buf_cap, buf_size, channel_len;
- bool ok;
+ bool ok, success;
char dump_suffix[64];
char *dump_path = NULL;
int dump_fd = -1;
@@ -794,10 +794,15 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
struct audio_state state = {};
if (!alsa_test_output_configuration(alsa, playback_channels,
- playback_rate))
+ playback_rate)) {
+ igt_debug("Skipping test with sample rate %d and %d channels "
+ "because selected output devices don't support this "
+ "configuration\n", playback_rate, playback_channels);
return false;
+ }
- igt_debug("Testing with playback sampling rate %d\n", playback_rate);
+ igt_debug("Testing with playback sampling rate %d and %d channels\n",
+ playback_rate, playback_channels);
alsa_configure_output(alsa, playback_channels, playback_rate);
chamelium_start_capturing_audio(data->chamelium, port, false);
@@ -825,8 +830,12 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
signal = audio_signal_init(playback_channels, playback_rate);
igt_assert(signal);
- for (i = 0; i < test_frequencies_count; i++)
- audio_signal_add_frequency(signal, test_frequencies[i]);
+ for (i = 0; i < test_frequencies_count; i++) {
+ for (j = 0; j < playback_channels; j++) {
+ freq = test_frequencies[i];
+ audio_signal_add_frequency(signal, freq, j);
+ }
+ }
audio_signal_synthesize(signal);
state.signal = signal;
@@ -851,10 +860,11 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
recv = NULL;
recv_len = 0;
+ success = false;
streak = 0;
msec = 0;
i = 0;
- while (streak < MIN_STREAK && msec < AUDIO_TIMEOUT) {
+ while (!success && msec < AUDIO_TIMEOUT) {
ok = chamelium_stream_receive_realtime_audio(stream,
&page_count,
&recv, &recv_len);
@@ -872,21 +882,27 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
igt_assert(write(dump_fd, buf, buf_size) == buf_size);
}
- /* TODO: check other channels too, not just the first one */
- audio_extract_channel_s32_le(channel, channel_len, buf, buf_len,
- capture_channels, 0);
-
msec = i * channel_len / (double) capture_rate * 1000;
igt_debug("Detecting audio signal, t=%d msec\n", msec);
- if (audio_signal_detect(signal, capture_rate, channel,
- channel_len))
- streak++;
- else
- streak = 0;
+ for (j = 0; j < playback_channels; j++) {
+ igt_debug("Processing channel %zu\n", j);
+
+ audio_extract_channel_s32_le(channel, channel_len,
+ buf, buf_len,
+ capture_channels, j);
+
+ if (audio_signal_detect(signal, capture_rate, j,
+ channel, channel_len))
+ streak++;
+ else
+ streak = 0;
+ }
buf_len = 0;
i++;
+
+ success = streak == MIN_STREAK * playback_channels;
}
igt_debug("Stopping audio playback\n");
@@ -898,7 +914,7 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
if (dump_fd >= 0) {
close(dump_fd);
- if (streak == MIN_STREAK) {
+ if (success) {
/* Test succeeded, no need to keep the captured data */
unlink(dump_path);
} else
@@ -921,12 +937,10 @@ do_test_display_audio(data_t *data, struct chamelium_port *port,
chamelium_destroy_audio_file(audio_file);
}
- audio_signal_clean(signal);
- free(signal);
-
+ audio_signal_fini(signal);
chamelium_stream_deinit(stream);
- igt_assert(streak == MIN_STREAK);
+ igt_assert(success);
return true;
}