[DEV] create basic resampling speex algorithm
This commit is contained in:
commit
b358318a9d
64
.gitignore
vendored
Normal file
64
.gitignore
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
###################################
|
||||||
|
# folders
|
||||||
|
###################################
|
||||||
|
CVS
|
||||||
|
.svn
|
||||||
|
Object_*
|
||||||
|
doxygen/API/
|
||||||
|
doxygen/ALL/
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# backup files
|
||||||
|
###################################
|
||||||
|
*~
|
||||||
|
*.swp
|
||||||
|
*.old
|
||||||
|
*.bck
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# Compiled source #
|
||||||
|
###################################
|
||||||
|
*.com
|
||||||
|
*.class
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
|
*.pyc
|
||||||
|
tags
|
||||||
|
#ewol
|
||||||
|
out
|
||||||
|
ewol_debug
|
||||||
|
ewol_release
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# Packages #
|
||||||
|
###################################
|
||||||
|
# it's better to unpack these files and commit the raw source
|
||||||
|
# git has its own built in compression methods
|
||||||
|
*.7z
|
||||||
|
*.dmg
|
||||||
|
*.gz
|
||||||
|
*.iso
|
||||||
|
*.jar
|
||||||
|
*.rar
|
||||||
|
*.tar
|
||||||
|
*.zip
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# Logs and databases #
|
||||||
|
###################################
|
||||||
|
*.log
|
||||||
|
*.sql
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# OS generated files #
|
||||||
|
###################################
|
||||||
|
.DS_Store?
|
||||||
|
ehthumbs.db
|
||||||
|
Icon?
|
||||||
|
Thumbs.db
|
||||||
|
Sources/libewol/ewol/os/AndroidAbstraction.cpp
|
||||||
|
org_ewol_EwolConstants.h
|
120
audio/algo/speex/Resampler.cpp
Normal file
120
audio/algo/speex/Resampler.cpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <audio/algo/speex/Resampler.h>
|
||||||
|
#include <audio/algo/speex/debug.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#undef __class__
|
||||||
|
#define __class__ "algo::speex::Resampler"
|
||||||
|
|
||||||
|
audio::algo::speex::Resampler::Resampler() :
|
||||||
|
#ifdef HAVE_SPEEX_DSP
|
||||||
|
m_speexResampler(nullptr),
|
||||||
|
#endif
|
||||||
|
m_isConfigured(false) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
audio::algo::speex::Resampler::~Resampler() {
|
||||||
|
#ifdef HAVE_SPEEX_DSP
|
||||||
|
if (m_speexResampler != nullptr) {
|
||||||
|
speex_resampler_destroy(m_speexResampler);
|
||||||
|
m_speexResampler = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::algo::speex::Resampler::init(int8_t _nbChannel, float _inputSampleRate, float _outputSampleRate, int8_t _quality) {
|
||||||
|
#ifdef HAVE_SPEEX_DSP
|
||||||
|
if (m_speexResampler != nullptr) {
|
||||||
|
speex_resampler_destroy(m_speexResampler);
|
||||||
|
m_speexResampler = nullptr;
|
||||||
|
}
|
||||||
|
AA_SPEEX_DEBUG("Create resampler for : " << _inputSampleRate << " to " << _outputSampleRate);
|
||||||
|
int err = 0;
|
||||||
|
m_speexResampler = speex_resampler_init(_nbChannel,
|
||||||
|
_inputSampleRate,
|
||||||
|
_outputSampleRate,
|
||||||
|
_quality, &err);
|
||||||
|
m_isConfigured = true;
|
||||||
|
#else
|
||||||
|
AA_SPEEX_WARNING("SPEEX DSP lib not accessible ==> can not resample");
|
||||||
|
m_isConfigured = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<enum audio::format> audio::algo::speex::Resampler::getSupportedFormat() {
|
||||||
|
std::vector<enum audio::format> out = getNativeSupportedFormat();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<enum audio::format> audio::algo::speex::Resampler::getNativeSupportedFormat() {
|
||||||
|
std::vector<enum audio::format> out;
|
||||||
|
out.push_back(audio::format_float);
|
||||||
|
out.push_back(audio::format_int16);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio::algo::speex::Resampler::process(void* _output, size_t& _nbChunkOut, const void* _input, size_t _nbChunk, enum audio::format _format) {
|
||||||
|
if (m_isConfigured == false) {
|
||||||
|
AA_SPEEX_ERROR("Algo is not initialized...");
|
||||||
|
}
|
||||||
|
#ifdef HAVE_SPEEX_DSP
|
||||||
|
switch (_format) {
|
||||||
|
case audio::format_int16:
|
||||||
|
{
|
||||||
|
uint32_t nbChunkInput = _nbChunk;
|
||||||
|
uint32_t nbChunkOutput = _nbChunkOut;
|
||||||
|
int ret = speex_resampler_process_interleaved_int(m_speexResampler,
|
||||||
|
reinterpret_cast<const int16_t*>(_input),
|
||||||
|
&nbChunkInput,
|
||||||
|
reinterpret_cast<int16_t*>(_output),
|
||||||
|
&nbChunkOutput);
|
||||||
|
// Check all input and output ...
|
||||||
|
if (nbChunkInput != _nbChunk) {
|
||||||
|
AA_SPEEX_ERROR("inputSize (not all read ...) proceed=" << nbChunkInput << " requested=" << _nbChunk);
|
||||||
|
// TODO : manage this case ...
|
||||||
|
}
|
||||||
|
if (nbChunkOutput == _nbChunkOut) {
|
||||||
|
AA_SPEEX_ERROR("Might have not enought data in output... output size=" << _nbChunkOut);
|
||||||
|
// TODO : manage this case ...
|
||||||
|
}
|
||||||
|
_nbChunkOut = nbChunkOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case audio::format_float:
|
||||||
|
{
|
||||||
|
uint32_t nbChunkInput = _nbChunk;
|
||||||
|
uint32_t nbChunkOutput = _nbChunkOut;
|
||||||
|
int ret = speex_resampler_process_interleaved_float(m_speexResampler,
|
||||||
|
reinterpret_cast<const float*>(_input),
|
||||||
|
&nbChunkInput,
|
||||||
|
reinterpret_cast<float*>(_output),
|
||||||
|
&nbChunkOutput);
|
||||||
|
// Check all input and output ...
|
||||||
|
if (nbChunkInput != _nbChunk) {
|
||||||
|
AA_SPEEX_ERROR("inputSize (not all read ...) proceed=" << nbChunkInput << " requested=" << _nbChunk);
|
||||||
|
// TODO : manage this case ...
|
||||||
|
}
|
||||||
|
if (nbChunkOutput == _nbChunkOut) {
|
||||||
|
AA_SPEEX_ERROR("Might have not enought data in output... output size=" << _nbChunkOut);
|
||||||
|
// TODO : manage this case ...
|
||||||
|
}
|
||||||
|
_nbChunkOut = nbChunkOutput;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
AA_SPEEX_ERROR("Can not Limit with unsupported format : " << _format);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
AA_SPEEX_ERROR("Not build with speex DSP ... ");
|
||||||
|
_nbChunkOut = _nbChunk/10;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
65
audio/algo/speex/Resampler.h
Normal file
65
audio/algo/speex/Resampler.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __AUDIO_ALGO_SPEEX_RESAMPLER_H__
|
||||||
|
#define __AUDIO_ALGO_SPEEX_RESAMPLER_H__
|
||||||
|
|
||||||
|
#include <etk/types.h>
|
||||||
|
#include <audio/format.h>
|
||||||
|
#include <etk/chrono.h>
|
||||||
|
#include <vector>
|
||||||
|
#ifdef HAVE_SPEEX_DSP
|
||||||
|
#include <speex/speex_resampler.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace algo {
|
||||||
|
namespace speex {
|
||||||
|
class Resampler {
|
||||||
|
protected:
|
||||||
|
#ifdef HAVE_SPEEX_DSP
|
||||||
|
SpeexResamplerState* m_speexResampler;
|
||||||
|
#endif
|
||||||
|
bool m_isConfigured;
|
||||||
|
public:
|
||||||
|
Resampler();
|
||||||
|
virtual ~Resampler();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Initialize the Algorithm
|
||||||
|
* @param[in] _nbChannel Number of channel in the stream.
|
||||||
|
* @param[in] _inputSampleRate Input sample rate.
|
||||||
|
* @param[in] _outputSampleRate Output sample rate.
|
||||||
|
* @param[in] _quality Resampler quality [1..10].
|
||||||
|
*/
|
||||||
|
virtual void init(int8_t _nbChannel, float _inputSampleRate, float _outputSampleRate, int8_t _quality);
|
||||||
|
/**
|
||||||
|
* @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,out] _nbChunkOut Number of chunk allocated in the output buffer and return the number of chunk in the buffer.
|
||||||
|
* @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, size_t& _nbChunkOut, const void* _input, size_t _nbChunk, enum audio::format _format = audio::format_float);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
14
audio/algo/speex/debug.cpp
Normal file
14
audio/algo/speex/debug.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
int32_t audio::algo::speex::getLogId() {
|
||||||
|
static int32_t g_val = etk::log::registerInstance("audio-algo-speex");
|
||||||
|
return g_val;
|
||||||
|
}
|
||||||
|
|
46
audio/algo/speex/debug.h
Normal file
46
audio/algo/speex/debug.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUDIO_ALGO_SPEEX_DEBUG_H__
|
||||||
|
#define __AUDIO_ALGO_SPEEX_DEBUG_H__
|
||||||
|
|
||||||
|
#include <etk/log.h>
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace algo {
|
||||||
|
namespace speex {
|
||||||
|
int32_t getLogId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define AA_SPEEX_BASE(info,data) TK_LOG_BASE(audio::algo::speex::getLogId(),info,data)
|
||||||
|
|
||||||
|
#define AA_SPEEX_PRINT(data) AA_SPEEX_BASE(-1, data)
|
||||||
|
#define AA_SPEEX_CRITICAL(data) AA_SPEEX_BASE(1, data)
|
||||||
|
#define AA_SPEEX_ERROR(data) AA_SPEEX_BASE(2, data)
|
||||||
|
#define AA_SPEEX_WARNING(data) AA_SPEEX_BASE(3, data)
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define AA_SPEEX_INFO(data) AA_SPEEX_BASE(4, data)
|
||||||
|
#define AA_SPEEX_DEBUG(data) AA_SPEEX_BASE(5, data)
|
||||||
|
#define AA_SPEEX_VERBOSE(data) AA_SPEEX_BASE(6, data)
|
||||||
|
#define AA_SPEEX_TODO(data) AA_SPEEX_BASE(4, "TODO : " << data)
|
||||||
|
#else
|
||||||
|
#define AA_SPEEX_INFO(data) do { } while(false)
|
||||||
|
#define AA_SPEEX_DEBUG(data) do { } while(false)
|
||||||
|
#define AA_SPEEX_VERBOSE(data) do { } while(false)
|
||||||
|
#define AA_SPEEX_TODO(data) do { } while(false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AA_SPEEX_ASSERT(cond,data) \
|
||||||
|
do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
AA_SPEEX_CRITICAL(data); \
|
||||||
|
assert(!#cond); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
31
lutin_audio_algo_speex.py
Normal file
31
lutin_audio_algo_speex.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import lutinModule as module
|
||||||
|
import lutinTools as tools
|
||||||
|
import lutinDebug as debug
|
||||||
|
|
||||||
|
def get_desc():
|
||||||
|
return "audio_algo_speex : speex algos wrapper"
|
||||||
|
|
||||||
|
|
||||||
|
def create(target):
|
||||||
|
myModule = module.Module(__file__, 'audio_algo_speex', 'LIBRARY')
|
||||||
|
myModule.add_src_file([
|
||||||
|
'audio/algo/speex/debug.cpp',
|
||||||
|
'audio/algo/speex/Resampler.cpp'
|
||||||
|
])
|
||||||
|
myModule.add_module_depend(['etk', 'audio'])
|
||||||
|
|
||||||
|
myModule.add_optionnal_module_depend('speexdsp', "HAVE_SPEEX_DSP", True)
|
||||||
|
|
||||||
|
myModule.add_export_path(tools.get_current_path(__file__))
|
||||||
|
# return module
|
||||||
|
return myModule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
26
lutin_audio_algo_speex_test.py
Normal file
26
lutin_audio_algo_speex_test.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
import lutinModule as module
|
||||||
|
import lutinTools as tools
|
||||||
|
import lutinDebug as debug
|
||||||
|
|
||||||
|
def get_desc():
|
||||||
|
return "audio_algo_speex_test: test for speex ALGO"
|
||||||
|
|
||||||
|
|
||||||
|
def create(target):
|
||||||
|
myModule = module.Module(__file__, 'audio_algo_speex_test', 'BINARY')
|
||||||
|
myModule.add_src_file([
|
||||||
|
'test/main.cpp',
|
||||||
|
'test/debug.cpp'
|
||||||
|
])
|
||||||
|
myModule.add_module_depend(['audio_algo_speex'])
|
||||||
|
return myModule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
13
test/debug.cpp
Normal file
13
test/debug.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
int32_t appl::getLogId() {
|
||||||
|
static int32_t g_val = etk::log::registerInstance("test-speex");
|
||||||
|
return g_val;
|
||||||
|
}
|
||||||
|
|
41
test/debug.h
Normal file
41
test/debug.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __APPL_DEBUG_H__
|
||||||
|
#define __APPL_DEBUG_H__
|
||||||
|
|
||||||
|
#include <etk/log.h>
|
||||||
|
|
||||||
|
namespace appl {
|
||||||
|
int32_t getLogId();
|
||||||
|
};
|
||||||
|
|
||||||
|
#define APPL_BASE(info,data) TK_LOG_BASE(appl::getLogId(),info,data)
|
||||||
|
|
||||||
|
#define APPL_PRINT(data) APPL_BASE(-1, data)
|
||||||
|
#define APPL_CRITICAL(data) APPL_BASE(1, data)
|
||||||
|
#define APPL_ERROR(data) APPL_BASE(2, data)
|
||||||
|
#define APPL_WARNING(data) APPL_BASE(3, data)
|
||||||
|
#define APPL_INFO(data) APPL_BASE(4, data)
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define APPL_DEBUG(data) APPL_BASE(5, data)
|
||||||
|
#define APPL_VERBOSE(data) APPL_BASE(6, data)
|
||||||
|
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
|
||||||
|
#else
|
||||||
|
#define APPL_DEBUG(data) do { } while(false)
|
||||||
|
#define APPL_VERBOSE(data) do { } while(false)
|
||||||
|
#define APPL_TODO(data) do { } while(false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define APPL_ASSERT(cond,data) \
|
||||||
|
do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
APPL_CRITICAL(data); \
|
||||||
|
assert(!#cond); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
284
test/main.cpp
Normal file
284
test/main.cpp
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
/** @file
|
||||||
|
* @author Edouard DUPIN
|
||||||
|
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||||
|
* @license APACHE v2.0 (see license file)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <test/debug.h>
|
||||||
|
#include <etk/etk.h>
|
||||||
|
#include <audio/algo/speex/Resampler.h>
|
||||||
|
#include <etk/os/FSNode.h>
|
||||||
|
#include <etk/chrono.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#undef __class__
|
||||||
|
#define __class__ "test"
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
float performanceResamplerStepFloat(float _sampleRateIn, float _sampleRateOut, int8_t _quality) {
|
||||||
|
std::vector<float> input;
|
||||||
|
input.resize(1024, 0);
|
||||||
|
std::vector<float> output;
|
||||||
|
output.resize(input.size()*10, 0);
|
||||||
|
double sampleRate = _sampleRateIn;
|
||||||
|
{
|
||||||
|
double phase = 0;
|
||||||
|
double baseCycle = 2.0*M_PI/sampleRate * 480.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_INFO("Start Resampler performance ... " << _sampleRateIn << " -> " << _sampleRateOut << " float");
|
||||||
|
Performance perfo;
|
||||||
|
audio::algo::speex::Resampler algo;
|
||||||
|
algo.init(1, _sampleRateIn, _sampleRateOut, _quality);
|
||||||
|
for (int32_t iii=0; iii<1024; ++iii) {
|
||||||
|
perfo.tic();
|
||||||
|
size_t sizeOut = output.size();
|
||||||
|
algo.process(&output[0], sizeOut, &input[0], input.size(), audio::format_float);
|
||||||
|
perfo.toc();
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
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 ");
|
||||||
|
float avg = (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0;
|
||||||
|
APPL_INFO(" min < avg < max= " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
|
||||||
|
<< avg << "% < "
|
||||||
|
<< (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%");
|
||||||
|
APPL_PRINT("float : " << _sampleRateIn << " -> " << _sampleRateOut << " quality=" << int32_t(_quality) << " : " << avg << "%");
|
||||||
|
return avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
float performanceResamplerStepI16(float _sampleRateIn, float _sampleRateOut, int8_t _quality) {
|
||||||
|
std::vector<int16_t> input;
|
||||||
|
input.resize(1024, 0);
|
||||||
|
std::vector<int16_t> output;
|
||||||
|
output.resize(input.size()*10, 0);
|
||||||
|
double sampleRate = _sampleRateIn;
|
||||||
|
{
|
||||||
|
double phase = 0;
|
||||||
|
double baseCycle = 2.0*M_PI/sampleRate * 480.0;
|
||||||
|
for (int32_t iii=0; iii<input.size(); iii++) {
|
||||||
|
input[iii] = cos(phase) * 30000.0;
|
||||||
|
phase += baseCycle;
|
||||||
|
if (phase >= 2*M_PI) {
|
||||||
|
phase -= 2*M_PI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
APPL_INFO("Start Resampler performance ... " << _sampleRateIn << " -> " << _sampleRateOut << " int16_t");
|
||||||
|
Performance perfo;
|
||||||
|
audio::algo::speex::Resampler algo;
|
||||||
|
algo.init(1, _sampleRateIn, _sampleRateOut, _quality);
|
||||||
|
for (int32_t iii=0; iii<1024; ++iii) {
|
||||||
|
perfo.tic();
|
||||||
|
size_t sizeOut = output.size();
|
||||||
|
algo.process(&output[0], sizeOut, &input[0], input.size(), audio::format_int16);
|
||||||
|
perfo.toc();
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
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 ");
|
||||||
|
float avg = (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0;
|
||||||
|
APPL_INFO(" min < avg < max= " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
|
||||||
|
<< avg << "% < "
|
||||||
|
<< (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%");
|
||||||
|
APPL_PRINT("int16_t : " << _sampleRateIn << " -> " << _sampleRateOut << " quality=" << int32_t(_quality) << " : " << avg << "%");
|
||||||
|
return avg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void performanceResampler() {
|
||||||
|
for (int8_t iii=1; iii<=10; ++iii) {
|
||||||
|
float modeFloat = performanceResamplerStepFloat(8000, 48000, iii);
|
||||||
|
float modeI16 = performanceResamplerStepI16(8000, 48000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(16000, 48000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(16000, 48000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(32000, 48000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(32000, 48000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(44100, 48000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(44100, 48000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48001, 48000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48001, 48000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(96000, 48000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(96000, 48000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48000, 96000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48000, 96000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48000, 48001, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48000, 48001, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48000, 44100, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48000, 44100, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48000, 32000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48000, 32000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48000, 16000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48000, 16000, iii);
|
||||||
|
modeFloat = performanceResamplerStepFloat(48000, 8000, iii);
|
||||||
|
modeI16 = performanceResamplerStepI16(48000, 8000, iii);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int _argc, const char** _argv) {
|
||||||
|
// the only one init for etk:
|
||||||
|
etk::init(_argc, _argv);
|
||||||
|
std::string inputName = "";
|
||||||
|
std::string outputName = "output.raw";
|
||||||
|
bool performance = false;
|
||||||
|
bool perf = false;
|
||||||
|
int64_t sampleRateIn = 48000;
|
||||||
|
int64_t sampleRateOut = 48000;
|
||||||
|
int32_t nbChan = 1;
|
||||||
|
int32_t quality = 4;
|
||||||
|
std::string test = "";
|
||||||
|
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||||
|
std::string data = _argv[iii];
|
||||||
|
if (etk::start_with(data,"--in=")) {
|
||||||
|
inputName = &data[5];
|
||||||
|
} else if (etk::start_with(data,"--out=")) {
|
||||||
|
outputName = &data[6];
|
||||||
|
} else if (data == "--performance") {
|
||||||
|
performance = true;
|
||||||
|
} else if (data == "--perf") {
|
||||||
|
perf = true;
|
||||||
|
} else if (etk::start_with(data,"--test=")) {
|
||||||
|
data = &data[7];
|
||||||
|
sampleRateIn = etk::string_to_int32_t(data);
|
||||||
|
} else if (etk::start_with(data,"--sample-rate-in=")) {
|
||||||
|
data = &data[17];
|
||||||
|
sampleRateIn = etk::string_to_int32_t(data);
|
||||||
|
} else if (etk::start_with(data,"--sample-rate-out=")) {
|
||||||
|
data = &data[18];
|
||||||
|
sampleRateOut = etk::string_to_int32_t(data);
|
||||||
|
} else if (etk::start_with(data,"--nb=")) {
|
||||||
|
data = &data[5];
|
||||||
|
nbChan = etk::string_to_int32_t(data);
|
||||||
|
} else if (etk::start_with(data,"--quality=")) {
|
||||||
|
data = &data[10];
|
||||||
|
quality = etk::string_to_int32_t(data);
|
||||||
|
} else if ( data == "-h"
|
||||||
|
|| data == "--help") {
|
||||||
|
APPL_PRINT("Help : ");
|
||||||
|
APPL_PRINT(" ./xxx --fb=file.raw --mic=file.raw");
|
||||||
|
APPL_PRINT(" --in=YYY.raw input file");
|
||||||
|
APPL_PRINT(" --out=zzz.raw output 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(" --test=XXXX some test availlable ...");
|
||||||
|
APPL_PRINT(" RESAMPLING Test resampling data 16 bit mode");
|
||||||
|
APPL_PRINT(" --sample-rate-in=XXXX Input signal sample rate (default 48000)");
|
||||||
|
APPL_PRINT(" --sample-rate-out=XXXX Output signal sample rate (default 48000)");
|
||||||
|
APPL_PRINT(" --quality=XX Resampling quality [0..10] (default 4)");
|
||||||
|
APPL_PRINT(" --nb=XX Number of channel in the file (default 1)");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// PERFORMANCE test only ....
|
||||||
|
if (performance == true) {
|
||||||
|
performanceResampler();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (test == "RESAMPLING") {
|
||||||
|
APPL_INFO("Start resampling test ... ");
|
||||||
|
if (inputName == "") {
|
||||||
|
APPL_ERROR("Can not Process missing parameters...");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
APPL_INFO("Read input:");
|
||||||
|
std::vector<int16_t> inputData = etk::FSNodeReadAllDataType<int16_t>(inputName);
|
||||||
|
APPL_INFO(" " << inputData.size() << " samples");
|
||||||
|
// resize output :
|
||||||
|
std::vector<int16_t> output;
|
||||||
|
output.resize(inputData.size()*sampleRateOut/sampleRateIn+5000, 0);
|
||||||
|
// process in chunk of 256 samples
|
||||||
|
int32_t blockSize = 256*nbChan;
|
||||||
|
|
||||||
|
Performance perfo;
|
||||||
|
audio::algo::speex::Resampler algo;
|
||||||
|
algo.init(nbChan, sampleRateIn, sampleRateOut, quality);
|
||||||
|
int32_t lastPourcent = -1;
|
||||||
|
size_t outputPosition = 0;
|
||||||
|
for (int32_t iii=0; iii<inputData.size()/blockSize; ++iii) {
|
||||||
|
if (lastPourcent != 100*iii / (inputData.size()/blockSize)) {
|
||||||
|
lastPourcent = 100*iii / (inputData.size()/blockSize);
|
||||||
|
APPL_INFO("Process : " << iii*blockSize << "/" << int32_t(inputData.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
|
||||||
|
} else {
|
||||||
|
APPL_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(inputData.size()/blockSize)*blockSize);
|
||||||
|
}
|
||||||
|
size_t availlableSize = (output.size() - outputPosition) / nbChan;
|
||||||
|
perfo.tic();
|
||||||
|
algo.process(&output[outputPosition], availlableSize, &inputData[iii*blockSize], blockSize, audio::format_int16);
|
||||||
|
if (perf == true) {
|
||||||
|
perfo.toc();
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
outputPosition += availlableSize*nbChan;
|
||||||
|
}
|
||||||
|
if (perf == true) {
|
||||||
|
APPL_INFO("Performance Result: ");
|
||||||
|
APPL_INFO(" blockSize=" << blockSize << " sample");
|
||||||
|
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((perfo.getMinProcessing().count()*sampleRateIn)/blockSize)/1000000000.0)*100.0 << " %");
|
||||||
|
APPL_INFO(" max=" << (float((perfo.getMaxProcessing().count()*sampleRateIn)/blockSize)/1000000000.0)*100.0 << " %");
|
||||||
|
APPL_INFO(" avg=" << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRateIn)/blockSize)/1000000000.0)*100.0 << " %");
|
||||||
|
}
|
||||||
|
etk::FSNodeWriteAllDataType<int16_t>(outputName, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user