[DEV] update algo interface and add test
This commit is contained in:
parent
e912b34365
commit
715957ac75
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
219
test/main.cpp
219
test/main.cpp
@ -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));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user