[DEV] add dynamic interface

This commit is contained in:
Edouard DUPIN 2015-02-02 21:48:57 +01:00
parent 57ec4acb9d
commit 87e3cf9747
17 changed files with 694 additions and 199 deletions

View File

@ -8,19 +8,6 @@
#include "debug.h"
std::ostream& airtalgo::operator <<(std::ostream& _os, const IOFormatInterface& _obj) {
_os << "{";
if (_obj.getConfigured() == false) {
_os << "Not configured";
} else {
_os << "format=" << _obj.getFormat();
_os << ", frequency=" << _obj.getFrequency();
_os << ", map=" << _obj.getMap();
}
_os << "}";
return _os;
}
#undef __class__
#define __class__ "Algo"

View File

@ -16,155 +16,11 @@
#include <chrono>
#include <functional>
#include <memory>
#include "AutoLogInOut.h"
#include "IOFormatInterface.h"
#include "debug.h"
namespace airtalgo{
class autoLogInOut {
private:
std::string m_value;
public:
autoLogInOut(const std::string& _value) :
m_value(_value) {
AIRTALGO_VERBOSE(" '" << m_value << "' [START]");
}
~autoLogInOut() {
AIRTALGO_VERBOSE(" '" << m_value << "' [STOP]");
}
};
class IOFormatInterface {
public:
IOFormatInterface() :
m_configured(false),
m_format(airtalgo::format_unknow),
m_map(),
m_frequency(0) {
m_map.push_back(airtalgo::channel_frontLeft);
m_map.push_back(airtalgo::channel_frontRight);
}
IOFormatInterface(std::vector<airtalgo::channel> _map, airtalgo::format _format=airtalgo::format_int16, float _frequency=48000.0f) :
m_configured(true),
m_format(_format),
m_map(_map),
m_frequency(_frequency) {
AIRTALGO_WARNING(" plop : " << m_map << " " << m_format << " " << m_frequency);
}
void set(std::vector<airtalgo::channel> _map, airtalgo::format _format=airtalgo::format_int16, float _frequency=48000.0f) {
bool hasChange = false;
if (m_map != _map) {
m_map = _map;
hasChange = true;
}
if (m_format != _format) {
m_format = _format;
hasChange = true;
}
if (m_frequency == _frequency) {
m_frequency = _frequency;
hasChange = true;
}
if (hasChange == true) {
m_configured = true;
configurationChange();
}
AIRTALGO_WARNING(" plop : " << m_map << " " << m_format << " " << m_frequency);
}
protected:
bool m_configured;
public:
void setConfigured(bool _value) {
m_configured = _value;
}
bool getConfigured() const {
return m_configured;
}
protected:
airtalgo::format m_format; //!< input Algo Format
public:
/**
* @brief Get the algo format.
* @return the current Format.
*/
airtalgo::format getFormat() const {
return m_format;
}
/**
* @brief Set the algo format.
* @param[in] _value New Format.
*/
void setFormat(airtalgo::format _value) {
if (m_format == _value) {
return;
}
m_format = _value;
m_configured = true;
configurationChange();
}
protected:
std::vector<airtalgo::channel> m_map; //!< input channel Map
public:
/**
* @brief Get the algo channel Map.
* @return the current channel Map.
*/
const std::vector<airtalgo::channel>& getMap() const{
return m_map;
}
/**
* @brief Set the algo channel Map.
* @param[in] _value New channel Map.
*/
void setMap(const std::vector<airtalgo::channel>& _value) {
AIRTALGO_DEBUG(" base : " << m_map << " " << _value);
if (m_map == _value) {
return;
}
m_map = _value;
m_configured = true;
AIRTALGO_DEBUG(" base2 : " << m_map);
configurationChange();
}
protected:
float m_frequency; //!< input Algo Format
public:
/**
* @brief Get the algo frequency.
* @return the current frequency.
*/
float getFrequency() const{
return m_frequency;
}
/**
* @brief Set the algo frequency.
* @param[in] _value New frequency.
*/
void setFrequency(float _value) {
if (m_frequency == _value) {
return;
}
m_configured = true;
m_frequency = _value;
configurationChange();
}
protected:
std::function<void()> m_ioChangeFunctor; //!< function pointer on the upper class
void configurationChange() {
if (m_ioChangeFunctor != nullptr) {
m_ioChangeFunctor();
}
}
public:
/**
* @brief Set the callback function to be notify when the arameter change.
* @param[in] _functor Function to call.
*/
void setCallback(const std::function<void()>& _functor) {
m_ioChangeFunctor = _functor;
}
};
std::ostream& operator <<(std::ostream& _os, const IOFormatInterface& _obj);
class Algo : public std::enable_shared_from_this<Algo> {
private:
std::string m_name;
@ -211,7 +67,6 @@ namespace airtalgo{
IOFormatInterface m_input; //!< Input audio property
public:
void setInputFormat(const IOFormatInterface& _format) {
AIRTALGO_WARNING(" plopp : " << _format.getMap() << " " << _format.getFormat() << " " << _format.getFrequency());
m_input.set(_format.getMap(), _format.getFormat(), _format.getFrequency());
}
const IOFormatInterface& getInputFormat() const {
@ -224,7 +79,6 @@ namespace airtalgo{
IOFormatInterface m_output; //!< Output audio property
public:
void setOutputFormat(const IOFormatInterface& _format) {
AIRTALGO_WARNING(" plopp : " << _format.getMap() << " " << _format.getFormat() << " " << _format.getFrequency());
m_output.set(_format.getMap(), _format.getFormat(), _format.getFrequency());
}
const IOFormatInterface& getOutputFormat() const {

17
airtalgo/AutoLogInOut.cpp Normal file
View File

@ -0,0 +1,17 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "AutoLogInOut.h"
#include "debug.h"
airtalgo::AutoLogInOut::AutoLogInOut(const std::string& _value) :
m_value(_value) {
AIRTALGO_VERBOSE(" '" << m_value << "' [START]");
}
airtalgo::AutoLogInOut::~AutoLogInOut() {
AIRTALGO_VERBOSE(" '" << m_value << "' [STOP]");
}

27
airtalgo/AutoLogInOut.h Normal file
View File

@ -0,0 +1,27 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_AUTO_LOG_IN_OUT_H__
#define __AIRT_ALGO_AUTO_LOG_IN_OUT_H__
#include <string>
#include "debug.h"
namespace airtalgo{
class AutoLogInOut {
private:
std::string m_value;
public:
AutoLogInOut(const std::string& _value);
~AutoLogInOut();
};
}
#include "debugRemove.h"
#endif

View File

@ -30,7 +30,7 @@ std::shared_ptr<airtalgo::ChannelReorder> airtalgo::ChannelReorder::create() {
}
void airtalgo::ChannelReorder::configurationChange() {
airtalgo::autoLogInOut("ChannelReorder (config)");
airtalgo::AutoLogInOut("ChannelReorder (config)");
airtalgo::Algo::configurationChange();
if (m_input.getFormat() != m_output.getFormat()) {
AIRTALGO_ERROR("can not support Format Change ...");
@ -54,7 +54,7 @@ bool airtalgo::ChannelReorder::process(std::chrono::system_clock::time_point& _t
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
airtalgo::autoLogInOut tmpLog("ChannelReorder");
airtalgo::AutoLogInOut tmpLog("ChannelReorder");
_outputNbChunk = _inputNbChunk;
// check if we need to process:
if (m_needProcess == false) {

View File

@ -51,7 +51,7 @@ bool airtalgo::EndPointCallback::process(std::chrono::system_clock::time_point&
size_t _inputNbChunk, // requested number of sample ...
void*& _output,
size_t& _outputNbChunk){
airtalgo::autoLogInOut tmpLog("EndPointCallback");
airtalgo::AutoLogInOut tmpLog("EndPointCallback");
if (m_outputFunction != nullptr) {
// update buffer size ...
m_outputData.resize(_inputNbChunk*m_output.getMap().size()*m_formatSize);

View File

@ -37,7 +37,7 @@ bool airtalgo::EndPointRead::process(std::chrono::system_clock::time_point& _tim
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk){
airtalgo::autoLogInOut tmpLog("EndPointRead");
airtalgo::AutoLogInOut tmpLog("EndPointRead");
return false;
}

View File

@ -37,7 +37,7 @@ bool airtalgo::EndPointWrite::process(std::chrono::system_clock::time_point& _ti
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk){
airtalgo::autoLogInOut tmpLog("EndPointWrite");
airtalgo::AutoLogInOut tmpLog("EndPointWrite");
//AIRTALGO_INFO(" nb Sample in buffer : " << m_tmpData.size());
if (m_function != nullptr) {
if (m_tmpData.size() <= 20000) {
@ -72,9 +72,10 @@ bool airtalgo::EndPointWrite::process(std::chrono::system_clock::time_point& _ti
void airtalgo::EndPointWrite::write(const void* _value, size_t _nbChunk) {
std::unique_lock<std::mutex> lock(m_mutex);
AIRTALGO_INFO("[ASYNC] Get data : " << _nbChunk << " chunks"
AIRTALGO_INFO("[ASYNC] Write data : " << _nbChunk << " chunks"
<< " ==> " << _nbChunk*m_output.getMap().size() << " samples"
<< " formatSize=" << int32_t(m_formatSize));
<< " formatSize=" << int32_t(m_formatSize)
<< " bufferSize=" << m_tmpData.size());
const int8_t* value = static_cast<const int8_t*>(_value);
for (size_t iii=0; iii<_nbChunk*m_formatSize*m_output.getMap().size(); ++iii) {
m_tmpData.push_back(*value++);

View File

@ -248,14 +248,14 @@ bool airtalgo::FormatUpdate::process(std::chrono::system_clock::time_point& _tim
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
airtalgo::autoLogInOut tmpLog("FormatUpdate");
airtalgo::AutoLogInOut tmpLog("FormatUpdate");
// chack if we need to process:
if (m_needProcess == false) {
_output = _input;
_outputNbChunk = _inputNbChunk;
return true;
}
if (_input == NULL) {
if (_input == nullptr) {
_output = &(m_outputData[0]);
_outputNbChunk = 0;
AIRTALGO_ERROR("null pointer input ... ");
@ -264,7 +264,7 @@ bool airtalgo::FormatUpdate::process(std::chrono::system_clock::time_point& _tim
_outputNbChunk = _inputNbChunk;
m_outputData.resize(_outputNbChunk*m_input.getMap().size()*m_formatSize);
_output = &(m_outputData[0]);
if (m_functionConvert == NULL) {
if (m_functionConvert == nullptr) {
AIRTALGO_ERROR("null function ptr");
return false;
}

View File

@ -0,0 +1,119 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "IOFormatInterface.h"
#include "debug.h"
#undef __class__
#define __class__ "IOFormatInterface"
std::ostream& airtalgo::operator <<(std::ostream& _os, const IOFormatInterface& _obj) {
_os << "{";
if (_obj.getConfigured() == false) {
_os << "Not configured";
} else {
_os << "format=" << _obj.getFormat();
_os << ", frequency=" << _obj.getFrequency();
_os << ", map=" << _obj.getMap();
}
_os << "}";
return _os;
}
airtalgo::IOFormatInterface::IOFormatInterface() :
m_configured(false),
m_format(airtalgo::format_unknow),
m_map(),
m_frequency(0) {
m_map.push_back(airtalgo::channel_frontLeft);
m_map.push_back(airtalgo::channel_frontRight);
}
airtalgo::IOFormatInterface::IOFormatInterface(std::vector<airtalgo::channel> _map, airtalgo::format _format, float _frequency) :
m_configured(true),
m_format(_format),
m_map(_map),
m_frequency(_frequency) {
}
void airtalgo::IOFormatInterface::set(std::vector<airtalgo::channel> _map, airtalgo::format _format, float _frequency) {
bool hasChange = false;
if (m_map != _map) {
m_map = _map;
hasChange = true;
}
if (m_format != _format) {
m_format = _format;
hasChange = true;
}
if (m_frequency != _frequency) {
m_frequency = _frequency;
hasChange = true;
}
if (hasChange == true) {
m_configured = true;
configurationChange();
}
}
void airtalgo::IOFormatInterface::setConfigured(bool _value) {
m_configured = _value;
}
bool airtalgo::IOFormatInterface::getConfigured() const {
return m_configured;
}
airtalgo::format airtalgo::IOFormatInterface::getFormat() const {
return m_format;
}
void airtalgo::IOFormatInterface::setFormat(airtalgo::format _value) {
if (m_format == _value) {
return;
}
m_format = _value;
m_configured = true;
configurationChange();
}
const std::vector<airtalgo::channel>& airtalgo::IOFormatInterface::getMap() const{
return m_map;
}
void airtalgo::IOFormatInterface::setMap(const std::vector<airtalgo::channel>& _value) {
if (m_map == _value) {
return;
}
m_map = _value;
m_configured = true;
configurationChange();
}
float airtalgo::IOFormatInterface::getFrequency() const{
return m_frequency;
}
void airtalgo::IOFormatInterface::setFrequency(float _value) {
if (m_frequency == _value) {
return;
}
m_configured = true;
m_frequency = _value;
configurationChange();
}
void airtalgo::IOFormatInterface::configurationChange() {
if (m_ioChangeFunctor != nullptr) {
m_ioChangeFunctor();
}
}
void airtalgo::IOFormatInterface::setCallback(const std::function<void()>& _functor) {
m_ioChangeFunctor = _functor;
}

View File

@ -0,0 +1,85 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_IO_FORMAT_INTERFACE_H__
#define __AIRT_ALGO_IO_FORMAT_INTERFACE_H__
#include <string>
#include <vector>
#include <stdint.h>
#include <airtalgo/format.h>
#include <airtalgo/channel.h>
#include <chrono>
#include <functional>
#include <memory>
#include "AutoLogInOut.h"
#include "debug.h"
namespace airtalgo{
class IOFormatInterface {
public:
IOFormatInterface();
IOFormatInterface(std::vector<airtalgo::channel> _map, airtalgo::format _format=airtalgo::format_int16, float _frequency=48000.0f);
void set(std::vector<airtalgo::channel> _map, airtalgo::format _format=airtalgo::format_int16, float _frequency=48000.0f);
protected:
bool m_configured;
public:
void setConfigured(bool _value);
bool getConfigured() const;
protected:
airtalgo::format m_format; //!< input Algo Format
public:
/**
* @brief Get the algo format.
* @return the current Format.
*/
airtalgo::format getFormat() const;
/**
* @brief Set the algo format.
* @param[in] _value New Format.
*/
void setFormat(airtalgo::format _value);
protected:
std::vector<airtalgo::channel> m_map; //!< input channel Map
public:
/**
* @brief Get the algo channel Map.
* @return the current channel Map.
*/
const std::vector<airtalgo::channel>& getMap() const;
/**
* @brief Set the algo channel Map.
* @param[in] _value New channel Map.
*/
void setMap(const std::vector<airtalgo::channel>& _value);
protected:
float m_frequency; //!< input Algo Format
public:
/**
* @brief Get the algo frequency.
* @return the current frequency.
*/
float getFrequency() const;
/**
* @brief Set the algo frequency.
* @param[in] _value New frequency.
*/
void setFrequency(float _value);
protected:
std::function<void()> m_ioChangeFunctor; //!< function pointer on the upper class
void configurationChange();
public:
/**
* @brief Set the callback function to be notify when the arameter change.
* @param[in] _functor Function to call.
*/
void setCallback(const std::function<void()>& _functor);
};
std::ostream& operator <<(std::ostream& _os, const IOFormatInterface& _obj);
}
#endif

View File

@ -12,12 +12,16 @@
#include <airtalgo/format.h>
#include <airtalgo/channel.h>
#include <airtalgo/Process.h>
#include <airtalgo/ChannelReorder.h>
#include <airtalgo/FormatUpdate.h>
#include <airtalgo/Resampler.h>
#include <chrono>
#undef __class__
#define __class__ "Process"
airtalgo::Process::Process() {
airtalgo::Process::Process() :
m_isConfigured(false) {
}
airtalgo::Process::~Process() {
@ -108,10 +112,12 @@ bool airtalgo::Process::process(std::chrono::system_clock::time_point& _time,
}
void airtalgo::Process::pushBack(const std::shared_ptr<airtalgo::Algo>& _algo) {
removeAlgoDynamic();
m_listAlgo.push_back(_algo);
}
void airtalgo::Process::pushFront(const std::shared_ptr<airtalgo::Algo>& _algo) {
removeAlgoDynamic();
m_listAlgo.insert(m_listAlgo.begin(), _algo);
}
@ -151,6 +157,10 @@ template<typename T> std::vector<T> getUnion(const std::vector<T>& _out, const s
}
void airtalgo::Process::updateInterAlgo() {
if (m_isConfigured == true) {
// cahin is already configured
return ;
}
AIRTALGO_INFO(" display properties : nbAlgo : " << m_listAlgo.size());
for (auto &it : m_listAlgo) {
AIRTALGO_INFO(" [" << it->getType() << "] '" << it->getName() << "'");
@ -175,33 +185,155 @@ void airtalgo::Process::updateInterAlgo() {
for (size_t iii=1; iii<m_listAlgo.size(); ++iii) {
if ( m_listAlgo[iii-1]->getOutputFormat().getConfigured() == false
&& m_listAlgo[iii]->getInputFormat().getConfigured() == false) {
std::vector<float> freq;
std::vector<std::vector<airtalgo::channel>> map;
std::vector<airtalgo::format> format;
// step 1 : check frequency:
freq = getUnion<float>(m_listAlgo[iii-1]->getFrequencySupportedOutput(),
m_listAlgo[iii]->getFrequencySupportedInput());
std::vector<float> freqOut = m_listAlgo[iii-1]->getFrequencySupportedOutput();
std::vector<float> freqIn = m_listAlgo[iii]->getFrequencySupportedInput();
std::vector<float> freq = getUnion<float>(freqOut, freqIn);
// step 2 : Check map:
map = getUnion<std::vector<airtalgo::channel>>(m_listAlgo[iii-1]->getMapSupportedOutput(),
m_listAlgo[iii]->getMapSupportedInput());
std::vector<std::vector<airtalgo::channel>> mapOut = m_listAlgo[iii-1]->getMapSupportedOutput();
std::vector<std::vector<airtalgo::channel>> mapIn = m_listAlgo[iii]->getMapSupportedInput();
std::vector<std::vector<airtalgo::channel>> map = getUnion<std::vector<airtalgo::channel>>(mapOut, mapIn);
// step 3 : Check Format:
format = getUnion<airtalgo::format>(m_listAlgo[iii-1]->getFormatSupportedOutput(),
m_listAlgo[iii]->getFormatSupportedInput());
std::vector<airtalgo::format> formatOut = m_listAlgo[iii-1]->getFormatSupportedOutput();
std::vector<airtalgo::format> formatIn = m_listAlgo[iii]->getFormatSupportedInput();
std::vector<airtalgo::format> format = getUnion<airtalgo::format>(formatOut, formatIn);
if ( freq.size() == 1
&& map.size() == 1
&& format.size() == 1) {
if ( freq.size() >= 1
&& map.size() >= 1
&& format.size() >= 1) {
AIRTALGO_INFO(" find 1 compatibility :{format=" << format << ",frequency=" << freq << ",map=" << map << "}");
airtalgo::IOFormatInterface tmp(map[0], format[0], freq[0]);
m_listAlgo[iii-1]->setOutputFormat(tmp);
m_listAlgo[iii]->setInputFormat(tmp);
continue;
}
// create mapping to transform:
airtalgo::IOFormatInterface out;
airtalgo::IOFormatInterface in;
if (freq.size() > 0) {
out.setFrequency(freq[0]);
in.setFrequency(freq[0]);
} else {
if (freqOut.size() == 0) {
if (freqIn.size() == 0) {
out.setFrequency(m_listAlgo[iii-1]->getInputFormat().getFrequency());
in.setFrequency(m_listAlgo[iii-1]->getInputFormat().getFrequency());
} else {
out.setFrequency(freqIn[0]);
in.setFrequency(freqIn[0]);
}
} else {
if (freqIn.size() == 0) {
out.setFrequency(freqOut[0]);
in.setFrequency(freqOut[0]);
} else {
out.setFrequency(freqOut[0]);
in.setFrequency(freqIn[0]);
}
}
}
if (map.size() > 0) {
out.setMap(map[0]);
in.setMap(map[0]);
} else {
if (mapOut.size() == 0) {
if (mapIn.size() == 0) {
out.setMap(m_listAlgo[iii-1]->getInputFormat().getMap());
in.setMap(m_listAlgo[iii-1]->getInputFormat().getMap());
} else {
out.setMap(mapIn[0]);
in.setMap(mapIn[0]);
}
} else {
if (mapIn.size() == 0) {
out.setMap(mapOut[0]);
in.setMap(mapOut[0]);
} else {
out.setMap(mapOut[0]);
in.setMap(mapIn[0]);
}
}
}
if (format.size() > 0) {
out.setFormat(format[0]);
in.setFormat(format[0]);
} else {
if (formatOut.size() == 0) {
if (formatIn.size() == 0) {
out.setFormat(m_listAlgo[iii-1]->getInputFormat().getFormat());
in.setFormat(m_listAlgo[iii-1]->getInputFormat().getFormat());
} else {
out.setFormat(formatIn[0]);
in.setFormat(formatIn[0]);
}
} else {
if (formatIn.size() == 0) {
out.setFormat(formatOut[0]);
in.setFormat(formatOut[0]);
} else {
out.setFormat(formatOut[0]);
in.setFormat(formatIn[0]);
}
}
}
AIRTALGO_INFO(" union:");
AIRTALGO_INFO(" format : " << format);
AIRTALGO_INFO(" frequency : " << freq);
AIRTALGO_INFO(" map : " << map);
AIRTALGO_INFO(" update: out=" << out);
AIRTALGO_INFO(" in=" << in);
m_listAlgo[iii-1]->setOutputFormat(out);
m_listAlgo[iii]->setInputFormat(in);
// TODO : Add updater with an optimisation of CPU
if (out.getFrequency() != in.getFrequency()) {
// TODO : Do it better: special check for resampler : only support int16_t
if ( out.getFormat() != format_int16
/* && out.getFormat() != format_float */) {
// need add a format Updater
std::shared_ptr<airtalgo::FormatUpdate> algo = airtalgo::FormatUpdate::create();
algo->setTemporary();
algo->setInputFormat(out);
out.setFormat(format_int16);
algo->setOutputFormat(out);
m_listAlgo.insert(m_listAlgo.begin()+iii, algo);
AIRTALGO_INFO("convert " << out.getFormat() << " -> " << in.getFormat());
iii++;
}
// need add a resampler
std::shared_ptr<airtalgo::Resampler> algo = airtalgo::Resampler::create();
algo->setTemporary();
algo->setInputFormat(out);
out.setFrequency(in.getFrequency());
algo->setOutputFormat(out);
m_listAlgo.insert(m_listAlgo.begin()+iii, algo);
AIRTALGO_INFO("convert " << out.getFrequency() << " -> " << in.getFrequency());
out.setFrequency(in.getFrequency());
iii++;
}
if (out.getMap() != in.getMap()) {
// need add a channel Reorder
std::shared_ptr<airtalgo::ChannelReorder> algo = airtalgo::ChannelReorder::create();
algo->setTemporary();
algo->setInputFormat(out);
out.setMap(in.getMap());
algo->setOutputFormat(out);
m_listAlgo.insert(m_listAlgo.begin()+iii, algo);
AIRTALGO_INFO("convert " << out.getMap() << " -> " << in.getMap());
iii++;
}
if (out.getFormat() != in.getFormat()) {
// need add a format Updater
std::shared_ptr<airtalgo::FormatUpdate> algo = airtalgo::FormatUpdate::create();
algo->setTemporary();
algo->setInputFormat(out);
out.setFormat(in.getFormat());
algo->setOutputFormat(out);
m_listAlgo.insert(m_listAlgo.begin()+iii, algo);
AIRTALGO_INFO("convert " << out.getFormat() << " -> " << in.getFormat());
iii++;
}
} else if ( m_listAlgo[iii-1]->getOutputFormat().getConfigured() == false
|| m_listAlgo[iii]->getInputFormat().getConfigured() == false) {
AIRTALGO_ERROR(" configuration error mode in " << iii-1 << " && " << iii );
@ -221,10 +353,14 @@ void airtalgo::Process::updateInterAlgo() {
AIRTALGO_ERROR(" Output : Not configured");
}
}
m_isConfigured = true;
//exit(-1);
}
void airtalgo::Process::removeAlgoDynamic() {
if (m_isConfigured == true) {
// chain is already unconfigured.
return;
}
m_isConfigured = false;
}

View File

@ -70,6 +70,7 @@ namespace airtalgo{
void pushBack(const std::shared_ptr<airtalgo::Algo>& _algo);
void pushFront(const std::shared_ptr<airtalgo::Algo>& _algo);
void clear() {
m_isConfigured = false;
m_listAlgo.clear();
}
template<typename T> void removeIfFirst() {
@ -100,6 +101,9 @@ namespace airtalgo{
}
return false;
}
private:
bool m_isConfigured;
public:
void updateInterAlgo();
void removeAlgoDynamic();
};

View File

@ -23,6 +23,7 @@ airtalgo::Resampler::Resampler() :
void airtalgo::Resampler::init() {
airtalgo::Algo::init();
m_type = "Resampler";
m_supportedFormat.push_back(format_int16);
}
std::shared_ptr<airtalgo::Resampler> airtalgo::Resampler::create() {
@ -82,7 +83,7 @@ bool airtalgo::Resampler::process(std::chrono::system_clock::time_point& _time,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
airtalgo::autoLogInOut tmpLog("Resampler");
airtalgo::AutoLogInOut tmpLog("Resampler");
_outputNbChunk = 2048;
// chack if we need to process:
if (m_needProcess == false) {

View File

@ -13,7 +13,8 @@
airtalgo::Volume::Volume() :
m_volumedB(0.0f),
m_volumeAppli(1.0f) {
m_volumeAppli(1.0f),
m_functionConvert(nullptr) {
}
@ -34,10 +35,104 @@ airtalgo::Volume::~Volume() {
}
static void convert__int16__to__int16(void* _input, void* _output, size_t _nbSample, int32_t _volumeCoef, int32_t _volumeDecalage, float _volumeAppli) {
int16_t* in = static_cast<int16_t*>(_input);
int16_t* out = static_cast<int16_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
out[iii] = int16_t((int32_t(in[iii]) * int32_t(_volumeCoef)) >> _volumeDecalage);
}
}
static void convert__int16__to__int32(void* _input, void* _output, size_t _nbSample, int32_t _volumeCoef, int32_t _volumeDecalage, float _volumeAppli) {
int16_t* in = static_cast<int16_t*>(_input);
int32_t* out = static_cast<int32_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
out[iii] = (int32_t(in[iii]) * int32_t(_volumeCoef)) >> _volumeDecalage;
}
//AIRTALGO_INFO("plop " << in[0] << " >> " << out[0]);
}
static void convert__int32__to__int16(void* _input, void* _output, size_t _nbSample, int32_t _volumeCoef, int32_t _volumeDecalage, float _volumeAppli) {
int32_t* in = static_cast<int32_t*>(_input);
int16_t* out = static_cast<int16_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
int32_t value = in[iii] >> 16;
out[iii] = int16_t((int64_t(in[iii]) * int64_t(_volumeCoef)) >> _volumeDecalage);
}
}
static void convert__int32__to__int32(void* _input, void* _output, size_t _nbSample, int32_t _volumeCoef, int32_t _volumeDecalage, float _volumeAppli) {
int32_t* in = static_cast<int32_t*>(_input);
int32_t* out = static_cast<int32_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
out[iii] = int32_t((int64_t(in[iii]) * int64_t(_volumeCoef)) >> _volumeDecalage);
}
//AIRTALGO_INFO("plop " << in[0] << " >> " << out[0]);
}
static void convert__float__to__float(void* _input, void* _output, size_t _nbSample, int32_t _volumeCoef, int32_t _volumeDecalage, float _volumeAppli) {
float* in = static_cast<float*>(_input);
float* out = static_cast<float*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
out[iii] = in[iii] * _volumeAppli;
}
}
void airtalgo::Volume::configurationChange() {
airtalgo::Algo::configurationChange();
if (m_input.getFormat() != m_output.getFormat()) {
AIRTALGO_ERROR("Volume format change is not supported");
switch (m_input.getFormat()) {
default:
case format_int16:
switch (m_output.getFormat()) {
default:
case format_int16:
m_functionConvert = &convert__int16__to__int16;
AIRTALGO_DEBUG("Use converter : 'convert__int16__to__int16' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_int16_on_int32:
case format_int32:
m_functionConvert = &convert__int16__to__int32;
AIRTALGO_DEBUG("Use converter : 'convert__int16__to__int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_float:
AIRTALGO_ERROR("Impossible case 1");
break;
}
break;
case format_int16_on_int32:
case format_int32:
switch (m_output.getFormat()) {
default:
case format_int16:
m_functionConvert = &convert__int32__to__int16;
AIRTALGO_DEBUG("Use converter : 'convert__int32__to__int16' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_int16_on_int32:
case format_int32:
m_functionConvert = &convert__int32__to__int32;
AIRTALGO_DEBUG("Use converter : 'convert__int32__to__int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_float:
AIRTALGO_ERROR("Impossible case 2");
break;
}
break;
case format_float:
switch (m_output.getFormat()) {
default:
case format_int16:
case format_int16_on_int32:
case format_int32:
AIRTALGO_ERROR("Impossible case 4");
break;
case format_float:
m_functionConvert = &convert__float__to__float;
AIRTALGO_DEBUG("Use converter : 'convert__float__to__float' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
}
break;
}
if (m_input.getMap() != m_output.getMap()) {
AIRTALGO_ERROR("Volume map change is not supported");
@ -46,29 +141,183 @@ void airtalgo::Volume::configurationChange() {
AIRTALGO_ERROR("Volume frequency change is not supported");
}
// nee to process all time (the format not change (just a simple filter))
m_needProcess = false;
m_needProcess = true;
}
void airtalgo::Volume::updateVolumeValues() {
//m_volumeAppli = 20 * log(m_volumedB);
m_volumeAppli = std::pow(10.0f, m_volumedB/20.0f);
switch (m_input.getFormat()) {
default:
case format_int16:
switch (m_output.getFormat()) {
default:
case format_int16:
if (m_volumeAppli <= 1.0f) {
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 16;
} else {
int32_t neareast = neareastsss(m_volumeAppli);
m_volumeCoef = m_volumeAppli*float(1<<(16-neareast));
m_volumeDecalage = 16-neareast;
}
break;
case format_int16_on_int32:
if (m_volumeAppli <= 1.0f) {
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 16;
} else {
int32_t neareast = neareastsss(m_volumeAppli);
m_volumeCoef = m_volumeAppli*float(1<<(16-neareast));
m_volumeDecalage = 16-neareast;
}
break;
case format_int32:
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 0;
break;
case format_float:
AIRTALGO_ERROR("Impossible case 1");
break;
}
break;
case format_int16_on_int32:
switch (m_output.getFormat()) {
default:
case format_int16:
if (m_volumeAppli <= 1.0f) {
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 16;
} else {
int32_t neareast = neareastsss(m_volumeAppli);
m_volumeCoef = m_volumeAppli*float(1<<(16-neareast));
m_volumeDecalage = 16-neareast;
}
break;
case format_int16_on_int32:
if (m_volumeAppli <= 1.0f) {
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 16;
} else {
int32_t neareast = neareastsss(m_volumeAppli);
m_volumeCoef = m_volumeAppli*float(1<<(16-neareast));
m_volumeDecalage = 16-neareast;
}
break;
case format_int32:
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 0;
break;
case format_float:
AIRTALGO_ERROR("Impossible case 2");
break;
}
break;
case format_int32:
switch (m_output.getFormat()) {
default:
case format_int16:
if (m_volumeAppli <= 1.0f) {
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 32;
} else {
int32_t neareast = neareastsss(m_volumeAppli);
m_volumeCoef = m_volumeAppli*float(1<<(16-neareast));
m_volumeDecalage = 32-neareast;
}
break;
case format_int16_on_int32:
if (m_volumeAppli <= 1.0f) {
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 32;
} else {
int32_t neareast = neareastsss(m_volumeAppli);
m_volumeCoef = m_volumeAppli*float(1<<(16-neareast));
m_volumeDecalage = 32-neareast;
}
break;
case format_int32:
m_volumeCoef = m_volumeAppli*float(1<<16);
m_volumeDecalage = 16;
break;
case format_float:
AIRTALGO_ERROR("Impossible case 3");
break;
}
break;
case format_float:
// nothing to do (use m_volumeAppli)
break;
}
}
std::vector<airtalgo::format> airtalgo::Volume::getFormatSupportedInput() {
return m_supportedFormat;
std::vector<airtalgo::format> tmp;
if (m_output.getFormat() == format_float) {
tmp.push_back(format_float);
}
if ( m_output.getFormat() == format_int16
|| m_output.getFormat() == format_int16_on_int32
|| m_output.getFormat() == format_int32) {
tmp.push_back(format_int16);
tmp.push_back(format_int16_on_int32);
tmp.push_back(format_int32);
}
return tmp;
};
std::vector<airtalgo::format> airtalgo::Volume::getFormatSupportedOutput() {
return m_supportedFormat;
std::vector<airtalgo::format> tmp;
if (m_input.getFormat() == format_float) {
tmp.push_back(format_float);
}
if ( m_input.getFormat() == format_int16
|| m_input.getFormat() == format_int16_on_int32
|| m_input.getFormat() == format_int32) {
tmp.push_back(format_int16);
tmp.push_back(format_int16_on_int32);
tmp.push_back(format_int32);
}
return tmp;
};
static int32_t neareastsss(float _val) {
int32_t out = 0;
while (_val > float(1<<out)) {
out++;
}
return std::min(16,out);
}
bool airtalgo::Volume::process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
airtalgo::autoLogInOut tmpLog("Volume");
if (m_volumeAppli == 1.0f) {
airtalgo::AutoLogInOut tmpLog("Volume");
// chack if we need to process:
if (m_needProcess == false) {
_output = _input;
_outputNbChunk = _inputNbChunk;
return true;
}
if (_input == nullptr) {
_output = &(m_outputData[0]);
_outputNbChunk = 0;
AIRTALGO_ERROR("null pointer input ... ");
return false;
}
_outputNbChunk = _inputNbChunk;
m_outputData.resize(_outputNbChunk*m_input.getMap().size()*m_formatSize);
_output = &(m_outputData[0]);
if (m_functionConvert == nullptr) {
AIRTALGO_ERROR("null function ptr");
return false;
}
// Calculate in every case the volume to apply :
updateVolumeValues();
//AIRTALGO_WARNING("Apply volume : " << m_volumedB << "dB " << m_volumeAppli << " ==> x*" << m_volumeCoef << ">>" << m_volumeDecalage << " ex:50*C>>D=" << (50*m_volumeCoef>>m_volumeDecalage) );
m_functionConvert(_input, _output, _outputNbChunk*m_input.getMap().size(), m_volumeCoef, m_volumeDecalage, m_volumeAppli);
return true;
}

View File

@ -14,10 +14,21 @@
#include <memory>
namespace airtalgo {
// TODO: Optimisation
// TODO: Zero crossing
// TODO: Continuous update volume
// TODO: Manage multiple volume
// TODO: Manage set volume
class Volume : public Algo {
private:
float m_volumedB;
// for float input :
float m_volumeAppli;
// for integer input :
int32_t m_volumeDecalage; // Volume to apply is simple as : X * m_coef >> m_coef
int32_t m_volumeCoef;
// convertion function:
void (*m_functionConvert)(void* _input, void* _output, size_t _nbSample, int32_t _volumeCoef, int32_t _volumeDecalage, float _volumeAppli);
protected:
/**
* @brief Constructor
@ -41,6 +52,8 @@ namespace airtalgo {
public:
virtual std::vector<airtalgo::format> getFormatSupportedInput();
virtual std::vector<airtalgo::format> getFormatSupportedOutput();
protected:
virtual void updateVolumeValues();
};
};

View File

@ -24,10 +24,12 @@ def create(target):
'airtalgo/FormatUpdate.cpp',
'airtalgo/Process.cpp',
'airtalgo/Resampler.cpp',
'airtalgo/Volume.cpp'
'airtalgo/Volume.cpp',
'airtalgo/IOFormatInterface.cpp',
'airtalgo/AutoLogInOut.cpp'
])
# TODO: myModule.add_optionnal_module_depend('speexdsp', "HAVE_SPEEX_DSP_RESAMPLE")
# TODO: myModule.add_optional_module_depend('speexdsp', "HAVE_SPEEX_DSP_RESAMPLE")
myModule.compile_flags_CC("-DHAVE_SPEEX_DSP_RESAMPLE")
myModule.add_module_depend(['etk', 'speexdsp'])
myModule.add_export_path(tools.get_current_path(__file__))