[DEV] create algo basic interface for simple audio flow

This commit is contained in:
Edouard DUPIN 2015-01-25 22:10:49 +01:00
commit 51d16858c5
28 changed files with 1768 additions and 0 deletions

80
airtalgo/Algo.cpp Normal file
View File

@ -0,0 +1,80 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <airtalgo/Algo.h>
#include <functional>
#include "debug.h"
airtalgo::Algo::Algo() :
m_outputData(),
m_formatSize(0),
m_needProcess(false) {
// set notification callback :
m_input.setCallback(std::bind(&airtalgo::Algo::configurationChange, this));
m_output.setCallback(std::bind(&airtalgo::Algo::configurationChange, this));
// first configure ==> update the internal parameters
configurationChange();
}
void airtalgo::Algo::configurationChange() {
m_needProcess = false;
if (m_input.getFormat() != m_output.getFormat()) {
m_needProcess = true;
}
if (m_input.getMap() != m_output.getMap()) {
m_needProcess = true;
}
if (m_input.getFrequency() != m_output.getFrequency()) {
m_needProcess = true;
}
switch (m_output.getFormat()) {
case format_int16:
m_formatSize = sizeof(int16_t);
break;
case format_int16_on_int32:
case format_int32:
m_formatSize = sizeof(int32_t);
break;
case format_float:
m_formatSize = sizeof(float);
break;
}
}
size_t airtalgo::Algo::needInputData(size_t _output) {
size_t input = _output;
if (m_input.getFormat() != m_output.getFormat()) {
int32_t inputSize = 3;
switch (m_input.getFormat()) {
case format_int16:
inputSize = sizeof(int16_t);
break;
case format_int16_on_int32:
case format_int32:
inputSize = sizeof(int32_t);
break;
case format_float:
inputSize = sizeof(float);
break;
}
if (inputSize != m_formatSize) {
input *= inputSize;
input /= m_formatSize;
}
}
if (m_input.getMap().size() != m_output.getMap().size()) {
input *= m_input.getMap().size();
input /= m_output.getMap().size();
}
if (m_input.getFrequency() != m_output.getFrequency()) {
input *= m_input.getFrequency();
input /= m_output.getFrequency();
// to prevent missing data in the resampler
input += 2;
}
return input;
}

197
airtalgo/Algo.h Normal file
View File

@ -0,0 +1,197 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_CORE_ALGO_H__
#define __AIRT_ALGO_CORE_ALGO_H__
#include <string>
#include <vector>
#include <stdint.h>
#include <airtalgo/format.h>
#include <airtalgo/channel.h>
#include <chrono>
#include <functional>
#include "debug.h"
namespace airtalgo{
class autoLogInOut {
private:
std::string m_value;
public:
autoLogInOut(const std::string& _value) :
m_value(_value) {
AIRTALGO_DEBUG(" '" << m_value << "' [START]");
}
~autoLogInOut() {
AIRTALGO_DEBUG(" '" << m_value << "' [STOP]");
}
};
class IOFormatInterface {
public:
IOFormatInterface() :
m_format(airtalgo::format_int16),
m_map(),
m_frequency(48000) {
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) :
m_format(_format),
m_map(_map),
m_frequency(_frequency) {
}
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;
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;
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_frequency = _value;
configurationChange();
}
protected:
std::function<void()> m_ioChangeFunctor; //!< function pointer on the upper class
void configurationChange() {
if (m_ioChangeFunctor != NULL) {
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;
}
};
class Algo {
protected:
std::vector<int8_t> m_outputData;
int8_t m_formatSize; //!< sample size
public:
/**
* @brief Constructor
*/
Algo();
/**
* @brief Destructor
*/
virtual ~Algo() {};
protected:
bool m_needProcess; //!< if no change, then no need to process, just forward buffer...
IOFormatInterface m_input; //!< Input audio property
public:
void setInputFormat(const IOFormatInterface& _format) {
m_input.setFormat(_format.getFormat());
m_input.setFrequency(_format.getFrequency());
m_input.setMap(_format.getMap());
}
const IOFormatInterface& getInputFormat() const {
return m_input;
}
protected:
IOFormatInterface m_output; //!< Output audio property
public:
void setOutputFormat(const IOFormatInterface& _format) {
m_output.setFormat(_format.getFormat());
m_output.setFrequency(_format.getFrequency());
m_output.setMap(_format.getMap());
}
const IOFormatInterface& getOutputFormat() const {
return m_output;
}
/**
* @brief Called when a parameter change
*/
virtual void configurationChange();
public:
/**
* @brief Process Algorithm
* @param[in] _time Current buffer Time
* @param[in] _input input pointer data (not free)
* @param[in] _inputNbChunk Number of chunk in the buffer
* @param[in] _output Output buffer (provide here) Do not free (can be the input buffer)
* @param[in] _outputNbChunk Number of chunk in the output buffer
* @return true The process is done corectly
* @return false An error occured
*/
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) = 0;
/**
* @brief To approximatively have the correct input of data of every algo ge call it to have an aproxomation of input data needed.
* @param[in] _output number of chunk estimate in output
* @return number of sample needed to have nearly the good number of sample
*/
virtual size_t needInputData(size_t _output);
};
};
#include "debugRemove.h"
#endif

125
airtalgo/ChannelReorder.cpp Normal file
View File

@ -0,0 +1,125 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <airtalgo/ChannelReorder.h>
#include <iostream>
#include "debug.h"
#include "debug.h"
airtalgo::ChannelReorder::ChannelReorder() {
}
void airtalgo::ChannelReorder::configurationChange() {
airtalgo::autoLogInOut("ChannelReorder (config)");
airtalgo::Algo::configurationChange();
if (m_input.getFormat() != m_output.getFormat()) {
AIRTALGO_ERROR("can not support Format Change ...");
m_needProcess = false;
}
if (m_input.getFrequency() != m_output.getFrequency()) {
AIRTALGO_ERROR("can not support frequency Change ...");
m_needProcess = false;
}
if (m_input.getMap() == m_output.getMap()) {
// nothing to process...
m_needProcess = false;
AIRTALGO_INFO(" no need to convert ... " << m_input.getMap() << " ==> " << m_output.getMap());
return;
}
}
bool airtalgo::ChannelReorder::process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
//airtalgo::autoLogInOut("ChannelReorder");
_outputNbChunk = _inputNbChunk;
// chack if we need to process:
if (m_needProcess == false) {
_output = _input;
return true;
}
if (_input == nullptr) {
_output = &(m_outputData[0]);
_outputNbChunk = 0;
AIRTALGO_ERROR("null pointer input ... ");
return false;
}
m_outputData.resize(_outputNbChunk*m_output.getMap().size()*m_formatSize);
_output = &(m_outputData[0]);
// real process: (only depend of data size):
switch (m_output.getFormat()) {
default:
case format_int16:
{
AIRTALGO_INFO("convert " << m_input.getMap() << " ==> " << m_output.getMap());
int16_t* in = static_cast<int16_t*>(_input);
int16_t* out = static_cast<int16_t*>(_output);
for (size_t kkk=0; kkk<m_output.getMap().size(); ++kkk) {
int32_t convertId = -1;
if ( m_input.getMap().size() == 1
&& m_input.getMap()[0] == airtalgo::channel_frontCenter) {
convertId = 0;
} else {
for (size_t jjj=0; jjj<m_input.getMap().size(); ++jjj) {
if (m_output.getMap()[kkk] == m_input.getMap()[jjj]) {
convertId = jjj;
break;
}
}
}
if (convertId == -1) {
for (size_t iii=0; iii<_outputNbChunk; ++iii) {
out[iii*m_output.getMap().size()+kkk] = 0;
}
} else {
for (size_t iii=0; iii<_outputNbChunk; ++iii) {
out[iii*m_output.getMap().size()+kkk] = in[iii*m_input.getMap().size()+convertId];
}
}
}
}
break;
case format_int16_on_int32:
case format_int32:
case format_float:
{
AIRTALGO_INFO("convert (2) " << m_input.getMap() << " ==> " << m_output.getMap());
uint32_t* in = static_cast<uint32_t*>(_input);
uint32_t* out = static_cast<uint32_t*>(_output);
for (size_t kkk=0; kkk<m_output.getMap().size(); ++kkk) {
int32_t convertId = -1;
if ( m_input.getMap().size() == 1
&& m_input.getMap()[0] == airtalgo::channel_frontCenter) {
convertId = 0;
} else {
for (size_t jjj=0; jjj<m_input.getMap().size(); ++jjj) {
if (m_output.getMap()[kkk] == m_input.getMap()[jjj]) {
convertId = jjj;
break;
}
}
}
if (convertId == -1) {
for (size_t iii=0; iii<_outputNbChunk; ++iii) {
out[iii*m_output.getMap().size()+kkk] = 0;
}
} else {
for (size_t iii=0; iii<_outputNbChunk; ++iii) {
out[iii*m_output.getMap().size()+kkk] = in[iii*m_input.getMap().size()+convertId];
}
}
}
}
break;
}
return true;
}

34
airtalgo/ChannelReorder.h Normal file
View File

@ -0,0 +1,34 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_CHANNEL_REORDER_H__
#define __AIRT_ALGO_CHANNEL_REORDER_H__
#include <airtalgo/Algo.h>
namespace airtalgo{
class ChannelReorder : public Algo {
public:
/**
* @brief Constructor
*/
ChannelReorder();
/**
* @brief Destructor
*/
virtual ~ChannelReorder() {};
protected:
virtual void configurationChange();
public:
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk);
};
};
#endif

0
airtalgo/EndPoint.cpp Normal file
View File

26
airtalgo/EndPoint.h Normal file
View File

@ -0,0 +1,26 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_END_POINT_H__
#define __AIRT_ALGO_END_POINT_H__
#include <airtalgo/Algo.h>
namespace airtalgo{
class EndPoint : public Algo {
public:
/**
* @brief Constructor
*/
EndPoint() {};
/**
* @brief Destructor
*/
virtual ~EndPoint() {};
};
};
#endif

View File

@ -0,0 +1,65 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <airtalgo/EndPointCallback.h>
airtalgo::EndPointCallback::EndPointCallback(needDataFunction _callback, enum formatDataType _dataFormat) :
m_dataFormat(_dataFormat),
m_output(_callback),
m_input(nullptr) {
}
airtalgo::EndPointCallback::EndPointCallback(haveNewDataFunction _callback, enum formatDataType _dataFormat) :
m_dataFormat(_dataFormat),
m_output(nullptr),
m_input(_callback) {
}
void airtalgo::EndPointCallback::configurationChange() {
airtalgo::EndPoint::configurationChange();
m_needProcess = true;
}
bool airtalgo::EndPointCallback::process(std::chrono::system_clock::time_point& _time,
void* _input, // uneeded
size_t _inputNbChunk, // requested number of sample ...
void*& _output,
size_t& _outputNbChunk){
airtalgo::autoLogInOut("EndPointCallback");
/*
if (m_output != nullptr) {
// call user
AIRTALGO_INFO("call user get I16*" << _inputNbChunk << "*" << airtalgo::Algo::m_output.getMap().size() << " " << airtalgo::Algo::m_output.getMap());
m_data = m_output(_time, _inputNbChunk, airtalgo::Algo::m_output.getMap());
if (m_data.size() != _inputNbChunk*airtalgo::Algo::m_output.getMap().size()) {
//ERROR
return false;
}
_output = &m_data[0];
_outputNbChunk = _inputNbChunk;
return true;
}
if (m_input != nullptr) {
// convert in data :
// TODO : ...
m_data.resize(_inputNbChunk*airtalgo::Algo::m_input.getMap().size());
int16_t* data = static_cast<int16_t*>(_input);
for (size_t iii; iii<m_data.size(); ++iii) {
m_data[iii] = *data++;
}
// Call user ...
AIRTALGO_INFO("call user set I16*" << _inputNbChunk << "*" << airtalgo::Algo::m_input.getMap().size());
m_input(_time, _inputNbChunk, airtalgo::Algo::m_input.getMap(), m_data);
return true;
}
*/
return false;
}

View File

@ -0,0 +1,46 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_END_POINT_CALLBACK_H__
#define __AIRT_ALGO_END_POINT_CALLBACK_H__
#include <airtalgo/EndPoint.h>
#include <functional>
namespace airtalgo {
enum formatDataType {
formatDataTypeInt16,
formatDataTypeInt32,
};
typedef std::function<void (const std::chrono::system_clock::time_point& _playTime, size_t _nbChunk, const std::vector<airtalgo::channel>& _map, void* _data, enum formatDataType& _type)> needDataFunction;
typedef std::function<void (const std::chrono::system_clock::time_point& _readTime, size_t _nbChunk, const std::vector<airtalgo::channel>& _map, const void* _data, enum formatDataType& _type)> haveNewDataFunction;
class EndPointCallback : public EndPoint {
private:
enum formatDataType m_dataFormat;
needDataFunction m_output;
haveNewDataFunction m_input;
std::vector<uint8_t> m_data;
public:
/**
* @brief Constructor
*/
EndPointCallback(needDataFunction _callback, enum formatDataType _dataFormat);
EndPointCallback(haveNewDataFunction _callback, enum formatDataType _dataFormat);
/**
* @brief Destructor
*/
virtual ~EndPointCallback() {};
virtual void configurationChange();
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk);
};
};
#endif

29
airtalgo/EndPointRead.cpp Normal file
View File

@ -0,0 +1,29 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <airtalgo/EndPointRead.h>
airtalgo::EndPointRead::EndPointRead() {
}
void airtalgo::EndPointRead::configurationChange() {
airtalgo::EndPoint::configurationChange();
m_needProcess = true;
}
bool airtalgo::EndPointRead::process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk){
airtalgo::autoLogInOut("EndPointRead");
return false;
}

32
airtalgo/EndPointRead.h Normal file
View File

@ -0,0 +1,32 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_END_POINT_READ_H__
#define __AIRT_ALGO_END_POINT_READ_H__
#include <airtalgo/EndPoint.h>
namespace airtalgo{
class EndPointRead : public EndPoint {
public:
/**
* @brief Constructor
*/
EndPointRead();
/**
* @brief Destructor
*/
virtual ~EndPointRead() {};
virtual void configurationChange();
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk);
};
};
#endif

View File

@ -0,0 +1,65 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <airtalgo/EndPointWrite.h>
airtalgo::EndPointWrite::EndPointWrite() :
m_function(nullptr) {
}
void airtalgo::EndPointWrite::configurationChange() {
airtalgo::EndPoint::configurationChange();
m_needProcess = true;
}
bool airtalgo::EndPointWrite::process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk){
//airtalgo::autoLogInOut("EndPointWrite");
//AIRTALGO_INFO(" nb Sample in buffer : " << m_tmpData.size());
if (m_function != nullptr) {
if (m_tmpData.size() <= 20000) {
m_function(_time, _inputNbChunk, m_output.getMap());
}
}
// resize output buffer:
//AIRTALGO_INFO(" resize : " << (int32_t)m_formatSize << "*" << (int32_t)_inputNbChunk << "*" << (int32_t)m_outputMap.size());
m_outputData.resize(m_formatSize*_inputNbChunk*m_output.getMap().size());
// clear buffer
memset(&m_outputData[0], 0, m_outputData.size());
// set output pointer:
_outputNbChunk = m_outputData.size()/(m_formatSize*m_output.getMap().size());
_output = &m_outputData[0];
std::unique_lock<std::mutex> lock(m_mutex);
// check if data in the tmpBuffer
if (m_tmpData.size() == 0) {
AIRTALGO_WARNING("No data in the user buffer (write null data ... " << _outputNbChunk << " chunks)");
// just send no data ...
return true;
}
AIRTALGO_INFO("Write " << _outputNbChunk << " chunks");
// check if we have enought data:
int32_t nbChunkToCopy = std::min(_inputNbChunk, m_outputData.size()/m_output.getMap().size());
// copy data to the output:
memcpy(_output, &m_tmpData[0], nbChunkToCopy*m_output.getMap().size()*m_formatSize);
// remove old data:
m_tmpData.erase(m_tmpData.begin(), m_tmpData.begin()+nbChunkToCopy*m_output.getMap().size());
//AIRTALGO_INFO(" nb Sample in buffer : " << m_tmpData.size());
return true;
}
void airtalgo::EndPointWrite::write(const int16_t* _value, size_t _nbValue) {
std::unique_lock<std::mutex> lock(m_mutex);
AIRTALGO_INFO("[ASYNC] Get data : " << _nbValue << " ==> " << _nbValue/m_output.getMap().size() << " chumks");
for (size_t iii=0; iii<_nbValue; ++iii) {
m_tmpData.push_back(*_value++);
}
}

43
airtalgo/EndPointWrite.h Normal file
View File

@ -0,0 +1,43 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_ALGO_END_POINT_WRITE_H__
#define __AIRT_ALGO_ALGO_END_POINT_WRITE_H__
#include <airtalgo/EndPoint.h>
#include <mutex>
#include <functional>
namespace airtalgo{
typedef std::function<void (const std::chrono::system_clock::time_point& _playTime, const size_t& _nbChunk, const std::vector<airtalgo::channel>& _map)> writeNeedDataFunction_int16_t;
class EndPointWrite : public EndPoint {
private:
std::vector<int16_t> m_tmpData;
writeNeedDataFunction_int16_t m_function;
std::mutex m_mutex;
public:
/**
* @brief Constructor
*/
EndPointWrite();
/**
* @brief Destructor
*/
virtual ~EndPointWrite() {};
virtual void configurationChange();
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk);
virtual void write(const int16_t* _value, size_t _nbValue);
virtual void setCallback(writeNeedDataFunction_int16_t _function) {
m_function = _function;
}
};
};
#endif

259
airtalgo/FormatUpdate.cpp Normal file
View File

@ -0,0 +1,259 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <airtalgo/FormatUpdate.h>
#include <iostream>
#ifndef INT16_MAX
#define INT16_MAX 0x7fff
#endif
#ifndef INT16_MIN
#define INT16_MIN (-INT16_MAX - 1)
#endif
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffffL
#endif
#ifndef INT32_MIN
#define INT32_MIN (-INT32_MAX - 1L)
#endif
static void convert__int16__to__int16_on_int32(void* _input, void* _output, size_t _nbSample) {
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] = in[iii];
}
}
static void convert__int16__to__int32(void* _input, void* _output, size_t _nbSample) {
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] = in[iii]<<16;
}
}
static void convert__int16__to__float(void* _input, void* _output, size_t _nbSample) {
int16_t* in = static_cast<int16_t*>(_input);
float* out = static_cast<float*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
// TODO : Set * intead of /
out[iii] = static_cast<float>(in[iii])/static_cast<float>(INT16_MAX);
}
}
static void convert__int16_on_int32__to__int16(void* _input, void* _output, size_t _nbSample) {
int32_t* in = static_cast<int32_t*>(_input);
int16_t* out = static_cast<int16_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
out[iii] = static_cast<int16_t>(std::min(std::max(INT16_MIN, in[iii]), INT16_MAX));
}
}
static void convert__int16_on_int32__to__int32(void* _input, void* _output, size_t _nbSample) {
int32_t* in = static_cast<int32_t*>(_input);
int32_t* out = static_cast<int32_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
int32_t value = std::min(std::max(INT16_MIN, in[iii]), INT16_MAX);
out[iii] = value << 16;
}
}
static void convert__int16_on_int32__to__float(void* _input, void* _output, size_t _nbSample) {
int32_t* in = static_cast<int32_t*>(_input);
float* out = static_cast<float*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
// TODO : Set * intead of /
out[iii] = static_cast<float>(in[iii])/static_cast<float>(INT16_MAX);
}
}
static void convert__int32__to__int16(void* _input, void* _output, size_t _nbSample) {
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] = static_cast<int16_t>(std::min(std::max(INT16_MIN, value), INT16_MAX));
}
}
static void convert__int32__to__int16_on_int32(void* _input, void* _output, size_t _nbSample) {
int32_t* in = static_cast<int32_t*>(_input);
int16_t* out = static_cast<int16_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
out[iii] = in[iii] >> 16;
}
}
static void convert__int32__to__float(void* _input, void* _output, size_t _nbSample) {
int32_t* in = static_cast<int32_t*>(_input);
float* out = static_cast<float*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
// TODO : Set * intead of /
out[iii] = static_cast<float>(in[iii])/static_cast<float>(INT32_MAX);
}
}
static void convert__float__to__int16(void* _input, void* _output, size_t _nbSample) {
float* in = static_cast<float*>(_input);
int16_t* out = static_cast<int16_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
float value = in[iii] * static_cast<float>(INT16_MAX);
value = std::min(std::max(static_cast<float>(INT16_MIN), value), static_cast<float>(INT16_MAX));
out[iii] = static_cast<int16_t>(value);
//AIRTALGO_VERBOSE(" in=" << in[iii] << " out=" << out[iii]);
}
}
static void convert__float__to__int16_on_int32(void* _input, void* _output, size_t _nbSample) {
float* in = static_cast<float*>(_input);
int32_t* out = static_cast<int32_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
float value = in[iii] * static_cast<float>(INT16_MAX);
value = std::min(std::max(static_cast<float>(INT32_MIN), value), static_cast<float>(INT32_MAX));
out[iii] = static_cast<int32_t>(value);
}
}
static void convert__float__to__int32(void* _input, void* _output, size_t _nbSample) {
float* in = static_cast<float*>(_input);
int32_t* out = static_cast<int32_t*>(_output);
for (size_t iii=0; iii<_nbSample; ++iii) {
float value = in[iii] * static_cast<float>(INT32_MAX);
value = std::min(std::max(static_cast<float>(INT32_MIN), value), static_cast<float>(INT32_MAX));
out[iii] = static_cast<int32_t>(value);
}
}
airtalgo::FormatUpdate::FormatUpdate() :
m_functionConvert(NULL) {
}
void airtalgo::FormatUpdate::configurationChange() {
airtalgo::Algo::configurationChange();
if (m_input.getMap() != m_output.getMap()) {
AIRTALGO_ERROR("can not support Map Change ...");
m_needProcess = false;
}
if (m_input.getFrequency() != m_output.getFrequency()) {
AIRTALGO_ERROR("can not support frequency Change ...");
m_needProcess = false;
}
if (m_input.getFormat() == m_output.getFormat()) {
// nothing to process...
m_needProcess = false;
return;
}
switch (m_input.getFormat()) {
default:
case format_int16:
switch (m_output.getFormat()) {
default:
case format_int16:
AIRTALGO_ERROR(" Impossible case 1");
break;
case format_int16_on_int32:
m_functionConvert = &convert__int16__to__int16_on_int32;
AIRTALGO_DEBUG(" use converter : 'convert__int16__to__int16_on_int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
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:
m_functionConvert = &convert__int16__to__float;
AIRTALGO_DEBUG(" use converter : 'convert__int16__to__float' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
}
break;
case format_int16_on_int32:
switch (m_output.getFormat()) {
default:
case format_int16:
m_functionConvert = &convert__int16_on_int32__to__int16;
AIRTALGO_DEBUG(" use converter : 'convert__int16_on_int32__to__int16' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_int16_on_int32:
AIRTALGO_ERROR(" Impossible case 2");
break;
case format_int32:
m_functionConvert = &convert__int16_on_int32__to__int32;
AIRTALGO_DEBUG(" use converter : 'convert__int16_on_int32__to__int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_float:
m_functionConvert = &convert__int16_on_int32__to__float;
AIRTALGO_DEBUG(" use converter : 'convert__int16_on_int32__to__float' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
}
break;
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:
m_functionConvert = &convert__int32__to__int16_on_int32;
AIRTALGO_DEBUG(" use converter : 'convert__int32__to__int16_on_int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_int32:
AIRTALGO_ERROR(" Impossible case 3");
break;
case format_float:
m_functionConvert = &convert__int32__to__float;
AIRTALGO_DEBUG(" use converter : 'convert__int32__to__float' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
}
break;
case format_float:
switch (m_output.getFormat()) {
default:
case format_int16:
m_functionConvert = &convert__float__to__int16;
AIRTALGO_DEBUG(" use converter : 'convert__float__to__int16' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_int16_on_int32:
m_functionConvert = &convert__float__to__int16_on_int32;
AIRTALGO_DEBUG(" use converter : 'convert__float__to__int16_on_int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_int32:
m_functionConvert = &convert__float__to__int32;
AIRTALGO_DEBUG(" use converter : 'convert__float__to__int32' for " << m_input.getFormat() << " to " << m_output.getFormat());
break;
case format_float:
AIRTALGO_ERROR(" Impossible case 4");
break;
}
break;
}
}
bool airtalgo::FormatUpdate::process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
//airtalgo::autoLogInOut("FormatUpdate");
// chack if we need to process:
if (m_needProcess == false) {
_output = _input;
_outputNbChunk = _inputNbChunk;
return true;
}
if (_input == NULL) {
_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 == NULL) {
AIRTALGO_ERROR("null function ptr");
return false;
}
m_functionConvert(_input, _output, _outputNbChunk*m_input.getMap().size());
return true;
}

35
airtalgo/FormatUpdate.h Normal file
View File

@ -0,0 +1,35 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_FORMAT_UPDATE_H__
#define __AIRT_ALGO_FORMAT_UPDATE_H__
#include <airtalgo/Algo.h>
namespace airtalgo {
class FormatUpdate : public Algo {
public:
/**
* @brief Constructor
*/
FormatUpdate();
/**
* @brief Destructor
*/
virtual ~FormatUpdate() {};
protected:
virtual void configurationChange();
public:
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk);
private:
void (*m_functionConvert)(void* _input, void* _output, size_t _nbSample);
};
};
#endif

81
airtalgo/Process.cpp Normal file
View File

@ -0,0 +1,81 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <string>
#include <vector>
#include <stdint.h>
#include <airtalgo/format.h>
#include <airtalgo/channel.h>
#include <airtalgo/Process.h>
#include <chrono>
airtalgo::Process::Process() {
}
bool airtalgo::Process::push(std::chrono::system_clock::time_point& _time,
void* _data,
size_t _nbChunk) {
void* out = nullptr;
size_t nbChunkOut;
AIRTALGO_VERBOSE(" Interface DIRECT ");
process(_time, _data, _nbChunk, out, nbChunkOut);
}
bool airtalgo::Process::pull(std::chrono::system_clock::time_point& _time,
void*& _data,
size_t& _nbChunk) {
void* in = nullptr;
size_t nbChunkIn = _nbChunk;
void* out = nullptr;
size_t nbChunkOut;
if (nbChunkIn < 128) {
nbChunkIn = 128;
}
for (int32_t iii=m_listAlgo.size()-1; iii >=0; --iii) {
if (m_listAlgo[iii] != nullptr) {
nbChunkIn = m_listAlgo[iii]->needInputData(nbChunkIn);
}
}
if (nbChunkIn < 32) {
nbChunkIn = 32;
}
process(_time, in, nbChunkIn, _data, _nbChunk);
}
bool airtalgo::Process::process(std::chrono::system_clock::time_point& _time,
void* _inData,
size_t _inNbChunk,
void*& _outData,
size_t& _outNbChunk) {
if (m_listAlgo.size() == 0) {
_outData = _inData;
_outNbChunk = _inNbChunk;
return true;
}
for (size_t iii=0; iii<m_listAlgo.size(); ++iii) {
//std::cout << " Algo " << iii+1 << "/" << m_listAlgo.size() << std::endl;
if (m_listAlgo[iii] != nullptr) {
m_listAlgo[iii]->process(_time, _inData, _inNbChunk, _outData, _outNbChunk);
_inData = _outData;
_inNbChunk = _outNbChunk;
}
}
}
void airtalgo::Process::pushBack(const std::shared_ptr<airtalgo::Algo>& _algo) {
m_listAlgo.push_back(_algo);
}
void airtalgo::Process::pushFront(const std::shared_ptr<airtalgo::Algo>& _algo) {
m_listAlgo.insert(m_listAlgo.begin(), _algo);
}
void airtalgo::Process::updateInterAlgo() {
// TODO : ...
}

74
airtalgo/Process.h Normal file
View File

@ -0,0 +1,74 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_PROCESS_H__
#define __AIRT_ALGO_PROCESS_H__
#include <string>
#include <vector>
#include <stdint.h>
#include <airtalgo/format.h>
#include <airtalgo/channel.h>
#include <airtalgo/Algo.h>
#include <chrono>
#include <memory>
namespace airtalgo{
class Process {
public:
Process();
public:
/**
* @brief Push data in the algo stream.
* @param[in] _time Time of the first sample pushed.
* @param[in] _data Pointer on the data pushed.
* @param[in] _nbChunk Number of chunk present in the pointer.
* @return true The procress is done corectly.
* @return false An error occured.
*/
bool push(std::chrono::system_clock::time_point& _time,
void* _data,
size_t _nbChunk);
/**
* @brief Push data in the algo stream.
* @param[in] _time Time of the first sample requested.
* @param[in] _data Pointer on the data pushed.
* @param[in,out] _nbChunk Number of chunk present in the pointer (set at the number of chunk requested(hope)).
* @return true The procress is done corectly.
* @return false An error occured.
*/
bool pull(std::chrono::system_clock::time_point& _time,
void*& _data,
size_t& _nbChunk);
/**
* @brief Push data in the algo stream.
* @param[in] _time Time of the first sample pushed.
* @param[in] _inData Pointer on the data pushed.
* @param[in] _inNbChunk Number of chunk present in the input pointer.
* @param[out] _outData Pointer on the data geted.
* @param[out] _outNbChunk Number of chunk present in the output pointer.
* @return true The procress is done corectly.
* @return false An error occured.
*/
bool process(std::chrono::system_clock::time_point& _time,
void* _inData,
size_t _inNbChunk,
void*& _outData,
size_t& _outNbChunk);
protected:
std::vector<std::shared_ptr<airtalgo::Algo> > m_listAlgo;
public:
void pushBack(const std::shared_ptr<airtalgo::Algo>& _algo);
void pushFront(const std::shared_ptr<airtalgo::Algo>& _algo);
void updateInterAlgo();
void clear() {
m_listAlgo.clear();
}
};
};
#endif

129
airtalgo/Resampler.cpp Normal file
View File

@ -0,0 +1,129 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <airtalgo/Resampler.h>
#include <iostream>
airtalgo::Resampler::Resampler() :
#ifdef HAVE_SPEEX_DSP_RESAMPLE
m_speexResampler(nullptr),
#endif
m_positionRead(0),
m_positionWrite(0) {
}
airtalgo::Resampler::~Resampler() {
#ifdef HAVE_SPEEX_DSP_RESAMPLE
if (m_speexResampler != nullptr) {
speex_resampler_destroy(m_speexResampler);
m_speexResampler = nullptr;
}
#endif
}
void airtalgo::Resampler::configurationChange() {
airtalgo::Algo::configurationChange();
if (m_input.getFormat() != m_output.getFormat()) {
AIRTALGO_ERROR("can not support Format Change ...");
m_needProcess = false;
}
if (m_input.getFormat() != format_int16) {
AIRTALGO_ERROR("can not support Format other than int16_t ...");
m_needProcess = false;
return;
}
if (m_output.getMap() != m_output.getMap()) {
AIRTALGO_ERROR("can not support map Change ...");
m_needProcess = false;
}
if (m_input.getFrequency() == m_output.getFrequency()) {
// nothing to process...
m_needProcess = false;
return;
}
#ifdef HAVE_SPEEX_DSP_RESAMPLE
if (m_speexResampler != nullptr) {
speex_resampler_destroy(m_speexResampler);
m_speexResampler = nullptr;
}
int err = 0;
m_speexResampler = speex_resampler_init(m_outputMap.size(),
m_inputFrequency,
m_outputFrequency,
10, &err);
#else
std::cerr << "SPEEX DSP lib not accessible ==> can not resample" << std::endl;
m_needProcess = false;
#endif
}
bool airtalgo::Resampler::process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk) {
//airtalgo::autoLogInOut("Resampler");
_outputNbChunk = 2048;
// chack if we need to process:
if (m_needProcess == false) {
AIRTALGO_WARNING("no process");
_output = _input;
_outputNbChunk = _inputNbChunk;
return true;
}
if (_input == nullptr) {
_output = &(m_outputData[0]);
_outputNbChunk = 0;
AIRTALGO_ERROR("null pointer input ... ");
return false;
}
#ifdef HAVE_SPEEX_DSP_RESAMPLE
float nbInputTime = static_cast<float>(_inputNbChunk)/m_input.getFrequency();
float nbOutputSample = nbInputTime*m_output.getFrequency();
// we add 10% of the buffer size to have all the time enought data in the output to proceed all the input data...
_outputNbChunk = static_cast<size_t>(nbOutputSample*1.5f);
AIRTALGO_VERBOSE(" freq in=" << m_inputFrequency << " out=" << m_outputFrequency);
AIRTALGO_VERBOSE(" Frame duration=" << nbInputTime);
AIRTALGO_VERBOSE(" nbInput chunk=" << _inputNbChunk << " nbOutputChunk=" << nbOutputSample);
m_outputData.resize(_outputNbChunk*m_input.getMap().size()*m_formatSize);
_output = &(m_outputData[0]);
if (m_speexResampler == nullptr) {
std::cout << " No speex resampler" << std::endl;
return false;
}
uint32_t nbChunkInput = _inputNbChunk;
uint32_t nbChunkOutput = _outputNbChunk;
AIRTALGO_VERBOSE(" >> input=" << nbChunkInput << " output=" << nbChunkOutput);
int ret = speex_resampler_process_interleaved_int(m_speexResampler,
static_cast<int16_t*>(_input),
&nbChunkInput,
static_cast<int16_t*>(_output),
&nbChunkOutput);
AIRTALGO_VERBOSE(" << input=" << nbChunkInput << " output=" << nbChunkOutput);
// update position of data:
m_positionWrite += nbChunkOutput;
// Check all input and output ...
if (nbChunkInput != _inputNbChunk) {
AIRTALGO_ERROR(" inputSize (not all read ...) proceed=" << nbChunkInput << " requested=" << _inputNbChunk);
// TODO : manage this case ...
}
if (nbChunkOutput == _outputNbChunk) {
AIRTALGO_ERROR(" Might have not enought data in output... output size=" << _outputNbChunk);
// TODO : manage this case ...
}
_outputNbChunk = nbChunkOutput;
AIRTALGO_VERBOSE(" process chunk=" << nbChunkInput << " out=" << nbChunkOutput);
return true;
#else
_output = _input;
_outputNbChunk = _inputNbChunk;
return false;
#endif
}

44
airtalgo/Resampler.h Normal file
View File

@ -0,0 +1,44 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_RESAMPLER_H__
#define __AIRT_ALGO_RESAMPLER_H__
#include <airtalgo/Algo.h>
#ifdef HAVE_SPEEX_DSP_RESAMPLE
#include <speex/speex_resampler.h>
#endif
#include <memory>
namespace airtalgo {
class Resampler : public Algo {
private:
#ifdef HAVE_SPEEX_DSP_RESAMPLE
SpeexResamplerState* m_speexResampler;
#endif
size_t m_positionRead; //!< For residual data in the buffer last read number of chunk
size_t m_positionWrite; //!< Current pointer of writing new output data of resampler
public:
/**
* @brief Constructor
*/
Resampler();
/**
* @brief Destructor
*/
virtual ~Resampler();
protected:
virtual void configurationChange();
public:
virtual bool process(std::chrono::system_clock::time_point& _time,
void* _input,
size_t _inputNbChunk,
void*& _output,
size_t& _outputNbChunk);
};
};
#endif

8
airtalgo/airtalgo.cpp Normal file
View File

@ -0,0 +1,8 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"

43
airtalgo/airtalgo.h Normal file
View File

@ -0,0 +1,43 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_CORE_H__
#define __AIRT_ALGO_CORE_H__
#include <string>
#include <airtalgo/format.h>
#include <airtalgo/channel.h>
#include <chrono>
namespace airtalgo {
/**
* @brief Init the instance af algorithm (add all internal factory)
*/
void init();
/**
* @brief Uninit the instance af algorithm (rm all internal factory)
*/
void init();
/**
* @brief Create a process Algo with his name.
* @param[in] _name Name of the Algorithm.
* @return Instanciate algorithm
*/
airtalgo::Algo* createAlgo(const std::string& _name);
/**
* @brief Add a Factory Algorithm in the internal List (static for all instance)
* @param[in] _name Name of the Algorithm.
* @param[in] _functor Function of the factory
*/
void addAlgoFactory(const std::string& _name, std::function<airtalgo::Algo*(void)> _functor);
/**
* @brief Remove a Factory Algorithm in the internal List (static for all instance)
* @param[in] _name Name of the Algorithm.
*/
void RmAlgoFactory(const std::string& _name);
};
#endif

119
airtalgo/channel.cpp Normal file
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 <airtalgo/channel.h>
#include "debug.h"
std::ostream& airtalgo::operator <<(std::ostream& _os, enum airtalgo::channel _obj) {
_os << getChannelString(_obj);
return _os;
}
std::string airtalgo::getChannelString(enum airtalgo::channel _value) {
switch (_value) {
case channel_frontLeft:
return "front-left";
break;
case channel_frontCenter:
return "front-center";
break;
case channel_frontRight:
return "front-right";
break;
case channel_rearLeft:
return "rear-left";
break;
case channel_rearCenter:
return "rear-center";
break;
case channel_rearRight:
return "rear-right";
break;
case channel_surroundLeft:
return "surround-left";
break;
case channel_surroundRight:
return "surround-right";
break;
case channel_subWoofer:
return "sub-woofer";
break;
case channel_lfe:
return "lfe";
break;
};
}
std::string airtalgo::getChannelString(const std::vector<enum airtalgo::channel>& _value) {
std::string out;
for (size_t iii=0; iii<_value.size(); ++iii) {
if (iii != 0) {
out += ";";
}
out += getChannelString(_value[iii]);
}
return out;
}
std::ostream& airtalgo::operator <<(std::ostream& _os, std::vector<enum airtalgo::channel> _obj) {
_os << std::string("{");
for (size_t iii=0; iii<_obj.size(); ++iii) {
if (iii!=0) {
_os << std::string(";");
}
_os << _obj[iii];
}
_os << std::string("}");
return _os;
}
static std::vector<std::string> split(const std::string& _input, char _val) {
std::vector<std::string> list;
size_t lastStartPos = 0;
for(size_t iii=0; iii<_input.size(); iii++) {
if (_input[iii]==_val) {
list.push_back(std::string(_input, lastStartPos, iii - lastStartPos));
lastStartPos = iii+1;
}
}
if (lastStartPos<_input.size()) {
list.push_back(std::string(_input, lastStartPos));
}
return list;
}
std::vector<enum airtalgo::channel> airtalgo::getChannelFromString(const std::string& _value) {
std::vector<enum airtalgo::channel> out;
std::vector<std::string> listIO = split(_value, ';');
for (size_t iii=0; iii<listIO.size(); ++iii) {
if (listIO[iii] == "front-left") {
out.push_back(channel_frontLeft);
} else if (listIO[iii] == "front-right") {
out.push_back(channel_frontRight);
} else if (listIO[iii] == "front-center") {
out.push_back(channel_frontCenter);
} else if (listIO[iii] == "rear-left") {
out.push_back(channel_rearLeft);
} else if (listIO[iii] == "rear-right") {
out.push_back(channel_rearRight);
} else if (listIO[iii] == "rear-center") {
out.push_back(channel_rearCenter);
} else if (listIO[iii] == "surround-right") {
out.push_back(channel_surroundLeft);
} else if (listIO[iii] == "surround-left") {
out.push_back(channel_surroundRight);
} else if (listIO[iii] == "lfe") {
out.push_back(channel_lfe);
} else if (listIO[iii] == "sub-woofer") {
out.push_back(channel_subWoofer);
} else {
//ROS_ERROR("Unknow: '%s' in [front-left;front-right;front-center;rear-left;rear-right;rear-center;surround-right;surround-left;lfe;subwoofer]", listIO[iii].c_str());
}
}
return out;
}

34
airtalgo/channel.h Normal file
View File

@ -0,0 +1,34 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_CORE_CHANNEL_H__
#define __AIRT_ALGO_CORE_CHANNEL_H__
#include <string>
#include <vector>
namespace airtalgo{
enum channel {
channel_frontLeft, //!< channel Front Left
channel_frontCenter, //!< channel Front Center
channel_frontRight, //!< channel Front Right
channel_rearLeft, //!< channel rear Left
channel_rearCenter, //!< channel rear Center
channel_rearRight, //!< channel rear Right
channel_surroundLeft, //!< channel surround Left
channel_surroundRight, //!< channel surround Right
channel_subWoofer, //!< channel Sub-woofer
channel_lfe, //!< channel Low frequency
};
std::string getChannelString(enum airtalgo::channel);
std::string getChannelString(const std::vector<enum airtalgo::channel>&);
std::vector<enum airtalgo::channel> getChannelFromString(const std::string& _value);
std::ostream& operator <<(std::ostream& _os, enum airtalgo::channel _obj);
std::ostream& operator <<(std::ostream& _os, std::vector<enum airtalgo::channel> _obj);
};
#endif

13
airtalgo/debug.cpp Normal file
View File

@ -0,0 +1,13 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include <airtalgo/debug.h>
int32_t airtalgo::getLogId() {
static int32_t g_val = etk::log::registerInstance("airtalgo");
return g_val;
}

50
airtalgo/debug.h Normal file
View File

@ -0,0 +1,50 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRTALGO_DEBUG_H__
#define __AIRTALGO_DEBUG_H__
#include <etk/log.h>
namespace airtalgo {
int32_t getLogId();
};
// TODO : Review this problem of multiple intanciation of "std::stringbuf sb"
#define AIRTALGO_BASE(info,data) \
do { \
if (info <= etk::log::getLevel(airtalgo::getLogId())) { \
std::stringbuf sb; \
std::ostream tmpStream(&sb); \
tmpStream << data; \
etk::log::logStream(airtalgo::getLogId(), info, __LINE__, __class__, __func__, tmpStream); \
} \
} while(0)
#define AIRTALGO_CRITICAL(data) AIRTALGO_BASE(1, data)
#define AIRTALGO_ERROR(data) AIRTALGO_BASE(2, data)
#define AIRTALGO_WARNING(data) AIRTALGO_BASE(3, data)
#ifdef DEBUG
#define AIRTALGO_INFO(data) AIRTALGO_BASE(4, data)
#define AIRTALGO_DEBUG(data) AIRTALGO_BASE(5, data)
#define AIRTALGO_VERBOSE(data) AIRTALGO_BASE(6, data)
#define AIRTALGO_TODO(data) AIRTALGO_BASE(4, "TODO : " << data)
#else
#define AIRTALGO_INFO(data) do { } while(false)
#define AIRTALGO_DEBUG(data) do { } while(false)
#define AIRTALGO_VERBOSE(data) do { } while(false)
#define AIRTALGO_TODO(data) do { } while(false)
#endif
#define AIRTALGO_ASSERT(cond,data) \
do { \
if (!(cond)) { \
AIRTALGO_CRITICAL(data); \
assert(!#cond); \
} \
} while (0)
#endif

22
airtalgo/debugRemove.h Normal file
View File

@ -0,0 +1,22 @@
/**
* @author Edouard DUPIN
*
* @copyright 2011, Edouard DUPIN, all right reserved
*
* @license BSD 3 clauses (see license file)
*/
#ifdef __AIRTALGOO_DEBUG_H__
#undef __AIRTALGOO_DEBUG_H__
#undef AIRTALGO_BASE
#undef AIRTALGO_CRITICAL
#undef AIRTALGO_ERROR
#undef AIRTALGO_WARNING
#undef AIRTALGO_INFO
#undef AIRTALGO_DEBUG
#undef AIRTALGO_VERBOSE
#undef AIRTALGO_TODO
#undef AIRTALGO_ASSERT
#endif

46
airtalgo/format.cpp Normal file
View File

@ -0,0 +1,46 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#include "debug.h"
#include <airtalgo/format.h>
std::ostream& airtalgo::operator <<(std::ostream& _os, enum airtalgo::format _obj) {
_os << getFormatString(_obj);
return _os;
}
std::string airtalgo::getFormatString(enum airtalgo::format _value) {
switch (_value) {
case format_int16:
return "format_int16";
break;
case format_int16_on_int32:
return "format_int16_on_int32";
break;
case format_int32:
return "format_int32";
break;
case format_float:
return "format_float";
break;
};
}
enum airtalgo::format airtalgo::getFormatFromString(const std::string& _value) {
if (_value == "format_int16") {
return format_int16;
}
if (_value == "format_int16_on_int32") {
return format_int16_on_int32;
}
if (_value == "format_int32") {
return format_int32;
}
if (_value == "format_float") {
return format_float;
}
return format_int16;
}

26
airtalgo/format.h Normal file
View File

@ -0,0 +1,26 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __AIRT_ALGO_CORE_FORMAT_H__
#define __AIRT_ALGO_CORE_FORMAT_H__
#include <string>
namespace airtalgo{
enum format {
format_int16, //!< Signed 16 bits
format_int16_on_int32, //!< Signed 16 bits on 32bits data (16 bit fixpoint value)
format_int32, //!< Signed 32 bits
format_float, //!< Floating point (single precision)
};
std::string getFormatString(enum airtalgo::format);
enum airtalgo::format getFormatFromString(const std::string& _value);
std::ostream& operator <<(std::ostream& _os, enum airtalgo::format _obj);
};
#endif

43
lutin_airtalgo.py Normal file
View File

@ -0,0 +1,43 @@
#!/usr/bin/python
import lutinModule as module
import lutinTools as tools
import lutinDebug as debug
def get_desc():
return "airtalgo : Basic algo interface"
def create(target):
myModule = module.Module(__file__, 'airtalgo', 'LIBRARY')
myModule.add_src_file([
'airtalgo/debug.cpp',
'airtalgo/airtalgo.cpp',
'airtalgo/Algo.cpp',
'airtalgo/channel.cpp',
'airtalgo/ChannelReorder.cpp',
'airtalgo/EndPointCallback.cpp',
'airtalgo/EndPoint.cpp',
'airtalgo/EndPointRead.cpp',
'airtalgo/EndPointWrite.cpp',
'airtalgo/format.cpp',
'airtalgo/FormatUpdate.cpp',
'airtalgo/Process.cpp',
'airtalgo/Resampler.cpp'
])
myModule.add_module_depend(['etk'])
myModule.add_export_path(tools.get_current_path(__file__))
# add the currrent module at the
return myModule