commit 51d16858c5a4ebaf2fea0202d312e39b4ec1dcf9 Author: Edouard DUPIN Date: Sun Jan 25 22:10:49 2015 +0100 [DEV] create algo basic interface for simple audio flow diff --git a/airtalgo/Algo.cpp b/airtalgo/Algo.cpp new file mode 100644 index 0000000..122e7ef --- /dev/null +++ b/airtalgo/Algo.cpp @@ -0,0 +1,80 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#include +#include +#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; +} diff --git a/airtalgo/Algo.h b/airtalgo/Algo.h new file mode 100644 index 0000000..4f5f0f9 --- /dev/null +++ b/airtalgo/Algo.h @@ -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 +#include +#include +#include +#include +#include +#include +#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 _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 m_map; //!< input channel Map + public: + /** + * @brief Get the algo channel Map. + * @return the current channel Map. + */ + const std::vector& getMap() const{ + return m_map; + } + /** + * @brief Set the algo channel Map. + * @param[in] _value New channel Map. + */ + void setMap(const std::vector& _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 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& _functor) { + m_ioChangeFunctor = _functor; + } + + }; + + class Algo { + protected: + std::vector 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 diff --git a/airtalgo/ChannelReorder.cpp b/airtalgo/ChannelReorder.cpp new file mode 100644 index 0000000..0d85d75 --- /dev/null +++ b/airtalgo/ChannelReorder.cpp @@ -0,0 +1,125 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#include +#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(_input); + int16_t* out = static_cast(_output); + for (size_t kkk=0; kkk " << m_output.getMap()); + uint32_t* in = static_cast(_input); + uint32_t* out = static_cast(_output); + for (size_t kkk=0; kkk + +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 diff --git a/airtalgo/EndPoint.cpp b/airtalgo/EndPoint.cpp new file mode 100644 index 0000000..e69de29 diff --git a/airtalgo/EndPoint.h b/airtalgo/EndPoint.h new file mode 100644 index 0000000..b1c9d3b --- /dev/null +++ b/airtalgo/EndPoint.h @@ -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 + +namespace airtalgo{ + class EndPoint : public Algo { + public: + /** + * @brief Constructor + */ + EndPoint() {}; + /** + * @brief Destructor + */ + virtual ~EndPoint() {}; + }; +}; + +#endif diff --git a/airtalgo/EndPointCallback.cpp b/airtalgo/EndPointCallback.cpp new file mode 100644 index 0000000..444121e --- /dev/null +++ b/airtalgo/EndPointCallback.cpp @@ -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::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(_input); + for (size_t iii; iii +#include + + +namespace airtalgo { + enum formatDataType { + formatDataTypeInt16, + formatDataTypeInt32, + }; + typedef std::function& _map, void* _data, enum formatDataType& _type)> needDataFunction; + typedef std::function& _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 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 diff --git a/airtalgo/EndPointRead.cpp b/airtalgo/EndPointRead.cpp new file mode 100644 index 0000000..4a9a733 --- /dev/null +++ b/airtalgo/EndPointRead.cpp @@ -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::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; +} + diff --git a/airtalgo/EndPointRead.h b/airtalgo/EndPointRead.h new file mode 100644 index 0000000..90b8af1 --- /dev/null +++ b/airtalgo/EndPointRead.h @@ -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 + +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 diff --git a/airtalgo/EndPointWrite.cpp b/airtalgo/EndPointWrite.cpp new file mode 100644 index 0000000..26e726d --- /dev/null +++ b/airtalgo/EndPointWrite.cpp @@ -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::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 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 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++); + } +} diff --git a/airtalgo/EndPointWrite.h b/airtalgo/EndPointWrite.h new file mode 100644 index 0000000..b1df8ea --- /dev/null +++ b/airtalgo/EndPointWrite.h @@ -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 +#include +#include + +namespace airtalgo{ + typedef std::function& _map)> writeNeedDataFunction_int16_t; + class EndPointWrite : public EndPoint { + private: + std::vector 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 diff --git a/airtalgo/FormatUpdate.cpp b/airtalgo/FormatUpdate.cpp new file mode 100644 index 0000000..e9125d7 --- /dev/null +++ b/airtalgo/FormatUpdate.cpp @@ -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 +#include + +#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(_input); + int32_t* out = static_cast(_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(_input); + int32_t* out = static_cast(_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(_input); + float* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + // TODO : Set * intead of / + out[iii] = static_cast(in[iii])/static_cast(INT16_MAX); + } +} + +static void convert__int16_on_int32__to__int16(void* _input, void* _output, size_t _nbSample) { + int32_t* in = static_cast(_input); + int16_t* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + out[iii] = static_cast(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(_input); + int32_t* out = static_cast(_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(_input); + float* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + // TODO : Set * intead of / + out[iii] = static_cast(in[iii])/static_cast(INT16_MAX); + } +} + +static void convert__int32__to__int16(void* _input, void* _output, size_t _nbSample) { + int32_t* in = static_cast(_input); + int16_t* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + int32_t value = in[iii] >> 16; + out[iii] = static_cast(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(_input); + int16_t* out = static_cast(_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(_input); + float* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + // TODO : Set * intead of / + out[iii] = static_cast(in[iii])/static_cast(INT32_MAX); + } +} + +static void convert__float__to__int16(void* _input, void* _output, size_t _nbSample) { + float* in = static_cast(_input); + int16_t* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + float value = in[iii] * static_cast(INT16_MAX); + value = std::min(std::max(static_cast(INT16_MIN), value), static_cast(INT16_MAX)); + out[iii] = static_cast(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(_input); + int32_t* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + float value = in[iii] * static_cast(INT16_MAX); + value = std::min(std::max(static_cast(INT32_MIN), value), static_cast(INT32_MAX)); + out[iii] = static_cast(value); + } +} +static void convert__float__to__int32(void* _input, void* _output, size_t _nbSample) { + float* in = static_cast(_input); + int32_t* out = static_cast(_output); + for (size_t iii=0; iii<_nbSample; ++iii) { + float value = in[iii] * static_cast(INT32_MAX); + value = std::min(std::max(static_cast(INT32_MIN), value), static_cast(INT32_MAX)); + out[iii] = static_cast(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; +} diff --git a/airtalgo/FormatUpdate.h b/airtalgo/FormatUpdate.h new file mode 100644 index 0000000..3d149bf --- /dev/null +++ b/airtalgo/FormatUpdate.h @@ -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 + +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 diff --git a/airtalgo/Process.cpp b/airtalgo/Process.cpp new file mode 100644 index 0000000..ccbce37 --- /dev/null +++ b/airtalgo/Process.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +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; iiiprocess(_time, _inData, _inNbChunk, _outData, _outNbChunk); + _inData = _outData; + _inNbChunk = _outNbChunk; + } + } +} + +void airtalgo::Process::pushBack(const std::shared_ptr& _algo) { + m_listAlgo.push_back(_algo); +} + +void airtalgo::Process::pushFront(const std::shared_ptr& _algo) { + m_listAlgo.insert(m_listAlgo.begin(), _algo); +} + +void airtalgo::Process::updateInterAlgo() { + // TODO : ... +} diff --git a/airtalgo/Process.h b/airtalgo/Process.h new file mode 100644 index 0000000..7d6b0b9 --- /dev/null +++ b/airtalgo/Process.h @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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 > m_listAlgo; + public: + void pushBack(const std::shared_ptr& _algo); + void pushFront(const std::shared_ptr& _algo); + void updateInterAlgo(); + void clear() { + m_listAlgo.clear(); + } + }; +}; + +#endif diff --git a/airtalgo/Resampler.cpp b/airtalgo/Resampler.cpp new file mode 100644 index 0000000..b24552e --- /dev/null +++ b/airtalgo/Resampler.cpp @@ -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 +#include + + +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(_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(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(_input), + &nbChunkInput, + static_cast(_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 +} diff --git a/airtalgo/Resampler.h b/airtalgo/Resampler.h new file mode 100644 index 0000000..9be6902 --- /dev/null +++ b/airtalgo/Resampler.h @@ -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 +#ifdef HAVE_SPEEX_DSP_RESAMPLE + #include +#endif +#include + +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 diff --git a/airtalgo/airtalgo.cpp b/airtalgo/airtalgo.cpp new file mode 100644 index 0000000..cdda07f --- /dev/null +++ b/airtalgo/airtalgo.cpp @@ -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" + diff --git a/airtalgo/airtalgo.h b/airtalgo/airtalgo.h new file mode 100644 index 0000000..fda10d3 --- /dev/null +++ b/airtalgo/airtalgo.h @@ -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 +#include +#include +#include + +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 _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 diff --git a/airtalgo/channel.cpp b/airtalgo/channel.cpp new file mode 100644 index 0000000..5317a16 --- /dev/null +++ b/airtalgo/channel.cpp @@ -0,0 +1,119 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include +#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& _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 _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 split(const std::string& _input, char _val) { + std::vector 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 airtalgo::getChannelFromString(const std::string& _value) { + std::vector out; + std::vector listIO = split(_value, ';'); + for (size_t iii=0; iii +#include + +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&); + std::vector getChannelFromString(const std::string& _value); + std::ostream& operator <<(std::ostream& _os, enum airtalgo::channel _obj); + std::ostream& operator <<(std::ostream& _os, std::vector _obj); +}; + + +#endif diff --git a/airtalgo/debug.cpp b/airtalgo/debug.cpp new file mode 100644 index 0000000..b301815 --- /dev/null +++ b/airtalgo/debug.cpp @@ -0,0 +1,13 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include + + +int32_t airtalgo::getLogId() { + static int32_t g_val = etk::log::registerInstance("airtalgo"); + return g_val; +} diff --git a/airtalgo/debug.h b/airtalgo/debug.h new file mode 100644 index 0000000..17a6b06 --- /dev/null +++ b/airtalgo/debug.h @@ -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 + +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 + diff --git a/airtalgo/debugRemove.h b/airtalgo/debugRemove.h new file mode 100644 index 0000000..42f4f80 --- /dev/null +++ b/airtalgo/debugRemove.h @@ -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 + diff --git a/airtalgo/format.cpp b/airtalgo/format.cpp new file mode 100644 index 0000000..3db1feb --- /dev/null +++ b/airtalgo/format.cpp @@ -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 + +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; +} \ No newline at end of file diff --git a/airtalgo/format.h b/airtalgo/format.h new file mode 100644 index 0000000..3d2b263 --- /dev/null +++ b/airtalgo/format.h @@ -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 + +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 + diff --git a/lutin_airtalgo.py b/lutin_airtalgo.py new file mode 100644 index 0000000..c022739 --- /dev/null +++ b/lutin_airtalgo.py @@ -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 + + + + + + + + +