[DEV] update algo interface and add test

This commit is contained in:
Edouard DUPIN 2015-04-20 21:56:16 +02:00
parent e912b34365
commit 715957ac75
10 changed files with 359 additions and 104 deletions

View File

@ -29,14 +29,14 @@
audio::algo::chunkware::Compressor::Compressor() :
AttRelEnvelope(10.0, 100.0),
m_isConfigured(false),
m_threshdB(0.0),
m_thresholddB(0.0),
m_ratio(1.0),
m_overThresholdEnvelopeDB(DC_OFFSET) {
}
void audio::algo::chunkware::Compressor::setThreshold(double _dB) {
m_threshdB = _dB;
m_thresholddB = _dB;
}
void audio::algo::chunkware::Compressor::setRatio(double _ratio) {
@ -115,7 +115,7 @@ void audio::algo::chunkware::Compressor::processDouble(double* _out, const doubl
_keyLinked += DC_OFFSET; // add DC offset to avoid log(0)
double keydB = lin2dB(_keyLinked); // convert linear -> dB
// threshold
double overdB = keydB - m_threshdB; // delta over threshold
double overdB = keydB - m_thresholddB; // delta over threshold
if (overdB < 0.0) {
overdB = 0.0;
}

View File

@ -50,12 +50,12 @@ namespace audio {
* @brief Get list of format suported in input.
* @return list of supported format
*/
std::vector<enum audio::format> getSupportedFormat();
virtual std::vector<enum audio::format> getSupportedFormat();
/**
* @brief Get list of algorithm format suported. No format convertion.
* @return list of supported format
*/
std::vector<enum audio::format> getNativeSupportedFormat();
virtual std::vector<enum audio::format> getNativeSupportedFormat();
/**
* @brief Main input algo process.
* @param[in,out] _output Output data.
@ -64,24 +64,24 @@ namespace audio {
* @param[in] _nbChannel Number of channel in the stream.
* @param[in] _format Input data format.
*/
void process(void* _output, const void* _input, size_t _nbChunk, int8_t _nbChannel = 2, enum audio::format _format = audio::format_double);
virtual void process(void* _output, const void* _input, size_t _nbChunk, int8_t _nbChannel = 2, enum audio::format _format = audio::format_double);
protected:
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel);
void processDouble(double* _out, const double* _in, int8_t _nbChannel, double _value);
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel, double _value);
/*
void process(float* _out, const float* _in, int8_t _nbChannel);
void process(int16_16_t* _out, const int16_16_t* _in, int8_t _nbChannel);
void process(int16_32_t* _out, const int16_32_t* _in, int8_t _nbChannel);
void process(int24_32_t* _out, const int24_32_t* _in, int8_t _nbChannel);
void process(int32_32_t* _out, const int32_32_t* _in, int8_t _nbChannel);
void process(int32_64_t* _out, const int32_64_t* _in, int8_t _nbChannel);
virtual void processFloat(float* _out, const float* _in, int8_t _nbChannel);
virtual void process16_16(int16_16_t* _out, const int16_16_t* _in, int8_t _nbChannel);
virtual void process16_32(int16_32_t* _out, const int16_32_t* _in, int8_t _nbChannel);
virtual void process24_32(int24_32_t* _out, const int24_32_t* _in, int8_t _nbChannel);
virtual void process32_32(int32_32_t* _out, const int32_32_t* _in, int8_t _nbChannel);
virtual void process32_64(int32_64_t* _out, const int32_64_t* _in, int8_t _nbChannel);
*/
protected:
double m_threshdB;//!< threshold (dB)
double m_thresholddB;//!< threshold (dB)
public:
virtual void setThreshold(double _dB);
virtual double getThreshold() const {
return m_threshdB;
return m_thresholddB;
}
protected:
double m_ratio; //!< ratio (compression: < 1 ; expansion: > 1)

View File

@ -45,7 +45,7 @@ namespace audio {
}
public:
virtual void init();
void processDouble(double* _out, const double* _in, int8_t _nbChannel);
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel);
protected:
audio::algo::chunkware::EnvelopeDetector m_averager; //!< averager
double m_averageSuares; //!< average of squares

View File

@ -25,45 +25,97 @@
#include <audio/algo/chunkware/Gate.h>
#include <audio/algo/chunkware/debug.h>
audio::algo::chunkware::Gate::Gate() :
AttRelEnvelope(1.0, 100.0),
m_threshdB(0.0),
m_thresholddB(0.0),
m_threshold(1.0),
m_overThresholdEnvelope(DC_OFFSET) {
}
void audio::algo::chunkware::Gate::setThresh(double _dB) {
m_threshdB = _dB;
void audio::algo::chunkware::Gate::setThreshold(double _dB) {
m_thresholddB = _dB;
m_threshold = dB2lin(_dB);
}
void audio::algo::chunkware::Gate::initRuntime() {
void audio::algo::chunkware::Gate::init() {
m_overThresholdEnvelope = DC_OFFSET;
m_isConfigured = true;
}
void audio::algo::chunkware::Gate::process(double& _in1, double& _in2) {
// create sidechain
double rect1 = fabs(_in1); // rectify input
double rect2 = fabs(_in2);
/* if desired, one could use another EnvelopeDetector to smooth
* the rectified signal.
*/
double link = std::max(rect1, rect2); // link channels with greater of 2
process(_in1, _in2, link); // rest of process
std::vector<enum audio::format> audio::algo::chunkware::Gate::getSupportedFormat() {
std::vector<enum audio::format> out = getNativeSupportedFormat();
out.push_back(audio::format_int16);
return out;
}
void audio::algo::chunkware::Gate::process(double& _in1, double& _in2, double _keyLinked) {
_keyLinked = fabs(_keyLinked); // rectify (just in case)
std::vector<enum audio::format> audio::algo::chunkware::Gate::getNativeSupportedFormat() {
std::vector<enum audio::format> out;
out.push_back(audio::format_double);
return out;
}
void audio::algo::chunkware::Gate::process(void* _output, const void* _input, size_t _nbChunk, int8_t _nbChannel, enum audio::format _format) {
// TODO : Check init ...
if (_nbChannel != 1) {
AA_CHUNK_ERROR("Can not compress with Other than single channel: " << _nbChannel);
}
switch (_format) {
case audio::format_int16:
{
const int16_t* input = reinterpret_cast<const int16_t*>(_input);
int16_t* output = reinterpret_cast<int16_t*>(_output);
double vals[_nbChannel];
for (size_t iii=0; iii<_nbChunk ; ++iii) {
for (int8_t kkk=0; kkk<_nbChannel ; ++kkk) {
vals[kkk] = double(input[iii*_nbChannel+kkk]) / 32768.0;
}
processDouble(vals, vals, _nbChannel);
for (int8_t kkk=0; kkk<_nbChannel ; ++kkk) {
vals[kkk] *= 32768.0;
output[iii*_nbChannel+kkk] = int16_t(std::avg(-32768.0, vals[kkk], 32767.0));
}
}
}
break;
case audio::format_double:
{
const double* input = reinterpret_cast<const double*>(_input);
double* output = reinterpret_cast<double*>(_output);
for (size_t iii=0; iii<_nbChunk ; ++iii) {
processDouble(&output[iii*_nbChannel], &input[iii*_nbChannel], _nbChannel);
//AA_CHUNK_INFO(" in=" << input[iii] << " => " << output[iii]);
}
}
break;
default:
AA_CHUNK_ERROR("Can not compress with unsupported format : " << _format);
return;
}
}
void audio::algo::chunkware::Gate::processDouble(double* _out, const double* _in, int8_t _nbChannel) {
double keyLink = 0;
// get greater value;
for (int8_t iii=0; iii<_nbChannel; ++iii) {
double absValue = std::abs(_in[iii]);
keyLink = std::max(keyLink, absValue);
}
processDouble(_out, _in, _nbChannel, keyLink);
}
void audio::algo::chunkware::Gate::processDouble(double* _out, const double* _in, int8_t _nbChannel, double _keyLinked) {
// threshold
// key over threshold (0.0 or 1.0)
double over = double(_keyLinked > m_threshold);
// attack/release
over += DC_OFFSET; // add DC offset to avoid denormal
over += DC_OFFSET; // add DC offset to avoid denormal
audio::algo::chunkware::AttRelEnvelope::run(over, m_overThresholdEnvelope); // run attack/release
over = m_overThresholdEnvelope - DC_OFFSET; // subtract DC offset
over = m_overThresholdEnvelope - DC_OFFSET; // subtract DC offset
/* REGARDING THE DC OFFSET: In this case, since the offset is added before
* the attack/release processes, the envelope will never fall below the offset,
* thereby avoiding denormals. However, to prevent the offset from causing
@ -71,6 +123,7 @@ void audio::algo::chunkware::Gate::process(double& _in1, double& _in2, double _k
* a minimum value of 0dB.
*/
// output gain
_in1 *= over; // apply gain reduction to input
_in2 *= over;
for (int8_t iii=0; iii<_nbChannel; ++iii) {
_out[iii] = _in[iii] * over;
}
}

View File

@ -30,29 +30,61 @@
#include <etk/types.h>
#include <audio/algo/chunkware/AttRelEnvelope.h>
#include <audio/algo/chunkware/Gain.h>
#include <audio/format.h>
namespace audio {
namespace algo {
namespace chunkware {
class Gate : public AttRelEnvelope {
protected:
bool m_isConfigured;
public:
Gate();
virtual ~Gate() {}
public:
/**
* @brief Initialize the Algorithm
*/
virtual void init();
/**
* @brief Get list of format suported in input.
* @return list of supported format
*/
virtual std::vector<enum audio::format> getSupportedFormat();
/**
* @brief Get list of algorithm format suported. No format convertion.
* @return list of supported format
*/
virtual std::vector<enum audio::format> getNativeSupportedFormat();
/**
* @brief Main input algo process.
* @param[in,out] _output Output data.
* @param[in] _input Input data.
* @param[in] _nbChunk Number of chunk in the input buffer.
* @param[in] _nbChannel Number of channel in the stream.
* @param[in] _format Input data format.
*/
virtual void process(void* _output, const void* _input, size_t _nbChunk, int8_t _nbChannel = 2, enum audio::format _format = audio::format_double);
protected:
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel);
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel, double _value);
/*
virtual void processFloat(float* _out, const float* _in, int8_t _nbChannel);
virtual void process16_16(int16_16_t* _out, const int16_16_t* _in, int8_t _nbChannel);
virtual void process16_32(int16_32_t* _out, const int16_32_t* _in, int8_t _nbChannel);
virtual void process24_32(int24_32_t* _out, const int24_32_t* _in, int8_t _nbChannel);
virtual void process32_32(int32_32_t* _out, const int32_32_t* _in, int8_t _nbChannel);
virtual void process32_64(int32_64_t* _out, const int32_64_t* _in, int8_t _nbChannel);
*/
public:
// parameters
virtual void setThresh(double _dB);
virtual double getThresh() const {
return m_threshdB;
virtual void setThreshold(double _dB);
virtual double getThreshold() const {
return m_thresholddB;
}
// runtime
// call before runtime (in resume())
virtual void initRuntime();
// gate runtime process
void process(double& _in1, double& _in2);
// with stereo-linked key in
void process(double& _in1, double& _in2, double _keyLinked);
private:
// transfer function
double m_threshdB; //!< threshold (dB)
double m_thresholddB; //!< threshold (dB)
double m_threshold; //!< threshold (linear)
// runtime variables
double m_overThresholdEnvelope; //!< over-threshold envelope (linear)

View File

@ -28,7 +28,7 @@
audio::algo::chunkware::GateRms::GateRms() :
m_averager(5.0),
m_averageSuares(DC_OFFSET) {
m_averageSquares(DC_OFFSET) {
}
@ -41,24 +41,26 @@ void audio::algo::chunkware::GateRms::setWindow(double _ms) {
m_averager.setTc(_ms);
}
void audio::algo::chunkware::GateRms::initRuntime() {
audio::algo::chunkware::Gate::initRuntime();
m_averageSuares = DC_OFFSET;
void audio::algo::chunkware::GateRms::init() {
m_averageSquares = DC_OFFSET;
audio::algo::chunkware::Gate::init();
}
void audio::algo::chunkware::GateRms::process(double& _in1, double& _in2) {
void audio::algo::chunkware::GateRms::processDouble(double* _out, const double* _in, int8_t _nbChannel) {
double sum = 0.0;
// create sidechain
double inSq1 = _in1 * _in1; // square input
double inSq2 = _in2 * _in2;
double sum = inSq1 + inSq2; // power summing
sum += DC_OFFSET; // DC offset, to prevent denormal
m_averager.run(sum, m_averageSuares); // average of squares
double rms = sqrt(m_averageSuares); // rms (sort of ...)
for (int8_t iii=0; iii<_nbChannel; ++iii) {
sum += _in[iii] * _in[iii]; // square input
}
sum += DC_OFFSET; // DC offset, to prevent denormal
m_averager.run(sum, m_averageSquares); // average of squares
double rms = sqrt(m_averageSquares); // rms (sort of ...)
/* REGARDING THE RMS AVERAGER: Ok, so this isn't a REAL RMS
* calculation. A true RMS is an FIR moving average. This
* approximation is a 1-pole IIR. Nonetheless, in practice,
* and in the interest of simplicity, this method will suffice,
* giving comparable results.
*/
audio::algo::chunkware::Gate::process(_in1, _in2, rms); // rest of process
// rest of process
audio::algo::chunkware::Gate::processDouble(_out, _in, _nbChannel, rms);
}

View File

@ -42,14 +42,13 @@ namespace audio {
virtual double getWindow() const {
return m_averager.getTc();
}
// runtime process
// call before runtime (in resume())
virtual void initRuntime();
// gate runtime process
void process(double& _in1, double& _in2);
public:
virtual void init();
protected:
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel);
private:
audio::algo::chunkware::EnvelopeDetector m_averager; //!< averager
double m_averageSuares; //!< average of squares
double m_averageSquares; //!< average of squares
};
}
}

View File

@ -29,7 +29,7 @@
audio::algo::chunkware::Limiter::Limiter() :
m_isConfigured(false),
m_threshdB(0.0),
m_thresholddB(0.0),
m_threshold(1.0),
m_peakHold(0),
m_peakTimer(0),
@ -45,7 +45,7 @@ audio::algo::chunkware::Limiter::Limiter() :
}
void audio::algo::chunkware::Limiter::setThreshold(double _dB) {
m_threshdB = _dB;
m_thresholddB = _dB;
m_threshold = dB2lin(_dB);
}

View File

@ -66,12 +66,12 @@ namespace audio {
* @brief Get list of format suported in input.
* @return list of supported format
*/
std::vector<enum audio::format> getSupportedFormat();
virtual std::vector<enum audio::format> getSupportedFormat();
/**
* @brief Get list of algorithm format suported. No format convertion.
* @return list of supported format
*/
std::vector<enum audio::format> getNativeSupportedFormat();
virtual std::vector<enum audio::format> getNativeSupportedFormat();
/**
* @brief Main input algo process.
* @param[in,out] _output Output data.
@ -80,23 +80,23 @@ namespace audio {
* @param[in] _nbChannel Number of channel in the stream.
* @param[in] _format Input data format.
*/
void process(void* _output, const void* _input, size_t _nbChunk, int8_t _nbChannel = 2, enum audio::format _format = audio::format_double);
virtual void process(void* _output, const void* _input, size_t _nbChunk, int8_t _nbChannel = 2, enum audio::format _format = audio::format_double);
protected:
void processDouble(double* _out, const double* _in, int8_t _nbChannel);
virtual void processDouble(double* _out, const double* _in, int8_t _nbChannel);
/*
void process(float* _out, const float* _in, int8_t _nbChannel);
void process(int16_16_t* _out, const int16_16_t* _in, int8_t _nbChannel);
void process(int16_32_t* _out, const int16_32_t* _in, int8_t _nbChannel);
void process(int24_32_t* _out, const int24_32_t* _in, int8_t _nbChannel);
void process(int32_32_t* _out, const int32_32_t* _in, int8_t _nbChannel);
void process(int32_64_t* _out, const int32_64_t* _in, int8_t _nbChannel);
virtual void processFloat(float* _out, const float* _in, int8_t _nbChannel);
virtual void process16_16(int16_16_t* _out, const int16_16_t* _in, int8_t _nbChannel);
virtual void process16_32(int16_32_t* _out, const int16_32_t* _in, int8_t _nbChannel);
virtual void process24_32(int24_32_t* _out, const int24_32_t* _in, int8_t _nbChannel);
virtual void process32_32(int32_32_t* _out, const int32_32_t* _in, int8_t _nbChannel);
virtual void process32_64(int32_64_t* _out, const int32_64_t* _in, int8_t _nbChannel);
*/
protected:
double m_threshdB; //!< threshold (dB)
double m_thresholddB; //!< threshold (dB)
public:
virtual void setThreshold(double _dB);
virtual double getThreshold() const {
return m_threshdB;
return m_thresholddB;
}
protected:

View File

@ -8,6 +8,7 @@
#include <etk/etk.h>
#include <audio/algo/chunkware/Compressor.h>
#include <audio/algo/chunkware/Limiter.h>
#include <audio/algo/chunkware/Gate.h>
#include <etk/os/FSNode.h>
#include <etk/chrono.h>
@ -37,16 +38,190 @@ static std::vector<int16_t> convert(const std::vector<double>& _data) {
return out;
}
class Performance {
private:
std11::chrono::steady_clock::time_point m_timeStart;
std11::chrono::steady_clock::time_point m_timeStop;
std11::chrono::nanoseconds m_totalTimeProcessing;
std11::chrono::nanoseconds m_minProcessing;
std11::chrono::nanoseconds m_maxProcessing;
int32_t m_totalIteration;
public:
Performance() :
m_totalTimeProcessing(0),
m_minProcessing(99999999999999LL),
m_maxProcessing(0),
m_totalIteration(0) {
}
void tic() {
m_timeStart = std11::chrono::steady_clock::now();
}
void toc() {
m_timeStop = std11::chrono::steady_clock::now();
std11::chrono::nanoseconds time = m_timeStop - m_timeStart;
m_minProcessing = std::min(m_minProcessing, time);
m_maxProcessing = std::max(m_maxProcessing, time);
m_totalTimeProcessing += time;
m_totalIteration++;
}
std11::chrono::nanoseconds getTotalTimeProcessing() {
return m_totalTimeProcessing;
}
std11::chrono::nanoseconds getMinProcessing() {
return m_minProcessing;
}
std11::chrono::nanoseconds getMaxProcessing() {
return m_maxProcessing;
}
int32_t getTotalIteration() {
return m_totalIteration;
}
};
void performanceCompressor() {
std::vector<double> input;
input.resize(8192, 0);
std::vector<double> output;
output.resize(8192, 0);
double sampleRate = 48000.0;
{
double phase = 0;
double baseCycle = 2.0*M_PI/sampleRate * 1280.0;
for (int32_t iii=0; iii<input.size(); iii++) {
input[iii] = cos(phase) * 5.0;
phase += baseCycle;
if (phase >= 2*M_PI) {
phase -= 2*M_PI;
}
}
}
APPL_PRINT("Start compressor performance ...");
Performance perfo;
audio::algo::chunkware::Compressor algo;
algo.setThreshold(-10);
algo.setRatio(-5);
int32_t lastPourcent = -1;
for (int32_t iii=0; iii<4096; ++iii) {
perfo.tic();
algo.process(&output[0], &input[0], input.size(), 1, audio::format_double);
perfo.toc();
usleep(1000);
}
APPL_INFO("Performance Compressor (double): ");
APPL_INFO(" blockSize=" << input.size() << " sample");
APPL_INFO(" min < avg < max =" << perfo.getMinProcessing().count() << "ns < "
<< perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < "
<< perfo.getMaxProcessing().count() << "ns ");
APPL_INFO(" min < avg < max= " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
<< (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
<< (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%");
}
void performanceLimiter() {
std::vector<double> input;
input.resize(8192, 0);
std::vector<double> output;
output.resize(8192, 0);
double sampleRate = 48000.0;
{
double phase = 0;
double baseCycle = 2.0*M_PI/sampleRate * 1280.0;
for (int32_t iii=0; iii<input.size(); iii++) {
input[iii] = cos(phase) * 5.0;
phase += baseCycle;
if (phase >= 2*M_PI) {
phase -= 2*M_PI;
}
}
}
APPL_PRINT("Start Limiter performance ...");
Performance perfo;
audio::algo::chunkware::Limiter algo;
algo.setSampleRate(48000);
algo.setThreshold(0);
algo.setAttack(0.1);
algo.setRelease(2);
algo.init(1);
int32_t lastPourcent = -1;
for (int32_t iii=0; iii<4096; ++iii) {
perfo.tic();
algo.process(&output[0], &input[0], input.size(), 1, audio::format_double);
perfo.toc();
usleep(1000);
}
APPL_INFO("Performance Limiter (double): ");
APPL_INFO(" blockSize=" << input.size() << " sample");
APPL_INFO(" min < avg < max =" << perfo.getMinProcessing().count() << "ns < "
<< perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < "
<< perfo.getMaxProcessing().count() << "ns ");
APPL_INFO(" min < avg < max = " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
<< (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
<< (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%");
}
void performanceGate() {
std::vector<double> input;
input.resize(8192, 0);
std::vector<double> output;
output.resize(8192, 0);
double sampleRate = 48000.0;
{
double phase = 0;
double baseCycle = 2.0*M_PI/sampleRate * 1280.0;
for (int32_t iii=0; iii<input.size(); iii++) {
input[iii] = cos(phase) * 5.0;
phase += baseCycle;
if (phase >= 2*M_PI) {
phase -= 2*M_PI;
}
}
}
APPL_PRINT("Start Gate performance ...");
Performance perfo;
audio::algo::chunkware::Gate algo;
algo.setSampleRate(48000);
algo.setThreshold(0);
algo.setAttack(0.1);
algo.setRelease(2);
algo.init();
int32_t lastPourcent = -1;
for (int32_t iii=0; iii<4096; ++iii) {
perfo.tic();
algo.process(&output[0], &input[0], input.size(), 1, audio::format_double);
perfo.toc();
usleep(1000);
}
APPL_INFO("Performance Gate (double): ");
APPL_INFO(" blockSize=" << input.size() << " sample");
APPL_INFO(" min < avg < max =" << perfo.getMinProcessing().count() << "ns < "
<< perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < "
<< perfo.getMaxProcessing().count() << "ns ");
APPL_INFO(" min < avg < max = " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
<< (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
<< (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%");
}
int main(int _argc, const char** _argv) {
// the only one init for etk:
etk::init(_argc, _argv);
std::string inputName = "";
bool performance = false;
bool perf = false;
int64_t sampleRate = 48000;
for (int32_t iii=0; iii<_argc ; ++iii) {
std::string data = _argv[iii];
if (etk::start_with(data,"--in=")) {
inputName = &data[5];
} else if (data == "--performance") {
performance = true;
} else if (data == "--perf") {
perf = true;
} else if (etk::start_with(data,"--sample-rate=")) {
@ -57,11 +232,19 @@ int main(int _argc, const char** _argv) {
APPL_PRINT("Help : ");
APPL_PRINT(" ./xxx --fb=file.raw --mic=file.raw");
APPL_PRINT(" --in=YYY.raw inout file");
APPL_PRINT(" --performance Generate signal to force algo to maximum process time");
APPL_PRINT(" --perf Enable performence test (little slower but real performence test)");
APPL_PRINT(" --sample-rate=XXXX Signal sample rate (default 48000)");
exit(0);
}
}
// PERFORMANCE test only ....
if (performance == true) {
performanceCompressor();
performanceLimiter();
performanceGate();
return 0;
}
if (inputName == "") {
APPL_ERROR("Can not Process missing parameters...");
exit(-1);
@ -74,12 +257,8 @@ int main(int _argc, const char** _argv) {
output.resize(inputData.size(), 0);
// process in chunk of 256 samples
int32_t blockSize = 256;
// for CPU consomtion:
std11::chrono::nanoseconds totalTimeProcessing(0);
std11::chrono::nanoseconds minProcessing(99999999999999LL);
std11::chrono::nanoseconds maxProcessing(0);
int32_t totalIteration = 0;
Performance perfo;
/*
audio::algo::chunkware::Compressor algo;
algo.setThreshold(-10);
@ -92,15 +271,10 @@ int main(int _argc, const char** _argv) {
} else {
APPL_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
}
std11::chrono::steady_clock::time_point timeStart = std11::chrono::steady_clock::now();
perfo.tic();
algo.process(audio::format_double, &output[iii*blockSize], &inputData[iii*blockSize], blockSize, 1);
if (perf == true) {
std11::chrono::steady_clock::time_point timeEnd = std11::chrono::steady_clock::now();
std11::chrono::nanoseconds time = timeEnd - timeStart;
minProcessing = std::min(minProcessing, time);
maxProcessing = std::max(maxProcessing, time);
totalTimeProcessing += time;
totalIteration++;
perfo.toc();
usleep(1000);
}
}
@ -119,15 +293,10 @@ int main(int _argc, const char** _argv) {
} else {
APPL_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
}
std11::chrono::steady_clock::time_point timeStart = std11::chrono::steady_clock::now();
perfo.tic();
algo.process(&output[iii*blockSize], &inputData[iii*blockSize], blockSize, 1, audio::format_double);
if (perf == true) {
std11::chrono::steady_clock::time_point timeEnd = std11::chrono::steady_clock::now();
std11::chrono::nanoseconds time = timeEnd - timeStart;
minProcessing = std::min(minProcessing, time);
maxProcessing = std::max(maxProcessing, time);
totalTimeProcessing += time;
totalIteration++;
perfo.toc();
usleep(1000);
}
}
@ -136,13 +305,13 @@ int main(int _argc, const char** _argv) {
if (perf == true) {
APPL_INFO("Performance Result: ");
APPL_INFO(" blockSize=" << blockSize << " sample");
APPL_INFO(" min=" << minProcessing.count() << " ns");
APPL_INFO(" max=" << maxProcessing.count() << " ns");
APPL_INFO(" avg=" << totalTimeProcessing.count()/totalIteration << " ns");
APPL_INFO(" min=" << perfo.getMinProcessing().count() << " ns");
APPL_INFO(" max=" << perfo.getMaxProcessing().count() << " ns");
APPL_INFO(" avg=" << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << " ns");
APPL_INFO(" min=" << (float((minProcessing.count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
APPL_INFO(" max=" << (float((maxProcessing.count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
APPL_INFO(" avg=" << (float(((totalTimeProcessing.count()/totalIteration)*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
APPL_INFO(" min=" << (float((perfo.getMinProcessing().count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
APPL_INFO(" max=" << (float((perfo.getMaxProcessing().count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
APPL_INFO(" avg=" << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
}
etk::FSNodeWriteAllDataType<int16_t>("output.raw", convert(output));