diff --git a/airtio/Interface.cpp b/airtio/Interface.cpp index a59ce65..0427e4c 100644 --- a/airtio/Interface.cpp +++ b/airtio/Interface.cpp @@ -15,6 +15,9 @@ #include +#undef __class__ +#define __class__ "Interface" + airtio::Interface::Interface(void) : m_node(nullptr), m_freq(8000), @@ -120,20 +123,20 @@ airtio::Interface::~Interface() { } -void airtio::Interface::setOutputCallback(size_t _chunkSize, airtalgo::needDataFunction _function, enum airtalgo::formatDataType _dataType) { +void airtio::Interface::setOutputCallback(size_t _chunkSize, airtalgo::needDataFunction _function) { std::unique_lock lock(m_mutex); m_process->removeIfFirst(); - std::shared_ptr algo = std::make_shared(_function, _dataType); + std::shared_ptr algo = std::make_shared(_function); 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_process->pushFront(algo); } -void airtio::Interface::setInputCallback(size_t _chunkSize, airtalgo::haveNewDataFunction _function, enum airtalgo::formatDataType _dataType) { +void airtio::Interface::setInputCallback(size_t _chunkSize, airtalgo::haveNewDataFunction _function) { std::unique_lock lock(m_mutex); m_process->removeIfLast(); - std::shared_ptr algo = std::make_shared(_function, _dataType); + std::shared_ptr algo = std::make_shared(_function); algo->setInputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); algo->setOutputFormat(airtalgo::IOFormatInterface(m_map, m_format, m_freq)); m_process->pushBack(algo); @@ -181,11 +184,7 @@ std::pair airtio::Interface::getVolumeRange() const { return std::make_pair(-120.0f, 0.0f); } -void airtio::Interface::write(const std::vector& _value) { - write(&_value[0], _value.size()); -} - -void airtio::Interface::write(const int16_t* _value, size_t _nbChunk) { +void airtio::Interface::write(const void* _value, size_t _nbChunk) { std::unique_lock lock(m_mutex); std::shared_ptr algo = m_process->get(0); if (algo == nullptr) { @@ -194,6 +193,7 @@ void airtio::Interface::write(const int16_t* _value, size_t _nbChunk) { algo->write(_value, _nbChunk); } +#if 0 // TODO : add API aCCess mutex for Read and write... std::vector airtio::Interface::read(size_t _nbChunk) { // TODO :... @@ -216,8 +216,9 @@ std::vector airtio::Interface::read(size_t _nbChunk) { */ return data; } +#endif -void airtio::Interface::read(const int16_t* _value, size_t _nbChunk) { +void airtio::Interface::read(void* _value, size_t _nbChunk) { std::unique_lock lock(m_mutex); // TODO :... @@ -256,64 +257,10 @@ std::chrono::system_clock::time_point airtio::Interface::getCurrentTime() const -void airtio::Interface::systemNewInputData(std::chrono::system_clock::time_point _time, void* _data, int32_t _nbChunk) { +void airtio::Interface::systemNewInputData(std::chrono::system_clock::time_point _time, void* _data, size_t _nbChunk) { 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); - AIRTIO_VERBOSE(" Interface DIRECT "); - while(m_data.size()<_nbChunk*_chunkSize) { - void* in = nullptr; - size_t nbChunkIn = _nbChunk - m_data.size()/_chunkSize; - void* out = nullptr; - size_t nbChunkOut; - if (nbChunkIn < 128) { - nbChunkIn = 128; - } - // TODO : maybe remove this for input data ... - 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; - } - //nbChunkIn *= 4; - // get data from the upstream - 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); - memcpy(&m_data[position], out, nbChunkOut*_chunkSize); - } else { - // TODO : ERROR ... - break; - } - } - if (m_data.size()>=_nbChunk*_chunkSize) { - AIRTIO_VERBOSE(" * copy needed data"); - memcpy(_data, &m_data[0], _nbChunk*_chunkSize); - m_data.erase(m_data.begin(), m_data.begin()+_nbChunk*_chunkSize); - } else { - AIRTIO_VERBOSE(" * soft underflow"); - // ERROR - m_data.clear(); - } - /* - process(_time, in, nbChunkIn, out, nbChunkOut); - if (nbChunkIn!=nbChunkOut) { - AIRTIO_ERROR(" wrong size : request=" << _nbChunk << " get=" << nbChunkOut); - return; - } - memcpy(_data, out, _nbChunk*_chunkSize); - */ -#endif +void airtio::Interface::systemNeedOutputData(std::chrono::system_clock::time_point _time, void*& _data, size_t& _nbChunk, size_t _chunkSize) { + m_process->pull(_time, _data, _nbChunk);//, _chunkSize); } diff --git a/airtio/Interface.h b/airtio/Interface.h index c2e2b58..ed4bd9a 100644 --- a/airtio/Interface.h +++ b/airtio/Interface.h @@ -65,8 +65,8 @@ namespace airtio { * @brief When we want to implement a Callback Mode : */ //virtual void setWriteCallback(size_t _chunkSize, writeNeedDataFunction_int16_t _function) {}; - virtual void setOutputCallback(size_t _chunkSize, airtalgo::needDataFunction _function, enum airtalgo::formatDataType _dataType); - virtual void setInputCallback(size_t _chunkSize, airtalgo::haveNewDataFunction _function, enum airtalgo::formatDataType _dataType); + virtual void setOutputCallback(size_t _chunkSize, airtalgo::needDataFunction _function); + virtual void setInputCallback(size_t _chunkSize, airtalgo::haveNewDataFunction _function); public: /** * @brief Start the Audio interface flow. @@ -100,32 +100,20 @@ namespace airtio { * @return The gain in decibel range of this interface */ virtual std::pair getVolumeRange() const; - /** - * @brief write some audio sample in the speakers - * @param[in] _value Data To write on output - */ - // TODO : TimeOut ??? - virtual void write(const std::vector& _value); /** * @brief write some audio sample in the speakers * @param[in] _value Data To write on output * @param[in] _nbChunk Number of audio chunk to write */ // TODO : TimeOut ??? - virtual void write(const int16_t* _value, size_t _nbChunk); - /** - * @brief write some audio sample in the speakers - * @param[in] _value Data To write on output - */ - // TODO : TimeOut ??? - virtual std::vector read(size_t _nbChunk); + virtual void write(const void* _value, size_t _nbChunk); /** * @brief read some audio sample from Microphone * @param[in] _value Data To write on output * @param[in] _nbChunk Number of audio chunk to write */ // TODO : TimeOut ??? - virtual void read(const int16_t* _value, size_t _nbChunk); + virtual void read(void* _value, size_t _nbChunk); /** * @brief Get number of chunk in the local buffer * @return Number of chunk @@ -151,8 +139,8 @@ namespace airtio { */ virtual std::chrono::system_clock::time_point getCurrentTime() const; private: - virtual void systemNewInputData(std::chrono::system_clock::time_point _time, void* _data, int32_t _nbChunk); - virtual void systemNeedOutputData(std::chrono::system_clock::time_point _time, void* _data, int32_t _nbChunk, size_t _chunkSize); + virtual void systemNewInputData(std::chrono::system_clock::time_point _time, void* _data, size_t _nbChunk); + virtual void systemNeedOutputData(std::chrono::system_clock::time_point _time, void*& _data, size_t& _nbChunk, size_t _chunkSize); std::vector m_data; float m_volume; //!< Local channel Volume diff --git a/airtio/Manager.cpp b/airtio/Manager.cpp index 804bc65..16e8dcd 100644 --- a/airtio/Manager.cpp +++ b/airtio/Manager.cpp @@ -12,6 +12,9 @@ #include "io/Manager.h" #include "io/Node.h" +#undef __class__ +#define __class__ "Manager" + std::shared_ptr airtio::Manager::create(const std::string& _applicationUniqueId) { return std::shared_ptr(new airtio::Manager(_applicationUniqueId)); } diff --git a/airtio/io/Manager.cpp b/airtio/io/Manager.cpp index 37c82d9..47ab7da 100644 --- a/airtio/io/Manager.cpp +++ b/airtio/io/Manager.cpp @@ -8,6 +8,9 @@ #include #include "Node.h" +#undef __class__ +#define __class__ "io::Manager" + std::shared_ptr airtio::io::Manager::getInstance() { static std::shared_ptr manager(new Manager()); return manager; diff --git a/airtio/io/Node.cpp b/airtio/io/Node.cpp index 6bde9c9..e9b7c28 100644 --- a/airtio/io/Node.cpp +++ b/airtio/io/Node.cpp @@ -9,6 +9,9 @@ #include +#undef __class__ +#define __class__ "io::Node" + #ifndef INT16_MAX #define INT16_MAX 0x7fff #endif @@ -22,26 +25,11 @@ #define INT32_MIN (-INT32_MAX - 1L) #endif -// RT audio out callback -static int rtAudioCallbackStatic(void* _outputBuffer, - void* _inputBuffer, - unsigned int _nBufferFrames, - double _streamTime, - airtaudio::streamStatus _status, - void* _data) { - airtio::io::Node* interface = static_cast(_data); - return interface->rtAudioCallback(static_cast(_outputBuffer), - static_cast(_inputBuffer), - _nBufferFrames, - _streamTime, - _status); -} - -int airtio::io::Node::rtAudioCallback(int16_t* _outputBuffer, - int16_t* _inputBuffer, - unsigned int _nBufferFrames, - double _streamTime, - airtaudio::streamStatus _status) { +int32_t airtio::io::Node::rtAudioCallback(void* _outputBuffer, + void* _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(); @@ -49,13 +37,16 @@ int airtio::io::Node::rtAudioCallback(int16_t* _outputBuffer, 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) { - 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()); + int16_t* outputTmp = nullptr; + void* outputTmp2 = nullptr; + size_t tmpSize = 0; + for (auto &it : m_list) { + if (it != nullptr) { + AIRTIO_VERBOSE(" IO : " /* << std::distance(m_list.begin(), it)*/ << "/" << m_list.size() << " name="<< it->getName()); + tmpSize = _nBufferFrames; + it->systemNeedOutputData(ttime, outputTmp2, tmpSize, sizeof(int16_t)*m_map.size()); + outputTmp = static_cast(outputTmp2); + //it->systemNeedOutputData(ttime, _outputBuffer, _nBufferFrames, sizeof(int16_t)*m_map.size()); // Add data to the output tmp buffer : for (size_t kkk=0; kkk(outputTmp[kkk]); @@ -64,17 +55,19 @@ int airtio::io::Node::rtAudioCallback(int16_t* _outputBuffer, break; } } + int16_t* outputBuffer = static_cast(_outputBuffer); for (size_t kkk=0; kkk(std::min(std::max(INT16_MIN, output[kkk]), INT16_MAX)); + *outputBuffer++ = static_cast(std::min(std::max(INT16_MIN, output[kkk]), INT16_MAX)); //*_outputBuffer++ = static_cast(output[kkk]); } } if (_inputBuffer != nullptr) { AIRTIO_INFO("data Input"); + int16_t* inputBuffer = static_cast(_inputBuffer); for (size_t iii=0; iii< m_list.size(); ++iii) { if (m_list[iii] != nullptr) { AIRTIO_INFO(" IO : " << iii+1 << "/" << m_list.size() << " name="<< m_list[iii]->getName()); - m_list[iii]->systemNewInputData(ttime, _inputBuffer, _nBufferFrames); + m_list[iii]->systemNewInputData(ttime, inputBuffer, _nBufferFrames); } } } @@ -180,9 +173,27 @@ airtio::io::Node::Node(const std::string& _streamName, bool _isInput) : AIRTIO_INFO("Open output stream nbChannels=" << params.nChannels); enum airtaudio::errorType err = airtaudio::errorNone; if (m_isInput == true) { - err = m_adac.openStream( nullptr, ¶ms, airtaudio::SINT16, m_frequency, &m_rtaudioFrameSize, &rtAudioCallbackStatic, (void *)this ); + err = m_adac.openStream(nullptr, ¶ms, + airtaudio::SINT16, m_frequency, &m_rtaudioFrameSize, + std::bind(&airtio::io::Node::rtAudioCallback, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4, + std::placeholders::_5) + ); } else { - err = m_adac.openStream( ¶ms, nullptr, airtaudio::SINT16, m_frequency, &m_rtaudioFrameSize, &rtAudioCallbackStatic, (void *)this ); + err = m_adac.openStream(¶ms, nullptr, + airtaudio::SINT16, m_frequency, &m_rtaudioFrameSize, + std::bind(&airtio::io::Node::rtAudioCallback, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4, + std::placeholders::_5) + ); } if (err != airtaudio::errorNone) { AIRTIO_ERROR("Create stream : '" << m_streamName << "' mode=" << (m_isInput?"input":"output") << " can not create strem " << err); diff --git a/airtio/io/Node.h b/airtio/io/Node.h index 061475f..7dbaf99 100644 --- a/airtio/io/Node.h +++ b/airtio/io/Node.h @@ -47,11 +47,11 @@ namespace airtio { airtaudio::DeviceInfo m_info; unsigned int m_rtaudioFrameSize; public: - int rtAudioCallback(int16_t* _outputBuffer, - int16_t* _inputBuffer, - unsigned int _nBufferFrames, - double _streamTime, - airtaudio::streamStatus _status); + int32_t rtAudioCallback(void* _outputBuffer, + void * _inputBuffer, + unsigned int _nBufferFrames, + double _streamTime, + airtaudio::streamStatus _status); private: std::string m_streamName; public: diff --git a/test/main.cpp b/test/main.cpp index 36b5fc3..5bb5585 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -13,7 +13,9 @@ #include #include -#if 0 +#undef __class__ +#define __class__ "test" + class testOutWrite { private: std::vector m_channelMap; @@ -21,7 +23,7 @@ class testOutWrite { std::shared_ptr m_interface; public: testOutWrite(std::shared_ptr _manager) : - m_manager(_manager){ + m_manager(_manager) { //Set stereo output: m_channelMap.push_back(airtalgo::channel_frontLeft); m_channelMap.push_back(airtalgo::channel_frontRight); @@ -31,33 +33,41 @@ class testOutWrite { "default", "WriteMode"); } - ~testOutWrite() { - - } - void run() { m_interface->start(); double phase=0; std::vector data; data.resize(1024*m_channelMap.size()); - double baseCycle = 2.0*M_PI/(double)48000 * (double)440; + double baseCycle = 2.0*M_PI/48000.0 * 440.0; for (int32_t kkk=0; kkk<100; ++kkk) { for (int32_t iii=0; iii= 2*M_PI) { phase -= 2*M_PI; } } - APPL_INFO("send data"); - m_interface->write(data); + m_interface->write(&data[0], data.size()/m_channelMap.size()); + // TODO : Add a function to get number of time we need to wait enought time ... + usleep(15000); } m_interface->stop(); } }; -#endif + +TEST(TestALL, testOutputWrite) { + 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); +} + class testOutCallback { private: @@ -85,25 +95,18 @@ class testOutCallback { std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), - airtalgo::formatDataTypeInt16); + std::placeholders::_5)); } - - ~testOutCallback() { - - } - 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 ..."); + enum airtalgo::format _type) { + if (_type != airtalgo::format_int16) { + APPL_ERROR("call wrong type ... (need int16_t)"); } 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; @@ -113,25 +116,7 @@ class testOutCallback { m_phase -= 2*M_PI; } } - /* - std::vector data; - data.resize(_nbChunk*_map.size()); - double baseCycle = 2.0*M_PI/(double)48000 * (double)550; - APPL_INFO("Get data ..."); - - for (int32_t iii=0; iii= 2*M_PI) { - m_phase -= 2*M_PI; - } - } - return data; - */ } - void run() { m_interface->start(); // wait 2 second ... @@ -140,6 +125,18 @@ class testOutCallback { } }; +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); +} + + #if 0 class testInRead { private: @@ -158,10 +155,6 @@ class testInRead { "default", "WriteMode"); } - ~testInRead() { - - } - void run() { m_interface->start(); std::vector data; @@ -177,7 +170,7 @@ class testInRead { m_interface->stop(); } }; - +#endif class testInCallback { private: @@ -198,25 +191,31 @@ class testInCallback { "default", "WriteModeCallback"); // set callback mode ... - m_interface->setInputCallbackInt16(1024, std::bind(&testInCallback::onDataReceived, this, _1, _2, _3, _4)); + m_interface->setInputCallback(1024, + std::bind(&testInCallback::onDataReceived, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3, + std::placeholders::_4, + std::placeholders::_5)); } - - ~testInCallback() { - - } - - void onDataReceived(const std::chrono::system_clock::time_point& _playTime, - const size_t& _nbChunk, + void onDataReceived(const std::chrono::system_clock::time_point& _readTime, + size_t _nbChunk, 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]); + const void* _data, + enum airtalgo::format _type) { + if (_type != airtalgo::format_int16) { + APPL_ERROR("call wrong type ... (need int16_t)"); } - value /= _data.size(); + const int16_t* data = static_cast(_data); + int64_t value = 0; + for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) { + value += std::abs(data[iii]); + } + value /= (_nbChunk*_map.size()); APPL_INFO("Get data ... average=" << int32_t(value)); } - void run() { m_interface->start(); // wait 2 second ... @@ -225,7 +224,18 @@ class testInCallback { } }; +TEST(TestALL, testInputCallBack) { + std::shared_ptr manager; + manager = airtio::Manager::create("testApplication"); + APPL_INFO("test input (callback mode)"); + std::shared_ptr process = std::make_shared(manager); + process->run(); + process.reset(); + usleep(500000); +} + +#if 0 class testOutCallbackFloat { private: std::shared_ptr m_manager; @@ -402,16 +412,7 @@ class testOutCallbackFloat { #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) {