diff --git a/airtio/Interface.cpp b/airtio/Interface.cpp index ef73368..a59ce65 100644 --- a/airtio/Interface.cpp +++ b/airtio/Interface.cpp @@ -4,7 +4,9 @@ * @license APACHE v2.0 (see license file) */ +#include "debug.h" #include "Interface.h" +#include "io/Node.h" #include #include #include @@ -14,11 +16,11 @@ airtio::Interface::Interface(void) : - m_name(""), m_node(nullptr), m_freq(8000), m_map(), m_format(airtalgo::format_int16), + m_name(""), m_volume(0.0f) { } @@ -33,7 +35,72 @@ bool airtio::Interface::init(const std::string& _name, m_freq = _freq; m_map = _map; m_format = _format; + m_process = std::make_shared(); m_volume = 0.0f; + + // Create convertion interface + if (m_node->isInput() == true) { + if (m_map != m_node->getMap()) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_node->getMap(), m_node->getFormat(), m_node->getFrequency())); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); + m_process->pushBack(algo); + AIRTIO_INFO("convert " << m_node->getMap() << " -> " << m_map); + } + if (m_freq != m_node->getFrequency()) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); + m_process->pushBack(algo); + AIRTIO_INFO("convert " << m_node->getFrequency() << " -> " << m_freq); + } + if (m_format != m_node->getFormat()) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); + m_process->pushBack(algo); + AIRTIO_INFO("convert " << m_node->getFormat() << " -> " << m_format); + } + // by default we add a read node + if (true) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); + m_process->pushBack(algo); + AIRTIO_INFO("add default read node ..."); + } + } else { + // by default we add a write node: + if (true) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); + m_process->pushBack(algo); + AIRTIO_INFO("add default write node ..."); + } + if (m_format != m_node->getFormat()) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); + m_process->pushBack(algo); + AIRTIO_INFO("convert " << m_format << " -> " << m_node->getFormat()); + } + if (m_freq != m_node->getFrequency()) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); + m_process->pushBack(algo); + AIRTIO_INFO("convert " << m_freq << " -> " << m_node->getFrequency()); + } + if (m_map != m_node->getMap()) { + std::shared_ptr algo = std::make_shared(); + algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); + algo->setOutputFormat(airtalgo::IOFormatInterface(m_node->getMap(), m_node->getFormat(), m_node->getFrequency())); + m_process->pushBack(algo); + AIRTIO_INFO("convert " << m_map << " -> " << m_node->getMap()); + } + } + //m_node->interfaceAdd(shared_from_this()); return true; } @@ -42,149 +109,70 @@ std::shared_ptr airtio::Interface::create(const std::string& const std::vector& _map, airtalgo::format _format, const std::shared_ptr& _node) { - std::shared_ptr out = std::make_shared(new airtio::Interface()); + std::shared_ptr out = std::shared_ptr(new airtio::Interface()); out->init(_name, _freq, _map, _format, _node); return out; } -void airtio::Interface::init() { - - // Create convertion interface - if (m_node->isInput() == true) { - if (m_map != m_node->getMap()) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_node->getMap(), m_node->getFormat(), m_node->getFrequency())); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); - m_listAlgo.push_back(algo); - std::cout << "[INFO] convert " << m_node->getMap() << " -> " << m_map << std::endl; - } - if (m_freq != m_node->getFrequency()) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); - m_listAlgo.push_back(algo); - std::cout << "[INFO] convert " << m_node->getFrequency() << " -> " << m_freq << std::endl; - } - if (m_format != m_node->getFormat()) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - m_listAlgo.push_back(algo); - std::cout << "[INFO] convert " << m_node->getFormat() << " -> " << m_format << std::endl; - } - // by default we add a read node - if (true) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - m_listAlgo.push_back(algo); - std::cout << "[INFO] add default read node ..." << std::endl; - } - } else { - // by default we add a write node: - if (true) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - m_listAlgo.push_back(algo); - std::cout << "[INFO] add default write node ..." << std::endl; - } - if (m_format != m_node->getFormat()) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); - m_listAlgo.push_back(algo); - std::cout << "[INFO] convert " << m_format << " -> " << m_node->getFormat() << std::endl; - } - if (m_freq != m_node->getFrequency()) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_freq)); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); - m_listAlgo.push_back(algo); - std::cout << "[INFO] convert " << m_freq << " -> " << m_node->getFrequency() << std::endl; - } - if (m_map != m_node->getMap()) { - std::shared_ptr algo = boost::make_shared(); - algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_node->getFormat(), m_node->getFrequency())); - algo->setOutputFormat(airtalgo::IOFormatInterface(m_node->getMap(), m_node->getFormat(), m_node->getFrequency())); - m_listAlgo.push_back(algo); - std::cout << "[INFO] convert " << m_map << " -> " << m_node->getMap() << std::endl; - } - } - //m_node->interfaceAdd(shared_from_this()); -} - airtio::Interface::~Interface() { std::unique_lock lock(m_mutex); //m_node->interfaceRemove(shared_from_this()); } -void airtio::Interface::setWriteCallbackInt16(size_t _chunkSize, writeNeedDataFunction_int16_t _function) { - std::unique_lock lock(m_mutex); - if (m_listAlgo.size() <= 0) { - return; - } - std::shared_ptr algo = boost::dynamic_pointer_cast(m_listAlgo[0]); - if (algo == nullptr) { - return; - } - algo->setCallback(_function); -} - void airtio::Interface::setOutputCallback(size_t _chunkSize, airtalgo::needDataFunction _function, enum airtalgo::formatDataType _dataType) { std::unique_lock lock(m_mutex); - if (m_listAlgo.size() > 0) { - std::shared_ptr algoEP = boost::dynamic_pointer_cast(m_listAlgo[0]); - if (algoEP != nullptr) { - m_listAlgo.erase(m_listAlgo.begin()); - } - } - std::shared_ptr algo = boost::make_shared(_function, _dataType); - std::cout << "[INFO] set property: " << m_map << " " << m_format << " " << m_freq <removeIfFirst(); + std::shared_ptr algo = std::make_shared(_function, _dataType); + AIRTIO_INFO("set property: " << m_map << " " << m_format << " " << m_freq); algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - m_listAlgo.insert(m_listAlgo.begin(), algo); + m_process->pushFront(algo); } void airtio::Interface::setInputCallback(size_t _chunkSize, airtalgo::haveNewDataFunction _function, enum airtalgo::formatDataType _dataType) { std::unique_lock lock(m_mutex); - if (m_listAlgo.size() > 0) { - std::shared_ptr algoEP = boost::dynamic_pointer_cast(m_listAlgo[m_listAlgo.size()-1]); - if (algoEP != nullptr) { - m_listAlgo.erase(m_listAlgo.begin()+m_listAlgo.size()-1); - } - } - std::shared_ptr algo = boost::make_shared(_function, _dataType); + m_process->removeIfLast(); + std::shared_ptr algo = std::make_shared(_function, _dataType); algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); - m_listAlgo.push_back(algo); + m_process->pushBack(algo); } void airtio::Interface::start(const std::chrono::system_clock::time_point& _time) { std::unique_lock lock(m_mutex); + AIRTIO_DEBUG("start [BEGIN]"); m_node->interfaceAdd(shared_from_this()); + AIRTIO_DEBUG("start [ END ]"); } void airtio::Interface::stop(bool _fast, bool _abort) { std::unique_lock lock(m_mutex); + AIRTIO_DEBUG("stop [BEGIN]"); m_node->interfaceRemove(shared_from_this()); + AIRTIO_DEBUG("stop [ END]"); } void airtio::Interface::abort() { std::unique_lock lock(m_mutex); + AIRTIO_DEBUG("abort [BEGIN]"); // TODO :... + AIRTIO_DEBUG("abort [ END ]"); } void airtio::Interface::setVolume(float _gainDB) { std::unique_lock lock(m_mutex); + AIRTIO_DEBUG("setVolume [BEGIN]"); // TODO :... + AIRTIO_DEBUG("setVolume [ END ]"); } float airtio::Interface::getVolume() const { std::unique_lock lock(m_mutex); + AIRTIO_DEBUG("getVolume [BEGIN]"); // TODO :... + AIRTIO_DEBUG("getVolume [ END ]"); return 0; } @@ -199,7 +187,7 @@ void airtio::Interface::write(const std::vector& _value) { void airtio::Interface::write(const int16_t* _value, size_t _nbChunk) { std::unique_lock lock(m_mutex); - std::shared_ptr algo = boost::dynamic_pointer_cast(m_listAlgo[0]); + std::shared_ptr algo = m_process->get(0); if (algo == nullptr) { return; } @@ -247,7 +235,7 @@ void airtio::Interface::setBufferSize(size_t _nbChunk) { } -void airtio::Interface::setBufferSize(const std::chrono::duration& _time) { +void airtio::Interface::setBufferSize(const std::chrono::duration& _time) { std::unique_lock lock(m_mutex); // TODO :... @@ -266,45 +254,19 @@ std::chrono::system_clock::time_point airtio::Interface::getCurrentTime() const return std::chrono::system_clock::now(); } -void airtio::Interface::setMasterVolume(float _gainDB) { - std::unique_lock lock(m_mutex); - //m_volumeMaster = _gainDB; - // TODO :... -} - -bool airtio::Interface::process(std::chrono::system_clock::time_point& _time, - void* _input, - size_t _inputNbChunk, - void*& _output, - size_t& _outputNbChunk) { - if (m_listAlgo.size() == 0) { - _output = _input; - _outputNbChunk = _inputNbChunk; - return true; - } - for (size_t iii=0; iiiprocess(_time, _input, _inputNbChunk, _output, _outputNbChunk); - _input = _output; - _inputNbChunk = _outputNbChunk; - } - } - return true; -} void airtio::Interface::systemNewInputData(std::chrono::system_clock::time_point _time, void* _data, int32_t _nbChunk) { - void* out = nullptr; - size_t nbChunkOut; - //std::cout << " Interface DIRECT " << std::endl; - process(_time, _data, _nbChunk, out, nbChunkOut); + m_process->push(_time, _data, _nbChunk); } void airtio::Interface::systemNeedOutputData(std::chrono::system_clock::time_point _time, void* _data, int32_t _nbChunk, size_t _chunkSize) { + size_t nbChunk2 = _nbChunk; + m_process->pull(_time, _data, nbChunk2);//, _chunkSize); +#if 0 // TODO : while enought data or fhush data: memset(_data, 0, _nbChunk*_chunkSize); - //std::cout << " Interface DIRECT " << std::endl; + AIRTIO_VERBOSE(" Interface DIRECT "); while(m_data.size()<_nbChunk*_chunkSize) { void* in = nullptr; size_t nbChunkIn = _nbChunk - m_data.size()/_chunkSize; @@ -324,9 +286,9 @@ void airtio::Interface::systemNeedOutputData(std::chrono::system_clock::time_poi } //nbChunkIn *= 4; // get data from the upstream - //std::cout << " * request " << nbChunkIn << " chunk" << std::endl; - process(_time, in, nbChunkIn, out, nbChunkOut); - //std::cout << " * get " << nbChunkOut << " chunk" << std::endl; + AIRTIO_VERBOSE(" * request " << nbChunkIn << " chunk"); + m_process->process(_time, in, nbChunkIn, out, nbChunkOut); + AIRTIO_VERBOSE(" * get " << nbChunkOut << " chunk"); if (nbChunkOut > 0) { size_t position = m_data.size(); m_data.resize(m_data.size() + nbChunkOut*_chunkSize); @@ -337,20 +299,21 @@ void airtio::Interface::systemNeedOutputData(std::chrono::system_clock::time_poi } } if (m_data.size()>=_nbChunk*_chunkSize) { - //std::cout << " * copy needed data" << std::endl; + AIRTIO_VERBOSE(" * copy needed data"); memcpy(_data, &m_data[0], _nbChunk*_chunkSize); m_data.erase(m_data.begin(), m_data.begin()+_nbChunk*_chunkSize); } else { - //std::cout << " * soft underflow" << std::endl; + AIRTIO_VERBOSE(" * soft underflow"); // ERROR m_data.clear(); } /* process(_time, in, nbChunkIn, out, nbChunkOut); if (nbChunkIn!=nbChunkOut) { - std::cout << " wrong size : request=" << _nbChunk << " get=" << nbChunkOut << std::endl; + AIRTIO_ERROR(" wrong size : request=" << _nbChunk << " get=" << nbChunkOut); return; } memcpy(_data, out, _nbChunk*_chunkSize); */ +#endif } diff --git a/airtio/Interface.h b/airtio/Interface.h index a2c159c..c2e2b58 100644 --- a/airtio/Interface.h +++ b/airtio/Interface.h @@ -54,7 +54,7 @@ namespace airtio { /** * @brief Destructor */ - virtual ~Interface() {}; + virtual ~Interface(); static std::shared_ptr create(const std::string& _name, float _freq, const std::vector& _map, @@ -156,11 +156,6 @@ namespace airtio { std::vector m_data; float m_volume; //!< Local channel Volume - bool process(std::chrono::system_clock::time_point& _time, - void* _input, - size_t _inputNbChunk, - void*& _output, - size_t& _outputNbChunk); }; }; diff --git a/airtio/Manager.cpp b/airtio/Manager.cpp index 36ef84c..804bc65 100644 --- a/airtio/Manager.cpp +++ b/airtio/Manager.cpp @@ -5,7 +5,7 @@ */ #include "Manager.h" -#include "InterfaceDirect.h" +#include "Interface.h" #include #include @@ -13,7 +13,7 @@ #include "io/Node.h" std::shared_ptr airtio::Manager::create(const std::string& _applicationUniqueId) { - return std::make_shared(_applicationUniqueId); + return std::shared_ptr(new airtio::Manager(_applicationUniqueId)); } airtio::Manager::Manager(const std::string& _applicationUniqueId) : @@ -41,6 +41,7 @@ std::vector > airtio::Manager::getListStreamO return output; } +// TODO : Deprecated ... void airtio::Manager::setMasterOutputVolume(float _gainDB) { if (_gainDB < m_masterVolumeRange.first) { //throw std::range_error(std::string(_gainDB) + " is out of bonds : [" + m_masterVolumeRange.first + ".." + m_masterVolumeRange.second + "]"); @@ -51,15 +52,13 @@ void airtio::Manager::setMasterOutputVolume(float _gainDB) { return; } m_masterVolume = _gainDB; - for (std::list >::iterator it(m_listOpenInterface.begin()); - it != m_listOpenInterface.end(); - ++it) { - std::shared_ptr tmpElem = it->lock(); + for (auto &it : m_listOpenInterface) { + std::shared_ptr tmpElem = it.lock(); if (tmpElem == nullptr) { continue; } // TODO : Deprecated ... - tmpElem->setMasterVolume(m_masterVolume); + //tmpElem->setMasterVolume(m_masterVolume); } } @@ -94,13 +93,12 @@ airtio::Manager::createOutput(float _freq, // get the output or input channel : std::shared_ptr node = manager->getNode(_streamName, false); // create user iterface: - std::shared_ptr interface; - interface = std::make_shared(_name, _freq, _map, _format, node); - interface->init(); + std::shared_ptr interface; + interface = airtio::Interface::create(_name, _freq, _map, _format, node); // store it in a list (needed to apply some parameters). m_listOpenInterface.push_back(interface); // TODO : DEPRECATED ... - interface->setMasterVolume(m_masterVolume); + //interface->setMasterVolume(m_masterVolume); return interface; } @@ -115,12 +113,11 @@ airtio::Manager::createInput(float _freq, // get the output or input channel : std::shared_ptr node = manager->getNode(_streamName, true); // create user iterface: - std::shared_ptr interface; - interface = std::make_shared(_name, _freq, _map, _format, node); - interface->init(); + std::shared_ptr interface; + interface = airtio::Interface::create(_name, _freq, _map, _format, node); // store it in a list (needed to apply some parameters). m_listOpenInterface.push_back(interface); // TODO : DEPRECATED ... - interface->setMasterVolume(m_masterVolume); + //interface->setMasterVolume(m_masterVolume); return interface; } diff --git a/airtio/Manager.h b/airtio/Manager.h index 6ecac95..4fa0cda 100644 --- a/airtio/Manager.h +++ b/airtio/Manager.h @@ -21,29 +21,29 @@ namespace airtio { class Manager { private: const std::string& m_applicationUniqueId; //!< name of the application that open the Audio Interface. - std::list > m_listOpenInterface; //!< List of all open Stream. + std::vector > m_listOpenInterface; //!< List of all open Stream. protected: /** * @brief Constructor */ - Manager() {}; + Manager(const std::string& _applicationUniqueId); public: static std::shared_ptr create(const std::string& _applicationUniqueId); /** * @brief Destructor */ - virtual ~Manager() {}; + virtual ~Manager(); public: /** * @brief Get all input audio stream description. * @return a list of all availlables input stream (name + description) */ - virtual std::vector > getListStreamInput() = 0; + virtual std::vector > getListStreamInput(); /** * @brief Get all output audio stream description. * @return a list of all availlables output stream (name + description) */ - virtual std::vector > getListStreamOutput() = 0; + virtual std::vector > getListStreamOutput(); protected: float m_masterVolume; std::pair m_masterVolumeRange; diff --git a/airtio/io/Manager.h b/airtio/io/Manager.h index f1c1384..5f9cee0 100644 --- a/airtio/io/Manager.h +++ b/airtio/io/Manager.h @@ -11,12 +11,11 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include namespace airtio { namespace io { diff --git a/airtio/io/Node.cpp b/airtio/io/Node.cpp index 8d526a8..6bde9c9 100644 --- a/airtio/io/Node.cpp +++ b/airtio/io/Node.cpp @@ -4,7 +4,8 @@ * @license APACHE v2.0 (see license file) */ -#include "Node.hpp" +#include "Node.h" +#include #include @@ -26,7 +27,7 @@ static int rtAudioCallbackStatic(void* _outputBuffer, void* _inputBuffer, unsigned int _nBufferFrames, double _streamTime, - RtAudioStreamStatus _status, + airtaudio::streamStatus _status, void* _data) { airtio::io::Node* interface = static_cast(_data); return interface->rtAudioCallback(static_cast(_outputBuffer), @@ -37,23 +38,22 @@ static int rtAudioCallbackStatic(void* _outputBuffer, } int airtio::io::Node::rtAudioCallback(int16_t* _outputBuffer, - int16_t* _inputBuffer, - unsigned int _nBufferFrames, - double _streamTime, - RtAudioStreamStatus _status) { - std::mutex::scoped_lock lock(m_mutex); - - std::chrono::system_clock::time_point ttime = boost::chrono::system_clock::time_point();//boost::chrono::system_clock::now(); + int16_t* _inputBuffer, + unsigned int _nBufferFrames, + double _streamTime, + airtaudio::streamStatus _status) { + std::unique_lock lock(m_mutex); + std::chrono::system_clock::time_point ttime = std::chrono::system_clock::time_point();//std::chrono::system_clock::now(); if (_outputBuffer != nullptr) { - //std::cout << "data Output" << std::endl; + AIRTIO_VERBOSE("data Output"); std::vector output; output.resize(_nBufferFrames*m_map.size(), 0); std::vector outputTmp; outputTmp.resize(_nBufferFrames*m_map.size()); for (size_t iii=0; iii< m_list.size(); ++iii) { if (m_list[iii] != nullptr) { - //std::cout << " IO : " << iii+1 << "/" << m_list.size() << " name="<< m_list[iii]->getName() << std::endl; + AIRTIO_VERBOSE(" IO : " << iii+1 << "/" << m_list.size() << " name="<< m_list[iii]->getName()); m_list[iii]->systemNeedOutputData(ttime, &outputTmp[0], _nBufferFrames, sizeof(int16_t)*m_map.size()); //m_list[iii]->systemNeedOutputData(ttime, _outputBuffer, _nBufferFrames, sizeof(int16_t)*m_map.size()); // Add data to the output tmp buffer : @@ -70,10 +70,10 @@ int airtio::io::Node::rtAudioCallback(int16_t* _outputBuffer, } } if (_inputBuffer != nullptr) { - std::cout << "data Input" << std::endl; + AIRTIO_INFO("data Input"); for (size_t iii=0; iii< m_list.size(); ++iii) { if (m_list[iii] != nullptr) { - std::cout << " IO : " << iii+1 << "/" << m_list.size() << " name="<< m_list[iii]->getName() << std::endl; + AIRTIO_INFO(" IO : " << iii+1 << "/" << m_list.size() << " name="<< m_list[iii]->getName()); m_list[iii]->systemNewInputData(ttime, _inputBuffer, _nBufferFrames); } } @@ -91,10 +91,11 @@ airtio::io::Node::Node(const std::string& _streamName, bool _isInput) : m_frequency(48000), m_format(airtalgo::format_int16), m_isInput(_isInput) { - std::cout << "-----------------------------------------------------------------" << std::endl; - std::cout << "-- CREATE NODE --" << std::endl; - std::cout << "-----------------------------------------------------------------" << std::endl; - + AIRTIO_INFO("-----------------------------------------------------------------"); + AIRTIO_INFO("-- CREATE NODE --"); + AIRTIO_INFO("-----------------------------------------------------------------"); + // intanciate specific API ... + m_adac.instanciate(); if (m_streamName == "") { m_streamName = "default"; @@ -104,19 +105,19 @@ airtio::io::Node::Node(const std::string& _streamName, bool _isInput) : m_map.push_back(airtalgo::channel_frontRight); // search device ID : - std::cout << "Open :" << std::endl; - std::cout << " m_streamName=" << m_streamName << std::endl; - std::cout << " m_freq=" << m_frequency << std::endl; - std::cout << " m_map=" << m_map << std::endl; - std::cout << " m_format=" << m_format << std::endl; - std::cout << " m_isInput=" << m_isInput << std::endl; + AIRTIO_INFO("Open :"); + AIRTIO_INFO(" m_streamName=" << m_streamName); + AIRTIO_INFO(" m_freq=" << m_frequency); + AIRTIO_INFO(" m_map=" << m_map); + AIRTIO_INFO(" m_format=" << m_format); + AIRTIO_INFO(" m_isInput=" << m_isInput); int32_t deviceId = 0; - std::cout << "Device list:" << std::endl; + AIRTIO_INFO("Device list:"); for (int32_t iii=0; iii lock(m_mutex); + AIRTIO_INFO("-----------------------------------------------------------------"); + AIRTIO_INFO("-- DESTRO NODE --"); + AIRTIO_INFO("-----------------------------------------------------------------"); + AIRTIO_INFO("close input stream"); if (m_adac.isStreamOpen() ) { m_adac.closeStream(); } }; void airtio::io::Node::start() { - std::mutex::scoped_lock lock(m_mutex); - std::cout << "[INFO] Start stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output")<< std::endl; - try { - m_adac.startStream(); - } catch (RtAudioError& e ) { - e.printMessage(); - std::cout << "[ERROR] Can not start stream Input" << std::endl; - if (m_adac.isStreamOpen() ) { - m_adac.closeStream(); - } - return; + std::unique_lock lock(m_mutex); + AIRTIO_INFO("Start stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") ); + enum airtaudio::errorType err = m_adac.startStream(); + if (err != airtaudio::errorNone) { + AIRTIO_ERROR("Start stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") << " can not start stream ... " << err); } } void airtio::io::Node::stop() { - std::mutex::scoped_lock lock(m_mutex); - std::cout << "[INFO] Stop stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output")<< std::endl; - try { - m_adac.stopStream(); - } catch ( RtAudioError& e ) { - e.printMessage(); - std::cout << "[ERROR] Can not stop stream" << std::endl; - if (m_adac.isStreamOpen() ) { - m_adac.closeStream(); - } - return; + std::unique_lock lock(m_mutex); + AIRTIO_INFO("Stop stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") ); + enum airtaudio::errorType err = m_adac.stopStream(); + if (err != airtaudio::errorNone) { + AIRTIO_ERROR("Stop stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") << " can not stop stream ... " << err); } } - - - void airtio::io::Node::interfaceAdd(const std::shared_ptr& _interface) { for (size_t iii=0; iii< m_list.size(); ++iii) { if (_interface == m_list[iii]) { return; } } + AIRTIO_INFO("ADD interface for stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") ); m_list.push_back(_interface); - start(); + if (m_list.size() == 1) { + start(); + } } void airtio::io::Node::interfaceRemove(const std::shared_ptr& _interface) { for (size_t iii=0; iii< m_list.size(); ++iii) { if (_interface == m_list[iii]) { m_list.erase(m_list.begin()+iii); + AIRTIO_INFO("RM interface for stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") ); break; } } diff --git a/airtio/io/Node.h b/airtio/io/Node.h index b1f0bbf..061475f 100644 --- a/airtio/io/Node.h +++ b/airtio/io/Node.h @@ -15,9 +15,10 @@ #include #include #include -#include "io/Manager.h" +#include "Manager.h" #include #include +#include namespace airtio { namespace io { @@ -42,15 +43,15 @@ namespace airtio { void interfaceAdd(const std::shared_ptr& _interface); void interfaceRemove(const std::shared_ptr& _interface); private: - RtAudio m_adac; //!< Real audio interface - RtAudio::DeviceInfo m_info; + airtaudio::Interface m_adac; //!< Real audio interface + airtaudio::DeviceInfo m_info; unsigned int m_rtaudioFrameSize; public: int rtAudioCallback(int16_t* _outputBuffer, int16_t* _inputBuffer, unsigned int _nBufferFrames, double _streamTime, - RtAudioStreamStatus _status); + airtaudio::streamStatus _status); private: std::string m_streamName; public: diff --git a/lutin_airtio_test.py b/lutin_airtio_test.py new file mode 100644 index 0000000..dada5ab --- /dev/null +++ b/lutin_airtio_test.py @@ -0,0 +1,30 @@ +#!/usr/bin/python +import lutinModule as module +import lutinTools as tools +import lutinDebug as debug + +def get_desc(): + return "airtio_test : Multi-nodal audio interface test" + + +def create(target): + myModule = module.Module(__file__, 'airtio_test', 'BINARY') + + myModule.add_src_file([ + 'test/main.cpp', + 'test/debug.cpp' + ]) + + myModule.add_module_depend(['airtio', 'gtest', 'etk']) + + # add the currrent module at the + return myModule + + + + + + + + + diff --git a/test/debug.cpp b/test/debug.cpp new file mode 100644 index 0000000..bc8cd03 --- /dev/null +++ b/test/debug.cpp @@ -0,0 +1,15 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2010, Edouard DUPIN, all right reserved + * + * @license GPL v3 (see license file) + */ + +#include "debug.h" + +int32_t appl::getLogId() { + static int32_t g_val = etk::log::registerInstance("test"); + return g_val; +} + diff --git a/test/debug.h b/test/debug.h new file mode 100644 index 0000000..2b07d37 --- /dev/null +++ b/test/debug.h @@ -0,0 +1,51 @@ +/** + * @author Edouard DUPIN + * + * @copyright 2010, Edouard DUPIN, all right reserved + * + * @license GPL v3 (see license file) + */ + +#ifndef __APPL_DEBUG_H__ +#define __APPL_DEBUG_H__ + +#include + +namespace appl { + int32_t getLogId(); +}; +// TODO : Review this problem of multiple intanciation of "std::stringbuf sb" +#define APPL_BASE(info,data) \ + do { \ + if (info <= etk::log::getLevel(appl::getLogId())) { \ + std::stringbuf sb; \ + std::ostream tmpStream(&sb); \ + tmpStream << data; \ + etk::log::logStream(appl::getLogId(), info, __LINE__, __class__, __func__, tmpStream); \ + } \ + } while(0) + +#define APPL_CRITICAL(data) APPL_BASE(1, data) +#define APPL_ERROR(data) APPL_BASE(2, data) +#define APPL_WARNING(data) APPL_BASE(3, data) +#ifdef DEBUG + #define APPL_INFO(data) APPL_BASE(4, data) + #define APPL_DEBUG(data) APPL_BASE(5, data) + #define APPL_VERBOSE(data) APPL_BASE(6, data) + #define APPL_TODO(data) APPL_BASE(4, "TODO : " << data) +#else + #define APPL_INFO(data) do { } while(false) + #define APPL_DEBUG(data) do { } while(false) + #define APPL_VERBOSE(data) do { } while(false) + #define APPL_TODO(data) do { } while(false) +#endif + +#define APPL_ASSERT(cond,data) \ + do { \ + if (!(cond)) { \ + APPL_CRITICAL(data); \ + assert(!#cond); \ + } \ + } while (0) + +#endif diff --git a/test/main.cpp b/test/main.cpp index 051ef7a..36b5fc3 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,24 +1,33 @@ -#include "ros/ros.h" -#include -#include +/** @file + * @author Edouard DUPIN + * @copyright 2015, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ + +#include "debug.h" +#include +#include +#include +#include #include +#include - +#if 0 class testOutWrite { private: - std::vector m_channelMap; - boost::shared_ptr m_manager; - boost::shared_ptr m_interface; + std::vector m_channelMap; + std::shared_ptr m_manager; + std::shared_ptr m_interface; public: - testOutWrite(boost::shared_ptr _manager) : + testOutWrite(std::shared_ptr _manager) : m_manager(_manager){ //Set stereo output: - m_channelMap.push_back(audio_algo_core::channel_frontLeft); - m_channelMap.push_back(audio_algo_core::channel_frontRight); + m_channelMap.push_back(airtalgo::channel_frontLeft); + m_channelMap.push_back(airtalgo::channel_frontRight); m_interface = m_manager->createOutput(48000, m_channelMap, - audio_algo_core::format_int16, + airtalgo::format_int16, "default", "WriteMode"); } @@ -42,47 +51,73 @@ class testOutWrite { phase -= 2*M_PI; } } - ROS_INFO("send data"); + APPL_INFO("send data"); m_interface->write(data); } m_interface->stop(); } }; - +#endif class testOutCallback { private: - boost::shared_ptr m_manager; - boost::shared_ptr m_interface; + std::shared_ptr m_manager; + std::shared_ptr m_interface; double m_phase; public: - testOutCallback(boost::shared_ptr _manager) : + testOutCallback(std::shared_ptr _manager) : m_manager(_manager), m_phase(0) { //Set stereo output: - std::vector channelMap; - channelMap.push_back(audio_algo_core::channel_frontLeft); - channelMap.push_back(audio_algo_core::channel_frontRight); + std::vector channelMap; + channelMap.push_back(airtalgo::channel_frontLeft); + channelMap.push_back(airtalgo::channel_frontRight); m_interface = m_manager->createOutput(48000, channelMap, - audio_algo_core::format_int16, + airtalgo::format_int16, "default", "WriteModeCallback"); // set callback mode ... - m_interface->setOutputCallbackInt16(1024, boost::bind(&testOutCallback::onDataNeeded, this, _1, _2, _3)); + m_interface->setOutputCallback(1024, + std::bind(&testOutCallback::onDataNeeded, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4, + std::placeholders::_5), + airtalgo::formatDataTypeInt16); } ~testOutCallback() { } - std::vector onDataNeeded(const boost::chrono::system_clock::time_point& _playTime, - const size_t& _nbChunk, - const std::vector& _map) { + void onDataNeeded(const std::chrono::system_clock::time_point& _playTime, + const size_t& _nbChunk, + const std::vector& _map, + void* _data, + enum airtalgo::formatDataType& _type) { + if (_type != airtalgo::formatDataTypeInt16) { + APPL_ERROR("call wrong type ..."); + } + int16_t* data = static_cast(_data); + double baseCycle = 2.0*M_PI/(double)48000 * (double)550; + APPL_INFO("Get data ..."); + for (int32_t iii=0; iii<_nbChunk; iii++) { + for (int32_t jjj=0; jjj<_map.size(); jjj++) { + data[_map.size()*iii+jjj] = cos(m_phase) * 30000; + } + m_phase += baseCycle; + if (m_phase >= 2*M_PI) { + m_phase -= 2*M_PI; + } + } + /* std::vector data; data.resize(_nbChunk*_map.size()); double baseCycle = 2.0*M_PI/(double)48000 * (double)550; - ROS_INFO("Get data ..."); + APPL_INFO("Get data ..."); for (int32_t iii=0; iii m_channelMap; - boost::shared_ptr m_manager; - boost::shared_ptr m_interface; + std::vector m_channelMap; + std::shared_ptr m_manager; + std::shared_ptr m_interface; public: - testInRead(boost::shared_ptr _manager) : + testInRead(std::shared_ptr _manager) : m_manager(_manager){ //Set stereo output: - m_channelMap.push_back(audio_algo_core::channel_frontLeft); - m_channelMap.push_back(audio_algo_core::channel_frontRight); + m_channelMap.push_back(airtalgo::channel_frontLeft); + m_channelMap.push_back(airtalgo::channel_frontRight); m_interface = m_manager->createInput(48000, m_channelMap, - audio_algo_core::format_int16, + airtalgo::format_int16, "default", "WriteMode"); } @@ -136,7 +172,7 @@ class testInRead { value += std::abs(data[iii]); } value /= data.size(); - ROS_INFO("Get data ... average = %d", static_cast(value)); + APPL_INFO("Get data ... average=" << int32_t(value)); } m_interface->stop(); } @@ -145,40 +181,40 @@ class testInRead { class testInCallback { private: - boost::shared_ptr m_manager; - boost::shared_ptr m_interface; + std::shared_ptr m_manager; + std::shared_ptr m_interface; double m_phase; public: - testInCallback(boost::shared_ptr _manager) : + testInCallback(std::shared_ptr _manager) : m_manager(_manager), m_phase(0) { //Set stereo output: - std::vector channelMap; - channelMap.push_back(audio_algo_core::channel_frontLeft); - channelMap.push_back(audio_algo_core::channel_frontRight); + std::vector channelMap; + channelMap.push_back(airtalgo::channel_frontLeft); + channelMap.push_back(airtalgo::channel_frontRight); m_interface = m_manager->createInput(48000, channelMap, - audio_algo_core::format_int16, + airtalgo::format_int16, "default", "WriteModeCallback"); // set callback mode ... - m_interface->setInputCallbackInt16(1024, boost::bind(&testInCallback::onDataReceived, this, _1, _2, _3, _4)); + m_interface->setInputCallbackInt16(1024, std::bind(&testInCallback::onDataReceived, this, _1, _2, _3, _4)); } ~testInCallback() { } - void onDataReceived(const boost::chrono::system_clock::time_point& _playTime, + void onDataReceived(const std::chrono::system_clock::time_point& _playTime, const size_t& _nbChunk, - const std::vector& _map, + const std::vector& _map, const std::vector& _data) { int64_t value = 0; for (size_t iii=0; iii<_data.size(); ++iii) { value += std::abs(_data[iii]); } value /= _data.size(); - ROS_INFO("Get data ... average = %d", static_cast(value)); + APPL_INFO("Get data ... average=" << int32_t(value)); } void run() { @@ -192,76 +228,76 @@ class testInCallback { class testOutCallbackFloat { private: - boost::shared_ptr m_manager; - boost::shared_ptr m_interface; + std::shared_ptr m_manager; + std::shared_ptr m_interface; double m_phase; float m_freq; int32_t m_nbChannels; float m_generateFreq; public: - testOutCallbackFloat(boost::shared_ptr _manager, + testOutCallbackFloat(std::shared_ptr _manager, float _freq=48000.0f, int32_t _nbChannels=2, - audio_algo_core::format _format=audio_algo_core::format_int16) : + airtalgo::format _format=airtalgo::format_int16) : m_manager(_manager), m_phase(0), m_freq(_freq), m_nbChannels(_nbChannels), m_generateFreq(550.0f) { //Set stereo output: - std::vector channelMap; + std::vector channelMap; if (m_nbChannels == 1) { - channelMap.push_back(audio_algo_core::channel_frontCenter); + channelMap.push_back(airtalgo::channel_frontCenter); } else if (m_nbChannels == 2) { - channelMap.push_back(audio_algo_core::channel_frontLeft); - channelMap.push_back(audio_algo_core::channel_frontRight); + channelMap.push_back(airtalgo::channel_frontLeft); + channelMap.push_back(airtalgo::channel_frontRight); } else if (m_nbChannels == 4) { - channelMap.push_back(audio_algo_core::channel_frontLeft); - channelMap.push_back(audio_algo_core::channel_frontRight); - channelMap.push_back(audio_algo_core::channel_rearLeft); - channelMap.push_back(audio_algo_core::channel_rearRight); + channelMap.push_back(airtalgo::channel_frontLeft); + channelMap.push_back(airtalgo::channel_frontRight); + channelMap.push_back(airtalgo::channel_rearLeft); + channelMap.push_back(airtalgo::channel_rearRight); } else { - ROS_ERROR("Can not generate with channel != 1,2,4"); + APPL_ERROR("Can not generate with channel != 1,2,4"); return; } switch (_format) { - case audio_algo_core::format_int16: + case airtalgo::format_int16: m_interface = m_manager->createOutput(m_freq, channelMap, _format, "default", "WriteModeCallbackI16"); // set callback mode ... - ROS_ERROR("Set callback"); - m_interface->setOutputCallbackInt16(1024, boost::bind(&testOutCallbackFloat::onDataNeededI16, this, _1, _2, _3)); + APPL_ERROR("Set callback"); + m_interface->setOutputCallbackInt16(1024, std::bind(&testOutCallbackFloat::onDataNeededI16, this, _1, _2, _3)); break; - case audio_algo_core::format_int16_on_int32: + case airtalgo::format_int16_on_int32: m_interface = m_manager->createOutput(m_freq, channelMap, _format, "default", "WriteModeCallbackI16onI32"); // set callback mode ... - m_interface->setOutputCallbackInt32(1024, boost::bind(&testOutCallbackFloat::onDataNeededI16_I32, this, _1, _2, _3)); + m_interface->setOutputCallbackInt32(1024, std::bind(&testOutCallbackFloat::onDataNeededI16_I32, this, _1, _2, _3)); break; - case audio_algo_core::format_int32: + case airtalgo::format_int32: m_interface = m_manager->createOutput(m_freq, channelMap, _format, "default", "WriteModeCallbackI32"); // set callback mode ... - m_interface->setOutputCallbackInt32(1024, boost::bind(&testOutCallbackFloat::onDataNeededI32, this, _1, _2, _3)); + m_interface->setOutputCallbackInt32(1024, std::bind(&testOutCallbackFloat::onDataNeededI32, this, _1, _2, _3)); break; - case audio_algo_core::format_float: + case airtalgo::format_float: m_interface = m_manager->createOutput(m_freq, channelMap, _format, "default", "WriteModeCallbackFloat"); // set callback mode ... - m_interface->setOutputCallbackFloat(1024, boost::bind(&testOutCallbackFloat::onDataNeededFloat, this, _1, _2, _3)); + m_interface->setOutputCallbackFloat(1024, std::bind(&testOutCallbackFloat::onDataNeededFloat, this, _1, _2, _3)); break; } } @@ -270,13 +306,13 @@ class testOutCallbackFloat { } - std::vector onDataNeededI16(const boost::chrono::system_clock::time_point& _playTime, + std::vector onDataNeededI16(const std::chrono::system_clock::time_point& _playTime, const size_t& _nbChunk, - const std::vector& _map) { + const std::vector& _map) { std::vector data; data.resize(_nbChunk*_map.size()); double baseCycle = 2.0*M_PI/(double)m_freq * (double)m_generateFreq; - ROS_INFO("Get data ... %ld", _map.size()); + APPL_INFO("Get data ... " << _map.size()); for (int32_t iii=0; iii onDataNeededI16_I32(const boost::chrono::system_clock::time_point& _playTime, + std::vector onDataNeededI16_I32(const std::chrono::system_clock::time_point& _playTime, const size_t& _nbChunk, - const std::vector& _map) { + const std::vector& _map) { std::vector data; data.resize(_nbChunk*_map.size()); double baseCycle = 2.0*M_PI/(double)m_freq * (double)m_generateFreq; - //ROS_INFO("Get data ..."); + APPL_VERBOSE("Get data ..."); for (int32_t iii=0; iii onDataNeededI32(const boost::chrono::system_clock::time_point& _playTime, + std::vector onDataNeededI32(const std::chrono::system_clock::time_point& _playTime, const size_t& _nbChunk, - const std::vector& _map) { + const std::vector& _map) { std::vector data; data.resize(_nbChunk*_map.size()); double baseCycle = 2.0*M_PI/(double)m_freq * (double)m_generateFreq; - //ROS_INFO("Get data ..."); + APPL_VERBOSE("Get data ..."); for (int32_t iii=0; iii onDataNeededFloat(const boost::chrono::system_clock::time_point& _playTime, + std::vector onDataNeededFloat(const std::chrono::system_clock::time_point& _playTime, const size_t& _nbChunk, - const std::vector& _map) { + const std::vector& _map) { std::vector data; data.resize(_nbChunk*_map.size()); double baseCycle = 2.0*M_PI/(double)m_freq * (double)m_generateFreq; - //ROS_INFO("Get data ..."); + APPL_VERBOSE("Get data ..."); for (int32_t iii=0; iiistop(); } else { - ROS_ERROR("Can not create interface !!!"); + APPL_ERROR("Can not create interface !!!"); } } }; +#endif - +TEST(TestALL, testOutputCallBack) { + std::shared_ptr manager; + manager = airtio::Manager::create("testApplication"); + + APPL_INFO("test output (callback mode)"); + std::shared_ptr process = std::make_shared(manager); + process->run(); + process.reset(); + usleep(500000); +} int main(int argc, char **argv) { - boost::shared_ptr manager; - manager = audio_base::Manager::create("testApplication"); + // init Google test : + ::testing::InitGoogleTest(&argc, const_cast(argv)); + // the only one init for etk: + etk::log::setLevel(etk::log::logLevelNone); + for (int32_t iii=0; iii process = boost::make_shared(manager); + std::shared_ptr process = std::make_shared(manager); process->run(); process.reset(); } @@ -382,9 +465,9 @@ int main(int argc, char **argv) { #endif #if 0 - ROS_INFO("test output (callback mode)"); + APPL_INFO("test input (Read mode)"); { - boost::shared_ptr process = boost::make_shared(manager); + std::shared_ptr process = std::make_shared(manager); process->run(); process.reset(); } @@ -392,27 +475,17 @@ int main(int argc, char **argv) { #endif #if 0 - ROS_INFO("test input (Read mode)"); + APPL_INFO("test input (callback mode)"); { - boost::shared_ptr process = boost::make_shared(manager); + std::shared_ptr process = std::make_shared(manager); process->run(); process.reset(); } - usleep(500000); #endif + #if 0 - ROS_INFO("test input (callback mode)"); - { - boost::shared_ptr process = boost::make_shared(manager); - process->run(); - process.reset(); - } - #endif - - - #if 1 - ROS_INFO("test convert flaot to output (callback mode)"); + APPL_INFO("test convert flaot to output (callback mode)"); std::vector listFreq; listFreq.push_back(4000); listFreq.push_back(8000); @@ -431,18 +504,18 @@ int main(int argc, char **argv) { listChannel.push_back(1); listChannel.push_back(2); listChannel.push_back(4); - std::vector listFormat; - listFormat.push_back(audio_algo_core::format_int16); - listFormat.push_back(audio_algo_core::format_int16_on_int32); - listFormat.push_back(audio_algo_core::format_int32); - listFormat.push_back(audio_algo_core::format_float); + std::vector listFormat; + listFormat.push_back(airtalgo::format_int16); + listFormat.push_back(airtalgo::format_int16_on_int32); + listFormat.push_back(airtalgo::format_int32); + listFormat.push_back(airtalgo::format_float); for (int32_t iii=0; iii::iterator formatIt = listFormat.begin(); formatIt != listFormat.end(); ++formatIt) { + for (std::vector::iterator formatIt = listFormat.begin(); formatIt != listFormat.end(); ++formatIt) { float freq = listFreq[iii]; int32_t channel = listChannel[jjj]; - ROS_INFO("freq = %f channel=%d format=%s", freq, channel, getFormatString(*formatIt).c_str()); - boost::shared_ptr process = boost::make_shared(manager, freq, channel, *formatIt); + APPL_INFO("freq=" << freq << " channel=" << channel << " format=" << getFormatString(*formatIt)); + std::shared_ptr process = std::make_shared(manager, freq, channel, *formatIt); process->run(); process.reset(); usleep(500000); @@ -450,8 +523,5 @@ int main(int argc, char **argv) { } } #endif - ROS_INFO("TEST ended"); - - return 0; }