[DOC] write nealy all documentation on the class

This commit is contained in:
Edouard DUPIN 2015-03-22 09:29:21 +01:00
parent 4c3fe665cf
commit 3891b0ac52
13 changed files with 392 additions and 88 deletions

19
monk_river.py Normal file
View File

@ -0,0 +1,19 @@
#!/usr/bin/python
import monkModule as module
import monkTools as tools
def get_desc():
return "river : Multiple flow input output audio"
def create():
# module name is 'edn' and type binary.
myModule = module.Module(__file__, 'river', 'LIBRARY')
# enable doculentation :
myModule.set_website("http://heeroyui.github.io/river/")
myModule.set_website_sources("http://github.com/heeroyui/river/")
myModule.set_path(tools.get_current_path(__file__) + "/river/")
myModule.set_path_general_doc(tools.get_current_path(__file__) + "/doc/")
# add the currrent module at the
return myModule

View File

@ -35,6 +35,10 @@ namespace river {
modeInterface_output, modeInterface_output,
modeInterface_feedback, modeInterface_feedback,
}; };
/**
* @brief Interface is the basic handle to manage the input output stream
* @note To create this class see @ref river::Manager class
*/
class Interface : public std11::enable_shared_from_this<Interface> { class Interface : public std11::enable_shared_from_this<Interface> {
friend class io::Node; friend class io::Node;
friend class io::NodeAirTAudio; friend class io::NodeAirTAudio;
@ -45,14 +49,34 @@ namespace river {
uint32_t m_uid; //!< unique ID for interface uint32_t m_uid; //!< unique ID for interface
protected: protected:
/** /**
* @brief Constructor * @brief Constructor (use factory)
*/ */
Interface(); Interface();
/**
* @brief Initilize the Class (do all that is not manage by constructor) Call by factory.
* @param[in] _freq Frequency.
* @param[in] _map Channel map organization.
* @param[in] _format Sample format
* @param[in] _node Low level interface to connect the flow.
* @param[in] _config Special configuration of this interface.
* @return true Configuration done corectly.
* @return false the configuration has an error.
*/
bool init(float _freq, bool init(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std11::shared_ptr<river::io::Node>& _node, const std11::shared_ptr<river::io::Node>& _node,
const std11::shared_ptr<const ejson::Object>& _config); const std11::shared_ptr<const ejson::Object>& _config);
/**
* @brief Factory of this interface (called by class river::Manager)
* @param[in] _freq Frequency.
* @param[in] _map Channel map organization.
* @param[in] _format Sample format
* @param[in] _node Low level interface to connect the flow.
* @param[in] _config Special configuration of this interface.
* @return nullptr The configuration does not work.
* @return pointer The interface has been corectly created.
*/
static std11::shared_ptr<Interface> create(float _freq, static std11::shared_ptr<Interface> create(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
@ -64,16 +88,25 @@ namespace river {
*/ */
virtual ~Interface(); virtual ~Interface();
protected: protected:
mutable std11::recursive_mutex m_mutex; mutable std11::recursive_mutex m_mutex; //!< Local mutex to protect data
std11::shared_ptr<const ejson::Object> m_config; std11::shared_ptr<const ejson::Object> m_config; //!< configuration set by the user.
protected: protected:
enum modeInterface m_mode; enum modeInterface m_mode; //!< interface type (input/output/feedback)
public: public:
/**
* @brief Get mode type of the current interface.
* @return The mode requested.
*/
enum modeInterface getMode() { enum modeInterface getMode() {
return m_mode; return m_mode;
} }
drain::Process m_process; protected:
drain::Process m_process; //!< Algorithme processing engine
public: public:
/**
* @brief Get the interface format configuration.
* @return The current format.
*/
const drain::IOFormatInterface& getInterfaceFormat() { const drain::IOFormatInterface& getInterfaceFormat() {
if ( m_mode == modeInterface_input if ( m_mode == modeInterface_input
|| m_mode == modeInterface_feedback) { || m_mode == modeInterface_feedback) {
@ -82,27 +115,47 @@ namespace river {
return m_process.getInputConfig(); return m_process.getInputConfig();
} }
} }
protected: protected:
std11::shared_ptr<river::io::Node> m_node; std11::shared_ptr<river::io::Node> m_node; //!< Hardware interface to/from stream audio flow.
protected: protected:
std::string m_name; std::string m_name; //!< Name of the interface.
public: public:
/**
* @brief Get interface name.
* @return The current name.
*/
virtual std::string getName() { virtual std::string getName() {
return m_name; return m_name;
}; };
/**
* @brief Set the interface name
* @param[in] _name new name of the interface
*/
virtual void setName(const std::string& _name) { virtual void setName(const std::string& _name) {
m_name = _name; m_name = _name;
}; };
/** /**
* @brief set the read/write mode enable. * @brief set the read/write mode enable.
* @note If you not set a output/input callback you must call this function.
*/ */
virtual void setReadwrite(); virtual void setReadwrite();
/** /**
* @brief When we want to implement a Callback Mode: * @brief When we want to implement a Callback Mode:
*/ */
/**
* @brief Set a callback on the write mode interface to know when data is needed in the buffer
* @param[in] _function Function to call
*/
virtual void setWriteCallback(drain::playbackFunctionWrite _function); virtual void setWriteCallback(drain::playbackFunctionWrite _function);
/**
* @brief Set Output callback mode with the specify callback.
* @param[in] _function Function to call
*/
virtual void setOutputCallback(drain::playbackFunction _function); virtual void setOutputCallback(drain::playbackFunction _function);
/**
* @brief Set Input callback mode with the specify callback.
* @param[in] _function Function to call
*/
virtual void setInputCallback(drain::recordFunction _function); virtual void setInputCallback(drain::recordFunction _function);
/** /**
* @brief Add a volume group of the current channel. * @brief Add a volume group of the current channel.
@ -223,18 +276,52 @@ namespace river {
*/ */
virtual std11::chrono::system_clock::time_point getCurrentTime() const; virtual std11::chrono::system_clock::time_point getCurrentTime() const;
private: private:
/**
* @brief Node Call interface : Input interface node has new data.
* @param[in] _time Time where the first sample has been capture.
* @param[in] _data Pointer on the new data.
* @param[in] _nbChunk Number of chunk in the buffer.
*/
virtual void systemNewInputData(std11::chrono::system_clock::time_point _time, const void* _data, size_t _nbChunk); virtual void systemNewInputData(std11::chrono::system_clock::time_point _time, const void* _data, size_t _nbChunk);
/**
* @brief Node Call interface: Output interface node need new data.
* @param[in] _time Time where the data might be played
* @param[in] _data Pointer on the data.
* @param[in] _nbChunk Number of chunk that might be write
* @param[in] _chunkSize Chunk size.
*/
virtual void systemNeedOutputData(std11::chrono::system_clock::time_point _time, void* _data, size_t _nbChunk, size_t _chunkSize); virtual void systemNeedOutputData(std11::chrono::system_clock::time_point _time, void* _data, size_t _nbChunk, size_t _chunkSize);
/**
* @brief Node Call interface: A volume has change.
*/
virtual void systemVolumeChange(); virtual void systemVolumeChange();
public: public:
/**
* @brief Create the dot in the FileNode stream.
* @param[in,out] _node File node to write data.
* @param[in] _nameIO Name to link the interface node
* @param[in] _isLink True if the node is connected on the current interface.
*/
virtual void generateDot(etk::FSNode& _node, const std::string& _nameIO, bool _isLink=true); virtual void generateDot(etk::FSNode& _node, const std::string& _nameIO, bool _isLink=true);
/**
* @brief Get the current 'dot' name of the interface
* @return The anme requested.
*/
virtual std::string getDotNodeName() const; virtual std::string getDotNodeName() const;
private: protected:
//statusFunction m_statusFunction; /**
public: * @brief Interfanel generate of status
* @param[in] _origin status source
* @param[in] _status Event status
*/
void generateStatus(const std::string& _origin, const std::string& _status) { void generateStatus(const std::string& _origin, const std::string& _status) {
m_process.generateStatus(_origin, _status); m_process.generateStatus(_origin, _status);
} }
public:
/**
* @brief Set status callback
* @param[in] _newFunction Function to call
*/
void setStatusFunction(drain::statusFunction _newFunction) { void setStatusFunction(drain::statusFunction _newFunction) {
m_process.setStatusFunction(_newFunction); m_process.setStatusFunction(_newFunction);
} }

View File

@ -19,7 +19,7 @@ namespace river {
/** /**
* @brief Audio interface manager : Single interface for every application that want to access on the Audio input/output * @brief Audio interface manager : Single interface for every application that want to access on the Audio input/output
*/ */
class Manager { class Manager : public std11::enable_shared_from_this<Manager> {
private: private:
const std::string& m_applicationUniqueId; //!< name of the application that open the Audio Interface. const std::string& m_applicationUniqueId; //!< name of the application that open the Audio Interface.
std::vector<std11::weak_ptr<river::Interface> > m_listOpenInterface; //!< List of all open Stream. std::vector<std11::weak_ptr<river::Interface> > m_listOpenInterface; //!< List of all open Stream.
@ -29,6 +29,11 @@ namespace river {
*/ */
Manager(const std::string& _applicationUniqueId); Manager(const std::string& _applicationUniqueId);
public: public:
/**
* @brief factory of the manager. Every Application will have only one maager for all his flow. this permit to manage all of it
* @param[in] _applicationUniqueId Unique name of the application
* @return Pointer on the manager or nullptr if an error occured
*/
static std11::shared_ptr<river::Manager> create(const std::string& _applicationUniqueId); static std11::shared_ptr<river::Manager> create(const std::string& _applicationUniqueId);
/** /**
* @brief Destructor * @brief Destructor

View File

@ -16,5 +16,6 @@
#undef RIVER_VERBOSE #undef RIVER_VERBOSE
#undef RIVER_TODO #undef RIVER_TODO
#undef RIVER_ASSERT #undef RIVER_ASSERT
#endif #endif

View File

@ -16,17 +16,57 @@ namespace river {
namespace io { namespace io {
class Node; class Node;
class Manager; class Manager;
/**
* @brief Group is contituate to manage some input and output in the same start and stop.
* It link N interface in a group. The start and the sopt is requested in Node inside the
* group they will start and stop when the first start is requested and stop when the last
* is stopped.
* @note For the Alsa interface a low level link is availlable with AirTAudio for Alsa (One thread)
*/
class Group : public std11::enable_shared_from_this<Group> { class Group : public std11::enable_shared_from_this<Group> {
public: public:
/**
* @brief Contructor. No special thing to do.
*/
Group() {} Group() {}
~Group() {} /**
* @brief Destructor
*/
~Group() {
// TODO : ...
}
private: private:
std::vector< std11::shared_ptr<Node> > m_list; std::vector< std11::shared_ptr<Node> > m_list; //!< List of all node in the group
public: public:
/**
* @brief Create a group with all node needed to syncronize together
* @param[in] _obj json document to create all the node in the group named _name
* @param[in] _name Name of the group to create
*/
void createFrom(const ejson::Document& _obj, const std::string& _name); void createFrom(const ejson::Document& _obj, const std::string& _name);
/**
* @brief Get a node in the group (if the node is not in the group nothing append).
* @param[in] _name Name of the node requested.
* @return nullptr The node named _name was not found.
* @return pointer The node was find in this group.
*/
std11::shared_ptr<river::io::Node> getNode(const std::string& _name); std11::shared_ptr<river::io::Node> getNode(const std::string& _name);
/**
* @brief Start the group.
* @note all sub-node will be started.
*/
void start(); void start();
/**
* @brief Stop the group.
* @note All sub-node will be stopped at the reserve order that they start.
*/
void stop(); void stop();
/**
* @brief Create the dot in the FileNode stream.
* @param[in,out] _node File node to write data.
* @param[in] _hardwareNode true if user want only display the hardware
* node and not the software node. false The oposite.
*/
void generateDot(etk::FSNode& _node, bool _hardwareNode); void generateDot(etk::FSNode& _node, bool _hardwareNode);
}; };
} }

View File

@ -25,9 +25,13 @@
namespace river { namespace river {
namespace io { namespace io {
class Node; class Node;
class Manager { /**
* @brief Internal sigleton of all Flow hadware and virtuals.
* @note this class will be initialize by the river::init() function at the start of the application.
*/
class Manager : public std11::enable_shared_from_this<Manager> {
private: private:
mutable std11::recursive_mutex m_mutex; mutable std11::recursive_mutex m_mutex; //!< prevent multiple access
private: private:
/** /**
* @brief Constructor * @brief Constructor
@ -39,18 +43,39 @@ namespace river {
* @brief Destructor * @brief Destructor
*/ */
~Manager(); ~Manager();
/**
* @brief Called by river::init() to set the hardware configuration file.
* @param[in] _filename Name of the file to initialize.
*/
void init(const std::string& _filename); void init(const std::string& _filename);
/**
* @brief Called by river::initString() to set the hardware configuration string.
* @param[in] _data json configuration string.
*/
void initString(const std::string& _data); void initString(const std::string& _data);
/**
* @brief Called by river::inInit() to uninitialize all the low level interface.
*/
void unInit(); void unInit();
private: private:
ejson::Document m_config; // harware configuration ejson::Document m_config; //!< harware configuration
std::vector<std11::shared_ptr<river::io::Node> > m_listKeepAlive; //!< list of all Node that might be keep alive sone time std::vector<std11::shared_ptr<river::io::Node> > m_listKeepAlive; //!< list of all Node that might be keep alive sone/all time
std::vector<std11::weak_ptr<river::io::Node> > m_list; //!< List of all IO node std::vector<std11::weak_ptr<river::io::Node> > m_list; //!< List of all IO node
public: public:
/**
* @brief Get a node with his name (the name is set in the description file.
* @param[in] _name Name of the node
* @return Pointer on the noe or a nullptr if the node does not exist in the file or an error occured.
*/
std11::shared_ptr<river::io::Node> getNode(const std::string& _name); std11::shared_ptr<river::io::Node> getNode(const std::string& _name);
private: private:
std::vector<std11::shared_ptr<drain::VolumeElement> > m_volumeGroup; std::vector<std11::shared_ptr<drain::VolumeElement> > m_volumeGroup; //!< List of All global volume in the Low level interface.
public: public:
/**
* @brief Get a volume in the global list of vilume
* @param[in] _name Name of the volume.
* @return pointer on the requested volume (create it if does not exist). nullptr if the name is empty.
*/
std11::shared_ptr<drain::VolumeElement> getVolumeGroup(const std::string& _name); std11::shared_ptr<drain::VolumeElement> getVolumeGroup(const std::string& _name);
/** /**
* @brief Get all input audio stream. * @brief Get all input audio stream.
@ -103,6 +128,11 @@ namespace river {
void generateDot(const std::string& _filename); void generateDot(const std::string& _filename);
private: private:
std::map<std::string, std11::shared_ptr<river::io::Group> > m_listGroup; //!< List of all groups std::map<std::string, std11::shared_ptr<river::io::Group> > m_listGroup; //!< List of all groups
/**
* @brief get a low level interface group.
* @param[in] _name Name of the group.
* @return Pointer on the requested group or nullptr if the group does not existed.
*/
std11::shared_ptr<river::io::Group> getGroup(const std::string& _name); std11::shared_ptr<river::io::Group> getGroup(const std::string& _name);
}; };

View File

@ -189,11 +189,11 @@ void river::io::Node::volumeChange() {
} }
} }
int32_t river::io::Node::newInput(const void* _inputBuffer, void river::io::Node::newInput(const void* _inputBuffer,
uint32_t _nbChunk, uint32_t _nbChunk,
const std11::chrono::system_clock::time_point& _time) { const std11::chrono::system_clock::time_point& _time) {
if (_inputBuffer == nullptr) { if (_inputBuffer == nullptr) {
return -1; return;
} }
const int16_t* inputBuffer = static_cast<const int16_t *>(_inputBuffer); const int16_t* inputBuffer = static_cast<const int16_t *>(_inputBuffer);
for (size_t iii=0; iii< m_list.size(); ++iii) { for (size_t iii=0; iii< m_list.size(); ++iii) {
@ -207,14 +207,14 @@ int32_t river::io::Node::newInput(const void* _inputBuffer,
m_list[iii]->systemNewInputData(_time, inputBuffer, _nbChunk); m_list[iii]->systemNewInputData(_time, inputBuffer, _nbChunk);
} }
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [ END ]"); RIVER_VERBOSE("data Input size request :" << _nbChunk << " [ END ]");
return 0; return;
} }
int32_t river::io::Node::newOutput(void* _outputBuffer, void river::io::Node::newOutput(void* _outputBuffer,
uint32_t _nbChunk, uint32_t _nbChunk,
const std11::chrono::system_clock::time_point& _time) { const std11::chrono::system_clock::time_point& _time) {
if (_outputBuffer == nullptr) { if (_outputBuffer == nullptr) {
return -1; return;
} }
std::vector<int32_t> output; std::vector<int32_t> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size()); RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
@ -259,7 +259,7 @@ int32_t river::io::Node::newOutput(void* _outputBuffer,
m_list[iii]->systemNewInputData(_time, _outputBuffer, _nbChunk); m_list[iii]->systemNewInputData(_time, _outputBuffer, _nbChunk);
} }
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [ END ]"); RIVER_VERBOSE("data Output size request :" << _nbChunk << " [ END ]");
return 0; return;
} }
static void link(etk::FSNode& _node, const std::string& _first, const std::string& _op, const std::string& _second) { static void link(etk::FSNode& _node, const std::string& _first, const std::string& _op, const std::string& _second) {

View File

@ -27,13 +27,19 @@ namespace river {
namespace io { namespace io {
class Manager; class Manager;
class Group; class Group;
/**
* @brief A node is the base for input/output interface. When a output id declared, we automaticly have a feedback associated.
* this manage the muxing of data for output an the demuxing for input.
*/
class Node : public std11::enable_shared_from_this<Node> { class Node : public std11::enable_shared_from_this<Node> {
friend class river::io::Group; friend class river::io::Group;
protected: protected:
uint32_t m_uid; // uniqueNodeID uint32_t m_uid; //!< uniqueNodeID use for debug an dot generation.
protected: protected:
/** /**
* @brief Constructor * @brief Constructor
* @param[in] _name Name of the node.
* @param[in] _config Configuration of the node.
*/ */
Node(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config); Node(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config);
public: public:
@ -41,15 +47,24 @@ namespace river {
* @brief Destructor * @brief Destructor
*/ */
virtual ~Node(); virtual ~Node();
/**
* @brief Get the status of this node acces on harware or acces on other node (virtual).
* @return true This is an harware interface.
* @return false this is a virtual interface.
*/
virtual bool isHarwareNode() { virtual bool isHarwareNode() {
return false; return false;
}; };
protected: protected:
mutable std11::mutex m_mutex; mutable std11::mutex m_mutex; //!< prevent open/close/write/read access that is multi-threaded.
std11::shared_ptr<const ejson::Object> m_config; std11::shared_ptr<const ejson::Object> m_config; //!< configuration description.
protected: protected:
drain::Process m_process; drain::Process m_process; //!< Low level algorithms
public: public:
/**
* @brief Get the uper client interface configuration.
* @return process configuration.
*/
const drain::IOFormatInterface& getInterfaceFormat() { const drain::IOFormatInterface& getInterfaceFormat() {
if (m_isInput == true) { if (m_isInput == true) {
return m_process.getOutputConfig(); return m_process.getOutputConfig();
@ -57,6 +72,10 @@ namespace river {
return m_process.getInputConfig(); return m_process.getInputConfig();
} }
} }
/**
* @brief Get the harware client interface configuration.
* @return process configuration.
*/
const drain::IOFormatInterface& getHarwareFormat() { const drain::IOFormatInterface& getHarwareFormat() {
if (m_isInput == true) { if (m_isInput == true) {
return m_process.getInputConfig(); return m_process.getInputConfig();
@ -65,62 +84,138 @@ namespace river {
} }
} }
protected: protected:
std11::shared_ptr<drain::VolumeElement> m_volume; //!< if a volume is set it is set here ... for hardware interface only.
std11::shared_ptr<drain::VolumeElement> m_volume; //!< if a volume is set it is set here ...
protected: protected:
std::vector<std11::weak_ptr<river::Interface> > m_listAvaillable; //!< List of all interface that exist on this Node std::vector<std11::weak_ptr<river::Interface> > m_listAvaillable; //!< List of all interface that exist on this Node
std::vector<std11::shared_ptr<river::Interface> > m_list; std::vector<std11::shared_ptr<river::Interface> > m_list; //!< List of all connected interface at this node.
/**
* @brief Get the number of interface with a specific type.
* @param[in] _interfaceType Type of the interface.
* @return Number of interface connected.
*/
size_t getNumberOfInterface(enum river::modeInterface _interfaceType); size_t getNumberOfInterface(enum river::modeInterface _interfaceType);
/**
* @brief Get the number of interface with a specific type that can connect on the Node.
* @param[in] _interfaceType Type of the interface.
* @return Number of interface that can connect.
*/
size_t getNumberOfInterfaceAvaillable(enum river::modeInterface _interfaceType); size_t getNumberOfInterfaceAvaillable(enum river::modeInterface _interfaceType);
public: public:
/**
* @brief Get the number of interface connected
* @return Number of interfaces.
*/
size_t getNumberOfInterface() { size_t getNumberOfInterface() {
return m_list.size(); return m_list.size();
} }
public: public:
/**
* @brief Register an interface that can connect on it. (might be done in the Interface Init)
* @note We keep a std::weak_ptr. this is the reason why we do not have a remove.
* @param[in] _interface Pointer on the interface to register.
*/
void registerAsRemote(const std11::shared_ptr<river::Interface>& _interface); void registerAsRemote(const std11::shared_ptr<river::Interface>& _interface);
/**
* @brief Request this interface might receve/send dat on the flow. (start/resume)
* @param[in] _interface Pointer on the interface to register.
*/
void interfaceAdd(const std11::shared_ptr<river::Interface>& _interface); void interfaceAdd(const std11::shared_ptr<river::Interface>& _interface);
/**
* @brief Un-register the interface as an availlable read/write interface. (suspend/stop)
* @param[in] _interface Pointer on the interface to register.
*/
void interfaceRemove(const std11::shared_ptr<river::Interface>& _interface); void interfaceRemove(const std11::shared_ptr<river::Interface>& _interface);
protected: protected:
std::string m_name; //!< Harware.json configuration name std::string m_name; //!< Name of the interface
public: public:
/**
* @brief Get the interface name.
* @return Current name.
*/
const std::string& getName() { const std::string& getName() {
return m_name; return m_name;
} }
protected: protected:
bool m_isInput; bool m_isInput; //!< sense of the stream
public: public:
/**
* @brief Check if it is an input stream
* @return true if it is an input/ false otherwise
*/
bool isInput() { bool isInput() {
return m_isInput; return m_isInput;
} }
/**
* @brief Check if it is an output stream
* @return true if it is an output/ false otherwise
*/
bool isOutput() { bool isOutput() {
return !m_isInput; return !m_isInput;
} }
protected: protected:
std11::weak_ptr<river::io::Group> m_group; std11::weak_ptr<river::io::Group> m_group; //!< reference on the group. If available.
public: public:
/**
* @brief Set this node in a low level group.
* @param[in] _group Group reference.
*/
void setGroup(std11::shared_ptr<river::io::Group> _group) { void setGroup(std11::shared_ptr<river::io::Group> _group) {
m_group = _group; m_group = _group;
} }
protected: protected:
/**
* @brief Start the flow in the group (start if no group)
*/
void startInGroup(); void startInGroup();
/**
* @brief Stop the flow in the group (stop if no group)
*/
void stopInGroup(); void stopInGroup();
/**
* @brief Real start of the stream
*/
virtual void start() = 0; virtual void start() = 0;
/**
* @brief Real stop of the stream
*/
virtual void stop() = 0; virtual void stop() = 0;
public: public:
/**
* @brief If this iss an hardware interface we can have a resuest of the volume stage:
* @return pointer on the requested volume.
*/
const std11::shared_ptr<drain::VolumeElement>& getVolume() { const std11::shared_ptr<drain::VolumeElement>& getVolume() {
return m_volume; return m_volume;
} }
public: public:
/**
* @brief Called when a group wolume has been change to update all volume stage.
*/
void volumeChange(); void volumeChange();
protected: protected:
int32_t newInput(const void* _inputBuffer, /**
uint32_t _nbChunk, * @brief Call by child classes to process data in all interface linked on the current Node. Have new input to process.
const std11::chrono::system_clock::time_point& _time); * @param[in] _inputBuffer Pointer on the data.
int32_t newOutput(void* _outputBuffer, * @param[in] _nbChunk Number of chunk in the buffer.
uint32_t _nbChunk, * @param[in] _time Time where the first sample has been capture.
const std11::chrono::system_clock::time_point& _time); */
void newInput(const void* _inputBuffer,
uint32_t _nbChunk,
const std11::chrono::system_clock::time_point& _time);
/**
* @brief Call by child classes to process data in all interface linked on the current Node. Have new output to get. this call the feedback too.
* @param[in,out] _outputBuffer Pointer on the buffer to write the data.
* @param[in] _nbChunk Number of chunk to write in the buffer.
* @param[in] _time Time where the data might be played.
*/
void newOutput(void* _outputBuffer,
uint32_t _nbChunk,
const std11::chrono::system_clock::time_point& _time);
public: public:
/**
* @brief Generate the node dot file section
* @param[in] _node File node to generate the data.
*/
virtual void generateDot(etk::FSNode& _node); virtual void generateDot(etk::FSNode& _node);
}; };
} }

View File

@ -197,10 +197,8 @@ void river::io::NodeAEC::onDataReceivedFeedBack(const void* _data,
} }
void river::io::NodeAEC::process() { void river::io::NodeAEC::process() {
if (m_bufferMicrophone.getSize() <= 256) { if ( m_bufferMicrophone.getSize() <= 256
return; || m_bufferFeedBack.getSize() <= 256) {
}
if (m_bufferFeedBack.getSize() <= 256) {
return; return;
} }
std11::chrono::system_clock::time_point MicTime = m_bufferMicrophone.getReadTimeStamp(); std11::chrono::system_clock::time_point MicTime = m_bufferMicrophone.getReadTimeStamp();

View File

@ -21,6 +21,11 @@ namespace river {
*/ */
NodeAEC(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config); NodeAEC(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config);
public: public:
/**
* @brief Factory of this Virtual Node.
* @param[in] _name Name of the node.
* @param[in] _config Configuration of the node.
*/
static std11::shared_ptr<NodeAEC> create(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config); static std11::shared_ptr<NodeAEC> create(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config);
/** /**
* @brief Destructor * @brief Destructor
@ -29,29 +34,58 @@ namespace river {
protected: protected:
virtual void start(); virtual void start();
virtual void stop(); virtual void stop();
std11::shared_ptr<river::Interface> m_interfaceMicrophone; std11::shared_ptr<river::Interface> m_interfaceMicrophone; //!< Interface on the Microphone.
std11::shared_ptr<river::Interface> m_interfaceFeedBack; std11::shared_ptr<river::Interface> m_interfaceFeedBack; //!< Interface on the feedback of speaker.
/**
* @brief Internal: create an input with the specific parameter:
* @param[in] _freq Frequency.
* @param[in] _map Channel map organization.
* @param[in] _format Sample format
* @param[in] _streamName
* @param[in] _name
* @return Interfae Pointer.
*/
std11::shared_ptr<river::Interface> createInput(float _freq, std11::shared_ptr<river::Interface> createInput(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::string& _streamName, const std::string& _streamName,
const std::string& _name); const std::string& _name);
/**
* @brief Stream data input callback
* @todo : copy doc ..
*/
void onDataReceivedMicrophone(const void* _data, void onDataReceivedMicrophone(const void* _data,
const std11::chrono::system_clock::time_point& _time, const std11::chrono::system_clock::time_point& _time,
size_t _nbChunk, size_t _nbChunk,
enum audio::format _format, enum audio::format _format,
uint32_t _frequency, uint32_t _frequency,
const std::vector<audio::channel>& _map); const std::vector<audio::channel>& _map);
/**
* @brief Stream data input callback
* @todo : copy doc ..
*/
void onDataReceivedFeedBack(const void* _data, void onDataReceivedFeedBack(const void* _data,
const std11::chrono::system_clock::time_point& _time, const std11::chrono::system_clock::time_point& _time,
size_t _nbChunk, size_t _nbChunk,
enum audio::format _format, enum audio::format _format,
uint32_t _frequency, uint32_t _frequency,
const std::vector<audio::channel>& _map); const std::vector<audio::channel>& _map);
drain::CircularBuffer m_bufferMicrophone; protected:
drain::CircularBuffer m_bufferFeedBack; drain::CircularBuffer m_bufferMicrophone; //!< temporary buffer to synchronize data.
drain::CircularBuffer m_bufferFeedBack; //!< temporary buffer to synchronize data.
std11::chrono::nanoseconds m_sampleTime; //!< represent the sample time at the specify frequency. std11::chrono::nanoseconds m_sampleTime; //!< represent the sample time at the specify frequency.
/**
* @brief Process synchronization on the 2 flow.
*/
void process(); void process();
/**
* @brief Process algorithm on the current 2 syncronize flow.
* @param[in] _dataMic Pointer in the Microphione interface.
* @param[in] _dataFB Pointer on the beedback buffer.
* @param[in] _nbChunk Number of chunk to process.
* @param[in] _time Time on the firsta sample that data has been captured.
* @return
*/
void processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const std11::chrono::system_clock::time_point& _time); void processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const std11::chrono::system_clock::time_point& _time);
public: public:
virtual void generateDot(etk::FSNode& _node); virtual void generateDot(etk::FSNode& _node);

View File

@ -23,25 +23,6 @@ static std::string asString(const std11::chrono::system_clock::time_point& tp) {
return ts; return ts;
} }
int32_t river::io::NodeAirTAudio::duplexCallback(const void* _inputBuffer,
const std11::chrono::system_clock::time_point& _timeInput,
void* _outputBuffer,
const std11::chrono::system_clock::time_point& _timeOutput,
uint32_t _nbChunk,
const std::vector<airtaudio::status>& _status) {
std11::unique_lock<std11::mutex> lock(m_mutex);
// TODO : Manage status ...
if (_inputBuffer != nullptr) {
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newInput(_inputBuffer, _nbChunk, _timeInput);
}
if (_outputBuffer != nullptr) {
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newOutput(_outputBuffer, _nbChunk, _timeOutput);
}
return 0;
}
int32_t river::io::NodeAirTAudio::recordCallback(const void* _inputBuffer, int32_t river::io::NodeAirTAudio::recordCallback(const void* _inputBuffer,
const std11::chrono::system_clock::time_point& _timeInput, const std11::chrono::system_clock::time_point& _timeInput,
uint32_t _nbChunk, uint32_t _nbChunk,

View File

@ -15,7 +15,10 @@ namespace river {
namespace io { namespace io {
class Manager; class Manager;
class Group; class Group;
class NodeAirTAudio : public Node { /**
* @brief Low level node that is manage on the interface with the extern lib airtaudio
*/
class NodeAirTAudio : public river::io::Node {
friend class river::io::Group; friend class river::io::Group;
protected: protected:
/** /**
@ -32,20 +35,30 @@ namespace river {
return true; return true;
}; };
protected: protected:
airtaudio::Interface m_adac; //!< Real audio interface airtaudio::Interface m_adac; //!< Real airtaudio interface
airtaudio::DeviceInfo m_info; airtaudio::DeviceInfo m_info; //!< information on the stream.
unsigned int m_rtaudioFrameSize; unsigned int m_rtaudioFrameSize; // DEPRECATED soon...
public: public:
int32_t duplexCallback(const void* _inputBuffer, /**
const std11::chrono::system_clock::time_point& _timeInput, * @brief Input Callback . Have recaive new data to process.
void* _outputBuffer, * @param[in] _inputBuffer Pointer on the data buffer.
const std11::chrono::system_clock::time_point& _timeOutput, * @param[in] _timeInput Time on the fist sample has been recorded.
uint32_t _nbChunk, * @param[in] _nbChunk Number of chunk in the buffer
const std::vector<airtaudio::status>& _status); * @param[in] _status DEPRECATED soon
* @return DEPRECATED soon
*/
int32_t recordCallback(const void* _inputBuffer, int32_t recordCallback(const void* _inputBuffer,
const std11::chrono::system_clock::time_point& _timeInput, const std11::chrono::system_clock::time_point& _timeInput,
uint32_t _nbChunk, uint32_t _nbChunk,
const std::vector<airtaudio::status>& _status); const std::vector<airtaudio::status>& _status);
/**
* @brief Playback callback. Request new data on output
* @param[in,out] _outputBuffer Pointer on the buffer to fill data.
* @param[in] _timeOutput Time on wich the data might be played.
* @param[in] _nbChunk Number of chunk in the buffer
* @param[in] _status DEPRECATED soon
* @return DEPRECATED soon
*/
int32_t playbackCallback(void* _outputBuffer, int32_t playbackCallback(void* _outputBuffer,
const std11::chrono::system_clock::time_point& _timeOutput, const std11::chrono::system_clock::time_point& _timeOutput,
uint32_t _nbChunk, uint32_t _nbChunk,

View File

@ -16,6 +16,7 @@
namespace river { namespace river {
namespace io { namespace io {
class Manager; class Manager;
//! @not-in-doc
class NodePortAudio : public Node { class NodePortAudio : public Node {
protected: protected:
/** /**