214 lines
6.9 KiB
C++
214 lines
6.9 KiB
C++
/** @file
|
|
* @author Edouard DUPIN
|
|
* @copyright 2015, Edouard DUPIN, all right reserved
|
|
* @license MPL v2.0 (see license file)
|
|
*/
|
|
|
|
#include <test-debug/debug.hpp>
|
|
#include <etk/etk.hpp>
|
|
#include <etk/uri/uri.hpp>
|
|
#include <audio/algo/river/Lms.hpp>
|
|
#include <audio/algo/river/Nlms.hpp>
|
|
#include <echrono/Steady.hpp>
|
|
#include <ethread/tools.hpp>
|
|
|
|
|
|
|
|
|
|
class Performance {
|
|
private:
|
|
echrono::Steady m_timeStart;
|
|
echrono::Steady m_timeStop;
|
|
echrono::Duration m_totalTimeProcessing;
|
|
echrono::Duration m_minProcessing;
|
|
echrono::Duration m_maxProcessing;
|
|
int32_t m_totalIteration;
|
|
public:
|
|
Performance() :
|
|
m_totalTimeProcessing(0),
|
|
m_minProcessing(int64_t(99999999999999LL)),
|
|
m_maxProcessing(0),
|
|
m_totalIteration(0) {
|
|
|
|
}
|
|
void tic() {
|
|
m_timeStart = echrono::Steady::now();
|
|
}
|
|
void toc() {
|
|
m_timeStop = echrono::Steady::now();
|
|
echrono::Duration time = m_timeStop - m_timeStart;
|
|
m_minProcessing = etk::min(m_minProcessing, time);
|
|
m_maxProcessing = etk::max(m_maxProcessing, time);
|
|
m_totalTimeProcessing += time;
|
|
m_totalIteration++;
|
|
|
|
}
|
|
|
|
echrono::Duration getTotalTimeProcessing() {
|
|
return m_totalTimeProcessing;
|
|
}
|
|
echrono::Duration getMinProcessing() {
|
|
return m_minProcessing;
|
|
}
|
|
echrono::Duration getMaxProcessing() {
|
|
return m_maxProcessing;
|
|
}
|
|
int32_t getTotalIteration() {
|
|
return m_totalIteration;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
int main(int _argc, const char** _argv) {
|
|
// the only one init for etk:
|
|
etk::init(_argc, _argv);
|
|
ethread::setName("test thread");
|
|
etk::Path fbName;
|
|
etk::Path micName;
|
|
int32_t filterSize = 0;
|
|
float mu = 0.0f;
|
|
bool nlms = false;
|
|
bool perf = false;
|
|
int64_t sampleRate = 48000;
|
|
for (int32_t iii=0; iii<_argc ; ++iii) {
|
|
etk::String data = _argv[iii];
|
|
if (etk::start_with(data,"--fb=")) {
|
|
fbName = &data[5];
|
|
} else if (etk::start_with(data,"--mic=")) {
|
|
micName = &data[6];
|
|
} else if (etk::start_with(data,"--filter-size=")) {
|
|
data = &data[14];
|
|
filterSize = etk::string_to_int32_t(data);
|
|
} else if (etk::start_with(data,"--mu=")) {
|
|
data = &data[5];
|
|
mu = etk::string_to_float(data);
|
|
} else if (data == "--nlms") {
|
|
nlms = true;
|
|
} else if (data == "--perf") {
|
|
ethread::setPriority(-2);
|
|
perf = true;
|
|
} else if (etk::start_with(data,"--sample-rate=")) {
|
|
data = &data[14];
|
|
sampleRate = etk::string_to_int32_t(data);
|
|
} else if ( data == "-h"
|
|
|| data == "--help") {
|
|
TEST_PRINT("Help : ");
|
|
TEST_PRINT(" ./xxx --fb=file.raw --mic=file.raw");
|
|
TEST_PRINT(" --fb=YYY.raw Feedback file");
|
|
TEST_PRINT(" --mic=XXX.raw Microphone file");
|
|
TEST_PRINT(" --filter-size=xxx Size of the filter");
|
|
TEST_PRINT(" --mu=0.xx Mu value -1.0< mu < -1.0");
|
|
TEST_PRINT(" --nlms NLMS version");
|
|
TEST_PRINT(" --perf Enable performence test (little slower but real performence test)");
|
|
TEST_PRINT(" --sample-rate=XXXX Signal sample rate (default 48000)");
|
|
exit(0);
|
|
}
|
|
}
|
|
if ( fbName.isEmpty() == true
|
|
|| micName.isEmpty() == true) {
|
|
TEST_ERROR("Can not Process missing parameters...");
|
|
exit(-1);
|
|
}
|
|
|
|
Performance perfo;
|
|
|
|
TEST_INFO("Read FeedBack:");
|
|
etk::Vector<int16_t> fbData;
|
|
{
|
|
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(fbName);
|
|
fileIO->open(etk::io::OpenMode::Read);
|
|
fbData = fileIO->readAll<int16_t>();
|
|
fileIO->close();
|
|
}
|
|
TEST_INFO(" " << fbData.size() << " samples");
|
|
TEST_INFO("Read Microphone:");
|
|
etk::Vector<int16_t> micData;
|
|
{
|
|
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(micName);
|
|
fileIO->open(etk::io::OpenMode::Read);
|
|
micData = fileIO->readAll<int16_t>();
|
|
fileIO->close();
|
|
}
|
|
TEST_INFO(" " << micData.size() << " samples");
|
|
// resize output :
|
|
etk::Vector<int16_t> output;
|
|
output.resize(etk::min(fbData.size(), micData.size()), 0);
|
|
// process in chunk of 256 samples
|
|
int32_t blockSize = 256;
|
|
if (nlms == false) {
|
|
TEST_PRINT("***********************");
|
|
TEST_PRINT("** LMS **");
|
|
TEST_PRINT("***********************");
|
|
audio::algo::river::Lms algo;
|
|
algo.init(1, sampleRate, audio::format_float);
|
|
if (filterSize != 0) {
|
|
algo.setFilterSize(filterSize);
|
|
}
|
|
if (mu != 0.0f) {
|
|
algo.setMu(mu);
|
|
}
|
|
int32_t lastPourcent = -1;
|
|
for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
|
|
if (lastPourcent != 100*iii / (output.size()/blockSize)) {
|
|
lastPourcent = 100*iii / (output.size()/blockSize);
|
|
TEST_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
|
|
} else {
|
|
TEST_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
|
|
}
|
|
perfo.tic();
|
|
algo.process(&output[iii*blockSize], &fbData[iii*blockSize], &micData[iii*blockSize], blockSize);
|
|
if (perf == true) {
|
|
perfo.toc();
|
|
ethread::sleepMilliSeconds((1));
|
|
}
|
|
}
|
|
} else {
|
|
TEST_PRINT("***********************");
|
|
TEST_PRINT("** NLMS (power) **");
|
|
TEST_PRINT("***********************");
|
|
audio::algo::river::Nlms algo;
|
|
algo.init(1, sampleRate, audio::format_float);
|
|
if (filterSize != 0) {
|
|
algo.setFilterSize(filterSize);
|
|
}
|
|
int32_t lastPourcent = -1;
|
|
for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
|
|
if (lastPourcent != 100*iii / (output.size()/blockSize)) {
|
|
lastPourcent = 100*iii / (output.size()/blockSize);
|
|
TEST_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
|
|
} else {
|
|
TEST_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
|
|
}
|
|
perfo.tic();
|
|
algo.process(&output[iii*blockSize], &fbData[iii*blockSize], &micData[iii*blockSize], blockSize);
|
|
if (perf == true) {
|
|
perfo.toc();
|
|
ethread::sleepMilliSeconds((1));
|
|
}
|
|
}
|
|
}
|
|
TEST_PRINT("Process done");
|
|
if (perf == true) {
|
|
TEST_PRINT("Performance Result: ");
|
|
TEST_INFO(" blockSize=" << blockSize << " sample");
|
|
TEST_INFO(" min < avg < max =" << perfo.getMinProcessing() << " < "
|
|
<< perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration() << "ns < "
|
|
<< perfo.getMaxProcessing());
|
|
float avg = (float(((perfo.getTotalTimeProcessing().get()/perfo.getTotalIteration())*sampleRate)/double(blockSize))/1000000000.0)*100.0;
|
|
TEST_INFO(" min < avg < max= " << (float((perfo.getMinProcessing().get()*sampleRate)/double(blockSize))/1000000000.0)*100.0 << "% < "
|
|
<< avg << "% < "
|
|
<< (float((perfo.getMaxProcessing().get()*sampleRate)/double(blockSize))/1000000000.0)*100.0 << "%");
|
|
TEST_PRINT("float : " << sampleRate << " : " << avg << "%");
|
|
}
|
|
{
|
|
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(etk::Path("output.raw"));
|
|
if (fileIO->open(etk::io::OpenMode::Write) == false) {
|
|
return -1;
|
|
}
|
|
fileIO->writeAll<int16_t>(output);
|
|
fileIO->close();
|
|
}
|
|
}
|
|
|