[DEV] Correct synchonizer
This commit is contained in:
parent
4832570448
commit
d0bcaed9db
@ -239,10 +239,11 @@ void river::CircularBuffer::setReadPosition(const std::chrono::system_clock::tim
|
|||||||
size_t usedSizeBeforeEnd = getUsedSizeBeforEnd();
|
size_t usedSizeBeforeEnd = getUsedSizeBeforEnd();
|
||||||
if (0 < m_size) {
|
if (0 < m_size) {
|
||||||
// check the time of the read :
|
// check the time of the read :
|
||||||
std::chrono::nanoseconds deltaTime = m_timeRead - _time;
|
std::chrono::nanoseconds deltaTime = _time - m_timeRead;
|
||||||
size_t nbSampleToRemove = m_frequency*-deltaTime.count()/100000000;
|
size_t nbSampleToRemove = m_frequency*deltaTime.count()/1000000000;
|
||||||
nbSampleToRemove = std::min(nbSampleToRemove, m_size);
|
nbSampleToRemove = std::min(nbSampleToRemove, m_size);
|
||||||
RIVER_WARNING("Remove sample in the buffer " << nbSampleToRemove << " / " << m_size);
|
RIVER_WARNING("Remove sample in the buffer " << nbSampleToRemove << " / " << m_size);
|
||||||
|
std::chrono::nanoseconds updateTime((nbSampleToRemove*1000000000)/int64_t(m_frequency));
|
||||||
if (usedSizeBeforeEnd >= nbSampleToRemove) {
|
if (usedSizeBeforeEnd >= nbSampleToRemove) {
|
||||||
usedSizeBeforeEnd -= nbSampleToRemove;
|
usedSizeBeforeEnd -= nbSampleToRemove;
|
||||||
m_size -= nbSampleToRemove;
|
m_size -= nbSampleToRemove;
|
||||||
@ -252,7 +253,8 @@ void river::CircularBuffer::setReadPosition(const std::chrono::system_clock::tim
|
|||||||
m_size -= nbSampleToRemove;
|
m_size -= nbSampleToRemove;
|
||||||
m_read = &m_data[0] + nbSampleToRemove*m_sizeChunk;
|
m_read = &m_data[0] + nbSampleToRemove*m_sizeChunk;
|
||||||
}
|
}
|
||||||
m_timeRead += deltaTime;
|
m_timeRead += updateTime;
|
||||||
|
//m_timeRead += deltaTime;
|
||||||
} else {
|
} else {
|
||||||
m_timeRead = std::chrono::system_clock::time_point();
|
m_timeRead = std::chrono::system_clock::time_point();
|
||||||
}
|
}
|
||||||
|
@ -153,3 +153,13 @@ std::shared_ptr<river::Interface> river::Manager::createInput(float _freq,
|
|||||||
m_listOpenInterface.push_back(interface);
|
m_listOpenInterface.push_back(interface);
|
||||||
return interface;
|
return interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void river::Manager::generateDotAll(const std::string& _filename) {
|
||||||
|
// get global hardware interface:
|
||||||
|
std::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
|
||||||
|
if (manager == nullptr) {
|
||||||
|
RIVER_ERROR("Can not get the harware manager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
manager->generateDot(_filename);
|
||||||
|
}
|
@ -99,6 +99,11 @@ namespace river {
|
|||||||
audio::format _format,
|
audio::format _format,
|
||||||
const std::string& _streamName = "",
|
const std::string& _streamName = "",
|
||||||
const std::string& _name = "");
|
const std::string& _name = "");
|
||||||
|
/**
|
||||||
|
* @brief Generate the dot file corresponding at all the actif nodes.
|
||||||
|
* @param[in] _filename Name of the file to write data.
|
||||||
|
*/
|
||||||
|
virtual void generateDotAll(const std::string& _filename);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
#include "NodeAEC.h"
|
#include "NodeAEC.h"
|
||||||
#include "NodeAirTAudio.h"
|
#include "NodeAirTAudio.h"
|
||||||
|
#include <etk/os/FSNode.h>
|
||||||
|
|
||||||
#undef __class__
|
#undef __class__
|
||||||
#define __class__ "io::Manager"
|
#define __class__ "io::Manager"
|
||||||
@ -142,3 +143,24 @@ float river::io::Manager::getVolume(const std::string& _volumeName) {
|
|||||||
std::pair<float,float> river::io::Manager::getVolumeRange(const std::string& _volumeName) const {
|
std::pair<float,float> river::io::Manager::getVolumeRange(const std::string& _volumeName) const {
|
||||||
return std::make_pair<float,float>(-300, 300);
|
return std::make_pair<float,float>(-300, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void river::io::Manager::generateDot(const std::string& _filename) {
|
||||||
|
etk::FSNode node(_filename);
|
||||||
|
RIVER_INFO("Generate the DOT files: " << node);
|
||||||
|
if (node.fileOpenWrite() == false) {
|
||||||
|
RIVER_ERROR("Can not Write the dot file (fail to open) : " << node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node << "digraph G {" << "\n";
|
||||||
|
int32_t id = 0;
|
||||||
|
for (auto &it2 : m_list) {
|
||||||
|
std::shared_ptr<river::io::Node> val = it2.lock();
|
||||||
|
if (val != nullptr) {
|
||||||
|
val->generateDot(node);
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node << "}" << "\n";
|
||||||
|
node.fileClose();
|
||||||
|
RIVER_INFO("Generate the DOT files: " << node << " (DONE)");
|
||||||
|
}
|
||||||
|
@ -68,6 +68,11 @@ namespace river {
|
|||||||
* @example ret = getVolumeRange("MASTER"); can return something like ret=(-120.0f,0.0f)
|
* @example ret = getVolumeRange("MASTER"); can return something like ret=(-120.0f,0.0f)
|
||||||
*/
|
*/
|
||||||
virtual std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
|
virtual std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
|
||||||
|
/**
|
||||||
|
* @brief Generate the dot file corresponding at the actif nodes.
|
||||||
|
* @param[in] _filename Name of the file to write data.
|
||||||
|
*/
|
||||||
|
virtual void generateDot(const std::string& _filename);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,3 +223,25 @@ int32_t river::io::Node::newOutput(void* _outputBuffer,
|
|||||||
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [ END ]");
|
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [ END ]");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void river::io::Node::generateDot(etk::FSNode& _node) {
|
||||||
|
_node << "subgraph cluster_0 {\n";
|
||||||
|
// configure display:
|
||||||
|
_node << " node [shape=record, fontname=Helvetica, fontsize=10, color=lightsteelblue1, style=filled];\n";
|
||||||
|
//_node << " node [shape=diamond, fontname=Helvetica, fontsize=10, color=orangered, style=filled];\n"
|
||||||
|
//_node << " node [shape=ellipse, fontname=Helvetica, fontsize=8, color=aquamarine2, style=filled];\n";
|
||||||
|
// add elements
|
||||||
|
int32_t idNode = 0;
|
||||||
|
_node << " NODE_" << idNode << " [ label=\"name=" << m_name << "\" ];\n";
|
||||||
|
// add IO
|
||||||
|
_node << " node [shape=ellipse, fontname=Helvetica, fontsize=8, color=aquamarine2, style=filled];\n";
|
||||||
|
int32_t id = 0;
|
||||||
|
for (auto &it : m_list) {
|
||||||
|
if (it != nullptr) {
|
||||||
|
_node << " interface_" << id << " [ label=\"name=" << it->getName() << "\" ];\n";
|
||||||
|
_node << " NODE_" << idNode << " -> interface_" << id << " [ arrowhead=\"open\"];\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_node << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <airtaudio/Interface.h>
|
#include <airtaudio/Interface.h>
|
||||||
#include <drain/IOFormatInterface.h>
|
#include <drain/IOFormatInterface.h>
|
||||||
#include <drain/Volume.h>
|
#include <drain/Volume.h>
|
||||||
|
#include <etk/os/FSNode.h>
|
||||||
|
|
||||||
namespace river {
|
namespace river {
|
||||||
namespace io {
|
namespace io {
|
||||||
@ -99,6 +100,9 @@ namespace river {
|
|||||||
int32_t newOutput(void* _outputBuffer,
|
int32_t newOutput(void* _outputBuffer,
|
||||||
uint32_t _nbChunk,
|
uint32_t _nbChunk,
|
||||||
const std::chrono::system_clock::time_point& _time);
|
const std::chrono::system_clock::time_point& _time);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void generateDot(etk::FSNode& _node);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,7 @@ river::io::NodeAEC::NodeAEC(const std::string& _name, const std::shared_ptr<cons
|
|||||||
Node(_name, _config) {
|
Node(_name, _config) {
|
||||||
drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
||||||
drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||||
|
m_sampleTime = std::chrono::nanoseconds(1000000000*int64_t(hardwareFormat.getFrequency()));
|
||||||
/**
|
/**
|
||||||
# connect in input mode
|
# connect in input mode
|
||||||
map-on-microphone:{
|
map-on-microphone:{
|
||||||
@ -311,20 +312,21 @@ void river::io::NodeAEC::process() {
|
|||||||
std::chrono::system_clock::time_point MicTime = m_bufferMicrophone.getReadTimeStamp();
|
std::chrono::system_clock::time_point MicTime = m_bufferMicrophone.getReadTimeStamp();
|
||||||
std::chrono::system_clock::time_point fbTime = m_bufferFeedBack.getReadTimeStamp();
|
std::chrono::system_clock::time_point fbTime = m_bufferFeedBack.getReadTimeStamp();
|
||||||
|
|
||||||
// Synchronize if possible
|
if (MicTime-fbTime > m_sampleTime) {
|
||||||
if (MicTime < fbTime) {
|
// Synchronize if possible
|
||||||
RIVER_INFO("micTime < fbTime : Change Microphone time start " << fbTime);
|
if (MicTime < fbTime) {
|
||||||
RIVER_INFO(" old time stamp=" << m_bufferMicrophone.getReadTimeStamp());
|
RIVER_INFO("micTime < fbTime : Change Microphone time start " << fbTime);
|
||||||
m_bufferMicrophone.setReadPosition(fbTime);
|
RIVER_INFO(" old time stamp=" << m_bufferMicrophone.getReadTimeStamp());
|
||||||
RIVER_INFO(" new time stamp=" << m_bufferMicrophone.getReadTimeStamp());
|
m_bufferMicrophone.setReadPosition(fbTime);
|
||||||
|
RIVER_INFO(" new time stamp=" << m_bufferMicrophone.getReadTimeStamp());
|
||||||
|
}
|
||||||
|
if (MicTime > fbTime) {
|
||||||
|
RIVER_INFO("micTime > fbTime : Change FeedBack time start " << MicTime);
|
||||||
|
RIVER_INFO(" old time stamp=" << m_bufferFeedBack.getReadTimeStamp());
|
||||||
|
m_bufferFeedBack.setReadPosition(MicTime);
|
||||||
|
RIVER_INFO(" new time stamp=" << m_bufferFeedBack.getReadTimeStamp());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (MicTime > fbTime) {
|
|
||||||
RIVER_INFO("micTime > fbTime : Change FeedBack time start " << fbTime);
|
|
||||||
RIVER_INFO(" old time stamp=" << m_bufferFeedBack.getReadTimeStamp());
|
|
||||||
m_bufferFeedBack.setReadPosition(MicTime);
|
|
||||||
RIVER_INFO(" new time stamp=" << m_bufferFeedBack.getReadTimeStamp());
|
|
||||||
}*/
|
|
||||||
// check if enought time after synchronisation ...
|
// check if enought time after synchronisation ...
|
||||||
if (m_bufferMicrophone.getSize() <= 256) {
|
if (m_bufferMicrophone.getSize() <= 256) {
|
||||||
return;
|
return;
|
||||||
@ -336,7 +338,7 @@ void river::io::NodeAEC::process() {
|
|||||||
MicTime = m_bufferMicrophone.getReadTimeStamp();
|
MicTime = m_bufferMicrophone.getReadTimeStamp();
|
||||||
fbTime = m_bufferFeedBack.getReadTimeStamp();
|
fbTime = m_bufferFeedBack.getReadTimeStamp();
|
||||||
|
|
||||||
if (MicTime != fbTime) {
|
if (MicTime-fbTime > m_sampleTime) {
|
||||||
RIVER_ERROR("Can not synchronize flow ... : " << MicTime << " != " << fbTime << " delta = " << (MicTime-fbTime).count()/1000 << " µs");
|
RIVER_ERROR("Can not synchronize flow ... : " << MicTime << " != " << fbTime << " delta = " << (MicTime-fbTime).count()/1000 << " µs");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ namespace river {
|
|||||||
const std::vector<audio::channel>& _map);
|
const std::vector<audio::channel>& _map);
|
||||||
river::CircularBuffer m_bufferMicrophone;
|
river::CircularBuffer m_bufferMicrophone;
|
||||||
river::CircularBuffer m_bufferFeedBack;
|
river::CircularBuffer m_bufferFeedBack;
|
||||||
|
std::chrono::nanoseconds m_sampleTime; //!< represent the sample time at the specify frequency.
|
||||||
void process();
|
void process();
|
||||||
void processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const std::chrono::system_clock::time_point& _time);
|
void processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const std::chrono::system_clock::time_point& _time);
|
||||||
};
|
};
|
||||||
|
@ -339,6 +339,8 @@ class testInCallback {
|
|||||||
m_interface->start();
|
m_interface->start();
|
||||||
// wait 2 second ...
|
// wait 2 second ...
|
||||||
usleep(2000000);
|
usleep(2000000);
|
||||||
|
|
||||||
|
m_manager->generateDotAll("activeProcess.dot");
|
||||||
m_interface->stop();
|
m_interface->stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -625,6 +627,7 @@ TEST(TestALL, testInputCallBackMicClean) {
|
|||||||
process->run();
|
process->run();
|
||||||
process.reset();
|
process.reset();
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
|
tmpThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user