From 9bc49645720ad1deefbb3d152430634b811e94df Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 5 Mar 2018 16:10:42 +0100 Subject: [PATCH] speaker-test: Refactor the tone-generator codes There are many redundant open codes in speaker-test for performing the similar things, and especially the tone generator codes are ugly. Let's clean up a bit. This patch combines all open-codes into a single common helper with the callback for generating the tone. Signed-off-by: Takashi Iwai --- speaker-test/speaker-test.c | 288 ++++++++++++------------------------ 1 file changed, 98 insertions(+), 190 deletions(-) diff --git a/speaker-test/speaker-test.c b/speaker-test/speaker-test.c index 46b0589..65ab523 100644 --- a/speaker-test/speaker-test.c +++ b/speaker-test/speaker-test.c @@ -101,7 +101,6 @@ static unsigned int nperiods = 4; /* number of periods static double freq = 440.0; /* sinusoidal wave frequency in Hz */ static int test_type = TEST_PINK_NOISE; /* Test type. 1 = noise, 2 = sine wave */ static float generator_scale = 0.8; /* Scale to use for sine volume */ -static pink_noise_t pink; static snd_pcm_uframes_t buffer_size; static snd_pcm_uframes_t period_size; static const char *given_test_wav_file = NULL; @@ -289,12 +288,15 @@ static const int supported_formats[] = { -1 }; -static void generate_sine(uint8_t *frames, int channel, int count, double *_phase) { - double phase = *_phase; - double max_phase = 1.0 / freq; - double step = 1.0 / (double)rate; - double res; - float fres; +typedef union { + float f; + int32_t i; +} value_t; + +static void do_generate(uint8_t *frames, int channel, int count, + value_t (*generate)(void *), void *arg) +{ + value_t res; int chn; int32_t ires; int8_t *samp8 = (int8_t*) frames; @@ -304,134 +306,30 @@ static void generate_sine(uint8_t *frames, int channel, int count, double *_phas while (count-- > 0) { for(chn=0;chn> 24; - } else { - *samp8++ = 0; - } + *samp8++ = res.i >> 24; break; case SND_PCM_FORMAT_S16_LE: - if (chn==channel) { - res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * generator_scale * 0x7fffffff; - ires = res; - *samp16++ = LE_SHORT(ires >> 16); - } else { - *samp16++ = 0; - } + *samp16++ = LE_SHORT(res.i >> 16); break; case SND_PCM_FORMAT_S16_BE: - if (chn==channel) { - res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * generator_scale * 0x7fffffff; - ires = res; - *samp16++ = BE_SHORT(ires >> 16); - } else { - *samp16++ = 0; - } + *samp16++ = BE_SHORT(res.i >> 16); break; case SND_PCM_FORMAT_FLOAT_LE: - if (chn==channel) { - res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * generator_scale; - fres = res; - *samp_f++ = fres; - } else { - *samp_f++ = 0.0; - } + *samp_f++ = res.f; break; case SND_PCM_FORMAT_S32_LE: - if (chn==channel) { - res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * generator_scale * 0x7fffffff; - ires = res; - *samp32++ = LE_INT(ires); - } else { - *samp32++ = 0; - } + *samp32++ = LE_INT(res.i); break; case SND_PCM_FORMAT_S32_BE: - if (chn==channel) { - res = (sin((phase * 2 * M_PI) / max_phase - M_PI)) * generator_scale * 0x7fffffff; - ires = res; - *samp32++ = BE_INT(ires); - } else { - *samp32++ = 0; - } - break; - default: - ; - } - } - - phase += step; - if (phase >= max_phase) - phase -= max_phase; - } - - *_phase = phase; -} - -/* Pink noise is a better test than sine wave because we can tell - * where pink noise is coming from more easily that a sine wave. - */ - - -static void generate_pink_noise( uint8_t *frames, int channel, int count) { - double res; - int chn; - int32_t ires; - int8_t *samp8 = (int8_t*) frames; - int16_t *samp16 = (int16_t*) frames; - int32_t *samp32 = (int32_t*) frames; - - while (count-- > 0) { - for(chn=0;chn> 24; - } else { - *samp8++ = 0; - } - break; - case SND_PCM_FORMAT_S16_LE: - if (chn==channel) { - res = generate_pink_noise_sample(&pink) * generator_scale * 0x07fffffff; - ires = res; - *samp16++ = LE_SHORT(ires >> 16); - } else { - *samp16++ = 0; - } - break; - case SND_PCM_FORMAT_S16_BE: - if (chn==channel) { - res = generate_pink_noise_sample(&pink) * generator_scale * 0x07fffffff; - ires = res; - *samp16++ = BE_SHORT(ires >> 16); - } else { - *samp16++ = 0; - } - break; - case SND_PCM_FORMAT_S32_LE: - if (chn==channel) { - res = generate_pink_noise_sample(&pink) * generator_scale * 0x07fffffff; - ires = res; - *samp32++ = LE_INT(ires); - } else { - *samp32++ = 0; - } - break; - case SND_PCM_FORMAT_S32_BE: - if (chn==channel) { - res = generate_pink_noise_sample(&pink) * generator_scale * 0x07fffffff; - ires = res; - *samp32++ = BE_INT(ires); - } else { - *samp32++ = 0; - } + *samp32++ = BE_INT(res.i); break; default: ; @@ -440,69 +338,63 @@ static void generate_pink_noise( uint8_t *frames, int channel, int count) { } } +/* + * Sine generator + */ +typedef struct { + double phase; + double max_phase; + double step; +} sine_t; + +static void init_sine(sine_t *sine) +{ + sine->phase = 0; + sine->max_phase = 1.0 / freq; + sine->step = 1.0 / (double)rate; +} + +static value_t generate_sine(void *arg) +{ + sine_t *sine = arg; + value_t res; + + res.f = sin((sine->phase * 2 * M_PI) / sine->max_phase - M_PI); + res.f *= generator_scale; + if (format != SND_PCM_FORMAT_FLOAT_LE) + res.i = res.f * INT32_MAX; + sine->phase += sine->step; + if (sine->phase >= sine->max_phase) + sine->phase -= sine->max_phase; + return res; +} + +/* Pink noise is a better test than sine wave because we can tell + * where pink noise is coming from more easily that a sine wave. + */ +static value_t generate_pink_noise(void *arg) +{ + pink_noise_t *pink = arg; + value_t res; + + res.f = generate_pink_noise_sample(pink) * generator_scale; + if (format != SND_PCM_FORMAT_FLOAT_LE) + res.i = res.f * INT32_MAX; + return res; +} + /* * useful for tests */ -static void generate_pattern(uint8_t *frames, int channel, int count, int *_pattern) { - int pattern = *_pattern; - int chn; - int8_t *samp8 = (int8_t*) frames; - int16_t *samp16 = (int16_t*) frames; - int32_t *samp32 = (int32_t*) frames; - float *samp_f = (float*) frames; +static value_t generate_pattern(void *arg) +{ + value_t res; - while (count-- > 0) { - for(chn=0;chn