[alsa-devel] [RFCv3][PATCH 34/39] axfer: add a unit test for vumeter calculation
Takashi Sakamoto
o-takashi at sakamocchi.jp
Mon Oct 2 02:19:35 CEST 2017
In a previous commit, vumeter is implemented. This commit adds a simple
unit test for the feature. This tests positive cases only.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
axfer/test/Makefile.am | 14 +++-
axfer/test/vumeter-test.c | 184 ++++++++++++++++++++++++++++++++++++++++++
axfer/xfer-libasound-irq-rw.c | 2 +-
3 files changed, 196 insertions(+), 4 deletions(-)
create mode 100644 axfer/test/vumeter-test.c
diff --git a/axfer/test/Makefile.am b/axfer/test/Makefile.am
index 76a93bfc..0e48b9f2 100644
--- a/axfer/test/Makefile.am
+++ b/axfer/test/Makefile.am
@@ -1,10 +1,12 @@
TESTS = \
- container-test \
- mapper-test
+ container-test \
+ mapper-test \
+ vumeter-test
check_PROGRAMS = \
container-test \
- mapper-test
+ mapper-test \
+ vumeter-test
container_test_SOURCES = \
../container.h \
@@ -29,3 +31,9 @@ mapper_test_SOURCES = \
../mapper-multiple.c \
generator.c \
mapper-test.c
+
+vumeter_test_SOURCES = \
+ ../vumeter.h \
+ ../vumeter.c \
+ generator.c \
+ vumeter-test.c
diff --git a/axfer/test/vumeter-test.c b/axfer/test/vumeter-test.c
new file mode 100644
index 00000000..6df7c067
--- /dev/null
+++ b/axfer/test/vumeter-test.c
@@ -0,0 +1,184 @@
+/*
+ * test-vumeter.c - A unit test for Volume Unit meter.
+ *
+ * Copyright (c) 2017 Takashi Sakamoto <o-takashi at sakamocchi.jp>
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include "../vumeter.h"
+#include "../misc.h"
+
+#include "generator.h"
+
+#include <stdlib.h>
+
+static bool verbose;
+
+static int callback(struct test_generator *gen, snd_pcm_access_t access,
+ snd_pcm_format_t sample_format,
+ unsigned int samples_per_frame, void *frame_buffer,
+ unsigned int frame_count)
+{
+ static const enum vumeter_mode modes[] = {
+ [0] = VUMETER_MODE_MONO,
+ [1] = VUMETER_MODE_STEREO,
+ };
+ struct vumeter_context *vu = gen->private_data;
+ int i;
+ int err;
+
+ char **vector = NULL;
+
+ if (access == SND_PCM_ACCESS_MMAP_NONINTERLEAVED) {
+ char *buf;
+ unsigned int size;
+
+ vector = calloc(samples_per_frame, sizeof(*vector));
+ if (vector == NULL)
+ return -ENOMEM;
+
+ buf = frame_buffer;
+ size = snd_pcm_format_physical_width(sample_format) *
+ frame_count / 8;
+
+ for (i = 0; i < samples_per_frame; ++i)
+ vector[i] = buf + size * i;
+
+ frame_buffer = vector;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(modes); ++i) {
+ int j;
+
+ if (verbose) {
+ printf("%d %s %s %d %d\n",
+ modes[i], snd_pcm_access_name(access),
+ snd_pcm_format_name(sample_format),
+ samples_per_frame, frame_count);
+ }
+
+ memset(vu, 0, sizeof(*vu));
+ err = vumeter_context_init(vu, modes[i], access, sample_format,
+ samples_per_frame, 4000);
+ if (err < 0)
+ break;
+ assert(vu->significant_bits_per_sample >= 0);
+ assert(vu->bytes_per_sample >= 0);
+ assert(vu->samples_per_frame >= 0);
+ assert(vu->frames_per_second >= 0);
+ assert(vu->max > 0);
+ assert(vu->peaks != NULL);
+ assert(vu->ratios != NULL);
+ assert(vu->max_ratios_in_second != NULL);
+ assert(vu->printer != NULL);
+ assert(vu->calculator != NULL);
+
+ vumeter_context_prepare(vu);
+ for (j = 0; j < samples_per_frame; ++j) {
+ assert(vu->ratios[j] == 0);
+ assert(vu->max_ratios_in_second[j] == 0);
+ }
+
+ vumeter_context_calculate(vu, frame_buffer, frame_count);
+ for (j = 0; j < samples_per_frame; ++j) {
+ assert(vu->peaks[j] <= vu->max);
+ assert(vu->max_ratios_in_second[j] <= vu->max);
+ assert(vu->max_ratios_in_second[j] <= 100);
+ }
+
+ vumeter_context_destroy(vu);
+ assert(vu->ratios == NULL);
+ assert(vu->max_ratios_in_second == NULL);
+ assert(vu->peaks == NULL);
+ }
+
+ if (vector != NULL)
+ free(vector);
+
+ return err;
+}
+
+int main(int argc, const char *argv[])
+{
+ const uint64_t sample_format_mask =
+ (1ul << SND_PCM_FORMAT_S8) |
+ (1ul << SND_PCM_FORMAT_U8) |
+ (1ul << SND_PCM_FORMAT_S16_LE) |
+ (1ul << SND_PCM_FORMAT_S16_BE) |
+ (1ul << SND_PCM_FORMAT_U16_LE) |
+ (1ul << SND_PCM_FORMAT_U16_BE) |
+ (1ul << SND_PCM_FORMAT_S24_LE) |
+ (1ul << SND_PCM_FORMAT_S24_BE) |
+ (1ul << SND_PCM_FORMAT_U24_LE) |
+ (1ul << SND_PCM_FORMAT_U24_BE) |
+ (1ul << SND_PCM_FORMAT_S32_LE) |
+ (1ul << SND_PCM_FORMAT_S32_BE) |
+ (1ul << SND_PCM_FORMAT_U32_LE) |
+ (1ul << SND_PCM_FORMAT_U32_BE) |
+ (1ul << SND_PCM_FORMAT_S24_3LE) |
+ (1ul << SND_PCM_FORMAT_S24_3BE) |
+ (1ul << SND_PCM_FORMAT_U24_3LE) |
+ (1ul << SND_PCM_FORMAT_U24_3BE) |
+ (1ul << SND_PCM_FORMAT_S24_3LE) |
+ (1ul << SND_PCM_FORMAT_S24_3BE) |
+ (1ul << SND_PCM_FORMAT_U24_3LE) |
+ (1ul << SND_PCM_FORMAT_U24_3BE) |
+ (1ul << SND_PCM_FORMAT_S20_3LE) |
+ (1ul << SND_PCM_FORMAT_S20_3BE) |
+ (1ul << SND_PCM_FORMAT_U20_3LE) |
+ (1ul << SND_PCM_FORMAT_U20_3BE) |
+ (1ul << SND_PCM_FORMAT_S18_3LE) |
+ (1ul << SND_PCM_FORMAT_S18_3BE) |
+ (1ul << SND_PCM_FORMAT_U18_3LE) |
+ (1ul << SND_PCM_FORMAT_U18_3BE);
+ uint64_t access_mask;
+ struct test_generator gen = {0};
+ snd_pcm_access_t access;
+ int err;
+
+ if (argc > 1) {
+ char *term;
+
+ access = strtol(argv[1], &term, 10);
+ if (errno != 0 || *term != '\0') {
+ err = -EINVAL;
+ goto end;
+ }
+ if (access < SND_PCM_ACCESS_MMAP_INTERLEAVED &&
+ access > SND_PCM_ACCESS_RW_NONINTERLEAVED) {
+ err = -EINVAL;
+ goto end;
+ }
+ if (access == SND_PCM_ACCESS_MMAP_COMPLEX) {
+ err = -EINVAL;
+ goto end;
+ }
+ access_mask = 1ul << access;
+ verbose = true;
+ } else {
+ access_mask = (1ul << SND_PCM_ACCESS_MMAP_INTERLEAVED) |
+ (1ul << SND_PCM_ACCESS_MMAP_NONINTERLEAVED) |
+ (1ul << SND_PCM_ACCESS_RW_INTERLEAVED) |
+ (1ul << SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ verbose = false;
+ }
+
+
+ err = generator_context_init(&gen, access_mask, sample_format_mask,
+ 1, 128, 23, 4500, 1024,
+ sizeof(struct vumeter_context));
+ if (err < 0)
+ return EXIT_FAILURE;
+
+ err = generator_context_run(&gen, callback);
+
+ generator_context_destroy(&gen);
+end:
+ if (err < 0) {
+ printf("%s\n", strerror(-err));
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/axfer/xfer-libasound-irq-rw.c b/axfer/xfer-libasound-irq-rw.c
index ee5ce801..a2152d92 100644
--- a/axfer/xfer-libasound-irq-rw.c
+++ b/axfer/xfer-libasound-irq-rw.c
@@ -261,11 +261,11 @@ static int write_frames(struct libasound_state *state,
err = snd_pcm_writen(state->handle, cache->buf, consumed_count);
if (err < 0)
return err;
+ consumed_count = (unsigned int)err;
if (vu)
vumeter_context_calculate(vu, cache->buf, consumed_count);
- consumed_count = (unsigned int)err;
cache->align_frames(cache, consumed_count, cache->bytes_per_sample,
cache->samples_per_frame);
--
2.11.0
More information about the Alsa-devel
mailing list