Skip to content

Commit

Permalink
chronicle now has a working audio meter and interface! fixes #16
Browse files Browse the repository at this point in the history
  • Loading branch information
calmcl1 committed Feb 28, 2017
1 parent 9fa8afd commit 5fc3735
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 28 deletions.
41 changes: 22 additions & 19 deletions chronicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ void doRecord(boost::filesystem::path directory, string fileNameFormat) {
exit(0);
}

sf_command(mySnd, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);

// Set up signal handling; fixes #1
{
signal(SIGINT, signalHandler);
Expand Down Expand Up @@ -256,7 +258,7 @@ void doRecord(boost::filesystem::path directory, string fileNameFormat) {

try {
updateRecordingToPath(audioFileFullPath.string());
audio.openStream(NULL, &params, RTAUDIO_SINT16, rp.sampleRate, &(rp.bufferLength), &cb_record);
audio.openStream(NULL, &params, RTAUDIO_SINT16, rp.sampleRate, &(rp.bufferLength), &cb_record, &(rp.channelCount));
audio.startStream();
}
catch (RtAudioError &e) {
Expand All @@ -274,6 +276,11 @@ void doRecord(boost::filesystem::path directory, string fileNameFormat) {

int cb_record(void *outputBuffer, void *inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status, void *userData)
{
/* userData is the channel count. */

int* pChannelCount = (int*)userData;
int channelCount = *pChannelCount;

short* data = (short*)inputBuffer;
sf_writef_short(mySnd, data, nFrames);

Expand All @@ -284,6 +291,7 @@ int cb_record(void *outputBuffer, void *inputBuffer, unsigned int nFrames, doubl
The data is cast to a short. sizeof(short) = 2 (bytes) = 16 bits.
Max value in a short is therefore 2^16 -1 = 65535.
However, since the values are read from -1 to +1, the range is halved to 32763.
It is appropriate to assume that a -60dB is sufficient for silence detection. Anything
lower than this is negligible, especially for analogue broadcast.
Expand All @@ -294,36 +302,31 @@ int cb_record(void *outputBuffer, void *inputBuffer, unsigned int nFrames, doubl
-> I_db / 10 = log10(I / I_0)
-> 10^(I_db / 10) = I / I_0
-> I = 10^(I_db / 10) * I_0
-> I = 10^(-60 / 10) * 65535
-> I = 10^(-6) * 65535
-> I = 10^(-60 / 10) * 32763
-> I = 10^(-6) * 32763
-> I = 0.065535
*/
//cout << streamTime << endl;
//if ((long)round(streamTime) % 2 == 0) {
//cout << (long)round(streamTime) << endl;

int maxAudioVal = (pow(2, (sizeof(short) * 8)) - 1);
short maxAudioVal = (pow(2, (sizeof(short) * 8))/2) - 1;
int thresholdDB = -60;
float thresholdVal = (pow(10, thresholdDB / 10))*maxAudioVal;

unsigned int framesSum;
float framesAvg;
for (int i = 0; i < nFrames * 2; i++) {
framesSum += abs((*(data + i)));
short framesPeak=0;

for (int i = 0; i < nFrames * channelCount; i++) {
short val = abs(*(data+i));
framesPeak = max(val, framesPeak);
};

framesAvg = framesSum / nFrames;
float level = log10(framesAvg / maxAudioVal) * 10;
/*cout << "\rLevel: " << level << "dB";
if (framesAvg < threshold) { cout << "silence at "<<streamTime << " (" << framesAvg << ")"; }
cout << flush;*/
float level = log10(float(framesPeak) / float(maxAudioVal)) * 10;
//float level = float(framesPeak)/float(maxAudioVal);
string label = to_string(level) + " dB";

#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
int numberOfEquals = (framesAvg / maxAudioVal) * 60;
cout << "\r|";
cout << setfill('=') << setw(numberOfEquals) << " " << setfill(' ') << setw(63 - numberOfEquals);
cout << "] " << level << " dB" << flush;
#endif
updateAudioMeter(0 ,30, 30-abs(level), label);
//updateAudioMeter(0,maxAudioVal,framesPeak,to_string(level));

return 0;
}
Expand Down
56 changes: 47 additions & 9 deletions screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,31 @@ WINDOW *mainWindow;

int POS_FNAME_X = 2;
int POS_FNAME_Y = 8;

int POS_AUDIO_DEVICE_X;
int POS_AUDIO_DEVICE_Y;
int POS_SAMPLERATE_X;
int POS_SAMPLERATE_Y;
int POS_CHANNELCOUNT_X;
int POS_CHANNELCOUNT_Y;
int POS_STATUSBAR_Y;

int POS_AUDIOMETER_X;
int POS_AUDIOMETER_Y;
int POS_AUDIOMETER_MAXWIDTH;
int POS_AUDIOMETER_LABEL_X;
int POS_AUDIOMETER_LABEL_Y;

void initCurses(string windowTitle)
{
initscr();
cbreak(); // To disable the buffering of typed characters by the TTY driver and get a character-at-a-time input
noecho(); // To suppress the automatic echoing of typed characters
mainWindow = newwin(LINES, COLS, 0, 0);
calculateWindowPositions();
calculateWindowPositions();

/* Add the border and window title */
wborder(mainWindow, 0, 0, 0, 0, 0, 0, 0, 0);

string paddedWindowTitle = " " + windowTitle + " ";
wmove(mainWindow, 0, (COLS - paddedWindowTitle.length()) / 2);
wmove(mainWindow, 0, (COLS - paddedWindowTitle.length()) / 2);
wprintw(mainWindow, paddedWindowTitle.c_str());

/* Draw the horizontal line above the 'status bar' */
Expand All @@ -45,11 +49,19 @@ void closeCurses()
void calculateWindowPositions()
{
/* Stuff that goes on the status bar */
POS_STATUSBAR_Y = LINES-2;
POS_AUDIO_DEVICE_X = 1;
POS_STATUSBAR_Y = LINES - 2;

POS_AUDIO_DEVICE_X = 1;
POS_CHANNELCOUNT_X = COLS - 14;
POS_SAMPLERATE_X = POS_CHANNELCOUNT_X - 14;

/* Recording audio meter */
POS_AUDIOMETER_X = POS_FNAME_X;
POS_AUDIOMETER_Y = POS_FNAME_Y + 2;
POS_AUDIOMETER_MAXWIDTH = COLS - POS_AUDIOMETER_X - 15;

POS_AUDIOMETER_LABEL_X = POS_AUDIOMETER_X + 60;
POS_AUDIOMETER_LABEL_Y = POS_AUDIOMETER_Y;
}

void updateRecordingToPath(string filePath)
Expand All @@ -63,17 +75,43 @@ void updateRecordingToPath(string filePath)

void updateAudioDevice(string audioDevice, int sampleRate, int channelCount)
{
/* Draw audio device name */
wmove(mainWindow, POS_STATUSBAR_Y, POS_AUDIO_DEVICE_X);
wprintw(mainWindow, audioDevice.c_str());
wrefresh(mainWindow);
wrefresh(mainWindow);

/* Draw sample rate */
wmove(mainWindow, POS_STATUSBAR_Y, POS_SAMPLERATE_X);
string sampleRateStr = to_string(sampleRate) + " Hz";
wprintw(mainWindow, sampleRateStr.c_str());

/* Draw channel count */
wmove(mainWindow, POS_STATUSBAR_Y, POS_CHANNELCOUNT_X);
string channelCountStr = to_string(channelCount) + " Channels";
wprintw(mainWindow, channelCountStr.c_str());

wrefresh(mainWindow);
}

void updateAudioMeter(int minVal, int maxVal, int currentVal, string volumeLabel)
{
wmove(mainWindow, POS_AUDIOMETER_Y, POS_AUDIOMETER_X);
wprintw(mainWindow, "| ");

float range = (maxVal-minVal);
float proportion = currentVal / range;
int barWidth = (POS_AUDIOMETER_MAXWIDTH - 3) * proportion;

whline(mainWindow, '=', barWidth);
wmove(mainWindow, POS_AUDIOMETER_Y, barWidth);
whline(mainWindow, ' ', POS_AUDIOMETER_MAXWIDTH - barWidth - 3);

wmove(mainWindow, POS_AUDIOMETER_Y, POS_AUDIOMETER_MAXWIDTH - 1);
wprintw(mainWindow, "| ");
wprintw(mainWindow, volumeLabel.c_str());
//wprintw(mainWindow, currentVal);
//wprintw(mainWindow, to_string(proportion).c_str());
wprintw(mainWindow," ");

wrefresh(mainWindow);
}
3 changes: 3 additions & 0 deletions screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ void calculateWindowPositions();

void updateRecordingToPath(string filePath);
void updateAudioDevice(string audioDevice, int sampleRate, int channelCount);
//void updateAudioMeter(float minVal, float maxVal, float currentVal, string volumeLabel);
//void updateAudioMeter(short minVal, short maxVal, short currentVal, string volumeLabel);
void updateAudioMeter(int minVal, int maxVal, int currentVal, string volumeLabel);

#endif //__SCREEN_H__

0 comments on commit 5fc3735

Please sign in to comment.