From 01d36bd995501c4389605201099e6376e6e9095a Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 17 Feb 2015 21:08:15 +0100 Subject: [PATCH] [DEV] change callback name and update the timestamp of the resampler --- drain/Algo.h | 1 + drain/EndPointCallback.cpp | 46 ++-- drain/EndPointCallback.h | 30 +-- drain/EndPointWrite.cpp | 10 +- drain/EndPointWrite.h | 13 +- drain/Process.cpp | 496 ++++++++++++++++++------------------- drain/Process.h | 3 + drain/Resampler.cpp | 40 ++- drain/Resampler.h | 4 + 9 files changed, 333 insertions(+), 310 deletions(-) diff --git a/drain/Algo.h b/drain/Algo.h index 07808d3..02a323c 100644 --- a/drain/Algo.h +++ b/drain/Algo.h @@ -120,6 +120,7 @@ namespace drain{ * @param[in] _output number of chunk estimate in output * @return number of sample needed to have nearly the good number of sample */ + // TODO : Manage the change of the timestamp ... virtual size_t needInputData(size_t _output); protected: // note when nothing ==> support all type std::vector m_supportedFormat; diff --git a/drain/EndPointCallback.cpp b/drain/EndPointCallback.cpp index 99f8432..800f0cb 100644 --- a/drain/EndPointCallback.cpp +++ b/drain/EndPointCallback.cpp @@ -16,24 +16,24 @@ drain::EndPointCallback::EndPointCallback() : } -void drain::EndPointCallback::init(needDataFunction _callback) { +void drain::EndPointCallback::init(playbackFunction _callback) { m_outputFunction = _callback; drain::EndPoint::init(); m_type = "EndPointCallback"; } -void drain::EndPointCallback::init(haveNewDataFunction _callback) { +void drain::EndPointCallback::init(recordFunction _callback) { m_inputFunction = _callback; drain::EndPoint::init(); m_type = "EndPointCallback"; } -std::shared_ptr drain::EndPointCallback::create(needDataFunction _callback) { +std::shared_ptr drain::EndPointCallback::create(playbackFunction _callback) { std::shared_ptr tmp(new drain::EndPointCallback()); tmp->init(_callback); return tmp; } -std::shared_ptr drain::EndPointCallback::create(haveNewDataFunction _callback) { +std::shared_ptr drain::EndPointCallback::create(recordFunction _callback) { std::shared_ptr tmp(new drain::EndPointCallback()); tmp->init(_callback); return tmp; @@ -47,21 +47,33 @@ void drain::EndPointCallback::configurationChange() { bool drain::EndPointCallback::process(std::chrono::system_clock::time_point& _time, - void* _input, // uneeded - size_t _inputNbChunk, // requested number of sample ... - void*& _output, - size_t& _outputNbChunk){ + void* _input, + size_t _inputNbChunk, + void*& _output, + size_t& _outputNbChunk){ drain::AutoLogInOut tmpLog("EndPointCallback"); + if (m_inputFunction != nullptr) { + // Call user ... + DRAIN_VERBOSE("call user set " << _inputNbChunk << "*" << m_input.getMap().size()); + m_inputFunction(_input, + _time, + _inputNbChunk, + m_output.getFormat(), + m_output.getFrequency(), + m_output.getMap()); + return true; + } if (m_outputFunction != nullptr) { // update buffer size ... m_outputData.resize(_inputNbChunk*m_output.getMap().size()*m_formatSize); // call user DRAIN_VERBOSE("call user get " << _inputNbChunk << "*" << m_output.getMap().size() << " map=" << m_output.getMap() << " datasize=" << int32_t(m_formatSize)); - m_outputFunction(_time, + m_outputFunction(&m_outputData[0], + _time, _inputNbChunk, - m_output.getMap(), - &m_outputData[0], - m_output.getFormat()); + m_output.getFormat(), + m_output.getFrequency(), + m_output.getMap()); if (m_outputData.size() != _inputNbChunk*m_output.getMap().size()*m_formatSize) { DRAIN_ERROR(" can not get enough data from user ... " << m_outputData.size() << " != " << _inputNbChunk*m_output.getMap().size()); return false; @@ -70,16 +82,6 @@ bool drain::EndPointCallback::process(std::chrono::system_clock::time_point& _ti _outputNbChunk = _inputNbChunk; return true; } - if (m_inputFunction != nullptr) { - // Call user ... - DRAIN_VERBOSE("call user set " << _inputNbChunk << "*" << m_input.getMap().size()); - m_inputFunction(_time, - _inputNbChunk, - m_input.getMap(), - _input, - m_input.getFormat()); - return true; - } return false; } diff --git a/drain/EndPointCallback.h b/drain/EndPointCallback.h index 5bfdbb7..c2bdc8e 100644 --- a/drain/EndPointCallback.h +++ b/drain/EndPointCallback.h @@ -12,30 +12,32 @@ namespace drain { - typedef std::function& _map, - void* _data, - enum audio::format _type)> needDataFunction; - typedef std::function& _map)> playbackFunction; + typedef std::function& _map, - const void* _data, - enum audio::format _type)> haveNewDataFunction; + enum audio::format _format, + uint32_t _frequency, + const std::vector& _map)> recordFunction; class EndPointCallback : public EndPoint { private: - needDataFunction m_outputFunction; - haveNewDataFunction m_inputFunction; + playbackFunction m_outputFunction; + recordFunction m_inputFunction; protected: /** * @brief Constructor */ EndPointCallback(); - void init(needDataFunction _callback); - void init(haveNewDataFunction _callback); + void init(playbackFunction _callback); + void init(recordFunction _callback); public: - static std::shared_ptr create(needDataFunction _callback); - static std::shared_ptr create(haveNewDataFunction _callback); + static std::shared_ptr create(playbackFunction _callback); + static std::shared_ptr create(recordFunction _callback); /** * @brief Destructor */ diff --git a/drain/EndPointWrite.cpp b/drain/EndPointWrite.cpp index e8c65c3..2809033 100644 --- a/drain/EndPointWrite.cpp +++ b/drain/EndPointWrite.cpp @@ -33,15 +33,15 @@ void drain::EndPointWrite::configurationChange() { bool drain::EndPointWrite::process(std::chrono::system_clock::time_point& _time, - void* _input, - size_t _inputNbChunk, - void*& _output, - size_t& _outputNbChunk){ + void* _input, + size_t _inputNbChunk, + void*& _output, + size_t& _outputNbChunk){ drain::AutoLogInOut tmpLog("EndPointWrite"); //DRAIN_INFO(" nb Sample in buffer : " << m_tmpData.size()); if (m_function != nullptr) { if (m_tmpData.size() <= 20000) { - m_function(_time, _inputNbChunk, m_output.getMap(), m_output.getFormat()); + m_function(_time, _inputNbChunk, m_output.getFormat(), m_output.getFrequency(), m_output.getMap()); } } // resize output buffer: diff --git a/drain/EndPointWrite.h b/drain/EndPointWrite.h index 0b08a2a..7b54576 100644 --- a/drain/EndPointWrite.h +++ b/drain/EndPointWrite.h @@ -12,14 +12,15 @@ #include namespace drain{ - typedef std::function& _map, - enum audio::format _type)> needDataFunctionWrite; + typedef std::function& _map)> playbackFunctionWrite; class EndPointWrite : public EndPoint { private: std::vector m_tmpData; - needDataFunctionWrite m_function; + playbackFunctionWrite m_function; std::mutex m_mutex; protected: /** @@ -40,7 +41,7 @@ namespace drain{ void*& _output, size_t& _outputNbChunk); virtual void write(const void* _value, size_t _nbChunk); - virtual void setCallback(needDataFunctionWrite _function) { + virtual void setCallback(playbackFunctionWrite _function) { m_function = _function; } }; diff --git a/drain/Process.cpp b/drain/Process.cpp index 5f379bc..f337ec5 100644 --- a/drain/Process.cpp +++ b/drain/Process.cpp @@ -143,12 +143,8 @@ template std::vector getUnion(const std::vector& _out, const s return out; } -void drain::Process::updateInterAlgo() { - if (m_isConfigured == true) { - // cahin is already configured - return ; - } - DRAIN_DEBUG("Display properties : nbAlgo : " << m_listAlgo.size()); + +void drain::Process::displayAlgo() { DRAIN_DEBUG(" Input : " << m_inputConfig); for (auto &it : m_listAlgo) { DRAIN_DEBUG(" [" << it->getType() << "] '" << it->getName() << "'"); @@ -170,272 +166,254 @@ void drain::Process::updateInterAlgo() { } } DRAIN_DEBUG(" Output : " << m_outputConfig); - DRAIN_DEBUG("********* configuration START *************"); - // TODO : Better management of this ... - /* - if (m_listAlgo.size() == 0) { - DRAIN_ERROR("manage empty drain ..."); - return; - } - if (m_listAlgo.size() == 1) { - DRAIN_ERROR("manage Single drain ..."); - return; - } - */ - /* - DRAIN_INFO("configuration Input"); - if (m_listAlgo.size()>1) { - m_listAlgo[0]->setInputFormat(m_inputConfig); - } - DRAIN_INFO("configuration Output"); - if (m_listAlgo.size()>1) { - m_listAlgo[m_listAlgo.size()-1]->setOutputFormat(m_outputConfig); - } - */ - for (size_t iii=0; iii<=m_listAlgo.size(); ++iii) { - DRAIN_VERBOSE(" id = " << iii); - if ( ( iii == 0 - || ( iii > 0 - && m_listAlgo[iii-1]->getOutputFormat().getConfigured() == false - ) - ) - && ( iii == m_listAlgo.size() - || ( iii < m_listAlgo.size() - && m_listAlgo[iii]->getInputFormat().getConfigured() == false - ) - ) - ) { - // step 1 : check frequency: - std::vector freqOut; - std::vector freqIn; - if (iii == 0) { - freqOut.push_back(m_inputConfig.getFrequency()); - } else { - freqOut = m_listAlgo[iii-1]->getFrequencySupportedOutput(); +} + +void drain::Process::updateAlgo(size_t _position) { + DRAIN_VERBOSE(" id = " << _position); + if ( ( _position == 0 + || ( _position > 0 + && m_listAlgo[_position-1]->getOutputFormat().getConfigured() == false + ) + ) + && ( _position == m_listAlgo.size() + || ( _position < m_listAlgo.size() + && m_listAlgo[_position]->getInputFormat().getConfigured() == false + ) + ) + ) { + // step 1 : check frequency: + std::vector freqOut; + std::vector freqIn; + if (_position == 0) { + freqOut.push_back(m_inputConfig.getFrequency()); + } else { + freqOut = m_listAlgo[_position-1]->getFrequencySupportedOutput(); + } + if (_position == m_listAlgo.size()) { + freqIn.push_back(m_outputConfig.getFrequency()); + } else { + freqIn = m_listAlgo[_position]->getFrequencySupportedInput(); + } + std::vector freq = getUnion(freqOut, freqIn); + DRAIN_VERBOSE(" freq out :" << freqOut); + DRAIN_VERBOSE(" freq in :" << freqIn); + DRAIN_DEBUG(" freq union :" << freq); + + // step 2 : Check map: + std::vector> mapOut; + std::vector> mapIn; + if (_position == 0) { + mapOut.push_back(m_inputConfig.getMap()); + } else { + mapOut = m_listAlgo[_position-1]->getMapSupportedOutput(); + } + if (_position == m_listAlgo.size()) { + mapIn.push_back(m_outputConfig.getMap()); + } else { + mapIn = m_listAlgo[_position]->getMapSupportedInput(); + } + std::vector> map = getUnion>(mapOut, mapIn); + DRAIN_VERBOSE(" map out :" << mapOut); + DRAIN_VERBOSE(" map in :" << mapIn); + DRAIN_DEBUG(" map union :" << map); + // step 3 : Check Format: + std::vector formatOut; + std::vector formatIn; + if (_position == 0) { + formatOut.push_back(m_inputConfig.getFormat()); + } else { + formatOut = m_listAlgo[_position-1]->getFormatSupportedOutput(); + } + if (_position == m_listAlgo.size()) { + formatIn.push_back(m_outputConfig.getFormat()); + } else { + formatIn = m_listAlgo[_position]->getFormatSupportedInput(); + } + std::vector format = getUnion(formatOut, formatIn); + DRAIN_VERBOSE(" format out :" << formatOut); + DRAIN_VERBOSE(" format in :" << formatIn); + DRAIN_DEBUG(" format union :" << format); + + if ( freq.size() >= 1 + && map.size() >= 1 + && format.size() >= 1) { + DRAIN_DEBUG(" find 1 compatibility :{format=" << format << ",frequency=" << freq << ",map=" << map << "}"); + drain::IOFormatInterface tmp(map[0], format[0], freq[0]); + if (_position > 0) { + m_listAlgo[_position-1]->setOutputFormat(tmp); } - if (iii == m_listAlgo.size()) { - freqIn.push_back(m_outputConfig.getFrequency()); - } else { - freqIn = m_listAlgo[iii]->getFrequencySupportedInput(); + if (_position setInputFormat(tmp); } - std::vector freq = getUnion(freqOut, freqIn); - DRAIN_VERBOSE(" freq out :" << freqOut); - DRAIN_VERBOSE(" freq in :" << freqIn); - DRAIN_DEBUG(" freq union :" << freq); + return; + } + // create mapping to transform: + drain::IOFormatInterface out; + drain::IOFormatInterface in; + if (freq.size() > 0) { + out.setFrequency(freq[0]); + in.setFrequency(freq[0]); + } else { + if (freqOut.size() == 0) { + if (freqIn.size() == 0) { + if (_position == 0) { + DRAIN_ERROR("IMPOSSIBLE CASE"); + } else { + out.setFrequency(m_listAlgo[_position-1]->getInputFormat().getFrequency()); + in.setFrequency(m_listAlgo[_position-1]->getInputFormat().getFrequency()); + } + } else { + out.setFrequency(freqIn[0]); + in.setFrequency(freqIn[0]); + } + } else { + if (freqIn.size() == 0) { + out.setFrequency(freqOut[0]); + in.setFrequency(freqOut[0]); + } else { + out.setFrequency(freqOut[0]); + in.setFrequency(freqIn[0]); + } + } + } + if (map.size() > 0) { + out.setMap(map[0]); + in.setMap(map[0]); + } else { + if (mapOut.size() == 0) { + if (mapIn.size() == 0) { + if (_position == 0) { + DRAIN_ERROR("IMPOSSIBLE CASE"); + } else { + out.setMap(m_listAlgo[_position-1]->getInputFormat().getMap()); + in.setMap(m_listAlgo[_position-1]->getInputFormat().getMap()); + } + } else { + out.setMap(mapIn[0]); + in.setMap(mapIn[0]); + } + } else { + if (mapIn.size() == 0) { + out.setMap(mapOut[0]); + in.setMap(mapOut[0]); + } else { + out.setMap(mapOut[0]); + in.setMap(mapIn[0]); + } + } + } + if (format.size() > 0) { + out.setFormat(format[0]); + in.setFormat(format[0]); + } else { + if (formatOut.size() == 0) { + if (formatIn.size() == 0) { + if (_position == 0) { + DRAIN_ERROR("IMPOSSIBLE CASE"); + } else { + out.setFormat(m_listAlgo[_position-1]->getInputFormat().getFormat()); + in.setFormat(m_listAlgo[_position-1]->getInputFormat().getFormat()); + } + } else { + out.setFormat(formatIn[0]); + in.setFormat(formatIn[0]); + } + } else { + if (formatIn.size() == 0) { + out.setFormat(formatOut[0]); + in.setFormat(formatOut[0]); + } else { + out.setFormat(formatOut[0]); + in.setFormat(formatIn[0]); + } + } + } + DRAIN_DEBUG(" update: out=" << out); + DRAIN_DEBUG(" in=" << in); + if (_position > 0) { + m_listAlgo[_position-1]->setOutputFormat(out); + } + if (_position < m_listAlgo.size()) { + m_listAlgo[_position]->setInputFormat(in); + } + // TODO : Add updater with an optimisation of CPU + if (out.getFrequency() != in.getFrequency()) { - // step 2 : Check map: - std::vector> mapOut; - std::vector> mapIn; - if (iii == 0) { - mapOut.push_back(m_inputConfig.getMap()); - } else { - mapOut = m_listAlgo[iii-1]->getMapSupportedOutput(); - } - if (iii == m_listAlgo.size()) { - mapIn.push_back(m_outputConfig.getMap()); - } else { - mapIn = m_listAlgo[iii]->getMapSupportedInput(); - } - std::vector> map = getUnion>(mapOut, mapIn); - DRAIN_VERBOSE(" map out :" << mapOut); - DRAIN_VERBOSE(" map in :" << mapIn); - DRAIN_DEBUG(" map union :" << map); - // step 3 : Check Format: - std::vector formatOut; - std::vector formatIn; - if (iii == 0) { - formatOut.push_back(m_inputConfig.getFormat()); - } else { - formatOut = m_listAlgo[iii-1]->getFormatSupportedOutput(); - } - if (iii == m_listAlgo.size()) { - formatIn.push_back(m_outputConfig.getFormat()); - } else { - formatIn = m_listAlgo[iii]->getFormatSupportedInput(); - } - std::vector format = getUnion(formatOut, formatIn); - DRAIN_VERBOSE(" format out :" << formatOut); - DRAIN_VERBOSE(" format in :" << formatIn); - DRAIN_DEBUG(" format union :" << format); - - if ( freq.size() >= 1 - && map.size() >= 1 - && format.size() >= 1) { - DRAIN_DEBUG(" find 1 compatibility :{format=" << format << ",frequency=" << freq << ",map=" << map << "}"); - drain::IOFormatInterface tmp(map[0], format[0], freq[0]); - if (iii > 0) { - m_listAlgo[iii-1]->setOutputFormat(tmp); - } - if (iii setInputFormat(tmp); - } - continue; - } - // create mapping to transform: - drain::IOFormatInterface out; - drain::IOFormatInterface in; - if (freq.size() > 0) { - out.setFrequency(freq[0]); - in.setFrequency(freq[0]); - } else { - if (freqOut.size() == 0) { - if (freqIn.size() == 0) { - if (iii == 0) { - DRAIN_ERROR("IMPOSSIBLE CASE"); - } else { - out.setFrequency(m_listAlgo[iii-1]->getInputFormat().getFrequency()); - in.setFrequency(m_listAlgo[iii-1]->getInputFormat().getFrequency()); - } - } else { - out.setFrequency(freqIn[0]); - in.setFrequency(freqIn[0]); - } - } else { - if (freqIn.size() == 0) { - out.setFrequency(freqOut[0]); - in.setFrequency(freqOut[0]); - } else { - out.setFrequency(freqOut[0]); - in.setFrequency(freqIn[0]); - } - } - } - if (map.size() > 0) { - out.setMap(map[0]); - in.setMap(map[0]); - } else { - if (mapOut.size() == 0) { - if (mapIn.size() == 0) { - if (iii == 0) { - DRAIN_ERROR("IMPOSSIBLE CASE"); - } else { - out.setMap(m_listAlgo[iii-1]->getInputFormat().getMap()); - in.setMap(m_listAlgo[iii-1]->getInputFormat().getMap()); - } - } else { - out.setMap(mapIn[0]); - in.setMap(mapIn[0]); - } - } else { - if (mapIn.size() == 0) { - out.setMap(mapOut[0]); - in.setMap(mapOut[0]); - } else { - out.setMap(mapOut[0]); - in.setMap(mapIn[0]); - } - } - } - if (format.size() > 0) { - out.setFormat(format[0]); - in.setFormat(format[0]); - } else { - if (formatOut.size() == 0) { - if (formatIn.size() == 0) { - if (iii == 0) { - DRAIN_ERROR("IMPOSSIBLE CASE"); - } else { - out.setFormat(m_listAlgo[iii-1]->getInputFormat().getFormat()); - in.setFormat(m_listAlgo[iii-1]->getInputFormat().getFormat()); - } - } else { - out.setFormat(formatIn[0]); - in.setFormat(formatIn[0]); - } - } else { - if (formatIn.size() == 0) { - out.setFormat(formatOut[0]); - in.setFormat(formatOut[0]); - } else { - out.setFormat(formatOut[0]); - in.setFormat(formatIn[0]); - } - } - } - DRAIN_DEBUG(" update: out=" << out); - DRAIN_DEBUG(" in=" << in); - if (iii > 0) { - m_listAlgo[iii-1]->setOutputFormat(out); - } - if (iii < m_listAlgo.size()) { - m_listAlgo[iii]->setInputFormat(in); - } - // TODO : Add updater with an optimisation of CPU - if (out.getFrequency() != in.getFrequency()) { - - // TODO : Do it better: special check for resampler : only support int16_t - if ( out.getFormat() != audio::format_int16 - /* && out.getFormat() != format_float */) { - // need add a format Updater - std::shared_ptr algo = drain::FormatUpdate::create(); - algo->setTemporary(); - algo->setInputFormat(out); - out.setFormat(audio::format_int16); - algo->setOutputFormat(out); - m_listAlgo.insert(m_listAlgo.begin()+iii, algo); - DRAIN_DEBUG("convert " << out.getFormat() << " -> " << in.getFormat()); - iii++; - } - // need add a resampler - std::shared_ptr algo = drain::Resampler::create(); - algo->setTemporary(); - algo->setInputFormat(out); - out.setFrequency(in.getFrequency()); - algo->setOutputFormat(out); - m_listAlgo.insert(m_listAlgo.begin()+iii, algo); - DRAIN_DEBUG("convert " << out.getFrequency() << " -> " << in.getFrequency()); - out.setFrequency(in.getFrequency()); - iii++; - } - if (out.getMap() != in.getMap()) { - // need add a channel Reorder - std::shared_ptr algo = drain::ChannelReorder::create(); - algo->setTemporary(); - algo->setInputFormat(out); - out.setMap(in.getMap()); - algo->setOutputFormat(out); - m_listAlgo.insert(m_listAlgo.begin()+iii, algo); - DRAIN_DEBUG("convert " << out.getMap() << " -> " << in.getMap()); - iii++; - } - if (out.getFormat() != in.getFormat()) { + // TODO : Do it better: special check for resampler : only support int16_t + if ( out.getFormat() != audio::format_int16 + /* && out.getFormat() != format_float */) { // need add a format Updater std::shared_ptr algo = drain::FormatUpdate::create(); algo->setTemporary(); algo->setInputFormat(out); - out.setFormat(in.getFormat()); + out.setFormat(audio::format_int16); algo->setOutputFormat(out); - m_listAlgo.insert(m_listAlgo.begin()+iii, algo); + m_listAlgo.insert(m_listAlgo.begin()+_position, algo); DRAIN_DEBUG("convert " << out.getFormat() << " -> " << in.getFormat()); - iii++; + _position++; } - - } else if ( ( iii > 0 - && m_listAlgo[iii-1]->getOutputFormat().getConfigured() == false - ) - || ( iii < m_listAlgo.size() - && m_listAlgo[iii]->getInputFormat().getConfigured() == false - ) - ) { - DRAIN_ERROR(" configuration error mode in " << iii-1 << " && " << iii ); + // need add a resampler + std::shared_ptr algo = drain::Resampler::create(); + algo->setTemporary(); + algo->setInputFormat(out); + out.setFrequency(in.getFrequency()); + algo->setOutputFormat(out); + m_listAlgo.insert(m_listAlgo.begin()+_position, algo); + DRAIN_DEBUG("convert " << out.getFrequency() << " -> " << in.getFrequency()); + out.setFrequency(in.getFrequency()); + _position++; } + if (out.getMap() != in.getMap()) { + // need add a channel Reorder + std::shared_ptr algo = drain::ChannelReorder::create(); + algo->setTemporary(); + algo->setInputFormat(out); + out.setMap(in.getMap()); + algo->setOutputFormat(out); + m_listAlgo.insert(m_listAlgo.begin()+_position, algo); + DRAIN_DEBUG("convert " << out.getMap() << " -> " << in.getMap()); + _position++; + } + if (out.getFormat() != in.getFormat()) { + // need add a format Updater + std::shared_ptr algo = drain::FormatUpdate::create(); + algo->setTemporary(); + algo->setInputFormat(out); + out.setFormat(in.getFormat()); + algo->setOutputFormat(out); + m_listAlgo.insert(m_listAlgo.begin()+_position, algo); + DRAIN_DEBUG("convert " << out.getFormat() << " -> " << in.getFormat()); + _position++; + } + + } else if ( ( _position > 0 + && m_listAlgo[_position-1]->getOutputFormat().getConfigured() == false + ) + || ( _position < m_listAlgo.size() + && m_listAlgo[_position]->getInputFormat().getConfigured() == false + ) + ) { + DRAIN_ERROR(" configuration error mode in " << _position-1 << " && " << _position ); + } +} + +void drain::Process::updateInterAlgo() { + if (m_isConfigured == true) { + // cahin is already configured + return ; + } + DRAIN_DEBUG("Display properties : nbAlgo : " << m_listAlgo.size()); + displayAlgo(); + DRAIN_DEBUG("********* configuration START *************"); + // configure first the endpoint ... + if (m_listAlgo.size() > 1) { + updateAlgo(m_listAlgo.size()); + } + for (size_t iii=0; iii<=m_listAlgo.size(); ++iii) { + updateAlgo(iii); } DRAIN_DEBUG("********* configuration will be done *************"); - DRAIN_DEBUG(" Input : " << m_inputConfig); - for (auto &it : m_listAlgo) { - DRAIN_DEBUG(" [" << it->getType() << "] '" << it->getName() << "'"); - if (it->getInputFormat().getConfigured() == true) { - DRAIN_DEBUG(" Input : " << it->getInputFormat()); - } else { - DRAIN_ERROR(" Input : Not configured"); - } - if (it->getOutputFormat().getConfigured() == true) { - DRAIN_DEBUG(" Output: " << it->getOutputFormat()); - } else { - DRAIN_ERROR(" Output : Not configured"); - } - } - DRAIN_DEBUG(" Output : " << m_outputConfig); + displayAlgo(); m_isConfigured = true; //exit(-1); } diff --git a/drain/Process.h b/drain/Process.h index 7987c40..ee055a6 100644 --- a/drain/Process.h +++ b/drain/Process.h @@ -157,6 +157,9 @@ namespace drain{ public: void updateInterAlgo(); void removeAlgoDynamic(); + private: + void displayAlgo(); + void updateAlgo(size_t _position); }; }; diff --git a/drain/Resampler.cpp b/drain/Resampler.cpp index ce6cbde..944f477 100644 --- a/drain/Resampler.cpp +++ b/drain/Resampler.cpp @@ -83,12 +83,30 @@ void drain::Resampler::configurationChange() { #endif } +namespace std { + static std::ostream& operator <<(std::ostream& _os, const std::chrono::system_clock::time_point& _obj) { + std::chrono::nanoseconds ns = std::chrono::duration_cast(_obj.time_since_epoch()); + int64_t totalSecond = ns.count()/1000000000; + int64_t millisecond = (ns.count()%1000000000)/1000000; + int64_t microsecond = (ns.count()%1000000)/1000; + int64_t nanosecond = ns.count()%1000; + //_os << totalSecond << "s " << millisecond << "ms " << microsecond << "µs " << nanosecond << "ns"; + + int32_t second = totalSecond % 60; + int32_t minute = (totalSecond/60)%60; + int32_t hour = (totalSecond/3600)%24; + int32_t day = (totalSecond/(24*3600))%365; + int32_t year = totalSecond/(24*3600*365); + _os << year << "y " << day << "d " << hour << "h" << minute << ":"<< second << "s " << millisecond << "ms " << microsecond << "µs " << nanosecond << "ns"; + return _os; + } +} bool drain::Resampler::process(std::chrono::system_clock::time_point& _time, - void* _input, - size_t _inputNbChunk, - void*& _output, - size_t& _outputNbChunk) { + void* _input, + size_t _inputNbChunk, + void*& _output, + size_t& _outputNbChunk) { drain::AutoLogInOut tmpLog("Resampler"); _outputNbChunk = 2048; // chack if we need to process: @@ -104,6 +122,12 @@ bool drain::Resampler::process(std::chrono::system_clock::time_point& _time, DRAIN_ERROR("null pointer input ... "); return false; } + // Update Output time with the previous delta of the buffer + DRAIN_VERBOSE("Resampler correct timestamp : " << _time << " ==> " << (_time - m_residualTimeInResampler)); + _time -= m_residualTimeInResampler; + + std::chrono::nanoseconds inTime((int64_t(_inputNbChunk)*int64_t(1000000000)) / int64_t(m_input.getFrequency())); + m_residualTimeInResampler += inTime; #ifdef HAVE_SPEEX_DSP_RESAMPLE float nbInputTime = float(_inputNbChunk)/m_input.getFrequency(); float nbOutputSample = nbInputTime*m_output.getFrequency(); @@ -141,6 +165,14 @@ bool drain::Resampler::process(std::chrono::system_clock::time_point& _time, } _outputNbChunk = nbChunkOutput; DRAIN_VERBOSE(" process chunk=" << nbChunkInput << " out=" << nbChunkOutput); + std::chrono::nanoseconds outTime((int64_t(_outputNbChunk)*int64_t(1000000000)) / int64_t(m_output.getFrequency())); + // correct time : + m_residualTimeInResampler -= outTime; + /* + if (m_residualTimeInResampler.count() < 0) { + DRAIN_TODO("manage this case ... residual time in resampler : " << m_residualTimeInResampler.count() << "ns"); + } + */ return true; #else _output = _input; diff --git a/drain/Resampler.h b/drain/Resampler.h index 37a8f6d..a297c1d 100644 --- a/drain/Resampler.h +++ b/drain/Resampler.h @@ -14,6 +14,8 @@ #include namespace drain { + // TODO: Manage change timestamp when pull mode + // TODO: drain ... class Resampler : public Algo { private: #ifdef HAVE_SPEEX_DSP_RESAMPLE @@ -41,6 +43,8 @@ namespace drain { size_t _inputNbChunk, void*& _output, size_t& _outputNbChunk); + private: + std::chrono::nanoseconds m_residualTimeInResampler; //!< the time of data locked in the resampler ... }; };