[DEV] some River rework

This commit is contained in:
Edouard DUPIN 2015-03-12 22:28:15 +01:00
parent ec4eae4242
commit f9ae8f23bd
17 changed files with 533 additions and 281 deletions

135
data/hardwareNao.json Normal file
View File

@ -0,0 +1,135 @@
{
speaker:{
io:"output",
map-on:{
interface:"alsa",
name:"AD1989A_outputs",
timestamp-mode:"trigered",
},
frequency:48000,
channel-map:[
"front-left", "front-right",
],
type:"int16",
nb-chunk:6000,
volume-name:"MASTER",
mux-demux-type:"int16-on-int32",
},
microphone:{
io:"input",
map-on:{
interface:"alsa",
name:"AD1989A_inputs",
timestamp-mode:"trigered",
},
frequency:48000,
channel-map:[
"front-left", "front-right"
, "rear-left", "rear-right"
],
type:"int16",
nb-chunk:6000,
mux-demux-type:"int16",
},
speakerGroup:{
io:"output",
map-on:{
interface:"alsa",
name:"hw:0,0",
timestamp-mode:"trigered",
},
group:"baseIOSynchrone",
frequency:48000,
channel-map:[
"front-left", "front-right",
],
type:"int16",
nb-chunk:1024,
volume-name:"MASTER",
mux-demux-type:"int16-on-int32",
},
microphone-front:{
io:"input",
map-on:{
interface:"alsa",
name:"hw:0,0,0",
timestamp-mode:"trigered",
},
group:"baseIOSynchrone",
frequency:48000,
channel-map:[
"front-left", "front-right"
],
type:"int16",
nb-chunk:1024,
mux-demux-type:"int16",
},
microphone-rear:{
io:"input",
map-on:{
interface:"alsa",
name:"hw:0,0,1",
timestamp-mode:"trigered",
},
group:"baseIOSynchrone",
frequency:48000,
channel-map:[
"rear-left", "rear-right"
],
type:"int16",
nb-chunk:1024,
mux-demux-type:"int16",
},
# virtual Nodes :
microphone-clean:{
io:"aec",
# connect in input mode
map-on-microphone:{
# generic virtual definition
io:"input",
map-on:"microphone-muxed",
resampling-type:"speexdsp",
resampling-option:"quality=10"
},
# connect in feedback mode
map-on-feedback:{
io:"feedback",
map-on:"speaker",
resampling-type:"speexdsp",
resampling-option:"quality=10",
},
#classical format configuration:
frequency:16000,
channel-map:[
"front-left", "front-right", "rear-left", "rear-right"
],
type:"int16",
# AEC algo definition
algo:"river-remover",
algo-mode:"cutter",
feedback-delay:10000, # in nanosecond
mux-demux-type:"int16",
},
microphone-muxed:{
io:"muxer",
map-on-input-1:{
# generic virtual definition
io:"input",
map-on:"microphone-front",
resampling-type:"speexdsp",
resampling-option:"quality=10"
},
map-on-input-2:{
io:"input",
map-on:"microphone-rear",
resampling-type:"speexdsp",
resampling-option:"quality=10",
},
frequency:48000,
channel-map:[
"front-left", "front-right", "rear-left", "rear-right"
],
type:"int16",
mux-demux-type:"int16",
},
}

View File

@ -1,38 +0,0 @@
{
# name of the virtual interface
microphone:{
# input or output
io:"input",
# name of the harware device
map-on:"microphone",
# name of the resampler
resampling-type:"speexdsp",
# some option to the resampler
resampling-option:"quality=10"
},
speaker:{
io:"output",
map-on:"speaker",
resampling-type:"speexdsp",
resampling-option:"quality=10"
},
feedback:{
# note : Feedback is plugged on an output not an input
io:"feedback",
map-on:"speaker",
resampling-type:"speexdsp",
resampling-option:"quality=10"
},
microphone-clean:{
io:"input",
map-on:"microphone-clean",
resampling-type:"speexdsp",
resampling-option:"quality=10"
},
microphone-muxed:{
io:"input",
map-on:"microphone-muxed",
resampling-type:"speexdsp",
resampling-option:"quality=10"
},
}

View File

@ -12,6 +12,7 @@ def create(target):
myModule.add_src_file([ myModule.add_src_file([
'river/debug.cpp', 'river/debug.cpp',
'river/river.cpp',
'river/Manager.cpp', 'river/Manager.cpp',
'river/Interface.cpp', 'river/Interface.cpp',
'river/CircularBuffer.cpp', 'river/CircularBuffer.cpp',

View File

@ -28,7 +28,6 @@ def create(target):
else: else:
debug.warning("unknow target for AIRTAudio : " + target.name); debug.warning("unknow target for AIRTAudio : " + target.name);
myModule.copy_file('data/virtual.json', 'virtual.json')
myModule.add_module_depend(['river', 'gtest', 'etk']) myModule.add_module_depend(['river', 'gtest', 'etk'])
# add the currrent module at the # add the currrent module at the

View File

@ -18,26 +18,23 @@
river::Interface::Interface(void) : river::Interface::Interface(void) :
m_node(), m_node(),
m_name(""), m_name("") {
m_volume(0.0f) {
static uint32_t uid = 0; static uint32_t uid = 0;
m_uid = uid++; m_uid = uid++;
} }
bool river::Interface::init(const std::string& _name, bool river::Interface::init(float _freq,
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) {
std::vector<audio::channel> map(_map); std::vector<audio::channel> map(_map);
m_name = _name;
m_node = _node; m_node = _node;
m_volume = 0.0f;
m_config = _config; m_config = _config;
m_mode = river::modeInterface_unknow; m_mode = river::modeInterface_unknow;
std::string type = m_config->getStringValue("io", "error"); std::string type = m_config->getStringValue("io", "error");
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type;
if (type == "output") { if (type == "output") {
m_mode = river::modeInterface_output; m_mode = river::modeInterface_output;
} else if (type == "input") { } else if (type == "input") {
@ -97,14 +94,13 @@ bool river::Interface::init(const std::string& _name,
return true; return true;
} }
std11::shared_ptr<river::Interface> river::Interface::create(const std::string& _name, std11::shared_ptr<river::Interface> river::Interface::create(float _freq,
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) {
std11::shared_ptr<river::Interface> out = std11::shared_ptr<river::Interface>(new river::Interface()); std11::shared_ptr<river::Interface> out = std11::shared_ptr<river::Interface>(new river::Interface());
out->init(_name, _freq, _map, _format, _node, _config); out->init(_freq, _map, _format, _node, _config);
return out; return out;
} }

View File

@ -48,8 +48,12 @@ namespace river {
* @brief Constructor * @brief Constructor
*/ */
Interface(); Interface();
bool init(const std::string& _name, bool init(float _freq,
float _freq, const std::vector<audio::channel>& _map,
audio::format _format,
const std11::shared_ptr<river::io::Node>& _node,
const std11::shared_ptr<const ejson::Object>& _config);
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,
const std11::shared_ptr<river::io::Node>& _node, const std11::shared_ptr<river::io::Node>& _node,
@ -59,13 +63,6 @@ namespace river {
* @brief Destructor * @brief Destructor
*/ */
virtual ~Interface(); virtual ~Interface();
static std11::shared_ptr<Interface> create(const std::string& _name,
float _freq,
const std::vector<audio::channel>& _map,
audio::format _format,
const std11::shared_ptr<river::io::Node>& _node,
const std11::shared_ptr<const ejson::Object>& _config);
protected: protected:
mutable std11::recursive_mutex m_mutex; mutable std11::recursive_mutex m_mutex;
std11::shared_ptr<const ejson::Object> m_config; std11::shared_ptr<const ejson::Object> m_config;
@ -94,6 +91,9 @@ namespace river {
virtual std::string getName() { virtual std::string getName() {
return m_name; return m_name;
}; };
virtual void setName(const std::string& _name) {
m_name = _name;
};
/** /**
* @brief set the read/write mode enable. * @brief set the read/write mode enable.
*/ */
@ -206,7 +206,6 @@ namespace river {
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);
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);
virtual void systemVolumeChange(); virtual void systemVolumeChange();
float m_volume; //!< Local channel Volume
public: public:
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);
virtual std::string getDotNodeName() const; virtual std::string getDotNodeName() const;

View File

@ -11,27 +11,11 @@
#include "io/Manager.h" #include "io/Manager.h"
#include "io/Node.h" #include "io/Node.h"
#include "debug.h" #include "debug.h"
#include <ejson/ejson.h>
#undef __class__ #undef __class__
#define __class__ "Manager" #define __class__ "Manager"
static std::string basicAutoConfig =
"{\n"
" microphone:{\n"
" io:'input',\n"
" map-on:'microphone',\n"
" resampling-type:'speexdsp',\n"
" resampling-option:'quality=10'\n"
" },\n"
" speaker:{\n"
" io:'output',\n"
" map-on:'speaker',\n"
" resampling-type:'speexdsp',\n"
" resampling-option:'quality=10'\n"
" }\n"
"}\n";
std11::shared_ptr<river::Manager> river::Manager::create(const std::string& _applicationUniqueId) { std11::shared_ptr<river::Manager> river::Manager::create(const std::string& _applicationUniqueId) {
return std11::shared_ptr<river::Manager>(new river::Manager(_applicationUniqueId)); return std11::shared_ptr<river::Manager>(new river::Manager(_applicationUniqueId));
} }
@ -39,11 +23,7 @@ std11::shared_ptr<river::Manager> river::Manager::create(const std::string& _app
river::Manager::Manager(const std::string& _applicationUniqueId) : river::Manager::Manager(const std::string& _applicationUniqueId) :
m_applicationUniqueId(_applicationUniqueId), m_applicationUniqueId(_applicationUniqueId),
m_listOpenInterface() { m_listOpenInterface() {
// TODO : Maybe create a single interface property (and all get the same ...)
if (m_config.load("DATA:virtual.json") == false) {
RIVER_WARNING("you must set a basic configuration file for virtual configuration: DATA:virtual.json (load default interface)");
m_config.parse(basicAutoConfig);
}
} }
river::Manager::~Manager() { river::Manager::~Manager() {
@ -51,79 +31,103 @@ river::Manager::~Manager() {
} }
std::vector<std::pair<std::string,std::string> > river::Manager::getListStreamInput() { std::vector<std::string> river::Manager::getListStreamInput() {
std::vector<std::pair<std::string,std::string> > output; std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys(); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
for (size_t iii=0; iii<keys.size(); ++iii) { if (manager == nullptr) {
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]); RIVER_ERROR("Unable to load harware IO manager ... ");
if (tmppp != nullptr) { } else {
std::string type = tmppp->getStringValue("io", "error"); output = manager->getListStreamInput();
if ( type == "input"
|| type == "feedback") {
output.push_back(std::make_pair<std::string,std::string>(std::string(keys[iii]), std::string("---")));
}
}
} }
return output; return output;
} }
std::vector<std::pair<std::string,std::string> > river::Manager::getListStreamOutput() { std::vector<std::string> river::Manager::getListStreamOutput() {
std::vector<std::pair<std::string,std::string> > output; std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys(); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
for (size_t iii=0; iii<keys.size(); ++iii) { if (manager == nullptr) {
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]); RIVER_ERROR("Unable to load harware IO manager ... ");
if (tmppp != nullptr) { } else {
std::string type = tmppp->getStringValue("io", "error"); output = manager->getListStreamOutput();
if (type == "output") {
output.push_back(std::make_pair<std::string,std::string>(std::string(keys[iii]), std::string("---")));
}
}
} }
return output; return output;
} }
std::vector<std::string> river::Manager::getListStreamVirtual() {
std::vector<std::string> output;
std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
} else {
output = manager->getListStreamVirtual();
}
return output;
}
std::vector<std::string> river::Manager::getListStream() {
std::vector<std::string> output;
std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
} else {
output = manager->getListStream();
}
return output;
}
bool river::Manager::setVolume(const std::string& _volumeName, float _valuedB) { bool river::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
return river::io::Manager::getInstance()->setVolume(_volumeName, _valuedB); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return false;
}
return manager->setVolume(_volumeName, _valuedB);
} }
float river::Manager::getVolume(const std::string& _volumeName) const { float river::Manager::getVolume(const std::string& _volumeName) const {
return river::io::Manager::getInstance()->getVolume(_volumeName); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return false;
}
return manager->getVolume(_volumeName);
} }
std::pair<float,float> river::Manager::getVolumeRange(const std::string& _volumeName) const { std::pair<float,float> river::Manager::getVolumeRange(const std::string& _volumeName) const {
return river::io::Manager::getInstance()->getVolumeRange(_volumeName); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return std::make_pair<float,float>(0.0f,0.0f);
}
return manager->getVolumeRange(_volumeName);
} }
std11::shared_ptr<river::Interface> river::Manager::createOutput(float _freq, std11::shared_ptr<river::Interface> river::Manager::createOutput(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& _options) {
// check if the output exist
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(_streamName);
if (tmppp == nullptr) {
RIVER_ERROR("can not open a non existance virtual input: '" << _streamName << "' not present in : " << m_config.getKeys());
return std11::shared_ptr<river::Interface>();
}
// check if it is an Output:
std::string type = tmppp->getStringValue("io", "error");
if (type != "output") {
RIVER_ERROR("can not open in output a virtual interface: '" << _streamName << "' configured has : " << type);
return std11::shared_ptr<river::Interface>();
}
std::string mapOn = tmppp->getStringValue("map-on", "");
if (mapOn == "") {
RIVER_ERROR("can not open in output a virtual interface: '" << _streamName << "' No 'map-on' element in json file ... ");
return std11::shared_ptr<river::Interface>();
}
// get global hardware interface: // get global hardware interface:
std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance(); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return std11::shared_ptr<river::Interface>();
}
// get the output or input channel : // get the output or input channel :
std11::shared_ptr<river::io::Node> node = manager->getNode(mapOn); std11::shared_ptr<river::io::Node> node = manager->getNode(_streamName);
if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return std11::shared_ptr<river::Interface>();
}
if (node->isOutput() != true) {
RIVER_ERROR("Can not Connect output on other thing than output ... for stream '" << _streamName << "'");;
return std11::shared_ptr<river::Interface>();
}
// create user iterface: // create user iterface:
std11::shared_ptr<river::Interface> interface; std11::shared_ptr<river::Interface> interface;
interface = river::Interface::create(_name, _freq, _map, _format, node, tmppp); std11::shared_ptr<ejson::Object> tmpOption = ejson::Object::create(_options);
tmpOption->addString("io", "output");
interface = river::Interface::create(_freq, _map, _format, node, tmpOption);
// store it in a list (needed to apply some parameters). // store it in a list (needed to apply some parameters).
m_listOpenInterface.push_back(interface); m_listOpenInterface.push_back(interface);
return interface; return interface;
@ -133,32 +137,60 @@ std11::shared_ptr<river::Interface> river::Manager::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& _options) {
// check if the output exist
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(_streamName);
if (tmppp == nullptr) {
RIVER_ERROR("can not open a non existance virtual interface: '" << _streamName << "' not present in : " << m_config.getKeys());
return std11::shared_ptr<river::Interface>();
}
// check if it is an Output:
std::string type = tmppp->getStringValue("io", "error");
if ( type != "input"
&& type != "feedback") {
RIVER_ERROR("can not open in output a virtual interface: '" << _streamName << "' configured has : " << type);
return std11::shared_ptr<river::Interface>();
}
std::string mapOn = tmppp->getStringValue("map-on", "");
if (mapOn == "") {
RIVER_ERROR("can not open in output a virtual interface: '" << _streamName << "' No 'map-on' element in json file ... ");
return std11::shared_ptr<river::Interface>();
}
// get global hardware interface: // get global hardware interface:
std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance(); std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return std11::shared_ptr<river::Interface>();
}
// get the output or input channel : // get the output or input channel :
std11::shared_ptr<river::io::Node> node = manager->getNode(mapOn); std11::shared_ptr<river::io::Node> node = manager->getNode(_streamName);
if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return std11::shared_ptr<river::Interface>();
}
if (node->isInput() != true) {
RIVER_ERROR("Can not Connect input on other thing than input ... for stream '" << _streamName << "'");;
return std11::shared_ptr<river::Interface>();
}
// create user iterface: // create user iterface:
std11::shared_ptr<river::Interface> interface; std11::shared_ptr<river::Interface> interface;
interface = river::Interface::create(_name, _freq, _map, _format, node, tmppp); std11::shared_ptr<ejson::Object> tmpOption = ejson::Object::create(_options);
tmpOption->addString("io", "input");
interface = river::Interface::create(_freq, _map, _format, node, tmpOption);
// store it in a list (needed to apply some parameters).
m_listOpenInterface.push_back(interface);
return interface;
}
std11::shared_ptr<river::Interface> river::Manager::createFeedback(float _freq,
const std::vector<audio::channel>& _map,
audio::format _format,
const std::string& _streamName,
const std::string& _options) {
// get global hardware interface:
std11::shared_ptr<river::io::Manager> manager = river::io::Manager::getInstance();
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return std11::shared_ptr<river::Interface>();
}
// get the output or input channel :
std11::shared_ptr<river::io::Node> node = manager->getNode(_streamName);
if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return std11::shared_ptr<river::Interface>();
}
if (node->isOutput() != true) {
RIVER_ERROR("Can not Connect feedback on other thing than output ... for stream '" << _streamName << "'");;
return std11::shared_ptr<river::Interface>();
}
// create user iterface:
std11::shared_ptr<river::Interface> interface;
std11::shared_ptr<ejson::Object> tmpOption = ejson::Object::create(_options);
tmpOption->addString("io", "feedback");
interface = river::Interface::create(_freq, _map, _format, node, tmpOption);
// store it in a list (needed to apply some parameters). // store it in a list (needed to apply some parameters).
m_listOpenInterface.push_back(interface); m_listOpenInterface.push_back(interface);
return interface; return interface;

View File

@ -21,7 +21,6 @@ namespace river {
*/ */
class Manager { class Manager {
private: private:
ejson::Document m_config; // virtual configuration
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.
protected: protected:
@ -37,15 +36,25 @@ namespace river {
virtual ~Manager(); virtual ~Manager();
public: public:
/** /**
* @brief Get all input audio stream description. * @brief Get all input audio stream.
* @return a list of all availlables input stream (name + description) * @return a list of all availlables input stream name
*/ */
virtual std::vector<std::pair<std::string,std::string> > getListStreamInput(); std::vector<std::string> getListStreamInput();
/** /**
* @brief Get all output audio stream description. * @brief Get all output audio stream.
* @return a list of all availlables output stream (name + description) * @return a list of all availlables output stream name
*/ */
virtual std::vector<std::pair<std::string,std::string> > getListStreamOutput(); std::vector<std::string> getListStreamOutput();
/**
* @brief Get all audio virtual stream.
* @return a list of all availlables virtual stream name
*/
std::vector<std::string> getListStreamVirtual();
/**
* @brief Get all audio stream.
* @return a list of all availlables stream name
*/
std::vector<std::string> getListStream();
/** /**
* @brief Set a volume for a specific group * @brief Set a volume for a specific group
@ -75,30 +84,44 @@ namespace river {
* @brief Create output Interface * @brief Create output Interface
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz * @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
* @param[in] _map ChannelMap of the Output * @param[in] _map ChannelMap of the Output
* @param[in] _format Sample Format to open the stream [int8_t] * @param[in] _format Sample Format to open the stream [int8_t, int16_t, ...]
* @param[in] _streamName Stream name to open: "" or "default" open current selected output * @param[in] _streamName Stream name to open: "" or "default" open current selected output
* @param[in] _name Name of this interface * @param[in] _options Json option to configure default resampling and many other things.
* @return a pointer on the interface * @return a pointer on the interface
*/ */
virtual std11::shared_ptr<Interface> createOutput(float _freq, virtual std11::shared_ptr<Interface> createOutput(float _freq = 48000,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format, audio::format _format = audio::format_int16,
const std::string& _streamName = "", const std::string& _streamName = "",
const std::string& _name = ""); const std::string& _options = "");
/** /**
* @brief Create input Interface * @brief Create input Interface
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz * @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
* @param[in] _map ChannelMap of the Output * @param[in] _map ChannelMap of the Output
* @param[in] _format Sample Format to open the stream [int8_t] * @param[in] _format Sample Format to open the stream [int8_t, int16_t, ...]
* @param[in] _streamName Stream name to open: "" or "default" open current selected input * @param[in] _streamName Stream name to open: "" or "default" open current selected input
* @param[in] _name Name of this interface * @param[in] _options Json option to configure default resampling and many other things.
* @return a pointer on the interface * @return a pointer on the interface
*/ */
virtual std11::shared_ptr<Interface> createInput(float _freq, virtual std11::shared_ptr<Interface> createInput(float _freq = 48000,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format, audio::format _format = audio::format_int16,
const std::string& _streamName = "", const std::string& _streamName = "",
const std::string& _name = ""); const std::string& _options = "");
/**
* @brief Create input Feedback Interface
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
* @param[in] _map ChannelMap of the Output
* @param[in] _format Sample Format to open the stream [int8_t, int16_t, ...]
* @param[in] _streamName Stream name to open: "" or "default" open current selected input
* @param[in] _options Json option to configure default resampling and many other things.
* @return a pointer on the interface
*/
virtual std11::shared_ptr<Interface> createFeedback(float _freq = 48000,
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16,
const std::string& _streamName = "",
const std::string& _options = "");
/** /**
* @brief Generate the dot file corresponding at all the actif nodes. * @brief Generate the dot file corresponding at all the actif nodes.
* @param[in] _filename Name of the file to write data. * @param[in] _filename Name of the file to write data.

View File

@ -57,19 +57,27 @@ static std::string basicAutoConfig =
river::io::Manager::Manager() { river::io::Manager::Manager() {
if (m_config.load("DATA:hardware.json") == false) {
RIVER_WARNING("you must set a basic configuration file for harware configuration: DATA:hardware.json (load default interface)");
m_config.parse(basicAutoConfig);
}
// TODO : Load virtual.json and check if all is correct ...
#ifdef __PORTAUDIO_INFERFACE__ #ifdef __PORTAUDIO_INFERFACE__
PaError err = Pa_Initialize(); PaError err = Pa_Initialize();
if(err != paNoError) { if(err != paNoError) {
RIVER_WARNING("Can not initialize portaudio : " << Pa_GetErrorText(err)); RIVER_WARNING("Can not initialize portaudio : " << Pa_GetErrorText(err));
} }
#endif #endif
}; }
void river::io::Manager::init(const std::string _filename) {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
if (_filename == "") {
RIVER_INFO("Load default config");
m_config.parse(basicAutoConfig);
} else if (m_config.load(_filename) == false) {
RIVER_ERROR("you must set a basic configuration file for harware configuration: '" << _filename << "'");
}
}
void river::io::Manager::unInit() {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
}
river::io::Manager::~Manager() { river::io::Manager::~Manager() {
#ifdef __PORTAUDIO_INFERFACE__ #ifdef __PORTAUDIO_INFERFACE__
@ -80,12 +88,85 @@ river::io::Manager::~Manager() {
#endif #endif
}; };
std11::shared_ptr<river::io::Manager> river::io::Manager::getInstance() { std11::shared_ptr<river::io::Manager> river::io::Manager::getInstance() {
if (river::isInit() == false) {
return std11::shared_ptr<river::io::Manager>();
}
static std11::shared_ptr<river::io::Manager> manager(new Manager()); static std11::shared_ptr<river::io::Manager> manager(new Manager());
return manager; return manager;
} }
std::vector<std::string> river::io::Manager::getListStreamInput() {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) {
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]);
if (tmppp != nullptr) {
std::string type = tmppp->getStringValue("io", "error");
if ( type == "input"
|| type == "PAinput") {
output.push_back(keys[iii]);
}
}
}
return output;
}
std::vector<std::string> river::io::Manager::getListStreamOutput() {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) {
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]);
if (tmppp != nullptr) {
std::string type = tmppp->getStringValue("io", "error");
if ( type == "output"
|| type == "PAoutput") {
output.push_back(keys[iii]);
}
}
}
return output;
}
std::vector<std::string> river::io::Manager::getListStreamVirtual() {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) {
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]);
if (tmppp != nullptr) {
std::string type = tmppp->getStringValue("io", "error");
if ( type != "input"
&& type != "PAinput"
&& type != "output"
&& type != "PAoutput"
&& type != "error") {
output.push_back(keys[iii]);
}
}
}
return output;
}
std::vector<std::string> river::io::Manager::getListStream() {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) {
const std11::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]);
if (tmppp != nullptr) {
std::string type = tmppp->getStringValue("io", "error");
if (type != "error") {
output.push_back(keys[iii]);
}
}
}
return output;
}
std11::shared_ptr<river::io::Node> river::io::Manager::getNode(const std::string& _name) { std11::shared_ptr<river::io::Node> river::io::Manager::getNode(const std::string& _name) {
std11::unique_lock<std11::recursive_mutex> lock(m_mutex); std11::unique_lock<std11::recursive_mutex> lock(m_mutex);
RIVER_WARNING("Get node : " << _name); RIVER_WARNING("Get node : " << _name);

View File

@ -38,7 +38,9 @@ namespace river {
/** /**
* @brief Destructor * @brief Destructor
*/ */
virtual ~Manager(); ~Manager();
void init();
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 time
@ -49,6 +51,26 @@ namespace river {
std::vector<std11::shared_ptr<drain::VolumeElement> > m_volumeGroup; std::vector<std11::shared_ptr<drain::VolumeElement> > m_volumeGroup;
public: public:
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.
* @return a list of all availlables input stream name
*/
std::vector<std::string> getListStreamInput();
/**
* @brief Get all output audio stream.
* @return a list of all availlables output stream name
*/
std::vector<std::string> getListStreamOutput();
/**
* @brief Get all audio virtual stream.
* @return a list of all availlables virtual stream name
*/
std::vector<std::string> getListStreamVirtual();
/**
* @brief Get all audio stream.
* @return a list of all availlables stream name
*/
std::vector<std::string> getListStream();
/** /**
* @brief Set a volume for a specific group * @brief Set a volume for a specific group
@ -58,26 +80,26 @@ namespace river {
* @return false An error occured * @return false An error occured
* @example : setVolume("MASTER", -3.0f); * @example : setVolume("MASTER", -3.0f);
*/ */
virtual bool setVolume(const std::string& _volumeName, float _valuedB); bool setVolume(const std::string& _volumeName, float _valuedB);
/** /**
* @brief Get a volume value * @brief Get a volume value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...) * @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The Volume value in dB. * @return The Volume value in dB.
* @example ret = getVolume("MASTER"); can return something like ret = -3.0f * @example ret = getVolume("MASTER"); can return something like ret = -3.0f
*/ */
virtual float getVolume(const std::string& _volumeName); float getVolume(const std::string& _volumeName);
/** /**
* @brief Get a parameter value * @brief Get a parameter value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...) * @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The requested value Range. * @return The requested value Range.
* @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; std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
/** /**
* @brief Generate the dot file corresponding at the actif nodes. * @brief Generate the dot file corresponding at the actif nodes.
* @param[in] _filename Name of the file to write data. * @param[in] _filename Name of the file to write data.
*/ */
virtual 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
std11::shared_ptr<river::io::Group> getGroup(const std::string& _name); std11::shared_ptr<river::io::Group> getGroup(const std::string& _name);

View File

@ -13,81 +13,6 @@
#undef __class__ #undef __class__
#define __class__ "io::NodeAEC" #define __class__ "io::NodeAEC"
#if 0
int32_t river::io::NodeAEC::airtAudioCallback(void* _outputBuffer,
void* _inputBuffer,
uint32_t _nbChunk,
const std11::chrono::system_clock::time_point& _time,
airtaudio::status _status) {
std11::unique_lock<std11::mutex> lock(m_mutex);
//RIVER_INFO("Time=" << _time);
/*
for (int32_t iii=0; iii<400; ++iii) {
RIVER_VERBOSE("dummy=" << uint64_t(dummy[iii]));
}
*/
if (_outputBuffer != nullptr) {
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
std::vector<int32_t> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
const int32_t* outputTmp = nullptr;
std::vector<uint8_t> outputTmp2;
RIVER_VERBOSE("resize=" << sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk);
outputTmp2.resize(sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk, 0);
for (auto &it : m_list) {
if (it == nullptr) {
continue;
}
if (it->getMode() != river::modeInterface_output) {
continue;
}
RIVER_VERBOSE(" IO name="<< it->getName());
// clear datas ...
memset(&outputTmp2[0], 0, sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk);
RIVER_VERBOSE(" request Data="<< _nbChunk);
it->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, sizeof(int32_t)*m_process.getInputConfig().getMap().size());
RIVER_VERBOSE(" Mix it ...");
outputTmp = reinterpret_cast<const int32_t*>(&outputTmp2[0]);
// Add data to the output tmp buffer :
for (size_t kkk=0; kkk<output.size(); ++kkk) {
output[kkk] += outputTmp[kkk];
}
}
RIVER_VERBOSE(" End stack process data ...");
m_process.processIn(&outputTmp2[0], _nbChunk, _outputBuffer, _nbChunk);
RIVER_VERBOSE(" Feedback :");
for (auto &it : m_list) {
if (it == nullptr) {
continue;
}
if (it->getMode() != river::modeInterface_feedback) {
continue;
}
RIVER_VERBOSE(" IO name="<< it->getName() << " (feedback)");
it->systemNewInputData(_time, _outputBuffer, _nbChunk);
}
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [ END ]");
}
if (_inputBuffer != nullptr) {
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
int16_t* inputBuffer = static_cast<int16_t *>(_inputBuffer);
for (auto &it : m_list) {
if (it == nullptr) {
continue;
}
if (it->getMode() != river::modeInterface_input) {
continue;
}
RIVER_INFO(" IO name="<< it->getName());
it->systemNewInputData(_time, inputBuffer, _nbChunk);
}
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [ END ]");
}
return 0;
}
#endif
std11::shared_ptr<river::io::NodeAEC> river::io::NodeAEC::create(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config) { std11::shared_ptr<river::io::NodeAEC> river::io::NodeAEC::create(const std::string& _name, const std11::shared_ptr<const ejson::Object>& _config) {
return std11::shared_ptr<river::io::NodeAEC>(new river::io::NodeAEC(_name, _config)); return std11::shared_ptr<river::io::NodeAEC>(new river::io::NodeAEC(_name, _config));
} }
@ -119,7 +44,10 @@ std11::shared_ptr<river::Interface> river::io::NodeAEC::createInput(float _freq,
std11::shared_ptr<river::io::Node> node = manager->getNode(streamName); std11::shared_ptr<river::io::Node> node = manager->getNode(streamName);
// create user iterface: // create user iterface:
std11::shared_ptr<river::Interface> interface; std11::shared_ptr<river::Interface> interface;
interface = river::Interface::create(_name, _freq, _map, _format, node, tmppp); interface = river::Interface::create(_freq, _map, _format, node, tmppp);
if (interface != nullptr) {
interface->setName(_name);
}
return interface; return interface;
} }

View File

@ -44,7 +44,10 @@ std11::shared_ptr<river::Interface> river::io::NodeMuxer::createInput(float _fre
std11::shared_ptr<river::io::Node> node = manager->getNode(streamName); std11::shared_ptr<river::io::Node> node = manager->getNode(streamName);
// create user iterface: // create user iterface:
std11::shared_ptr<river::Interface> interface; std11::shared_ptr<river::Interface> interface;
interface = river::Interface::create(_name, _freq, _map, _format, node, tmppp); interface = river::Interface::create(_freq, _map, _format, node, tmppp);
if (interface != nullptr) {
interface->setName(_name);
}
return interface; return interface;
} }

38
river/river.cpp Normal file
View File

@ -0,0 +1,38 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#iclude <river/river.h>
#iclude <river/debug.h>
#include <river/io/Manager.h>
static bool river_isInit = false;
static std::string river_configFile = "";
void river::init(const std::string& _filename) {
if (river_isInit == false) {
river_isInit = true;
river_configFile = _filename;
RIVER_INFO("init RIVER :" << river_configFile);
std11::shared_ptr<river::io::Manager> mng = river::io::Manager::getInstance();
mng->init(river_configFile);
}
}
void river::unInit() {
if (river_isInit == true) {
river_isInit = false;
RIVER_INFO("un-init RIVER :" << river_configFile);
std11::shared_ptr<river::io::Manager> mng = river::io::Manager::getInstance();
mng->unInit();
}
}
bool river::isInit() {
return river_isInit;
}

33
river/river.h Normal file
View File

@ -0,0 +1,33 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#ifndef __RIVER_H__
#define __RIVER_H__
#include <etk/type.h>
namespace river {
/**
* @brief Initialize the River Library
* @param[in] _filename Name of the configuration file (if "" ==> default config file)
*/
void init(const std::string& _filename);
/**
* @brief Un-initialize the River Library
* @note this close all stream of all interfaces.
* @note really good for test.
*/
void unInit();
/**
* @brief Get the status of initialisation
* @return true River is init
* @return false River is NOT init
*/
bool isInit();
}
#endif

View File

@ -45,8 +45,6 @@ namespace river_test_echo_delay {
m_gain(-40) { m_gain(-40) {
//Set stereo output: //Set stereo output:
std::vector<audio::channel> channelMap; std::vector<audio::channel> channelMap;
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
m_interfaceOut = m_manager->createOutput(48000, m_interfaceOut = m_manager->createOutput(48000,
channelMap, channelMap,
audio::format_int16, audio::format_int16,
@ -345,6 +343,9 @@ namespace river_test_echo_delay {
m_interfaceOut->start(); m_interfaceOut->start();
m_interfaceIn->start(); m_interfaceIn->start();
//m_interfaceFB->start(); //m_interfaceFB->start();
while (m_estimateVolumeInput == true) {
usleep(10000);
}
usleep(10000000); usleep(10000000);
//m_interfaceFB->stop(); //m_interfaceFB->stop();
m_interfaceIn->stop(); m_interfaceIn->stop();

View File

@ -41,7 +41,7 @@ namespace river_test_muxer {
std11::placeholders::_5, std11::placeholders::_5,
std11::placeholders::_6)); std11::placeholders::_6));
m_interfaceOut->addVolumeGroup("FLOW"); m_interfaceOut->addVolumeGroup("FLOW");
m_interfaceOut->setParameter("volume", "FLOW", "-6dB"); //m_interfaceOut->setParameter("volume", "FLOW", "-6dB");
//Set stereo output: //Set stereo output:
m_interfaceIn = m_manager->createInput(48000, m_interfaceIn = m_manager->createInput(48000,
@ -71,7 +71,7 @@ namespace river_test_muxer {
double baseCycle = 2.0*M_PI/(double)48000 * 440; double baseCycle = 2.0*M_PI/(double)48000 * 440;
for (int32_t iii=0; iii<_nbChunk; iii++) { for (int32_t iii=0; iii<_nbChunk; iii++) {
for (int32_t jjj=0; jjj<_map.size(); jjj++) { for (int32_t jjj=0; jjj<_map.size(); jjj++) {
data[_map.size()*iii+jjj] = sin(m_phase) * 30000; data[_map.size()*iii+jjj] = sin(m_phase) * 7000;
} }
m_phase += baseCycle; m_phase += baseCycle;
if (m_phase >= 2*M_PI) { if (m_phase >= 2*M_PI) {

View File

@ -7,6 +7,8 @@
#ifndef __RIVER_TEST_RECORD_CALLBACK_H__ #ifndef __RIVER_TEST_RECORD_CALLBACK_H__
#define __RIVER_TEST_RECORD_CALLBACK_H__ #define __RIVER_TEST_RECORD_CALLBACK_H__
#include <river/debug.h>
#undef __class__ #undef __class__
#define __class__ "test_record_callback" #define __class__ "test_record_callback"
@ -20,8 +22,6 @@ namespace river_test_record_callback {
m_manager(_manager) { m_manager(_manager) {
//Set stereo output: //Set stereo output:
std::vector<audio::channel> channelMap; std::vector<audio::channel> channelMap;
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
m_interface = m_manager->createInput(48000, m_interface = m_manager->createInput(48000,
channelMap, channelMap,
audio::format_int16, audio::format_int16,
@ -46,6 +46,7 @@ namespace river_test_record_callback {
if (_format != audio::format_int16) { if (_format != audio::format_int16) {
APPL_ERROR("call wrong type ... (need int16_t)"); APPL_ERROR("call wrong type ... (need int16_t)");
} }
RIVER_SAVE_FILE_MACRO(int16_t, "REC_INPUT.raw", _data, _nbChunk * _map.size());
const int16_t* data = static_cast<const int16_t*>(_data); const int16_t* data = static_cast<const int16_t*>(_data);
int64_t value = 0; int64_t value = 0;
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) { for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
@ -57,9 +58,7 @@ namespace river_test_record_callback {
void run() { void run() {
m_interface->start(); m_interface->start();
// wait 2 second ... // wait 2 second ...
usleep(2000000); usleep(20000000);
m_interface->stop(); m_interface->stop();
} }
}; };