[DEV] change callback name and update the timestamp of the resampler

This commit is contained in:
Edouard DUPIN 2015-02-17 21:08:15 +01:00
parent c667f6c327
commit 01d36bd995
9 changed files with 333 additions and 310 deletions

View File

@ -120,6 +120,7 @@ namespace drain{
* @param[in] _output number of chunk estimate in output * @param[in] _output number of chunk estimate in output
* @return number of sample needed to have nearly the good number of sample * @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); virtual size_t needInputData(size_t _output);
protected: // note when nothing ==> support all type protected: // note when nothing ==> support all type
std::vector<audio::format> m_supportedFormat; std::vector<audio::format> m_supportedFormat;

View File

@ -16,24 +16,24 @@ drain::EndPointCallback::EndPointCallback() :
} }
void drain::EndPointCallback::init(needDataFunction _callback) { void drain::EndPointCallback::init(playbackFunction _callback) {
m_outputFunction = _callback; m_outputFunction = _callback;
drain::EndPoint::init(); drain::EndPoint::init();
m_type = "EndPointCallback"; m_type = "EndPointCallback";
} }
void drain::EndPointCallback::init(haveNewDataFunction _callback) { void drain::EndPointCallback::init(recordFunction _callback) {
m_inputFunction = _callback; m_inputFunction = _callback;
drain::EndPoint::init(); drain::EndPoint::init();
m_type = "EndPointCallback"; m_type = "EndPointCallback";
} }
std::shared_ptr<drain::EndPointCallback> drain::EndPointCallback::create(needDataFunction _callback) { std::shared_ptr<drain::EndPointCallback> drain::EndPointCallback::create(playbackFunction _callback) {
std::shared_ptr<drain::EndPointCallback> tmp(new drain::EndPointCallback()); std::shared_ptr<drain::EndPointCallback> tmp(new drain::EndPointCallback());
tmp->init(_callback); tmp->init(_callback);
return tmp; return tmp;
} }
std::shared_ptr<drain::EndPointCallback> drain::EndPointCallback::create(haveNewDataFunction _callback) { std::shared_ptr<drain::EndPointCallback> drain::EndPointCallback::create(recordFunction _callback) {
std::shared_ptr<drain::EndPointCallback> tmp(new drain::EndPointCallback()); std::shared_ptr<drain::EndPointCallback> tmp(new drain::EndPointCallback());
tmp->init(_callback); tmp->init(_callback);
return tmp; return tmp;
@ -47,21 +47,33 @@ void drain::EndPointCallback::configurationChange() {
bool drain::EndPointCallback::process(std::chrono::system_clock::time_point& _time, bool drain::EndPointCallback::process(std::chrono::system_clock::time_point& _time,
void* _input, // uneeded void* _input,
size_t _inputNbChunk, // requested number of sample ... size_t _inputNbChunk,
void*& _output, void*& _output,
size_t& _outputNbChunk){ size_t& _outputNbChunk){
drain::AutoLogInOut tmpLog("EndPointCallback"); 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) { if (m_outputFunction != nullptr) {
// update buffer size ... // update buffer size ...
m_outputData.resize(_inputNbChunk*m_output.getMap().size()*m_formatSize); m_outputData.resize(_inputNbChunk*m_output.getMap().size()*m_formatSize);
// call user // call user
DRAIN_VERBOSE("call user get " << _inputNbChunk << "*" << m_output.getMap().size() << " map=" << m_output.getMap() << " datasize=" << int32_t(m_formatSize)); 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, _inputNbChunk,
m_output.getMap(), m_output.getFormat(),
&m_outputData[0], m_output.getFrequency(),
m_output.getFormat()); m_output.getMap());
if (m_outputData.size() != _inputNbChunk*m_output.getMap().size()*m_formatSize) { 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()); DRAIN_ERROR(" can not get enough data from user ... " << m_outputData.size() << " != " << _inputNbChunk*m_output.getMap().size());
return false; return false;
@ -70,16 +82,6 @@ bool drain::EndPointCallback::process(std::chrono::system_clock::time_point& _ti
_outputNbChunk = _inputNbChunk; _outputNbChunk = _inputNbChunk;
return true; 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; return false;
} }

View File

@ -12,30 +12,32 @@
namespace drain { namespace drain {
typedef std::function<void (const std::chrono::system_clock::time_point& _playTime, typedef std::function<void (void* _data,
const std::chrono::system_clock::time_point& _playTime,
size_t _nbChunk, size_t _nbChunk,
const std::vector<audio::channel>& _map, enum audio::format _format,
void* _data, uint32_t _frequency,
enum audio::format _type)> needDataFunction; const std::vector<audio::channel>& _map)> playbackFunction;
typedef std::function<void (const std::chrono::system_clock::time_point& _readTime, typedef std::function<void (const void* _data,
const std::chrono::system_clock::time_point& _readTime,
size_t _nbChunk, size_t _nbChunk,
const std::vector<audio::channel>& _map, enum audio::format _format,
const void* _data, uint32_t _frequency,
enum audio::format _type)> haveNewDataFunction; const std::vector<audio::channel>& _map)> recordFunction;
class EndPointCallback : public EndPoint { class EndPointCallback : public EndPoint {
private: private:
needDataFunction m_outputFunction; playbackFunction m_outputFunction;
haveNewDataFunction m_inputFunction; recordFunction m_inputFunction;
protected: protected:
/** /**
* @brief Constructor * @brief Constructor
*/ */
EndPointCallback(); EndPointCallback();
void init(needDataFunction _callback); void init(playbackFunction _callback);
void init(haveNewDataFunction _callback); void init(recordFunction _callback);
public: public:
static std::shared_ptr<EndPointCallback> create(needDataFunction _callback); static std::shared_ptr<EndPointCallback> create(playbackFunction _callback);
static std::shared_ptr<EndPointCallback> create(haveNewDataFunction _callback); static std::shared_ptr<EndPointCallback> create(recordFunction _callback);
/** /**
* @brief Destructor * @brief Destructor
*/ */

View File

@ -33,15 +33,15 @@ void drain::EndPointWrite::configurationChange() {
bool drain::EndPointWrite::process(std::chrono::system_clock::time_point& _time, bool drain::EndPointWrite::process(std::chrono::system_clock::time_point& _time,
void* _input, void* _input,
size_t _inputNbChunk, size_t _inputNbChunk,
void*& _output, void*& _output,
size_t& _outputNbChunk){ size_t& _outputNbChunk){
drain::AutoLogInOut tmpLog("EndPointWrite"); drain::AutoLogInOut tmpLog("EndPointWrite");
//DRAIN_INFO(" nb Sample in buffer : " << m_tmpData.size()); //DRAIN_INFO(" nb Sample in buffer : " << m_tmpData.size());
if (m_function != nullptr) { if (m_function != nullptr) {
if (m_tmpData.size() <= 20000) { 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: // resize output buffer:

View File

@ -12,14 +12,15 @@
#include <functional> #include <functional>
namespace drain{ namespace drain{
typedef std::function<void (const std::chrono::system_clock::time_point& _playTime, typedef std::function<void (const std::chrono::system_clock::time_point& _time,
const size_t& _nbChunk, size_t _nbChunk,
const std::vector<audio::channel>& _map, enum audio::format _format,
enum audio::format _type)> needDataFunctionWrite; uint32_t _frequency,
const std::vector<audio::channel>& _map)> playbackFunctionWrite;
class EndPointWrite : public EndPoint { class EndPointWrite : public EndPoint {
private: private:
std::vector<int8_t> m_tmpData; std::vector<int8_t> m_tmpData;
needDataFunctionWrite m_function; playbackFunctionWrite m_function;
std::mutex m_mutex; std::mutex m_mutex;
protected: protected:
/** /**
@ -40,7 +41,7 @@ namespace drain{
void*& _output, void*& _output,
size_t& _outputNbChunk); size_t& _outputNbChunk);
virtual void write(const void* _value, size_t _nbChunk); virtual void write(const void* _value, size_t _nbChunk);
virtual void setCallback(needDataFunctionWrite _function) { virtual void setCallback(playbackFunctionWrite _function) {
m_function = _function; m_function = _function;
} }
}; };

View File

@ -143,12 +143,8 @@ template<typename T> std::vector<T> getUnion(const std::vector<T>& _out, const s
return out; return out;
} }
void drain::Process::updateInterAlgo() {
if (m_isConfigured == true) { void drain::Process::displayAlgo() {
// cahin is already configured
return ;
}
DRAIN_DEBUG("Display properties : nbAlgo : " << m_listAlgo.size());
DRAIN_DEBUG(" Input : " << m_inputConfig); DRAIN_DEBUG(" Input : " << m_inputConfig);
for (auto &it : m_listAlgo) { for (auto &it : m_listAlgo) {
DRAIN_DEBUG(" [" << it->getType() << "] '" << it->getName() << "'"); DRAIN_DEBUG(" [" << it->getType() << "] '" << it->getName() << "'");
@ -170,272 +166,254 @@ void drain::Process::updateInterAlgo() {
} }
} }
DRAIN_DEBUG(" Output : " << m_outputConfig); 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<float> freqOut;
std::vector<float> freqIn;
if (iii == 0) {
freqOut.push_back(m_inputConfig.getFrequency());
} else {
freqOut = m_listAlgo[iii-1]->getFrequencySupportedOutput();
}
if (iii == m_listAlgo.size()) {
freqIn.push_back(m_outputConfig.getFrequency());
} else {
freqIn = m_listAlgo[iii]->getFrequencySupportedInput();
}
std::vector<float> freq = getUnion<float>(freqOut, freqIn);
DRAIN_VERBOSE(" freq out :" << freqOut);
DRAIN_VERBOSE(" freq in :" << freqIn);
DRAIN_DEBUG(" freq union :" << freq);
// step 2 : Check map: void drain::Process::updateAlgo(size_t _position) {
std::vector<std::vector<audio::channel>> mapOut; DRAIN_VERBOSE(" id = " << _position);
std::vector<std::vector<audio::channel>> mapIn; if ( ( _position == 0
if (iii == 0) { || ( _position > 0
mapOut.push_back(m_inputConfig.getMap()); && m_listAlgo[_position-1]->getOutputFormat().getConfigured() == false
} else { )
mapOut = m_listAlgo[iii-1]->getMapSupportedOutput(); )
} && ( _position == m_listAlgo.size()
if (iii == m_listAlgo.size()) { || ( _position < m_listAlgo.size()
mapIn.push_back(m_outputConfig.getMap()); && m_listAlgo[_position]->getInputFormat().getConfigured() == false
} else { )
mapIn = m_listAlgo[iii]->getMapSupportedInput(); )
} ) {
std::vector<std::vector<audio::channel>> map = getUnion<std::vector<audio::channel>>(mapOut, mapIn); // step 1 : check frequency:
DRAIN_VERBOSE(" map out :" << mapOut); std::vector<float> freqOut;
DRAIN_VERBOSE(" map in :" << mapIn); std::vector<float> freqIn;
DRAIN_DEBUG(" map union :" << map); if (_position == 0) {
// step 3 : Check Format: freqOut.push_back(m_inputConfig.getFrequency());
std::vector<audio::format> formatOut; } else {
std::vector<audio::format> formatIn; freqOut = m_listAlgo[_position-1]->getFrequencySupportedOutput();
if (iii == 0) { }
formatOut.push_back(m_inputConfig.getFormat()); if (_position == m_listAlgo.size()) {
} else { freqIn.push_back(m_outputConfig.getFrequency());
formatOut = m_listAlgo[iii-1]->getFormatSupportedOutput(); } else {
} freqIn = m_listAlgo[_position]->getFrequencySupportedInput();
if (iii == m_listAlgo.size()) { }
formatIn.push_back(m_outputConfig.getFormat()); std::vector<float> freq = getUnion<float>(freqOut, freqIn);
} else { DRAIN_VERBOSE(" freq out :" << freqOut);
formatIn = m_listAlgo[iii]->getFormatSupportedInput(); DRAIN_VERBOSE(" freq in :" << freqIn);
} DRAIN_DEBUG(" freq union :" << freq);
std::vector<audio::format> format = getUnion<audio::format>(formatOut, formatIn);
DRAIN_VERBOSE(" format out :" << formatOut);
DRAIN_VERBOSE(" format in :" << formatIn);
DRAIN_DEBUG(" format union :" << format);
if ( freq.size() >= 1 // step 2 : Check map:
&& map.size() >= 1 std::vector<std::vector<audio::channel>> mapOut;
&& format.size() >= 1) { std::vector<std::vector<audio::channel>> mapIn;
DRAIN_DEBUG(" find 1 compatibility :{format=" << format << ",frequency=" << freq << ",map=" << map << "}"); if (_position == 0) {
drain::IOFormatInterface tmp(map[0], format[0], freq[0]); mapOut.push_back(m_inputConfig.getMap());
if (iii > 0) { } else {
m_listAlgo[iii-1]->setOutputFormat(tmp); mapOut = m_listAlgo[_position-1]->getMapSupportedOutput();
} }
if (iii <m_listAlgo.size()) { if (_position == m_listAlgo.size()) {
m_listAlgo[iii]->setInputFormat(tmp); mapIn.push_back(m_outputConfig.getMap());
} } else {
continue; mapIn = m_listAlgo[_position]->getMapSupportedInput();
}
std::vector<std::vector<audio::channel>> map = getUnion<std::vector<audio::channel>>(mapOut, mapIn);
DRAIN_VERBOSE(" map out :" << mapOut);
DRAIN_VERBOSE(" map in :" << mapIn);
DRAIN_DEBUG(" map union :" << map);
// step 3 : Check Format:
std::vector<audio::format> formatOut;
std::vector<audio::format> 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<audio::format> format = getUnion<audio::format>(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);
} }
// create mapping to transform: if (_position <m_listAlgo.size()) {
drain::IOFormatInterface out; m_listAlgo[_position]->setInputFormat(tmp);
drain::IOFormatInterface in; }
if (freq.size() > 0) { return;
out.setFrequency(freq[0]); }
in.setFrequency(freq[0]); // create mapping to transform:
} else { drain::IOFormatInterface out;
if (freqOut.size() == 0) { drain::IOFormatInterface in;
if (freqIn.size() == 0) { if (freq.size() > 0) {
if (iii == 0) { out.setFrequency(freq[0]);
DRAIN_ERROR("IMPOSSIBLE CASE"); in.setFrequency(freq[0]);
} else { } else {
out.setFrequency(m_listAlgo[iii-1]->getInputFormat().getFrequency()); if (freqOut.size() == 0) {
in.setFrequency(m_listAlgo[iii-1]->getInputFormat().getFrequency()); if (freqIn.size() == 0) {
} if (_position == 0) {
DRAIN_ERROR("IMPOSSIBLE CASE");
} else { } else {
out.setFrequency(freqIn[0]); out.setFrequency(m_listAlgo[_position-1]->getInputFormat().getFrequency());
in.setFrequency(freqIn[0]); in.setFrequency(m_listAlgo[_position-1]->getInputFormat().getFrequency());
} }
} else { } else {
if (freqIn.size() == 0) { out.setFrequency(freqIn[0]);
out.setFrequency(freqOut[0]); in.setFrequency(freqIn[0]);
in.setFrequency(freqOut[0]); }
} else { } else {
out.setFrequency(freqOut[0]); if (freqIn.size() == 0) {
in.setFrequency(freqIn[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]); if (map.size() > 0) {
in.setMap(map[0]); out.setMap(map[0]);
} else { in.setMap(map[0]);
if (mapOut.size() == 0) { } else {
if (mapIn.size() == 0) { if (mapOut.size() == 0) {
if (iii == 0) { if (mapIn.size() == 0) {
DRAIN_ERROR("IMPOSSIBLE CASE"); if (_position == 0) {
} else { DRAIN_ERROR("IMPOSSIBLE CASE");
out.setMap(m_listAlgo[iii-1]->getInputFormat().getMap());
in.setMap(m_listAlgo[iii-1]->getInputFormat().getMap());
}
} else { } else {
out.setMap(mapIn[0]); out.setMap(m_listAlgo[_position-1]->getInputFormat().getMap());
in.setMap(mapIn[0]); in.setMap(m_listAlgo[_position-1]->getInputFormat().getMap());
} }
} else { } else {
if (mapIn.size() == 0) { out.setMap(mapIn[0]);
out.setMap(mapOut[0]); in.setMap(mapIn[0]);
in.setMap(mapOut[0]); }
} else { } else {
out.setMap(mapOut[0]); if (mapIn.size() == 0) {
in.setMap(mapIn[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]); if (format.size() > 0) {
in.setFormat(format[0]); out.setFormat(format[0]);
} else { in.setFormat(format[0]);
if (formatOut.size() == 0) { } else {
if (formatIn.size() == 0) { if (formatOut.size() == 0) {
if (iii == 0) { if (formatIn.size() == 0) {
DRAIN_ERROR("IMPOSSIBLE CASE"); if (_position == 0) {
} else { DRAIN_ERROR("IMPOSSIBLE CASE");
out.setFormat(m_listAlgo[iii-1]->getInputFormat().getFormat());
in.setFormat(m_listAlgo[iii-1]->getInputFormat().getFormat());
}
} else { } else {
out.setFormat(formatIn[0]); out.setFormat(m_listAlgo[_position-1]->getInputFormat().getFormat());
in.setFormat(formatIn[0]); in.setFormat(m_listAlgo[_position-1]->getInputFormat().getFormat());
} }
} else { } else {
if (formatIn.size() == 0) { out.setFormat(formatIn[0]);
out.setFormat(formatOut[0]); in.setFormat(formatIn[0]);
in.setFormat(formatOut[0]); }
} else { } else {
out.setFormat(formatOut[0]); if (formatIn.size() == 0) {
in.setFormat(formatIn[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); DRAIN_DEBUG(" update: out=" << out);
if (iii > 0) { DRAIN_DEBUG(" in=" << in);
m_listAlgo[iii-1]->setOutputFormat(out); if (_position > 0) {
} m_listAlgo[_position-1]->setOutputFormat(out);
if (iii < m_listAlgo.size()) { }
m_listAlgo[iii]->setInputFormat(in); if (_position < m_listAlgo.size()) {
} m_listAlgo[_position]->setInputFormat(in);
// TODO : Add updater with an optimisation of CPU }
if (out.getFrequency() != in.getFrequency()) { // 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 // TODO : Do it better: special check for resampler : only support int16_t
if ( out.getFormat() != audio::format_int16 if ( out.getFormat() != audio::format_int16
/* && out.getFormat() != format_float */) { /* && out.getFormat() != format_float */) {
// need add a format Updater
std::shared_ptr<drain::FormatUpdate> 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<drain::Resampler> 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<drain::ChannelReorder> 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()) {
// need add a format Updater // need add a format Updater
std::shared_ptr<drain::FormatUpdate> algo = drain::FormatUpdate::create(); std::shared_ptr<drain::FormatUpdate> algo = drain::FormatUpdate::create();
algo->setTemporary(); algo->setTemporary();
algo->setInputFormat(out); algo->setInputFormat(out);
out.setFormat(in.getFormat()); out.setFormat(audio::format_int16);
algo->setOutputFormat(out); 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()); DRAIN_DEBUG("convert " << out.getFormat() << " -> " << in.getFormat());
iii++; _position++;
} }
// need add a resampler
} else if ( ( iii > 0 std::shared_ptr<drain::Resampler> algo = drain::Resampler::create();
&& m_listAlgo[iii-1]->getOutputFormat().getConfigured() == false algo->setTemporary();
) algo->setInputFormat(out);
|| ( iii < m_listAlgo.size() out.setFrequency(in.getFrequency());
&& m_listAlgo[iii]->getInputFormat().getConfigured() == false algo->setOutputFormat(out);
) m_listAlgo.insert(m_listAlgo.begin()+_position, algo);
) { DRAIN_DEBUG("convert " << out.getFrequency() << " -> " << in.getFrequency());
DRAIN_ERROR(" configuration error mode in " << iii-1 << " && " << iii ); out.setFrequency(in.getFrequency());
_position++;
} }
if (out.getMap() != in.getMap()) {
// need add a channel Reorder
std::shared_ptr<drain::ChannelReorder> 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<drain::FormatUpdate> 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("********* configuration will be done *************");
DRAIN_DEBUG(" Input : " << m_inputConfig); displayAlgo();
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);
m_isConfigured = true; m_isConfigured = true;
//exit(-1); //exit(-1);
} }

View File

@ -157,6 +157,9 @@ namespace drain{
public: public:
void updateInterAlgo(); void updateInterAlgo();
void removeAlgoDynamic(); void removeAlgoDynamic();
private:
void displayAlgo();
void updateAlgo(size_t _position);
}; };
}; };

View File

@ -83,12 +83,30 @@ void drain::Resampler::configurationChange() {
#endif #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<std::chrono::nanoseconds>(_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, bool drain::Resampler::process(std::chrono::system_clock::time_point& _time,
void* _input, void* _input,
size_t _inputNbChunk, size_t _inputNbChunk,
void*& _output, void*& _output,
size_t& _outputNbChunk) { size_t& _outputNbChunk) {
drain::AutoLogInOut tmpLog("Resampler"); drain::AutoLogInOut tmpLog("Resampler");
_outputNbChunk = 2048; _outputNbChunk = 2048;
// chack if we need to process: // 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 ... "); DRAIN_ERROR("null pointer input ... ");
return false; 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 #ifdef HAVE_SPEEX_DSP_RESAMPLE
float nbInputTime = float(_inputNbChunk)/m_input.getFrequency(); float nbInputTime = float(_inputNbChunk)/m_input.getFrequency();
float nbOutputSample = nbInputTime*m_output.getFrequency(); float nbOutputSample = nbInputTime*m_output.getFrequency();
@ -141,6 +165,14 @@ bool drain::Resampler::process(std::chrono::system_clock::time_point& _time,
} }
_outputNbChunk = nbChunkOutput; _outputNbChunk = nbChunkOutput;
DRAIN_VERBOSE(" process chunk=" << nbChunkInput << " out=" << 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; return true;
#else #else
_output = _input; _output = _input;

View File

@ -14,6 +14,8 @@
#include <memory> #include <memory>
namespace drain { namespace drain {
// TODO: Manage change timestamp when pull mode
// TODO: drain ...
class Resampler : public Algo { class Resampler : public Algo {
private: private:
#ifdef HAVE_SPEEX_DSP_RESAMPLE #ifdef HAVE_SPEEX_DSP_RESAMPLE
@ -41,6 +43,8 @@ namespace drain {
size_t _inputNbChunk, size_t _inputNbChunk,
void*& _output, void*& _output,
size_t& _outputNbChunk); size_t& _outputNbChunk);
private:
std::chrono::nanoseconds m_residualTimeInResampler; //!< the time of data locked in the resampler ...
}; };
}; };