[DEV] change callback name and update the timestamp of the resampler
This commit is contained in:
parent
c667f6c327
commit
01d36bd995
@ -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<audio::format> m_supportedFormat;
|
||||
|
@ -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> drain::EndPointCallback::create(needDataFunction _callback) {
|
||||
std::shared_ptr<drain::EndPointCallback> drain::EndPointCallback::create(playbackFunction _callback) {
|
||||
std::shared_ptr<drain::EndPointCallback> tmp(new drain::EndPointCallback());
|
||||
tmp->init(_callback);
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -12,30 +12,32 @@
|
||||
|
||||
|
||||
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,
|
||||
const std::vector<audio::channel>& _map,
|
||||
void* _data,
|
||||
enum audio::format _type)> needDataFunction;
|
||||
typedef std::function<void (const std::chrono::system_clock::time_point& _readTime,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map)> playbackFunction;
|
||||
typedef std::function<void (const void* _data,
|
||||
const std::chrono::system_clock::time_point& _readTime,
|
||||
size_t _nbChunk,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const void* _data,
|
||||
enum audio::format _type)> haveNewDataFunction;
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _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<EndPointCallback> create(needDataFunction _callback);
|
||||
static std::shared_ptr<EndPointCallback> create(haveNewDataFunction _callback);
|
||||
static std::shared_ptr<EndPointCallback> create(playbackFunction _callback);
|
||||
static std::shared_ptr<EndPointCallback> create(recordFunction _callback);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
|
@ -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:
|
||||
|
@ -12,14 +12,15 @@
|
||||
#include <functional>
|
||||
|
||||
namespace drain{
|
||||
typedef std::function<void (const std::chrono::system_clock::time_point& _playTime,
|
||||
const size_t& _nbChunk,
|
||||
const std::vector<audio::channel>& _map,
|
||||
enum audio::format _type)> needDataFunctionWrite;
|
||||
typedef std::function<void (const std::chrono::system_clock::time_point& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map)> playbackFunctionWrite;
|
||||
class EndPointWrite : public EndPoint {
|
||||
private:
|
||||
std::vector<int8_t> 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;
|
||||
}
|
||||
};
|
||||
|
@ -143,12 +143,8 @@ template<typename T> std::vector<T> getUnion(const std::vector<T>& _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<float> freqOut;
|
||||
std::vector<float> 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<float> freqOut;
|
||||
std::vector<float> 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<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:
|
||||
std::vector<std::vector<audio::channel>> mapOut;
|
||||
std::vector<std::vector<audio::channel>> 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<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);
|
||||
}
|
||||
if (iii == m_listAlgo.size()) {
|
||||
freqIn.push_back(m_outputConfig.getFrequency());
|
||||
} else {
|
||||
freqIn = m_listAlgo[iii]->getFrequencySupportedInput();
|
||||
if (_position <m_listAlgo.size()) {
|
||||
m_listAlgo[_position]->setInputFormat(tmp);
|
||||
}
|
||||
std::vector<float> freq = getUnion<float>(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<std::vector<audio::channel>> mapOut;
|
||||
std::vector<std::vector<audio::channel>> 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<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 (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<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 (iii > 0) {
|
||||
m_listAlgo[iii-1]->setOutputFormat(tmp);
|
||||
}
|
||||
if (iii <m_listAlgo.size()) {
|
||||
m_listAlgo[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<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()) {
|
||||
// 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<drain::FormatUpdate> 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<drain::Resampler> 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<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(" 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);
|
||||
}
|
||||
|
@ -157,6 +157,9 @@ namespace drain{
|
||||
public:
|
||||
void updateInterAlgo();
|
||||
void removeAlgoDynamic();
|
||||
private:
|
||||
void displayAlgo();
|
||||
void updateAlgo(size_t _position);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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<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,
|
||||
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;
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <memory>
|
||||
|
||||
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 ...
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user