23 Commits
0.2.0 ... 0.4.0

Author SHA1 Message Date
b114de5f1d [RELEASE] new version 0.4.0 2016-10-24 22:25:37 +02:00
d13298acf9 [CI] update build CI 2016-10-24 22:25:37 +02:00
a5ca43b7dd [DEV] remove dependency of unistd.h 2016-10-13 21:29:18 +02:00
abc2ce6a49 [DEV] Update new lutin 2.2.0 (no legacy support) 2016-10-04 23:41:29 +02:00
6a2e12c2ad [DEBUG] correct .hpp port + clean libC include 2016-10-02 23:42:50 +02:00
7d38eb190d [DEV/API] change .h in .hpp 2016-10-02 22:20:33 +02:00
bc47714cff [DEV] add support of the output float,double,int32/64 muxer 2016-09-27 21:46:47 +02:00
6ecf73bb11 [DEV] CORRECT INDENTATION 2016-09-26 22:31:05 +02:00
417845abc2 [DOC] wrong website 2016-09-16 21:05:30 +02:00
5acf1ead90 [DOC] update sample to the new doxy methode 2016-09-14 22:19:22 +02:00
e80670fd0c [DEV] remove catkin build methode 2016-09-14 21:43:24 +02:00
77241b828d [DEV] update dev tag version 2016-09-12 21:07:12 +02:00
d0bc917536 [RELEASE] create release 0.3.1 2016-09-12 21:06:37 +02:00
4fcde8de4f [DEV] update to future lutin 2.0 2016-09-08 21:35:02 +02:00
d20753518c [DEV] update to future lutin 2.0 2016-09-07 22:05:42 +02:00
2ffe31a3e9 [DEV] update dev tag version 2016-08-30 22:54:57 +02:00
f91dc09ac1 [RELEASE] create release 0.3.0 2016-08-30 22:54:08 +02:00
2566843a66 [DEV] add support of multiple input stream type 2016-08-22 21:52:31 +02:00
9a37b437c6 [DEV] update sharedPtr 2016-07-19 21:43:58 +02:00
e83ac7620d [DEV] rm __class__ 2016-05-02 22:01:55 +02:00
434c8097d0 [DEV] update the change on 'enum' to 'enum class' 2016-04-29 23:16:07 +02:00
07a56e29ae [DEV] update to ne new ejson API (remove helper) 2016-04-28 23:46:12 +02:00
aa5df52e14 [DEV] update new ejson interface 2016-04-20 21:19:11 +02:00
75 changed files with 1657 additions and 1645 deletions

View File

@@ -1,11 +1,7 @@
language: language: cpp
- cpp
sudo: false sudo: required
dist: trusty
os:
- linux
- osx
branches: branches:
only: only:
@@ -18,39 +14,83 @@ addons:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- g++-4.9 - g++-4.9
- expect
- binutils-mingw-w64-x86-64 # 64bit MinGW
- gcc-mingw-w64-x86-64
- g++-mingw-w64-x86-64
matrix:
include:
- os: linux
env: CONF=release BUILDER=gcc TARGET=Linux TAG=Linux COMPILATOR_OPTION="--compilator-version=4.9" GCOV=--gcov
compiler: gcc
- os: linux
env: CONF=debug BUILDER=clang TARGET=Linux
compiler: clang
- os: linux
env: CONF=release BUILDER=gcc TARGET=Windows TAG=Mingw
compiler: x86_64-w64-mingw32-gcc
- os: linux
env: CONF=release BUILDER=gcc TARGET=Android TAG=Android DISABLE_PACKAGE=-p
compiler: gcc
- os: osx
env: CONF=release BUILDER=clang TARGET=MacOs TAG=MacOs
compiler: clang
- os: osx
env: CONF=release BUILDER=clang TARGET=IOs TAG=IOs
compiler: clang
install: install:
- cd ..
- pip install --user lutin - pip install --user lutin
- if [ "$TAG" == "Android" ]; then
env: git clone --depth 1 --branch master https://github.com/HeeroYui/android-download-tool;
- CONF=debug BOARD=Linux BUILDER=clang GCOV= ./android-download-tool/dl-android.sh;
- CONF=release BOARD=Linux BUILDER=clang GCOV= fi
- CONF=debug BOARD=Linux BUILDER=gcc GCOV= - git clone --depth 1 --branch master https://github.com/atria-soft/ci.git
- CONF=release BOARD=Linux BUILDER=gcc GCOV= - cd -
- CONF=debug BOARD=Linux BUILDER=gcc GCOV=--gcov
before_script: before_script:
- cd .. - cd ..
- wget http://atria-soft.com/ci/coverage_send.py - git clone https://github.com/atria-soft/etk.git -b $TRAVIS_BRANCH
- wget http://atria-soft.com/ci/test_send.py - git clone https://github.com/atria-soft/elog.git -b $TRAVIS_BRANCH
- wget http://atria-soft.com/ci/warning_send.py - git clone https://github.com/atria-soft/ememory.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/echrono.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/ethread.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/ejson.git -b $TRAVIS_BRANCH
- git clone https://github.com/atria-soft/jvm-basics.git -b $TRAVIS_BRANCH
- git clone https://github.com/musicdsp/audio.git -b $TRAVIS_BRANCH
- git clone https://github.com/musicdsp/audio-algo-drain.git -b $TRAVIS_BRANCH
- git clone https://github.com/musicdsp/audio-algo-river.git -b $TRAVIS_BRANCH
- git clone https://github.com/musicdsp/audio-algo-speex.git -b $TRAVIS_BRANCH
- git clone https://github.com/musicdsp/audio-drain.git -b $TRAVIS_BRANCH
- git clone https://github.com/musicdsp/audio-orchestra.git -b $TRAVIS_BRANCH
- git clone https://github.com/generic-library/gtest-lutin.git --recursive - git clone https://github.com/generic-library/gtest-lutin.git --recursive
- git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
- git clone https://github.com/generic-library/z-lutin.git --recursive - git clone https://github.com/generic-library/z-lutin.git --recursive
- git clone https://github.com/atria-soft/etk.git - git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
- git clone https://github.com/atria-soft/ejson.git
- git clone https://github.com/musicdsp/audio.git
- git clone https://github.com/musicdsp/audio-algo-drain.git
- git clone https://github.com/musicdsp/audio-drain.git
- git clone https://github.com/musicdsp/audio-orchestra.git
- pwd - pwd
- ls -l - ls -l
- if [ "$BUILDER" == "gcc" ]; then COMPILATOR_OPTION="--compilator-version=4.9"; else COMPILATOR_OPTION=""; fi - if [ "$TRAVIS_OS_NAME" == "osx" ]; then
export PATH=$PATH:/Users/travis/Library/Python/2.7/bin/;
fi
- ./ci/build_send.py --tag=$TAG --status=START;
script: script:
- lutin -w -j4 -C -P -c $BUILDER $COMPILATOR_OPTION -m $CONF $GCOV -p audio-river-test - lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE audio-river-test*; STATUS=$?
# - ./out/Linux_x86_64/$CONF/staging/$BUILDER/audio-river-test/usr/bin/audio-river-test -l6 - ./ci/build_send.py --tag=$TAG --status="$STATUS";
after_script:
- if [ "$GCOV" != "" ]; then
./ci/warning_send.py --find-path ./out/Linux_x86_64/$CONF/build/$BUILDER/audio-river/;
fi
#- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE audio-river-test?run:--elog-level=3 | tee out_test.txt
#- if [ "$GCOV" != "" ]; then
# ./ci/test_send.py --file=out_test.txt;
# lutin -C -P -t $TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF -p audio-river?gcov;
# ./ci/coverage_send.py --json=out/Linux_x86_64/$CONF/build/$BUILDER/audio-river/audio-river_coverage.json;
# fi
notifications: notifications:
email: email:

View File

@@ -1,4 +1,88 @@
# audio-river audio-river
(APACHE v2.0) audio: virtualisation of hardware interface =====
`audio-river` is a High level hardware audio interface that connect to orchestra (multi-platform backend)
Release (master)
----------------
[![Build Status](https://travis-ci.org/musicdsp/audio-river.svg?branch=master)](https://travis-ci.org/musicdsp/audio-river) [![Build Status](https://travis-ci.org/musicdsp/audio-river.svg?branch=master)](https://travis-ci.org/musicdsp/audio-river)
[![Coverage Status](http://musicdsp.com/ci/coverage/musicdsp/audio-river.svg?branch=master)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Test Status](http://musicdsp.com/ci/test/musicdsp/audio-river.svg?branch=master)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Warning Status](http://musicdsp.com/ci/warning/musicdsp/audio-river.svg?branch=master)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=Linux)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=MacOs)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=Mingw)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=Android)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=IOs)](http://musicdsp.com/ci/musicdsp/audio-river)
Developement (dev)
------------------
[![Build Status](https://travis-ci.org/musicdsp/audio-river.svg?branch=dev)](https://travis-ci.org/musicdsp/audio-river)
[![Coverage Status](http://musicdsp.com/ci/coverage/musicdsp/audio-river.svg?branch=dev)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Test Status](http://musicdsp.com/ci/test/musicdsp/audio-river.svg?branch=dev)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Warning Status](http://musicdsp.com/ci/warning/musicdsp/audio-river.svg?branch=dev)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=Linux)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=MacOs)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=Mingw)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=Android)](http://musicdsp.com/ci/musicdsp/audio-river)
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=IOs)](http://musicdsp.com/ci/musicdsp/audio-river)
Instructions
============
download Build system:
----------------------
sudo pip install lutin
sudo pip install pillow
download the software:
----------------------
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
git clone https://github.com/atria-soft/etk.git
git clone https://github.com/atria-soft/elog.git
git clone https://github.com/atria-soft/ememory.git
git clone https://github.com/atria-soft/ethread.git
git clone https://github.com/atria-soft/ejson.git
git clone https://github.com/musicdsp/audio.git
git clone https://github.com/musicdsp/audio-algo-drain.git
git clone https://github.com/musicdsp/audio-algo-river.git
git clone https://github.com/musicdsp/audio-algo-speex.git
git clone https://github.com/musicdsp/audio-drain.git
git clone https://github.com/musicdsp/audio-orchestra.git
git clone https://github.com/musicdsp/audio-river.git
git clone https://github.com/generic-library/gtest-lutin.git --recursive
git clone https://github.com/generic-library/z-lutin.git --recursive
git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
Compile software:
-----------------
cd WORKING_DIRECTORY
lutin -C -P audio-river-test?build?run
License (APACHE v2.0)
=====================
Copyright audio-river Edouard DUPIN
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -4,17 +4,13 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include "debug.h" #include "debug.hpp"
#include "Interface.h" #include "Interface.hpp"
#include "io/Node.h" #include "io/Node.hpp"
#include <audio/drain/EndPointCallback.h> #include <audio/drain/EndPointCallback.hpp>
#include <audio/drain/EndPointWrite.h> #include <audio/drain/EndPointWrite.hpp>
#include <audio/drain/EndPointRead.h> #include <audio/drain/EndPointRead.hpp>
#include <audio/drain/Volume.h> #include <audio/drain/Volume.hpp>
#undef __class__
#define __class__ "Interface"
audio::river::Interface::Interface(void) : audio::river::Interface::Interface(void) :
m_node(), m_node(),
@@ -27,13 +23,13 @@ audio::river::Interface::Interface(void) :
bool audio::river::Interface::init(float _freq, bool audio::river::Interface::init(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<audio::river::io::Node>& _node, ememory::SharedPtr<audio::river::io::Node> _node,
const std::shared_ptr<const ejson::Object>& _config) { const ejson::Object& _config) {
std::vector<audio::channel> map(_map); std::vector<audio::channel> map(_map);
m_node = _node; m_node = _node;
m_config = _config; m_config = _config;
m_mode = audio::river::modeInterface_unknow; m_mode = audio::river::modeInterface_unknow;
std::string type = m_config->getStringValue("io", "error"); std::string type = m_config["io"].toString().get("error");
static int32_t uid=0; static int32_t uid=0;
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::to_string(uid++); m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::to_string(uid++);
if (type == "output") { if (type == "output") {
@@ -44,7 +40,7 @@ bool audio::river::Interface::init(float _freq,
m_mode = audio::river::modeInterface_feedback; m_mode = audio::river::modeInterface_feedback;
} }
// register interface to be notify from the volume change. // register interface to be notify from the volume change.
m_node->registerAsRemote(shared_from_this()); m_node->registerAsRemote(sharedFromThis());
if (map.size() == 0) { if (map.size() == 0) {
RIVER_INFO("Select auto map system ..."); RIVER_INFO("Select auto map system ...");
@@ -57,10 +53,10 @@ bool audio::river::Interface::init(float _freq,
&& m_mode == audio::river::modeInterface_input) { && m_mode == audio::river::modeInterface_input) {
m_process.setInputConfig(m_node->getInterfaceFormat()); m_process.setInputConfig(m_node->getInterfaceFormat());
// Add volume only if the Low level has a volume (otherwise it will be added by the application) // Add volume only if the Low level has a volume (otherwise it will be added by the application)
std::shared_ptr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume(); ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
if (tmpVolume != nullptr) { if (tmpVolume != nullptr) {
// add all time the volume stage : // add all time the volume stage :
std::shared_ptr<audio::drain::Volume> algo = audio::drain::Volume::create(); ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
//algo->setInputFormat(m_node->getInterfaceFormat()); //algo->setInputFormat(m_node->getInterfaceFormat());
algo->setName("volume"); algo->setName("volume");
m_process.pushBack(algo); m_process.pushBack(algo);
@@ -72,10 +68,10 @@ bool audio::river::Interface::init(float _freq,
&& m_mode == audio::river::modeInterface_output) { && m_mode == audio::river::modeInterface_output) {
m_process.setInputConfig(audio::drain::IOFormatInterface(map, _format, _freq)); m_process.setInputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
// Add volume only if the Low level has a volume (otherwise it will be added by the application) // Add volume only if the Low level has a volume (otherwise it will be added by the application)
std::shared_ptr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume(); ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
if (tmpVolume != nullptr) { if (tmpVolume != nullptr) {
// add all time the volume stage : // add all time the volume stage :
std::shared_ptr<audio::drain::Volume> algo = audio::drain::Volume::create(); ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
//algo->setOutputFormat(m_node->getInterfaceFormat()); //algo->setOutputFormat(m_node->getInterfaceFormat());
algo->setName("volume"); algo->setName("volume");
m_process.pushBack(algo); m_process.pushBack(algo);
@@ -95,12 +91,12 @@ bool audio::river::Interface::init(float _freq,
return true; return true;
} }
std::shared_ptr<audio::river::Interface> audio::river::Interface::create(float _freq, ememory::SharedPtr<audio::river::Interface> audio::river::Interface::create(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<audio::river::io::Node>& _node, const ememory::SharedPtr<audio::river::io::Node>& _node,
const std::shared_ptr<const ejson::Object>& _config) { const ejson::Object& _config) {
std::shared_ptr<audio::river::Interface> out = std::shared_ptr<audio::river::Interface>(new audio::river::Interface()); ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(new audio::river::Interface());
out->init(_freq, _map, _format, _node, _config); out->init(_freq, _map, _format, _node, _config);
return out; return out;
} }
@@ -108,7 +104,7 @@ std::shared_ptr<audio::river::Interface> audio::river::Interface::create(float _
audio::river::Interface::~Interface() { audio::river::Interface::~Interface() {
//stop(true, true); //stop(true, true);
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
//m_node->interfaceRemove(shared_from_this()); //m_node->interfaceRemove(sharedFromThis());
} }
/* /*
bool audio::river::Interface::hasEndPoint() { bool audio::river::Interface::hasEndPoint() {
@@ -124,11 +120,11 @@ void audio::river::Interface::setReadwrite() {
} }
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
m_process.removeIfLast<audio::drain::EndPoint>(); m_process.removeIfLast<audio::drain::EndPoint>();
std::shared_ptr<audio::drain::EndPointRead> algo = audio::drain::EndPointRead::create(); ememory::SharedPtr<audio::drain::EndPointRead> algo = audio::drain::EndPointRead::create();
m_process.pushBack(algo); m_process.pushBack(algo);
} else { } else {
m_process.removeIfFirst<audio::drain::EndPoint>(); m_process.removeIfFirst<audio::drain::EndPoint>();
std::shared_ptr<audio::drain::EndPointWrite> algo = audio::drain::EndPointWrite::create(); ememory::SharedPtr<audio::drain::EndPointWrite> algo = audio::drain::EndPointWrite::create();
m_process.pushFront(algo); m_process.pushFront(algo);
} }
} }
@@ -141,7 +137,7 @@ void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _
} }
m_process.removeAlgoDynamic(); m_process.removeAlgoDynamic();
m_process.removeIfFirst<audio::drain::EndPoint>(); m_process.removeIfFirst<audio::drain::EndPoint>();
std::shared_ptr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function); ememory::SharedPtr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function);
m_process.pushFront(algo); m_process.pushFront(algo);
} }
@@ -153,7 +149,7 @@ void audio::river::Interface::setInputCallback(audio::drain::recordFunction _fun
} }
m_process.removeAlgoDynamic(); m_process.removeAlgoDynamic();
m_process.removeIfLast<audio::drain::EndPoint>(); m_process.removeIfLast<audio::drain::EndPoint>();
std::shared_ptr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function); ememory::SharedPtr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function);
m_process.pushBack(algo); m_process.pushBack(algo);
} }
@@ -164,7 +160,7 @@ void audio::river::Interface::setWriteCallback(audio::drain::playbackFunctionWri
return; return;
} }
m_process.removeAlgoDynamic(); m_process.removeAlgoDynamic();
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
return; return;
} }
@@ -175,14 +171,14 @@ void audio::river::Interface::start(const audio::Time& _time) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("start [BEGIN]"); RIVER_DEBUG("start [BEGIN]");
m_process.updateInterAlgo(); m_process.updateInterAlgo();
m_node->interfaceAdd(shared_from_this()); m_node->interfaceAdd(sharedFromThis());
RIVER_DEBUG("start [ END ]"); RIVER_DEBUG("start [ END ]");
} }
void audio::river::Interface::stop(bool _fast, bool _abort) { void audio::river::Interface::stop(bool _fast, bool _abort) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("stop [BEGIN]"); RIVER_DEBUG("stop [BEGIN]");
m_node->interfaceRemove(shared_from_this()); m_node->interfaceRemove(sharedFromThis());
RIVER_DEBUG("stop [ END]"); RIVER_DEBUG("stop [ END]");
} }
@@ -201,7 +197,7 @@ bool audio::river::Interface::setParameter(const std::string& _filter, const std
RIVER_ERROR("Interface is not allowed to modify '" << _parameter << "' Volume just allowed to modify 'FLOW' volume"); RIVER_ERROR("Interface is not allowed to modify '" << _parameter << "' Volume just allowed to modify 'FLOW' volume");
return false; return false;
} }
std::shared_ptr<audio::drain::Algo> algo = m_process.get<audio::drain::Algo>(_filter); ememory::SharedPtr<audio::drain::Algo> algo = m_process.get<audio::drain::Algo>(_filter);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ..."); RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return false; return false;
@@ -213,7 +209,7 @@ bool audio::river::Interface::setParameter(const std::string& _filter, const std
std::string audio::river::Interface::getParameter(const std::string& _filter, const std::string& _parameter) const { std::string audio::river::Interface::getParameter(const std::string& _filter, const std::string& _parameter) const {
RIVER_DEBUG("getParameter [BEGIN] : '" << _filter << "':'" << _parameter << "'"); RIVER_DEBUG("getParameter [BEGIN] : '" << _filter << "':'" << _parameter << "'");
std::string out; std::string out;
std::shared_ptr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter); ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ..."); RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return "[ERROR]"; return "[ERROR]";
@@ -225,7 +221,7 @@ std::string audio::river::Interface::getParameter(const std::string& _filter, co
std::string audio::river::Interface::getParameterProperty(const std::string& _filter, const std::string& _parameter) const { std::string audio::river::Interface::getParameterProperty(const std::string& _filter, const std::string& _parameter) const {
RIVER_DEBUG("getParameterProperty [BEGIN] : '" << _filter << "':'" << _parameter << "'"); RIVER_DEBUG("getParameterProperty [BEGIN] : '" << _filter << "':'" << _parameter << "'");
std::string out; std::string out;
std::shared_ptr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter); ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ..."); RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return "[ERROR]"; return "[ERROR]";
@@ -238,7 +234,7 @@ std::string audio::river::Interface::getParameterProperty(const std::string& _fi
void audio::river::Interface::write(const void* _value, size_t _nbChunk) { void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
m_process.updateInterAlgo(); m_process.updateInterAlgo();
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
return; return;
} }
@@ -256,7 +252,7 @@ std::vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
int32_t nbChunkBuffer = m_circularBuffer.size() / m_map.size(); int32_t nbChunkBuffer = m_circularBuffer.size() / m_map.size();
m_mutex.unlock(); m_mutex.unlock();
while (nbChunkBuffer < _nbChunk) { while (nbChunkBuffer < _nbChunk) {
usleep(1000); std::this_thread::sleep_for(std::chrono::milliseconds(1));
nbChunkBuffer = m_circularBuffer.size() / m_map.size(); nbChunkBuffer = m_circularBuffer.size() / m_map.size();
} }
m_mutex.lock(); m_mutex.lock();
@@ -290,7 +286,7 @@ size_t audio::river::Interface::size() const {
void audio::river::Interface::setBufferSize(size_t _nbChunk) { void audio::river::Interface::setBufferSize(size_t _nbChunk) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
std::shared_ptr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1); ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return; return;
@@ -298,7 +294,7 @@ void audio::river::Interface::setBufferSize(size_t _nbChunk) {
algo->setBufferSize(_nbChunk); algo->setBufferSize(_nbChunk);
return; return;
} }
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return; return;
@@ -309,7 +305,7 @@ void audio::river::Interface::setBufferSize(size_t _nbChunk) {
void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _time) { void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _time) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
std::shared_ptr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1); ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return; return;
@@ -317,7 +313,7 @@ void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _ti
algo->setBufferSize(_time); algo->setBufferSize(_time);
return; return;
} }
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return; return;
@@ -328,14 +324,14 @@ void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _ti
size_t audio::river::Interface::getBufferSize() { size_t audio::river::Interface::getBufferSize() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
std::shared_ptr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1); ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0; return 0;
} }
return algo->getBufferSize(); return algo->getBufferSize();
} }
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0; return 0;
@@ -346,14 +342,14 @@ size_t audio::river::Interface::getBufferSize() {
std::chrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() { std::chrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
std::shared_ptr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1); ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return std::chrono::microseconds(0); return std::chrono::microseconds(0);
} }
return algo->getBufferSizeMicrosecond(); return algo->getBufferSizeMicrosecond();
} }
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return std::chrono::microseconds(0); return std::chrono::microseconds(0);
@@ -364,14 +360,14 @@ std::chrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
size_t audio::river::Interface::getBufferFillSize() { size_t audio::river::Interface::getBufferFillSize() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
std::shared_ptr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1); ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0; return 0;
} }
return algo->getBufferFillSize(); return algo->getBufferFillSize();
} }
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0; return 0;
@@ -383,14 +379,14 @@ size_t audio::river::Interface::getBufferFillSize() {
std::chrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() { std::chrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) { if (m_node->isInput() == true) {
std::shared_ptr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1); ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return std::chrono::microseconds(0); return std::chrono::microseconds(0);
} }
return algo->getBufferFillSizeMicrosecond(); return algo->getBufferFillSizeMicrosecond();
} }
std::shared_ptr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0); ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == nullptr) { if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ..."); RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return std::chrono::microseconds(0); return std::chrono::microseconds(0);
@@ -417,7 +413,7 @@ audio::Time audio::river::Interface::getCurrentTime() const {
void audio::river::Interface::addVolumeGroup(const std::string& _name) { void audio::river::Interface::addVolumeGroup(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("addVolumeGroup(" << _name << ")"); RIVER_DEBUG("addVolumeGroup(" << _name << ")");
std::shared_ptr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume"); ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
if (algo == nullptr) { if (algo == nullptr) {
m_process.removeAlgoDynamic(); m_process.removeAlgoDynamic();
// add all time the volume stage : // add all time the volume stage :
@@ -431,10 +427,10 @@ void audio::river::Interface::addVolumeGroup(const std::string& _name) {
} }
if (_name == "FLOW") { if (_name == "FLOW") {
// Local volume name // Local volume name
algo->addVolumeStage(std::make_shared<audio::drain::VolumeElement>(_name)); algo->addVolumeStage(ememory::makeShared<audio::drain::VolumeElement>(_name));
} else { } else {
// get manager unique instance: // get manager unique instance:
std::shared_ptr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
algo->addVolumeStage(mng->getVolumeGroup(_name)); algo->addVolumeStage(mng->getVolumeGroup(_name));
} }
} }
@@ -453,7 +449,7 @@ void audio::river::Interface::systemNeedOutputData(audio::Time _time, void* _dat
void audio::river::Interface::systemVolumeChange() { void audio::river::Interface::systemVolumeChange() {
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex); std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
std::shared_ptr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume"); ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
if (algo == nullptr) { if (algo == nullptr) {
return; return;
} }

View File

@@ -7,19 +7,19 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h> #include <cstdint>
#include <mutex> #include <mutex>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <memory> #include <ememory/memory.hpp>
#include <audio/format.h> #include <audio/format.hpp>
#include <audio/channel.h> #include <audio/channel.hpp>
#include <audio/drain/Process.h> #include <audio/drain/Process.hpp>
#include <audio/drain/EndPointCallback.h> #include <audio/drain/EndPointCallback.hpp>
#include <audio/drain/EndPointWrite.h> #include <audio/drain/EndPointWrite.hpp>
#include <ejson/ejson.h> #include <ejson/ejson.hpp>
#include <etk/os/FSNode.h> #include <etk/os/FSNode.hpp>
#include <audio/Time.h> #include <audio/Time.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -39,7 +39,7 @@ namespace audio {
* @brief Interface is the basic handle to manage the input output stream * @brief Interface is the basic handle to manage the input output stream
* @note To create this class see @ref audio::river::Manager class * @note To create this class see @ref audio::river::Manager class
*/ */
class Interface : public std::enable_shared_from_this<Interface> { class Interface : public ememory::EnableSharedFromThis<Interface> {
friend class io::Node; friend class io::Node;
friend class io::NodeAirTAudio; friend class io::NodeAirTAudio;
friend class io::NodeAEC; friend class io::NodeAEC;
@@ -65,8 +65,8 @@ namespace audio {
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 std::shared_ptr<audio::river::io::Node>& _node, ememory::SharedPtr<audio::river::io::Node> _node,
const std::shared_ptr<const ejson::Object>& _config); const ejson::Object& _config);
/** /**
* @brief Factory of this interface (called by class audio::river::Manager) * @brief Factory of this interface (called by class audio::river::Manager)
* @param[in] _freq Frequency. * @param[in] _freq Frequency.
@@ -77,11 +77,11 @@ namespace audio {
* @return nullptr The configuration does not work. * @return nullptr The configuration does not work.
* @return pointer The interface has been corectly created. * @return pointer The interface has been corectly created.
*/ */
static std::shared_ptr<Interface> create(float _freq, static ememory::SharedPtr<Interface> create(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::shared_ptr<audio::river::io::Node>& _node, const ememory::SharedPtr<audio::river::io::Node>& _node,
const std::shared_ptr<const ejson::Object>& _config); const ejson::Object& _config);
public: public:
/** /**
* @brief Destructor * @brief Destructor
@@ -89,7 +89,7 @@ namespace audio {
virtual ~Interface(); virtual ~Interface();
protected: protected:
mutable std::recursive_mutex m_mutex; //!< Local mutex to protect data mutable std::recursive_mutex m_mutex; //!< Local mutex to protect data
std::shared_ptr<const ejson::Object> m_config; //!< configuration set by the user. ejson::Object m_config; //!< configuration set by the user.
protected: protected:
enum modeInterface m_mode; //!< interface type (input/output/feedback) enum modeInterface m_mode; //!< interface type (input/output/feedback)
public: public:
@@ -116,7 +116,7 @@ namespace audio {
} }
} }
protected: protected:
std::shared_ptr<audio::river::io::Node> m_node; //!< Hardware interface to/from stream audio flow. ememory::SharedPtr<audio::river::io::Node> m_node; //!< Hardware interface to/from stream audio flow.
protected: protected:
std::string m_name; //!< Name of the interface. std::string m_name; //!< Name of the interface.
public: public:

View File

@@ -4,24 +4,22 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include "Manager.h" #include "Manager.hpp"
#include "Interface.h" #include "Interface.hpp"
#include <stdexcept> #include <stdexcept>
#include "io/Manager.h" #include "io/Manager.hpp"
#include "io/Node.h" #include "io/Node.hpp"
#include "debug.h" #include "debug.hpp"
#include <ejson/ejson.h> #include <ejson/ejson.hpp>
#undef __class__
#define __class__ "Manager"
static std::mutex g_mutex; static std::mutex g_mutex;
static std::vector<std::weak_ptr<audio::river::Manager> > g_listOfAllManager; static std::vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
std::shared_ptr<audio::river::Manager> audio::river::Manager::create(const std::string& _applicationUniqueId) { ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const std::string& _applicationUniqueId) {
std::unique_lock<std::mutex> lock(g_mutex); std::unique_lock<std::mutex> lock(g_mutex);
for (size_t iii=0; iii<g_listOfAllManager.size() ; ++iii) { for (size_t iii=0; iii<g_listOfAllManager.size() ; ++iii) {
std::shared_ptr<audio::river::Manager> tmp = g_listOfAllManager[iii].lock(); ememory::SharedPtr<audio::river::Manager> tmp = g_listOfAllManager[iii].lock();
if (tmp == nullptr) { if (tmp == nullptr) {
continue; continue;
} }
@@ -30,7 +28,7 @@ std::shared_ptr<audio::river::Manager> audio::river::Manager::create(const std::
} }
} }
// create a new one: // create a new one:
std::shared_ptr<audio::river::Manager> out = std::shared_ptr<audio::river::Manager>(new audio::river::Manager(_applicationUniqueId)); ememory::SharedPtr<audio::river::Manager> out = ememory::SharedPtr<audio::river::Manager>(new audio::river::Manager(_applicationUniqueId));
// add it at the list: // add it at the list:
for (size_t iii=0; iii<g_listOfAllManager.size() ; ++iii) { for (size_t iii=0; iii<g_listOfAllManager.size() ; ++iii) {
if (g_listOfAllManager[iii].expired() == true) { if (g_listOfAllManager[iii].expired() == true) {
@@ -55,7 +53,7 @@ audio::river::Manager::~Manager() {
std::vector<std::string> audio::river::Manager::getListStreamInput() { std::vector<std::string> audio::river::Manager::getListStreamInput() {
std::vector<std::string> output; std::vector<std::string> output;
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
} else { } else {
@@ -66,7 +64,7 @@ std::vector<std::string> audio::river::Manager::getListStreamInput() {
std::vector<std::string> audio::river::Manager::getListStreamOutput() { std::vector<std::string> audio::river::Manager::getListStreamOutput() {
std::vector<std::string> output; std::vector<std::string> output;
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
} else { } else {
@@ -77,7 +75,7 @@ std::vector<std::string> audio::river::Manager::getListStreamOutput() {
std::vector<std::string> audio::river::Manager::getListStreamVirtual() { std::vector<std::string> audio::river::Manager::getListStreamVirtual() {
std::vector<std::string> output; std::vector<std::string> output;
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
} else { } else {
@@ -88,7 +86,7 @@ std::vector<std::string> audio::river::Manager::getListStreamVirtual() {
std::vector<std::string> audio::river::Manager::getListStream() { std::vector<std::string> audio::river::Manager::getListStream() {
std::vector<std::string> output; std::vector<std::string> output;
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
} else { } else {
@@ -98,7 +96,7 @@ std::vector<std::string> audio::river::Manager::getListStream() {
} }
bool audio::river::Manager::setVolume(const std::string& _volumeName, float _valuedB) { bool audio::river::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return false; return false;
@@ -107,7 +105,7 @@ bool audio::river::Manager::setVolume(const std::string& _volumeName, float _val
} }
float audio::river::Manager::getVolume(const std::string& _volumeName) const { float audio::river::Manager::getVolume(const std::string& _volumeName) const {
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return false; return false;
@@ -116,7 +114,7 @@ float audio::river::Manager::getVolume(const std::string& _volumeName) const {
} }
std::pair<float,float> audio::river::Manager::getVolumeRange(const std::string& _volumeName) const { std::pair<float,float> audio::river::Manager::getVolumeRange(const std::string& _volumeName) const {
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return std::make_pair<float,float>(0.0f,0.0f); return std::make_pair<float,float>(0.0f,0.0f);
@@ -125,7 +123,7 @@ std::pair<float,float> audio::river::Manager::getVolumeRange(const std::string&
} }
void audio::river::Manager::setMute(const std::string& _volumeName, bool _mute) { void audio::river::Manager::setMute(const std::string& _volumeName, bool _mute) {
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return; return;
@@ -134,7 +132,7 @@ void audio::river::Manager::setMute(const std::string& _volumeName, bool _mute)
} }
bool audio::river::Manager::getMute(const std::string& _volumeName) const { bool audio::river::Manager::getMute(const std::string& _volumeName) const {
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return false; return false;
@@ -142,62 +140,62 @@ bool audio::river::Manager::getMute(const std::string& _volumeName) const {
return manager->getMute(_volumeName); return manager->getMute(_volumeName);
} }
std::shared_ptr<audio::river::Interface> audio::river::Manager::createOutput(float _freq, ememory::SharedPtr<audio::river::Interface> audio::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& _options) { const std::string& _options) {
// get global hardware interface: // get global hardware interface:
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// get the output or input channel : // get the output or input channel :
std::shared_ptr<audio::river::io::Node> node = manager->getNode(_streamName); ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(_streamName);
if (node == nullptr) { if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream()); RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
if (node->isOutput() != true) { if (node->isOutput() != true) {
RIVER_ERROR("Can not Connect output on other thing than output ... for stream '" << _streamName << "'");; RIVER_ERROR("Can not Connect output on other thing than output ... for stream '" << _streamName << "'");;
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// create user iterface: // create user iterface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
std::shared_ptr<ejson::Object> tmpOption = ejson::Object::create(_options); ejson::Object tmpOption = ejson::Object(_options);
tmpOption->addString("io", "output"); tmpOption.add("io", ejson::String("output"));
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption); interface = audio::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;
} }
std::shared_ptr<audio::river::Interface> audio::river::Manager::createInput(float _freq, ememory::SharedPtr<audio::river::Interface> audio::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& _options) { const std::string& _options) {
// get global hardware interface: // get global hardware interface:
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// get the output or input channel : // get the output or input channel :
std::shared_ptr<audio::river::io::Node> node = manager->getNode(_streamName); ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(_streamName);
if (node == nullptr) { if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream()); RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
if (node->isInput() != true) { if (node->isInput() != true) {
RIVER_ERROR("Can not Connect input on other thing than input ... for stream '" << _streamName << "'");; RIVER_ERROR("Can not Connect input on other thing than input ... for stream '" << _streamName << "'");;
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// create user iterface: // create user iterface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
std::shared_ptr<ejson::Object> tmpOption = ejson::Object::create(_options); ejson::Object tmpOption = ejson::Object(_options);
tmpOption->addString("io", "input"); tmpOption.add("io", ejson::String("input"));
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption); interface = audio::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);
@@ -205,31 +203,31 @@ std::shared_ptr<audio::river::Interface> audio::river::Manager::createInput(floa
} }
std::shared_ptr<audio::river::Interface> audio::river::Manager::createFeedback(float _freq, ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createFeedback(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& _options) { const std::string& _options) {
// get global hardware interface: // get global hardware interface:
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... "); RIVER_ERROR("Unable to load harware IO manager ... ");
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// get the output or input channel : // get the output or input channel :
std::shared_ptr<audio::river::io::Node> node = manager->getNode(_streamName); ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(_streamName);
if (node == nullptr) { if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream()); RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
if (node->isOutput() != true) { if (node->isOutput() != true) {
RIVER_ERROR("Can not Connect feedback on other thing than output ... for stream '" << _streamName << "'");; RIVER_ERROR("Can not Connect feedback on other thing than output ... for stream '" << _streamName << "'");;
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// create user iterface: // create user iterface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
std::shared_ptr<ejson::Object> tmpOption = ejson::Object::create(_options); ejson::Object tmpOption = ejson::Object(_options);
tmpOption->addString("io", "feedback"); tmpOption.add("io", ejson::String("feedback"));
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption); interface = audio::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);
@@ -238,7 +236,7 @@ std::shared_ptr<audio::river::Interface> audio::river::Manager::createFeedback(f
void audio::river::Manager::generateDotAll(const std::string& _filename) { void audio::river::Manager::generateDotAll(const std::string& _filename) {
// get global hardware interface: // get global hardware interface:
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == nullptr) { if (manager == nullptr) {
RIVER_ERROR("Can not get the harware manager"); RIVER_ERROR("Can not get the harware manager");
return; return;

View File

@@ -6,22 +6,22 @@
#pragma once #pragma once
#include <string> #include <string>
#include <stdint.h> #include <cstdint>
#include <memory> #include <ememory/memory.hpp>
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <audio/format.h> #include <audio/format.hpp>
#include <audio/channel.h> #include <audio/channel.hpp>
#include <ejson/ejson.h> #include <ejson/ejson.hpp>
namespace audio { namespace audio {
namespace river { 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 : public std::enable_shared_from_this<Manager> { class Manager : public ememory::EnableSharedFromThis<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<std::weak_ptr<audio::river::Interface> > m_listOpenInterface; //!< List of all open Stream. std::vector<ememory::WeakPtr<audio::river::Interface> > m_listOpenInterface; //!< List of all open Stream.
protected: protected:
/** /**
* @brief Constructor * @brief Constructor
@@ -33,7 +33,7 @@ namespace audio {
* @param[in] _applicationUniqueId Unique name of the application * @param[in] _applicationUniqueId Unique name of the application
* @return Pointer on the manager or nullptr if an error occured * @return Pointer on the manager or nullptr if an error occured
*/ */
static std::shared_ptr<audio::river::Manager> create(const std::string& _applicationUniqueId); static ememory::SharedPtr<audio::river::Manager> create(const std::string& _applicationUniqueId);
/** /**
* @brief Destructor * @brief Destructor
*/ */
@@ -106,7 +106,7 @@ namespace audio {
* @param[in] _options Json option to configure default resampling and many other things. * @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 std::shared_ptr<Interface> createOutput(float _freq = 48000, virtual ememory::SharedPtr<Interface> createOutput(float _freq = 48000,
const std::vector<audio::channel>& _map = std::vector<audio::channel>(), const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16, audio::format _format = audio::format_int16,
const std::string& _streamName = "", const std::string& _streamName = "",
@@ -120,7 +120,7 @@ namespace audio {
* @param[in] _options Json option to configure default resampling and many other things. * @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 std::shared_ptr<Interface> createInput(float _freq = 48000, virtual ememory::SharedPtr<Interface> createInput(float _freq = 48000,
const std::vector<audio::channel>& _map = std::vector<audio::channel>(), const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16, audio::format _format = audio::format_int16,
const std::string& _streamName = "", const std::string& _streamName = "",
@@ -134,7 +134,7 @@ namespace audio {
* @param[in] _options Json option to configure default resampling and many other things. * @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 std::shared_ptr<Interface> createFeedback(float _freq = 48000, virtual ememory::SharedPtr<Interface> createFeedback(float _freq = 48000,
const std::vector<audio::channel>& _map = std::vector<audio::channel>(), const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16, audio::format _format = audio::format_int16,
const std::string& _streamName = "", const std::string& _streamName = "",

View File

@@ -4,7 +4,7 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
int32_t audio::river::getLogId() { int32_t audio::river::getLogId() {

View File

@@ -5,7 +5,7 @@
*/ */
#pragma once #pragma once
#include <elog/log.h> #include <elog/log.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -14,6 +14,7 @@ namespace audio {
} }
#define RIVER_BASE(info,data) ELOG_BASE(audio::river::getLogId(),info,data) #define RIVER_BASE(info,data) ELOG_BASE(audio::river::getLogId(),info,data)
#define RIVER_PRINT(data) RIVER_BASE(-1, data)
#define RIVER_CRITICAL(data) RIVER_BASE(1, data) #define RIVER_CRITICAL(data) RIVER_BASE(1, data)
#define RIVER_ERROR(data) RIVER_BASE(2, data) #define RIVER_ERROR(data) RIVER_BASE(2, data)
#define RIVER_WARNING(data) RIVER_BASE(3, data) #define RIVER_WARNING(data) RIVER_BASE(3, data)

View File

@@ -4,42 +4,39 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/io/Group.h> #include <audio/river/io/Group.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include "Node.h" #include "Node.hpp"
#include "NodeAEC.h" #include "NodeAEC.hpp"
#include "NodeOrchestra.h" #include "NodeOrchestra.hpp"
#include "NodePortAudio.h" #include "NodePortAudio.hpp"
#include "Node.h" #include "Node.hpp"
#undef __class__
#define __class__ "io::Group"
void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std::string& _name) { void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std::string& _name) {
RIVER_INFO("Create Group[" << _name << "] (START) ___________________________"); RIVER_INFO("Create Group[" << _name << "] (START) ___________________________");
for (size_t iii=0; iii<_obj.size(); ++iii) { for (size_t iii=0; iii<_obj.size(); ++iii) {
const std::shared_ptr<const ejson::Object> tmpObject = _obj.getObject(_obj.getKey(iii)); const ejson::Object tmpObject = _obj[iii].toObject();
if (tmpObject == nullptr) { if (tmpObject.exist() == false) {
continue; continue;
} }
std::string groupName = tmpObject->getStringValue("group", ""); std::string groupName = tmpObject["group"].toString().get();
if (groupName == _name) { if (groupName == _name) {
RIVER_INFO("Add element in Group[" << _name << "]: " << _obj.getKey(iii)); RIVER_INFO("Add element in Group[" << _name << "]: " << _obj.getKey(iii));
// get type : io // get type : io
std::string ioType = tmpObject->getStringValue("io", "error"); std::string ioType = tmpObject["io"].toString().get("error");
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA #ifdef AUDIO_RIVER_BUILD_ORCHESTRA
if ( ioType == "input" if ( ioType == "input"
|| ioType == "output") { || ioType == "output") {
std::shared_ptr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_obj.getKey(iii), tmpObject); ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_obj.getKey(iii), tmpObject);
tmp->setGroup(shared_from_this()); tmp->setGroup(sharedFromThis());
m_list.push_back(tmp); m_list.push_back(tmp);
} }
#endif #endif
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO #ifdef AUDIO_RIVER_BUILD_PORTAUDIO
if ( ioType == "PAinput" if ( ioType == "PAinput"
|| ioType == "PAoutput") { || ioType == "PAoutput") {
std::shared_ptr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_obj.getKey(iii), tmpObject); ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_obj.getKey(iii), tmpObject);
tmp->setGroup(shared_from_this()); tmp->setGroup(sharedFromThis());
m_list.push_back(tmp); m_list.push_back(tmp);
} }
#endif #endif
@@ -49,10 +46,10 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std:
// Note : The interlink work only for alsa (NOW) and with AirTAudio... // Note : The interlink work only for alsa (NOW) and with AirTAudio...
if(m_list.size() > 1) { if(m_list.size() > 1) {
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA #ifdef AUDIO_RIVER_BUILD_ORCHESTRA
std::shared_ptr<audio::river::io::NodeOrchestra> linkRef = std::dynamic_pointer_cast<audio::river::io::NodeOrchestra>(m_list[0]); ememory::SharedPtr<audio::river::io::NodeOrchestra> linkRef = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_list[0]);
for (size_t iii=1; iii<m_list.size(); ++iii) { for (size_t iii=1; iii<m_list.size(); ++iii) {
if (m_list[iii] != nullptr) { if (m_list[iii] != nullptr) {
std::shared_ptr<audio::river::io::NodeOrchestra> link = std::dynamic_pointer_cast<audio::river::io::NodeOrchestra>(m_list[iii]); ememory::SharedPtr<audio::river::io::NodeOrchestra> link = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_list[iii]);
linkRef->m_interface.isMasterOf(link->m_interface); linkRef->m_interface.isMasterOf(link->m_interface);
} }
} }
@@ -62,7 +59,7 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std:
// manage Link Between Nodes : // manage Link Between Nodes :
if (m_link != nullptr) { if (m_link != nullptr) {
RIVER_INFO("******** START LINK ************"); RIVER_INFO("******** START LINK ************");
std::shared_ptr<audio::river::io::NodeOrchestra> link = std::dynamic_pointer_cast<audio::river::io::NodeOrchestra>(m_link); ememory::SharedPtr<audio::river::io::NodeOrchestra> link = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_link);
if (link == nullptr) { if (link == nullptr) {
RIVER_ERROR("Can not link 2 Interface with not the same type (reserved for HW interface)"); RIVER_ERROR("Can not link 2 Interface with not the same type (reserved for HW interface)");
return; return;
@@ -82,7 +79,7 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std:
} }
std::shared_ptr<audio::river::io::Node> audio::river::io::Group::getNode(const std::string& _name) { ememory::SharedPtr<audio::river::io::Node> audio::river::io::Group::getNode(const std::string& _name) {
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] != nullptr) { if (m_list[iii] != nullptr) {
if (m_list[iii]->getName() == _name) { if (m_list[iii]->getName() == _name) {
@@ -90,7 +87,7 @@ std::shared_ptr<audio::river::io::Node> audio::river::io::Group::getNode(const s
} }
} }
} }
return std::shared_ptr<audio::river::io::Node>(); return ememory::SharedPtr<audio::river::io::Node>();
} }
void audio::river::io::Group::start() { void audio::river::io::Group::start() {

View File

@@ -8,8 +8,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <ejson/ejson.h> #include <ejson/ejson.hpp>
#include <etk/os/FSNode.h> #include <etk/os/FSNode.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -23,7 +23,7 @@ namespace audio {
* is stopped. * is stopped.
* @note For the Alsa interface a low level link is availlable with AirTAudio for Alsa (One thread) * @note For the Alsa interface a low level link is availlable with AirTAudio for Alsa (One thread)
*/ */
class Group : public std::enable_shared_from_this<Group> { class Group : public ememory::EnableSharedFromThis<Group> {
public: public:
/** /**
* @brief Contructor. No special thing to do. * @brief Contructor. No special thing to do.
@@ -36,7 +36,7 @@ namespace audio {
// TODO : ... // TODO : ...
} }
private: private:
std::vector< std::shared_ptr<Node> > m_list; //!< List of all node in the group std::vector< ememory::SharedPtr<Node> > m_list; //!< List of all node in the group
public: public:
/** /**
* @brief Create a group with all node needed to syncronize together * @brief Create a group with all node needed to syncronize together
@@ -50,7 +50,7 @@ namespace audio {
* @return nullptr The node named _name was not found. * @return nullptr The node named _name was not found.
* @return pointer The node was find in this group. * @return pointer The node was find in this group.
*/ */
std::shared_ptr<audio::river::io::Node> getNode(const std::string& _name); ememory::SharedPtr<audio::river::io::Node> getNode(const std::string& _name);
/** /**
* @brief Start the group. * @brief Start the group.
* @note all sub-node will be started. * @note all sub-node will be started.

View File

@@ -4,22 +4,19 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/io/Manager.h> #include <audio/river/io/Manager.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <audio/river/river.h> #include <audio/river/river.hpp>
#include <audio/river/io/Node.h> #include <audio/river/io/Node.hpp>
#include <audio/river/io/NodeAEC.h> #include <audio/river/io/NodeAEC.hpp>
#include <audio/river/io/NodeMuxer.h> #include <audio/river/io/NodeMuxer.hpp>
#include <audio/river/io/NodeOrchestra.h> #include <audio/river/io/NodeOrchestra.hpp>
#include <audio/river/io/NodePortAudio.h> #include <audio/river/io/NodePortAudio.hpp>
#include <etk/os/FSNode.h> #include <etk/os/FSNode.hpp>
#include <memory> #include <ememory/memory.hpp>
#include <etk/types.h> #include <etk/types.hpp>
#include <utility> #include <utility>
#undef __class__
#define __class__ "io::Manager"
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO #ifdef AUDIO_RIVER_BUILD_PORTAUDIO
#include <portaudio/portaudio.h> #include <portaudio/portaudio.h>
#endif #endif
@@ -37,7 +34,8 @@ static std::string basicAutoConfig =
" 'front-left', 'front-right'\n" " 'front-left', 'front-right'\n"
" ],\n" " ],\n"
" type:'auto',\n" " type:'auto',\n"
" nb-chunk:1024\n" " nb-chunk:1024,\n"
" mux-demux-type:'float'\n"
" },\n" " },\n"
" speaker:{\n" " speaker:{\n"
" io:'output',\n" " io:'output',\n"
@@ -51,7 +49,8 @@ static std::string basicAutoConfig =
" ],\n" " ],\n"
" type:'auto',\n" " type:'auto',\n"
" nb-chunk:1024,\n" " nb-chunk:1024,\n"
" volume-name:'MASTER'\n" " volume-name:'MASTER',\n"
" mux-demux-type:'float'\n"
" }\n" " }\n"
"}\n"; "}\n";
@@ -95,11 +94,11 @@ audio::river::io::Manager::~Manager() {
#endif #endif
}; };
std::shared_ptr<audio::river::io::Manager> audio::river::io::Manager::getInstance() { ememory::SharedPtr<audio::river::io::Manager> audio::river::io::Manager::getInstance() {
if (audio::river::isInit() == false) { if (audio::river::isInit() == false) {
return std::shared_ptr<audio::river::io::Manager>(); return ememory::SharedPtr<audio::river::io::Manager>();
} }
static std::shared_ptr<audio::river::io::Manager> manager(new Manager()); static ememory::SharedPtr<audio::river::io::Manager> manager(new Manager());
return manager; return manager;
} }
@@ -108,13 +107,13 @@ std::vector<std::string> audio::river::io::Manager::getListStreamInput() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output; std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys(); std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) { for (auto &it : keys) {
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]); const ejson::Object tmppp = m_config[it].toObject();
if (tmppp != nullptr) { if (tmppp.exist() == true) {
std::string type = tmppp->getStringValue("io", "error"); std::string type = tmppp["io"].toString().get("error");
if ( type == "input" if ( type == "input"
|| type == "PAinput") { || type == "PAinput") {
output.push_back(keys[iii]); output.push_back(it);
} }
} }
} }
@@ -125,13 +124,13 @@ std::vector<std::string> audio::river::io::Manager::getListStreamOutput() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output; std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys(); std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) { for (auto &it : keys) {
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]); const ejson::Object tmppp = m_config[it].toObject();
if (tmppp != nullptr) { if (tmppp.exist() == true) {
std::string type = tmppp->getStringValue("io", "error"); std::string type = tmppp["io"].toString().get("error");
if ( type == "output" if ( type == "output"
|| type == "PAoutput") { || type == "PAoutput") {
output.push_back(keys[iii]); output.push_back(it);
} }
} }
} }
@@ -142,16 +141,16 @@ std::vector<std::string> audio::river::io::Manager::getListStreamVirtual() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output; std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys(); std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) { for (auto &it : keys) {
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]); const ejson::Object tmppp = m_config[it].toObject();
if (tmppp != nullptr) { if (tmppp.exist() == true) {
std::string type = tmppp->getStringValue("io", "error"); std::string type = tmppp["io"].toString().get("error");
if ( type != "input" if ( type != "input"
&& type != "PAinput" && type != "PAinput"
&& type != "output" && type != "output"
&& type != "PAoutput" && type != "PAoutput"
&& type != "error") { && type != "error") {
output.push_back(keys[iii]); output.push_back(it);
} }
} }
} }
@@ -162,24 +161,24 @@ std::vector<std::string> audio::river::io::Manager::getListStream() {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output; std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys(); std::vector<std::string> keys = m_config.getKeys();
for (size_t iii=0; iii<keys.size(); ++iii) { for (auto &it : keys) {
const std::shared_ptr<const ejson::Object> tmppp = m_config.getObject(keys[iii]); const ejson::Object tmppp = m_config[it].toObject();
if (tmppp != nullptr) { if (tmppp.exist() == true) {
std::string type = tmppp->getStringValue("io", "error"); std::string type = tmppp["io"].toString().get("error");
if (type != "error") { if (type != "error") {
output.push_back(keys[iii]); output.push_back(it);
} }
} }
} }
return output; return output;
} }
std::shared_ptr<audio::river::io::Node> audio::river::io::Manager::getNode(const std::string& _name) { ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_WARNING("Get node : " << _name); RIVER_WARNING("Get node : " << _name);
// search in the standalone list : // search in the standalone list :
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
std::shared_ptr<audio::river::io::Node> tmppp = m_list[iii].lock(); ememory::SharedPtr<audio::river::io::Node> tmppp = m_list[iii].lock();
if ( tmppp != nullptr if ( tmppp != nullptr
&& _name == tmppp->getName()) { && _name == tmppp->getName()) {
RIVER_WARNING(" find it ... in standalone"); RIVER_WARNING(" find it ... in standalone");
@@ -188,11 +187,11 @@ std::shared_ptr<audio::river::io::Node> audio::river::io::Manager::getNode(const
} }
// search in the group list: // search in the group list:
{ {
for (std::map<std::string, std::shared_ptr<audio::river::io::Group> >::iterator it(m_listGroup.begin()); for (std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it(m_listGroup.begin());
it != m_listGroup.end(); it != m_listGroup.end();
++it) { ++it) {
if (it->second != nullptr) { if (it->second != nullptr) {
std::shared_ptr<audio::river::io::Node> node = it->second->getNode(_name); ememory::SharedPtr<audio::river::io::Node> node = it->second->getNode(_name);
if (node != nullptr) { if (node != nullptr) {
RIVER_WARNING(" find it ... in group: " << it->first); RIVER_WARNING(" find it ... in group: " << it->first);
return node; return node;
@@ -202,21 +201,21 @@ std::shared_ptr<audio::river::io::Node> audio::river::io::Manager::getNode(const
} }
RIVER_WARNING("Try create a new one : " << _name); RIVER_WARNING("Try create a new one : " << _name);
// check if the node can be open : // check if the node can be open :
const std::shared_ptr<const ejson::Object> tmpObject = m_config.getObject(_name); const ejson::Object tmpObject = m_config[_name].toObject();
if (tmpObject != nullptr) { if (tmpObject.exist() == true) {
//Check if it is in a group: //Check if it is in a group:
std::string groupName = tmpObject->getStringValue("group", ""); std::string groupName = tmpObject["group"].toString().get();
// get type : io // get type : io
std::string ioType = tmpObject->getStringValue("io", "error"); std::string ioType = tmpObject["io"].toString().get("error");
if ( groupName != "" if ( groupName != ""
&& ( ioType == "input" && ( ioType == "input"
|| ioType == "output" || ioType == "output"
|| ioType == "PAinput" || ioType == "PAinput"
|| ioType == "PAoutput") ) { || ioType == "PAoutput") ) {
std::shared_ptr<audio::river::io::Group> tmpGroup = getGroup(groupName); ememory::SharedPtr<audio::river::io::Group> tmpGroup = getGroup(groupName);
if (tmpGroup == nullptr) { if (tmpGroup == nullptr) {
RIVER_WARNING("Can not get group ... '" << groupName << "'"); RIVER_WARNING("Can not get group ... '" << groupName << "'");
return std::shared_ptr<audio::river::io::Node>(); return ememory::SharedPtr<audio::river::io::Node>();
} }
return tmpGroup->getNode(_name); return tmpGroup->getNode(_name);
} else { } else {
@@ -228,7 +227,7 @@ std::shared_ptr<audio::river::io::Node> audio::river::io::Manager::getNode(const
if ( ioType == "input" if ( ioType == "input"
|| ioType == "output") { || ioType == "output") {
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA #ifdef AUDIO_RIVER_BUILD_ORCHESTRA
std::shared_ptr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_name, tmpObject); ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_name, tmpObject);
m_list.push_back(tmp); m_list.push_back(tmp);
return tmp; return tmp;
#else #else
@@ -238,7 +237,7 @@ std::shared_ptr<audio::river::io::Node> audio::river::io::Manager::getNode(const
if ( ioType == "PAinput" if ( ioType == "PAinput"
|| ioType == "PAoutput") { || ioType == "PAoutput") {
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO #ifdef AUDIO_RIVER_BUILD_PORTAUDIO
std::shared_ptr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_name, tmpObject); ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_name, tmpObject);
m_list.push_back(tmp); m_list.push_back(tmp);
return tmp; return tmp;
#else #else
@@ -246,26 +245,26 @@ std::shared_ptr<audio::river::io::Node> audio::river::io::Manager::getNode(const
#endif #endif
} }
if (ioType == "aec") { if (ioType == "aec") {
std::shared_ptr<audio::river::io::Node> tmp = audio::river::io::NodeAEC::create(_name, tmpObject); ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeAEC::create(_name, tmpObject);
m_list.push_back(tmp); m_list.push_back(tmp);
return tmp; return tmp;
} }
if (ioType == "muxer") { if (ioType == "muxer") {
std::shared_ptr<audio::river::io::Node> tmp = audio::river::io::NodeMuxer::create(_name, tmpObject); ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeMuxer::create(_name, tmpObject);
m_list.push_back(tmp); m_list.push_back(tmp);
return tmp; return tmp;
} }
} }
} }
RIVER_ERROR("Can not create the interface : '" << _name << "' the node is not DEFINED in the configuration file availlable : " << m_config.getKeys()); RIVER_ERROR("Can not create the interface : '" << _name << "' the node is not DEFINED in the configuration file availlable : " << m_config.getKeys());
return std::shared_ptr<audio::river::io::Node>(); return ememory::SharedPtr<audio::river::io::Node>();
} }
std::shared_ptr<audio::drain::VolumeElement> audio::river::io::Manager::getVolumeGroup(const std::string& _name) { ememory::SharedPtr<audio::drain::VolumeElement> audio::river::io::Manager::getVolumeGroup(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (_name == "") { if (_name == "") {
RIVER_ERROR("Try to create an audio group with no name ..."); RIVER_ERROR("Try to create an audio group with no name ...");
return std::shared_ptr<audio::drain::VolumeElement>(); return ememory::SharedPtr<audio::drain::VolumeElement>();
} }
for (size_t iii=0; iii<m_volumeGroup.size(); ++iii) { for (size_t iii=0; iii<m_volumeGroup.size(); ++iii) {
if (m_volumeGroup[iii] == nullptr) { if (m_volumeGroup[iii] == nullptr) {
@@ -276,14 +275,14 @@ std::shared_ptr<audio::drain::VolumeElement> audio::river::io::Manager::getVolum
} }
} }
RIVER_DEBUG("Add a new volume group : '" << _name << "'"); RIVER_DEBUG("Add a new volume group : '" << _name << "'");
std::shared_ptr<audio::drain::VolumeElement> tmpVolume = std::make_shared<audio::drain::VolumeElement>(_name); ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = ememory::makeShared<audio::drain::VolumeElement>(_name);
m_volumeGroup.push_back(tmpVolume); m_volumeGroup.push_back(tmpVolume);
return tmpVolume; return tmpVolume;
} }
bool audio::river::io::Manager::setVolume(const std::string& _volumeName, float _valuedB) { bool audio::river::io::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName); ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == nullptr) { if (volume == nullptr) {
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'"); RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'");
return false; return false;
@@ -295,7 +294,7 @@ bool audio::river::io::Manager::setVolume(const std::string& _volumeName, float
} }
volume->setVolume(_valuedB); volume->setVolume(_valuedB);
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
std::shared_ptr<audio::river::io::Node> val = m_list[iii].lock(); ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != nullptr) { if (val != nullptr) {
val->volumeChange(); val->volumeChange();
} }
@@ -305,7 +304,7 @@ bool audio::river::io::Manager::setVolume(const std::string& _volumeName, float
float audio::river::io::Manager::getVolume(const std::string& _volumeName) { float audio::river::io::Manager::getVolume(const std::string& _volumeName) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName); ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == nullptr) { if (volume == nullptr) {
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'"); RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
return 0.0f; return 0.0f;
@@ -319,14 +318,14 @@ std::pair<float,float> audio::river::io::Manager::getVolumeRange(const std::stri
void audio::river::io::Manager::setMute(const std::string& _volumeName, bool _mute) { void audio::river::io::Manager::setMute(const std::string& _volumeName, bool _mute) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName); ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == nullptr) { if (volume == nullptr) {
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'"); RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'");
return; return;
} }
volume->setMute(_mute); volume->setMute(_mute);
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
std::shared_ptr<audio::river::io::Node> val = m_list[iii].lock(); ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != nullptr) { if (val != nullptr) {
val->volumeChange(); val->volumeChange();
} }
@@ -335,7 +334,7 @@ void audio::river::io::Manager::setMute(const std::string& _volumeName, bool _mu
bool audio::river::io::Manager::getMute(const std::string& _volumeName) { bool audio::river::io::Manager::getMute(const std::string& _volumeName) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName); ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == nullptr) { if (volume == nullptr) {
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'"); RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
return false; return false;
@@ -357,14 +356,14 @@ void audio::river::io::Manager::generateDot(const std::string& _filename) {
{ {
// standalone // standalone
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
std::shared_ptr<audio::river::io::Node> val = m_list[iii].lock(); ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != nullptr) { if (val != nullptr) {
if (val->isHarwareNode() == true) { if (val->isHarwareNode() == true) {
val->generateDot(node); val->generateDot(node);
} }
} }
} }
for (std::map<std::string, std::shared_ptr<audio::river::io::Group> >::iterator it(m_listGroup.begin()); for (std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it(m_listGroup.begin());
it != m_listGroup.end(); it != m_listGroup.end();
++it) { ++it) {
if (it->second != nullptr) { if (it->second != nullptr) {
@@ -376,14 +375,14 @@ void audio::river::io::Manager::generateDot(const std::string& _filename) {
{ {
// standalone // standalone
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
std::shared_ptr<audio::river::io::Node> val = m_list[iii].lock(); ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != nullptr) { if (val != nullptr) {
if (val->isHarwareNode() == false) { if (val->isHarwareNode() == false) {
val->generateDot(node); val->generateDot(node);
} }
} }
} }
for (std::map<std::string, std::shared_ptr<audio::river::io::Group> >::iterator it(m_listGroup.begin()); for (std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it(m_listGroup.begin());
it != m_listGroup.end(); it != m_listGroup.end();
++it) { ++it) {
if (it->second != nullptr) { if (it->second != nullptr) {
@@ -397,16 +396,16 @@ void audio::river::io::Manager::generateDot(const std::string& _filename) {
RIVER_INFO("Generate the DOT files: " << node << " (DONE)"); RIVER_INFO("Generate the DOT files: " << node << " (DONE)");
} }
std::shared_ptr<audio::river::io::Group> audio::river::io::Manager::getGroup(const std::string& _name) { ememory::SharedPtr<audio::river::io::Group> audio::river::io::Manager::getGroup(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex); std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::shared_ptr<audio::river::io::Group> out; ememory::SharedPtr<audio::river::io::Group> out;
std::map<std::string, std::shared_ptr<audio::river::io::Group> >::iterator it = m_listGroup.find(_name); std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it = m_listGroup.find(_name);
if (it == m_listGroup.end()) { if (it == m_listGroup.end()) {
RIVER_INFO("Create a new group: " << _name << " (START)"); RIVER_INFO("Create a new group: " << _name << " (START)");
out = std::make_shared<audio::river::io::Group>(); out = ememory::makeShared<audio::river::io::Group>();
if (out != nullptr) { if (out != nullptr) {
out->createFrom(m_config, _name); out->createFrom(m_config, _name);
std::pair<std::string, std::shared_ptr<audio::river::io::Group> > plop(std::string(_name), out); std::pair<std::string, ememory::SharedPtr<audio::river::io::Group> > plop(std::string(_name), out);
m_listGroup.insert(plop); m_listGroup.insert(plop);
RIVER_INFO("Create a new group: " << _name << " ( END )"); RIVER_INFO("Create a new group: " << _name << " ( END )");
} else { } else {

View File

@@ -9,16 +9,16 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <list> #include <list>
#include <stdint.h> #include <cstdint>
#include <mutex> #include <mutex>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <memory> #include <ememory/memory.hpp>
#include <audio/format.h> #include <audio/format.hpp>
#include <audio/channel.h> #include <audio/channel.hpp>
#include <ejson/ejson.h> #include <ejson/ejson.hpp>
#include <audio/drain/Volume.h> #include <audio/drain/Volume.hpp>
#include <audio/river/io/Group.h> #include <audio/river/io/Group.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -28,7 +28,7 @@ namespace audio {
* @brief Internal sigleton of all Flow hadware and virtuals. * @brief Internal sigleton of all Flow hadware and virtuals.
* @note this class will be initialize by the audio::river::init() function at the start of the application. * @note this class will be initialize by the audio::river::init() function at the start of the application.
*/ */
class Manager : public std::enable_shared_from_this<Manager> { class Manager : public ememory::EnableSharedFromThis<Manager> {
private: private:
mutable std::recursive_mutex m_mutex; //!< prevent multiple access mutable std::recursive_mutex m_mutex; //!< prevent multiple access
private: private:
@@ -37,7 +37,7 @@ namespace audio {
*/ */
Manager(); Manager();
public: public:
static std::shared_ptr<Manager> getInstance(); static ememory::SharedPtr<Manager> getInstance();
/** /**
* @brief Destructor * @brief Destructor
*/ */
@@ -58,24 +58,24 @@ namespace audio {
void unInit(); void unInit();
private: private:
ejson::Document m_config; //!< harware configuration ejson::Document m_config; //!< harware configuration
std::vector<std::shared_ptr<audio::river::io::Node> > m_listKeepAlive; //!< list of all Node that might be keep alive sone/all time std::vector<ememory::SharedPtr<audio::river::io::Node> > m_listKeepAlive; //!< list of all Node that might be keep alive sone/all time
std::vector<std::weak_ptr<audio::river::io::Node> > m_list; //!< List of all IO node std::vector<ememory::WeakPtr<audio::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. * @brief Get a node with his name (the name is set in the description file.
* @param[in] _name Name of the node * @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. * @return Pointer on the noe or a nullptr if the node does not exist in the file or an error occured.
*/ */
std::shared_ptr<audio::river::io::Node> getNode(const std::string& _name); ememory::SharedPtr<audio::river::io::Node> getNode(const std::string& _name);
private: private:
std::vector<std::shared_ptr<audio::drain::VolumeElement> > m_volumeGroup; //!< List of All global volume in the Low level interface. std::vector<ememory::SharedPtr<audio::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 * @brief Get a volume in the global list of vilume
* @param[in] _name Name of the volume. * @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. * @return pointer on the requested volume (create it if does not exist). nullptr if the name is empty.
*/ */
std::shared_ptr<audio::drain::VolumeElement> getVolumeGroup(const std::string& _name); ememory::SharedPtr<audio::drain::VolumeElement> getVolumeGroup(const std::string& _name);
/** /**
* @brief Get all input audio stream. * @brief Get all input audio stream.
* @return a list of all availlables input stream name * @return a list of all availlables input stream name
@@ -138,13 +138,13 @@ namespace audio {
*/ */
void generateDot(const std::string& _filename); void generateDot(const std::string& _filename);
private: private:
std::map<std::string, std::shared_ptr<audio::river::io::Group> > m_listGroup; //!< List of all groups std::map<std::string, ememory::SharedPtr<audio::river::io::Group> > m_listGroup; //!< List of all groups
/** /**
* @brief get a low level interface group. * @brief get a low level interface group.
* @param[in] _name Name of the group. * @param[in] _name Name of the group.
* @return Pointer on the requested group or nullptr if the group does not existed. * @return Pointer on the requested group or nullptr if the group does not existed.
*/ */
std::shared_ptr<audio::river::io::Group> getGroup(const std::string& _name); ememory::SharedPtr<audio::river::io::Group> getGroup(const std::string& _name);
}; };
} }

View File

@@ -4,14 +4,10 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include "Node.h" #include "Node.hpp"
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#undef __class__ audio::river::io::Node::Node(const std::string& _name, const ejson::Object& _config) :
#define __class__ "io::Node"
audio::river::io::Node::Node(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) :
m_config(_config), m_config(_config),
m_name(_name), m_name(_name),
m_isInput(false) { m_isInput(false) {
@@ -34,7 +30,7 @@ audio::river::io::Node::Node(const std::string& _name, const std::shared_ptr<con
# muxer/demuxer format type (int8-on-int16, int16-on-int32, int24-on-int32, int32-on-int64, float) # muxer/demuxer format type (int8-on-int16, int16-on-int32, int24-on-int32, int32-on-int64, float)
mux-demux-type:"int16_on_int32", mux-demux-type:"int16_on_int32",
*/ */
std::string interfaceType = m_config->getStringValue("io"); std::string interfaceType = m_config["io"].toString().get();
RIVER_INFO("interfaceType=" << interfaceType); RIVER_INFO("interfaceType=" << interfaceType);
if ( interfaceType == "input" if ( interfaceType == "input"
|| interfaceType == "PAinput" || interfaceType == "PAinput"
@@ -45,12 +41,12 @@ audio::river::io::Node::Node(const std::string& _name, const std::shared_ptr<con
m_isInput = false; m_isInput = false;
} }
int32_t frequency = m_config->getNumberValue("frequency", 1); int32_t frequency = m_config["frequency"].toNumber().get(1);
// Get audio format type: // Get audio format type:
std::string type = m_config->getStringValue("type", "int16"); std::string type = m_config["type"].toString().get("int16");
enum audio::format formatType = audio::getFormatFromString(type); enum audio::format formatType = audio::getFormatFromString(type);
// Get volume stage : // Get volume stage :
std::string volumeName = m_config->getStringValue("volume-name", ""); std::string volumeName = m_config["volume-name"].toString().get();
if (volumeName != "") { if (volumeName != "") {
RIVER_INFO("add node volume stage : '" << volumeName << "'"); RIVER_INFO("add node volume stage : '" << volumeName << "'");
// use global manager for volume ... // use global manager for volume ...
@@ -58,15 +54,15 @@ audio::river::io::Node::Node(const std::string& _name, const std::shared_ptr<con
} }
// Get map type : // Get map type :
std::vector<audio::channel> map; std::vector<audio::channel> map;
const std::shared_ptr<const ejson::Array> listChannelMap = m_config->getArray("channel-map"); const ejson::Array listChannelMap = m_config["channel-map"].toArray();
if ( listChannelMap == nullptr if ( listChannelMap.exist() == false
|| listChannelMap->size() == 0) { || listChannelMap.size() == 0) {
// set default channel property: // set default channel property:
map.push_back(audio::channel_frontLeft); map.push_back(audio::channel_frontLeft);
map.push_back(audio::channel_frontRight); map.push_back(audio::channel_frontRight);
} else { } else {
for (size_t iii=0; iii<listChannelMap->size(); ++iii) { for (auto it : listChannelMap) {
std::string value = listChannelMap->getStringValue(iii); std::string value = it.toString().get();
map.push_back(audio::getChannelFromString(value)); map.push_back(audio::getChannelFromString(value));
} }
} }
@@ -75,17 +71,20 @@ audio::river::io::Node::Node(const std::string& _name, const std::shared_ptr<con
std::string muxerDemuxerConfig; std::string muxerDemuxerConfig;
if (m_isInput == true) { if (m_isInput == true) {
muxerDemuxerConfig = m_config->getStringValue("mux-demux-type", "int16"); muxerDemuxerConfig = m_config["mux-demux-type"].toString().get("int16");
} else { } else {
muxerDemuxerConfig = m_config->getStringValue("mux-demux-type", "int16-on-int32"); muxerDemuxerConfig = m_config["mux-demux-type"].toString().get("int16-on-int32");
} }
enum audio::format muxerFormatType = audio::getFormatFromString(muxerDemuxerConfig); enum audio::format muxerFormatType = audio::getFormatFromString(muxerDemuxerConfig);
if (m_isInput == true) { if (m_isInput == true) {
if (muxerFormatType != audio::format_int16) { // Support all ...
RIVER_CRITICAL("not supported demuxer type ... " << muxerFormatType << " for INPUT set in file:" << muxerDemuxerConfig);
}
} else { } else {
if (muxerFormatType != audio::format_int16_on_int32) { if ( muxerFormatType != audio::format_int8_on_int16
&& muxerFormatType != audio::format_int16_on_int32
&& muxerFormatType != audio::format_int24_on_int32
&& muxerFormatType != audio::format_int32_on_int64
&& muxerFormatType != audio::format_float
&& muxerFormatType != audio::format_double) {
RIVER_CRITICAL("not supported demuxer type ... " << muxerFormatType << " for OUTPUT set in file:" << muxerDemuxerConfig); RIVER_CRITICAL("not supported demuxer type ... " << muxerFormatType << " for OUTPUT set in file:" << muxerDemuxerConfig);
} }
} }
@@ -123,7 +122,7 @@ size_t audio::river::io::Node::getNumberOfInterface(enum audio::river::modeInter
size_t audio::river::io::Node::getNumberOfInterfaceAvaillable(enum audio::river::modeInterface _interfaceType) { size_t audio::river::io::Node::getNumberOfInterfaceAvaillable(enum audio::river::modeInterface _interfaceType) {
size_t out = 0; size_t out = 0;
for (size_t iii=0; iii<m_listAvaillable.size(); ++iii) { for (size_t iii=0; iii<m_listAvaillable.size(); ++iii) {
std::shared_ptr<audio::river::Interface> element = m_listAvaillable[iii].lock(); ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == nullptr) { if (element == nullptr) {
continue; continue;
} }
@@ -134,8 +133,8 @@ size_t audio::river::io::Node::getNumberOfInterfaceAvaillable(enum audio::river:
return out; return out;
} }
void audio::river::io::Node::registerAsRemote(const std::shared_ptr<audio::river::Interface>& _interface) { void audio::river::io::Node::registerAsRemote(const ememory::SharedPtr<audio::river::Interface>& _interface) {
std::vector<std::weak_ptr<audio::river::Interface> >::iterator it = m_listAvaillable.begin(); std::vector<ememory::WeakPtr<audio::river::Interface> >::iterator it = m_listAvaillable.begin();
while (it != m_listAvaillable.end()) { while (it != m_listAvaillable.end()) {
if (it->expired() == true) { if (it->expired() == true) {
it = m_listAvaillable.erase(it); it = m_listAvaillable.erase(it);
@@ -146,7 +145,7 @@ void audio::river::io::Node::registerAsRemote(const std::shared_ptr<audio::river
m_listAvaillable.push_back(_interface); m_listAvaillable.push_back(_interface);
} }
void audio::river::io::Node::interfaceAdd(const std::shared_ptr<audio::river::Interface>& _interface) { void audio::river::io::Node::interfaceAdd(const ememory::SharedPtr<audio::river::Interface>& _interface) {
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
for (size_t iii=0; iii<m_list.size(); ++iii) { for (size_t iii=0; iii<m_list.size(); ++iii) {
@@ -162,7 +161,7 @@ void audio::river::io::Node::interfaceAdd(const std::shared_ptr<audio::river::In
} }
} }
void audio::river::io::Node::interfaceRemove(const std::shared_ptr<audio::river::Interface>& _interface) { void audio::river::io::Node::interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface) {
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
for (size_t iii=0; iii< m_list.size(); ++iii) { for (size_t iii=0; iii< m_list.size(); ++iii) {
@@ -182,7 +181,7 @@ void audio::river::io::Node::interfaceRemove(const std::shared_ptr<audio::river:
void audio::river::io::Node::volumeChange() { void audio::river::io::Node::volumeChange() {
for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) { for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) {
std::shared_ptr<audio::river::Interface> node = m_listAvaillable[iii].lock(); ememory::SharedPtr<audio::river::Interface> node = m_listAvaillable[iii].lock();
if (node != nullptr) { if (node != nullptr) {
node->systemVolumeChange(); node->systemVolumeChange();
} }
@@ -195,7 +194,6 @@ void audio::river::io::Node::newInput(const void* _inputBuffer,
if (_inputBuffer == nullptr) { if (_inputBuffer == nullptr) {
return; return;
} }
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) {
if (m_list[iii] == nullptr) { if (m_list[iii] == nullptr) {
continue; continue;
@@ -204,7 +202,7 @@ void audio::river::io::Node::newInput(const void* _inputBuffer,
continue; continue;
} }
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName()); RIVER_VERBOSE(" IO name="<< m_list[iii]->getName());
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; return;
@@ -216,15 +214,22 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
if (_outputBuffer == nullptr) { if (_outputBuffer == nullptr) {
return; return;
} }
std::vector<int32_t> output; enum audio::format muxerFormatType = m_process.getInputConfig().getFormat();
std::vector<uint8_t> outputTmp2;
uint32_t nbByteTmpBuffer = audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size()*_nbChunk;
RIVER_VERBOSE("resize=" << nbByteTmpBuffer);
outputTmp2.resize(nbByteTmpBuffer);
if (muxerFormatType == audio::format_int8_on_int16) {
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 16 bits
//////////////////////////////////////////////////////////////////////////////////////////////////
// $$$$ change the int16
std::vector<int16_t> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size()); RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0); output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
// TODO : set here the mixer selection ... // $$$$ change the int16
if (true) { const int16_t* outputTmp = nullptr;
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 (size_t iii=0; iii< m_list.size(); ++iii) { for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == nullptr) { if (m_list[iii] == nullptr) {
continue; continue;
@@ -234,19 +239,144 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
} }
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii); RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
// clear datas ... // clear datas ...
memset(&outputTmp2[0], 0, sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk); memset(&outputTmp2[0], 0, nbByteTmpBuffer);
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time); RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, sizeof(int32_t)*m_process.getInputConfig().getMap().size()); m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
// $$$$ change the int16
outputTmp = reinterpret_cast<const int16_t*>(&outputTmp2[0]);
RIVER_VERBOSE(" Mix it ...");
// Add data to the output tmp buffer:
for (size_t kkk=0; kkk<output.size(); ++kkk) {
output[kkk] += outputTmp[kkk];
}
// TODO : if a signal is upper than 256* the maximum of 1 it can create a real problem ...
}
RIVER_VERBOSE(" End stack process data ...");
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
} else if ( muxerFormatType == audio::format_int16_on_int32
|| muxerFormatType == audio::format_int24_on_int32) {
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 32 bits
//////////////////////////////////////////////////////////////////////////////////////////////////
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;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
continue;
}
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
// clear datas ...
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
outputTmp = reinterpret_cast<const int32_t*>(&outputTmp2[0]); outputTmp = reinterpret_cast<const int32_t*>(&outputTmp2[0]);
RIVER_VERBOSE(" Mix it ..."); RIVER_VERBOSE(" Mix it ...");
// Add data to the output tmp buffer: // Add data to the output tmp buffer:
for (size_t kkk=0; kkk<output.size(); ++kkk) { for (size_t kkk=0; kkk<output.size(); ++kkk) {
output[kkk] += outputTmp[kkk]; output[kkk] += outputTmp[kkk];
} }
// TODO : if a signal is upper than 256* (for 24 bits) or 65335* (for 16 bits) the maximum of 1 it can create a real problem ...
}
RIVER_VERBOSE(" End stack process data ...");
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
} else if (muxerFormatType == audio::format_int32_on_int64) {
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 64 bits
//////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<int64_t> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
const int64_t* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
continue;
}
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
// clear datas ...
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
outputTmp = reinterpret_cast<const int64_t*>(&outputTmp2[0]);
RIVER_VERBOSE(" Mix it ...");
// Add data to the output tmp buffer:
for (size_t kkk=0; kkk<output.size(); ++kkk) {
output[kkk] += outputTmp[kkk];
}
// TODO : if a signal is upper than 2000000000* the maximum of 1 it can create a real problem ...
}
RIVER_VERBOSE(" End stack process data ...");
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
} else if (muxerFormatType == audio::format_float) {
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 32 bits FLOAT
//////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<float> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
const float* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
continue;
}
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
// clear datas ...
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
outputTmp = reinterpret_cast<const float*>(&outputTmp2[0]);
RIVER_VERBOSE(" Mix it ...");
// 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 ..."); RIVER_VERBOSE(" End stack process data ...");
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk); m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
} else if (muxerFormatType == audio::format_double) {
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 64 bits FLOAT
//////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<double> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
const double* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
continue;
}
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
// clear datas ...
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
outputTmp = reinterpret_cast<const double*>(&outputTmp2[0]);
RIVER_VERBOSE(" Mix it ...");
// 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(&output[0], _nbChunk, _outputBuffer, _nbChunk);
} else {
RIVER_ERROR("Wrong demuxer type: " << muxerFormatType);
return;
}
// The feedback get the real output data (after processing ...==> then no nneed to specify for each channels
RIVER_VERBOSE(" Feedback :"); RIVER_VERBOSE(" Feedback :");
for (size_t iii=0; iii< m_list.size(); ++iii) { for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == nullptr) { if (m_list[iii] == nullptr) {
@@ -324,7 +454,7 @@ void audio::river::io::Node::generateDot(etk::FSNode& _node) {
if (m_listAvaillable[iii].expired() == true) { if (m_listAvaillable[iii].expired() == true) {
continue; continue;
} }
std::shared_ptr<audio::river::Interface> element = m_listAvaillable[iii].lock(); ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == nullptr) { if (element == nullptr) {
continue; continue;
} }
@@ -350,7 +480,7 @@ void audio::river::io::Node::generateDot(etk::FSNode& _node) {
void audio::river::io::Node::startInGroup() { void audio::river::io::Node::startInGroup() {
std::shared_ptr<audio::river::io::Group> group = m_group.lock(); ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
if (group != nullptr) { if (group != nullptr) {
group->start(); group->start();
} else { } else {
@@ -359,7 +489,7 @@ void audio::river::io::Node::startInGroup() {
} }
void audio::river::io::Node::stopInGroup() { void audio::river::io::Node::stopInGroup() {
std::shared_ptr<audio::river::io::Group> group = m_group.lock(); ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
if (group != nullptr) { if (group != nullptr) {
group->stop(); group->stop();
} else { } else {

View File

@@ -8,17 +8,17 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <list> #include <list>
#include <stdint.h> #include <cstdint>
#include <chrono> #include <chrono>
#include <functional> #include <functional>
#include <memory> #include <ememory/memory.hpp>
#include <audio/format.h> #include <audio/format.hpp>
#include <audio/channel.h> #include <audio/channel.hpp>
#include "Manager.h" #include "Manager.hpp"
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <audio/drain/IOFormatInterface.h> #include <audio/drain/IOFormatInterface.hpp>
#include <audio/drain/Volume.h> #include <audio/drain/Volume.hpp>
#include <etk/os/FSNode.h> #include <etk/os/FSNode.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -29,7 +29,7 @@ namespace audio {
* @brief A node is the base for input/output interface. When a output id declared, we automaticly have a feedback associated. * @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. * this manage the muxing of data for output an the demuxing for input.
*/ */
class Node : public std::enable_shared_from_this<Node> { class Node : public ememory::EnableSharedFromThis<Node> {
friend class audio::river::io::Group; friend class audio::river::io::Group;
protected: protected:
uint32_t m_uid; //!< uniqueNodeID use for debug an dot generation. uint32_t m_uid; //!< uniqueNodeID use for debug an dot generation.
@@ -39,7 +39,7 @@ namespace audio {
* @param[in] _name Name of the node. * @param[in] _name Name of the node.
* @param[in] _config Configuration of the node. * @param[in] _config Configuration of the node.
*/ */
Node(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); Node(const std::string& _name, const ejson::Object& _config);
public: public:
/** /**
* @brief Destructor * @brief Destructor
@@ -55,7 +55,7 @@ namespace audio {
}; };
protected: protected:
mutable std::mutex m_mutex; //!< prevent open/close/write/read access that is multi-threaded. mutable std::mutex m_mutex; //!< prevent open/close/write/read access that is multi-threaded.
std::shared_ptr<const ejson::Object> m_config; //!< configuration description. const ejson::Object m_config; //!< configuration description.
protected: protected:
audio::drain::Process m_process; //!< Low level algorithms audio::drain::Process m_process; //!< Low level algorithms
public: public:
@@ -82,10 +82,10 @@ namespace audio {
} }
} }
protected: protected:
std::shared_ptr<audio::drain::VolumeElement> m_volume; //!< if a volume is set it is set here ... for hardware interface only. ememory::SharedPtr<audio::drain::VolumeElement> m_volume; //!< if a volume is set it is set here ... for hardware interface only.
protected: protected:
std::vector<std::weak_ptr<audio::river::Interface> > m_listAvaillable; //!< List of all interface that exist on this Node std::vector<ememory::WeakPtr<audio::river::Interface> > m_listAvaillable; //!< List of all interface that exist on this Node
std::vector<std::shared_ptr<audio::river::Interface> > m_list; //!< List of all connected interface at this node. std::vector<ememory::SharedPtr<audio::river::Interface> > m_list; //!< List of all connected interface at this node.
/** /**
* @brief Get the number of interface with a specific type. * @brief Get the number of interface with a specific type.
* @param[in] _interfaceType Type of the interface. * @param[in] _interfaceType Type of the interface.
@@ -109,20 +109,20 @@ namespace audio {
public: public:
/** /**
* @brief Register an interface that can connect on it. (might be done in the Interface Init) * @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. * @note We keep a ememory::WeakPtr. this is the reason why we do not have a remove.
* @param[in] _interface Pointer on the interface to register. * @param[in] _interface Pointer on the interface to register.
*/ */
void registerAsRemote(const std::shared_ptr<audio::river::Interface>& _interface); void registerAsRemote(const ememory::SharedPtr<audio::river::Interface>& _interface);
/** /**
* @brief Request this interface might receve/send dat on the flow. (start/resume) * @brief Request this interface might receve/send dat on the flow. (start/resume)
* @param[in] _interface Pointer on the interface to register. * @param[in] _interface Pointer on the interface to register.
*/ */
void interfaceAdd(const std::shared_ptr<audio::river::Interface>& _interface); void interfaceAdd(const ememory::SharedPtr<audio::river::Interface>& _interface);
/** /**
* @brief Un-register the interface as an availlable read/write interface. (suspend/stop) * @brief Un-register the interface as an availlable read/write interface. (suspend/stop)
* @param[in] _interface Pointer on the interface to register. * @param[in] _interface Pointer on the interface to register.
*/ */
void interfaceRemove(const std::shared_ptr<audio::river::Interface>& _interface); void interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface);
protected: protected:
std::string m_name; //!< Name of the interface std::string m_name; //!< Name of the interface
public: public:
@@ -151,13 +151,13 @@ namespace audio {
return !m_isInput; return !m_isInput;
} }
protected: protected:
std::weak_ptr<audio::river::io::Group> m_group; //!< reference on the group. If available. ememory::WeakPtr<audio::river::io::Group> m_group; //!< reference on the group. If available.
public: public:
/** /**
* @brief Set this node in a low level group. * @brief Set this node in a low level group.
* @param[in] _group Group reference. * @param[in] _group Group reference.
*/ */
void setGroup(std::shared_ptr<audio::river::io::Group> _group) { void setGroup(ememory::SharedPtr<audio::river::io::Group> _group) {
m_group = _group; m_group = _group;
} }
protected: protected:
@@ -182,7 +182,7 @@ namespace audio {
* @brief If this iss an hardware interface we can have a resuest of the volume stage: * @brief If this iss an hardware interface we can have a resuest of the volume stage:
* @return pointer on the requested volume. * @return pointer on the requested volume.
*/ */
const std::shared_ptr<audio::drain::VolumeElement>& getVolume() { const ememory::SharedPtr<audio::drain::VolumeElement>& getVolume() {
return m_volume; return m_volume;
} }
public: public:

View File

@@ -4,46 +4,43 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/io/NodeAEC.h> #include <audio/river/io/NodeAEC.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <etk/types.h> #include <etk/types.hpp>
#include <memory> #include <ememory/memory.hpp>
#include <functional> #include <functional>
#undef __class__ ememory::SharedPtr<audio::river::io::NodeAEC> audio::river::io::NodeAEC::create(const std::string& _name, const ejson::Object& _config) {
#define __class__ "io::NodeAEC" return ememory::SharedPtr<audio::river::io::NodeAEC>(new audio::river::io::NodeAEC(_name, _config));
std::shared_ptr<audio::river::io::NodeAEC> audio::river::io::NodeAEC::create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) {
return std::shared_ptr<audio::river::io::NodeAEC>(new audio::river::io::NodeAEC(_name, _config));
} }
std::shared_ptr<audio::river::Interface> audio::river::io::NodeAEC::createInput(float _freq, ememory::SharedPtr<audio::river::Interface> audio::river::io::NodeAEC::createInput(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::string& _objectName, const std::string& _objectName,
const std::string& _name) { const std::string& _name) {
// check if the output exist // check if the output exist
const std::shared_ptr<const ejson::Object> tmppp = m_config->getObject(_objectName); const ejson::Object tmppp = m_config[_objectName].toObject();
if (tmppp == nullptr) { if (tmppp.exist() == false) {
RIVER_ERROR("can not open a non existance virtual interface: '" << _objectName << "' not present in : " << m_config->getKeys()); RIVER_ERROR("can not open a non existance virtual interface: '" << _objectName << "' not present in : " << m_config.getKeys());
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
std::string streamName = tmppp->getStringValue("map-on", "error"); std::string streamName = tmppp["map-on"].toString().get("error");
m_nbChunk = m_config->getNumberValue("nb-chunk", 1024); m_nbChunk = m_config["nb-chunk"].toNumber().get(1024);
// check if it is an Output: // check if it is an Output:
std::string type = tmppp->getStringValue("io", "error"); std::string type = tmppp["io"].toString().get("error");
if ( type != "input" if ( type != "input"
&& type != "feedback") { && type != "feedback") {
RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type); RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type);
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// get global hardware interface: // get global hardware interface:
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
// get the output or input channel : // get the output or input channel :
std::shared_ptr<audio::river::io::Node> node = manager->getNode(streamName); ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(streamName);
// create user iterface: // create user iterface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp); interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp);
if (interface != nullptr) { if (interface != nullptr) {
interface->setName(_name); interface->setName(_name);
@@ -52,7 +49,7 @@ std::shared_ptr<audio::river::Interface> audio::river::io::NodeAEC::createInput(
} }
audio::river::io::NodeAEC::NodeAEC(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) : audio::river::io::NodeAEC::NodeAEC(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config), Node(_name, _config),
m_P_attaqueTime(1), m_P_attaqueTime(1),
m_P_releaseTime(100), m_P_releaseTime(100),
@@ -346,7 +343,7 @@ void audio::river::io::NodeAEC::generateDot(etk::FSNode& _node) {
if (m_listAvaillable[iii].expired() == true) { if (m_listAvaillable[iii].expired() == true) {
continue; continue;
} }
std::shared_ptr<audio::river::Interface> element = m_listAvaillable[iii].lock(); ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == nullptr) { if (element == nullptr) {
continue; continue;
} }

View File

@@ -5,9 +5,9 @@
*/ */
#pragma once #pragma once
#include <audio/river/io/Node.h> #include <audio/river/io/Node.hpp>
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <audio/drain/CircularBuffer.h> #include <audio/drain/CircularBuffer.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -18,14 +18,14 @@ namespace audio {
/** /**
* @brief Constructor * @brief Constructor
*/ */
NodeAEC(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); NodeAEC(const std::string& _name, const ejson::Object& _config);
public: public:
/** /**
* @brief Factory of this Virtual Node. * @brief Factory of this Virtual Node.
* @param[in] _name Name of the node. * @param[in] _name Name of the node.
* @param[in] _config Configuration of the node. * @param[in] _config Configuration of the node.
*/ */
static std::shared_ptr<NodeAEC> create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); static ememory::SharedPtr<NodeAEC> create(const std::string& _name, const ejson::Object& _config);
/** /**
* @brief Destructor * @brief Destructor
*/ */
@@ -33,8 +33,8 @@ namespace audio {
protected: protected:
virtual void start(); virtual void start();
virtual void stop(); virtual void stop();
std::shared_ptr<audio::river::Interface> m_interfaceMicrophone; //!< Interface on the Microphone. ememory::SharedPtr<audio::river::Interface> m_interfaceMicrophone; //!< Interface on the Microphone.
std::shared_ptr<audio::river::Interface> m_interfaceFeedBack; //!< Interface on the feedback of speaker. ememory::SharedPtr<audio::river::Interface> m_interfaceFeedBack; //!< Interface on the feedback of speaker.
/** /**
* @brief Internal: create an input with the specific parameter: * @brief Internal: create an input with the specific parameter:
* @param[in] _freq Frequency. * @param[in] _freq Frequency.
@@ -44,7 +44,7 @@ namespace audio {
* @param[in] _name * @param[in] _name
* @return Interfae Pointer. * @return Interfae Pointer.
*/ */
std::shared_ptr<audio::river::Interface> createInput(float _freq, ememory::SharedPtr<audio::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,

View File

@@ -6,12 +6,9 @@
#ifdef AUDIO_RIVER_BUILD_FILE #ifdef AUDIO_RIVER_BUILD_FILE
#include <audio/river/io/NodeFile.h> #include <audio/river/io/NodeFile.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <memory> #include <ememory/memory.hpp>
#undef __class__
#define __class__ "io::NodeFile"
int32_t audio::river::io::NodeFile::recordCallback(const void* _inputBuffer, int32_t audio::river::io::NodeFile::recordCallback(const void* _inputBuffer,
const audio::Time& _timeInput, const audio::Time& _timeInput,
@@ -37,11 +34,11 @@ int32_t audio::river::io::NodeFile::playbackCallback(void* _outputBuffer,
std::shared_ptr<audio::river::io::NodeFile> audio::river::io::NodeFile::create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) { ememory::SharedPtr<audio::river::io::NodeFile> audio::river::io::NodeFile::create(const std::string& _name, const ejson::Object& _config) {
return std::shared_ptr<audio::river::io::NodeFile>(new audio::river::io::NodeFile(_name, _config)); return ememory::SharedPtr<audio::river::io::NodeFile>(new audio::river::io::NodeFile(_name, _config));
} }
audio::river::io::NodeFile::NodeFile(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) : audio::river::io::NodeFile::NodeFile(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) { Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat(); audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat(); audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@@ -52,25 +49,25 @@ audio::river::io::NodeFile::NodeFile(const std::string& _name, const std::shared
}, },
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user) nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
*/ */
std::string typeInterface = audio::orchestra::type_undefined; std::string typeInterface = audio::orchestra::type::undefined;
std::string streamName = "default"; std::string streamName = "default";
const std::shared_ptr<const ejson::Object> tmpObject = m_config->getObject("map-on"); const ejson::Object tmpObject = m_config["map-on"].toObject();
if (tmpObject == nullptr) { if (tmpObject.exist() == false) {
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'"); RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
} else { } else {
typeInterface = tmpObject->getStringValue("interface", audio::orchestra::type_undefined); typeInterface = tmpObject.getStringValue("interface", audio::orchestra::type::undefined);
if (typeInterface == "auto") { if (typeInterface == "auto") {
typeInterface = audio::orchestra::type_undefined; typeInterface = audio::orchestra::type::undefined;
} }
streamName = tmpObject->getStringValue("name", "default"); streamName = tmpObject.getStringValue("name", "default");
} }
int32_t nbChunk = m_config->getNumberValue("nb-chunk", 1024); int32_t nbChunk = m_config.getNumberValue("nb-chunk", 1024);
// intanciate specific API ... // intanciate specific API ...
m_interface.instanciate(typeInterface); m_interface.instanciate(typeInterface);
m_interface.setName(_name); m_interface.setName(_name);
// TODO : Check return ... // TODO : Check return ...
std::string type = m_config->getStringValue("type", "int16"); std::string type = m_config.getStringValue("type", "int16");
if (streamName == "") { if (streamName == "") {
streamName = "default"; streamName = "default";
} }
@@ -256,7 +253,7 @@ void audio::river::io::NodeFile::start() {
} }
m_alive = true; m_alive = true;
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") ); RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") );
m_thread = std::make_shared<std::thread>(&audio::river::io::NodeFile::threadCallback2, this); m_thread = ememory::makeShared<std::thread>(&audio::river::io::NodeFile::threadCallback2, this);
m_time = audio::Time::now(); m_time = audio::Time::now();
} }

View File

@@ -7,8 +7,8 @@
#ifdef AUDIO_RIVER_BUILD_FILE #ifdef AUDIO_RIVER_BUILD_FILE
#include <audio/river/io/Node.h> #include <audio/river/io/Node.hpp>
#include <audio/orchestra/Interface.h> #include <audio/orchestra/Interface.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -24,9 +24,9 @@ namespace audio {
/** /**
* @brief Constructor * @brief Constructor
*/ */
NodeFile(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); NodeFile(const std::string& _name, const ejson::Object& _config);
public: public:
static std::shared_ptr<NodeFile> create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); static ememory::SharedPtr<NodeFile> create(const std::string& _name, const ejson::Object& _config);
/** /**
* @brief Destructor * @brief Destructor
*/ */
@@ -41,7 +41,7 @@ namespace audio {
uint32_t m_sampleRate; //!< Sample Rate of the Raw file uint32_t m_sampleRate; //!< Sample Rate of the Raw file
audio::format m_format; //!< Format of the file audio::format m_format; //!< Format of the file
std::vector<audio::channel> m_map; //!< Map of the file std::vector<audio::channel> m_map; //!< Map of the file
std::shared_ptr<std::thread> m_thread; //!< playing thread of the flow ememory::SharedPtr<std::thread> m_thread; //!< playing thread of the flow
std::atomic<bool> m_alive; //!< thread is active std::atomic<bool> m_alive; //!< thread is active
protected: protected:
virtual void start(); virtual void start();

View File

@@ -4,46 +4,43 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/io/NodeMuxer.h> #include <audio/river/io/NodeMuxer.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <etk/types.h> #include <etk/types.hpp>
#include <memory> #include <ememory/memory.hpp>
#include <functional> #include <functional>
#undef __class__ ememory::SharedPtr<audio::river::io::NodeMuxer> audio::river::io::NodeMuxer::create(const std::string& _name, const ejson::Object& _config) {
#define __class__ "io::NodeMuxer" return ememory::SharedPtr<audio::river::io::NodeMuxer>(new audio::river::io::NodeMuxer(_name, _config));
std::shared_ptr<audio::river::io::NodeMuxer> audio::river::io::NodeMuxer::create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) {
return std::shared_ptr<audio::river::io::NodeMuxer>(new audio::river::io::NodeMuxer(_name, _config));
} }
std::shared_ptr<audio::river::Interface> audio::river::io::NodeMuxer::createInput(float _freq, ememory::SharedPtr<audio::river::Interface> audio::river::io::NodeMuxer::createInput(float _freq,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
audio::format _format, audio::format _format,
const std::string& _objectName, const std::string& _objectName,
const std::string& _name) { const std::string& _name) {
// check if the output exist // check if the output exist
const std::shared_ptr<const ejson::Object> tmppp = m_config->getObject(_objectName); const ejson::Object tmppp = m_config[_objectName].toObject();
if (tmppp == nullptr) { if (tmppp.exist() == false) {
RIVER_ERROR("can not open a non existance virtual interface: '" << _objectName << "' not present in : " << m_config->getKeys()); RIVER_ERROR("can not open a non existance virtual interface: '" << _objectName << "' not present in : " << m_config.getKeys());
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
std::string streamName = tmppp->getStringValue("map-on", "error"); std::string streamName = tmppp["map-on"].toString().get("error");
// check if it is an Output: // check if it is an Output:
std::string type = tmppp->getStringValue("io", "error"); std::string type = tmppp["io"].toString().get("error");
if ( type != "input" if ( type != "input"
&& type != "feedback") { && type != "feedback") {
RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type); RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type);
return std::shared_ptr<audio::river::Interface>(); return ememory::SharedPtr<audio::river::Interface>();
} }
// get global hardware interface: // get global hardware interface:
std::shared_ptr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
// get the output or input channel : // get the output or input channel :
std::shared_ptr<audio::river::io::Node> node = manager->getNode(streamName); ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(streamName);
// create user iterface: // create user iterface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp); interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp);
if (interface != nullptr) { if (interface != nullptr) {
interface->setName(_name); interface->setName(_name);
@@ -52,7 +49,7 @@ std::shared_ptr<audio::river::Interface> audio::river::io::NodeMuxer::createInpu
} }
audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) : audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) { Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat(); audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat(); audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@@ -88,14 +85,14 @@ audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const std::shar
RIVER_ERROR("Can not opne virtual device ... map-on-input-1 in " << _name); RIVER_ERROR("Can not opne virtual device ... map-on-input-1 in " << _name);
return; return;
} }
std::shared_ptr<const ejson::Array> listChannelMap = m_config->getArray("input-1-remap"); const ejson::Array listChannelMap = m_config["input-1-remap"].toArray();
if ( listChannelMap == nullptr if ( listChannelMap.exist() == false
|| listChannelMap->size() == 0) { || listChannelMap.size() == 0) {
m_mapInput1 = m_interfaceInput1->getInterfaceFormat().getMap(); m_mapInput1 = m_interfaceInput1->getInterfaceFormat().getMap();
} else { } else {
m_mapInput1.clear(); m_mapInput1.clear();
for (size_t iii=0; iii<listChannelMap->size(); ++iii) { for (const auto it : listChannelMap) {
std::string value = listChannelMap->getStringValue(iii); std::string value = it.toString().get();
m_mapInput1.push_back(audio::getChannelFromString(value)); m_mapInput1.push_back(audio::getChannelFromString(value));
} }
if (m_mapInput1.size() != m_interfaceInput1->getInterfaceFormat().getMap().size()) { if (m_mapInput1.size() != m_interfaceInput1->getInterfaceFormat().getMap().size()) {
@@ -114,14 +111,14 @@ audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const std::shar
RIVER_ERROR("Can not opne virtual device ... map-on-input-2 in " << _name); RIVER_ERROR("Can not opne virtual device ... map-on-input-2 in " << _name);
return; return;
} }
listChannelMap = m_config->getArray("input-2-remap"); const ejson::Array listChannelMap2 = m_config["input-2-remap"].toArray();
if ( listChannelMap == nullptr if ( listChannelMap2.exist() == false
|| listChannelMap->size() == 0) { || listChannelMap2.size() == 0) {
m_mapInput2 = m_interfaceInput2->getInterfaceFormat().getMap(); m_mapInput2 = m_interfaceInput2->getInterfaceFormat().getMap();
} else { } else {
m_mapInput2.clear(); m_mapInput2.clear();
for (size_t iii=0; iii<listChannelMap->size(); ++iii) { for (const auto it : listChannelMap2) {
std::string value = listChannelMap->getStringValue(iii); std::string value = it.toString().get();
m_mapInput2.push_back(audio::getChannelFromString(value)); m_mapInput2.push_back(audio::getChannelFromString(value));
} }
if (m_mapInput2.size() != m_interfaceInput2->getInterfaceFormat().getMap().size()) { if (m_mapInput2.size() != m_interfaceInput2->getInterfaceFormat().getMap().size()) {
@@ -196,15 +193,17 @@ void audio::river::io::NodeMuxer::onDataReceivedInput1(const void* _data,
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) {
RIVER_DEBUG("Microphone Time=" << _time << " _nbChunk=" << _nbChunk << " _map=" << _map << " _format=" << _format << " freq=" << _frequency); RIVER_PRINT("Input-1 Time=" << _time << " _nbChunk=" << _nbChunk << " _map=" << _map << " _format=" << _format << " freq=" << _frequency);
RIVER_DEBUG(" next=" << _time + audio::Duration(0, _nbChunk*1000000000LL/int64_t(_frequency)) ); RIVER_DEBUG(" next=" << _time + audio::Duration(0, _nbChunk*1000000000LL/int64_t(_frequency)) );
/*
if (_format != audio::format_int16) { if (_format != audio::format_int16) {
RIVER_ERROR("call wrong type ... (need int16_t)"); RIVER_ERROR("call wrong type ... (need int16_t)");
} }
*/
// push data synchronize // push data synchronize
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
m_bufferInput1.write(_data, _nbChunk, _time); m_bufferInput1.write(_data, _nbChunk, _time);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_Microphone.raw", _data, _nbChunk*_map.size()); //RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_input_1.raw", _data, _nbChunk*_map.size());
process(); process();
} }
@@ -214,15 +213,17 @@ void audio::river::io::NodeMuxer::onDataReceivedInput2(const void* _data,
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) {
RIVER_DEBUG("FeedBack Time=" << _time << " _nbChunk=" << _nbChunk << " _map=" << _map << " _format=" << _format << " freq=" << _frequency); RIVER_PRINT("Input-2 Time=" << _time << " _nbChunk=" << _nbChunk << " _map=" << _map << " _format=" << _format << " freq=" << _frequency);
RIVER_DEBUG(" next=" << _time + audio::Duration(0, _nbChunk*1000000000LL/int64_t(_frequency)) ); RIVER_DEBUG(" next=" << _time + audio::Duration(0, _nbChunk*1000000000LL/int64_t(_frequency)) );
/*
if (_format != audio::format_int16) { if (_format != audio::format_int16) {
RIVER_ERROR("call wrong type ... (need int16_t)"); RIVER_ERROR("call wrong type ... (need int16_t)");
} }
*/
// push data synchronize // push data synchronize
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
m_bufferInput2.write(_data, _nbChunk, _time); m_bufferInput2.write(_data, _nbChunk, _time);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_FeedBack.raw", _data, _nbChunk*_map.size()); //RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_input_2.raw", _data, _nbChunk*_map.size());
process(); process();
} }
@@ -233,6 +234,7 @@ void audio::river::io::NodeMuxer::process() {
if (m_bufferInput2.getSize() <= 256) { if (m_bufferInput2.getSize() <= 256) {
return; return;
} }
RIVER_PRINT("process : s1=" << m_bufferInput1.getSize() << " s2=" << m_bufferInput2.getSize());
audio::Time in1Time = m_bufferInput1.getReadTimeStamp(); audio::Time in1Time = m_bufferInput1.getReadTimeStamp();
audio::Time in2Time = m_bufferInput2.getReadTimeStamp(); audio::Time in2Time = m_bufferInput2.getReadTimeStamp();
audio::Duration delta; audio::Duration delta;
@@ -241,18 +243,17 @@ void audio::river::io::NodeMuxer::process() {
} else { } else {
delta = in1Time - in2Time; delta = in1Time - in2Time;
} }
RIVER_VERBOSE("check delta " << delta.count() << " > " << m_sampleTime.count());
RIVER_INFO("check delta " << delta.count() << " > " << m_sampleTime.count());
if (delta > m_sampleTime) { if (delta > m_sampleTime) {
// Synchronize if possible // Synchronize if possible
if (in1Time < in2Time) { if (in1Time < in2Time) {
RIVER_INFO("in1Time < in2Time : Change Microphone time start " << in2Time); RIVER_INFO("in1Time < in2Time : Change Input-1 time start " << in2Time);
RIVER_INFO(" old time stamp=" << m_bufferInput1.getReadTimeStamp()); RIVER_INFO(" old time stamp=" << m_bufferInput1.getReadTimeStamp());
m_bufferInput1.setReadPosition(in2Time); m_bufferInput1.setReadPosition(in2Time);
RIVER_INFO(" new time stamp=" << m_bufferInput1.getReadTimeStamp()); RIVER_INFO(" new time stamp=" << m_bufferInput1.getReadTimeStamp());
} }
if (in1Time > in2Time) { if (in1Time > in2Time) {
RIVER_INFO("in1Time > in2Time : Change FeedBack time start " << in1Time); RIVER_INFO("in1Time > in2Time : Change Input-2 time start " << in1Time);
RIVER_INFO(" old time stamp=" << m_bufferInput2.getReadTimeStamp()); RIVER_INFO(" old time stamp=" << m_bufferInput2.getReadTimeStamp());
m_bufferInput2.setReadPosition(in1Time); m_bufferInput2.setReadPosition(in1Time);
RIVER_INFO(" new time stamp=" << m_bufferInput2.getReadTimeStamp()); RIVER_INFO(" new time stamp=" << m_bufferInput2.getReadTimeStamp());
@@ -275,17 +276,17 @@ void audio::river::io::NodeMuxer::process() {
} }
std::vector<uint8_t> dataIn1; std::vector<uint8_t> dataIn1;
std::vector<uint8_t> dataIn2; std::vector<uint8_t> dataIn2;
dataIn1.resize(256*sizeof(int16_t)*m_mapInput1.size(), 0); dataIn1.resize(256*audio::getFormatBytes(getInterfaceFormat().getFormat())*m_mapInput1.size(), 0);
dataIn2.resize(256*sizeof(int16_t)*m_mapInput2.size(), 0); dataIn2.resize(256*audio::getFormatBytes(getInterfaceFormat().getFormat())*m_mapInput2.size(), 0);
m_data.resize(256*sizeof(int16_t)*getInterfaceFormat().getMap().size(), 0); m_data.resize(256*audio::getFormatBytes(getInterfaceFormat().getFormat())*getInterfaceFormat().getMap().size(), 0);
while (true) { while (true) {
in1Time = m_bufferInput1.getReadTimeStamp(); in1Time = m_bufferInput1.getReadTimeStamp();
in2Time = m_bufferInput2.getReadTimeStamp(); in2Time = m_bufferInput2.getReadTimeStamp();
//RIVER_INFO(" process 256 samples ... in1Time=" << in1Time << " in2Time=" << in2Time << " delta = " << (in1Time-in2Time).count()); //RIVER_INFO(" process 256 samples ... in1Time=" << in1Time << " in2Time=" << in2Time << " delta = " << (in1Time-in2Time).count());
m_bufferInput1.read(&dataIn1[0], 256); m_bufferInput1.read(&dataIn1[0], 256);
m_bufferInput2.read(&dataIn2[0], 256); m_bufferInput2.read(&dataIn2[0], 256);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_INPUT1.raw", &dataIn1[0], 256 * m_mapInput1.size()); //RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_output_1.raw", &dataIn1[0], 256 * m_mapInput1.size());
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_INPUT2.raw", &dataIn2[0], 256 * m_mapInput2.size()); //RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_output_2.raw", &dataIn2[0], 256 * m_mapInput2.size());
// if threaded : send event / otherwise, process ... // if threaded : send event / otherwise, process ...
processMuxer(&dataIn1[0], &dataIn2[0], 256, in1Time); processMuxer(&dataIn1[0], &dataIn2[0], 256, in1Time);
if ( m_bufferInput1.getSize() <= 256 if ( m_bufferInput1.getSize() <= 256
@@ -460,7 +461,7 @@ void audio::river::io::NodeMuxer::generateDot(etk::FSNode& _node) {
if (m_listAvaillable[iii].expired() == true) { if (m_listAvaillable[iii].expired() == true) {
continue; continue;
} }
std::shared_ptr<audio::river::Interface> element = m_listAvaillable[iii].lock(); ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == nullptr) { if (element == nullptr) {
continue; continue;
} }

View File

@@ -5,9 +5,9 @@
*/ */
#pragma once #pragma once
#include <audio/river/io/Node.h> #include <audio/river/io/Node.hpp>
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <audio/drain/CircularBuffer.h> #include <audio/drain/CircularBuffer.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -18,9 +18,9 @@ namespace audio {
/** /**
* @brief Constructor * @brief Constructor
*/ */
NodeMuxer(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); NodeMuxer(const std::string& _name, const ejson::Object& _config);
public: public:
static std::shared_ptr<NodeMuxer> create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); static ememory::SharedPtr<NodeMuxer> create(const std::string& _name, const ejson::Object& _config);
/** /**
* @brief Destructor * @brief Destructor
*/ */
@@ -28,9 +28,9 @@ namespace audio {
protected: protected:
virtual void start(); virtual void start();
virtual void stop(); virtual void stop();
std::shared_ptr<audio::river::Interface> m_interfaceInput1; ememory::SharedPtr<audio::river::Interface> m_interfaceInput1;
std::shared_ptr<audio::river::Interface> m_interfaceInput2; ememory::SharedPtr<audio::river::Interface> m_interfaceInput2;
std::shared_ptr<audio::river::Interface> createInput(float _freq, ememory::SharedPtr<audio::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,

View File

@@ -6,12 +6,9 @@
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA #ifdef AUDIO_RIVER_BUILD_ORCHESTRA
#include <audio/river/io/NodeOrchestra.h> #include <audio/river/io/NodeOrchestra.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <memory> #include <ememory/memory.hpp>
#undef __class__
#define __class__ "io::NodeOrchestra"
int32_t audio::river::io::NodeOrchestra::recordCallback(const void* _inputBuffer, int32_t audio::river::io::NodeOrchestra::recordCallback(const void* _inputBuffer,
const audio::Time& _timeInput, const audio::Time& _timeInput,
@@ -30,18 +27,18 @@ int32_t audio::river::io::NodeOrchestra::playbackCallback(void* _outputBuffer,
const std::vector<audio::orchestra::status>& _status) { const std::vector<audio::orchestra::status>& _status) {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Manage status ... // TODO : Manage status ...
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size()); RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size() << " data=" << uint64_t(_outputBuffer));
newOutput(_outputBuffer, _nbChunk, _timeOutput); newOutput(_outputBuffer, _nbChunk, _timeOutput);
return 0; return 0;
} }
std::shared_ptr<audio::river::io::NodeOrchestra> audio::river::io::NodeOrchestra::create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) { ememory::SharedPtr<audio::river::io::NodeOrchestra> audio::river::io::NodeOrchestra::create(const std::string& _name, const ejson::Object& _config) {
return std::shared_ptr<audio::river::io::NodeOrchestra>(new audio::river::io::NodeOrchestra(_name, _config)); return ememory::SharedPtr<audio::river::io::NodeOrchestra>(new audio::river::io::NodeOrchestra(_name, _config));
} }
audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) : audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) { Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat(); audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat(); audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@@ -52,25 +49,25 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const s
}, },
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user) nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
*/ */
std::string typeInterface = audio::orchestra::type_undefined; std::string typeInterface = audio::orchestra::typeUndefined;
std::string streamName = "default"; std::string streamName = "default";
const std::shared_ptr<const ejson::Object> tmpObject = m_config->getObject("map-on"); const ejson::Object tmpObject = m_config["map-on"].toObject();
if (tmpObject == nullptr) { if (tmpObject.exist() == false) {
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'"); RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
} else { } else {
typeInterface = tmpObject->getStringValue("interface", audio::orchestra::type_undefined); typeInterface = tmpObject["interface"].toString().get(audio::orchestra::typeUndefined);
if (typeInterface == "auto") { if (typeInterface == "auto") {
typeInterface = audio::orchestra::type_undefined; typeInterface = audio::orchestra::typeUndefined;
} }
streamName = tmpObject->getStringValue("name", "default"); streamName = tmpObject["name"].toString().get("default");
} }
int32_t nbChunk = m_config->getNumberValue("nb-chunk", 1024); int32_t nbChunk = m_config["nb-chunk"].toNumber().get(1024);
// intanciate specific API ... // intanciate specific API ...
m_interface.instanciate(typeInterface); m_interface.instanciate(typeInterface);
m_interface.setName(_name); m_interface.setName(_name);
// TODO : Check return ... // TODO : Check return ...
std::string type = m_config->getStringValue("type", "int16"); std::string type = m_config["type"].toString().get("int16");
if (streamName == "") { if (streamName == "") {
streamName = "default"; streamName = "default";
} }
@@ -148,7 +145,8 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const s
RIVER_CRITICAL("auto set format no element in the configuration: " << m_info.nativeFormats); RIVER_CRITICAL("auto set format no element in the configuration: " << m_info.nativeFormats);
} }
} else { } else {
RIVER_CRITICAL("Can not manage input transforamtion: " << hardwareFormat.getFormat() << " not in " << m_info.nativeFormats); RIVER_ERROR("Can not manage input transforamtion: " << hardwareFormat.getFormat() << " not in " << m_info.nativeFormats);
hardwareFormat.setFormat(hardwareFormat.getFormat());
} }
} }
if (etk::isIn(hardwareFormat.getFrequency(), m_info.sampleRates) == false) { if (etk::isIn(hardwareFormat.getFrequency(), m_info.sampleRates) == false) {
@@ -174,7 +172,7 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const s
hardwareFormat.setFrequency(m_info.sampleRates[0]); hardwareFormat.setFrequency(m_info.sampleRates[0]);
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency() << "(first element in list) in " << m_info.sampleRates); RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency() << "(first element in list) in " << m_info.sampleRates);
} else { } else {
RIVER_CRITICAL("Can not manage input transforamtion:" << hardwareFormat.getFrequency() << " not in " << m_info.sampleRates); RIVER_ERROR("Can not manage input transforamtion:" << hardwareFormat.getFrequency() << " not in " << m_info.sampleRates);
} }
interfaceFormat.setFrequency(hardwareFormat.getFrequency()); interfaceFormat.setFrequency(hardwareFormat.getFrequency());
} }
@@ -186,10 +184,10 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const s
params.deviceName = streamName; params.deviceName = streamName;
params.nChannels = hardwareFormat.getMap().size(); params.nChannels = hardwareFormat.getMap().size();
if (m_info.channels.size() < params.nChannels) { if (m_info.channels.size() < params.nChannels) {
RIVER_CRITICAL("Can not open hardware device with more channel (" << params.nChannels << ") that is autorized by hardware (" << m_info.channels.size() << ")."); RIVER_ERROR("Can not open hardware device with more channel (" << params.nChannels << ") that is autorized by hardware (" << m_info.channels.size() << ").");
} }
audio::orchestra::StreamOptions option; audio::orchestra::StreamOptions option;
etk::from_string(option.mode, tmpObject->getStringValue("timestamp-mode", "soft")); etk::from_string(option.mode, tmpObject["timestamp-mode"].toString().get("soft"));
RIVER_DEBUG("interfaceFormat=" << interfaceFormat); RIVER_DEBUG("interfaceFormat=" << interfaceFormat);
RIVER_DEBUG("hardwareFormat=" << hardwareFormat); RIVER_DEBUG("hardwareFormat=" << hardwareFormat);

View File

@@ -7,8 +7,8 @@
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA #ifdef AUDIO_RIVER_BUILD_ORCHESTRA
#include <audio/river/io/Node.h> #include <audio/river/io/Node.hpp>
#include <audio/orchestra/Interface.h> #include <audio/orchestra/Interface.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
@@ -24,9 +24,9 @@ namespace audio {
/** /**
* @brief Constructor * @brief Constructor
*/ */
NodeOrchestra(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); NodeOrchestra(const std::string& _name, const ejson::Object& _config);
public: public:
static std::shared_ptr<NodeOrchestra> create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); static ememory::SharedPtr<NodeOrchestra> create(const std::string& _name, const ejson::Object& _config);
/** /**
* @brief Destructor * @brief Destructor
*/ */

View File

@@ -6,14 +6,11 @@
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO #ifdef AUDIO_RIVER_BUILD_PORTAUDIO
#include <audio/river/io/NodePortAudio.h> #include <audio/river/io/NodePortAudio.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <memory> #include <ememory/memory.hpp>
#include <audio/Time.h> #include <audio/Time.hpp>
#include <audio/Duration.h> #include <audio/Duration.hpp>
#undef __class__
#define __class__ "io::NodePortAudio"
static int portAudioStreamCallback(const void *_input, static int portAudioStreamCallback(const void *_input,
void *_output, void *_output,
@@ -56,11 +53,11 @@ int32_t audio::river::io::NodePortAudio::duplexCallback(const void* _inputBuffer
} }
std::shared_ptr<audio::river::io::NodePortAudio> audio::river::io::NodePortAudio::create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) { ememory::SharedPtr<audio::river::io::NodePortAudio> audio::river::io::NodePortAudio::create(const std::string& _name, const ejson::Object& _config) {
return std::shared_ptr<audio::river::io::NodePortAudio>(new audio::river::io::NodePortAudio(_name, _config)); return ememory::SharedPtr<audio::river::io::NodePortAudio>(new audio::river::io::NodePortAudio(_name, _config));
} }
audio::river::io::NodePortAudio::NodePortAudio(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config) : audio::river::io::NodePortAudio::NodePortAudio(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) { Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat(); audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat(); audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@@ -72,14 +69,14 @@ audio::river::io::NodePortAudio::NodePortAudio(const std::string& _name, const s
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user) nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
*/ */
std::string streamName = "default"; std::string streamName = "default";
const std::shared_ptr<const ejson::Object> tmpObject = m_config->getObject("map-on"); const ejson::Object tmpObject = m_config["map-on"].toObject();
if (tmpObject == nullptr) { if (tmpObject.exist() == false) {
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'"); RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
} else { } else {
std::string value = tmpObject->getStringValue("interface", "default"); std::string value = tmpObject.getStringValue("interface", "default");
streamName = tmpObject->getStringValue("name", "default"); streamName = tmpObject.getStringValue("name", "default");
} }
int32_t nbChunk = m_config->getNumberValue("nb-chunk", 1024); int32_t nbChunk = m_config.getNumberValue("nb-chunk", 1024);
PaError err = 0; PaError err = 0;
if (m_isInput == true) { if (m_isInput == true) {

View File

@@ -7,23 +7,23 @@
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO #ifdef AUDIO_RIVER_BUILD_PORTAUDIO
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <audio/river/io/Node.h> #include <audio/river/io/Node.hpp>
#include <portaudio/portaudio.h> #include <portaudio/portaudio.hpp>
namespace audio { namespace audio {
namespace river { namespace river {
namespace io { namespace io {
class Manager; class Manager;
//! @not-in-doc //! @not_in_doc
class NodePortAudio : public Node { class NodePortAudio : public Node {
protected: protected:
/** /**
* @brief Constructor * @brief Constructor
*/ */
NodePortAudio(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); NodePortAudio(const std::string& _name, const ejson::Object& _config);
public: public:
static std::shared_ptr<NodePortAudio> create(const std::string& _name, const std::shared_ptr<const ejson::Object>& _config); static ememory::SharedPtr<NodePortAudio> create(const std::string& _name, const ejson::Object& _config);
/** /**
* @brief Destructor * @brief Destructor
*/ */

View File

@@ -4,9 +4,9 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/river.h> #include <audio/river/river.hpp>
#include <audio/river/debug.h> #include <audio/river/debug.hpp>
#include <audio/river/io/Manager.h> #include <audio/river/io/Manager.hpp>
static bool river_isInit = false; static bool river_isInit = false;
static std::string river_configFile = ""; static std::string river_configFile = "";
@@ -18,7 +18,7 @@ void audio::river::init(const std::string& _filename) {
river_isInit = true; river_isInit = true;
river_configFile = _filename; river_configFile = _filename;
RIVER_DEBUG("init RIVER :" << river_configFile); RIVER_DEBUG("init RIVER :" << river_configFile);
std::shared_ptr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
if (mng != nullptr) { if (mng != nullptr) {
mng->init(river_configFile); mng->init(river_configFile);
} }
@@ -32,7 +32,7 @@ void audio::river::initString(const std::string& _config) {
river_isInit = true; river_isInit = true;
river_configFile = _config; river_configFile = _config;
RIVER_DEBUG("init RIVER with config."); RIVER_DEBUG("init RIVER with config.");
std::shared_ptr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
if (mng != nullptr) { if (mng != nullptr) {
mng->initString(river_configFile); mng->initString(river_configFile);
} }
@@ -45,7 +45,7 @@ void audio::river::unInit() {
if (river_isInit == true) { if (river_isInit == true) {
river_isInit = false; river_isInit = false;
RIVER_DEBUG("un-init RIVER."); RIVER_DEBUG("un-init RIVER.");
std::shared_ptr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance(); ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
if (mng != nullptr) { if (mng != nullptr) {
RIVER_ERROR("Can not get on the RIVER hardware manager !!!"); RIVER_ERROR("Can not get on the RIVER hardware manager !!!");
mng->unInit(); mng->unInit();

View File

@@ -5,9 +5,14 @@
*/ */
#pragma once #pragma once
#include <etk/types.h> #include <etk/types.hpp>
/**
* @brief Audio library namespace
*/
namespace audio { namespace audio {
/**
* @brief Audio-river library namespace
*/
namespace river { namespace river {
/** /**
* @brief Initialize the River Library * @brief Initialize the River Library

1
authors.txt Normal file
View File

@@ -0,0 +1 @@
MR Edouard DUPIN <yui.heero@gmail.com>

View File

@@ -1,79 +0,0 @@
cmake_minimum_required(VERSION 2.8.3)
project(audio_river)
set(CMAKE_VERBOSE_MAKEFILE ON)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
audio_drain
audio
audio_orchestra
ejson
)
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
INCLUDE_DIRS ../
LIBRARIES ${PROJECT_NAME}
CATKIN_DEPENDS audio_orchestra audio audio_drain ejson
DEPENDS system_lib
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
..
${catkin_INCLUDE_DIRS}
)
## Declare a cpp library
add_library(${PROJECT_NAME}
../audio/river/debug.cpp
../audio/river/river.cpp
../audio/river/Manager.cpp
../audio/river/Interface.cpp
../audio/river/io/Group.cpp
../audio/river/io/Node.cpp
../audio/river/io/NodeOrchestra.cpp
../audio/river/io/NodePortAudio.cpp
../audio/river/io/NodeAEC.cpp
../audio/river/io/NodeMuxer.cpp
../audio/river/io/Manager.cpp
)
add_definitions(-DAUDIO_RIVER_BUILD_ORCHESTRA)
## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
)
#############
## Install ##
#############
## Mark executables and/or libraries for installation
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
)
## Mark cpp header files for installation
install(DIRECTORY ../audio/river/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
)

View File

@@ -1,17 +0,0 @@
<?xml version="1.0"?>
<package>
<name>audio_river</name>
<version>0.3.0</version>
<description>Ewol River Intrerface : Is to multiple acces on different format on Audio IO</description>
<maintainer email="yui.heero@gmail.com">Edouard DUPIN</maintainer>
<license>Apache-2.0</license>
<build_depend>ejson</build_depend>
<build_depend>audio</build_depend>
<build_depend>audio_orchestra</build_depend>
<build_depend>audio_drain</build_depend>
<buildtool_depend>catkin</buildtool_depend>
<run_depend>ejson</run_depend>
<run_depend>audio</run_depend>
<run_depend>audio_orchestra</run_depend>
<run_depend>audio_drain</run_depend>
</package>

View File

@@ -1,41 +0,0 @@
=?=RIVER: Bases =?=
__________________________________________________
[right][tutorial[000_Build | Next: Tutorals]][/right]
=== Overview:===
===User requires:===
To use ewol you need to know only C++ language. It could be usefull to know:
:** [b]Python[/b] for all build tool.
:** [b]git[/b] for all version management
:** [b]Audio[/b] Basic knowlege of audio streaming af data organisation.
=== Architecture:===
River has been designed to replace the pulseAudio basic asyncronous interface that create
more problem that it will solve. The second point is that is not enougth portable to be
embended in a proprietary software without distributing all the sources (Ios).
Start at this point we will have simple objectives :
:** manage multiple Low level interface: (done by the [lib[airtaudio | AirTAudio]] interface):
::** for linux
:::** Alsa
:::** Pulse
:::** Oss
::** for Mac-OsX
:::** CoreAudio
::** for IOs
:::** CoreAudio (embended version)
::** for Windows
:::** ASIO
::** For Android
:::** Java (JDK-6)
:** Synchronous interface ==> no delay and reduce latency
:** Manage the thread priority (need sometimes to be more reactive)
:** manage mixing of some flow (2 inputs stereo and the user want 1 input quad)
:** AEC Acoustic Echo Cancelation (TODO : in the current implementation we have a simple sound cutter)
:** Equalizer (done with [lib[drain | Drain])
:** Resmpling (done by the libspeexDSP)
:** Correct volume management (and configurable)
:** Fade-in and Fade-out (done with [lib[drain | Drain])
:** Channel reorganisation (done with [lib[drain | Drain])
:** A correct feedback interface

100
doc/build.md Normal file
View File

@@ -0,0 +1,100 @@
Build lib & build sample {#audio_river_build}
========================
@tableofcontents
Download: {#audio_river_build_download}
=========
ege use some tools to manage source and build it:
need google repo: {#audio_river_build_download_repo}
-----------------
see: http://source.android.com/source/downloading.html#installing-repo
On all platform:
```{.sh}
mkdir ~/.bin
PATH=~/.bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+x ~/.bin/repo
```
On ubuntu
```{.sh}
sudo apt-get install repo
```
On archlinux
```{.sh}
sudo pacman -S repo
```
lutin (build-system): {#audio_river_build_download_lutin}
---------------------
```{.sh}
pip install lutin --user
# optionnal dependency of lutin (manage image changing size for application release)
pip install pillow --user
```
dependency: {#audio_river_build_download_dependency}
-----------
```{.sh}
mkdir -p WORKING_DIRECTORY/framework
cd WORKING_DIRECTORY/framework
repo init -u git://github.com/atria-soft/manifest.git
repo sync -j8
cd ../..
```
sources: {#audio_river_build_download_sources}
--------
They are already download in the repo manifest in:
```{.sh}
cd WORKING_DIRECTORY/framework/musicdsp/audio-river
```
Build: {#audio_river_build_build}
======
you must stay in zour working directory...
```{.sh}
cd WORKING_DIRECTORY
```
library: {#audio_river_build_build_library}
--------
```{.sh}
lutin -mdebug audio-river
```
Sample: {#audio_river_build_build_sample}
-------
```{.sh}
lutin -mdebug audio-river-sample-read?run
lutin -mdebug audio-river-sample-write?run
```
A fast way:
```{.sh}
lutin -mdebug audio-river-*
```
Run sample: {#audio_river_build_run_sample}
===========
in distinct bash:
```{.sh}
lutin -mdebug audio-river-sample-read?run
lutin -mdebug audio-river-sample-write?run
```

77
doc/configFile.md Normal file
View File

@@ -0,0 +1,77 @@
River configuration file {#audio_river_config_file}
========================
@tableofcontents
Objectifs: {#audio_river_config_file_objectif}
==========
- Understand the architecture of the configuration file.
- all that can be done with it.
Basis: {#audio_river_config_file_bases}
======
The river configuration file is a json file. We use @ref ejson_mainpage_what to parse it then we have some writing facilities.
River provide a list a harware interface and virtual interface.
The hardware interface are provided by @ref audio_orchestra_mainpage_what then we will plug on every platform.
The file is simply architecture around a list of object:
```{.json}
{
"speaker":{
},
"microphone":{
},
"mixed-in-out":{
},
}
```
With this config we declare 3 interfaces : speaker, microphone and mixed-in-out.
Harware configuration: {#audio_river_config_file_hw_config}
======================
In every interface we need to define some Element:
- "io" : Can be input/output/... depending of virtual interface...
- "map-on": An object to configure airtaudio interface.
- "frequency": 0 to automatic select one. Or the frequency to open harware device
- "channel-map": List of all channel in the stream:
* "front-left"
* "front-center"
* "front-right"
* "rear-left"
* "rear-center"
* "rear-right"
* "surround-left",
* "surround-right",
* "sub-woofer",
* "lfe"
- "type": Fomat to open the stream:
* "auto": Detect the best type
* "int8",
* "int8-on-int16",
* "int16",
* "int16-on-int32",
* "int24",
* "int32",
* "int32-on-int64",
* "int64",
* "float",
* "double"
- "nb-chunk": Number of chunk to open the stream.

View File

@@ -1,36 +0,0 @@
=?= FAQ =?=
== What is ewol licence ==
This is really simple : APACHE-2 :
Copyright ewol Edouard DUPIN
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
[[http://www.apache.org/licenses/LICENSE-2.0]]
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
== Why we use "DECLARE_FACTORY" Macro ? ==
For some reason!!! But everything might be clear:
:** In ewol we masively use std::shared_ptr<xxx> (I have create my own but it is not "standard" (I like when we use genecic system)).
:** The main class : [class[ewol::Object]] herited from [i]std::enable_shared_from_this<Object>[/i] to permit to access at his own [i]std::shared_ptr[/i].
:** Acces At his own [i]std::shared_ptr[/i] is not allowed in the class contructor/destructor.
:** Many time for meta-widget we need to propagate our [i]std::shared_ptr[/i] in child.
Then for all these reasons, I have create a simple MACRO that create a static template funtion that create the object and just after
creation call the init(...) function to permit to create a complex widget or others with some writing convinience.

View File

@@ -1,8 +1,15 @@
Read stream feedback {#audio_river_feedback}
====================
=== Objectif === @tableofcontents
:** Implement a feedback.
=== Bases: === Objectifs: {#audio_river_feedback_objectif}
==========
- Implement a feedback.
Bases: {#audio_river_feedback_base}
======
A feedback is a stream that is generated by an output. A feedback is a stream that is generated by an output.
@@ -11,15 +18,13 @@ To get a feedback this is the same implementation of an input and link it on an
What change: What change:
[code style=c++] ```{.cpp}
//Get the generic feedback on speaker: //Get the generic feedback on speaker:
interface = manager->createFeedback(48000, interface = manager->createFeedback(48000,
std::vector<audio::channel>(), std::vector<audio::channel>(),
audio::format_int16, audio::format_int16,
"speaker"); "speaker");
[/code] ```
[note] **Note:** Input interface does not provide feedback.
Input interface does not provide feedback.
[/note]

View File

@@ -1,69 +0,0 @@
== [center]RIVER library[/center] ==
__________________________________________________
===What is RIVER, and how can I use it?===
RIVER is a multi-platform library to manage the input and output audio flow.
It can be compared with PulseAudio or Jack, but at the difference at the 2 interfaces
it is designed to be multi-platform and is based on licence that permit to integrate it
on every program we want.
===Where can I use it?===
Everywhere! RIVER is cross-platform devolopped to support bases OS:
: ** Linux (over Alsa, Pulseaudio, JackD)
: ** Windows (over ASIO)
: ** MacOs (over CoreAudio)
: ** Android (Over Ewol wrapper little complicated need to be change later)
: ** IOs (over CoreAudio for ios)
===What languages are supported?===
RIVER is written in C++11 with posibilities to compile it with C++03 + Boost
===Are there any licensing restrictions?===
RIVER is [b]FREE software[/b] and [i]all sub-library are FREE and staticly linkable !!![/i]
That allow you to use it for every program you want, including those developing proprietary software, without any license fees or royalties.
[note]The static support is important for some platform like IOs, and this limit the external library use at some license like :
:** BSD*
:** MIT
:** APPACHE-2
:** PNG
:** ZLIB
This exclude the classical extern library with licence:
:** L-GPL
:** GPL
[/note]
==== License (APACHE 2) ====
Copyright ewol Edouard DUPIN
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
[[http://www.apache.org/licenses/LICENSE-2.0]]
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==== Depends library: ====
===== License: =====
:** [b][lib[etk | e-tk]][/b] : APACHE-2
:** [b][lib[airtaudio | airtaudio]][/b] : MIT/APACHE-2
:** [b][lib[ejson | e-json]][/b] : APACHE-2
:** [b][lib[drain | Drain]][/b] : APACHE-2
===== Program Using RIVER =====
:** [b][[http://play.google.com/store/apps/details?id=com.edouarddupin.worddown | worddown]][/b] : (Proprietary) Worddown is a simple word game threw [lib[ewolsa | ewol-simple-audio]].
== Main documentation: ==
[doc[001_bases | Global Documantation]]
[tutorial[000_Build | Tutorials]]

92
doc/mainpage.md Normal file
View File

@@ -0,0 +1,92 @@
AUDIO-RIVER library {#mainpage}
===================
@tableofcontents
What is AUDIO-RIVER: {#audio_river_mainpage_what}
====================
AUDIO-RIVER, is a multi-platform library to manage the input and output audio flow.
It can be compared with PulseAudio or Jack, but at the difference at the 2 interfaces
it is designed to be multi-platform and is based on licence that permit to integrate it
on every program we want.
What it does: {#audio_river_mainpage_what_it_does}
=============
Everywhere! RIVER is cross-platform devolopped to support bases OS:
: ** Linux (over Alsa, Pulseaudio, JackD)
: ** Windows (over ASIO)
: ** MacOs (over CoreAudio)
: ** Android (Over Ewol wrapper little complicated need to be change later)
: ** IOs (over CoreAudio for ios)
AUDIO-RIVER is dependent of the STL (compatible with MacOs stl (CXX))
Architecture:
-------------
River has been designed to replace the pulseAudio basic asyncronous interface that create
more problem that it will solve. The second point is that is not enougth portable to be
embended in a proprietary software without distributing all the sources (Ios).
Start at this point we will have simple objectives :
- Manage multiple Low level interface: @ref audio_orchestra_mainpage_what
* for linux (Alsa, Pulse, Oss)
* for Mac-OsX (CoreAudio)
* for IOs (coreAudio (embended version))
* for Windows (ASIO)
* For Android (Java (JDK...))
- Synchronous interface ==> no delay and reduce latency
- Manage the thread priority (need sometimes to be more reactive)
- manage mixing of some flow (2 inputs stereo and the user want 1 input quad)
- AEC Acoustic Echo Cancelation (TODO : in the current implementation we have a simple sound cutter)
- Equalizer (done with @ref audio_drain_mainpage_what)
- Resmpling (done by the libspeexDSP)
- Correct volume management (and configurable)
- Fade-in and Fade-out @ref audio_drain_mainpage_what
- Channel reorganisation @ref audio_drain_mainpage_what
- A correct feedback interface
What languages are supported? {#audio_river_mainpage_language}
=============================
AUDIO-RIVER is written in C++.
Are there any licensing restrictions? {#audio_river_mainpage_license_restriction}
=====================================
AUDIO-RIVER is **FREE software** and _all sub-library are FREE and staticly linkable !!!_
License (APACHE-2.0) {#audio_river_mainpage_license}
====================
Copyright AUDIO-RIVER Edouard DUPIN
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
<http://www.apache.org/licenses/LICENSE-2.0>
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Other pages {#audio_river_mainpage_sub_page}
===========
- @ref audio_river_build
- @ref audio_river_read
- @ref audio_river_write
- @ref audio_river_feedback
- @ref audio_river_config_file
- [**ewol coding style**](http://atria-soft.github.io/ewol/ewol_coding_style.html)

115
doc/read.md Normal file
View File

@@ -0,0 +1,115 @@
Read stream form Audio input {#audio_river_read}
============================
@tableofcontents
Objectifs: {#audio_river_read_objectif}
==========
- Understand basis of river
- Create a simple recording interface that print the average of sample absolute value.
When you will create an application based on the river audio interface you need :
Include: {#audio_river_read_include}
========
Include manager and interface node
@snippet read.cpp audio_river_sample_include
Initilize the River library: {#audio_river_read_init}
============================
We first need to initialize etk sub library (needed to select the log level of sub-libraries and file access abstraction
@snippet read.cpp audio_river_sample_init
Now we will initilaize the river library.
To do this We have 2 posibilities:
With a file:
------------
```{.cpp}
// initialize river interface
river::init("DATA:configFileName.json");
```
With a json string:
-------------------
@snippet read.cpp audio_river_sample_read_config_file
```{.cpp}
// initialize river interface
river::initString(configurationRiver);
```
For the example we select the second solution (faster to implement example and resource at the same position.
river::init / river::initString must be called only one time for all the application, this represent the hardware configuration.
It is NOT dynamic
To understand the configuration file Please see @ref audio_river_config_file
This json is parsed by the @ref {#ejson_mainpage_what} it contain some update like:
- Optionnal " in the name of element.
- The possibilities to remplace " with '.
Get the river interface manager: {#audio_river_read_river_interface}
================================
An application can have many interface and only one Manager. And a process can contain many application.
Then, we will get the first application manager handle.
@snippet read.cpp audio_river_sample_get_interface
*Note:* You can get back the application handle when you create a new one with the same name.
Create your read interface: {#audio_river_read_river_read_interface}
===========================
Generic code:
@snippet read.cpp audio_river_sample_create_read_interface
Here we create an interface with:
- The frequency of 48000 Hz.
- The default Low level definition channel
- A data interface of 16 bits samples coded in [-32768..32767]
- Select input interaface name "microphone"
set data callback: {#audio_river_read_get_data}
==================
The best way to get data is to instanciate a simple callback.
The callback is called when sample arrive and you have the nbChunk/frequency
to process the data, otherwise you can generate error in data stream.
@snippet read.cpp audio_river_sample_set_callback
Callback inplementation: {#audio_river_read_callback}
========================
Simply declare your function and do what you want inside.
@snippet read.cpp audio_river_sample_callback_implement
start and stop the stream: {#audio_river_read_start_stop}
==========================
@snippet read.cpp audio_river_sample_read_start_stop
Remove interfaces: {#audio_river_read_reset}
==================
@snippet read.cpp audio_river_sample_read_reset
Full Sample: {#audio_river_read_full_sample}
============
@snippet read.cpp audio_river_sample_read_all

View File

@@ -1,57 +0,0 @@
=?=River extract and build examples an example=?=
All developpement software will start by getting the dependency and the sources.
=== Linux dependency packages ===
[code style=shell]
sudo apt-get install g++ zlib1g-dev libasound2-dev
# if you want to compile with clang :
sudo apt-get install clang
[/code]
=== Download instructions ===
Download the software : This is the simple way You really need only a part of the ewol framework
[code style=shell]
# create a working directory path
mkdir your_workspace_path
cd your_workspace_path
# clone ewol and all sub-library
git clone git://github.com/HeeroYui/ewol.git
cd ewol
git submodule init
git submodule update
cd ..
[/code]
If you prefer creating with the packege you needed :
[code style=shell]
mkdir -p your_workspace_path
cd your_workspace_path
# download all you needs
git clone git://github.com/HeeroYui/lutin.git
git clone git://github.com/HeeroYui/etk.git
git clone git://github.com/HeeroYui/audio.git
git clone git://github.com/HeeroYui/ejson.git
git clone git://github.com/HeeroYui/airtaudio.git
git clone git://github.com/HeeroYui/drain.git
git clone git://github.com/HeeroYui/river.git
[/code]
[note]
The full build tool documentation is availlable here : [[http://heeroyui.github.io/lutin/ | lutin]]
[/note]
=== Common build instructions ===
Build the basic examples & test:
[code style=shell]
./ewol/build/lutin.py -mdebug river_sample_read
[/code]
To run an application you will find it directly on the out 'staging' tree :
[code style=shell]
./out/Linux/debug/staging/clang/river_sample_read/usr/bin/river_sample_read -l4
[/code]

View File

@@ -1,158 +0,0 @@
=== Objectif ===
:** Understand basis of river
:** Create a simple recording interface that print the average of sample absolute value.
=== sample source: ===
[[http://github.com/HeeroYui/river.git/sample/read/ | sample source]]
=== Bases: ===
When you will create an application based on the river audio interface you need :
==== Include: ====
Include manager and interface node
[code style=c++]
#include <river/river.h>
#include <river/Manager.h>
#include <river/Interface.h>
[/code]
==== Initilize the River library: ====
We first need to initialize etk sub library (needed to select the log level of sub-libraries and file access abstraction
[code style=c++]
// the only one init for etk:
etk::init(_argc, _argv);
[/code]
Now we will initilaize the river library.
To do this We have 2 posibilities:
:** With a file:
[code style=c++]
// initialize river interface
river::init("DATA:configFileName.json");
[/code]
:** With a json string:
[code style=c++]
static const std::string configurationRiver =
"{\n"
" microphone:{\n"
" io:'input',\n"
" map-on:{\n"
" interface:'auto',\n"
" name:'default',\n"
" },\n"
" frequency:0,\n"
" channel-map:['front-left', 'front-right'],\n"
" type:'auto',\n"
" nb-chunk:1024\n"
" }\n"
"}\n";
// initialize river interface
river::initString(configurationRiver);
[/code]
For the example we select the second solution (faster to implement example and resource at the same position.
river::init / river::initString must be called only one time for all the application, this represent the hardware configuration.
It is Nearly not dynamic
To understand the configuration file Please see [tutorial[004_ConfigurationFile | Configuration file]]
[note]
This json is parsed by the [lib[ejson | e-json library]] it containe some update like:
:** Optionnal " in the name of element.
:** The possibilities to remplace " with '.
[/note]
==== Get the river interface manager: ====
An application can have many interface and only one Manager, And a process can contain many application.
Then, we will get the first application manager handle.
[code style=c++]
// Create the River manager for tha application or part of the application.
std11::shared_ptr<river::Manager> manager = river::Manager::create("river_sample_read");
[/code]
[note]
You can get back the application handle when you create a new one with the same name.
[/note]
==== Create your read interface: ====
[code style=c++]
// create interface:
std11::shared_ptr<river::Interface> interface;
//Get the generic input:
interface = manager->createInput(48000,
std::vector<audio::channel>(),
audio::format_int16,
"microphone");
[/code]
Here we create an interface with:
:** The frequency of 48000 Hz.
:** The default Low level definition channel
:** A data interface of 16 bits samples coded in [-32768..32767]
:** Select input interaface name "microphone"
==== Get datas: ====
The best way to get data is to instanciate a simple callback.
The callback is called when sample arrive and you have the nbChunk/frequency
to process the data, otherwise you can generate error in data stream.
[code style=c++]
// set callback mode ...
interface->setInputCallback(std11::bind(&onDataReceived,
std11::placeholders::_1,
std11::placeholders::_2,
std11::placeholders::_3,
std11::placeholders::_4,
std11::placeholders::_5,
std11::placeholders::_6));
[/code]
==== Callback inplementation: ====
Simply declare your function and do what you want inside.
[code style=c++]
void onDataReceived(const void* _data,
const std11::chrono::system_clock::time_point& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const std::vector<audio::channel>& _map) {
if (_format == audio::format_int16) {
// stuff here
}
}
[/code]
==== start and stop: ====
[code style=c++]
// start the stream
interface->start();
// wait 10 second ...
sleep(10);
// stop the stream
interface->stop();
[/code]
==== Remove interfaces: ====
[code style=c++]
// remove interface and manager.
interface.reset();
manager.reset();
[/code]

View File

@@ -1,84 +0,0 @@
=== Objectif ===
:** Understand write audio stream
=== sample source: ===
[[http://github.com/HeeroYui/river.git/sample/write/ | sample source]]
=== Bases: ===
The writing work nearly like the read turoral. Then we will just see what has change.
==== File configuration: ====
[code style=c++]
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
" map-on:{\n"
" interface:'auto',\n"
" name:'default',\n"
" },\n"
" frequency:0,\n"
" channel-map:['front-left', 'front-right'],\n"
" type:'auto',\n"
" nb-chunk:1024,\n"
" volume-name:'MASTER'\n"
" }\n"
"}\n";
[/code]
==== Create your write interface: ====
[code style=c++]
// create interface:
std11::shared_ptr<river::Interface> interface;
//Get the generic input:
interface = manager->createOutput(48000,
std::vector<audio::channel>(),
audio::format_int16,
"speaker");
[/code]
Here we create an interface with:
:** The frequency of 48000 Hz.
:** The default Low level definition channel
:** A data interface of 16 bits samples coded in [-32768..32767]
:** Select input interaface name "speaker"
==== write datas: ====
The best way to get data is to instanciate a simple callback.
The callback is called when sample are needed and you have the nbChunk/frequency
to generate the data, otherwise you can generate error in data stream.
[code style=c++]
// set callback mode ...
interface->setOutputCallback(std11::bind(&onDataNeeded,
std11::placeholders::_1,
std11::placeholders::_2,
std11::placeholders::_3,
std11::placeholders::_4,
std11::placeholders::_5,
std11::placeholders::_6));
[/code]
==== Callback inplementation: ====
Simply declare your function and do what you want inside.
[code style=c++]
void onDataNeeded(void* _data,
const std11::chrono::system_clock::time_point& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const std::vector<audio::channel>& _map) {
if (_format == audio::format_int16) {
// stuff here
}
}
[/code]

View File

@@ -1,70 +0,0 @@
=== Objectif ===
:** Understand the architecture of the configuration file.
:** all that can be done with it.
=== Basis: ===
The river configuration file is a json file. We use [lib[ejson | e-json library]] to parse it then we have some writing facilities.
River provide a list a harware interface and virtual interface.
The hardware interface are provided by [lib[airtaudio | AirTAudio library]] then we will plug on every platform.
The file is simply architecture around a list of object:
[code style=json]
{
"speaker":{
},
"microphone":{
},
"mixed-in-out":{
},
}
[/code]
With this config we declare 3 interfaces : speaker, microphone and mixed-in-out.
=== Harware configuration: ===
In every interface we need to define some Element:
:** "io" :
:: Can be input/output/... depending of virtual interface...
:** "map-on": An object to configure airtaudio interface.
:** "frequency": 0 to automatic select one. Or the frequency to open harware device
:** "channel-map": List of all channel in the stream:
::** "front-left"
::** "front-center"
::** "front-right"
::** "rear-left"
::** "rear-center"
::** "rear-right"
::** "surround-left",
::** "surround-right",
::** "sub-woofer",
::** "lfe"
:** "type": Fomat to open the stream:
::** "auto": Detect the best type
::** "int8",
::** "int8-on-int16",
::** "int16",
::** "int16-on-int32",
::** "int24",
::** "int32",
::** "int32-on-int64",
::** "int64",
::** "float",
::** "double"
:** "nb-chunk": Number of chunk to open the stream.

53
doc/write.md Normal file
View File

@@ -0,0 +1,53 @@
Write stream to Audio output {#audio_river_write}
============================
@tableofcontents
Objectifs: {#audio_river_write_objectif}
==========
- Understand write audio stream
The writing work nearly like the read turoral. Then we will just see what has change.
File configuration: {#audio_river_write_config}
===================
@snippet write.cpp audio_river_sample_write_config_file
Create your write interface: {#audio_river_write_interface}
============================
Generic code:
@snippet write.cpp audio_river_sample_create_write_interface
Here we create an interface with:
- The frequency of 48000 Hz.
- The default Low level definition channel
- A data interface of 16 bits samples coded in [-32768..32767]
- Select input interaface name "speaker"
set data callback: {#audio_river_write_get_data}
==================
The best way to get data is to instanciate a simple callback.
The callback is called when sample are needed and you have the nbChunk/frequency
to generate the data, otherwise you can generate error in data stream.
@snippet write.cpp audio_river_sample_set_callback
Callback inplementation: {#audio_river_write_callback}
========================
Simply declare your function and do what you want inside.
@snippet write.cpp audio_river_sample_callback_implement
Full Sample: {#audio_river_write_full_sample}
============
@snippet write.cpp audio_river_sample_write_all

37
doxy_audio-river.py Normal file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/python
import os
import doxy.module as module
import doxy.debug as debug
import doxy.tools as tools
def create(target, module_name):
my_module = module.Module(__file__, module_name)
my_module.set_version("version.txt")
my_module.set_title("audio-river: Multi-nodal audio interface")
my_module.set_website("http://musicdsp.github.io/" + module_name)
my_module.set_website_sources("http://github.com/musicdsp/" + module_name)
my_module.add_path([
"audio",
"doc"
])
my_module.add_sample_path([
"sample",
])
my_module.add_depend([
'audio',
'audio-drain',
'audio-orchestra',
'ejson'
])
my_module.add_exclude_symbols([
'*operator<<*',
])
my_module.add_exclude_file([
'debug.h',
])
my_module.add_file_patterns([
'*.h',
'*.md',
])
return my_module

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python #!/usr/bin/python
import lutin.module as module import lutin.debug as debug
import lutin.tools as tools import lutin.tools as tools
@@ -22,14 +22,18 @@ def get_compagny_name():
return "atria-soft" return "atria-soft"
def get_maintainer(): def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return "authors.txt"
def create(target, module_name): def configure(target, my_module):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([ my_module.add_src_file([
'test/main.cpp' 'test/main.cpp'
]) ])
my_module.add_module_depend(['audio-river', 'gtest', 'etk', 'test-debug']) my_module.add_depend([
return my_module 'audio-river',
'gtest',
'etk',
'test-debug'
])
return True

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python #!/usr/bin/python
import lutin.module as module import lutin.debug as debug
import lutin.tools as tools import lutin.tools as tools
@@ -19,13 +19,12 @@ def get_compagny_name():
return "atria-soft" return "atria-soft"
def get_maintainer(): def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return "authors.txt"
def get_version(): def get_version():
return [0,0,0] return "version.txt"
def create(target, module_name): def configure(target, my_module):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([ my_module.add_src_file([
'audio/river/debug.cpp', 'audio/river/debug.cpp',
'audio/river/river.cpp', 'audio/river/river.cpp',
@@ -40,18 +39,22 @@ def create(target, module_name):
'audio/river/io/Manager.cpp' 'audio/river/io/Manager.cpp'
]) ])
my_module.add_header_file([ my_module.add_header_file([
'audio/river/river.h', 'audio/river/river.hpp',
'audio/river/Manager.h', 'audio/river/Manager.hpp',
'audio/river/Interface.h', 'audio/river/Interface.hpp',
'audio/river/io/Group.h', 'audio/river/io/Group.hpp',
'audio/river/io/Node.h', 'audio/river/io/Node.hpp',
'audio/river/io/Manager.h' 'audio/river/io/Manager.hpp'
]) ])
my_module.add_optionnal_module_depend('audio-orchestra', ["c++", "-DAUDIO_RIVER_BUILD_ORCHESTRA"]) my_module.add_optionnal_depend('audio-orchestra', ["c++", "-DAUDIO_RIVER_BUILD_ORCHESTRA"])
my_module.add_optionnal_module_depend('portaudio', ["c++", "-DAUDIO_RIVER_BUILD_PORTAUDIO"]) my_module.add_optionnal_depend('portaudio', ["c++", "-DAUDIO_RIVER_BUILD_PORTAUDIO"])
my_module.add_module_depend(['audio', 'audio-drain', 'ejson']) my_module.add_depend([
my_module.add_path(tools.get_current_path(__file__)) 'audio',
return my_module 'audio-drain',
'ejson'
])
my_module.add_path(".")
return True

View File

@@ -1,19 +0,0 @@
#!/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

@@ -1,21 +1,16 @@
/** /** @file
* @author Edouard DUPIN * @author Edouard DUPIN
* * @copyright 2015, Edouard DUPIN, all right reserved
* @copyright 2010, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file)
*
* @license BSD 3 clauses (see license file)
*/ */
#include <ewol/ewol.h> #include <ewol/ewol.hpp>
#include <appl/debug.h> #include <appl/debug.hpp>
#include <appl/Windows.h> #include <appl/Windows.hpp>
#include <ewol/widget/Label.h> #include <ewol/widget/Label.hpp>
#include <ewol/widget/Button.h> #include <ewol/widget/Button.hpp>
#include <audio/river/widget/TemporalViewer.h> #include <audio/river/widget/TemporalViewer.hpp>
#include <etk/tool.h> #include <etk/tool.hpp>
#undef __class__
#define __class__ "Windows"
appl::Windows::Windows() : appl::Windows::Windows() :
m_composer(nullptr) { m_composer(nullptr) {
@@ -49,19 +44,19 @@ void appl::Windows::init() {
} }
m_composer->loadFromString(composition); m_composer->loadFromString(composition);
setSubWidget(m_composer); setSubWidget(m_composer);
subBind(ewol::widget::Button, "bt-record", signalPressed, shared_from_this(), &appl::Windows::onCallbackRecord); subBind(ewol::widget::Button, "bt-record", signalPressed, sharedFromThis(), &appl::Windows::onCallbackRecord);
subBind(ewol::widget::Button, "bt-generate", signalPressed, shared_from_this(), &appl::Windows::onCallbackGenerate); subBind(ewol::widget::Button, "bt-generate", signalPressed, sharedFromThis(), &appl::Windows::onCallbackGenerate);
} }
void appl::Windows::onCallbackRecord() { void appl::Windows::onCallbackRecord() {
std::shared_ptr<audio::river::widget::TemporalViewer> tmpDisp = std::dynamic_pointer_cast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer")); ememory::SharedPtr<audio::river::widget::TemporalViewer> tmpDisp = ememory::dynamicPointerCast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != nullptr) { if (tmpDisp != nullptr) {
tmpDisp->recordToggle(); tmpDisp->recordToggle();
} }
} }
void appl::Windows::onCallbackGenerate() { void appl::Windows::onCallbackGenerate() {
std::shared_ptr<audio::river::widget::TemporalViewer> tmpDisp = std::dynamic_pointer_cast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer")); ememory::SharedPtr<audio::river::widget::TemporalViewer> tmpDisp = ememory::dynamicPointerCast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != nullptr) { if (tmpDisp != nullptr) {
tmpDisp->generateToggle(); tmpDisp->generateToggle();
} }

View File

@@ -1,19 +1,17 @@
/** /** @file
* @author Edouard DUPIN * @author Edouard DUPIN
* * @copyright 2015, Edouard DUPIN, all right reserved
* @copyright 2010, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file)
*
* @license BSD 3 clauses (see license file)
*/ */
#pragma once #pragma once
#include <ewol/widget/Windows.h> #include <ewol/widget/Windows.hpp>
#include <ewol/widget/Composer.h> #include <ewol/widget/Composer.hpp>
namespace appl { namespace appl {
class Windows : public ewol::widget::Windows { class Windows : public ewol::widget::Windows {
private: private:
std::shared_ptr<ewol::widget::Composer> m_composer; ememory::SharedPtr<ewol::widget::Composer> m_composer;
protected: protected:
Windows(); Windows();
void init(); void init();

View File

@@ -4,7 +4,7 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <appl/debug.h> #include <appl/debug.hpp>
int32_t appl::getLogId() { int32_t appl::getLogId() {

View File

@@ -5,7 +5,7 @@
*/ */
#pragma once #pragma once
#include <elog/log.h> #include <elog/log.hpp>
namespace appl { namespace appl {
int32_t getLogId(); int32_t getLogId();

View File

@@ -1,22 +1,20 @@
/** /** @file
* @author Edouard DUPIN * @author Edouard DUPIN
* * @copyright 2015, Edouard DUPIN, all right reserved
* @copyright 2010, Edouard DUPIN, all right reserved * @license APACHE v2.0 (see license file)
*
* @license BSD 3 clauses (see license file)
*/ */
#include <etk/types.h> #include <etk/types.hpp>
#include <ewol/ewol.h> #include <ewol/ewol.hpp>
#include <gale/context/commandLine.h> #include <gale/context/commandLine.hpp>
#include <appl/debug.h> #include <appl/debug.hpp>
#include <appl/Windows.h> #include <appl/Windows.hpp>
#include <ewol/object/Object.h> #include <ewol/object/Object.hpp>
#include <ewol/widget/Manager.h> #include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.h> #include <ewol/context/Context.hpp>
#include <audio/river/widget/TemporalViewer.h> #include <audio/river/widget/TemporalViewer.hpp>
static const std::string configurationRiver = static const std::string configurationRiver =
"{\n" "{\n"
@@ -49,7 +47,7 @@ class MainApplication : public ewol::context::Application {
audio::river::widget::TemporalViewer::createManagerWidget(_context.getWidgetManager()); audio::river::widget::TemporalViewer::createManagerWidget(_context.getWidgetManager());
std::shared_ptr<ewol::widget::Windows> basicWindows = appl::Windows::create(); ememory::SharedPtr<ewol::widget::Windows> basicWindows = appl::Windows::create();
// create the specific windows // create the specific windows
_context.setWindows(basicWindows); _context.setWindows(basicWindows);
APPL_INFO("==> Init APPL (END)"); APPL_INFO("==> Init APPL (END)");

View File

@@ -1,7 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
import lutin.module as module import lutin.debug as debug
import lutin.tools as tools import lutin.tools as tools
import datetime
import os import os
@@ -23,26 +22,18 @@ def get_compagny_name():
def get_maintainer(): def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name): def configure(target, my_module):
my_module = module.Module(__file__, module_name, get_type()) my_module.add_extra_flags()
my_module.add_extra_compile_flags()
my_module.add_src_file([ my_module.add_src_file([
'appl/debug.cpp', 'appl/debug.cpp',
'appl/main.cpp', 'appl/main.cpp',
'appl/Windows.cpp']) 'appl/Windows.cpp'])
my_module.add_module_depend(['ewol', 'audio-river', 'audio-river-widget']) my_module.add_depend(['ewol', 'audio-river', 'audio-river-widget'])
my_module.add_path(tools.get_current_path(__file__)) my_module.add_path(".")
# set the package properties : # set the package properties :
my_module.pkg_set("VERSION", "1.0.0") my_module.set_pkg("SECTION", ["Development"])
my_module.pkg_set("VERSION_CODE", "1") my_module.set_pkg("PRIORITY", "optional")
my_module.pkg_set("COMPAGNY_TYPE", "org")
my_module.pkg_set("COMPAGNY_NAME", "Edouard DUPIN")
my_module.pkg_set("MAINTAINER", ["Mr DUPIN Edouard <yui.heero@gmail.com>"])
my_module.pkg_set("SECTION", ["Development"])
my_module.pkg_set("PRIORITY", "optional")
my_module.pkg_set("DESCRIPTION", "Simple wiewer")
my_module.pkg_set("NAME", "ioViewer")
my_module.pkg_add("RIGHT", "RECORD_AUDIO") my_module.add_pkg("RIGHT", "RECORD_AUDIO")
return my_module return True

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python #!/usr/bin/python
import lutin.module as module import lutin.debug as debug
import lutin.tools as tools import lutin.tools as tools
@@ -24,13 +24,15 @@ def get_compagny_name():
def get_maintainer(): def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name): def configure(target, my_module):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([ my_module.add_src_file([
'main.cpp', 'read.cpp',
]) ])
my_module.add_module_depend(['audio-river', 'etk']) my_module.add_depend([
return my_module 'audio-river',
'etk'
])
return True

View File

@@ -4,14 +4,19 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/river.h> //! [audio_river_sample_read_all]
#include <audio/river/Manager.h> //! [audio_river_sample_include]
#include <audio/river/Interface.h> #include <audio/river/river.hpp>
#include <etk/os/FSNode.h> #include <audio/river/Manager.hpp>
#include <etk/etk.h> #include <audio/river/Interface.hpp>
#include <unistd.h> //! [audio_river_sample_include]
#include <etk/os/FSNode.hpp>
#include <etk/etk.hpp>
#include <thread>
//! [audio_river_sample_read_config_file]
static const std::string configurationRiver = static const std::string configurationRiver =
"{\n" "{\n"
" microphone:{\n" " microphone:{\n"
@@ -19,6 +24,7 @@ static const std::string configurationRiver =
" map-on:{\n" " map-on:{\n"
" interface:'auto',\n" " interface:'auto',\n"
" name:'default',\n" " name:'default',\n"
//" timestamp-mode:'trigered',\n"
" },\n" " },\n"
" frequency:0,\n" " frequency:0,\n"
" channel-map:['front-left', 'front-right'],\n" " channel-map:['front-left', 'front-right'],\n"
@@ -26,8 +32,10 @@ static const std::string configurationRiver =
" nb-chunk:1024\n" " nb-chunk:1024\n"
" }\n" " }\n"
"}\n"; "}\n";
//! [audio_river_sample_read_config_file]
//! [audio_river_sample_callback_implement]
void onDataReceived(const void* _data, void onDataReceived(const void* _data,
const audio::Time& _time, const audio::Time& _time,
size_t _nbChunk, size_t _nbChunk,
@@ -35,10 +43,14 @@ void onDataReceived(const void* _data,
uint32_t _frequency, uint32_t _frequency,
const std::vector<audio::channel>& _map, const std::vector<audio::channel>& _map,
etk::FSNode* _outputNode) { etk::FSNode* _outputNode) {
if (_format != audio::format_int16) { if ( _format != audio::format_int16
std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl; && _format != audio::format_float) {
std::cout << "[ERROR] call wrong type ... (need int16_t.float)" << std::endl;
return;
} }
//! [audio_river_sample_callback_implement]
if (_outputNode->fileIsOpen() == false) { if (_outputNode->fileIsOpen() == false) {
if (_format != audio::format_int16) {
// get the curent power of the signal. // get the curent power of the signal.
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;
@@ -47,16 +59,28 @@ void onDataReceived(const void* _data,
} }
value /= (_nbChunk*_map.size()); value /= (_nbChunk*_map.size());
std::cout << "Get data ... average=" << int32_t(value) << std::endl; std::cout << "Get data ... average=" << int32_t(value) << std::endl;
} else {
// get the curent power of the signal.
const float* data = static_cast<const float*>(_data);
float value = 0;
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
value += std::abs(data[iii]);
}
value /= (_nbChunk*_map.size());
std::cout << "Get data ... average=" << float(value) << std::endl;
}
} else { } else {
// just write data // just write data
std::cout << "Get data ... chunks=" << _nbChunk << " time=" << _time << std::endl; //std::cout << "Get data ... chunks=" << _nbChunk << " time=" << _time << std::endl;
_outputNode->fileWrite(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk); _outputNode->fileWrite(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
} }
} }
int main(int _argc, const char **_argv) { int main(int _argc, const char **_argv) {
//! [audio_river_sample_init]
// the only one init for etk: // the only one init for etk:
etk::init(_argc, _argv); etk::init(_argc, _argv);
//! [audio_river_sample_init]
// local parameter: // local parameter:
std::string configFile; std::string configFile;
std::string ioName="microphone"; std::string ioName="microphone";
@@ -87,10 +111,13 @@ int main(int _argc, const char **_argv) {
} else { } else {
audio::river::init(configFile); audio::river::init(configFile);
} }
//! [audio_river_sample_get_interface]
// Create the River manager for tha application or part of the application. // Create the River manager for tha application or part of the application.
std::shared_ptr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read"); ememory::SharedPtr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read");
//! [audio_river_sample_get_interface]
//! [audio_river_sample_create_read_interface]
// create interface: // create interface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
//Get the generic input: //Get the generic input:
interface = manager->createInput(48000, interface = manager->createInput(48000,
std::vector<audio::channel>(), std::vector<audio::channel>(),
@@ -100,12 +127,14 @@ int main(int _argc, const char **_argv) {
std::cout << "nullptr interface" << std::endl; std::cout << "nullptr interface" << std::endl;
return -1; return -1;
} }
//! [audio_river_sample_create_read_interface]
etk::FSNode outputNode; etk::FSNode outputNode;
// open output file if needed: // open output file if needed:
if (outputFileName != "") { if (outputFileName != "") {
outputNode.setName(outputFileName); outputNode.setName(outputFileName);
outputNode.fileOpenWrite(); outputNode.fileOpenWrite();
} }
//! [audio_river_sample_set_callback]
// set callback mode ... // set callback mode ...
interface->setInputCallback(std::bind(&onDataReceived, interface->setInputCallback(std::bind(&onDataReceived,
std::placeholders::_1, std::placeholders::_1,
@@ -115,15 +144,20 @@ int main(int _argc, const char **_argv) {
std::placeholders::_5, std::placeholders::_5,
std::placeholders::_6, std::placeholders::_6,
&outputNode)); &outputNode));
//! [audio_river_sample_set_callback]
//! [audio_river_sample_read_start_stop]
// start the stream // start the stream
interface->start(); interface->start();
// wait 10 second ... // wait 10 second ...
sleep(10); std::this_thread::sleep_for(std::chrono::seconds(10));
// stop the stream // stop the stream
interface->stop(); interface->stop();
//! [audio_river_sample_read_start_stop]
//! [audio_river_sample_read_reset]
// remove interface and manager. // remove interface and manager.
interface.reset(); interface.reset();
manager.reset(); manager.reset();
//! [audio_river_sample_read_reset]
// close the output file // close the output file
if (outputFileName != "") { if (outputFileName != "") {
outputNode.fileClose(); outputNode.fileClose();
@@ -131,3 +165,5 @@ int main(int _argc, const char **_argv) {
return 0; return 0;
} }
//! [audio_river_sample_read_all]

View File

@@ -1,5 +1,5 @@
#!/usr/bin/python #!/usr/bin/python
import lutin.module as module import lutin.debug as debug
import lutin.tools as tools import lutin.tools as tools
@@ -24,13 +24,15 @@ def get_compagny_name():
def get_maintainer(): def get_maintainer():
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"] return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
def create(target, module_name): def configure(target, my_module):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([ my_module.add_src_file([
'main.cpp', 'write.cpp',
]) ])
my_module.add_module_depend(['audio-river', 'etk']) my_module.add_depend([
return my_module 'audio-river',
'etk'
])
return True

View File

@@ -4,51 +4,62 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/river.h> //! [audio_river_sample_write_all]
#include <audio/river/Manager.h>
#include <audio/river/Interface.h> #include <audio/river/river.hpp>
#include <etk/etk.h> #include <audio/river/Manager.hpp>
#include <unistd.h> #include <audio/river/Interface.hpp>
#include <etk/etk.hpp>
#include <thread>
//! [audio_river_sample_write_config_file]
static const std::string configurationRiver = static const std::string configurationRiver =
"{\n" "{\n"
" speaker:{\n" " speaker:{\n"
" io:'output',\n" " io:'output',\n"
" map-on:{\n" " map-on:{\n"
" interface:'auto',\n" " interface:'alsa',\n"
" name:'default',\n" " name:'hw:0,0',\n"
" },\n" " },\n"
" frequency:0,\n" " frequency:48000,\n"
//" channel-map:['front-left', 'front-right', 'rear-left', 'rear-right'],\n"
" channel-map:['front-left', 'front-right'],\n" " channel-map:['front-left', 'front-right'],\n"
" type:'auto',\n" " type:'int16',\n"
" nb-chunk:1024,\n" " nb-chunk:1024,\n"
" volume-name:'MASTER'\n" " volume-name:'MASTER'\n"
" }\n" " }\n"
"}\n"; "}\n";
//! [audio_river_sample_write_config_file]
static const int32_t nbChannelMax=8;
//! [audio_river_sample_callback_implement]
void onDataNeeded(void* _data, void onDataNeeded(void* _data,
const audio::Time& _time, const audio::Time& _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) {
static double phase = 0; static double phase[8] = {0,0,0,0,0,0,0,0};
if (_format != audio::format_int16) { if (_format != audio::format_int16) {
std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl; std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl;
} }
//std::cout << "Map " << _map << std::endl;
int16_t* data = static_cast<int16_t*>(_data); int16_t* data = static_cast<int16_t*>(_data);
double baseCycle = 2.0*M_PI/(double)48000 * (double)550; double baseCycle = 2.0*M_PI/double(48000) * double(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] = cos(phase) * 30000; data[_map.size()*iii+jjj] = cos(phase[jjj]) * 30000;
} phase[jjj] += baseCycle*jjj;
phase += baseCycle; if (phase[jjj] >= 2*M_PI) {
if (phase >= 2*M_PI) { phase[jjj] -= 2*M_PI;
phase -= 2*M_PI;
} }
} }
} }
}
//! [audio_river_sample_callback_implement]
int main(int _argc, const char **_argv) { int main(int _argc, const char **_argv) {
// the only one init for etk: // the only one init for etk:
@@ -65,9 +76,10 @@ int main(int _argc, const char **_argv) {
// initialize river interface // initialize river interface
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
// Create the River manager for tha application or part of the application. // Create the River manager for tha application or part of the application.
std::shared_ptr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read"); ememory::SharedPtr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read");
//! [audio_river_sample_create_write_interface]
// create interface: // create interface:
std::shared_ptr<audio::river::Interface> interface; ememory::SharedPtr<audio::river::Interface> interface;
//Get the generic input: //Get the generic input:
interface = manager->createOutput(48000, interface = manager->createOutput(48000,
std::vector<audio::channel>(), std::vector<audio::channel>(),
@@ -77,6 +89,8 @@ int main(int _argc, const char **_argv) {
std::cout << "nullptr interface" << std::endl; std::cout << "nullptr interface" << std::endl;
return -1; return -1;
} }
//! [audio_river_sample_create_write_interface]
//! [audio_river_sample_set_callback]
// set callback mode ... // set callback mode ...
interface->setOutputCallback(std::bind(&onDataNeeded, interface->setOutputCallback(std::bind(&onDataNeeded,
std::placeholders::_1, std::placeholders::_1,
@@ -85,10 +99,11 @@ int main(int _argc, const char **_argv) {
std::placeholders::_4, std::placeholders::_4,
std::placeholders::_5, std::placeholders::_5,
std::placeholders::_6)); std::placeholders::_6));
//! [audio_river_sample_set_callback]
// start the stream // start the stream
interface->start(); interface->start();
// wait 10 second ... // wait 10 second ...
sleep(10); std::this_thread::sleep_for(std::chrono::seconds(10));
// stop the stream // stop the stream
interface->stop(); interface->stop();
// remove interface and manager. // remove interface and manager.
@@ -97,3 +112,5 @@ int main(int _argc, const char **_argv) {
return 0; return 0;
} }
//! [audio_river_sample_write_all]

View File

@@ -1,55 +0,0 @@
cmake_minimum_required(VERSION 2.8.3)
project(audio_river_test)
set(CMAKE_VERBOSE_MAKEFILE ON)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
audio_river
rosconsole
)
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package()
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
..
${catkin_INCLUDE_DIRS}
)
## Declare a cpp library
catkin_add_gtest(${PROJECT_NAME}
../debug.cpp
../main.cpp
)
## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
)
#############
## Install ##
#############
## Mark executables and/or libraries for installation
#install(TARGETS ${PROJECT_NAME}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
#)

View File

@@ -1,13 +0,0 @@
<?xml version="1.0"?>
<package>
<name>audio_river_test</name>
<version>0.3.0</version>
<description>Ewol River test</description>
<maintainer email="yui.heero@gmail.com">Edouard DUPIN</maintainer>
<license>Apache-2.0</license>
<build_depend>gtest</build_depend>
<build_depend>audio_river</build_depend>
<buildtool_depend>catkin</buildtool_depend>
<run_depend>audio_river</run_depend>
<run_depend>gtest</run_depend>
</package>

View File

@@ -4,7 +4,7 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <test-debug/debug.h> #include <test-debug/debug.hpp>
#define TEST_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \ #define TEST_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \
do { \ do { \
@@ -27,29 +27,25 @@
#include <audio/river/river.h> #include <audio/river/river.hpp>
#include <audio/river/Manager.h> #include <audio/river/Manager.hpp>
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <etk/etk.h> #include <etk/etk.hpp>
#include <etk/os/FSNode.h> #include <etk/os/FSNode.hpp>
#include <math.h> #include <cmath>
#include <sstream> #include <sstream>
#include <unistd.h>
#include <thread> #include <thread>
#include "testAEC.h" #include "testAEC.hpp"
#include "testEchoDelay.h" #include "testEchoDelay.hpp"
#include "testFormat.h" #include "testFormat.hpp"
#include "testMuxer.h" #include "testMuxer.hpp"
#include "testPlaybackCallback.h" #include "testPlaybackCallback.hpp"
#include "testPlaybackWrite.h" #include "testPlaybackWrite.hpp"
#include "testRecordCallback.h" #include "testRecordCallback.hpp"
#include "testRecordRead.h" #include "testRecordRead.hpp"
#include "testVolume.h" #include "testVolume.hpp"
#undef __class__
#define __class__ "test"
int main(int _argc, const char** _argv) { int main(int _argc, const char** _argv) {
// init Google test : // init Google test :

View File

@@ -5,19 +5,18 @@
*/ */
#pragma once #pragma once
#undef __class__ #include <test-debug/debug.hpp>
#define __class__ "test_aec"
namespace river_test_aec { namespace river_test_aec {
class Linker { class Linker {
private: private:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interfaceOut; ememory::SharedPtr<audio::river::Interface> m_interfaceOut;
std::shared_ptr<audio::river::Interface> m_interfaceIn; ememory::SharedPtr<audio::river::Interface> m_interfaceIn;
audio::drain::CircularBuffer m_buffer; audio::drain::CircularBuffer m_buffer;
public: public:
Linker(std::shared_ptr<audio::river::Manager> _manager, const std::string& _input, const std::string& _output) : Linker(ememory::SharedPtr<audio::river::Manager> _manager, const std::string& _input, const std::string& _output) :
m_manager(_manager) { m_manager(_manager) {
//Set stereo output: //Set stereo output:
std::vector<audio::channel> channelMap; std::vector<audio::channel> channelMap;
@@ -198,13 +197,13 @@ namespace river_test_aec {
TEST(TestUser, testAECManually) { TEST(TestUser, testAECManually) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<Linker> processLink1 = std::make_shared<Linker>(manager, "microphone-clean", "speaker"); ememory::SharedPtr<Linker> processLink1 = ememory::makeShared<Linker>(manager, "microphone-clean", "speaker");
std::shared_ptr<Linker> processLink2 = std::make_shared<Linker>(manager, "microphone", "speaker-test"); ememory::SharedPtr<Linker> processLink2 = ememory::makeShared<Linker>(manager, "microphone", "speaker-test");
processLink1->start(); processLink1->start();
processLink2->start(); processLink2->start();
sleep(30); std::this_thread::sleep_for(std::chrono::seconds(20));
processLink1->stop(); processLink1->stop();
processLink2->stop(); processLink2->stop();
@@ -215,6 +214,4 @@ namespace river_test_aec {
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,18 +5,15 @@
*/ */
#pragma once #pragma once
#include <test-debug/debug.h> #include <test-debug/debug.hpp>
#undef __class__
#define __class__ "test_echo_delay"
namespace river_test_echo_delay { namespace river_test_echo_delay {
class TestClass { class TestClass {
private: private:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interfaceOut; ememory::SharedPtr<audio::river::Interface> m_interfaceOut;
std::shared_ptr<audio::river::Interface> m_interfaceIn; ememory::SharedPtr<audio::river::Interface> m_interfaceIn;
std::shared_ptr<audio::river::Interface> m_interfaceFB; ememory::SharedPtr<audio::river::Interface> m_interfaceFB;
double m_phase; double m_phase;
double m_freq; double m_freq;
int32_t m_nextSampleCount; int32_t m_nextSampleCount;
@@ -31,7 +28,7 @@ namespace river_test_echo_delay {
int16_t m_volumeInputMin; int16_t m_volumeInputMin;
float m_gain; float m_gain;
public: public:
TestClass(std::shared_ptr<audio::river::Manager> _manager) : TestClass(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager), m_manager(_manager),
m_phase(0), m_phase(0),
m_freq(400), m_freq(400),
@@ -363,9 +360,9 @@ namespace river_test_echo_delay {
m_interfaceIn->start(); m_interfaceIn->start();
//m_interfaceFB->start(); //m_interfaceFB->start();
while (m_estimateVolumeInput == true) { while (m_estimateVolumeInput == true) {
usleep(10000); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
usleep(10000000); std::this_thread::sleep_for(std::chrono::seconds(10));
//m_interfaceFB->stop(); //m_interfaceFB->stop();
m_interfaceIn->stop(); m_interfaceIn->stop();
m_interfaceOut->stop(); m_interfaceOut->stop();
@@ -416,16 +413,14 @@ namespace river_test_echo_delay {
TEST(TestTime, testDelay) { TEST(TestTime, testDelay) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<TestClass> process = std::make_shared<TestClass>(manager); ememory::SharedPtr<TestClass> process = ememory::makeShared<TestClass>(manager);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,9 +5,6 @@
*/ */
#pragma once #pragma once
#undef __class__
#define __class__ "test_format"
namespace river_test_format { namespace river_test_format {
static const std::string configurationRiver = static const std::string configurationRiver =
"{\n" "{\n"
@@ -26,15 +23,15 @@ namespace river_test_format {
"}\n"; "}\n";
class testOutCallbackType { class testOutCallbackType {
private: private:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
double m_phase; double m_phase;
float m_freq; float m_freq;
int32_t m_nbChannels; int32_t m_nbChannels;
float m_generateFreq; float m_generateFreq;
public: public:
testOutCallbackType(const std::shared_ptr<audio::river::Manager>& _manager, testOutCallbackType(const ememory::SharedPtr<audio::river::Manager>& _manager,
float _freq=48000.0f, float _freq=48000.0f,
int32_t _nbChannels=2, int32_t _nbChannels=2,
audio::format _format=audio::format_int16) : audio::format _format=audio::format_int16) :
@@ -139,9 +136,9 @@ namespace river_test_format {
} }
m_interface->start(); m_interface->start();
// wait 2 second ... // wait 2 second ...
usleep(1000000); std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->stop(); m_interface->stop();
usleep(100000); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
}; };
@@ -149,12 +146,12 @@ namespace river_test_format {
class testResampling : public ::testing::TestWithParam<float> {}; class testResampling : public ::testing::TestWithParam<float> {};
TEST_P(testResampling, base) { TEST_P(testResampling, base) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<testOutCallbackType> process = std::make_shared<testOutCallbackType>(manager, GetParam(), 2, audio::format_int16); ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, GetParam(), 2, audio::format_int16);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
@@ -166,12 +163,12 @@ namespace river_test_format {
class testFormat : public ::testing::TestWithParam<audio::format> {}; class testFormat : public ::testing::TestWithParam<audio::format> {};
TEST_P(testFormat, base) { TEST_P(testFormat, base) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<testOutCallbackType> process = std::make_shared<testOutCallbackType>(manager, 48000, 2, GetParam()); ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, 2, GetParam());
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
INSTANTIATE_TEST_CASE_P(InstantiationName, INSTANTIATE_TEST_CASE_P(InstantiationName,
@@ -182,12 +179,12 @@ namespace river_test_format {
class testChannels : public ::testing::TestWithParam<int32_t> {}; class testChannels : public ::testing::TestWithParam<int32_t> {};
TEST_P(testChannels, base) { TEST_P(testChannels, base) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<testOutCallbackType> process = std::make_shared<testOutCallbackType>(manager, 48000, GetParam(), audio::format_int16); ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, GetParam(), audio::format_int16);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
INSTANTIATE_TEST_CASE_P(InstantiationName, INSTANTIATE_TEST_CASE_P(InstantiationName,
@@ -197,7 +194,7 @@ namespace river_test_format {
TEST(TestALL, testChannelsFormatResampling) { TEST(TestALL, testChannelsFormatResampling) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test convert flaot to output (callback mode)"); TEST_INFO("test convert flaot to output (callback mode)");
std::vector<float> listFreq; std::vector<float> listFreq;
@@ -226,19 +223,15 @@ namespace river_test_format {
for (size_t ccc=0; ccc<listChannel.size(); ++ccc) { for (size_t ccc=0; ccc<listChannel.size(); ++ccc) {
for (size_t iii=0; iii<listFormat.size(); ++iii) { for (size_t iii=0; iii<listFormat.size(); ++iii) {
TEST_INFO("freq=" << listFreq[fff] << " channel=" << listChannel[ccc] << " format=" << getFormatString(listFormat[iii])); TEST_INFO("freq=" << listFreq[fff] << " channel=" << listChannel[ccc] << " format=" << getFormatString(listFormat[iii]));
std::shared_ptr<testOutCallbackType> process = std::make_shared<testOutCallbackType>(manager, listFreq[fff], listChannel[ccc], listFormat[iii]); ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, listFreq[fff], listChannel[ccc], listFormat[iii]);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
} }
} }
} }
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,20 +5,17 @@
*/ */
#pragma once #pragma once
#include <test-debug/debug.h> #include <test-debug/debug.hpp>
#undef __class__
#define __class__ "test_muxer"
namespace river_test_muxer { namespace river_test_muxer {
class TestClass { class TestClass {
private: private:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interfaceIn; ememory::SharedPtr<audio::river::Interface> m_interfaceIn;
std::shared_ptr<audio::river::Interface> m_interfaceOut; ememory::SharedPtr<audio::river::Interface> m_interfaceOut;
double m_phase; double m_phase;
public: public:
TestClass(std::shared_ptr<audio::river::Manager> _manager) : TestClass(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager), m_manager(_manager),
m_phase(0) { m_phase(0) {
std::vector<audio::channel> channelMap; std::vector<audio::channel> channelMap;
@@ -106,7 +103,7 @@ namespace river_test_muxer {
} }
m_interfaceOut->start(); m_interfaceOut->start();
m_interfaceIn->start(); m_interfaceIn->start();
usleep(10000000); std::this_thread::sleep_for(std::chrono::seconds(10));
m_interfaceIn->stop(); m_interfaceIn->stop();
m_interfaceOut->stop(); m_interfaceOut->stop();
} }
@@ -166,16 +163,14 @@ namespace river_test_muxer {
TEST(TestMuxer, testMuxing) { TEST(TestMuxer, testMuxing) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<TestClass> process = std::make_shared<TestClass>(manager); ememory::SharedPtr<TestClass> process = ememory::makeShared<TestClass>(manager);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,18 +5,15 @@
*/ */
#pragma once #pragma once
#undef __class__
#define __class__ "test_playback_callback"
namespace river_test_playback_callback { namespace river_test_playback_callback {
class testOutCallback { class testOutCallback {
public: public:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
double m_phase; double m_phase;
public: public:
testOutCallback(std::shared_ptr<audio::river::Manager> _manager, const std::string& _io="speaker") : testOutCallback(ememory::SharedPtr<audio::river::Manager> _manager, const std::string& _io="speaker") :
m_manager(_manager), m_manager(_manager),
m_phase(0) { m_phase(0) {
//Set stereo output: //Set stereo output:
@@ -69,7 +66,7 @@ namespace river_test_playback_callback {
} }
m_interface->start(); m_interface->start();
// wait 2 second ... // wait 2 second ...
usleep(2000000); std::this_thread::sleep_for(std::chrono::seconds(2));
m_interface->stop(); m_interface->stop();
} }
}; };
@@ -92,47 +89,42 @@ namespace river_test_playback_callback {
TEST(TestALL, testOutputCallBack) { TEST(TestALL, testOutputCallBack) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test output (callback mode)"); TEST_INFO("test output (callback mode)");
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager, "speaker"); ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker");
ASSERT_NE(process, nullptr); ASSERT_NE(process, nullptr);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
TEST(TestALL, testOutputCallBackPulse) { TEST(TestALL, testOutputCallBackPulse) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test output (callback mode)"); TEST_INFO("test output (callback mode)");
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager, "speaker-pulse"); ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker-pulse");
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
TEST(TestALL, testOutputCallBackJack) { TEST(TestALL, testOutputCallBackJack) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test output (callback mode)"); TEST_INFO("test output (callback mode)");
std::shared_ptr<testOutCallback> process = std::make_shared<testOutCallback>(manager, "speaker-jack"); ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker-jack");
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,9 +5,6 @@
*/ */
#pragma once #pragma once
#undef __class__
#define __class__ "test_playback_write"
namespace river_test_playback_write { namespace river_test_playback_write {
static const std::string configurationRiver = static const std::string configurationRiver =
"{\n" "{\n"
@@ -28,10 +25,10 @@ namespace river_test_playback_write {
class testOutWrite { class testOutWrite {
public: public:
std::vector<audio::channel> m_channelMap; std::vector<audio::channel> m_channelMap;
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
public: public:
testOutWrite(std::shared_ptr<audio::river::Manager> _manager) : testOutWrite(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager) { m_manager(_manager) {
//Set stereo output: //Set stereo output:
m_channelMap.push_back(audio::channel_frontLeft); m_channelMap.push_back(audio::channel_frontLeft);
@@ -81,7 +78,7 @@ namespace river_test_playback_write {
} }
m_interface->write(&data[0], data.size()/m_channelMap.size()); m_interface->write(&data[0], data.size()/m_channelMap.size());
// TODO : Add a function to get number of time we need to wait enought time ... // TODO : Add a function to get number of time we need to wait enought time ...
usleep(15000); std::this_thread::sleep_for(std::chrono::milliseconds(15));
} }
m_interface->stop(); m_interface->stop();
} }
@@ -89,24 +86,24 @@ namespace river_test_playback_write {
TEST(TestALL, testOutputWrite) { TEST(TestALL, testOutputWrite) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test output (write mode)"); TEST_INFO("test output (write mode)");
std::shared_ptr<testOutWrite> process = std::make_shared<testOutWrite>(manager); ememory::SharedPtr<testOutWrite> process = ememory::makeShared<testOutWrite>(manager);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
class testOutWriteCallback { class testOutWriteCallback {
public: public:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
double m_phase; double m_phase;
public: public:
testOutWriteCallback(std::shared_ptr<audio::river::Manager> _manager) : testOutWriteCallback(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager), m_manager(_manager),
m_phase(0) { m_phase(0) {
std::vector<audio::channel> channelMap; std::vector<audio::channel> channelMap;
@@ -159,26 +156,23 @@ namespace river_test_playback_write {
return; return;
} }
m_interface->start(); m_interface->start();
usleep(1000000); std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->stop(); m_interface->stop();
} }
}; };
TEST(TestALL, testOutputWriteWithCallback) { TEST(TestALL, testOutputWriteWithCallback) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test output (write with callback event mode)"); TEST_INFO("test output (write with callback event mode)");
std::shared_ptr<testOutWriteCallback> process = std::make_shared<testOutWriteCallback>(manager); ememory::SharedPtr<testOutWriteCallback> process = ememory::makeShared<testOutWriteCallback>(manager);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,10 +5,7 @@
*/ */
#pragma once #pragma once
#include <test-debug/debug.h> #include <test-debug/debug.hpp>
#undef __class__
#define __class__ "test_record_callback"
namespace river_test_record_callback { namespace river_test_record_callback {
static const std::string configurationRiver = static const std::string configurationRiver =
@@ -28,10 +25,10 @@ namespace river_test_record_callback {
class testInCallback { class testInCallback {
public: public:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
public: public:
testInCallback(std::shared_ptr<audio::river::Manager> _manager, const std::string& _input="microphone") : testInCallback(ememory::SharedPtr<audio::river::Manager> _manager, const std::string& _input="microphone") :
m_manager(_manager) { m_manager(_manager) {
//Set stereo output: //Set stereo output:
std::vector<audio::channel> channelMap; std::vector<audio::channel> channelMap;
@@ -78,25 +75,22 @@ namespace river_test_record_callback {
} }
m_interface->start(); m_interface->start();
// wait 2 second ... // wait 2 second ...
usleep(20000000); std::this_thread::sleep_for(std::chrono::seconds(20));
m_interface->stop(); m_interface->stop();
} }
}; };
TEST(TestALL, testInputCallBack) { TEST(TestALL, testInputCallBack) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
TEST_INFO("test input (callback mode)"); TEST_INFO("test input (callback mode)");
std::shared_ptr<testInCallback> process = std::make_shared<testInCallback>(manager); ememory::SharedPtr<testInCallback> process = ememory::makeShared<testInCallback>(manager);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,13 +5,7 @@
*/ */
#pragma once #pragma once
#undef __class__
#define __class__ "test_record_read"
namespace river_test_record_read { namespace river_test_record_read {
}; };
#undef __class__
#define __class__ nullptr

View File

@@ -5,9 +5,6 @@
*/ */
#pragma once #pragma once
#undef __class__
#define __class__ "test_volume"
namespace river_test_volume { namespace river_test_volume {
static const std::string configurationRiver = static const std::string configurationRiver =
"{\n" "{\n"
@@ -27,11 +24,11 @@ namespace river_test_volume {
class testCallbackVolume { class testCallbackVolume {
private: private:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
double m_phase; double m_phase;
public: public:
testCallbackVolume(std::shared_ptr<audio::river::Manager> _manager) : testCallbackVolume(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager), m_manager(_manager),
m_phase(0) { m_phase(0) {
//Set stereo output: //Set stereo output:
@@ -82,57 +79,55 @@ namespace river_test_volume {
return; return;
} }
m_interface->start(); m_interface->start();
usleep(1000000); std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->setParameter("volume", "FLOW", "-3dB"); m_interface->setParameter("volume", "FLOW", "-3dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-6dB"); m_interface->setParameter("volume", "FLOW", "-6dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-9dB"); m_interface->setParameter("volume", "FLOW", "-9dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-12dB"); m_interface->setParameter("volume", "FLOW", "-12dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-3dB"); m_interface->setParameter("volume", "FLOW", "-3dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "3dB"); m_interface->setParameter("volume", "FLOW", "3dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "6dB"); m_interface->setParameter("volume", "FLOW", "6dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "9dB"); m_interface->setParameter("volume", "FLOW", "9dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "0dB"); m_interface->setParameter("volume", "FLOW", "0dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") ); TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_manager->setVolume("MASTER", -3.0f); m_manager->setVolume("MASTER", -3.0f);
TEST_INFO("get volume MASTER: " << m_manager->getVolume("MASTER") ); TEST_INFO("get volume MASTER: " << m_manager->getVolume("MASTER") );
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_manager->setVolume("MEDIA", -3.0f); m_manager->setVolume("MEDIA", -3.0f);
TEST_INFO("get volume MEDIA: " << m_manager->getVolume("MEDIA") ); TEST_INFO("get volume MEDIA: " << m_manager->getVolume("MEDIA") );
usleep(1000000); std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->stop(); m_interface->stop();
} }
}; };
TEST(TestALL, testVolume) { TEST(TestALL, testVolume) {
audio::river::initString(configurationRiver); audio::river::initString(configurationRiver);
std::shared_ptr<audio::river::Manager> manager; ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication"); manager = audio::river::Manager::create("testApplication");
std::shared_ptr<testCallbackVolume> process = std::make_shared<testCallbackVolume>(manager); ememory::SharedPtr<testCallbackVolume> process = ememory::makeShared<testCallbackVolume>(manager);
process->run(); process->run();
process.reset(); process.reset();
usleep(500000); std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit(); audio::river::unInit();
} }
}; };
#undef __class__
#define __class__ nullptr

1
version.txt Normal file
View File

@@ -0,0 +1 @@
0.4.0

View File

@@ -4,12 +4,9 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/widget/debug.h> #include <audio/river/widget/debug.hpp>
#include <audio/river/widget/TemporalViewer.h> #include <audio/river/widget/TemporalViewer.hpp>
#include <etk/tool.h> #include <etk/tool.hpp>
#undef __class__
#define __class__ "TemporalViewer"
static const int32_t nbSecond = 3; static const int32_t nbSecond = 3;

View File

@@ -5,11 +5,11 @@
*/ */
#pragma once #pragma once
#include <ewol/widget/Widget.h> #include <ewol/widget/Widget.hpp>
#include <ewol/compositing/Drawing.h> #include <ewol/compositing/Drawing.hpp>
#include <audio/river/river.h> #include <audio/river/river.hpp>
#include <audio/river/Manager.h> #include <audio/river/Manager.hpp>
#include <audio/river/Interface.h> #include <audio/river/Interface.hpp>
#include <mutex> #include <mutex>
namespace audio { namespace audio {
@@ -43,8 +43,8 @@ namespace audio {
virtual void onRegenerateDisplay(); virtual void onRegenerateDisplay();
virtual void periodicCall(const ewol::event::Time& _event); virtual void periodicCall(const ewol::event::Time& _event);
private: private:
std::shared_ptr<audio::river::Manager> m_manager; ememory::SharedPtr<audio::river::Manager> m_manager;
std::shared_ptr<audio::river::Interface> m_interface; ememory::SharedPtr<audio::river::Interface> m_interface;
void onDataReceived(const void* _data, void onDataReceived(const void* _data,
const audio::Time& _time, const audio::Time& _time,
size_t _nbChunk, size_t _nbChunk,

View File

@@ -4,7 +4,7 @@
* @license APACHE v2.0 (see license file) * @license APACHE v2.0 (see license file)
*/ */
#include <audio/river/widget/debug.h> #include <audio/river/widget/debug.hpp>
int32_t audio::river::widget::getLogId() { int32_t audio::river::widget::getLogId() {

View File

@@ -5,7 +5,7 @@
*/ */
#pragma once #pragma once
#include <elog/log.h> #include <elog/log.hpp>
namespace audio { namespace audio {
namespace river { namespace river {

View File

@@ -1,7 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
import lutin.module as module
import lutin.tools as tools
import lutin.debug as debug import lutin.debug as debug
import lutin.tools as tools
import os import os
@@ -26,17 +25,19 @@ def get_maintainer():
def get_version(): def get_version():
return [0,0,0] return [0,0,0]
def create(target, module_name): def configure(target, my_module):
my_module = module.Module(__file__, module_name, get_type())
my_module.add_src_file([ my_module.add_src_file([
'audio/river/widget/TemporalViewer.cpp', 'audio/river/widget/TemporalViewer.cpp',
'audio/river/widget/debug.cpp' 'audio/river/widget/debug.cpp'
]) ])
my_module.add_header_file([ my_module.add_header_file([
'audio/river/widget/TemporalViewer.h' 'audio/river/widget/TemporalViewer.hpp'
]) ])
my_module.add_module_depend(['ewol', 'audio-river']) my_module.add_depend([
my_module.add_path(tools.get_current_path(__file__)) 'ewol',
return my_module 'audio-river'
])
my_module.add_path(".")
return True