/
CXVUSER
/
EqualizerAPO
Обзор
Документация
Войти
/
CXVUSER
/
EqualizerAPO
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Benchmark/Benchmark.cpp
246 строк
8 KB
xcv
up to 1.3
03 авг 2022, 21:39
03 авг 2022, 21:39
baa8447
Код
Авторство
О чём код?
/* This file is part of EqualizerAPO, a system-wide equalizer. Copyright (C) 2012 Jonas Thedering 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "stdafx.h" #ifdef DEBUG #include <stdlib.h> #include <crtdbg.h> #endif #include <cstdio> #define _USE_MATH_DEFINES #include <cmath> #include <string> #include <sndfile.h> #include <tclap/CmdLine.h> #include "version.h" #include "FilterEngine.h" #include "helpers/LogHelper.h" #include "helpers/StringHelper.h" #include "helpers/PrecisionTimer.h" #include "helpers/MemoryHelper.h" using namespace std; int main(int argc, char** argv) { try { stringstream versionStream; versionStream << MAJOR << "." << MINOR; if (REVISION != 0) versionStream << "." << REVISION; 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<string> guidArg("", "guid", "Endpoint GUID to use when parsing configuration (Default: <empty>)", false, "", "string", cmd); TCLAP::ValueArg<string> connectionnameArg("", "connectionname", "Connection name to use when parsing configuration (Default: File output)", false, "File output", "string", cmd); TCLAP::ValueArg<string> devicenameArg("", "devicename", "Device name to use when parsing configuration (Default: Benchmark)", false, "Benchmark", "string", cmd); TCLAP::ValueArg<unsigned> batchsizeArg("", "batchsize", "Number of frames processed in one batch (Default: 65536)", false, 65536, "integer", cmd); TCLAP::ValueArg<string> outputArg("o", "output", "File to write sound data to", false, "", "string", cmd); TCLAP::ValueArg<string> inputArg("i", "input", "File to load sound data from instead of generating sweep", false, "", "string", cmd); TCLAP::ValueArg<unsigned> rateArg("r", "rate", "Sample rate of generated sweep (Default: 44100)", false, 44100, "integer", cmd); TCLAP::ValueArg<float> toArg("t", "to", "End frequency of generated sweep in Hz (Default: 20000.0)", false, 20000.0f, "float", cmd); TCLAP::ValueArg<float> fromArg("f", "from", "Start frequency of generated sweep in Hz (Default: 0.1)", false, 1.0f, "float", cmd); TCLAP::ValueArg<float> lengthArg("l", "length", "Length of generated sweep in seconds (Default: 200.0)", false, 200.0f, "float", cmd); TCLAP::ValueArg<unsigned> channelArg("c", "channels", "Number of channels of generated sweep (Default: 2)", false, 2, "integer", cmd); cmd.parse(argc, argv); bool verbose = verboseArg.getValue(); LogHelper::set(stderr, verbose, true, true); #ifdef _DEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // _CrtSetBreakAlloc(3318); #endif unsigned sampleRate; unsigned channelCount; unsigned channelMask; unsigned frameCount; float length; float* buf; if (REVISION == 0) printf("Benchmark %d.%d\n", MAJOR, MINOR); else printf("Benchmark %d.%d.%d\n", MAJOR, MINOR, REVISION); printf("Run \"%s -h\" to show usage info\n", argv[0]); printf("\n"); string input = inputArg.getValue(); if (input != "") { printf("Reading sound data from %s\n", input.c_str()); PrecisionTimer timer; timer.start(); SF_INFO info; 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; double readTime = timer.stop(); printf("Reading input file took %g seconds\n", readTime); } 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); PrecisionTimer timer; timer.start(); buf = new float[frameCount * channelCount]; for (unsigned i = 0; i < frameCount; i++) { double t = i * 1.0 / sampleRate; float s = (float)sin(((sweepFrom + sweepDiff * (t / length) / 2) * t) * 2 * M_PI); for (unsigned j = 0; j < channelCount; j++) buf[i * channelCount + j] = s; } double genTime = timer.stop(); printf("Generating sweep took %g seconds\n", genTime); } unsigned batchsize = batchsizeArg.getValue(); float* buf2 = new float[frameCount * channelCount]; for (unsigned i = 0; i < frameCount * channelCount; i++) buf2[i] = 0.0f; PrecisionTimer timer; timer.start(); { FilterEngine engine; wstring deviceName = StringHelper::toWString(devicenameArg.getValue(), CP_ACP); wstring connectionName = StringHelper::toWString(connectionnameArg.getValue(), CP_ACP); wstring deviceGuid = StringHelper::toWString(guidArg.getValue(), CP_ACP); engine.setDeviceInfo(false, true, deviceName, connectionName, deviceGuid, deviceName + L" " + connectionName + L" " + deviceGuid); engine.initialize((float)sampleRate, channelCount, channelCount, channelCount, channelMask, batchsize); double initTime = timer.stop(); if (!verbose) printf("\nLoading configuration took %g ms\n", initTime * 1000.0); printf("\nProcessing %d frames from %d channel(s)\n", frameCount, channelCount); timer.start(); for (unsigned i = 0; i < frameCount; i += batchsize) { engine.process(buf2 + i * channelCount, buf + i * channelCount, min(batchsize, frameCount - i)); } double time = timer.stop(); printf("%d samples processed in %f seconds\n", frameCount * channelCount, time); printf("This is equivalent to %.2f%% CPU load (one core) when processing in real time\n", 100.0f * time / length); unsigned clipCount = 0; float max = 0; for (unsigned i = 0; i < frameCount * channelCount; i++) { float f = fabs(buf2[i]); if (f > 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, (int)sampleRate, (int)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; } sf_count_t numWritten = 0; while (numWritten < frameCount) numWritten += sf_writef_float(outFile, buf2 + numWritten * channelCount, frameCount - numWritten); sf_close(outFile); outFile = NULL; delete[] buf; delete[] buf2; } if (!noPauseArg.getValue()) system("pause"); return 0; } catch (TCLAP::ArgException e) { printf("Error: %s for arg %s\n", e.error().c_str(), e.argId().c_str()); return -1; } }