From 3dab99a85a9a11277033f416dc719fb588d66f90 Mon Sep 17 00:00:00 2001 From: jthedering <51533355+jthedering@users.noreply.github.com> Date: Tue, 30 Apr 2013 20:07:56 +0000 Subject: [PATCH] Improved: The benchmark application now has a real command line interface. To see the available options, type "Benchmark.exe -h" . --- Benchmark/Benchmark.cpp | 257 ++++++++++++++++++++++-------------- Benchmark/Benchmark.vcxproj | 8 +- LogHelper.cpp | 40 ++++-- LogHelper.h | 4 + ParametricEQ.cpp | 83 ++++++++---- ParametricEQ.h | 3 + 6 files changed, 258 insertions(+), 137 deletions(-) diff --git a/Benchmark/Benchmark.cpp b/Benchmark/Benchmark.cpp index fb2e206..a4dbebf 100644 --- a/Benchmark/Benchmark.cpp +++ b/Benchmark/Benchmark.cpp @@ -22,122 +22,181 @@ #include #include #include +#include +#include "../version.h" #include "../ParametricEQ.h" +#include "../LogHelper.h" +#include "../StringHelper.h" #include "PerformanceCounter.h" using namespace std; -const int BATCH_SIZE = 65536; - int main(int argc, char** argv) { - unsigned sampleRate; - unsigned channelCount; - unsigned channelMask; - unsigned frameCount; - float* buf; - - if(argc >= 2 && strlen(argv[1]) > 0) + try { - SF_INFO info; - printf("Reading sound data from %s\n", argv[1]); - SNDFILE* inFile = sf_open(argv[1], SFM_READ, &info); - if(inFile == NULL) + stringstream versionStream; + versionStream << MAJOR << "." << MINOR; + TCLAP::CmdLine cmd("Benchmark generates a linear sine sweep or reads from the given input file. " + "It then filters the waveform using the Equalizer APO filter configuration " + "and finally writes to the given file or into the user's temp directory.", ' ', versionStream.str()); + + TCLAP::SwitchArg noPauseArg("", "nopause", "Do not wait for key press at the end", cmd); + TCLAP::SwitchArg verboseArg("v", "verbose", "Print trace and error messages to console instead of logfile", cmd); + TCLAP::ValueArg guidArg("", "guid", "Endpoint GUID to use when parsing configuration (Default: )", false, "", "string", cmd); + TCLAP::ValueArg connectionnameArg("", "connectionname", "Connection name to use when parsing configuration (Default: File output)", false, "File output", "string", cmd); + TCLAP::ValueArg devicenameArg("", "devicename", "Device name to use when parsing configuration (Default: Benchmark)", false, "Benchmark", "string", cmd); + TCLAP::ValueArg batchsizeArg("", "batchsize", "Number of frames processed in one batch (Default: 65536)", false, 65536, "integer", cmd); + TCLAP::ValueArg outputArg("o", "output", "File to write sound data to", false, "", "string", cmd); + TCLAP::ValueArg inputArg("i", "input", "File to load sound data from instead of generating sweep", false, "", "string", cmd); + TCLAP::ValueArg rateArg("r", "rate", "Sample rate of generated sweep (Default: 44100)", false, 44100, "integer", cmd); + TCLAP::ValueArg toArg("t", "to", "End frequency of generated sweep in Hz (Default: 20000.0)", false, 20000.0f, "float", cmd); + TCLAP::ValueArg fromArg("f", "from", "Start frequency of generated sweep in Hz (Default: 0.1)", false, 0.1f, "float", cmd); + TCLAP::ValueArg lengthArg("l", "length", "Length of generated sweep in seconds (Default: 200.0)", false, 200.0f, "float", cmd); + TCLAP::ValueArg channelArg("c", "channels", "Number of channels of generated sweep (Default: 2)", false, 2, "integer", cmd); + + cmd.parse(argc, argv); + + LogHelper::set(stderr, verboseArg.getValue(), true); + + unsigned sampleRate; + unsigned channelCount; + unsigned channelMask; + unsigned frameCount; + float length; + float* buf; + + printf("Benchmark %d.%d\n", MAJOR, MINOR); + printf("Run \"%s -h\" to show usage info\n", argv[0]); + printf("\n"); + + string input = inputArg.getValue(); + if(input != "") { - fprintf(stderr, "%s", sf_strerror(inFile)); + SF_INFO info; + printf("Reading sound data from %s\n", input.c_str()); + SNDFILE* inFile = sf_open(input.c_str(), SFM_READ, &info); + if(inFile == NULL) + { + fprintf(stderr, "%s", sf_strerror(inFile)); + return 1; + } + + sampleRate = info.samplerate; + channelCount = info.channels; + channelMask = 0; + frameCount = (unsigned)info.frames; + length = float(frameCount) / sampleRate; + + buf = new float[frameCount * channelCount]; + + sf_count_t numRead = 0; + while(numRead < frameCount) + numRead += sf_readf_float(inFile, buf + numRead * channelCount, frameCount - numRead); + + sf_close(inFile); + inFile = NULL; + } + else + { + sampleRate = rateArg.getValue(); + channelMask = 0; + channelCount = channelArg.getValue(); + float sweepFrom = fromArg.getValue(); + float sweepTo = toArg.getValue(); + float sweepDiff = sweepTo - sweepFrom; + length = lengthArg.getValue(); + frameCount = (unsigned)(length * sampleRate); + + printf("No input file given, so generating linear sine sweep from %g to %g Hz over %g seconds\n", sweepFrom, sweepTo, length); + + buf = new float[frameCount * channelCount]; + + for(unsigned i=0;i max) + max = f; + if(f > 1.0f) + clipCount++; + } + + printf("Max output level: %f (%f dB)", max, log10(max) * 20.0f); + if(clipCount > 0) + printf(" (%d samples clipped!)", clipCount); + printf("\n"); + + string output = outputArg.getValue(); + if(output == "") + { + char temp[255]; + GetTempPathA(sizeof(temp)/sizeof(wchar_t), temp); + + output = temp; + output += "testout.wav"; + } + + printf("\nWriting output to %s\n", output.c_str()); + + SF_INFO info = {frameCount, sampleRate, channelCount, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 0}; + SNDFILE* outFile = sf_open(output.c_str(), SFM_WRITE, &info); + if(outFile == NULL) + { + fprintf(stderr, "%s", sf_strerror(outFile)); return 1; } - sampleRate = info.samplerate; - channelCount = info.channels; - channelMask = 0; - frameCount = (unsigned)info.frames; + sf_count_t numWritten = 0; + while(numWritten < frameCount) + numWritten += sf_writef_float(outFile, buf + numWritten * channelCount, frameCount - numWritten); - buf = new float[frameCount * channelCount]; + sf_close(outFile); + outFile = NULL; - sf_count_t numRead = 0; - while(numRead < frameCount) - numRead += sf_readf_float(inFile, buf + numRead * channelCount, frameCount - numRead); + delete[] buf; - sf_close(inFile); - inFile = NULL; + if(!noPauseArg.getValue()) + system("pause"); + + return 0; } - else + catch(TCLAP::ArgException e) { - sampleRate = 44100; - channelCount = 1; - channelMask = 0; - float sweepFrom = 0.1f; - float sweepTo = 20000; - float sweepDiff = sweepTo - sweepFrom; - float length = 200; - frameCount = (unsigned)(length * sampleRate); - - printf("No input file given, so generating linear sine sweep from %g to %g Hz over %g seconds\n", sweepFrom, sweepTo, length); - - buf = new float[frameCount * channelCount]; - - for(unsigned i=0;i= 3 && strlen(argv[2]) > 0) - outPath = argv[2]; - else - { - char temp[255]; - GetTempPathA(sizeof(temp)/sizeof(wchar_t), temp); - - outPath = temp; - outPath += "testout.wav"; - } - - printf("Writing output to %s\n", outPath.c_str()); - - SF_INFO info = {frameCount, sampleRate, channelCount, SF_FORMAT_WAV | SF_FORMAT_PCM_16, 0}; - SNDFILE* outFile = sf_open(outPath.c_str(), SFM_WRITE, &info); - if(outFile == NULL) - { - fprintf(stderr, "%s", sf_strerror(outFile)); - return 1; - } - - sf_count_t numWritten = 0; - while(numWritten < frameCount) - numWritten += sf_writef_float(outFile, buf + numWritten * channelCount, frameCount - numWritten); - - sf_close(outFile); - outFile = NULL; - - delete[] buf; - - if(argc < 3) - system("pause"); - - return 0; } diff --git a/Benchmark/Benchmark.vcxproj b/Benchmark/Benchmark.vcxproj index 7deb58f..a38752d 100644 --- a/Benchmark/Benchmark.vcxproj +++ b/Benchmark/Benchmark.vcxproj @@ -64,22 +64,22 @@ true - C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\tclap-1.2.1\include;C:\Program Files\libsndfile\include;$(IncludePath) C:\Program Files\libsndfile\lib;$(LibraryPath) true - C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\tclap-1.2.1\include;C:\Program Files\libsndfile\include;$(IncludePath) C:\Program Files\libsndfile\lib;$(LibraryPath) false - C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\tclap-1.2.1\include;C:\Program Files\libsndfile\include;$(IncludePath) C:\Program Files\libsndfile\lib;$(LibraryPath) false - C:\Program Files\libsndfile\include;$(IncludePath) + C:\Program Files\tclap-1.2.1\include;C:\Program Files\libsndfile\include;$(IncludePath) C:\Program Files\libsndfile\lib64;$(LibraryPath) diff --git a/LogHelper.cpp b/LogHelper.cpp index fa7e48e..c8d0736 100644 --- a/LogHelper.cpp +++ b/LogHelper.cpp @@ -18,7 +18,6 @@ */ #include -#include #define WIN32_LEAN_AND_MEAN #include @@ -30,6 +29,8 @@ using namespace std; bool LogHelper::initialized = false; wstring LogHelper::logPath; bool LogHelper::enableTrace = false; +FILE* LogHelper::presetFP = NULL; +bool LogHelper::compact = false; void LogHelper::log(const char* file, int line, void* caller, bool trace, const wchar_t* format, ...) { @@ -59,14 +60,24 @@ void LogHelper::log(const char* file, int line, void* caller, bool trace, const return; FILE* fp; - errno_t err = _wfopen_s(&fp, logPath.c_str(), L"at"); - if(err != 0) - return; + if(presetFP == NULL) + { + errno_t err = _wfopen_s(&fp, logPath.c_str(), L"at"); + if(err != 0) + return; + } + else + { + fp = presetFP; + } - SYSTEMTIME ___st; - GetLocalTime(&___st); - fwprintf(fp, L"%04d-%02d-%02d %02d:%02d:%02d.%03d %08X (%S:%d): ", - ___st.wYear, ___st.wMonth, ___st.wDay, ___st.wHour, ___st.wMinute, ___st.wSecond, ___st.wMilliseconds, caller, file, line); + if(!compact) + { + SYSTEMTIME ___st; + GetLocalTime(&___st); + fwprintf(fp, L"%04d-%02d-%02d %02d:%02d:%02d.%03d %08X (%S:%d): ", + ___st.wYear, ___st.wMonth, ___st.wDay, ___st.wHour, ___st.wMinute, ___st.wSecond, ___st.wMilliseconds, caller, file, line); + } if(trace) fwprintf(fp, L"(TRACE) "); @@ -77,7 +88,9 @@ void LogHelper::log(const char* file, int line, void* caller, bool trace, const va_end(varArgs); fwprintf(fp, L"\n"); - fclose(fp); + + if(presetFP == NULL) + fclose(fp); } void LogHelper::reset() @@ -86,3 +99,12 @@ void LogHelper::reset() logPath = L""; enableTrace = false; } + +void LogHelper::set(FILE* fp, bool enableTrace, bool compact) +{ + LogHelper::initialized = true; + + LogHelper::presetFP = fp; + LogHelper::enableTrace = enableTrace; + LogHelper::compact = compact; +} diff --git a/LogHelper.h b/LogHelper.h index fc534fa..3d891b1 100644 --- a/LogHelper.h +++ b/LogHelper.h @@ -20,6 +20,7 @@ #pragma once #include +#include #define TraceF(format, ...) LogHelper::log(__FILE__, __LINE__, this, true, format, __VA_ARGS__); #define TraceFStatic(format, ...) LogHelper::log(__FILE__, __LINE__, NULL, true, format, __VA_ARGS__); @@ -31,9 +32,12 @@ class LogHelper public: static void log(const char* file, int line, void* caller, bool trace, const wchar_t* format, ...); static void reset(); + static void set(FILE* fp, bool enableTrace, bool compact); private: static bool initialized; static std::wstring logPath; static bool enableTrace; + static FILE* presetFP; + static bool compact; }; diff --git a/ParametricEQ.cpp b/ParametricEQ.cpp index e5fe93c..30f6e37 100644 --- a/ParametricEQ.cpp +++ b/ParametricEQ.cpp @@ -35,6 +35,7 @@ #include "ParametricEQ.h" using namespace std; +using namespace stdext; BiQuad::BiQuad(float dbGain, float freq, float srate, float bandwidthOrQ, bool isQ) { @@ -73,6 +74,19 @@ ParametricEQ::ParametricEQ() channelData = NULL; lastInputWasSilent = false; threadHandle = NULL; + + channelNameToPosMap[L"L"] = SPEAKER_FRONT_LEFT; + channelNameToPosMap[L"R"] = SPEAKER_FRONT_RIGHT; + channelNameToPosMap[L"C"] = SPEAKER_FRONT_CENTER; + channelNameToPosMap[L"SUB"] = SPEAKER_LOW_FREQUENCY; + channelNameToPosMap[L"RL"] = SPEAKER_BACK_LEFT; + channelNameToPosMap[L"RR"] = SPEAKER_BACK_RIGHT; + channelNameToPosMap[L"RC"] = SPEAKER_BACK_CENTER; + channelNameToPosMap[L"SL"] = SPEAKER_SIDE_LEFT; + channelNameToPosMap[L"SR"] = SPEAKER_SIDE_RIGHT; + + for(hash_map::iterator it=channelNameToPosMap.begin(); it!=channelNameToPosMap.end(); it++) + channelPosToNameMap[it->second] = it->first; } ParametricEQ::~ParametricEQ() @@ -133,6 +147,24 @@ void ParametricEQ::initialize(float sampleRate, unsigned channelCount, unsigned } this->channelMask = channelMask; + wstringstream channelNames; + unsigned c=0; + for(int i=0; i<31; i++) + { + int channelPos = 1< 0) + channelNames << L" "; + if(channelPosToNameMap.find(channelPos) != channelPosToNameMap.end()) + channelNames << channelPosToNameMap[channelPos]; + else + channelNames << c; + } + } + TraceF(L"%d channels for this device: %s", channelCount, channelNames.str().c_str()); + try { configPath = RegistryHelper::readValue(APP_REGPATH, L"ConfigPath"); @@ -280,7 +312,7 @@ void ParametricEQ::loadConfig(const wstring& path, vector selectedChannels wstring currentWord; for(unsigned i=0; i selectedChannels { int channelNr = -1; - if(currentWord == L"all") + if(currentWord == L"ALL") { selectedChannels = vector(channelCount, true); } @@ -299,24 +331,8 @@ void ParametricEQ::loadConfig(const wstring& path, vector selectedChannels else { int channelPos = -1; - if(currentWord == L"l") - channelPos = SPEAKER_FRONT_LEFT; - else if(currentWord == L"r") - channelPos = SPEAKER_FRONT_RIGHT; - else if(currentWord == L"c") - channelPos = SPEAKER_FRONT_CENTER; - else if(currentWord == L"sub") - channelPos = SPEAKER_LOW_FREQUENCY; - else if(currentWord == L"rl") - channelPos = SPEAKER_BACK_LEFT; - else if(currentWord == L"rr") - channelPos = SPEAKER_BACK_RIGHT; - else if(currentWord == L"rc") - channelPos = SPEAKER_BACK_CENTER; - else if(currentWord == L"sl") - channelPos = SPEAKER_SIDE_LEFT; - else if(currentWord == L"sr") - channelPos = SPEAKER_SIDE_RIGHT; + if(channelNameToPosMap.find(currentWord) != channelNameToPosMap.end()) + channelPos = channelNameToPosMap[currentWord]; else LogF(L"Invalid channel position %s", currentWord.c_str()); @@ -338,18 +354,19 @@ void ParametricEQ::loadConfig(const wstring& path, vector selectedChannels } } - wstringstream channelStream; + wstringstream channelNumbers; for(unsigned c=0; c 0) - channelStream << L", "; - channelStream << c+1; + if(channelNumbers.tellp() > 0) + channelNumbers << L", "; + + channelNumbers << c+1; } } - TraceF(L"Selecting channel(s) %s", channelStream.str().c_str()); + TraceF(L"Selecting channel(s) number %s", channelNumbers.str().c_str()); } else if(key.find(L"Filter") == 0) { @@ -510,6 +527,22 @@ float ParametricEQ::getFreq(const wstring& freqString) unsigned ParametricEQ::getChannelNumber(unsigned position) { + //Special handling to accept "wrong", but unambiguous positions + if(channelMask == KSAUDIO_SPEAKER_5POINT1_SURROUND) + { + if(position == SPEAKER_BACK_LEFT) + return 4; + else if(position == SPEAKER_BACK_RIGHT) + return 5; + } + else if(channelMask == KSAUDIO_SPEAKER_5POINT1) + { + if(position == SPEAKER_SIDE_LEFT) + return 4; + else if(position == SPEAKER_SIDE_RIGHT) + return 5; + } + if((channelMask & position) == 0) return -1; diff --git a/ParametricEQ.h b/ParametricEQ.h index 8151155..aa14d2a 100644 --- a/ParametricEQ.h +++ b/ParametricEQ.h @@ -21,6 +21,7 @@ #include #include +#include #define IS_DENORMAL(f) (((*(unsigned int *)&(f))&0x7f800000) == 0) @@ -106,4 +107,6 @@ private: bool lastInputWasSilent; void* threadHandle; void* shutdownEvent; + stdext::hash_map channelNameToPosMap; + stdext::hash_map channelPosToNameMap; };