Renamed directory "dev" to "dev_tools". Replaced the ecasound-2.7.2 with a new download of ecasound. The reason is that the previous ecasound directory had all the Makefiles checked in with hardcoded paths from Naomi's computer. This prevented anyone else from being able to build. I copied over the modified version of ecacontrol.py.
593 lines
17 KiB
C++
593 lines
17 KiB
C++
// ------------------------------------------------------------------------
|
|
// ecasignalview.cpp: A simple command-line tools for monitoring
|
|
// signal amplitude.
|
|
// Copyright (C) 1999-2005,2007,2008 Kai Vehmanen
|
|
// Copyright (C) 2005 Jeffrey Cunningham
|
|
//
|
|
// 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
|
|
// ------------------------------------------------------------------------
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <cassert>
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#include <sys/time.h> /* POSIX: select() */
|
|
#include <sys/select.h> /* POSIX: timeval struct */
|
|
|
|
#include <kvutils/kvu_com_line.h>
|
|
#include <kvutils/kvu_utils.h>
|
|
#include <kvutils/kvu_numtostr.h>
|
|
|
|
#include <eca-control-interface.h>
|
|
|
|
#include "ecicpp_helpers.h"
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
/* see: http://www.opengroup.org/onlinepubs/007908799/xsh/termios.h.html */
|
|
#include <termios.h>
|
|
#endif
|
|
|
|
#if defined(ECA_USE_NCURSES_H) || defined(ECA_USE_NCURSES_NCURSES_H) || defined(ECA_USE_CURSES_H)
|
|
#define ECASV_USE_CURSES 1
|
|
|
|
#ifdef ECA_USE_NCURSES_H
|
|
#include <ncurses.h>
|
|
#include <term.h> /* for setupterm() */
|
|
#elif ECA_USE_NCURSES_NCURSES_H
|
|
#include <ncurses/ncurses.h>
|
|
#include <ncurses/term.h> /* for setupterm() */
|
|
#else
|
|
#include <curses.h>
|
|
#include <term.h> /* for setupterm() */
|
|
#endif
|
|
|
|
#endif /* ECA_*CURSES_H */
|
|
|
|
#include <cstring>
|
|
|
|
/**
|
|
* Import namespaces
|
|
*/
|
|
|
|
using namespace std;
|
|
|
|
/**
|
|
* Type definitions
|
|
*/
|
|
|
|
struct ecasv_channel_stats {
|
|
double last_peak;
|
|
double drawn_peak;
|
|
double max_peak;
|
|
long int clipped_samples;
|
|
vector<double> avg_peak; // jkc: addition
|
|
int avg_peak_ptr; // jkc: addition
|
|
double avg_peak_val; // jkc: addition
|
|
};
|
|
|
|
/**
|
|
* Function declarations
|
|
*/
|
|
|
|
int main(int argc, char *argv[]);
|
|
void ecasv_parse_command_line(ECA_CONTROL_INTERFACE* cop, int argc, char *argv[]);
|
|
void ecasv_fill_defaults(void);
|
|
std::string ecasv_cop_to_string(ECA_CONTROL_INTERFACE* cop);
|
|
void ecasv_output_init(void);
|
|
void ecasv_output_cleanup(void);
|
|
int ecasv_print_vu_meters(ECA_CONTROL_INTERFACE* eci,
|
|
std::vector<struct ecasv_channel_stats>* chstats);
|
|
void ecasv_update_chstats(std::vector<struct ecasv_channel_stats>* chstats,
|
|
int ch, double value);
|
|
void ecasv_create_bar(double value, int barlen, unsigned char* barbuf);
|
|
void ecasv_print_usage(void);
|
|
void ecasv_signal_handler(int signum);
|
|
void reset_stats_fcn(vector<struct ecasv_channel_stats>* chstats); // jkc: addition
|
|
float dB(float v) { return 10.0*log10(v*v); } // jkc: addition
|
|
void ecasv_set_buffered(void);
|
|
void ecasv_set_unbuffered(void);
|
|
int ecasv_kbhit();
|
|
|
|
/**
|
|
* Static global variables
|
|
*/
|
|
|
|
static const string ecatools_signalview_version = "20051112-10";
|
|
static bool ecasv_log_display_mode = false; // jkc: addition
|
|
static const double ecasv_clipped_threshold_const = 1.0f - 1.0f / 16384.0f;
|
|
static const int ecasv_bar_length_const = 32;
|
|
static const int ecasv_header_height_const = 9;
|
|
static const long int ecasv_rate_default_const = 50;
|
|
static const long int ecasv_buffersize_default_const = 128;
|
|
|
|
static unsigned char ecasv_bar_buffer[ecasv_bar_length_const + 1] = { 0 };
|
|
static bool ecasv_enable_debug, ecasv_enable_cumulative_mode;
|
|
static long int ecasv_buffersize, ecasv_rate_msec;
|
|
static string ecasv_input, ecasv_output, ecasv_format_string;
|
|
static int ecasv_chcount = 0;
|
|
|
|
static ECA_CONTROL_INTERFACE* ecasv_eci_repp = 0;
|
|
|
|
static sig_atomic_t done = 0;
|
|
static sig_atomic_t reset_stats = 0;
|
|
static int avg_peak_buffer_sz=100; // jkc: addition
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
struct termios old_term, new_term;
|
|
#endif
|
|
|
|
/**
|
|
* Function definitions
|
|
*/
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int res;
|
|
struct sigaction es_handler;
|
|
es_handler.sa_handler = ecasv_signal_handler;
|
|
sigemptyset(&es_handler.sa_mask);
|
|
es_handler.sa_flags = 0;
|
|
|
|
sigaction(SIGTERM, &es_handler, 0);
|
|
sigaction(SIGINT, &es_handler, 0);
|
|
sigaction(SIGQUIT, &es_handler, 0);
|
|
sigaction(SIGABRT, &es_handler, 0);
|
|
sigaction(SIGHUP, &es_handler, 0);
|
|
|
|
struct sigaction ign_handler;
|
|
ign_handler.sa_handler = SIG_IGN;
|
|
sigemptyset(&ign_handler.sa_mask);
|
|
ign_handler.sa_flags = 0;
|
|
|
|
/* ignore the following signals */
|
|
sigaction(SIGPIPE, &ign_handler, 0);
|
|
sigaction(SIGFPE, &ign_handler, 0);
|
|
|
|
ECA_CONTROL_INTERFACE eci;
|
|
|
|
eci.command("cs-add default");
|
|
eci.command("c-add default");
|
|
|
|
/* set engine buffersize */
|
|
eci.command("cs-set-param -b:" + kvu_numtostr(ecasv_buffersize));
|
|
/* in case JACK is used, do not send nor receive transport events */
|
|
eci.command("cs-set-param -G:jack,ecasignalview,notransport");
|
|
|
|
/* note: might change the cs options (-G, -z, etc) */
|
|
ecasv_parse_command_line(&eci,argc,argv);
|
|
|
|
if (ecasv_format_string.size() > 0) {
|
|
eci.command("cs-set-audio-format " + ecasv_format_string);
|
|
}
|
|
|
|
string format;
|
|
if (ecicpp_add_input(&eci, ecasv_input, &format) < 0) return -1;
|
|
|
|
cout << "Using audio format -f:" << format << "\n";
|
|
|
|
ecasv_chcount = ecicpp_format_channels(format);
|
|
cout << "Setting up " << ecasv_chcount << " separate channels for analysis." << endl;
|
|
|
|
if (ecicpp_add_output(&eci, ecasv_output, format) < 0) return -1;
|
|
|
|
ecasv_eci_repp = &eci;
|
|
|
|
vector<struct ecasv_channel_stats> chstats;
|
|
|
|
eci.command("cop-add -evp");
|
|
eci.command("cop-add -ev");
|
|
if (ecasv_enable_cumulative_mode == true) {
|
|
eci.command("cop-set 2,1,1");
|
|
}
|
|
|
|
eci.command("cop-select 1");
|
|
|
|
if (ecicpp_connect_chainsetup(&eci, "default") < 0) {
|
|
return -1;
|
|
}
|
|
|
|
int secs = 0, msecs = ecasv_rate_msec;
|
|
while(msecs > 999) {
|
|
++secs;
|
|
msecs -= 1000;
|
|
}
|
|
|
|
ecasv_output_init();
|
|
|
|
eci.command("start");
|
|
|
|
int chr=0; // jkc: addition
|
|
int rv=0; // jkc: addition
|
|
while(! done ) {
|
|
kvu_sleep(secs, msecs * 1000000);
|
|
res = ecasv_print_vu_meters(&eci, &chstats);
|
|
if (res < 0)
|
|
break;
|
|
|
|
#if defined(ECASV_USE_CURSES)
|
|
// jkc: addition until noted
|
|
if (ecasv_kbhit()) {
|
|
/* note: getch() is a curses.h function */
|
|
switch (chr=getch()) {
|
|
case 'q':
|
|
case 27: /* Esc */
|
|
case 'Q':
|
|
done=true;
|
|
break;
|
|
case ' ':
|
|
reset_stats_fcn(&chstats);
|
|
break;
|
|
}
|
|
}
|
|
// jkc: end of addition
|
|
#endif
|
|
}
|
|
|
|
ecasv_output_cleanup();
|
|
#ifdef ECASV_USE_CURSES
|
|
endwin();
|
|
#endif
|
|
|
|
return rv;
|
|
}
|
|
|
|
void ecasv_parse_command_line(ECA_CONTROL_INTERFACE *eci, int argc, char *argv[])
|
|
{
|
|
COMMAND_LINE cline = COMMAND_LINE (argc, argv);
|
|
if (cline.size() == 0 ||
|
|
cline.has("--version") ||
|
|
cline.has("--help") ||
|
|
cline.has("-h")) {
|
|
ecasv_print_usage();
|
|
exit(1);
|
|
}
|
|
|
|
ecasv_enable_debug = false;
|
|
ecasv_enable_cumulative_mode = false;
|
|
ecasv_rate_msec = 0;
|
|
ecasv_buffersize = 0;
|
|
|
|
cline.begin();
|
|
cline.next(); // 1st argument
|
|
while (cline.end() != true) {
|
|
string arg = cline.current();
|
|
if (arg.size() > 0) {
|
|
if (arg[0] != '-') {
|
|
if (ecasv_input == "")
|
|
ecasv_input = arg;
|
|
else
|
|
if (ecasv_output == "")
|
|
ecasv_output = arg;
|
|
}
|
|
else {
|
|
string prefix = kvu_get_argument_prefix(arg);
|
|
if (prefix == "b")
|
|
ecasv_buffersize = atol(kvu_get_argument_number(1, arg).c_str());
|
|
if (prefix == "c") ecasv_enable_cumulative_mode = true;
|
|
if (prefix == "d") ecasv_enable_debug = true;
|
|
if (prefix == "f")
|
|
ecasv_format_string = string(arg.begin() + 3, arg.end());
|
|
if (prefix == "I") ecasv_log_display_mode = false; // jkc: addition
|
|
if (prefix == "L") ecasv_log_display_mode = true; // jkc: addition
|
|
if (prefix == "r")
|
|
ecasv_rate_msec = atol(kvu_get_argument_number(1, arg).c_str());
|
|
if (prefix == "G" ||
|
|
prefix == "B" ||
|
|
(prefix.size() > 0 && prefix[0] == 'M') ||
|
|
prefix == "r" ||
|
|
prefix == "z") {
|
|
eci->command("cs-option " + arg);
|
|
}
|
|
}
|
|
}
|
|
cline.next();
|
|
}
|
|
|
|
ecasv_fill_defaults();
|
|
}
|
|
|
|
void ecasv_fill_defaults(void)
|
|
{
|
|
// ECA_RESOURCES ecarc;
|
|
|
|
if (ecasv_input.size() == 0) ecasv_input = "/dev/dsp";
|
|
if (ecasv_output.size() == 0) ecasv_output = "null";
|
|
if (ecasv_buffersize == 0) ecasv_buffersize = ecasv_buffersize_default_const;
|
|
if (ecasv_rate_msec == 0) ecasv_rate_msec = ecasv_rate_default_const;
|
|
if (ecasv_format_string.size() == 0) ecasv_format_string = "s16_le,2,44100,i";
|
|
|
|
// ecarc.resource("default-audio-format");
|
|
}
|
|
|
|
string ecasv_cop_to_string(ECA_CONTROL_INTERFACE* eci)
|
|
{
|
|
eci->command("cop-status");
|
|
return(eci->last_string());
|
|
}
|
|
|
|
void ecasv_output_init(void)
|
|
{
|
|
#ifdef ECASV_USE_CURSES
|
|
initscr();
|
|
erase();
|
|
int r=0; // jkc: added r for row indexing here and below
|
|
mvprintw(r++, 0, "ecasignalview v%s (%s) -- (C) K.Vehmanen, J.Cunningham", ecatools_signalview_version.c_str(), VERSION);
|
|
//mvprintw(r++, 0, "* (C) 1999-2005 Kai Vehmanen, Jeff Cunningham *\n");
|
|
//mvprintw(r++, 0, "******************************************************\n\n");
|
|
|
|
++r;
|
|
mvprintw(r++, 2, "Input/output: \"%s\" => \"%s\"",
|
|
ecasv_input.c_str(),ecasv_output.c_str());
|
|
double avg_length = (double)ecasv_rate_msec * avg_peak_buffer_sz;
|
|
mvprintw(r++, 2,
|
|
"Settings: %s refresh=%ldms bsize=%ld avg-length=%.0fms",
|
|
ecasv_format_string.c_str(), ecasv_rate_msec, ecasv_buffersize, avg_length);
|
|
/* mvprintw(r++, 0, "refresh rate = %ld (msec), buffer size = %ld, "
|
|
"avg-length = %.0f (msec)",
|
|
ecasv_rate_msec, ecasv_buffersize, avg_length); */
|
|
++r;
|
|
const char* bar="------------------------------------------------------------------------------\n";
|
|
mvprintw(r++, 0, bar);
|
|
mvprintw(r, 0, "channel");
|
|
if (ecasv_log_display_mode)
|
|
mvprintw(r++,38, "%s avg-peak dB max-peak dB clipped\n", ecasv_bar_buffer);
|
|
else
|
|
mvprintw(r++,38, "%s avg-peak max-peak clipped\n", ecasv_bar_buffer);
|
|
mvprintw(r++, 0, bar);
|
|
|
|
memset(ecasv_bar_buffer, ' ', ecasv_bar_length_const - 4);
|
|
ecasv_bar_buffer[ecasv_bar_length_const - 4] = 0;
|
|
mvprintw(r + ecasv_chcount + 3, 0, "Press spacebar to reset stats"); // jkc: addition
|
|
move(r + ecasv_chcount - 2, 0);
|
|
|
|
// 13 + 12
|
|
|
|
refresh();
|
|
#endif
|
|
}
|
|
|
|
void ecasv_output_cleanup(void)
|
|
{
|
|
#ifdef ECASV_USE_CURSES
|
|
endwin();
|
|
#endif
|
|
|
|
// FIXME: should be enabled
|
|
#if 0
|
|
if (ecasv_eci_repp != 0) {
|
|
cout << endl << endl << endl;
|
|
ecasv_eci_repp->command("cop-status");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// jkc: addition of reset_stats function
|
|
void reset_stats_fcn(vector<struct ecasv_channel_stats>* chstats)
|
|
{
|
|
#ifdef ECASV_USE_CURSES
|
|
vector<struct ecasv_channel_stats>::iterator s=chstats->begin();
|
|
while (s!=chstats->end()) {
|
|
s->last_peak=0;
|
|
s->max_peak=0;
|
|
s->drawn_peak=0;
|
|
s->clipped_samples=0;
|
|
s++;
|
|
}
|
|
#endif
|
|
}
|
|
// jkc: end of addition
|
|
|
|
int ecasv_print_vu_meters(ECA_CONTROL_INTERFACE* eci, vector<struct ecasv_channel_stats>* chstats)
|
|
{
|
|
int result = 0;
|
|
|
|
/* check wheter to reset peaks */
|
|
if (reset_stats) {
|
|
reset_stats = 0;
|
|
for(int n = 0; n < ecasv_chcount; n++) {
|
|
(*chstats)[n].max_peak = 0;
|
|
(*chstats)[n].clipped_samples = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef ECASV_USE_CURSES
|
|
for(int n = 0; n < ecasv_chcount; n++) {
|
|
eci->command("copp-select " + kvu_numtostr(n + 1));
|
|
eci->command("copp-get");
|
|
|
|
if (eci->error()) {
|
|
result = -1;
|
|
break;
|
|
}
|
|
|
|
double value = eci->last_float();
|
|
|
|
ecasv_update_chstats(chstats, n, value);
|
|
|
|
ecasv_create_bar((*chstats)[n].drawn_peak, ecasv_bar_length_const, ecasv_bar_buffer);
|
|
// jkc: commented out following two lines and substituted what follows until noted
|
|
// mvprintw(ecasv_header_height_const+n, 0, "Ch-%02d: %s| %.5f %ld\n",
|
|
// n + 1, ecasv_bar_buffer, (*chstats)[n].max_peak, (*chstats)[n].clipped_samples);
|
|
// Calculate average peak value
|
|
|
|
if (ecasv_log_display_mode)
|
|
mvprintw(ecasv_header_height_const+n, 0,
|
|
"Ch-%02d: %s %.2f %.2f %ld\n",
|
|
n+1, ecasv_bar_buffer,
|
|
dB((*chstats)[n].avg_peak_val),
|
|
dB((*chstats)[n].max_peak),
|
|
(*chstats)[n].clipped_samples);
|
|
else
|
|
mvprintw(ecasv_header_height_const+n, 0,
|
|
"Ch-%02d: %s %.5f %.5f %ld\n",
|
|
n+1, ecasv_bar_buffer,
|
|
(*chstats)[n].avg_peak_val,
|
|
(*chstats)[n].max_peak,
|
|
(*chstats)[n].clipped_samples);
|
|
// jkc: end of substitution
|
|
}
|
|
move(ecasv_header_height_const + 2 + ecasv_chcount, 0);
|
|
refresh();
|
|
#else
|
|
cout << ecasv_cop_to_string(eci) << endl;
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
void ecasv_update_chstats(vector<struct ecasv_channel_stats>* chstats, int ch, double value)
|
|
{
|
|
/* 1. in case a new channel is encoutered */
|
|
if (static_cast<int>(chstats->size()) <= ch) {
|
|
chstats->resize(ch + 1);
|
|
// jkc: added until noted
|
|
(*chstats)[ch].last_peak=0;
|
|
(*chstats)[ch].drawn_peak=0;
|
|
(*chstats)[ch].max_peak=0;
|
|
(*chstats)[ch].clipped_samples=0;
|
|
(*chstats)[ch].avg_peak.resize(avg_peak_buffer_sz,0);
|
|
(*chstats)[ch].avg_peak_ptr=0;
|
|
// jkc: end of additions
|
|
}
|
|
|
|
/* 2. update last_peak and drawn_peak */
|
|
(*chstats)[ch].last_peak = value;
|
|
if ((*chstats)[ch].last_peak < (*chstats)[ch].drawn_peak) {
|
|
(*chstats)[ch].drawn_peak *= ((*chstats)[ch].last_peak / (*chstats)[ch].drawn_peak);
|
|
}
|
|
else {
|
|
(*chstats)[ch].drawn_peak = (*chstats)[ch].last_peak;
|
|
}
|
|
|
|
/* 3. update max_peak */
|
|
if (value > (*chstats)[ch].max_peak) {
|
|
(*chstats)[ch].max_peak = value;
|
|
}
|
|
|
|
/* 4. update clipped_samples counter */
|
|
if (value > ecasv_clipped_threshold_const) {
|
|
(*chstats)[ch].clipped_samples++;
|
|
}
|
|
|
|
// jkc: added until noted
|
|
/* 5. update running average vector */
|
|
(*chstats)[ch].avg_peak[(*chstats)[ch].avg_peak_ptr] = value;
|
|
(*chstats)[ch].avg_peak_ptr = ((*chstats)[ch].avg_peak_ptr == avg_peak_buffer_sz-1)?
|
|
0 : (*chstats)[ch].avg_peak_ptr+1;
|
|
vector<double>::iterator p=(*chstats)[ch].avg_peak.begin();
|
|
(*chstats)[ch].avg_peak_val=0;
|
|
while (p!=(*chstats)[ch].avg_peak.end()) { (*chstats)[ch].avg_peak_val+=*p++; }
|
|
(*chstats)[ch].avg_peak_val/=avg_peak_buffer_sz;
|
|
// jkc; end of addition
|
|
}
|
|
|
|
void ecasv_create_bar(double value, int barlen, unsigned char* barbuf)
|
|
{
|
|
int curlen = static_cast<int>(rint(((value / 1.0f) * barlen)));
|
|
for(int n = 0; n < barlen; n++) {
|
|
if (n <= curlen)
|
|
barbuf[n] = '*';
|
|
else
|
|
barbuf[n] = ' ';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets terminal to unbuffered mode (no echo,
|
|
* non-canonical input). -jkc
|
|
*/
|
|
void ecasv_set_unbuffered(void)
|
|
{
|
|
#ifdef HAVE_TERMIOS_H
|
|
tcgetattr( STDIN_FILENO, &old_term );
|
|
new_term = old_term;
|
|
new_term.c_lflag &= ~( ICANON | ECHO );
|
|
tcsetattr( STDIN_FILENO, TCSANOW, &new_term );
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Sets terminal to buffered mode -jkc
|
|
*/
|
|
void ecasv_set_buffered(void)
|
|
{
|
|
#ifdef HAVE_TERMIOS_H
|
|
tcsetattr( STDIN_FILENO, TCSANOW, &old_term );
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Reads a character from the terminal console. -jkc
|
|
*/
|
|
int ecasv_kbhit(void)
|
|
{
|
|
int result;
|
|
fd_set set;
|
|
struct timeval tv;
|
|
|
|
FD_ZERO(&set);
|
|
FD_SET(STDIN_FILENO,&set); /* watch stdin */
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = 0; /* don't wait */
|
|
|
|
/* quick peek at the input, to see if anything is there */
|
|
ecasv_set_unbuffered();
|
|
result = select( STDIN_FILENO+1,&set,NULL,NULL,&tv);
|
|
ecasv_set_buffered();
|
|
|
|
return result == 1;
|
|
}
|
|
|
|
void ecasv_print_usage(void)
|
|
{
|
|
cerr << "****************************************************************************\n";
|
|
cerr << "* ecasignalview, v" << ecatools_signalview_version << " (" << VERSION << ")\n";
|
|
cerr << "* Copyright 1999-2005 Kai Vehmanen, Jeffrey Cunningham\n";
|
|
cerr << "* Licensed under the terms of the GNU General Public License\n";
|
|
cerr << "****************************************************************************\n";
|
|
|
|
cerr << "\nUSAGE: ecasignalview [options] [input] [output] \n";
|
|
cerr << "\nOptions:\n";
|
|
cerr << "\t-b:buffersize\n";
|
|
// cerr << "\t\t-c (cumulative mode)\n";
|
|
cerr << "\t-d (debug mode)\n";
|
|
cerr << "\t-f:bits,channels,samplerate\n";
|
|
cerr << "\t-r:refresh_msec\n\n";
|
|
cerr << "\t-I (linear-scale)\n";
|
|
cerr << "\t-L (logarithmic-scale)\n";
|
|
}
|
|
|
|
void ecasv_signal_handler(int signum)
|
|
{
|
|
if (signum == SIGHUP) {
|
|
reset_stats = 1;
|
|
}
|
|
else {
|
|
cerr << "Interrupted... cleaning up.\n";
|
|
done=1;
|
|
}
|
|
}
|