From eda0fbdaaa8b04dc10909485f9a794bee99b2ffb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 Apr 2009 00:53:36 +0200 Subject: Finish the code --- dbmeasure.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 14 deletions(-) diff --git a/dbmeasure.c b/dbmeasure.c index f9140c8..2c40e9d 100644 --- a/dbmeasure.c +++ b/dbmeasure.c @@ -108,27 +108,50 @@ static double compute_level(const float *buffer, float *sum, unsigned n_samples, for (i = 0; i < n_samples; i++) { sum[i] += buffer[i]; - if (sum[i] > max) - max = sum[i]; + if (fabs(sum[i]) > max) + max = fabs(sum[i]); } return max / (double) iteration; } +static int prompt(const char *t) { + char r[64]; + fputs(t, stderr); + + if (!fgets(r, sizeof(r), stdin)) + return 0; + + return 1; +} + +static double linear_to_dB(double f) { + return 20.0 * log10(f); +} + int main(int argc, char *argv[]) { int ret = 1; - float *signal = NULL, *silence = NULL, *buffer = NULL, *sum = NULL; + float *signal = NULL, *silence = NULL, *buffer = NULL, *sum = NULL, *current = NULL; snd_pcm_t *input = NULL, *output = NULL; unsigned rate = 44100; unsigned rindex = 0, windex = 0; - double frequency = 440.0, amplitude = 0.5; + double frequency = 440.0, amplitude = 0.5, noise_level_dB = -80.0, initial_level_max = 0.97, initial_level_min = 0.8, reference_level; unsigned iteration = 0; int icount, ocount; struct pollfd *pollfd; int e; + unsigned needed_iterations = 0; + int skip = 1; + FILE *log; + int level_count = 0; + + if (argc < 3) { + fprintf(stderr, "Need to specify device and output log file.\n"); + goto finish; + } - if (argc < 2) { - fprintf(stderr, "Need to specify device.\n"); + if (!(log = fopen(argv[2], "w"))) { + fprintf(stderr, "Failed to open log file %s: %s\n", argv[2], strerror(errno)); goto finish; } @@ -180,6 +203,12 @@ int main(int argc, char *argv[]) { goto finish; } + current = silence; + + prompt("Please set your control to the highest volume possible and press return.\n"); + + fprintf(stderr, "Measuring noise level.\n"); + for (;;) { snd_pcm_sframes_t n; unsigned short irevents, orevents; @@ -202,9 +231,9 @@ int main(int argc, char *argv[]) { } if (orevents) { - if ((n = snd_pcm_writei(output, signal + windex, rate - windex)) < 0) { + if ((n = snd_pcm_writei(output, current + windex, rate - windex)) < 0) { - if (snd_pcm_recover(output, n, 0) < 0) { + if (snd_pcm_recover(output, n, 1) < 0) { fprintf(stderr, "Cannot write samples: %s\n", snd_strerror(n)); goto finish; } else @@ -220,7 +249,7 @@ int main(int argc, char *argv[]) { if (irevents) { if ((n = snd_pcm_readi(input, buffer + rindex, rate - rindex)) < 0) { - if (snd_pcm_recover(input, n, 0) < 0) { + if (snd_pcm_recover(input, n, 1) < 0) { fprintf(stderr, "Cannot read samples: %s\n", snd_strerror(n)); goto finish; } @@ -235,13 +264,67 @@ int main(int argc, char *argv[]) { rindex += n; if (rindex == rate) { - double level; - rindex = 0; - iteration++; - level = compute_level(buffer, sum, rate, iteration); - fprintf(stderr, "Iteration %u, level is %g.\n", iteration, level); + if (skip) + skip = 0; + else { + double level; + + iteration++; + level = compute_level(buffer, sum, rate, iteration); + fprintf(stderr, "Iteration %u, level is %g (%g dB).\n", iteration, level, linear_to_dB(level)); + + if (needed_iterations == 0) { + if (linear_to_dB(level) < noise_level_dB) { + fprintf(stderr, "%u iterations necessary to push noise level below %g dB\n", iteration, noise_level_dB); + + needed_iterations = iteration; + current = signal; + windex = 0; + skip = 1; + iteration = 0; + memset(sum, 0, rate * sizeof(float)); + + fprintf(stderr, "Generating signal.\n"); + } + } else { + + if (iteration >= needed_iterations) { + + if (level_count <= 0) { + + if (level < initial_level_min || + level > initial_level_max) { + fprintf(stderr, + "Volume level measured (%g) was too high or too low.\n" + "Please adjust mixer so that initial level is between %g and %g.\n" + "Test run canceled.\n", level, initial_level_min, initial_level_max); + goto finish; + } + + reference_level = level; + } + + fprintf(log, "%i\t%g\t%g\t%g\t%g\n", + level_count, + level, linear_to_dB(level), + level/reference_level, linear_to_dB(level/reference_level)); + + fflush(log); + + level_count++; + + windex = 0; + skip = 1; + iteration = 0; + memset(sum, 0, rate * sizeof(float)); + + if (!(prompt("Please reduce volume by one step and press return. Press C-D when finished.\n"))) + break; + } + } + } } } } @@ -256,6 +339,9 @@ finish: if (output) snd_pcm_close(output); + if (log) + fclose(log); + free(signal); free(silence); free(buffer); -- cgit