summaryrefslogtreecommitdiff
path: root/examples/power.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/power.c')
-rw-r--r--examples/power.c220
1 files changed, 220 insertions, 0 deletions
diff --git a/examples/power.c b/examples/power.c
new file mode 100644
index 0000000..01bfe5d
--- /dev/null
+++ b/examples/power.c
@@ -0,0 +1,220 @@
+/*
+ This program is derived from Chris Vaill's normalize program
+ and has been modified to use the Audio File Library for file
+ reading and audio data conversion.
+
+ Copyright (C) 2001, Silicon Graphics, Inc.
+ Copyright (C) 1999-2001, Chris Vaill
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be
+ useful, but WITHOUT ANY WARRANTY; without even the implied
+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307, USA.
+*/
+
+/*
+ power.c
+
+ Calculate the power and peak amplitudes of an audio file.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <audiofile.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+struct smooth
+{
+ double *buf;
+ int length, start, n;
+};
+
+static double get_smoothed_data (struct smooth *s)
+{
+ int i;
+ double smoothed;
+
+ smoothed = 0;
+ for (i = 0; i < s->n; i++)
+ smoothed += s->buf[i];
+ smoothed = smoothed / s->n;
+
+ return smoothed;
+}
+
+void print_power (char *filename);
+
+int main (int argc, char **argv)
+{
+ int i;
+
+ if (argc < 2)
+ {
+ fprintf(stderr, "usage: %s filename [more filenames...]\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ for (i=1; i<argc; i++)
+ print_power(argv[i]);
+
+ return 0;
+}
+
+void print_power (char *filename)
+{
+ AFfilehandle file;
+ double *sums, *frames;
+ int channelCount, windowSize, frameCount;
+ int i, c;
+ struct smooth *powsmooth;
+ int winStart, winEnd;
+ int lastWindow = FALSE;
+ double pow, maxpow;
+
+ double level, peak, minSample = 1, maxSample = -1;
+
+ file = afOpenFile(filename, "r", NULL);
+ if (file == AF_NULL_FILEHANDLE)
+ {
+ fprintf(stderr, "Could not open file %s.\n", filename);
+ return;
+ }
+
+ channelCount = afGetChannels(file, AF_DEFAULT_TRACK);
+ windowSize = afGetRate(file, AF_DEFAULT_TRACK) / 100;
+ frameCount = afGetFrameCount(file, AF_DEFAULT_TRACK);
+
+ sums = calloc(channelCount, sizeof (double));
+ for (c=0; c<channelCount; c++)
+ sums[c] = 0;
+
+ frames = calloc(channelCount * windowSize, sizeof (double));
+
+ afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, AF_SAMPFMT_DOUBLE,
+ sizeof (double));
+
+ powsmooth = calloc(channelCount, sizeof (struct smooth));
+ for (c=0; c<channelCount; c++)
+ {
+ /* Use a 100-element (1 second) window. */
+ powsmooth[c].length = 100;
+ powsmooth[c].buf = calloc(powsmooth[c].length, sizeof (double));
+ powsmooth[c].start = 0;
+ powsmooth[c].n = 0;
+ }
+
+ winStart = 0;
+ winEnd = 0;
+ lastWindow = FALSE;
+ maxpow = 0;
+
+ do
+ {
+ winEnd = winStart + windowSize;
+
+ if (winEnd >= frameCount)
+ {
+ winEnd = frameCount;
+ lastWindow = TRUE;
+ }
+
+ afReadFrames(file, AF_DEFAULT_TRACK, frames, windowSize);
+
+ for (c=0; c<channelCount; c++)
+ {
+ sums[c] = 0;
+
+ for (i=0; i < winEnd - winStart; i++)
+ {
+ double sample;
+
+ sample = frames[i*channelCount + c];
+ sums[c] += sample*sample;
+
+ if (sample > maxSample)
+ maxSample = sample;
+ if (sample < minSample)
+ minSample = sample;
+ }
+ }
+
+ /* Compute power for each channel. */
+ for (c=0; c<channelCount; c++)
+ {
+ double pow;
+ int end;
+
+ pow = sums[c] / (winEnd - winStart);
+
+ end = (powsmooth[c].start + powsmooth[c].n) %
+ powsmooth[c].length;
+ powsmooth[c].buf[end] = pow;
+
+ if (powsmooth[c].n == powsmooth[c].length)
+ {
+ powsmooth[c].start = (powsmooth[c].start + 1) % powsmooth[c].length;
+ pow = get_smoothed_data(&powsmooth[c]);
+ if (pow > maxpow)
+ maxpow = pow;
+ }
+ else
+ {
+ powsmooth[c].n++;
+ }
+ }
+
+ winStart += windowSize;
+ } while (!lastWindow);
+
+ for (c = 0; c < channelCount; c++)
+ {
+ pow = get_smoothed_data(&powsmooth[c]);
+ if (pow > maxpow)
+ maxpow = pow;
+ }
+
+ free(sums);
+ free(frames);
+ for (c=0; c<channelCount; c++)
+ free(powsmooth[c].buf);
+ free(powsmooth);
+
+ level = sqrt(maxpow);
+
+ afCloseFile(file);
+
+ printf("file: %s\n", filename);
+
+ printf("level (dB): %f\n", 20 * log10(level));
+ printf("peak-: %f\n", minSample);
+ printf("peak+: %f\n", maxSample);
+
+ peak = abs(minSample);
+ if (peak < abs(maxSample))
+ peak = abs(maxSample);
+
+ printf("peak (dB): %f\n", 20 * log10(peak));
+}