//
// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Creation Date: Tue May 2 05:04:58 PDT 2006 (copied from sndpower)
// Last Modified: Tue May 2 20:11:48 PDT 2006
// Filename: ...soundfile/examples/smoothpower.cpp
// Syntax: C++
//
// Description: Calculate the average signal power for given durations
//
#include "soundfile.h"
#include <stdlib.h>
#include <math.h>
#ifndef OLDCPP
#include <iostream>
#include <iomanip>
using namespace std;
#else
#include <iostream.h>
#include <iomanip.h>
#endif
void printLongSummary(SoundFileRead& soundfile, int totalframes,
int start, int chunk);
double filterk = 0.3; // set with -k option
double smoothq = 1; // set with -S option
int achannel = -1; // set with -c option
int roundq = 1; // set with -R option
int centerq = 1;
const char *comment = ""; // set with --comment option
const char *datestring = ""; // set with -d option
int main(int argc, char** argv) {
Options options;
options.define("a|average=i:441", "Number of samples to average over");
options.define("s|start=i:0", "Starting sample");
options.define("c|channel=i:-1", "Channel to analyze");
options.define("C|no-center=b", "Do not center the timing data");
options.define("d|date=s:", "Date string");
options.define("comment=s:", "Comment string");
options.define("R|no-rounding=b", "Turn off db value rounding");
options.define("S|no-smoothing=b", "Turn off smoothing");
options.define("k|smoothing=d:0.3", "the 1/2 smoothing filter value");
options.define("n|count=i:-1", "Number of analyses to make");
options.define("all=b", "calculate the energy of the entire file");
options.define("q|quiet=b", "suppress printing of header info");
options.process(argc, argv);
if (options.getArgCount() == 0) {
cout << "Usage: " << options.getCommand()
<< " filename"
<< endl;
exit(1);
}
SoundFileRead soundfile(options.getArg(1));
filterk = options.getDouble("smoothing");
smoothq = !options.getBoolean("no-smoothing");
achannel = options.getInteger("channel");
roundq = !options.getBoolean("no-rounding");
centerq = !options.getBoolean("no-center");
if (options.getBoolean("comment")) {
comment = options.getString("comment");
}
if (options.getBoolean("date")) {
datestring = options.getString("date");
}
int chunk = options.getInteger("average");
int start = options.getInteger("start");
int totalframes = options.getInteger("count");
if (totalframes <= 0) {
totalframes = (soundfile.getSamples() - start)/chunk + 1;
}
// print header information
if (!options.getBoolean("quiet")) {
cout << "###Filename:\t\t" << options.getArg(1) << "\n";
cout << "###FrameSize:\t\t" << chunk << " samples; ";
cout << 1000.0 * chunk/soundfile.getSrate() << " milliseconds" << "\n";
cout << "###FrameCount:\t\t" << totalframes << "\n";
if (datestring[0] != '\0') {
cout << "###AnalysisDate:\t" << datestring << "\n";
}
if (comment[0] != '\0') {
cout << "###Comment:\t\t" << comment << "\n";
}
cout << "###Smoothing:\t\t";
if (smoothq) {
cout << filterk;
} else {
cout << 1;
}
cout << "\n";
cout << "###Channel:\t\t";
if (achannel < 0) {
if (soundfile.getChannels() == 1) {
cout << "all (mono)";
} else if (soundfile.getChannels() == 2) {
cout << "all (stereo)";
} else if (soundfile.getChannels() == 4) {
cout << "all (quad)";
} else {
cout << "all";
}
} else {
cout << achannel;
if (achannel == 0) {
cout << " (left)";
} else if (achannel == 1) {
cout << " (right)";
}
}
cout << "\n";
cout << "# time (seconds), dB\n";
}
if (options.getBoolean("all")) {
printLongSummary(soundfile, 1, 0, soundfile.getSamples());
} else {
printLongSummary(soundfile, totalframes, start, chunk);
}
return 0;
}
//////////////////////////////
//
// printLongSummary --
//
void printLongSummary(SoundFileRead& soundfile, int totalframes, int start, int chunk) {
double sum, value, db;
int i, j, channel;
Array<double> dbvalues;
dbvalues.setSize(totalframes);
dbvalues.allowGrowth(0);
for (i=0; i<totalframes; i++) {
sum = 0.0;
for (j=0; j<chunk; j++) {
if (achannel < 0) {
for (channel=0; channel < soundfile.getChannels(); channel++) {
value = soundfile.getCurrentSampleDouble(channel);
sum += value * value;
}
} else {
value = soundfile.getCurrentSampleDouble(achannel);
sum += value * value;
}
soundfile.incrementSample();
}
if (sum == 0.0) {
db = -100;
} else {
db = 10.0 * log10(sum/chunk/soundfile.getChannels());
}
if (!smoothq) {
if (centerq) {
cout << (double)((i+0.5) * chunk)/soundfile.getSrate();
} else {
cout << (double)(i * chunk)/soundfile.getSrate();
}
if (roundq) {
cout << "\t" << ((int)(db * 10.0 + 0.5))/10.0 << "\n";
} else {
cout << "\t" << db << "\n";
}
} else {
dbvalues[i] = db;
}
}
if (!smoothq) {
return;
}
// Difference equation for smoothing: y[n] = k * x[n] + (1-k) * y[n-1]
// do first half of smoothing:
double oneminusk = 1.0 - filterk;
for (i=1; i<totalframes; i++) {
dbvalues[i] = filterk * dbvalues[i] + oneminusk * dbvalues[i-1];
}
// do second half of smoothing:
for (i=totalframes-2; i>=0; i--) {
dbvalues[i] = filterk * dbvalues[i] + oneminusk * dbvalues[i+1];
}
// print results:
for (i=0; i<totalframes; i++) {
cout << (double)(i * chunk)/soundfile.getSrate();
if (roundq) {
cout << "\t" << ((int)(dbvalues[i] * 10.0 + 0.5))/10.0 << "\n";
} else {
cout << "\t" << dbvalues[i] << "\n";
}
}
}
// md5sum: 9df46191f314438a1cc3887e5791c510 smoothpower.cpp [20060701]