Compare commits

..

No commits in common. "6dfa58deddce28fe4c019814b7ccb0f645ef0962" and "b114de5f1da4d325c4b6d50dff259e0a83309cef" have entirely different histories.

60 changed files with 1297 additions and 1877 deletions

373
LICENSE
View File

@ -1,373 +0,0 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

View File

@ -1,5 +1,5 @@
audio-river
===========
=====
`audio-river` is a High level hardware audio interface that connect to orchestra (multi-platform backend)
@ -70,15 +70,15 @@ Compile software:
cd WORKING_DIRECTORY
lutin -C -P audio-river-test?build?run
License (MPL v2.0)
License (APACHE v2.0)
=====================
Copyright audio-river Edouard DUPIN
Licensed under the Mozilla Public License, Version 2.0 (the "License");
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
https://www.mozilla.org/MPL/2.0
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,

View File

@ -1,35 +1,37 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/debug.hpp>
#include <audio/river/Interface.hpp>
#include <audio/river/io/Node.hpp>
#include "debug.hpp"
#include "Interface.hpp"
#include "io/Node.hpp"
#include <audio/drain/EndPointCallback.hpp>
#include <audio/drain/EndPointWrite.hpp>
#include <audio/drain/EndPointRead.hpp>
#include <audio/drain/Volume.hpp>
audio::river::Interface::Interface(void) {
audio::river::Interface::Interface(void) :
m_node(),
m_name("") {
static uint32_t uid = 0;
m_uid = uid++;
}
bool audio::river::Interface::init(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
ememory::SharedPtr<audio::river::io::Node> _node,
const ejson::Object& _config) {
etk::Vector<audio::channel> map(_map);
std::vector<audio::channel> map(_map);
m_node = _node;
m_config = _config;
m_mode = audio::river::modeInterface_unknow;
etk::String type = m_config["io"].toString().get("error");
std::string type = m_config["io"].toString().get("error");
static int32_t uid=0;
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::toString(uid++);
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::to_string(uid++);
if (type == "output") {
m_mode = audio::river::modeInterface_output;
} else if (type == "input") {
@ -52,7 +54,7 @@ bool audio::river::Interface::init(float _freq,
m_process.setInputConfig(m_node->getInterfaceFormat());
// Add volume only if the Low level has a volume (otherwise it will be added by the application)
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
if (tmpVolume != null) {
if (tmpVolume != nullptr) {
// add all time the volume stage :
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
//algo->setInputFormat(m_node->getInterfaceFormat());
@ -67,7 +69,7 @@ bool audio::river::Interface::init(float _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)
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
if (tmpVolume != null) {
if (tmpVolume != nullptr) {
// add all time the volume stage :
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
//algo->setOutputFormat(m_node->getInterfaceFormat());
@ -90,18 +92,18 @@ bool audio::river::Interface::init(float _freq,
}
ememory::SharedPtr<audio::river::Interface> audio::river::Interface::create(float _freq,
const etk::Vector<audio::channel>& _map,
audio::format _format,
const ememory::SharedPtr<audio::river::io::Node>& _node,
const ejson::Object& _config) {
ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(ETK_NEW(audio::river::Interface));
const std::vector<audio::channel>& _map,
audio::format _format,
const ememory::SharedPtr<audio::river::io::Node>& _node,
const ejson::Object& _config) {
ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(new audio::river::Interface());
out->init(_freq, _map, _format, _node, _config);
return out;
}
audio::river::Interface::~Interface() {
//stop(true, true);
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
//m_node->interfaceRemove(sharedFromThis());
}
/*
@ -110,13 +112,12 @@ bool audio::river::Interface::hasEndPoint() {
}
*/
void audio::river::Interface::setReadwrite() {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
m_process.removeAlgoDynamic();
if (m_process.hasType<audio::drain::EndPoint>() ) {
RIVER_ERROR("Endpoint is already present ==> can not change");
return;
}
RIVER_WARNING("Add output ReadWrite");
if (m_node->isInput() == true) {
m_process.removeIfLast<audio::drain::EndPoint>();
ememory::SharedPtr<audio::drain::EndPointRead> algo = audio::drain::EndPointRead::create();
@ -129,12 +130,11 @@ void audio::river::Interface::setReadwrite() {
}
void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _function) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_mode != audio::river::modeInterface_output) {
RIVER_ERROR("Can not set output endpoint on other than a output IO");
return;
}
RIVER_WARNING("Add output callback");
m_process.removeAlgoDynamic();
m_process.removeIfFirst<audio::drain::EndPoint>();
ememory::SharedPtr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function);
@ -142,12 +142,11 @@ void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _
}
void audio::river::Interface::setInputCallback(audio::drain::recordFunction _function) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_mode == audio::river::modeInterface_output) {
RIVER_ERROR("Can not set output endpoint on other than a input or feedback IO");
return;
}
RIVER_WARNING("Add input callback");
m_process.removeAlgoDynamic();
m_process.removeIfLast<audio::drain::EndPoint>();
ememory::SharedPtr<audio::drain::Algo> algo = audio::drain::EndPointCallback::create(_function);
@ -155,22 +154,21 @@ void audio::river::Interface::setInputCallback(audio::drain::recordFunction _fun
}
void audio::river::Interface::setWriteCallback(audio::drain::playbackFunctionWrite _function) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_mode != audio::river::modeInterface_output) {
RIVER_ERROR("Can not set output endpoint on other than a output IO");
return;
}
RIVER_WARNING("Add output Write");
m_process.removeAlgoDynamic();
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
return;
}
algo->setCallback(_function);
}
void audio::river::Interface::start(const audio::Time& _time) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("start [BEGIN]");
m_process.updateInterAlgo();
m_node->interfaceAdd(sharedFromThis());
@ -178,20 +176,20 @@ void audio::river::Interface::start(const audio::Time& _time) {
}
void audio::river::Interface::stop(bool _fast, bool _abort) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("stop [BEGIN]");
m_node->interfaceRemove(sharedFromThis());
RIVER_DEBUG("stop [ END]");
}
void audio::river::Interface::abort() {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("abort [BEGIN]");
// TODO :...
RIVER_DEBUG("abort [ END ]");
}
bool audio::river::Interface::setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value) {
bool audio::river::Interface::setParameter(const std::string& _filter, const std::string& _parameter, const std::string& _value) {
RIVER_DEBUG("setParameter [BEGIN] : '" << _filter << "':'" << _parameter << "':'" << _value << "'");
bool out = false;
if ( _filter == "volume"
@ -200,7 +198,7 @@ bool audio::river::Interface::setParameter(const etk::String& _filter, const etk
return false;
}
ememory::SharedPtr<audio::drain::Algo> algo = m_process.get<audio::drain::Algo>(_filter);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return false;
}
@ -208,11 +206,11 @@ bool audio::river::Interface::setParameter(const etk::String& _filter, const etk
RIVER_DEBUG("setParameter [ END ] : '" << out << "'");
return out;
}
etk::String audio::river::Interface::getParameter(const etk::String& _filter, const etk::String& _parameter) const {
std::string audio::river::Interface::getParameter(const std::string& _filter, const std::string& _parameter) const {
RIVER_DEBUG("getParameter [BEGIN] : '" << _filter << "':'" << _parameter << "'");
etk::String out;
std::string out;
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return "[ERROR]";
}
@ -220,11 +218,11 @@ etk::String audio::river::Interface::getParameter(const etk::String& _filter, co
RIVER_DEBUG("getParameter [ END ] : '" << out << "'");
return out;
}
etk::String audio::river::Interface::getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const {
std::string audio::river::Interface::getParameterProperty(const std::string& _filter, const std::string& _parameter) const {
RIVER_DEBUG("getParameterProperty [BEGIN] : '" << _filter << "':'" << _parameter << "'");
etk::String out;
std::string out;
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
return "[ERROR]";
}
@ -234,10 +232,10 @@ etk::String audio::river::Interface::getParameterProperty(const etk::String& _fi
}
void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
m_process.updateInterAlgo();
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
return;
}
algo->write(_value, _nbChunk);
@ -245,16 +243,16 @@ void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
#if 0
// TODO : add API aCCess mutex for Read and write...
etk::Vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
std::vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
// TODO :...
etk::Vector<int16_t> data;
std::vector<int16_t> data;
/*
data.resize(_nbChunk*m_map.size(), 0);
m_mutex.lock();
int32_t nbChunkBuffer = m_circularBuffer.size() / m_map.size();
m_mutex.unlock();
while (nbChunkBuffer < _nbChunk) {
ethread::sleepMilliSeconds((1));
std::this_thread::sleep_for(std::chrono::milliseconds(1));
nbChunkBuffer = m_circularBuffer.size() / m_map.size();
}
m_mutex.lock();
@ -269,14 +267,14 @@ etk::Vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
#endif
void audio::river::Interface::read(void* _value, size_t _nbChunk) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
m_process.updateInterAlgo();
// TODO :...
}
size_t audio::river::Interface::size() const {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
// TODO :...
return 0;
}
@ -286,10 +284,10 @@ size_t audio::river::Interface::size() const {
void audio::river::Interface::setBufferSize(size_t _nbChunk) {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) {
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
@ -297,18 +295,18 @@ void audio::river::Interface::setBufferSize(size_t _nbChunk) {
return;
}
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
algo->setBufferSize(_nbChunk);
}
void audio::river::Interface::setBufferSize(const echrono::microseconds& _time) {
ethread::RecursiveLock lock(m_mutex);
void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _time) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) {
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
@ -316,7 +314,7 @@ void audio::river::Interface::setBufferSize(const echrono::microseconds& _time)
return;
}
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
return;
}
@ -324,53 +322,53 @@ void audio::river::Interface::setBufferSize(const echrono::microseconds& _time)
}
size_t audio::river::Interface::getBufferSize() {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) {
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferSize();
}
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferSize();
}
echrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
ethread::RecursiveLock lock(m_mutex);
std::chrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) {
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return echrono::microseconds(0);
return std::chrono::microseconds(0);
}
return algo->getBufferSizeMicrosecond();
}
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return echrono::microseconds(0);
return std::chrono::microseconds(0);
}
return algo->getBufferSizeMicrosecond();
}
size_t audio::river::Interface::getBufferFillSize() {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) {
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
return algo->getBufferFillSize();
}
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return 0;
}
@ -378,20 +376,20 @@ size_t audio::river::Interface::getBufferFillSize() {
}
echrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
ethread::RecursiveLock lock(m_mutex);
std::chrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (m_node->isInput() == true) {
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return echrono::microseconds(0);
return std::chrono::microseconds(0);
}
return algo->getBufferFillSizeMicrosecond();
}
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
if (algo == null) {
if (algo == nullptr) {
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
return echrono::microseconds(0);
return std::chrono::microseconds(0);
}
return algo->getBufferFillSizeMicrosecond();
}
@ -399,24 +397,24 @@ echrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
void audio::river::Interface::clearInternalBuffer() {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
m_process.updateInterAlgo();
// TODO :...
}
audio::Time audio::river::Interface::getCurrentTime() const {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
// TODO :...
return audio::Time();
return audio::Time::now();
}
void audio::river::Interface::addVolumeGroup(const etk::String& _name) {
ethread::RecursiveLock lock(m_mutex);
void audio::river::Interface::addVolumeGroup(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_DEBUG("addVolumeGroup(" << _name << ")");
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
if (algo == null) {
if (algo == nullptr) {
m_process.removeAlgoDynamic();
// add all time the volume stage :
algo = audio::drain::Volume::create();
@ -438,85 +436,85 @@ void audio::river::Interface::addVolumeGroup(const etk::String& _name) {
}
void audio::river::Interface::systemNewInputData(audio::Time _time, const void* _data, size_t _nbChunk) {
ethread::RecursiveLock lockProcess(m_mutex);
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
void * tmpData = const_cast<void*>(_data);
m_process.push(_time, tmpData, _nbChunk);
}
void audio::river::Interface::systemNeedOutputData(audio::Time _time, void* _data, size_t _nbChunk, size_t _chunkSize) {
ethread::RecursiveLock lockProcess(m_mutex);
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
//RIVER_INFO("time : " << _time);
m_process.pull(_time, _data, _nbChunk, _chunkSize);
}
void audio::river::Interface::systemVolumeChange() {
ethread::RecursiveLock lockProcess(m_mutex);
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
if (algo == null) {
if (algo == nullptr) {
return;
}
algo->volumeChange();
}
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second, bool _isLink=true) {
static void link(etk::FSNode& _node, const std::string& _first, const std::string& _op, const std::string& _second, bool _isLink=true) {
if (_op == "->") {
if (_isLink) {
*_io << " " << _first << " -> " << _second << ";\n";
_node << " " << _first << " -> " << _second << ";\n";
} else {
*_io << " " << _first << " -> " << _second << " [style=dashed];\n";
_node << " " << _first << " -> " << _second << " [style=dashed];\n";
}
} else if (_op == "<-") {
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
_node << " " << _first << " -> " <<_second<< " [color=transparent];\n";
if (_isLink) {
*_io << " " << _second << " -> " << _first << " [constraint=false];\n";
_node << " " << _second << " -> " << _first << " [constraint=false];\n";
} else {
*_io << " " << _second << " -> " << _first << " [constraint=false, style=dashed];\n";
_node << " " << _second << " -> " << _first << " [constraint=false, style=dashed];\n";
}
}
}
etk::String audio::river::Interface::getDotNodeName() const {
std::string audio::river::Interface::getDotNodeName() const {
if (m_mode == audio::river::modeInterface_input) {
return "API_" + etk::toString(m_uid) + "_input";
return "API_" + etk::to_string(m_uid) + "_input";
} else if (m_mode == audio::river::modeInterface_feedback) {
return "API_" + etk::toString(m_uid) + "_feedback";
return "API_" + etk::to_string(m_uid) + "_feedback";
} else if (m_mode == audio::river::modeInterface_output) {
return "API_" + etk::toString(m_uid) + "_output";
return "API_" + etk::to_string(m_uid) + "_output";
}
return "error";
}
void audio::river::Interface::generateDot(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _nameIO, bool _isLink) {
*_io << " subgraph clusterInterface_" << m_uid << " {\n";
*_io << " color=orange;\n";
*_io << " label=\"[" << m_uid << "] Interface : " << m_name << "\";\n";
etk::String nameIn;
etk::String nameOut;
void audio::river::Interface::generateDot(etk::FSNode& _node, const std::string& _nameIO, bool _isLink) {
_node << " subgraph clusterInterface_" << m_uid << " {\n";
_node << " color=orange;\n";
_node << " label=\"[" << m_uid << "] Interface : " << m_name << "\";\n";
std::string nameIn;
std::string nameOut;
if ( m_mode == audio::river::modeInterface_input
|| m_mode == audio::river::modeInterface_feedback) {
m_process.generateDot(_io, 3, 10000+m_uid, nameIn, nameOut, false);
m_process.generateDot(_node, 3, 10000+m_uid, nameIn, nameOut, false);
} else {
m_process.generateDot(_io, 3, 10000+m_uid, nameOut, nameIn, true);
m_process.generateDot(_node, 3, 10000+m_uid, nameIn, nameOut, true);
}
if ( m_mode == audio::river::modeInterface_input
|| m_mode == audio::river::modeInterface_feedback) {
link(_io, _nameIO, "->", nameIn, _isLink);
link(_node, _nameIO, "->", nameIn, _isLink);
} else {
link(_io, _nameIO, "<-", nameOut, _isLink);
link(_node, _nameIO, "<-", nameOut, _isLink);
}
*_io << " node [shape=Mdiamond];\n";
_node << " node [shape=Mdiamond];\n";
if (m_mode == audio::river::modeInterface_input) {
*_io << " " << getDotNodeName() << " [ label=\"API\\nINPUT\" ];\n";
link(_io, nameOut, "->", getDotNodeName());
_node << " " << getDotNodeName() << " [ label=\"API\\nINPUT\" ];\n";
link(_node, nameOut, "->", getDotNodeName());
} else if (m_mode == audio::river::modeInterface_feedback) {
*_io << " " << getDotNodeName() << " [ label=\"API\\nFEEDBACK\" ];\n";
link(_io, nameOut, "->", getDotNodeName());
_node << " " << getDotNodeName() << " [ label=\"API\\nFEEDBACK\" ];\n";
link(_node, nameOut, "->", getDotNodeName());
} else if (m_mode == audio::river::modeInterface_output) {
*_io << " " << getDotNodeName() << " [ label=\"API\\nOUTPUT\" ];\n";
link(_io, nameIn, "<-", getDotNodeName());
_node << " " << getDotNodeName() << " [ label=\"API\\nOUTPUT\" ];\n";
link(_node, nameIn, "<-", getDotNodeName());
}
*_io << " }\n \n";
_node << " }\n \n";
}

View File

@ -1,16 +1,16 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/String.hpp>
#include <etk/Vector.hpp>
#include <ethread/Mutex.hpp>
#include <ethread/MutexRecursive.hpp>
#include <echrono/echrono.hpp>
#include <etk/Function.hpp>
#include <string>
#include <vector>
#include <cstdint>
#include <mutex>
#include <chrono>
#include <functional>
#include <ememory/memory.hpp>
#include <audio/format.hpp>
#include <audio/channel.hpp>
@ -18,6 +18,7 @@
#include <audio/drain/EndPointCallback.hpp>
#include <audio/drain/EndPointWrite.hpp>
#include <ejson/ejson.hpp>
#include <etk/os/FSNode.hpp>
#include <audio/Time.hpp>
namespace audio {
@ -62,7 +63,7 @@ namespace audio {
* @return false the configuration has an error.
*/
bool init(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
ememory::SharedPtr<audio::river::io::Node> _node,
const ejson::Object& _config);
@ -73,11 +74,11 @@ namespace audio {
* @param[in] _format Sample format
* @param[in] _node Low level interface to connect the flow.
* @param[in] _config Special configuration of this interface.
* @return null The configuration does not work.
* @return nullptr The configuration does not work.
* @return pointer The interface has been corectly created.
*/
static ememory::SharedPtr<Interface> create(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const ememory::SharedPtr<audio::river::io::Node>& _node,
const ejson::Object& _config);
@ -87,7 +88,7 @@ namespace audio {
*/
virtual ~Interface();
protected:
mutable ethread::MutexRecursive m_mutex; //!< Local mutex to protect data
mutable std::recursive_mutex m_mutex; //!< Local mutex to protect data
ejson::Object m_config; //!< configuration set by the user.
protected:
enum modeInterface m_mode; //!< interface type (input/output/feedback)
@ -117,20 +118,20 @@ namespace audio {
protected:
ememory::SharedPtr<audio::river::io::Node> m_node; //!< Hardware interface to/from stream audio flow.
protected:
etk::String m_name; //!< Name of the interface.
std::string m_name; //!< Name of the interface.
public:
/**
* @brief Get interface name.
* @return The current name.
*/
virtual etk::String getName() {
virtual std::string getName() {
return m_name;
};
/**
* @brief Set the interface name
* @param[in] _name new name of the interface
*/
virtual void setName(const etk::String& _name) {
virtual void setName(const std::string& _name) {
m_name = _name;
};
/**
@ -168,7 +169,7 @@ namespace audio {
* - NOTIFICATION for urgent notification volume control.
* - NOISE for small noise volume control.
*/
virtual void addVolumeGroup(const etk::String& _name);
virtual void addVolumeGroup(const std::string& _name);
public:
/**
* @brief Start the Audio interface flow.
@ -197,7 +198,7 @@ namespace audio {
* @example : setParameter("volume", "FLOW", "-3dB");
* @example : setParameter("LowPassFilter", "cutFrequency", "1000Hz");
*/
virtual bool setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value);
virtual bool setParameter(const std::string& _filter, const std::string& _parameter, const std::string& _value);
/**
* @brief Get a parameter value
* @param[in] _filter name of the filter (if you added some personels)
@ -206,7 +207,7 @@ namespace audio {
* @example : getParameter("volume", "FLOW"); can return something like "-3dB"
* @example : getParameter("LowPassFilter", "cutFrequency"); can return something like "[-120..0]dB"
*/
virtual etk::String getParameter(const etk::String& _filter, const etk::String& _parameter) const;
virtual std::string getParameter(const std::string& _filter, const std::string& _parameter) const;
/**
* @brief Get a parameter value
* @param[in] _filter name of the filter (if you added some personels)
@ -215,7 +216,7 @@ namespace audio {
* @example : getParameter("volume", "FLOW"); can return something like "[-120..0]dB"
* @example : getParameter("LowPassFilter", "cutFreqiency"); can return something like "]100..10000]Hz"
*/
virtual etk::String getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const;
virtual std::string getParameterProperty(const std::string& _filter, const std::string& _parameter) const;
/**
* @brief write some audio sample in the speakers
* @param[in] _value Data To write on output
@ -244,7 +245,7 @@ namespace audio {
* @brief Set buffer size size of the buffer with the stored time in µs
* @param[in] _time Time in microsecond of the buffer
*/
virtual void setBufferSize(const echrono::microseconds& _time);
virtual void setBufferSize(const std::chrono::microseconds& _time);
/**
* @brief get buffer size in chunk number
* @return Number of chunk that can be written in the buffer
@ -254,7 +255,7 @@ namespace audio {
* @brief Set buffer size size of the buffer with the stored time in µs
* @return Time in microsecond that can be written in the buffer
*/
virtual echrono::microseconds getBufferSizeMicrosecond();
virtual std::chrono::microseconds getBufferSizeMicrosecond();
/**
* @brief Get buffer size filled in chunk number
* @return Number of chunk in the buffer (that might be read/write)
@ -264,7 +265,7 @@ namespace audio {
* @brief Set buffer size size of the buffer with the stored time in µs
* @return Time in microsecond of the buffer (that might be read/write)
*/
virtual echrono::microseconds getBufferFillSizeMicrosecond();
virtual std::chrono::microseconds getBufferFillSizeMicrosecond();
/**
* @brief Remove internal Buffer
*/
@ -297,23 +298,23 @@ namespace audio {
public:
/**
* @brief Create the dot in the FileNode stream.
* @param[in,out] _io File interafce to write data.
* @param[in,out] _node File node to write data.
* @param[in] _nameIO Name to link the interface node
* @param[in] _isLink True if the node is connected on the current interface.
*/
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _nameIO, bool _isLink=true);
virtual void generateDot(etk::FSNode& _node, const std::string& _nameIO, bool _isLink=true);
/**
* @brief Get the current 'dot' name of the interface
* @return The anme requested.
*/
virtual etk::String getDotNodeName() const;
virtual std::string getDotNodeName() const;
protected:
/**
* @brief Interfanel generate of status
* @param[in] _origin status source
* @param[in] _status Event status
*/
void generateStatus(const etk::String& _origin, const etk::String& _status) {
void generateStatus(const std::string& _origin, const std::string& _status) {
m_process.generateStatus(_origin, _status);
}
public:

View File

@ -1,24 +1,26 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include "Manager.hpp"
#include "Interface.hpp"
#include <stdexcept>
#include "io/Manager.hpp"
#include "io/Node.hpp"
#include "debug.hpp"
#include <ejson/ejson.hpp>
static ethread::Mutex g_mutex;
static etk::Vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
static std::mutex g_mutex;
static std::vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const etk::String& _applicationUniqueId) {
ethread::UniqueLock lock(g_mutex);
ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const std::string& _applicationUniqueId) {
std::unique_lock<std::mutex> lock(g_mutex);
for (size_t iii=0; iii<g_listOfAllManager.size() ; ++iii) {
ememory::SharedPtr<audio::river::Manager> tmp = g_listOfAllManager[iii].lock();
if (tmp == null) {
if (tmp == nullptr) {
continue;
}
if (tmp->m_applicationUniqueId == _applicationUniqueId) {
@ -26,7 +28,7 @@ ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const et
}
}
// create a new one:
ememory::SharedPtr<audio::river::Manager> out = ememory::SharedPtr<audio::river::Manager>(ETK_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:
for (size_t iii=0; iii<g_listOfAllManager.size() ; ++iii) {
if (g_listOfAllManager[iii].expired() == true) {
@ -34,11 +36,11 @@ ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const et
return out;
}
}
g_listOfAllManager.pushBack(out);
g_listOfAllManager.push_back(out);
return out;
}
audio::river::Manager::Manager(const etk::String& _applicationUniqueId) :
audio::river::Manager::Manager(const std::string& _applicationUniqueId) :
m_applicationUniqueId(_applicationUniqueId),
m_listOpenInterface() {
@ -49,10 +51,10 @@ audio::river::Manager::~Manager() {
}
etk::Vector<etk::String> audio::river::Manager::getListStreamInput() {
etk::Vector<etk::String> output;
std::vector<std::string> audio::river::Manager::getListStreamInput() {
std::vector<std::string> output;
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
} else {
output = manager->getListStreamInput();
@ -60,10 +62,10 @@ etk::Vector<etk::String> audio::river::Manager::getListStreamInput() {
return output;
}
etk::Vector<etk::String> audio::river::Manager::getListStreamOutput() {
etk::Vector<etk::String> output;
std::vector<std::string> audio::river::Manager::getListStreamOutput() {
std::vector<std::string> output;
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
} else {
output = manager->getListStreamOutput();
@ -71,10 +73,10 @@ etk::Vector<etk::String> audio::river::Manager::getListStreamOutput() {
return output;
}
etk::Vector<etk::String> audio::river::Manager::getListStreamVirtual() {
etk::Vector<etk::String> output;
std::vector<std::string> audio::river::Manager::getListStreamVirtual() {
std::vector<std::string> output;
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
} else {
output = manager->getListStreamVirtual();
@ -82,10 +84,10 @@ etk::Vector<etk::String> audio::river::Manager::getListStreamVirtual() {
return output;
}
etk::Vector<etk::String> audio::river::Manager::getListStream() {
etk::Vector<etk::String> output;
std::vector<std::string> audio::river::Manager::getListStream() {
std::vector<std::string> output;
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
} else {
output = manager->getListStream();
@ -93,45 +95,45 @@ etk::Vector<etk::String> audio::river::Manager::getListStream() {
return output;
}
bool audio::river::Manager::setVolume(const etk::String& _volumeName, float _valuedB) {
bool audio::river::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return false;
}
return manager->setVolume(_volumeName, _valuedB);
}
float audio::river::Manager::getVolume(const etk::String& _volumeName) const {
float audio::river::Manager::getVolume(const std::string& _volumeName) const {
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return false;
}
return manager->getVolume(_volumeName);
}
etk::Pair<float,float> audio::river::Manager::getVolumeRange(const etk::String& _volumeName) const {
std::pair<float,float> audio::river::Manager::getVolumeRange(const std::string& _volumeName) const {
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return etk::makePair<float,float>(0.0f,0.0f);
return std::make_pair<float,float>(0.0f,0.0f);
}
return manager->getVolumeRange(_volumeName);
}
void audio::river::Manager::setMute(const etk::String& _volumeName, bool _mute) {
void audio::river::Manager::setMute(const std::string& _volumeName, bool _mute) {
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return;
}
manager->setMute(_volumeName, _mute);
}
bool audio::river::Manager::getMute(const etk::String& _volumeName) const {
bool audio::river::Manager::getMute(const std::string& _volumeName) const {
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return false;
}
@ -139,19 +141,19 @@ bool audio::river::Manager::getMute(const etk::String& _volumeName) const {
}
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createOutput(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _streamName,
const etk::String& _options) {
const std::string& _streamName,
const std::string& _options) {
// get global hardware interface:
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return ememory::SharedPtr<audio::river::Interface>();
}
// get the output or input channel :
ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(_streamName);
if (node == null) {
if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return ememory::SharedPtr<audio::river::Interface>();
}
@ -165,24 +167,24 @@ ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createOutput(
tmpOption.add("io", ejson::String("output"));
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption);
// store it in a list (needed to apply some parameters).
m_listOpenInterface.pushBack(interface);
m_listOpenInterface.push_back(interface);
return interface;
}
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createInput(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _streamName,
const etk::String& _options) {
const std::string& _streamName,
const std::string& _options) {
// get global hardware interface:
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return ememory::SharedPtr<audio::river::Interface>();
}
// get the output or input channel :
ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(_streamName);
if (node == null) {
if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return ememory::SharedPtr<audio::river::Interface>();
}
@ -196,25 +198,25 @@ ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createInput(f
tmpOption.add("io", ejson::String("input"));
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption);
// store it in a list (needed to apply some parameters).
m_listOpenInterface.pushBack(interface);
m_listOpenInterface.push_back(interface);
return interface;
}
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createFeedback(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _streamName,
const etk::String& _options) {
const std::string& _streamName,
const std::string& _options) {
// get global hardware interface:
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Unable to load harware IO manager ... ");
return ememory::SharedPtr<audio::river::Interface>();
}
// get the output or input channel :
ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(_streamName);
if (node == null) {
if (node == nullptr) {
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
return ememory::SharedPtr<audio::river::Interface>();
}
@ -228,14 +230,14 @@ ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createFeedbac
tmpOption.add("io", ejson::String("feedback"));
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption);
// store it in a list (needed to apply some parameters).
m_listOpenInterface.pushBack(interface);
m_listOpenInterface.push_back(interface);
return interface;
}
void audio::river::Manager::generateDotAll(const etk::String& _filename) {
void audio::river::Manager::generateDotAll(const std::string& _filename) {
// get global hardware interface:
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
if (manager == null) {
if (manager == nullptr) {
RIVER_ERROR("Can not get the harware manager");
return;
}

View File

@ -1,11 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/String.hpp>
#include <string>
#include <cstdint>
#include <ememory/memory.hpp>
#include <audio/river/Interface.hpp>
#include <audio/format.hpp>
@ -19,20 +20,20 @@ namespace audio {
*/
class Manager : public ememory::EnableSharedFromThis<Manager> {
private:
const etk::String& m_applicationUniqueId; //!< name of the application that open the Audio Interface.
etk::Vector<ememory::WeakPtr<audio::river::Interface> > m_listOpenInterface; //!< List of all open Stream.
const std::string& m_applicationUniqueId; //!< name of the application that open the Audio Interface.
std::vector<ememory::WeakPtr<audio::river::Interface> > m_listOpenInterface; //!< List of all open Stream.
protected:
/**
* @brief Constructor
*/
Manager(const etk::String& _applicationUniqueId);
Manager(const std::string& _applicationUniqueId);
public:
/**
* @brief factory of the manager. Every Application will have only one maager for all his flow. this permit to manage all of it
* @param[in] _applicationUniqueId Unique name of the application
* @return Pointer on the manager or null if an error occured
* @return Pointer on the manager or nullptr if an error occured
*/
static ememory::SharedPtr<audio::river::Manager> create(const etk::String& _applicationUniqueId);
static ememory::SharedPtr<audio::river::Manager> create(const std::string& _applicationUniqueId);
/**
* @brief Destructor
*/
@ -42,22 +43,22 @@ namespace audio {
* @brief Get all input audio stream.
* @return a list of all availlables input stream name
*/
etk::Vector<etk::String> getListStreamInput();
std::vector<std::string> getListStreamInput();
/**
* @brief Get all output audio stream.
* @return a list of all availlables output stream name
*/
etk::Vector<etk::String> getListStreamOutput();
std::vector<std::string> getListStreamOutput();
/**
* @brief Get all audio virtual stream.
* @return a list of all availlables virtual stream name
*/
etk::Vector<etk::String> getListStreamVirtual();
std::vector<std::string> getListStreamVirtual();
/**
* @brief Get all audio stream.
* @return a list of all availlables stream name
*/
etk::Vector<etk::String> getListStream();
std::vector<std::string> getListStream();
/**
* @brief Set a volume for a specific group
@ -67,14 +68,14 @@ namespace audio {
* @return false An error occured
* @example : setVolume("MASTER", -3.0f);
*/
virtual bool setVolume(const etk::String& _volumeName, float _valuedB);
virtual bool setVolume(const std::string& _volumeName, float _valuedB);
/**
* @brief Get a volume value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The Volume value in dB.
* @example ret = getVolume("MASTER"); can return something like ret = -3.0f
*/
virtual float getVolume(const etk::String& _volumeName) const;
virtual float getVolume(const std::string& _volumeName) const;
/**
* @brief Get a parameter value
@ -82,19 +83,19 @@ namespace audio {
* @return The requested value Range.
* @example ret = getVolumeRange("MASTER"); can return something like ret=(-120.0f,0.0f)
*/
virtual etk::Pair<float,float> getVolumeRange(const etk::String& _volumeName) const;
virtual std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
/**
* @brief Set a Mute for a specific volume group
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @param[in] _mute Mute enable or disable.
*/
virtual void setMute(const etk::String& _volumeName, bool _mute);
virtual void setMute(const std::string& _volumeName, bool _mute);
/**
* @brief Get a volume value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The Mute of the volume volume.
*/
virtual bool getMute(const etk::String& _volumeName) const;
virtual bool getMute(const std::string& _volumeName) const;
/**
* @brief Create output Interface
@ -106,10 +107,10 @@ namespace audio {
* @return a pointer on the interface
*/
virtual ememory::SharedPtr<Interface> createOutput(float _freq = 48000,
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16,
const etk::String& _streamName = "",
const etk::String& _options = "");
const std::string& _streamName = "",
const std::string& _options = "");
/**
* @brief Create input Interface
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
@ -120,10 +121,10 @@ namespace audio {
* @return a pointer on the interface
*/
virtual ememory::SharedPtr<Interface> createInput(float _freq = 48000,
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16,
const etk::String& _streamName = "",
const etk::String& _options = "");
const std::string& _streamName = "",
const std::string& _options = "");
/**
* @brief Create input Feedback Interface
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
@ -134,15 +135,15 @@ namespace audio {
* @return a pointer on the interface
*/
virtual ememory::SharedPtr<Interface> createFeedback(float _freq = 48000,
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
audio::format _format = audio::format_int16,
const etk::String& _streamName = "",
const etk::String& _options = "");
const std::string& _streamName = "",
const std::string& _options = "");
/**
* @brief Generate the dot file corresponding at all the actif nodes.
* @param[in] _filename Name of the file to write data.
*/
virtual void generateDotAll(const etk::String& _filename);
virtual void generateDotAll(const std::string& _filename);
};
}
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/debug.hpp>

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -41,18 +41,18 @@ namespace audio {
#define RIVER_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \
do { \
static FILE *pointerOnFile = null; \
static FILE *pointerOnFile = nullptr; \
static bool errorOpen = false; \
if (pointerOnFile == null) { \
if (pointerOnFile == nullptr) { \
RIVER_WARNING("open file '" << fileName << "' type=" << #type); \
pointerOnFile = fopen(fileName,"w"); \
if ( errorOpen == false \
&& pointerOnFile == null) { \
&& pointerOnFile == nullptr) { \
RIVER_ERROR("ERROR OPEN file ... '" << fileName << "' type=" << #type); \
errorOpen=true; \
} \
} \
if (pointerOnFile != null) { \
if (pointerOnFile != nullptr) { \
fwrite((dataPointer), sizeof(type), (nbElement), pointerOnFile); \
/* fflush(pointerOnFile);*/ \
} \

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once

View File

@ -1,35 +1,35 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/io/Group.hpp>
#include <audio/river/debug.hpp>
#include <audio/river/io/Node.hpp>
#include <audio/river/io/NodeAEC.hpp>
#include <audio/river/io/NodeOrchestra.hpp>
#include <audio/river/io/NodePortAudio.hpp>
#include <audio/river/io/Node.hpp>
#include "Node.hpp"
#include "NodeAEC.hpp"
#include "NodeOrchestra.hpp"
#include "NodePortAudio.hpp"
#include "Node.hpp"
void audio::river::io::Group::createFrom(const ejson::Document& _obj, const etk::String& _name) {
void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std::string& _name) {
RIVER_INFO("Create Group[" << _name << "] (START) ___________________________");
for (size_t iii=0; iii<_obj.size(); ++iii) {
const ejson::Object tmpObject = _obj[iii].toObject();
if (tmpObject.exist() == false) {
continue;
}
etk::String groupName = tmpObject["group"].toString().get();
std::string groupName = tmpObject["group"].toString().get();
if (groupName == _name) {
RIVER_INFO("Add element in Group[" << _name << "]: " << _obj.getKey(iii));
// get type : io
etk::String ioType = tmpObject["io"].toString().get("error");
std::string ioType = tmpObject["io"].toString().get("error");
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
if ( ioType == "input"
|| ioType == "output") {
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_obj.getKey(iii), tmpObject);
tmp->setGroup(sharedFromThis());
m_list.pushBack(tmp);
m_list.push_back(tmp);
}
#endif
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
@ -37,7 +37,7 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const etk:
|| ioType == "PAoutput") {
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_obj.getKey(iii), tmpObject);
tmp->setGroup(sharedFromThis());
m_list.pushBack(tmp);
m_list.push_back(tmp);
}
#endif
}
@ -48,7 +48,7 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const etk:
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
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) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
ememory::SharedPtr<audio::river::io::NodeOrchestra> link = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_list[iii]);
linkRef->m_interface.isMasterOf(link->m_interface);
}
@ -57,10 +57,10 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const etk:
}
/*
// manage Link Between Nodes :
if (m_link != null) {
if (m_link != nullptr) {
RIVER_INFO("******** START LINK ************");
ememory::SharedPtr<audio::river::io::NodeOrchestra> link = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_link);
if (link == null) {
if (link == nullptr) {
RIVER_ERROR("Can not link 2 Interface with not the same type (reserved for HW interface)");
return;
}
@ -72,16 +72,16 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const etk:
RIVER_INFO("Create Group[" << _name << "] ( END ) ___________________________");
RIVER_INFO("Group[" << _name << "] List elements : ");
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
RIVER_INFO(" " << m_list[iii]->getName());
}
}
}
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Group::getNode(const etk::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) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
if (m_list[iii]->getName() == _name) {
return m_list[iii];
}
@ -94,7 +94,7 @@ void audio::river::io::Group::start() {
RIVER_ERROR("request start ");
int32_t count = 0;
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
count += m_list[iii]->getNumberOfInterface();
}
}
@ -102,7 +102,7 @@ void audio::river::io::Group::start() {
if (count == 1) {
RIVER_ERROR("GROUP :::::::::::: START() [START]");
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
m_list[iii]->start();
}
}
@ -114,7 +114,7 @@ void audio::river::io::Group::stop() {
RIVER_ERROR("request stop ");
int32_t count = 0;
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
count += m_list[iii]->getNumberOfInterface();
}
}
@ -122,7 +122,7 @@ void audio::river::io::Group::stop() {
if (count == 0) {
RIVER_ERROR("GROUP :::::::::::: STOP() [START]");
for (int32_t iii=m_list.size()-1; iii>=0; --iii) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
m_list[iii]->stop();
}
}
@ -130,11 +130,11 @@ void audio::river::io::Group::stop() {
}
}
void audio::river::io::Group::generateDot(ememory::SharedPtr<etk::io::Interface>& _io, bool _hardwareNode) {
void audio::river::io::Group::generateDot(etk::FSNode& _node, bool _hardwareNode) {
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] != null) {
if (m_list[iii] != nullptr) {
if (m_list[iii]->isHarwareNode() == _hardwareNode) {
m_list[iii]->generateDot(_io);
m_list[iii]->generateDot(_node);
}
}
}

View File

@ -1,15 +1,15 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/String.hpp>
#include <etk/Vector.hpp>
#include <string>
#include <vector>
#include <ejson/ejson.hpp>
#include <etk/io/Interface.hpp>
#include <etk/os/FSNode.hpp>
namespace audio {
namespace river {
@ -32,23 +32,25 @@ namespace audio {
/**
* @brief Destructor
*/
~Group() = default;
~Group() {
// TODO : ...
}
private:
etk::Vector< ememory::SharedPtr<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:
/**
* @brief Create a group with all node needed to syncronize together
* @param[in] _obj json document to create all the node in the group named _name
* @param[in] _name Name of the group to create
*/
void createFrom(const ejson::Document& _obj, const etk::String& _name);
void createFrom(const ejson::Document& _obj, const std::string& _name);
/**
* @brief Get a node in the group (if the node is not in the group nothing append).
* @param[in] _name Name of the node requested.
* @return null 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.
*/
ememory::SharedPtr<audio::river::io::Node> getNode(const etk::String& _name);
ememory::SharedPtr<audio::river::io::Node> getNode(const std::string& _name);
/**
* @brief Start the group.
* @note all sub-node will be started.
@ -65,7 +67,7 @@ namespace audio {
* @param[in] _hardwareNode true if user want only display the hardware
* node and not the software node. false The oposite.
*/
void generateDot(ememory::SharedPtr<etk::io::Interface>& _node, bool _hardwareNode);
void generateDot(etk::FSNode& _node, bool _hardwareNode);
};
}
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/io/Manager.hpp>
@ -12,18 +12,16 @@
#include <audio/river/io/NodeMuxer.hpp>
#include <audio/river/io/NodeOrchestra.hpp>
#include <audio/river/io/NodePortAudio.hpp>
#include <etk/os/FSNode.hpp>
#include <ememory/memory.hpp>
#include <etk/types.hpp>
#include <etk/path/fileSystem.hpp>
#include <etk/uri/uri.hpp>
#include <utility>
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
extern "C" {
#include <portaudio/portaudio.h>
}
#include <portaudio/portaudio.h>
#endif
static etk::String basicAutoConfig =
static std::string basicAutoConfig =
"{\n"
" microphone:{\n"
" io:'input',\n"
@ -57,7 +55,6 @@ static etk::String basicAutoConfig =
"}\n";
static etk::Uri pathToTheRiverConfigInHome(etk::path::getHomePath() / ".local" / "share" / "audio-river" / "config.json");
audio::river::io::Manager::Manager() {
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
@ -68,28 +65,23 @@ audio::river::io::Manager::Manager() {
#endif
}
void audio::river::io::Manager::init(const etk::Uri& _uri) {
RIVER_ERROR("kjqsdhfkjqshdfkjqhsdskjdfhfkqjshqhskdjfhqsdfqsdqsdfqsdqsdfqsdfqsdfqsdfqsdfqsd");
ethread::RecursiveLock lock(m_mutex);
if (_uri.isEmpty() == true) {
if (m_config.load(pathToTheRiverConfigInHome) == false) {
RIVER_INFO("Load default config");
m_config.parse(basicAutoConfig);
} else {
RIVER_INFO("Load default user configuration: " << pathToTheRiverConfigInHome);
}
} else if (m_config.load(_uri) == false) {
RIVER_ERROR("you must set a basic configuration file for harware configuration: " << _uri);
void audio::river::io::Manager::init(const std::string& _filename) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (_filename == "") {
RIVER_INFO("Load default config");
m_config.parse(basicAutoConfig);
} else if (m_config.load(_filename) == false) {
RIVER_ERROR("you must set a basic configuration file for harware configuration: '" << _filename << "'");
}
}
void audio::river::io::Manager::initString(const etk::String& _data) {
ethread::RecursiveLock lock(m_mutex);
void audio::river::io::Manager::initString(const std::string& _data) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
m_config.parse(_data);
}
void audio::river::io::Manager::unInit() {
ethread::RecursiveLock lock(m_mutex);
std::unique_lock<std::recursive_mutex> lock(m_mutex);
// TODO : ...
}
@ -106,88 +98,88 @@ ememory::SharedPtr<audio::river::io::Manager> audio::river::io::Manager::getInst
if (audio::river::isInit() == false) {
return ememory::SharedPtr<audio::river::io::Manager>();
}
static ememory::SharedPtr<audio::river::io::Manager> manager(ETK_NEW(Manager));
static ememory::SharedPtr<audio::river::io::Manager> manager(new Manager());
return manager;
}
etk::Vector<etk::String> audio::river::io::Manager::getListStreamInput() {
ethread::RecursiveLock lock(m_mutex);
etk::Vector<etk::String> output;
etk::Vector<etk::String> keys = m_config.getKeys();
std::vector<std::string> audio::river::io::Manager::getListStreamInput() {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (auto &it : keys) {
const ejson::Object tmppp = m_config[it].toObject();
if (tmppp.exist() == true) {
etk::String type = tmppp["io"].toString().get("error");
std::string type = tmppp["io"].toString().get("error");
if ( type == "input"
|| type == "PAinput") {
output.pushBack(it);
output.push_back(it);
}
}
}
return output;
}
etk::Vector<etk::String> audio::river::io::Manager::getListStreamOutput() {
ethread::RecursiveLock lock(m_mutex);
etk::Vector<etk::String> output;
etk::Vector<etk::String> keys = m_config.getKeys();
std::vector<std::string> audio::river::io::Manager::getListStreamOutput() {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (auto &it : keys) {
const ejson::Object tmppp = m_config[it].toObject();
if (tmppp.exist() == true) {
etk::String type = tmppp["io"].toString().get("error");
std::string type = tmppp["io"].toString().get("error");
if ( type == "output"
|| type == "PAoutput") {
output.pushBack(it);
output.push_back(it);
}
}
}
return output;
}
etk::Vector<etk::String> audio::river::io::Manager::getListStreamVirtual() {
ethread::RecursiveLock lock(m_mutex);
etk::Vector<etk::String> output;
etk::Vector<etk::String> keys = m_config.getKeys();
std::vector<std::string> audio::river::io::Manager::getListStreamVirtual() {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (auto &it : keys) {
const ejson::Object tmppp = m_config[it].toObject();
if (tmppp.exist() == true) {
etk::String type = tmppp["io"].toString().get("error");
std::string type = tmppp["io"].toString().get("error");
if ( type != "input"
&& type != "PAinput"
&& type != "output"
&& type != "PAoutput"
&& type != "error") {
output.pushBack(it);
output.push_back(it);
}
}
}
return output;
}
etk::Vector<etk::String> audio::river::io::Manager::getListStream() {
ethread::RecursiveLock lock(m_mutex);
etk::Vector<etk::String> output;
etk::Vector<etk::String> keys = m_config.getKeys();
std::vector<std::string> audio::river::io::Manager::getListStream() {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
std::vector<std::string> output;
std::vector<std::string> keys = m_config.getKeys();
for (auto &it : keys) {
const ejson::Object tmppp = m_config[it].toObject();
if (tmppp.exist() == true) {
etk::String type = tmppp["io"].toString().get("error");
std::string type = tmppp["io"].toString().get("error");
if (type != "error") {
output.pushBack(it);
output.push_back(it);
}
}
}
return output;
}
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(const etk::String& _name) {
ethread::RecursiveLock lock(m_mutex);
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
RIVER_WARNING("Get node : " << _name);
// search in the standalone list :
for (size_t iii=0; iii<m_list.size(); ++iii) {
ememory::SharedPtr<audio::river::io::Node> tmppp = m_list[iii].lock();
if ( tmppp != null
if ( tmppp != nullptr
&& _name == tmppp->getName()) {
RIVER_WARNING(" find it ... in standalone");
return tmppp;
@ -195,12 +187,12 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
}
// search in the group list:
{
for (etk::Map<etk::String, ememory::SharedPtr<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) {
if (it->second != null) {
if (it->second != nullptr) {
ememory::SharedPtr<audio::river::io::Node> node = it->second->getNode(_name);
if (node != null) {
if (node != nullptr) {
RIVER_WARNING(" find it ... in group: " << it->first);
return node;
}
@ -212,16 +204,16 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
const ejson::Object tmpObject = m_config[_name].toObject();
if (tmpObject.exist() == true) {
//Check if it is in a group:
etk::String groupName = tmpObject["group"].toString().get();
std::string groupName = tmpObject["group"].toString().get();
// get type : io
etk::String ioType = tmpObject["io"].toString().get("error");
std::string ioType = tmpObject["io"].toString().get("error");
if ( groupName != ""
&& ( ioType == "input"
|| ioType == "output"
|| ioType == "PAinput"
|| ioType == "PAoutput") ) {
ememory::SharedPtr<audio::river::io::Group> tmpGroup = getGroup(groupName);
if (tmpGroup == null) {
if (tmpGroup == nullptr) {
RIVER_WARNING("Can not get group ... '" << groupName << "'");
return ememory::SharedPtr<audio::river::io::Node>();
}
@ -236,7 +228,7 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
|| ioType == "output") {
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_name, tmpObject);
m_list.pushBack(tmp);
m_list.push_back(tmp);
return tmp;
#else
RIVER_WARNING("not present interface");
@ -246,7 +238,7 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
|| ioType == "PAoutput") {
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_name, tmpObject);
m_list.pushBack(tmp);
m_list.push_back(tmp);
return tmp;
#else
RIVER_WARNING("not present interface");
@ -254,12 +246,12 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
}
if (ioType == "aec") {
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeAEC::create(_name, tmpObject);
m_list.pushBack(tmp);
m_list.push_back(tmp);
return tmp;
}
if (ioType == "muxer") {
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeMuxer::create(_name, tmpObject);
m_list.pushBack(tmp);
m_list.push_back(tmp);
return tmp;
}
}
@ -268,14 +260,14 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
return ememory::SharedPtr<audio::river::io::Node>();
}
ememory::SharedPtr<audio::drain::VolumeElement> audio::river::io::Manager::getVolumeGroup(const etk::String& _name) {
ethread::RecursiveLock lock(m_mutex);
ememory::SharedPtr<audio::drain::VolumeElement> audio::river::io::Manager::getVolumeGroup(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
if (_name == "") {
RIVER_ERROR("Try to create an audio group with no name ...");
return ememory::SharedPtr<audio::drain::VolumeElement>();
}
for (size_t iii=0; iii<m_volumeGroup.size(); ++iii) {
if (m_volumeGroup[iii] == null) {
if (m_volumeGroup[iii] == nullptr) {
continue;
}
if (m_volumeGroup[iii]->getName() == _name) {
@ -284,14 +276,14 @@ ememory::SharedPtr<audio::drain::VolumeElement> audio::river::io::Manager::getVo
}
RIVER_DEBUG("Add a new volume group : '" << _name << "'");
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = ememory::makeShared<audio::drain::VolumeElement>(_name);
m_volumeGroup.pushBack(tmpVolume);
m_volumeGroup.push_back(tmpVolume);
return tmpVolume;
}
bool audio::river::io::Manager::setVolume(const etk::String& _volumeName, float _valuedB) {
ethread::RecursiveLock lock(m_mutex);
bool audio::river::io::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == null) {
if (volume == nullptr) {
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'");
return false;
}
@ -303,79 +295,79 @@ bool audio::river::io::Manager::setVolume(const etk::String& _volumeName, float
volume->setVolume(_valuedB);
for (size_t iii=0; iii<m_list.size(); ++iii) {
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != null) {
if (val != nullptr) {
val->volumeChange();
}
}
return true;
}
float audio::river::io::Manager::getVolume(const etk::String& _volumeName) {
ethread::RecursiveLock lock(m_mutex);
float audio::river::io::Manager::getVolume(const std::string& _volumeName) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == null) {
if (volume == nullptr) {
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
return 0.0f;
}
return volume->getVolume();
}
etk::Pair<float,float> audio::river::io::Manager::getVolumeRange(const etk::String& _volumeName) const {
return etk::makePair<float,float>(-300, 300);
std::pair<float,float> audio::river::io::Manager::getVolumeRange(const std::string& _volumeName) const {
return std::make_pair<float,float>(-300, 300);
}
void audio::river::io::Manager::setMute(const etk::String& _volumeName, bool _mute) {
ethread::RecursiveLock lock(m_mutex);
void audio::river::io::Manager::setMute(const std::string& _volumeName, bool _mute) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == null) {
if (volume == nullptr) {
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'");
return;
}
volume->setMute(_mute);
for (size_t iii=0; iii<m_list.size(); ++iii) {
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != null) {
if (val != nullptr) {
val->volumeChange();
}
}
}
bool audio::river::io::Manager::getMute(const etk::String& _volumeName) {
ethread::RecursiveLock lock(m_mutex);
bool audio::river::io::Manager::getMute(const std::string& _volumeName) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
if (volume == null) {
if (volume == nullptr) {
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
return false;
}
return volume->getMute();
}
void audio::river::io::Manager::generateDot(const etk::Uri& _uri) {
ethread::RecursiveLock lock(m_mutex);
ememory::SharedPtr<etk::io::Interface> ioFile = etk::uri::get(_uri);
RIVER_INFO("Generate the DOT files: " << _uri);
if (ioFile->open(etk::io::OpenMode::Write) == false) {
RIVER_ERROR("Can not Write the dot file (fail to open) : " << _uri);
void audio::river::io::Manager::generateDot(const std::string& _filename) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
etk::FSNode node(_filename);
RIVER_INFO("Generate the DOT files: " << node);
if (node.fileOpenWrite() == false) {
RIVER_ERROR("Can not Write the dot file (fail to open) : " << node);
return;
}
*ioFile << "digraph G {" << "\n";
*ioFile << " rankdir=\"LR\";\n";
node << "digraph G {" << "\n";
node << " rankdir=\"LR\";\n";
// First Step : Create all HW interface:
{
// standalone
for (size_t iii=0; iii<m_list.size(); ++iii) {
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != null) {
if (val != nullptr) {
if (val->isHarwareNode() == true) {
val->generateDot(ioFile);
val->generateDot(node);
}
}
}
for (etk::Map<etk::String, ememory::SharedPtr<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) {
if (it->second != null) {
it->second->generateDot(ioFile, true);
if (it->second != nullptr) {
it->second->generateDot(node, true);
}
}
}
@ -384,36 +376,37 @@ void audio::river::io::Manager::generateDot(const etk::Uri& _uri) {
// standalone
for (size_t iii=0; iii<m_list.size(); ++iii) {
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
if (val != null) {
if (val != nullptr) {
if (val->isHarwareNode() == false) {
val->generateDot(ioFile);
val->generateDot(node);
}
}
}
for (etk::Map<etk::String, ememory::SharedPtr<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) {
if (it->second != null) {
it->second->generateDot(ioFile, false);
if (it->second != nullptr) {
it->second->generateDot(node, false);
}
}
}
*ioFile << "}" << "\n";
ioFile->close();
RIVER_INFO("Generate the DOT files: " << _uri << " (DONE)");
node << "}" << "\n";
node.fileClose();
RIVER_INFO("Generate the DOT files: " << node << " (DONE)");
}
ememory::SharedPtr<audio::river::io::Group> audio::river::io::Manager::getGroup(const etk::String& _name) {
ethread::RecursiveLock lock(m_mutex);
ememory::SharedPtr<audio::river::io::Group> audio::river::io::Manager::getGroup(const std::string& _name) {
std::unique_lock<std::recursive_mutex> lock(m_mutex);
ememory::SharedPtr<audio::river::io::Group> out;
etk::Map<etk::String, ememory::SharedPtr<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()) {
RIVER_INFO("Create a new group: " << _name << " (START)");
out = ememory::makeShared<audio::river::io::Group>();
if (out != null) {
if (out != nullptr) {
out->createFrom(m_config, _name);
m_listGroup.add(_name, out);
std::pair<std::string, ememory::SharedPtr<audio::river::io::Group> > plop(std::string(_name), out);
m_listGroup.insert(plop);
RIVER_INFO("Create a new group: " << _name << " ( END )");
} else {
RIVER_ERROR("Can not create new group: " << _name << " ( END )");

View File

@ -1,22 +1,24 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/String.hpp>
#include <etk/Vector.hpp>
#include <etk/Map.hpp>
#include <ethread/Mutex.hpp>
#include <etk/Function.hpp>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <cstdint>
#include <mutex>
#include <chrono>
#include <functional>
#include <ememory/memory.hpp>
#include <audio/format.hpp>
#include <audio/channel.hpp>
#include <ejson/ejson.hpp>
#include <audio/drain/Volume.hpp>
#include <audio/river/io/Group.hpp>
#include <ethread/MutexRecursive.hpp>
namespace audio {
namespace river {
@ -28,7 +30,7 @@ namespace audio {
*/
class Manager : public ememory::EnableSharedFromThis<Manager> {
private:
mutable ethread::MutexRecursive m_mutex; //!< prevent multiple access
mutable std::recursive_mutex m_mutex; //!< prevent multiple access
private:
/**
* @brief Constructor
@ -42,58 +44,58 @@ namespace audio {
~Manager();
/**
* @brief Called by audio::river::init() to set the hardware configuration file.
* @param[in] _uri Uri file to initialize.
* @param[in] _filename Name of the file to initialize.
*/
void init(const etk::Uri& _uri);
void init(const std::string& _filename);
/**
* @brief Called by audio::river::initString() to set the hardware configuration string.
* @param[in] _data json configuration string.
*/
void initString(const etk::String& _data);
void initString(const std::string& _data);
/**
* @brief Called by audio::river::inInit() to uninitialize all the low level interface.
*/
void unInit();
private:
ejson::Document m_config; //!< harware configuration
etk::Vector<ememory::SharedPtr<audio::river::io::Node> > m_listKeepAlive; //!< list of all Node that might be keep alive sone/all time
etk::Vector<ememory::WeakPtr<audio::river::io::Node> > m_list; //!< List of all IO node
std::vector<ememory::SharedPtr<audio::river::io::Node> > m_listKeepAlive; //!< list of all Node that might be keep alive sone/all time
std::vector<ememory::WeakPtr<audio::river::io::Node> > m_list; //!< List of all IO node
public:
/**
* @brief Get a node with his name (the name is set in the description file.
* @param[in] _name Name of the node
* @return Pointer on the noe or a null 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.
*/
ememory::SharedPtr<audio::river::io::Node> getNode(const etk::String& _name);
ememory::SharedPtr<audio::river::io::Node> getNode(const std::string& _name);
private:
etk::Vector<ememory::SharedPtr<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:
/**
* @brief Get a volume in the global list of vilume
* @param[in] _name Name of the volume.
* @return pointer on the requested volume (create it if does not exist). null if the name is empty.
* @return pointer on the requested volume (create it if does not exist). nullptr if the name is empty.
*/
ememory::SharedPtr<audio::drain::VolumeElement> getVolumeGroup(const etk::String& _name);
ememory::SharedPtr<audio::drain::VolumeElement> getVolumeGroup(const std::string& _name);
/**
* @brief Get all input audio stream.
* @return a list of all availlables input stream name
*/
etk::Vector<etk::String> getListStreamInput();
std::vector<std::string> getListStreamInput();
/**
* @brief Get all output audio stream.
* @return a list of all availlables output stream name
*/
etk::Vector<etk::String> getListStreamOutput();
std::vector<std::string> getListStreamOutput();
/**
* @brief Get all audio virtual stream.
* @return a list of all availlables virtual stream name
*/
etk::Vector<etk::String> getListStreamVirtual();
std::vector<std::string> getListStreamVirtual();
/**
* @brief Get all audio stream.
* @return a list of all availlables stream name
*/
etk::Vector<etk::String> getListStream();
std::vector<std::string> getListStream();
/**
* @brief Set a volume for a specific group
@ -103,46 +105,46 @@ namespace audio {
* @return false An error occured
* @example : setVolume("MASTER", -3.0f);
*/
bool setVolume(const etk::String& _volumeName, float _valuedB);
bool setVolume(const std::string& _volumeName, float _valuedB);
/**
* @brief Get a volume value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The Volume value in dB.
* @example ret = getVolume("MASTER"); can return something like ret = -3.0f
*/
float getVolume(const etk::String& _volumeName);
float getVolume(const std::string& _volumeName);
/**
* @brief Get a parameter value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The requested value Range.
* @example ret = getVolumeRange("MASTER"); can return something like ret=(-120.0f,0.0f)
*/
etk::Pair<float,float> getVolumeRange(const etk::String& _volumeName) const;
std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
/**
* @brief Set a Mute for a specific volume group
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @param[in] _mute Mute enable or disable.
*/
void setMute(const etk::String& _volumeName, bool _mute);
void setMute(const std::string& _volumeName, bool _mute);
/**
* @brief Get a volume value
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
* @return The Mute of the volume volume.
*/
bool getMute(const etk::String& _volumeName);
bool getMute(const std::string& _volumeName);
/**
* @brief Generate the dot file corresponding at the actif nodes.
* @param[in] _uri Uri of the file to write data.
* @param[in] _filename Name of the file to write data.
*/
void generateDot(const etk::Uri& _uri);
void generateDot(const std::string& _filename);
private:
etk::Map<etk::String, ememory::SharedPtr<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.
* @param[in] _name Name of the group.
* @return Pointer on the requested group or null if the group does not existed.
* @return Pointer on the requested group or nullptr if the group does not existed.
*/
ememory::SharedPtr<audio::river::io::Group> getGroup(const etk::String& _name);
ememory::SharedPtr<audio::river::io::Group> getGroup(const std::string& _name);
};
}

View File

@ -1,13 +1,13 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include "Node.hpp"
#include <audio/river/debug.hpp>
audio::river::io::Node::Node(const etk::String& _name, const ejson::Object& _config) :
audio::river::io::Node::Node(const std::string& _name, const ejson::Object& _config) :
m_config(_config),
m_name(_name),
m_isInput(false) {
@ -30,7 +30,7 @@ audio::river::io::Node::Node(const etk::String& _name, const ejson::Object& _con
# muxer/demuxer format type (int8-on-int16, int16-on-int32, int24-on-int32, int32-on-int64, float)
mux-demux-type:"int16_on_int32",
*/
etk::String interfaceType = m_config["io"].toString().get();
std::string interfaceType = m_config["io"].toString().get();
RIVER_INFO("interfaceType=" << interfaceType);
if ( interfaceType == "input"
|| interfaceType == "PAinput"
@ -43,33 +43,33 @@ audio::river::io::Node::Node(const etk::String& _name, const ejson::Object& _con
int32_t frequency = m_config["frequency"].toNumber().get(1);
// Get audio format type:
etk::String type = m_config["type"].toString().get("int16");
std::string type = m_config["type"].toString().get("int16");
enum audio::format formatType = audio::getFormatFromString(type);
// Get volume stage :
etk::String volumeName = m_config["volume-name"].toString().get();
std::string volumeName = m_config["volume-name"].toString().get();
if (volumeName != "") {
RIVER_INFO("add node volume stage : '" << volumeName << "'");
// use global manager for volume ...
m_volume = audio::river::io::Manager::getInstance()->getVolumeGroup(volumeName);
}
// Get map type :
etk::Vector<audio::channel> map;
std::vector<audio::channel> map;
const ejson::Array listChannelMap = m_config["channel-map"].toArray();
if ( listChannelMap.exist() == false
|| listChannelMap.size() == 0) {
// set default channel property:
map.pushBack(audio::channel_frontLeft);
map.pushBack(audio::channel_frontRight);
map.push_back(audio::channel_frontLeft);
map.push_back(audio::channel_frontRight);
} else {
for (auto it : listChannelMap) {
etk::String value = it.toString().get();
map.pushBack(audio::getChannelFromString(value));
std::string value = it.toString().get();
map.push_back(audio::getChannelFromString(value));
}
}
hardwareFormat.set(map, formatType, frequency);
etk::String muxerDemuxerConfig;
std::string muxerDemuxerConfig;
if (m_isInput == true) {
muxerDemuxerConfig = m_config["mux-demux-type"].toString().get("int16");
} else {
@ -110,7 +110,7 @@ audio::river::io::Node::~Node() {
size_t audio::river::io::Node::getNumberOfInterface(enum audio::river::modeInterface _interfaceType) {
size_t out = 0;
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() == _interfaceType) {
@ -122,8 +122,8 @@ 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 out = 0;
for (size_t iii=0; iii<m_listAvaillable.size(); ++iii) {
auto element = m_listAvaillable[iii].lock();
if (element == null) {
ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == nullptr) {
continue;
}
if (element->getMode() == _interfaceType) {
@ -134,7 +134,7 @@ size_t audio::river::io::Node::getNumberOfInterfaceAvaillable(enum audio::river:
}
void audio::river::io::Node::registerAsRemote(const ememory::SharedPtr<audio::river::Interface>& _interface) {
auto it = m_listAvaillable.begin();
std::vector<ememory::WeakPtr<audio::river::Interface> >::iterator it = m_listAvaillable.begin();
while (it != m_listAvaillable.end()) {
if (it->expired() == true) {
it = m_listAvaillable.erase(it);
@ -142,19 +142,19 @@ void audio::river::io::Node::registerAsRemote(const ememory::SharedPtr<audio::ri
}
++it;
}
m_listAvaillable.pushBack(_interface);
m_listAvaillable.push_back(_interface);
}
void audio::river::io::Node::interfaceAdd(const ememory::SharedPtr<audio::river::Interface>& _interface) {
{
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
for (size_t iii=0; iii<m_list.size(); ++iii) {
if (_interface == m_list[iii]) {
return;
}
}
RIVER_INFO("ADD interface for stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
m_list.pushBack(_interface);
m_list.push_back(_interface);
}
if (m_list.size() == 1) {
startInGroup();
@ -163,7 +163,7 @@ void audio::river::io::Node::interfaceAdd(const ememory::SharedPtr<audio::river:
void audio::river::io::Node::interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface) {
{
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (_interface == m_list[iii]) {
m_list.erase(m_list.begin()+iii);
@ -175,13 +175,14 @@ void audio::river::io::Node::interfaceRemove(const ememory::SharedPtr<audio::riv
if (m_list.size() == 0) {
stopInGroup();
}
return;
}
void audio::river::io::Node::volumeChange() {
for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) {
auto node = m_listAvaillable[iii].lock();
if (node != null) {
ememory::SharedPtr<audio::river::Interface> node = m_listAvaillable[iii].lock();
if (node != nullptr) {
node->systemVolumeChange();
}
}
@ -190,11 +191,11 @@ void audio::river::io::Node::volumeChange() {
void audio::river::io::Node::newInput(const void* _inputBuffer,
uint32_t _nbChunk,
const audio::Time& _time) {
if (_inputBuffer == null) {
if (_inputBuffer == nullptr) {
return;
}
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_input) {
@ -210,11 +211,11 @@ void audio::river::io::Node::newInput(const void* _inputBuffer,
void audio::river::io::Node::newOutput(void* _outputBuffer,
uint32_t _nbChunk,
const audio::Time& _time) {
if (_outputBuffer == null) {
if (_outputBuffer == nullptr) {
return;
}
enum audio::format muxerFormatType = m_process.getInputConfig().getFormat();
etk::Vector<uint8_t> outputTmp2;
std::vector<uint8_t> outputTmp2;
uint32_t nbByteTmpBuffer = audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size()*_nbChunk;
RIVER_VERBOSE("resize=" << nbByteTmpBuffer);
outputTmp2.resize(nbByteTmpBuffer);
@ -224,13 +225,13 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
// process 16 bits
//////////////////////////////////////////////////////////////////////////////////////////////////
// $$$$ change the int16
etk::Vector<int16_t> output;
std::vector<int16_t> output;
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
// $$$$ change the int16
const int16_t* outputTmp = null;
const int16_t* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
@ -257,12 +258,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 32 bits
//////////////////////////////////////////////////////////////////////////////////////////////////
etk::Vector<int32_t> output;
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 = null;
const int32_t* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
@ -287,12 +288,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 64 bits
//////////////////////////////////////////////////////////////////////////////////////////////////
etk::Vector<int64_t> output;
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 = null;
const int64_t* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
@ -317,12 +318,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 32 bits FLOAT
//////////////////////////////////////////////////////////////////////////////////////////////////
etk::Vector<float> output;
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 = null;
const float* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
@ -346,12 +347,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
//////////////////////////////////////////////////////////////////////////////////////////////////
// process 64 bits FLOAT
//////////////////////////////////////////////////////////////////////////////////////////////////
etk::Vector<double> output;
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 = null;
const double* outputTmp = nullptr;
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
@ -378,7 +379,7 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
// The feedback get the real output data (after processing ...==> then no nneed to specify for each channels
RIVER_VERBOSE(" Feedback :");
for (size_t iii=0; iii< m_list.size(); ++iii) {
if (m_list[iii] == null) {
if (m_list[iii] == nullptr) {
continue;
}
if (m_list[iii]->getMode() != audio::river::modeInterface_feedback) {
@ -391,70 +392,70 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
return;
}
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second) {
static void link(etk::FSNode& _node, const std::string& _first, const std::string& _op, const std::string& _second) {
if (_op == "->") {
*_io << " " << _first << " -> " << _second << ";\n";
_node << " " << _first << " -> " << _second << ";\n";
} else if (_op == "<-") {
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
*_io << " " << _second << " -> " << _first << " [constraint=false];\n";
_node << " " << _first << " -> " <<_second<< " [color=transparent];\n";
_node << " " << _second << " -> " << _first << " [constraint=false];\n";
}
}
void audio::river::io::Node::generateDot(ememory::SharedPtr<etk::io::Interface>& _io) {
*_io << " subgraph clusterNode_" << m_uid << " {\n";
*_io << " color=blue;\n";
*_io << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
void audio::river::io::Node::generateDot(etk::FSNode& _node) {
_node << " subgraph clusterNode_" << m_uid << " {\n";
_node << " color=blue;\n";
_node << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
if (m_isInput == true) {
*_io << " node [shape=rarrow];\n";
*_io << " NODE_" << m_uid << "_HW_interface [ label=\"HW interface\\n interface=ALSA\\n stream=" << m_name << "\\n type=input\" ];\n";
etk::String nameIn;
etk::String nameOut;
m_process.generateDotProcess(_io, 3, m_uid, nameIn, nameOut, false);
*_io << " node [shape=square];\n";
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
_node << " node [shape=rarrow];\n";
_node << " NODE_" << m_uid << "_HW_interface [ label=\"HW interface\\n interface=ALSA\\n stream=" << m_name << "\\n type=input\" ];\n";
std::string nameIn;
std::string nameOut;
m_process.generateDotProcess(_node, 3, m_uid, nameIn, nameOut, false);
_node << " node [shape=square];\n";
_node << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::to_string(m_process.getOutputConfig().getFormat()) << "\" ];\n";
// Link all nodes :
*_io << " NODE_" << m_uid << "_HW_interface -> " << nameIn << " [arrowhead=\"open\"];\n";
*_io << " " << nameOut << " -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
_node << " NODE_" << m_uid << "_HW_interface -> " << nameIn << " [arrowhead=\"open\"];\n";
_node << " " << nameOut << " -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
} else {
size_t nbOutput = getNumberOfInterfaceAvaillable(audio::river::modeInterface_output);
size_t nbfeedback = getNumberOfInterfaceAvaillable(audio::river::modeInterface_feedback);
*_io << " node [shape=larrow];\n";
*_io << " NODE_" << m_uid << "_HW_interface [ label=\"HW interface\\n interface=ALSA\\n stream=" << m_name << "\\n type=output\" ];\n";
etk::String nameIn;
etk::String nameOut;
_node << " node [shape=larrow];\n";
_node << " NODE_" << m_uid << "_HW_interface [ label=\"HW interface\\n interface=ALSA\\n stream=" << m_name << "\\n type=output\" ];\n";
std::string nameIn;
std::string nameOut;
if (nbOutput>0) {
m_process.generateDotProcess(_io, 3, m_uid, nameIn, nameOut, true);
m_process.generateDotProcess(_node, 3, m_uid, nameIn, nameOut, true);
}
*_io << " node [shape=square];\n";
_node << " node [shape=square];\n";
if (nbOutput>0) {
*_io << " NODE_" << m_uid << "_muxer [ label=\"MUXER\\n format=" << etk::toString(m_process.getInputConfig().getFormat()) << "\" ];\n";
_node << " NODE_" << m_uid << "_muxer [ label=\"MUXER\\n format=" << etk::to_string(m_process.getInputConfig().getFormat()) << "\" ];\n";
}
if (nbfeedback>0) {
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
_node << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::to_string(m_process.getOutputConfig().getFormat()) << "\" ];\n";
}
// Link all nodes :
if (nbOutput>0) {
link(_io, "NODE_" + etk::toString(m_uid) + "_HW_interface", "<-", nameOut);
link(_io, nameIn, "<-", "NODE_" + etk::toString(m_uid) + "_muxer");
link(_node, "NODE_" + etk::to_string(m_uid) + "_HW_interface", "<-", nameOut);
link(_node, nameIn, "<-", "NODE_" + etk::to_string(m_uid) + "_muxer");
}
if (nbfeedback>0) {
*_io << " NODE_" << m_uid << "_HW_interface -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
_node << " NODE_" << m_uid << "_HW_interface -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
}
if ( nbOutput>0
&& nbfeedback>0) {
*_io << " { rank=same; NODE_" << m_uid << "_demuxer; NODE_" << m_uid << "_muxer }\n";
_node << " { rank=same; NODE_" << m_uid << "_demuxer; NODE_" << m_uid << "_muxer }\n";
}
}
*_io << " }\n \n";
_node << " }\n \n";
for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) {
if (m_listAvaillable[iii].expired() == true) {
continue;
}
ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == null) {
if (element == nullptr) {
continue;
}
bool isLink = false;
@ -463,13 +464,13 @@ void audio::river::io::Node::generateDot(ememory::SharedPtr<etk::io::Interface>&
isLink = true;
}
}
if (element != null) {
if (element != nullptr) {
if (element->getMode() == modeInterface_input) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
} else if (element->getMode() == modeInterface_output) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_muxer", isLink);
} else if (element->getMode() == modeInterface_feedback) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
} else {
}
@ -480,7 +481,7 @@ void audio::river::io::Node::generateDot(ememory::SharedPtr<etk::io::Interface>&
void audio::river::io::Node::startInGroup() {
ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
if (group != null) {
if (group != nullptr) {
group->start();
} else {
start();
@ -489,7 +490,7 @@ void audio::river::io::Node::startInGroup() {
void audio::river::io::Node::stopInGroup() {
ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
if (group != null) {
if (group != nullptr) {
group->stop();
} else {
stop();

View File

@ -1,13 +1,16 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/String.hpp>
#include <etk/Vector.hpp>
#include <etk/Function.hpp>
#include <string>
#include <vector>
#include <list>
#include <cstdint>
#include <chrono>
#include <functional>
#include <ememory/memory.hpp>
#include <audio/format.hpp>
#include <audio/channel.hpp>
@ -15,7 +18,7 @@
#include <audio/river/Interface.hpp>
#include <audio/drain/IOFormatInterface.hpp>
#include <audio/drain/Volume.hpp>
#include <etk/io/Interface.hpp>
#include <etk/os/FSNode.hpp>
namespace audio {
namespace river {
@ -36,7 +39,7 @@ namespace audio {
* @param[in] _name Name of the node.
* @param[in] _config Configuration of the node.
*/
Node(const etk::String& _name, const ejson::Object& _config);
Node(const std::string& _name, const ejson::Object& _config);
public:
/**
* @brief Destructor
@ -51,7 +54,7 @@ namespace audio {
return false;
};
protected:
mutable ethread::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.
const ejson::Object m_config; //!< configuration description.
protected:
audio::drain::Process m_process; //!< Low level algorithms
@ -81,8 +84,8 @@ namespace audio {
protected:
ememory::SharedPtr<audio::drain::VolumeElement> m_volume; //!< if a volume is set it is set here ... for hardware interface only.
protected:
etk::Vector<ememory::WeakPtr<audio::river::Interface> > m_listAvaillable; //!< List of all interface that exist on this Node
etk::Vector<ememory::SharedPtr<audio::river::Interface> > m_list; //!< List of all connected interface at this node.
std::vector<ememory::WeakPtr<audio::river::Interface> > m_listAvaillable; //!< List of all interface that exist on 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.
* @param[in] _interfaceType Type of the interface.
@ -121,13 +124,13 @@ namespace audio {
*/
void interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface);
protected:
etk::String m_name; //!< Name of the interface
std::string m_name; //!< Name of the interface
public:
/**
* @brief Get the interface name.
* @return Current name.
*/
const etk::String& getName() {
const std::string& getName() {
return m_name;
}
protected:
@ -209,9 +212,9 @@ namespace audio {
public:
/**
* @brief Generate the node dot file section
* @param[in] _io File interface to dump data.
* @param[in] _node File node to generate the data.
*/
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
virtual void generateDot(etk::FSNode& _node);
};
}
}

View File

@ -1,35 +1,35 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/io/NodeAEC.hpp>
#include <audio/river/debug.hpp>
#include <etk/types.hpp>
#include <ememory/memory.hpp>
#include <etk/Function.hpp>
#include <functional>
ememory::SharedPtr<audio::river::io::NodeAEC> audio::river::io::NodeAEC::create(const etk::String& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeAEC>(ETK_NEW(audio::river::io::NodeAEC, _name, _config));
ememory::SharedPtr<audio::river::io::NodeAEC> audio::river::io::NodeAEC::create(const std::string& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeAEC>(new audio::river::io::NodeAEC(_name, _config));
}
ememory::SharedPtr<audio::river::Interface> audio::river::io::NodeAEC::createInput(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _objectName,
const etk::String& _name) {
const std::string& _objectName,
const std::string& _name) {
// check if the output exist
const ejson::Object tmppp = m_config[_objectName].toObject();
if (tmppp.exist() == false) {
RIVER_ERROR("can not open a non existance virtual interface: '" << _objectName << "' not present in : " << m_config.getKeys());
return ememory::SharedPtr<audio::river::Interface>();
}
etk::String streamName = tmppp["map-on"].toString().get("error");
std::string streamName = tmppp["map-on"].toString().get("error");
m_nbChunk = m_config["nb-chunk"].toNumber().get(1024);
// check if it is an Output:
etk::String type = tmppp["io"].toString().get("error");
std::string type = tmppp["io"].toString().get("error");
if ( type != "input"
&& type != "feedback") {
RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type);
@ -42,14 +42,14 @@ ememory::SharedPtr<audio::river::Interface> audio::river::io::NodeAEC::createInp
// create user iterface:
ememory::SharedPtr<audio::river::Interface> interface;
interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp);
if (interface != null) {
if (interface != nullptr) {
interface->setName(_name);
}
return interface;
}
audio::river::io::NodeAEC::NodeAEC(const etk::String& _name, const ejson::Object& _config) :
audio::river::io::NodeAEC::NodeAEC(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config),
m_P_attaqueTime(1),
m_P_releaseTime(100),
@ -79,15 +79,15 @@ audio::river::io::NodeAEC::NodeAEC(const etk::String& _name, const ejson::Object
algo:"river-remover",
algo-mode:"cutter",
*/
etk::Vector<audio::channel> feedbackMap;
feedbackMap.pushBack(audio::channel_frontCenter);
std::vector<audio::channel> feedbackMap;
feedbackMap.push_back(audio::channel_frontCenter);
RIVER_INFO("Create FEEDBACK : ");
m_interfaceFeedBack = createInput(hardwareFormat.getFrequency(),
feedbackMap,
hardwareFormat.getFormat(),
"map-on-feedback",
_name + "-AEC-feedback");
if (m_interfaceFeedBack == null) {
if (m_interfaceFeedBack == nullptr) {
RIVER_ERROR("Can not opne virtual device ... map-on-feedback in " << _name);
return;
}
@ -97,33 +97,34 @@ audio::river::io::NodeAEC::NodeAEC(const etk::String& _name, const ejson::Object
hardwareFormat.getFormat(),
"map-on-microphone",
_name + "-AEC-microphone");
if (m_interfaceMicrophone == null) {
if (m_interfaceMicrophone == nullptr) {
RIVER_ERROR("Can not opne virtual device ... map-on-microphone in " << _name);
return;
}
// set callback mode ...
m_interfaceFeedBack->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceivedFeedBack(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceFeedBack->setInputCallback(std::bind(&audio::river::io::NodeAEC::onDataReceivedFeedBack,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
// set callback mode ...
m_interfaceMicrophone->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceivedMicrophone(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_bufferMicrophone.setCapacity(echrono::milliseconds(1000),
m_interfaceMicrophone->setInputCallback(std::bind(&audio::river::io::NodeAEC::onDataReceivedMicrophone,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_bufferMicrophone.setCapacity(std::chrono::milliseconds(1000),
audio::getFormatBytes(hardwareFormat.getFormat())*hardwareFormat.getMap().size(),
hardwareFormat.getFrequency());
m_bufferFeedBack.setCapacity(echrono::milliseconds(1000),
m_bufferFeedBack.setCapacity(std::chrono::milliseconds(1000),
audio::getFormatBytes(hardwareFormat.getFormat()), // only one channel ...
hardwareFormat.getFrequency());
@ -138,24 +139,24 @@ audio::river::io::NodeAEC::~NodeAEC() {
};
void audio::river::io::NodeAEC::start() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
if (m_interfaceFeedBack != null) {
if (m_interfaceFeedBack != nullptr) {
RIVER_INFO("Start FEEDBACK : ");
m_interfaceFeedBack->start();
}
if (m_interfaceMicrophone != null) {
if (m_interfaceMicrophone != nullptr) {
RIVER_INFO("Start Microphone : ");
m_interfaceMicrophone->start();
}
}
void audio::river::io::NodeAEC::stop() {
ethread::UniqueLock lock(m_mutex);
if (m_interfaceFeedBack != null) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_interfaceFeedBack != nullptr) {
m_interfaceFeedBack->stop();
}
if (m_interfaceMicrophone != null) {
if (m_interfaceMicrophone != nullptr) {
m_interfaceMicrophone->stop();
}
}
@ -166,14 +167,14 @@ void audio::river::io::NodeAEC::onDataReceivedMicrophone(const void* _data,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
RIVER_DEBUG("Microphone Time=" << _time << " _nbChunk=" << _nbChunk << " _map=" << _map << " _format=" << _format << " freq=" << _frequency);
RIVER_DEBUG(" next=" << _time + audio::Duration(0, _nbChunk*1000000000LL/int64_t(_frequency)) );
if (_format != audio::format_int16) {
RIVER_ERROR("call wrong type ... (need int16_t)");
}
// push data synchronize
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
m_bufferMicrophone.write(_data, _nbChunk, _time);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_Microphone.raw", _data, _nbChunk*_map.size());
process();
@ -184,14 +185,14 @@ void audio::river::io::NodeAEC::onDataReceivedFeedBack(const void* _data,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
RIVER_DEBUG("FeedBack Time=" << _time << " _nbChunk=" << _nbChunk << " _map=" << _map << " _format=" << _format << " freq=" << _frequency);
RIVER_DEBUG(" next=" << _time + audio::Duration(0, _nbChunk*1000000000LL/int64_t(_frequency)) );
if (_format != audio::format_int16) {
RIVER_ERROR("call wrong type ... (need int16_t)");
}
// push data synchronize
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
m_bufferFeedBack.write(_data, _nbChunk, _time);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_FeedBack.raw", _data, _nbChunk*_map.size());
process();
@ -211,7 +212,7 @@ void audio::river::io::NodeAEC::process() {
delta = MicTime - fbTime;
}
RIVER_INFO("check delta " << delta << " > " << m_sampleTime);
RIVER_INFO("check delta " << delta.count() << " > " << m_sampleTime.count());
if (delta > m_sampleTime) {
// Synchronize if possible
if (MicTime < fbTime) {
@ -237,17 +238,17 @@ void audio::river::io::NodeAEC::process() {
fbTime = m_bufferFeedBack.getReadTimeStamp();
if (MicTime-fbTime > m_sampleTime) {
RIVER_ERROR("Can not synchronize flow ... : " << MicTime << " != " << fbTime << " delta = " << (MicTime-fbTime));
RIVER_ERROR("Can not synchronize flow ... : " << MicTime << " != " << fbTime << " delta = " << (MicTime-fbTime).count()/1000 << " µs");
return;
}
etk::Vector<uint8_t> dataMic;
etk::Vector<uint8_t> dataFB;
std::vector<uint8_t> dataMic;
std::vector<uint8_t> dataFB;
dataMic.resize(m_nbChunk*sizeof(int16_t)*2, 0);
dataFB.resize(m_nbChunk*sizeof(int16_t), 0);
while (true) {
MicTime = m_bufferMicrophone.getReadTimeStamp();
fbTime = m_bufferFeedBack.getReadTimeStamp();
RIVER_INFO(" process 256 samples ... micTime=" << MicTime << " fbTime=" << fbTime << " delta = " << (MicTime-fbTime));
RIVER_INFO(" process 256 samples ... micTime=" << MicTime << " fbTime=" << fbTime << " delta = " << (MicTime-fbTime).count());
m_bufferMicrophone.read(&dataMic[0], m_nbChunk);
m_bufferFeedBack.read(&dataFB[0], m_nbChunk);
RIVER_SAVE_FILE_MACRO(int16_t, "REC_Microphone_sync.raw", &dataMic[0], m_nbChunk*getHarwareFormat().getMap().size());
@ -265,12 +266,12 @@ void audio::river::io::NodeAEC::process() {
void audio::river::io::NodeAEC::processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const audio::Time& _time) {
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
// TODO : Set all these parameter in the parameter configuration section ...
int32_t attaqueTime = etk::min(etk::max(0,m_P_attaqueTime),1000);
int32_t releaseTime = etk::min(etk::max(0,m_P_releaseTime),1000);
int32_t min_gain = 32767 * etk::min(etk::max(0,m_P_minimumGain),1000) / 1000;
int32_t threshold = 32767 * etk::min(etk::max(0,m_P_threshold),1000) / 1000;
int32_t attaqueTime = std::min(std::max(0,m_P_attaqueTime),1000);
int32_t releaseTime = std::min(std::max(0,m_P_releaseTime),1000);
int32_t min_gain = 32767 * std::min(std::max(0,m_P_minimumGain),1000) / 1000;
int32_t threshold = 32767 * std::min(std::max(0,m_P_threshold),1000) / 1000;
int32_t latencyTime = etk::min(etk::max(0,m_P_latencyTime),1000);
int32_t latencyTime = std::min(std::max(0,m_P_latencyTime),1000);
int32_t nb_sample_latency = (hardwareFormat.getFrequency()/1000)*latencyTime;
int32_t increaseSample = 32767;
@ -316,34 +317,34 @@ void audio::river::io::NodeAEC::processAEC(void* _dataMic, void* _dataFB, uint32
}
void audio::river::io::NodeAEC::generateDot(ememory::SharedPtr<etk::io::Interface>& _io) {
*_io << " subgraph clusterNode_" << m_uid << " {\n";
*_io << " color=blue;\n";
*_io << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
*_io << " NODE_" << m_uid << "_HW_AEC [ label=\"AEC\\n channelMap=" << etk::toString(getInterfaceFormat().getMap()) << "\" ];\n";
etk::String nameIn;
etk::String nameOut;
m_process.generateDot(_io, 3, m_uid, nameIn, nameOut, false);
*_io << " node [shape=square];\n";
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
void audio::river::io::NodeAEC::generateDot(etk::FSNode& _node) {
_node << " subgraph clusterNode_" << m_uid << " {\n";
_node << " color=blue;\n";
_node << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
_node << " NODE_" << m_uid << "_HW_AEC [ label=\"AEC\\n channelMap=" << etk::to_string(getInterfaceFormat().getMap()) << "\" ];\n";
std::string nameIn;
std::string nameOut;
m_process.generateDot(_node, 3, m_uid, nameIn, nameOut, false);
_node << " node [shape=square];\n";
_node << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::to_string(m_process.getOutputConfig().getFormat()) << "\" ];\n";
// Link all nodes :
*_io << " NODE_" << m_uid << "_HW_AEC -> " << nameIn << ";\n";
*_io << " " << nameOut << " -> NODE_" << m_uid << "_demuxer;\n";
*_io << " }\n";
if (m_interfaceMicrophone != null) {
*_io << " " << m_interfaceMicrophone->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\n";
_node << " NODE_" << m_uid << "_HW_AEC -> " << nameIn << ";\n";
_node << " " << nameOut << " -> NODE_" << m_uid << "_demuxer;\n";
_node << " }\n";
if (m_interfaceMicrophone != nullptr) {
_node << " " << m_interfaceMicrophone->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\n";
}
if (m_interfaceFeedBack != null) {
*_io << " " << m_interfaceFeedBack->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\n";
if (m_interfaceFeedBack != nullptr) {
_node << " " << m_interfaceFeedBack->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\n";
}
*_io << " \n";
_node << " \n";
for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) {
if (m_listAvaillable[iii].expired() == true) {
continue;
}
ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == null) {
if (element == nullptr) {
continue;
}
bool isLink = false;
@ -352,13 +353,13 @@ void audio::river::io::NodeAEC::generateDot(ememory::SharedPtr<etk::io::Interfac
isLink = true;
}
}
if (element != null) {
if (element != nullptr) {
if (element->getMode() == modeInterface_input) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
} else if (element->getMode() == modeInterface_output) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_muxer", isLink);
} else if (element->getMode() == modeInterface_feedback) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
} else {
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -18,14 +18,14 @@ namespace audio {
/**
* @brief Constructor
*/
NodeAEC(const etk::String& _name, const ejson::Object& _config);
NodeAEC(const std::string& _name, const ejson::Object& _config);
public:
/**
* @brief Factory of this Virtual Node.
* @param[in] _name Name of the node.
* @param[in] _config Configuration of the node.
*/
static ememory::SharedPtr<NodeAEC> create(const etk::String& _name, const ejson::Object& _config);
static ememory::SharedPtr<NodeAEC> create(const std::string& _name, const ejson::Object& _config);
/**
* @brief Destructor
*/
@ -45,10 +45,10 @@ namespace audio {
* @return Interfae Pointer.
*/
ememory::SharedPtr<audio::river::Interface> createInput(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _streamName,
const etk::String& _name);
const std::string& _streamName,
const std::string& _name);
/**
* @brief Stream data input callback
* @todo : copy doc ..
@ -58,7 +58,7 @@ namespace audio {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map);
const std::vector<audio::channel>& _map);
/**
* @brief Stream data input callback
* @todo : copy doc ..
@ -68,7 +68,7 @@ namespace audio {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map);
const std::vector<audio::channel>& _map);
protected:
audio::drain::CircularBuffer m_bufferMicrophone; //!< temporary buffer to synchronize data.
audio::drain::CircularBuffer m_bufferFeedBack; //!< temporary buffer to synchronize data.
@ -87,7 +87,7 @@ namespace audio {
*/
void processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const audio::Time& _time);
public:
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
virtual void generateDot(etk::FSNode& _node);
private:
int32_t m_nbChunk;
int32_t m_gainValue;

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#ifdef AUDIO_RIVER_BUILD_FILE
@ -13,8 +13,8 @@
int32_t audio::river::io::NodeFile::recordCallback(const void* _inputBuffer,
const audio::Time& _timeInput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status) {
ethread::UniqueLock lock(m_mutex);
const std::vector<audio::orchestra::status>& _status) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Manage status ...
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newInput(_inputBuffer, _nbChunk, _timeInput);
@ -24,8 +24,8 @@ int32_t audio::river::io::NodeFile::recordCallback(const void* _inputBuffer,
int32_t audio::river::io::NodeFile::playbackCallback(void* _outputBuffer,
const audio::Time& _timeOutput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status) {
ethread::UniqueLock lock(m_mutex);
const std::vector<audio::orchestra::status>& _status) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Manage status ...
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newOutput(_outputBuffer, _nbChunk, _timeOutput);
@ -34,12 +34,12 @@ int32_t audio::river::io::NodeFile::playbackCallback(void* _outputBuffer,
ememory::SharedPtr<audio::river::io::NodeFile> audio::river::io::NodeFile::create(const etk::Path& _path, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeFile>(ETK_NEW(audio::river::io::NodeFile, _path, _config));
ememory::SharedPtr<audio::river::io::NodeFile> audio::river::io::NodeFile::create(const std::string& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeFile>(new audio::river::io::NodeFile(_name, _config));
}
audio::river::io::NodeFile::NodeFile(const etk::Path& _path, const ejson::Object& _config) :
Node(_path.getString(), _config) {
audio::river::io::NodeFile::NodeFile(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
/**
@ -49,8 +49,8 @@ audio::river::io::NodeFile::NodeFile(const etk::Path& _path, const ejson::Object
},
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
*/
etk::String typeInterface = audio::orchestra::type::undefined;
etk::String streamName = "default";
std::string typeInterface = audio::orchestra::type::undefined;
std::string streamName = "default";
const ejson::Object tmpObject = m_config["map-on"].toObject();
if (tmpObject.exist() == false) {
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
@ -67,7 +67,7 @@ audio::river::io::NodeFile::NodeFile(const etk::Path& _path, const ejson::Object
m_interface.instanciate(typeInterface);
m_interface.setName(_name);
// TODO : Check return ...
etk::String type = m_config.getStringValue("type", "int16");
std::string type = m_config.getStringValue("type", "int16");
if (streamName == "") {
streamName = "default";
}
@ -197,40 +197,28 @@ audio::river::io::NodeFile::NodeFile(const etk::Path& _path, const ejson::Object
if (m_isInput == true) {
m_process.setInputConfig(hardwareFormat);
m_process.setOutputConfig(interfaceFormat);
err = m_interface.openStream(null,
&params,
hardwareFormat.getFormat(),
hardwareFormat.getFrequency(),
&m_rtaudioFrameSize,
[=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map
) {
recordCallback(_data, _time, _nbChunk, _map);
},
option
);
err = m_interface.openStream(nullptr, &params,
hardwareFormat.getFormat(), hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
std::bind(&audio::river::io::NodeFile::recordCallback,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_5,
std::placeholders::_6),
option
);
} else {
m_process.setInputConfig(interfaceFormat);
m_process.setOutputConfig(hardwareFormat);
err = m_interface.openStream(&params,
null,
hardwareFormat.getFormat(),
hardwareFormat.getFrequency(),
&m_rtaudioFrameSize,
[=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map
) {
playbackCallback(_data, _time, _nbChunk, _map);
},
option
err = m_interface.openStream(&params, nullptr,
hardwareFormat.getFormat(), hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
std::bind(&audio::river::io::NodeFile::playbackCallback,
this,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6),
option
);
}
if (err != audio::orchestra::error_none) {
@ -240,7 +228,7 @@ audio::river::io::NodeFile::NodeFile(const etk::Path& _path, const ejson::Object
}
audio::river::io::NodeFile::~NodeFile() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("close input stream");
if (m_interface.isStreamOpen() ) {
m_interface.closeStream();
@ -252,25 +240,25 @@ void audio::river::io::NodeFile::threadCallback() {
// open the file
while (m_alive == true) {
ethread::sleepMilliSeconds((100));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void audio::river::io::NodeFile::start() {
ethread::UniqueLock lock(m_mutex);
if (m_thread != null) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_thread != nullptr) {
RIVER_ERROR("Start stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") << " ==> already started ..." );
return;
}
m_alive = true;
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") );
m_thread = ememory::makeShared<ethread::Thread>(&audio::river::io::NodeFile::threadCallback2, this);
m_thread = ememory::makeShared<std::thread>(&audio::river::io::NodeFile::threadCallback2, this);
m_time = audio::Time::now();
}
void audio::river::io::NodeFile::stop() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
m_alive = false;
RIVER_INFO("Stop stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") );
// TODO : Need join ...

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -24,9 +24,9 @@ namespace audio {
/**
* @brief Constructor
*/
NodeFile(const etk::Path& _path, const ejson::Object& _config);
NodeFile(const std::string& _name, const ejson::Object& _config);
public:
static ememory::SharedPtr<NodeFile> create(const etk::Path& _path, const ejson::Object& _config);
static ememory::SharedPtr<NodeFile> create(const std::string& _name, const ejson::Object& _config);
/**
* @brief Destructor
*/
@ -36,13 +36,13 @@ namespace audio {
};
protected:
audio::Time m_time; //!< time of the flow
ememory::SharedPtr<etk::io::Interface>& m_file; //!< File interface
etk::FSNode m_file; //!< File interface
bool m_restartAtEnd; //!< The read is done in loop
uint32_t m_sampleRate; //!< Sample Rate of the Raw file
audio::format m_format; //!< Format of the file
etk::Vector<audio::channel> m_map; //!< Map of the file
ememory::SharedPtr<ethread::Thread> m_thread; //!< playing thread of the flow
bool m_alive; //!< thread is active
std::vector<audio::channel> m_map; //!< Map of the file
ememory::SharedPtr<std::thread> m_thread; //!< playing thread of the flow
std::atomic<bool> m_alive; //!< thread is active
protected:
virtual void start();
virtual void stop();

View File

@ -1,35 +1,35 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/io/NodeMuxer.hpp>
#include <audio/river/debug.hpp>
#include <etk/types.hpp>
#include <ememory/memory.hpp>
#include <etk/Function.hpp>
#include <functional>
ememory::SharedPtr<audio::river::io::NodeMuxer> audio::river::io::NodeMuxer::create(const etk::String& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeMuxer>(ETK_NEW(audio::river::io::NodeMuxer, _name, _config));
ememory::SharedPtr<audio::river::io::NodeMuxer> audio::river::io::NodeMuxer::create(const std::string& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeMuxer>(new audio::river::io::NodeMuxer(_name, _config));
}
ememory::SharedPtr<audio::river::Interface> audio::river::io::NodeMuxer::createInput(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _objectName,
const etk::String& _name) {
const std::string& _objectName,
const std::string& _name) {
// check if the output exist
const ejson::Object tmppp = m_config[_objectName].toObject();
if (tmppp.exist() == false) {
RIVER_ERROR("can not open a non existance virtual interface: '" << _objectName << "' not present in : " << m_config.getKeys());
return ememory::SharedPtr<audio::river::Interface>();
}
etk::String streamName = tmppp["map-on"].toString().get("error");
std::string streamName = tmppp["map-on"].toString().get("error");
// check if it is an Output:
etk::String type = tmppp["io"].toString().get("error");
std::string type = tmppp["io"].toString().get("error");
if ( type != "input"
&& type != "feedback") {
RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type);
@ -42,14 +42,14 @@ ememory::SharedPtr<audio::river::Interface> audio::river::io::NodeMuxer::createI
// create user iterface:
ememory::SharedPtr<audio::river::Interface> interface;
interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp);
if (interface != null) {
if (interface != nullptr) {
interface->setName(_name);
}
return interface;
}
audio::river::io::NodeMuxer::NodeMuxer(const etk::String& _name, const ejson::Object& _config) :
audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@ -77,11 +77,11 @@ audio::river::io::NodeMuxer::NodeMuxer(const etk::String& _name, const ejson::Ob
*/
RIVER_INFO("Create IN 1 : ");
m_interfaceInput1 = createInput(hardwareFormat.getFrequency(),
etk::Vector<audio::channel>(),
std::vector<audio::channel>(),
hardwareFormat.getFormat(),
"map-on-input-1",
_name + "-muxer-in1");
if (m_interfaceInput1 == null) {
if (m_interfaceInput1 == nullptr) {
RIVER_ERROR("Can not opne virtual device ... map-on-input-1 in " << _name);
return;
}
@ -92,8 +92,8 @@ audio::river::io::NodeMuxer::NodeMuxer(const etk::String& _name, const ejson::Ob
} else {
m_mapInput1.clear();
for (const auto it : listChannelMap) {
etk::String value = it.toString().get();
m_mapInput1.pushBack(audio::getChannelFromString(value));
std::string value = it.toString().get();
m_mapInput1.push_back(audio::getChannelFromString(value));
}
if (m_mapInput1.size() != m_interfaceInput1->getInterfaceFormat().getMap().size()) {
RIVER_ERROR("Request remap of the Input 1 the 2 size is wrong ... request=");
@ -103,11 +103,11 @@ audio::river::io::NodeMuxer::NodeMuxer(const etk::String& _name, const ejson::Ob
RIVER_INFO("Create IN 2 : ");
m_interfaceInput2 = createInput(hardwareFormat.getFrequency(),
etk::Vector<audio::channel>(),
std::vector<audio::channel>(),
hardwareFormat.getFormat(),
"map-on-input-2",
_name + "-muxer-in2");
if (m_interfaceInput2 == null) {
if (m_interfaceInput2 == nullptr) {
RIVER_ERROR("Can not opne virtual device ... map-on-input-2 in " << _name);
return;
}
@ -118,8 +118,8 @@ audio::river::io::NodeMuxer::NodeMuxer(const etk::String& _name, const ejson::Ob
} else {
m_mapInput2.clear();
for (const auto it : listChannelMap2) {
etk::String value = it.toString().get();
m_mapInput2.pushBack(audio::getChannelFromString(value));
std::string value = it.toString().get();
m_mapInput2.push_back(audio::getChannelFromString(value));
}
if (m_mapInput2.size() != m_interfaceInput2->getInterfaceFormat().getMap().size()) {
RIVER_ERROR("Request remap of the Input 2 the 2 size is wrong ... request=");
@ -128,28 +128,28 @@ audio::river::io::NodeMuxer::NodeMuxer(const etk::String& _name, const ejson::Ob
}
// set callback mode ...
m_interfaceInput1->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceivedInput1(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceInput1->setInputCallback(std::bind(&audio::river::io::NodeMuxer::onDataReceivedInput1,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
// set callback mode ...
m_interfaceInput2->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceivedInput2(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceInput2->setInputCallback(std::bind(&audio::river::io::NodeMuxer::onDataReceivedInput2,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_bufferInput1.setCapacity(echrono::milliseconds(1000),
m_bufferInput1.setCapacity(std::chrono::milliseconds(1000),
audio::getFormatBytes(hardwareFormat.getFormat())*m_mapInput1.size(),
hardwareFormat.getFrequency());
m_bufferInput2.setCapacity(echrono::milliseconds(1000),
m_bufferInput2.setCapacity(std::chrono::milliseconds(1000),
audio::getFormatBytes(hardwareFormat.getFormat())*m_mapInput2.size(),
hardwareFormat.getFrequency());
@ -164,24 +164,24 @@ audio::river::io::NodeMuxer::~NodeMuxer() {
};
void audio::river::io::NodeMuxer::start() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
if (m_interfaceInput1 != null) {
if (m_interfaceInput1 != nullptr) {
RIVER_INFO("Start FEEDBACK : ");
m_interfaceInput1->start();
}
if (m_interfaceInput2 != null) {
if (m_interfaceInput2 != nullptr) {
RIVER_INFO("Start Microphone : ");
m_interfaceInput2->start();
}
}
void audio::river::io::NodeMuxer::stop() {
ethread::UniqueLock lock(m_mutex);
if (m_interfaceInput1 != null) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_interfaceInput1 != nullptr) {
m_interfaceInput1->stop();
}
if (m_interfaceInput2 != null) {
if (m_interfaceInput2 != nullptr) {
m_interfaceInput2->stop();
}
}
@ -192,7 +192,7 @@ void audio::river::io::NodeMuxer::onDataReceivedInput1(const void* _data,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
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)) );
/*
@ -201,7 +201,7 @@ void audio::river::io::NodeMuxer::onDataReceivedInput1(const void* _data,
}
*/
// push data synchronize
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
m_bufferInput1.write(_data, _nbChunk, _time);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_input_1.raw", _data, _nbChunk*_map.size());
process();
@ -212,7 +212,7 @@ void audio::river::io::NodeMuxer::onDataReceivedInput2(const void* _data,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
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)) );
/*
@ -221,7 +221,7 @@ void audio::river::io::NodeMuxer::onDataReceivedInput2(const void* _data,
}
*/
// push data synchronize
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
m_bufferInput2.write(_data, _nbChunk, _time);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_input_2.raw", _data, _nbChunk*_map.size());
process();
@ -243,7 +243,7 @@ void audio::river::io::NodeMuxer::process() {
} else {
delta = in1Time - in2Time;
}
RIVER_VERBOSE("check delta " << delta << " > " << m_sampleTime);
RIVER_VERBOSE("check delta " << delta.count() << " > " << m_sampleTime.count());
if (delta > m_sampleTime) {
// Synchronize if possible
if (in1Time < in2Time) {
@ -271,18 +271,18 @@ void audio::river::io::NodeMuxer::process() {
in2Time = m_bufferInput2.getReadTimeStamp();
if (in1Time-in2Time > m_sampleTime) {
RIVER_ERROR("Can not synchronize flow ... : " << in1Time << " != " << in2Time << " delta = " << (in1Time-in2Time));
RIVER_ERROR("Can not synchronize flow ... : " << in1Time << " != " << in2Time << " delta = " << (in1Time-in2Time).count()/1000 << " µs");
return;
}
etk::Vector<uint8_t> dataIn1;
etk::Vector<uint8_t> dataIn2;
std::vector<uint8_t> dataIn1;
std::vector<uint8_t> dataIn2;
dataIn1.resize(256*audio::getFormatBytes(getInterfaceFormat().getFormat())*m_mapInput1.size(), 0);
dataIn2.resize(256*audio::getFormatBytes(getInterfaceFormat().getFormat())*m_mapInput2.size(), 0);
m_data.resize(256*audio::getFormatBytes(getInterfaceFormat().getFormat())*getInterfaceFormat().getMap().size(), 0);
while (true) {
in1Time = m_bufferInput1.getReadTimeStamp();
in2Time = m_bufferInput2.getReadTimeStamp();
//RIVER_INFO(" process 256 samples ... in1Time=" << in1Time << " in2Time=" << in2Time << " delta = " << (in1Time-in2Time));
//RIVER_INFO(" process 256 samples ... in1Time=" << in1Time << " in2Time=" << in2Time << " delta = " << (in1Time-in2Time).count());
m_bufferInput1.read(&dataIn1[0], 256);
m_bufferInput2.read(&dataIn2[0], 256);
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_output_1.raw", &dataIn1[0], 256 * m_mapInput1.size());
@ -297,7 +297,7 @@ void audio::river::io::NodeMuxer::process() {
}
void audio::river::io::NodeMuxer::reorder(void* _output, uint32_t _nbChunk, void* _input, const etk::Vector<audio::channel>& _mapInput) {
void audio::river::io::NodeMuxer::reorder(void* _output, uint32_t _nbChunk, void* _input, const std::vector<audio::channel>& _mapInput) {
// real process: (only depend of data size):
switch (getInterfaceFormat().getFormat()) {
case audio::format_int8:
@ -433,36 +433,36 @@ void audio::river::io::NodeMuxer::processMuxer(void* _dataIn1, void* _dataIn2, u
}
void audio::river::io::NodeMuxer::generateDot(ememory::SharedPtr<etk::io::Interface>& _io) {
*_io << " subgraph clusterNode_" << m_uid << " {\n";
*_io << " color=blue;\n";
*_io << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
void audio::river::io::NodeMuxer::generateDot(etk::FSNode& _node) {
_node << " subgraph clusterNode_" << m_uid << " {\n";
_node << " color=blue;\n";
_node << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
*_io << " node [shape=box];\n";
_node << " node [shape=box];\n";
// TODO : Create a structure ...
*_io << " NODE_" << m_uid << "_HW_MUXER [ label=\"Muxer\\n channelMap=" << etk::toString(getInterfaceFormat().getMap()) << "\" ];\n";
etk::String nameIn;
etk::String nameOut;
m_process.generateDot(_io, 3, m_uid, nameIn, nameOut, false);
*_io << " node [shape=square];\n";
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
_node << " NODE_" << m_uid << "_HW_MUXER [ label=\"Muxer\\n channelMap=" << etk::to_string(getInterfaceFormat().getMap()) << "\" ];\n";
std::string nameIn;
std::string nameOut;
m_process.generateDot(_node, 3, m_uid, nameIn, nameOut, false);
_node << " node [shape=square];\n";
_node << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::to_string(m_process.getOutputConfig().getFormat()) << "\" ];\n";
// Link all nodes :
*_io << " NODE_" << m_uid << "_HW_MUXER -> " << nameIn << ";\n";
*_io << " " << nameOut << " -> NODE_" << m_uid << "_demuxer;\n";
*_io << " }\n";
if (m_interfaceInput2 != null) {
*_io << " " << m_interfaceInput2->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
_node << " NODE_" << m_uid << "_HW_MUXER -> " << nameIn << ";\n";
_node << " " << nameOut << " -> NODE_" << m_uid << "_demuxer;\n";
_node << " }\n";
if (m_interfaceInput2 != nullptr) {
_node << " " << m_interfaceInput2->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
}
if (m_interfaceInput1 != null) {
*_io << " " << m_interfaceInput1->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
if (m_interfaceInput1 != nullptr) {
_node << " " << m_interfaceInput1->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
}
*_io << " \n";
_node << " \n";
for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) {
if (m_listAvaillable[iii].expired() == true) {
continue;
}
ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
if (element == null) {
if (element == nullptr) {
continue;
}
bool isLink = false;
@ -471,17 +471,17 @@ void audio::river::io::NodeMuxer::generateDot(ememory::SharedPtr<etk::io::Interf
isLink = true;
}
}
if (element != null) {
if (element != nullptr) {
if (element->getMode() == modeInterface_input) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
} else if (element->getMode() == modeInterface_output) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_muxer", isLink);
} else if (element->getMode() == modeInterface_feedback) {
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
} else {
}
}
}
*_io << "\n";
_node << "\n";
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -18,9 +18,9 @@ namespace audio {
/**
* @brief Constructor
*/
NodeMuxer(const etk::String& _name, const ejson::Object& _config);
NodeMuxer(const std::string& _name, const ejson::Object& _config);
public:
static ememory::SharedPtr<NodeMuxer> create(const etk::String& _name, const ejson::Object& _config);
static ememory::SharedPtr<NodeMuxer> create(const std::string& _name, const ejson::Object& _config);
/**
* @brief Destructor
*/
@ -31,34 +31,34 @@ namespace audio {
ememory::SharedPtr<audio::river::Interface> m_interfaceInput1;
ememory::SharedPtr<audio::river::Interface> m_interfaceInput2;
ememory::SharedPtr<audio::river::Interface> createInput(float _freq,
const etk::Vector<audio::channel>& _map,
const std::vector<audio::channel>& _map,
audio::format _format,
const etk::String& _streamName,
const etk::String& _name);
const std::string& _streamName,
const std::string& _name);
void onDataReceivedInput1(const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map);
const std::vector<audio::channel>& _map);
void onDataReceivedInput2(const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map);
etk::Vector<audio::channel> m_mapInput1;
etk::Vector<audio::channel> m_mapInput2;
const std::vector<audio::channel>& _map);
std::vector<audio::channel> m_mapInput1;
std::vector<audio::channel> m_mapInput2;
audio::drain::CircularBuffer m_bufferInput1;
audio::drain::CircularBuffer m_bufferInput2;
audio::Duration m_sampleTime; //!< represent the sample time at the specify frequency.
void process();
void processMuxer(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const audio::Time& _time);
etk::Vector<uint8_t> m_data;
std::vector<uint8_t> m_data;
public:
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
virtual void generateDot(etk::FSNode& _node);
private:
void reorder(void* _output, uint32_t _nbChunk, void* _input, const etk::Vector<audio::channel>& _mapInput);
void reorder(void* _output, uint32_t _nbChunk, void* _input, const std::vector<audio::channel>& _mapInput);
};
}
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
@ -13,8 +13,8 @@
int32_t audio::river::io::NodeOrchestra::recordCallback(const void* _inputBuffer,
const audio::Time& _timeInput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status) {
ethread::UniqueLock lock(m_mutex);
const std::vector<audio::orchestra::status>& _status) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Manage status ...
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newInput(_inputBuffer, _nbChunk, _timeInput);
@ -24,8 +24,8 @@ int32_t audio::river::io::NodeOrchestra::recordCallback(const void* _inputBuffer
int32_t audio::river::io::NodeOrchestra::playbackCallback(void* _outputBuffer,
const audio::Time& _timeOutput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status) {
ethread::UniqueLock lock(m_mutex);
const std::vector<audio::orchestra::status>& _status) {
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Manage status ...
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size() << " data=" << uint64_t(_outputBuffer));
newOutput(_outputBuffer, _nbChunk, _timeOutput);
@ -34,11 +34,11 @@ int32_t audio::river::io::NodeOrchestra::playbackCallback(void* _outputBuffer,
ememory::SharedPtr<audio::river::io::NodeOrchestra> audio::river::io::NodeOrchestra::create(const etk::String& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeOrchestra>(ETK_NEW(audio::river::io::NodeOrchestra, _name, _config));
ememory::SharedPtr<audio::river::io::NodeOrchestra> audio::river::io::NodeOrchestra::create(const std::string& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodeOrchestra>(new audio::river::io::NodeOrchestra(_name, _config));
}
audio::river::io::NodeOrchestra::NodeOrchestra(const etk::String& _name, const ejson::Object& _config) :
audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@ -49,8 +49,8 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const etk::String& _name, const e
},
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
*/
etk::String typeInterface = audio::orchestra::typeUndefined;
etk::String streamName = "default";
std::string typeInterface = audio::orchestra::typeUndefined;
std::string streamName = "default";
const ejson::Object tmpObject = m_config["map-on"].toObject();
if (tmpObject.exist() == false) {
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
@ -67,7 +67,7 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const etk::String& _name, const e
m_interface.instanciate(typeInterface);
m_interface.setName(_name);
// TODO : Check return ...
etk::String type = m_config["type"].toString().get("int16");
std::string type = m_config["type"].toString().get("int16");
if (streamName == "") {
streamName = "default";
}
@ -198,39 +198,29 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const etk::String& _name, const e
if (m_isInput == true) {
m_process.setInputConfig(hardwareFormat);
m_process.setOutputConfig(interfaceFormat);
err = m_interface.openStream(null,
&params,
hardwareFormat.getFormat(),
hardwareFormat.getFrequency(),
&m_rtaudioFrameSize,
[=] (const void* _inputBuffer,
const audio::Time& _timeInput,
void* _outputBuffer,
const audio::Time& _timeOutput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status) {
return recordCallback(_inputBuffer, _timeInput, _nbChunk, _status);
},
option
);
err = m_interface.openStream(nullptr, &params,
hardwareFormat.getFormat(), hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
std::bind(&audio::river::io::NodeOrchestra::recordCallback,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_5,
std::placeholders::_6),
option
);
} else {
m_process.setInputConfig(interfaceFormat);
m_process.setOutputConfig(hardwareFormat);
err = m_interface.openStream(&params,
null,
hardwareFormat.getFormat(),
hardwareFormat.getFrequency(),
&m_rtaudioFrameSize,
[=] (const void* _inputBuffer,
const audio::Time& _timeInput,
void* _outputBuffer,
const audio::Time& _timeOutput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status) {
return playbackCallback(_outputBuffer, _timeOutput, _nbChunk, _status);
},
option
);
err = m_interface.openStream(&params, nullptr,
hardwareFormat.getFormat(), hardwareFormat.getFrequency(), &m_rtaudioFrameSize,
std::bind(&audio::river::io::NodeOrchestra::playbackCallback,
this,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6),
option
);
}
if (err != audio::orchestra::error_none) {
RIVER_ERROR("Create stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not create stream " << err);
@ -239,7 +229,7 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const etk::String& _name, const e
}
audio::river::io::NodeOrchestra::~NodeOrchestra() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("close input stream");
if (m_interface.isStreamOpen() ) {
m_interface.closeStream();
@ -247,7 +237,7 @@ audio::river::io::NodeOrchestra::~NodeOrchestra() {
};
void audio::river::io::NodeOrchestra::start() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
enum audio::orchestra::error err = m_interface.startStream();
if (err != audio::orchestra::error_none) {
@ -256,7 +246,7 @@ void audio::river::io::NodeOrchestra::start() {
}
void audio::river::io::NodeOrchestra::stop() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("Stop stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
enum audio::orchestra::error err = m_interface.stopStream();
if (err != audio::orchestra::error_none) {

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -24,9 +24,9 @@ namespace audio {
/**
* @brief Constructor
*/
NodeOrchestra(const etk::String& _name, const ejson::Object& _config);
NodeOrchestra(const std::string& _name, const ejson::Object& _config);
public:
static ememory::SharedPtr<NodeOrchestra> create(const etk::String& _name, const ejson::Object& _config);
static ememory::SharedPtr<NodeOrchestra> create(const std::string& _name, const ejson::Object& _config);
/**
* @brief Destructor
*/
@ -50,7 +50,7 @@ namespace audio {
int32_t recordCallback(const void* _inputBuffer,
const audio::Time& _timeInput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status);
const std::vector<audio::orchestra::status>& _status);
/**
* @brief Playback callback. Request new data on output
* @param[in,out] _outputBuffer Pointer on the buffer to fill data.
@ -62,7 +62,7 @@ namespace audio {
int32_t playbackCallback(void* _outputBuffer,
const audio::Time& _timeOutput,
uint32_t _nbChunk,
const etk::Vector<audio::orchestra::status>& _status);
const std::vector<audio::orchestra::status>& _status);
protected:
virtual void start();
virtual void stop();

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
@ -39,13 +39,13 @@ int32_t audio::river::io::NodePortAudio::duplexCallback(const void* _inputBuffer
const audio::Time& _timeOutput,
uint32_t _nbChunk,
PaStreamCallbackFlags _status) {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
// TODO : Manage status ...
if (_inputBuffer != null) {
if (_inputBuffer != nullptr) {
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newInput(_inputBuffer, _nbChunk, _timeInput);
}
if (_outputBuffer != null) {
if (_outputBuffer != nullptr) {
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
newOutput(_outputBuffer, _nbChunk, _timeOutput);
}
@ -53,11 +53,11 @@ int32_t audio::river::io::NodePortAudio::duplexCallback(const void* _inputBuffer
}
ememory::SharedPtr<audio::river::io::NodePortAudio> audio::river::io::NodePortAudio::create(const etk::String& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodePortAudio>(ETK_NEW(audio::river::io::NodePortAudio,_name, _config));
ememory::SharedPtr<audio::river::io::NodePortAudio> audio::river::io::NodePortAudio::create(const std::string& _name, const ejson::Object& _config) {
return ememory::SharedPtr<audio::river::io::NodePortAudio>(new audio::river::io::NodePortAudio(_name, _config));
}
audio::river::io::NodePortAudio::NodePortAudio(const etk::String& _name, const ejson::Object& _config) :
audio::river::io::NodePortAudio::NodePortAudio(const std::string& _name, const ejson::Object& _config) :
Node(_name, _config) {
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
@ -68,12 +68,12 @@ audio::river::io::NodePortAudio::NodePortAudio(const etk::String& _name, const e
},
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
*/
etk::String streamName = "default";
std::string streamName = "default";
const ejson::Object tmpObject = m_config["map-on"].toObject();
if (tmpObject.exist() == false) {
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
} else {
etk::String value = tmpObject.getStringValue("interface", "default");
std::string value = tmpObject.getStringValue("interface", "default");
streamName = tmpObject.getStringValue("name", "default");
}
int32_t nbChunk = m_config.getNumberValue("nb-chunk", 1024);
@ -105,7 +105,7 @@ audio::river::io::NodePortAudio::NodePortAudio(const etk::String& _name, const e
}
audio::river::io::NodePortAudio::~NodePortAudio() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("close input stream");
PaError err = Pa_CloseStream( m_stream );
if( err != paNoError ) {
@ -114,7 +114,7 @@ audio::river::io::NodePortAudio::~NodePortAudio() {
};
void audio::river::io::NodePortAudio::start() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
PaError err = Pa_StartStream(m_stream);
if( err != paNoError ) {
@ -123,7 +123,7 @@ void audio::river::io::NodePortAudio::start() {
}
void audio::river::io::NodePortAudio::stop() {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
RIVER_INFO("Stop stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
PaError err = Pa_StopStream(m_stream);
if( err != paNoError ) {

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -21,9 +21,9 @@ namespace audio {
/**
* @brief Constructor
*/
NodePortAudio(const etk::String& _name, const ejson::Object& _config);
NodePortAudio(const std::string& _name, const ejson::Object& _config);
public:
static ememory::SharedPtr<NodePortAudio> create(const etk::String& _name, const ejson::Object& _config);
static ememory::SharedPtr<NodePortAudio> create(const std::string& _name, const ejson::Object& _config);
/**
* @brief Destructor
*/

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/river.hpp>
@ -9,17 +9,17 @@
#include <audio/river/io/Manager.hpp>
static bool river_isInit = false;
static etk::String river_configFile = "";
static std::string river_configFile = "";
void audio::river::init(const etk::String& _filename) {
void audio::river::init(const std::string& _filename) {
if (river_isInit == false) {
river_isInit = true;
river_configFile = _filename;
RIVER_DEBUG("init RIVER :" << river_configFile);
ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
if (mng != null) {
if (mng != nullptr) {
mng->init(river_configFile);
}
} else {
@ -27,13 +27,13 @@ void audio::river::init(const etk::String& _filename) {
}
}
void audio::river::initString(const etk::String& _config) {
void audio::river::initString(const std::string& _config) {
if (river_isInit == false) {
river_isInit = true;
river_configFile = _config;
RIVER_DEBUG("init RIVER with config.");
ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
if (mng != null) {
if (mng != nullptr) {
mng->initString(river_configFile);
}
} else {
@ -46,7 +46,7 @@ void audio::river::unInit() {
river_isInit = false;
RIVER_DEBUG("un-init RIVER.");
ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
if (mng != null) {
if (mng != nullptr) {
RIVER_ERROR("Can not get on the RIVER hardware manager !!!");
mng->unInit();
}

View File

@ -1,12 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/String.hpp>
/**
* @brief Audio library namespace
*/
@ -19,12 +18,12 @@ namespace audio {
* @brief Initialize the River Library
* @param[in] _filename Name of the configuration file (if "" ==> default config file)
*/
void init(const etk::String& _filename = "");
void init(const std::string& _filename = "");
/**
* @brief Initialize the River Library with a json data string
* @param[in] _config json sting data
*/
void initString(const etk::String& _config);
void initString(const std::string& _config);
/**
* @brief Un-initialize the River Library
* @note this close all stream of all interfaces.

View File

@ -74,46 +74,4 @@ In every interface we need to define some Element:
- "nb-chunk": Number of chunk to open the stream.
Generic configuration file use
==============================
You can specify a generic configuration file foir a user in the path ```~/.local/share/audio-river/config.json```
The default config file is:
```{.json}
{
microphone:{
io:"input",
map-on:{
interface:"auto",
name:"default",
},
frequency:0,
channel-map:[
"front-left", "front-right"
],
type:"auto",
nb-chunk:1024,
mux-demux-type:"float"
},
speaker:{
io:"output",
map-on:{
interface:"alsa",
name:"default",
},
frequency:0,
channel-map:[
"front-left", "front-right",
],
type:"auto",
nb-chunk:1024,
volume-name:"MASTER",
mux-demux-type:"float"
}
}
```
If the pplication start with no name it try to load this file and if it fail it load the internalversion of a basic file

View File

@ -21,7 +21,7 @@ What change:
```{.cpp}
//Get the generic feedback on speaker:
interface = manager->createFeedback(48000,
etk::Vector<audio::channel>(),
std::vector<audio::channel>(),
audio::format_int16,
"speaker");
```

View File

@ -62,16 +62,16 @@ Are there any licensing restrictions? {#audio_river_mainpage_license_
AUDIO-RIVER is **FREE software** and _all sub-library are FREE and staticly linkable !!!_
License (MPL v2.0) {#audio_river_mainpage_license}
==================
License (APACHE-2.0) {#audio_river_mainpage_license}
====================
Copyright AUDIO-RIVER Edouard DUPIN
Licensed under the Mozilla Public License, Version 2.0 (the "License");
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
<https://www.mozilla.org/MPL/2.0>
<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,

View File

@ -31,7 +31,7 @@ With a file:
```{.cpp}
// initialize river interface
river::init("DATA:///configFileName.json");
river::init("DATA:configFileName.json");
```
With a json string:

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.debug as debug
import lutin.tools as tools
@ -13,7 +13,7 @@ def get_desc():
return "Multi-nodal audio interface test"
def get_licence():
return "MPL-2"
return "APACHE-2"
def get_compagny_type():
return "com"
@ -26,20 +26,11 @@ def get_maintainer():
def configure(target, my_module):
my_module.add_src_file([
'test/main.cpp',
'test/testAEC.cpp',
'test/testEchoDelay.cpp',
'test/testFormat.cpp',
'test/testMuxer.cpp',
'test/testPlaybackCallback.cpp',
'test/testPlaybackWrite.cpp',
'test/testRecordCallback.cpp',
'test/testRecordRead.cpp',
'test/testVolume.cpp',
'test/main.cpp'
])
my_module.add_depend([
'audio-river',
'etest',
'gtest',
'etk',
'test-debug'
])

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.debug as debug
import lutin.tools as tools
@ -10,7 +10,7 @@ def get_desc():
return "Multi-nodal audio interface"
def get_licence():
return "MPL-2"
return "APACHE-2"
def get_compagny_type():
return "com"

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <ewol/ewol.hpp>
@ -13,14 +13,14 @@
#include <etk/tool.hpp>
appl::Windows::Windows() :
m_composer(null) {
m_composer(nullptr) {
addObjectType("appl::Windows");
propertyTitle.setDirectCheck("River IO viewer");
}
void appl::Windows::init() {
ewol::widget::Windows::init();
etk::String composition = etk::String("");
std::string composition = std::string("");
composition += "<sizer mode='vert'>\n";
composition += " <sizer mode='hori' lock='true' min-size='10,10%'>\n";
composition += " <button name='bt-record' expend='true' fill='true'>\n";
@ -38,7 +38,7 @@ void appl::Windows::init() {
composition += "</sizer>\n";
m_composer = ewol::widget::Composer::create();
if (m_composer == null) {
if (m_composer == nullptr) {
APPL_CRITICAL(" An error occured ... in the windows creatrion ...");
return;
}
@ -50,14 +50,14 @@ void appl::Windows::init() {
void appl::Windows::onCallbackRecord() {
ememory::SharedPtr<audio::river::widget::TemporalViewer> tmpDisp = ememory::dynamicPointerCast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
if (tmpDisp != nullptr) {
tmpDisp->recordToggle();
}
}
void appl::Windows::onCallbackGenerate() {
ememory::SharedPtr<audio::river::widget::TemporalViewer> tmpDisp = ememory::dynamicPointerCast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer"));
if (tmpDisp != null) {
if (tmpDisp != nullptr) {
tmpDisp->generateToggle();
}
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <appl/debug.hpp>

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2019, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @copyright 2015, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
@ -15,9 +15,8 @@
#include <ewol/widget/Manager.hpp>
#include <ewol/context/Context.hpp>
#include <audio/river/widget/TemporalViewer.hpp>
#include <etk/theme/theme.hpp>
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" microphone:{\n"
" io:'input',\n"
@ -35,38 +34,9 @@ static const etk::String configurationRiver =
class MainApplication : public ewol::context::Application {
public:
virtual void onCreate(ewol::Context& _context) override {
APPL_INFO(" == > CREATE ... (START) [" << gale::getBoardType() << "] (" << gale::getCompilationMode() << ") (BEGIN)");
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
etk::String tmpppp = _context.getCmd().get(iii);
if ( tmpppp == "-h"
|| tmpppp == "--help") {
//APPL_PRINT(" --ctags=xxx c-flags-file-name" );
exit(0);
}
}
etk::theme::setName("COLOR", "color/white/");
bool init(ewol::Context& _context, size_t _initId) {
APPL_INFO("==> Init APPL (START) [" << ewol::getBoardType() << "] (" << ewol::getCompilationMode() << ")");
_context.setSize(vec2(800, 600));
_context.setTitle("edn");
// select internal data for font ...
_context.getFontDefault().setUseExternal(true);
#ifdef __TARGET_OS__Android
_context.getFontDefault().set("FreeSerif", 19);
#else
_context.getFontDefault().set("FreeSerif;DejaVuSansMono",14);
#endif
// set the application icon ...
//_context.setIcon("DATA:///icon.png");
APPL_INFO("==> CREATE ... (END)");
}
void onStart(ewol::Context& _context) override {
APPL_INFO("==> START ... (BEGIN)");
// init internal global value
audio::river::initString(configurationRiver);
_context.setSize(vec2(800, 600));
@ -78,54 +48,15 @@ class MainApplication : public ewol::context::Application {
audio::river::widget::TemporalViewer::createManagerWidget(_context.getWidgetManager());
ememory::SharedPtr<ewol::widget::Windows> basicWindows = appl::Windows::create();
if (basicWindows == null) {
APPL_ERROR("Can not allocate the basic windows");
_context.exit(-1);
return;
}
// create the specific windows
_context.setWindows(basicWindows);
// add files
APPL_INFO("show list of files : ");
/*
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
etk::String tmpppp = _context.getCmd().get(iii);
if (tmpppp.startWith("--ctags=") == true) {
etk::String name = tmpppp.extract(8);
APPL_INFO("Load ctag file : \"" << name << "\"" );
appl::setCtagsFileName(name);
} else if ( tmpppp == "-h"
|| tmpppp == "--help") {
// nothing to do ...
} else {
etk::Path file(tmpppp);
if (etk::path::isFile(file) == true) {
APPL_INFO("need load file : \"" << file << "\"" );
m_bufferManager->open(file);
} else if (etk::path::isDirectory(file) == true) {
etk::Vector<etk::Path> listOfFiles = etk::path::list(file, etk::path::LIST_FILE);
for (auto &it: listOfFiles) {
if (etk::path::isFile(it) == true) {
APPL_INFO("need load file : \"" << it << "\"" );
m_bufferManager->open(it);
}
}
}
}
}
*/
APPL_INFO("==> START ... (END)");
return;
APPL_INFO("==> Init APPL (END)");
return true;
}
void onStop(ewol::Context& _context) override {
APPL_INFO("==> STOP ... (START)");
APPL_INFO("==> STOP ... (END)");
}
void onKillDemand(ewol::Context& _context) override {
APPL_INFO("==> User demand kill ... (START)");
_context.exit(0);
APPL_INFO("==> User demand kill ... (END)");
void unInit(ewol::Context& _context) {
APPL_INFO("==> Un-Init APPL (START)");
// nothing to do...
APPL_INFO("==> Un-Init APPL (END)");
}
};
@ -136,5 +67,5 @@ class MainApplication : public ewol::context::Application {
*/
int main(int _argc, const char *_argv[]) {
// second possibility
return ewol::run(ETK_NEW(MainApplication), _argc, _argv);
return ewol::run(new MainApplication(), _argc, _argv);
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.debug as debug
import lutin.tools as tools
import os
@ -11,7 +11,7 @@ def get_desc():
return "Simpleaudio IO viewer and test ..."
def get_licence():
return "MPL-2"
return "APACHE-2"
def get_compagny_type():
return "com"

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.debug as debug
import lutin.tools as tools
@ -13,7 +13,7 @@ def get_desc():
return "Read some data"
def get_licence():
return "MPL-2"
return "APACHE-2"
def get_compagny_type():
return "com"
@ -30,7 +30,6 @@ def configure(target, my_module):
])
my_module.add_depend([
'audio-river',
'test-debug',
'etk'
])
return True

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
//! [audio_river_sample_read_all]
@ -10,16 +10,14 @@
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
//! [audio_river_sample_include]
#include <etk/os/FSNode.hpp>
#include <etk/etk.hpp>
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#include <test-debug/debug.hpp>
#include <etk/uri/uri.hpp>
#include <thread>
//! [audio_river_sample_read_config_file]
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" microphone:{\n"
" io:'input',\n"
@ -43,38 +41,38 @@ void onDataReceived(const void* _data,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map,
ememory::SharedPtr<etk::io::Interface> _fileIO) {
const std::vector<audio::channel>& _map,
etk::FSNode* _outputNode) {
if ( _format != audio::format_int16
&& _format != audio::format_float) {
TEST_ERROR("Call wrong type ... (need int16_t.float)");
std::cout << "[ERROR] call wrong type ... (need int16_t.float)" << std::endl;
return;
}
//! [audio_river_sample_callback_implement]
if (_fileIO->isOpen() == false) {
if (_outputNode->fileIsOpen() == false) {
if (_format != audio::format_int16) {
// get the curent power of the signal.
const int16_t* data = static_cast<const int16_t*>(_data);
int64_t value = 0;
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
value += etk::abs(data[iii]);
value += std::abs(data[iii]);
}
value /= (_nbChunk*_map.size());
TEST_PRINT("Get data ... average=" << int32_t(value));
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 += etk::abs(data[iii]);
value += std::abs(data[iii]);
}
value /= (_nbChunk*_map.size());
TEST_PRINT("Get data ... average=" << float(value));
std::cout << "Get data ... average=" << float(value) << std::endl;
}
} else {
// just write data
TEST_VERBOSE("Get data ... chunks=" << _nbChunk << " time=" << _time);
_fileIO->write(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
//std::cout << "Get data ... chunks=" << _nbChunk << " time=" << _time << std::endl;
_outputNode->fileWrite(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
}
}
@ -84,27 +82,27 @@ int main(int _argc, const char **_argv) {
etk::init(_argc, _argv);
//! [audio_river_sample_init]
// local parameter:
etk::String configFile;
etk::String ioName="microphone";
etk::Path outputFileName = "";
std::string configFile;
std::string ioName="microphone";
std::string outputFileName = "";
for (int32_t iii=0; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
std::string data = _argv[iii];
if ( data == "-h"
|| data == "--help") {
TEST_PRINT("Help : ");
TEST_PRINT(" --conf=xxx.json Input/output configuration");
TEST_PRINT(" --io=xxx name configuration input");
TEST_PRINT(" --file=yyy.raw File name to store data");
std::cout << "Help : " << std::endl;
std::cout << " --conf=xxx.json Input/output configuration" << std::endl;
std::cout << " --io=xxx name configuration input" << std::endl;
std::cout << " --file=yyy.raw File name to store data" << std::endl;
exit(0);
} else if (etk::start_with(data, "--conf=") == true) {
configFile = etk::String(data.begin()+7, data.end());
TEST_PRINT("Select config: " << configFile);
configFile = std::string(data.begin()+7, data.end());
std::cout << "Select config: " << configFile << std::endl;
} else if (etk::start_with(data, "--io=") == true) {
ioName = etk::String(data.begin()+5, data.end());
TEST_PRINT("Select io: " << ioName);
ioName = std::string(data.begin()+5, data.end());
std::cout << "Select io: " << ioName << std::endl;
} else if (etk::start_with(data, "--file=") == true) {
outputFileName = etk::String(data.begin()+7, data.end());
TEST_PRINT("Select output file name: " << outputFileName);
outputFileName = std::string(data.begin()+7, data.end());
std::cout << "Select output file name: " << outputFileName << std::endl;
}
}
// initialize river interface
@ -122,35 +120,36 @@ int main(int _argc, const char **_argv) {
ememory::SharedPtr<audio::river::Interface> interface;
//Get the generic input:
interface = manager->createInput(48000,
etk::Vector<audio::channel>(),
std::vector<audio::channel>(),
audio::format_int16,
ioName);
if(interface == null) {
TEST_ERROR("null interface");
if(interface == nullptr) {
std::cout << "nullptr interface" << std::endl;
return -1;
}
//! [audio_river_sample_create_read_interface]
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(outputFileName);
etk::FSNode outputNode;
// open output file if needed:
if (outputFileName.isEmpty() == false) {
fileIO->open(etk::io::OpenMode::Write);
if (outputFileName != "") {
outputNode.setName(outputFileName);
outputNode.fileOpenWrite();
}
//! [audio_river_sample_set_callback]
// set callback mode ...
interface->setInputCallback([&](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map, fileIO);
});
interface->setInputCallback(std::bind(&onDataReceived,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6,
&outputNode));
//! [audio_river_sample_set_callback]
//! [audio_river_sample_read_start_stop]
// start the stream
interface->start();
// wait 10 second ...
ethread::sleepMilliSeconds(1000*(10));
std::this_thread::sleep_for(std::chrono::seconds(10));
// stop the stream
interface->stop();
//! [audio_river_sample_read_start_stop]
@ -161,7 +160,7 @@ int main(int _argc, const char **_argv) {
//! [audio_river_sample_read_reset]
// close the output file
if (outputFileName != "") {
fileIO->close();
outputNode.fileClose();
}
return 0;
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.debug as debug
import lutin.tools as tools
@ -13,7 +13,7 @@ def get_desc():
return "Write some data"
def get_licence():
return "MPL-2"
return "APACHE-2"
def get_compagny_type():
return "com"
@ -30,7 +30,6 @@ def configure(target, my_module):
])
my_module.add_depend([
'audio-river',
'test-debug',
'etk'
])
return True

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
//! [audio_river_sample_write_all]
@ -10,19 +10,17 @@
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etk/etk.hpp>
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#include <test-debug/debug.hpp>
#include <thread>
//! [audio_river_sample_write_config_file]
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
" map-on:{\n"
" interface:'alsa',\n"
" name:'hw:0,3',\n"
" name:'hw:0,0',\n"
" },\n"
" frequency:48000,\n"
//" channel-map:['front-left', 'front-right', 'rear-left', 'rear-right'],\n"
@ -41,14 +39,14 @@ void onDataNeeded(void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _sampleRate,
const etk::Vector<audio::channel>& _map) {
uint32_t _frequency,
const std::vector<audio::channel>& _map) {
static double phase[8] = {0,0,0,0,0,0,0,0};
if (_format != audio::format_int16) {
TEST_ERROR("Call wrong type ... (need int16_t)");
std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl;
}
//TEST_VERBOSE("Map " << _map);
//std::cout << "Map " << _map << std::endl;
int16_t* data = static_cast<int16_t*>(_data);
double baseCycle = 2.0*M_PI/double(48000) * double(440);
for (int32_t iii=0; iii<_nbChunk; iii++) {
@ -67,11 +65,11 @@ int main(int _argc, const char **_argv) {
// the only one init for etk:
etk::init(_argc, _argv);
for (int32_t iii=0; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
std::string data = _argv[iii];
if ( data == "-h"
|| data == "--help") {
TEST_PRINT("Help:");
TEST_PRINT(" ./xxx ---");
std::cout << "Help : " << std::endl;
std::cout << " ./xxx ---" << std::endl;
exit(0);
}
}
@ -84,29 +82,28 @@ int main(int _argc, const char **_argv) {
ememory::SharedPtr<audio::river::Interface> interface;
//Get the generic input:
interface = manager->createOutput(48000,
etk::Vector<audio::channel>(),
std::vector<audio::channel>(),
audio::format_int16,
"speaker");
if(interface == null) {
TEST_ERROR("null interface");
if(interface == nullptr) {
std::cout << "nullptr interface" << std::endl;
return -1;
}
//! [audio_river_sample_create_write_interface]
//! [audio_river_sample_set_callback]
// set callback mode ...
interface->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
interface->setOutputCallback(std::bind(&onDataNeeded,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
//! [audio_river_sample_set_callback]
// start the stream
interface->start();
// wait 10 second ...
ethread::sleepMilliSeconds(1000*(10));
std::this_thread::sleep_for(std::chrono::seconds(10));
// stop the stream
interface->stop();
// remove interface and manager.

View File

@ -1,25 +1,25 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#define TEST_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \
do { \
static FILE *pointerOnFile = null; \
static FILE *pointerOnFile = nullptr; \
static bool errorOpen = false; \
if (pointerOnFile == null) { \
if (pointerOnFile == nullptr) { \
TEST_WARNING("open file '" << fileName << "' type=" << #type); \
pointerOnFile = fopen(fileName,"w"); \
if ( errorOpen == false \
&& pointerOnFile == null) { \
&& pointerOnFile == nullptr) { \
TEST_ERROR("ERROR OPEN file ... '" << fileName << "' type=" << #type); \
errorOpen=true; \
} \
} \
if (pointerOnFile != null) { \
if (pointerOnFile != nullptr) { \
fwrite((dataPointer), sizeof(type), (nbElement), pointerOnFile); \
/* fflush(pointerOnFile);*/ \
} \
@ -30,18 +30,30 @@
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <gtest/gtest.h>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <etk/os/FSNode.hpp>
#include <cmath>
#include <sstream>
#include <ethread/Thread.hpp>
#include <thread>
#include "testAEC.hpp"
#include "testEchoDelay.hpp"
#include "testFormat.hpp"
#include "testMuxer.hpp"
#include "testPlaybackCallback.hpp"
#include "testPlaybackWrite.hpp"
#include "testRecordCallback.hpp"
#include "testRecordRead.hpp"
#include "testVolume.hpp"
int main(int _argc, const char** _argv) {
etest::init(_argc, _argv);
// init Google test :
::testing::InitGoogleTest(&_argc, const_cast<char **>(_argv));
// the only one init for etk:
etk::init(_argc, _argv);
for (int32_t iii=0; iii<_argc ; ++iii) {
etk::String data = _argv[iii];
std::string data = _argv[iii];
if ( data == "-h"
|| data == "--help") {
TEST_PRINT("Help : ");

View File

@ -1,21 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
namespace river_test_aec {
@ -26,35 +16,35 @@ namespace river_test_aec {
ememory::SharedPtr<audio::river::Interface> m_interfaceIn;
audio::drain::CircularBuffer m_buffer;
public:
Linker(ememory::SharedPtr<audio::river::Manager> _manager, const etk::String& _input, const etk::String& _output) :
Linker(ememory::SharedPtr<audio::river::Manager> _manager, const std::string& _input, const std::string& _output) :
m_manager(_manager) {
//Set stereo output:
etk::Vector<audio::channel> channelMap;
std::vector<audio::channel> channelMap;
if (false) { //"speaker" == _output) {
channelMap.pushBack(audio::channel_frontCenter);
channelMap.push_back(audio::channel_frontCenter);
} else {
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
}
m_buffer.setCapacity(echrono::milliseconds(2000), sizeof(int16_t)*channelMap.size(), 48000);
m_buffer.setCapacity(std::chrono::milliseconds(2000), sizeof(int16_t)*channelMap.size(), 48000);
m_interfaceOut = m_manager->createOutput(48000,
channelMap,
audio::format_int16,
_output);
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceOut->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceOut->setOutputCallback(std::bind(&Linker::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_interfaceOut->addVolumeGroup("FLOW");
if ("speaker" == _output) {
m_interfaceOut->setParameter("volume", "FLOW", "0dB");
@ -64,19 +54,19 @@ namespace river_test_aec {
channelMap,
audio::format_int16,
_input);
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceIn->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceIn->setInputCallback(std::bind(&Linker::onDataReceived,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
}
void onDataNeeded(void* _data,
@ -84,7 +74,7 @@ namespace river_test_aec {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
@ -95,31 +85,31 @@ namespace river_test_aec {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
m_buffer.write(_data, _nbChunk);
}
void start() {
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interfaceOut->start();
m_interfaceIn->start();
}
void stop() {
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_manager->generateDotAll("activeProcess.dot");
@ -128,7 +118,7 @@ namespace river_test_aec {
}
};
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -213,7 +203,7 @@ namespace river_test_aec {
ememory::SharedPtr<Linker> processLink2 = ememory::makeShared<Linker>(manager, "microphone", "speaker-test");
processLink1->start();
processLink2->start();
ethread::sleepMilliSeconds(1000*(20));
std::this_thread::sleep_for(std::chrono::seconds(20));
processLink1->stop();
processLink2->stop();

View File

@ -1,21 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
namespace river_test_echo_delay {
class TestClass {
@ -27,12 +17,12 @@ namespace river_test_echo_delay {
double m_phase;
double m_freq;
int32_t m_nextSampleCount;
echrono::milliseconds m_delayBetweenEvent;
std::chrono::milliseconds m_delayBetweenEvent;
audio::Time m_nextTick;
audio::Time m_currentTick;
int32_t m_stateFB;
int32_t m_stateMic;
etk::Vector<uint64_t> m_delayListMic;
std::vector<uint64_t> m_delayListMic;
bool m_estimateVolumeInput;
int16_t m_volumeInputMax;
int16_t m_volumeInputMin;
@ -49,62 +39,62 @@ namespace river_test_echo_delay {
m_estimateVolumeInput(true),
m_gain(-40) {
//Set stereo output:
etk::Vector<audio::channel> channelMap;
std::vector<audio::channel> channelMap;
m_interfaceOut = m_manager->createOutput(48000,
channelMap,
audio::format_int16,
"speaker");
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceOut->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceOut->setOutputCallback(std::bind(&TestClass::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_interfaceOut->addVolumeGroup("FLOW");
m_interfaceOut->setParameter("volume", "FLOW", etk::toString(m_gain) + "dB");
m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB");
m_interfaceIn = m_manager->createInput(48000,
channelMap,
audio::format_int16,
"microphone");
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceIn->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceIn->setInputCallback(std::bind(&TestClass::onDataReceived,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_interfaceFB = m_manager->createFeedback(48000,
channelMap,
audio::format_int16,
"speaker");
if(m_interfaceFB == null) {
TEST_ERROR("null interface");
if(m_interfaceFB == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceFB->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceivedFeedBack(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceFB->setInputCallback(std::bind(&TestClass::onDataReceivedFeedBack,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_manager->generateDotAll("activeProcess.dot");
}
@ -113,7 +103,7 @@ namespace river_test_echo_delay {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
int16_t* data = static_cast<int16_t*>(_data);
double baseCycle = 2.0*M_PI/(double)48000 * m_freq;
if (m_estimateVolumeInput == true) {
@ -137,7 +127,7 @@ namespace river_test_echo_delay {
}
if (m_nextTick == audio::Time()) {
m_nextTick = _time + m_delayBetweenEvent;
m_nextSampleCount = m_delayBetweenEvent.get()*int64_t(_frequency)/1000;
m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000;
m_phase = -1;
}
//TEST_INFO("sample : " << m_nextSampleCount);
@ -146,7 +136,7 @@ namespace river_test_echo_delay {
m_nextSampleCount--;
} else {
m_phase = 0;
m_nextSampleCount = m_delayBetweenEvent.get()*int64_t(_frequency)/1000;
m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000;
m_currentTick = m_nextTick;
m_nextTick += m_delayBetweenEvent;
}
@ -196,11 +186,11 @@ namespace river_test_echo_delay {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
//TEST_SAVE_FILE_MACRO(int16_t, "REC_FeedBack.raw", _data, _nbChunk*_map.size());
TEST_SAVE_FILE_MACRO(int16_t, "REC_FeedBack.raw", _data, _nbChunk*_map.size());
if (m_estimateVolumeInput == true) {
// nothing to do ...
} else {
@ -226,7 +216,7 @@ namespace river_test_echo_delay {
TEST_VERBOSE("FB: 1 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]);
TEST_VERBOSE("FB: 1 position 0: " << iii << " " << data[iii*_map.size() + jjj]);
TEST_WARNING("FB: 1 time detected: " << time << " delay = " << float((time-m_currentTick).get())/1000.0f << "µs");
TEST_WARNING("FB: 1 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs");
}
} else if (m_stateFB == 2) {
// inverse phase
@ -236,7 +226,7 @@ namespace river_test_echo_delay {
audio::Time time = getInterpolateTime(_time, iii-1, data[(iii-1)*_map.size() + jjj], data[iii*_map.size() + jjj], _frequency);
TEST_VERBOSE("FB: 2 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]);
TEST_VERBOSE("FB: 2 position 0: " << iii << " " << data[iii*_map.size() + jjj]);
TEST_WARNING("FB: 2 time detected: " << time << " delay = " << float((time-m_currentTick).get())/1000.0f << "µs");
TEST_WARNING("FB: 2 time detected: " << time << " delay = " << float((time-m_currentTick).count())/1000.0f << "µs");
}
} else if (m_stateFB == 3) {
// TODO : Detect the pic ...
@ -251,11 +241,11 @@ namespace river_test_echo_delay {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
//TEST_SAVE_FILE_MACRO(int16_t, "REC_Microphone.raw", _data, _nbChunk*_map.size());
TEST_SAVE_FILE_MACRO(int16_t, "REC_Microphone.raw", _data, _nbChunk*_map.size());
const int16_t* data = static_cast<const int16_t*>(_data);
if (m_estimateVolumeInput == true) {
m_stateMic ++;
@ -263,8 +253,8 @@ namespace river_test_echo_delay {
if (m_stateMic <= 40) {
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
//TEST_INFO("value=" << data[iii]);
m_volumeInputMax = etk::max(int16_t(data[iii]), m_volumeInputMax);
m_volumeInputMin = etk::min(int16_t(data[iii]), m_volumeInputMin);
m_volumeInputMax = std::max(int16_t(data[iii]), m_volumeInputMax);
m_volumeInputMin = std::min(int16_t(data[iii]), m_volumeInputMin);
}
if (m_stateMic == 40) {
m_volumeInputMax *= 2;
@ -275,8 +265,8 @@ namespace river_test_echo_delay {
int16_t valueMin = 0;
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
//TEST_INFO("value=" << data[iii]);
valueMax = etk::max(int16_t(data[iii]), valueMax);
valueMin = etk::min(int16_t(data[iii]), valueMin);
valueMax = std::max(int16_t(data[iii]), valueMax);
valueMin = std::min(int16_t(data[iii]), valueMin);
}
if ( valueMax > m_volumeInputMax
&& valueMin < m_volumeInputMin
@ -287,8 +277,8 @@ namespace river_test_echo_delay {
)
) {
m_gain += 3.0f;
m_gain = etk::min(m_gain, 0.0f);
m_interfaceOut->setParameter("volume", "FLOW", etk::toString(m_gain) + "dB");
m_gain = std::min(m_gain, 0.0f);
m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB");
TEST_INFO("Set detection volume : " << m_gain << " m_stateMic=" << m_stateMic);
m_stateMic = 3;
m_phase = -1;
@ -301,8 +291,8 @@ namespace river_test_echo_delay {
}
// just update volume
m_gain += 1.0f;
m_gain = etk::min(m_gain, 0.0f);
m_interfaceOut->setParameter("volume", "FLOW", etk::toString(m_gain) + "dB");
m_gain = std::min(m_gain, 0.0f);
m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB");
}
}
}
@ -328,9 +318,9 @@ namespace river_test_echo_delay {
TEST_VERBOSE("MIC: 1 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]);
TEST_VERBOSE("MIC: 1 position 0: " << iii << " " << data[iii*_map.size() + jjj]);
audio::Duration delay = time-m_currentTick;
int32_t sampleDalay = (delay.get()*_frequency)/1000000000LL;
TEST_WARNING("MIC: 1 time detected: " << time << " delay = " << float(delay.get())/1000.0f << "µs samples=" << sampleDalay);
m_delayListMic.pushBack(delay.get());
int32_t sampleDalay = (delay.count()*_frequency)/1000000000LL;
TEST_WARNING("MIC: 1 time detected: " << time << " delay = " << float(delay.count())/1000.0f << "µs samples=" << sampleDalay);
m_delayListMic.push_back(delay.count());
}
} else if (m_stateMic == 2) {
// inverse phase
@ -341,9 +331,9 @@ namespace river_test_echo_delay {
TEST_VERBOSE("MIC: 2 position -1: " << iii-1 << " " << data[(iii-1)*_map.size() + jjj]);
TEST_VERBOSE("MIC: 2 position 0: " << iii << " " << data[iii*_map.size() + jjj]);
audio::Duration delay = time-m_currentTick;
int32_t sampleDalay = (delay.get()*_frequency)/1000000000LL;
TEST_WARNING("MIC: 2 time detected: " << time << " delay = " << float(delay.get())/1000.0f << "µs samples=" << sampleDalay);
m_delayListMic.pushBack(delay.get());
int32_t sampleDalay = (delay.count()*_frequency)/1000000000LL;
TEST_WARNING("MIC: 2 time detected: " << time << " delay = " << float(delay.count())/1000.0f << "µs samples=" << sampleDalay);
m_delayListMic.push_back(delay.count());
}
} else if (m_stateMic == 3) {
// TODO : Detect the pic ...
@ -354,25 +344,25 @@ namespace river_test_echo_delay {
}
}
void run() {
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
if(m_interfaceFB == null) {
TEST_ERROR("null interface");
if(m_interfaceFB == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interfaceOut->start();
m_interfaceIn->start();
//m_interfaceFB->start();
while (m_estimateVolumeInput == true) {
ethread::sleepMilliSeconds((10));
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
ethread::sleepMilliSeconds(1000*(10));
std::this_thread::sleep_for(std::chrono::seconds(10));
//m_interfaceFB->stop();
m_interfaceIn->stop();
m_interfaceOut->stop();
@ -389,7 +379,7 @@ namespace river_test_echo_delay {
}
};
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -428,7 +418,7 @@ namespace river_test_echo_delay {
ememory::SharedPtr<TestClass> process = ememory::makeShared<TestClass>(manager);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
};

View File

@ -1,24 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#pragma once
namespace river_test_format {
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -53,17 +41,17 @@ namespace river_test_format {
m_nbChannels(_nbChannels),
m_generateFreq(550.0f) {
//Set stereo output:
etk::Vector<audio::channel> channelMap;
std::vector<audio::channel> channelMap;
if (m_nbChannels == 1) {
channelMap.pushBack(audio::channel_frontCenter);
channelMap.push_back(audio::channel_frontCenter);
} else if (m_nbChannels == 2) {
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
} else if (m_nbChannels == 4) {
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
channelMap.pushBack(audio::channel_rearLeft);
channelMap.pushBack(audio::channel_rearRight);
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
channelMap.push_back(audio::channel_rearLeft);
channelMap.push_back(audio::channel_rearRight);
} else {
TEST_ERROR("Can not generate with channel != 1,2,4");
return;
@ -73,26 +61,26 @@ namespace river_test_format {
_format,
"speaker",
"WriteModeCallbackType");
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interface->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interface->setOutputCallback(std::bind(&testOutCallbackType::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
}
void onDataNeeded(void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
//TEST_DEBUG("Get data ... " << _format << " map=" << _map << " chunk=" << _nbChunk);
double baseCycle = 2.0*M_PI/double(m_freq) * double(m_generateFreq);
if (_format == audio::format_int16) {
@ -142,78 +130,108 @@ namespace river_test_format {
}
}
void run() {
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->start();
// wait 2 second ...
ethread::sleepMilliSeconds(1000*(1));
std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->stop();
ethread::sleepMilliSeconds((100));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
etk::Vector<float> listFreq = {4000, 8000, 16000, 32000, 48000, 48001, 64000, 96000, 11250, 2250, 44100, 88200};
etk::Vector<int32_t> listChannel = {1, 2, 4};
etk::Vector<audio::format> listFormat = {audio::format_int16, audio::format_int16_on_int32, audio::format_int32, audio::format_float};
TEST(testResampling, base) {
class testResampling : public ::testing::TestWithParam<float> {};
TEST_P(testResampling, base) {
audio::river::initString(configurationRiver);
ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication");
for (auto itFrequency: listFreq) {
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, itFrequency, 2, audio::format_int16);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
}
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, GetParam(), 2, audio::format_int16);
process->run();
process.reset();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
TEST(testFormat, base) {
audio::river::initString(configurationRiver);
ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication");
for (auto itFormat: listFormat) {
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, 2, itFormat);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
}
audio::river::unInit();
}
INSTANTIATE_TEST_CASE_P(InstantiationName,
testResampling,
::testing::Values(4000, 8000, 16000, 32000, 48000, 48001, 64000, 96000, 11250, 2250, 44100, 88200));
TEST(testChannels, base) {
class testFormat : public ::testing::TestWithParam<audio::format> {};
TEST_P(testFormat, base) {
audio::river::initString(configurationRiver);
ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication");
for (auto itChannel: listChannel) {
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, itChannel, audio::format_int16);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
}
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, 2, GetParam());
process->run();
process.reset();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
INSTANTIATE_TEST_CASE_P(InstantiationName,
testFormat,
::testing::Values(audio::format_int16, audio::format_int16_on_int32, audio::format_int32, audio::format_float));
class testChannels : public ::testing::TestWithParam<int32_t> {};
TEST_P(testChannels, base) {
audio::river::initString(configurationRiver);
ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication");
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, GetParam(), audio::format_int16);
process->run();
process.reset();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
INSTANTIATE_TEST_CASE_P(InstantiationName,
testChannels,
::testing::Values(1,2,4));
TEST(TestALL, testChannelsFormatResampling) {
audio::river::initString(configurationRiver);
ememory::SharedPtr<audio::river::Manager> manager;
manager = audio::river::Manager::create("testApplication");
TEST_INFO("test convert flaot to output (callback mode)");
for (auto itFrequency: listFreq) {
for (auto itChannel: listChannel) {
for (auto itFormat: listFormat) {
TEST_INFO("freq=" << itFrequency << " channel=" << listChannel << " format=" << audio::getFormatString(itFormat));
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, itFrequency, itChannel, itFormat);
std::vector<float> listFreq;
listFreq.push_back(4000);
listFreq.push_back(8000);
listFreq.push_back(16000);
listFreq.push_back(32000);
listFreq.push_back(48000);
listFreq.push_back(48001);
listFreq.push_back(64000);
listFreq.push_back(96000);
listFreq.push_back(11250);
listFreq.push_back(2250);
listFreq.push_back(44100);
listFreq.push_back(88200);
std::vector<int32_t> listChannel;
listChannel.push_back(1);
listChannel.push_back(2);
listChannel.push_back(4);
std::vector<audio::format> listFormat;
listFormat.push_back(audio::format_int16);
listFormat.push_back(audio::format_int16_on_int32);
listFormat.push_back(audio::format_int32);
listFormat.push_back(audio::format_float);
for (size_t fff=0; fff<listFreq.size(); ++fff) {
for (size_t ccc=0; ccc<listChannel.size(); ++ccc) {
for (size_t iii=0; iii<listFormat.size(); ++iii) {
TEST_INFO("freq=" << listFreq[fff] << " channel=" << listChannel[ccc] << " format=" << getFormatString(listFormat[iii]));
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, listFreq[fff], listChannel[ccc], listFormat[iii]);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
}
audio::river::unInit();
}
}
};

View File

@ -1,20 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#pragma once
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#include <test-debug/debug.hpp>
namespace river_test_muxer {
class TestClass {
@ -27,47 +18,47 @@ namespace river_test_muxer {
TestClass(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager),
m_phase(0) {
etk::Vector<audio::channel> channelMap;
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
std::vector<audio::channel> channelMap;
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
m_interfaceOut = m_manager->createOutput(48000,
channelMap,
audio::format_int16,
"speaker");
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceOut->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceOut->setOutputCallback(std::bind(&TestClass::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_interfaceOut->addVolumeGroup("FLOW");
//m_interfaceOut->setParameter("volume", "FLOW", "-6dB");
//Set stereo output:
m_interfaceIn = m_manager->createInput(48000,
etk::Vector<audio::channel>(),
std::vector<audio::channel>(),
audio::format_int16,
"microphone-muxed");
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interfaceIn->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interfaceIn->setInputCallback(std::bind(&TestClass::onDataReceived,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_manager->generateDotAll("activeProcess.dot");
}
@ -76,7 +67,7 @@ namespace river_test_muxer {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
int16_t* data = static_cast<int16_t*>(_data);
double baseCycle = 2.0*M_PI/(double)48000 * 440;
for (int32_t iii=0; iii<_nbChunk; iii++) {
@ -94,31 +85,31 @@ namespace river_test_muxer {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
//TEST_SAVE_FILE_MACRO(int16_t, "REC_MicrophoneMuxed.raw", _data, _nbChunk*_map.size());
TEST_SAVE_FILE_MACRO(int16_t, "REC_MicrophoneMuxed.raw", _data, _nbChunk*_map.size());
TEST_ERROR("Receive data ... " << _nbChunk << " map=" << _map);
}
void run() {
if(m_interfaceIn == null) {
TEST_ERROR("null interface");
if(m_interfaceIn == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
if(m_interfaceOut == null) {
TEST_ERROR("null interface");
if(m_interfaceOut == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interfaceOut->start();
m_interfaceIn->start();
ethread::sleepMilliSeconds(1000*(10));
std::this_thread::sleep_for(std::chrono::seconds(10));
m_interfaceIn->stop();
m_interfaceOut->stop();
}
};
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -177,7 +168,7 @@ namespace river_test_muxer {
ememory::SharedPtr<TestClass> process = ememory::makeShared<TestClass>(manager);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
};

View File

@ -1,21 +1,9 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#pragma once
namespace river_test_playback_callback {
@ -25,37 +13,37 @@ namespace river_test_playback_callback {
ememory::SharedPtr<audio::river::Interface> m_interface;
double m_phase;
public:
testOutCallback(ememory::SharedPtr<audio::river::Manager> _manager, const etk::String& _io="speaker") :
testOutCallback(ememory::SharedPtr<audio::river::Manager> _manager, const std::string& _io="speaker") :
m_manager(_manager),
m_phase(0) {
//Set stereo output:
etk::Vector<audio::channel> channelMap;
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
std::vector<audio::channel> channelMap;
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
m_interface = m_manager->createOutput(48000,
channelMap,
audio::format_int16,
_io);
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interface->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interface->setOutputCallback(std::bind(&testOutCallback::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
}
void onDataNeeded(void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
@ -72,18 +60,18 @@ namespace river_test_playback_callback {
}
}
void run() {
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->start();
// wait 2 second ...
ethread::sleepMilliSeconds(1000*(2));
std::this_thread::sleep_for(std::chrono::seconds(2));
m_interface->stop();
}
};
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -106,10 +94,10 @@ namespace river_test_playback_callback {
TEST_INFO("test output (callback mode)");
ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker");
ASSERT_NE(process, null);
ASSERT_NE(process, nullptr);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
@ -122,7 +110,7 @@ namespace river_test_playback_callback {
ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker-pulse");
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
@ -135,7 +123,7 @@ namespace river_test_playback_callback {
ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker-jack");
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
};

View File

@ -1,24 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#pragma once
namespace river_test_playback_write {
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -36,32 +24,32 @@ namespace river_test_playback_write {
class testOutWrite {
public:
etk::Vector<audio::channel> m_channelMap;
std::vector<audio::channel> m_channelMap;
ememory::SharedPtr<audio::river::Manager> m_manager;
ememory::SharedPtr<audio::river::Interface> m_interface;
public:
testOutWrite(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager) {
//Set stereo output:
m_channelMap.pushBack(audio::channel_frontLeft);
m_channelMap.pushBack(audio::channel_frontRight);
m_channelMap.push_back(audio::channel_frontLeft);
m_channelMap.push_back(audio::channel_frontRight);
m_interface = m_manager->createOutput(48000,
m_channelMap,
audio::format_int16,
"speaker");
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->setReadwrite();
}
void run() {
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
double phase=0;
etk::Vector<int16_t> data;
std::vector<int16_t> data;
data.resize(1024*m_channelMap.size());
double baseCycle = 2.0*M_PI/48000.0 * 440.0;
// start fill buffer
@ -90,7 +78,7 @@ namespace river_test_playback_write {
}
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 ...
ethread::sleepMilliSeconds((15));
std::this_thread::sleep_for(std::chrono::milliseconds(15));
}
m_interface->stop();
}
@ -105,7 +93,7 @@ namespace river_test_playback_write {
ememory::SharedPtr<testOutWrite> process = ememory::makeShared<testOutWrite>(manager);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}
@ -118,36 +106,36 @@ namespace river_test_playback_write {
testOutWriteCallback(ememory::SharedPtr<audio::river::Manager> _manager) :
m_manager(_manager),
m_phase(0) {
etk::Vector<audio::channel> channelMap;
std::vector<audio::channel> channelMap;
//Set stereo output:
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
m_interface = m_manager->createOutput(48000,
channelMap,
audio::format_int16,
"speaker");
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->setReadwrite();
m_interface->setWriteCallback([=](const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_time, _nbChunk, _format, _frequency, _map);
});
m_interface->setWriteCallback(std::bind(&testOutWriteCallback::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5));
}
void onDataNeeded(const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
etk::Vector<int16_t> data;
std::vector<int16_t> data;
data.resize(1024*_map.size());
double baseCycle = 2.0*M_PI/48000.0 * 440.0;
// start fill buffer
@ -163,12 +151,12 @@ namespace river_test_playback_write {
m_interface->write(&data[0], data.size()/_map.size());
}
void run() {
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->start();
ethread::sleepMilliSeconds(1000*(1));
std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->stop();
}
};
@ -182,7 +170,7 @@ namespace river_test_playback_write {
ememory::SharedPtr<testOutWriteCallback> process = ememory::makeShared<testOutWriteCallback>(manager);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}

View File

@ -1,23 +1,14 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#pragma once
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#include <test-debug/debug.hpp>
namespace river_test_record_callback {
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" microphone:{\n"
" io:'input',\n"
@ -37,54 +28,54 @@ namespace river_test_record_callback {
ememory::SharedPtr<audio::river::Manager> m_manager;
ememory::SharedPtr<audio::river::Interface> m_interface;
public:
testInCallback(ememory::SharedPtr<audio::river::Manager> _manager, const etk::String& _input="microphone") :
testInCallback(ememory::SharedPtr<audio::river::Manager> _manager, const std::string& _input="microphone") :
m_manager(_manager) {
//Set stereo output:
etk::Vector<audio::channel> channelMap;
std::vector<audio::channel> channelMap;
m_interface = m_manager->createInput(48000,
channelMap,
audio::format_int16,
_input);
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interface->setInputCallback([=](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interface->setInputCallback(std::bind(&testInCallback::onDataReceived,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
}
void onDataReceived(const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
if (_format != audio::format_int16) {
TEST_ERROR("call wrong type ... (need int16_t)");
}
//TEST_SAVE_FILE_MACRO(int16_t, "REC_INPUT.raw", _data, _nbChunk * _map.size());
TEST_SAVE_FILE_MACRO(int16_t, "REC_INPUT.raw", _data, _nbChunk * _map.size());
const int16_t* data = static_cast<const int16_t*>(_data);
int64_t value = 0;
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
value += etk::abs(data[iii]);
value += std::abs(data[iii]);
}
value /= (_nbChunk*_map.size());
TEST_INFO("Get data ... average=" << int32_t(value));
}
void run() {
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->start();
// wait 2 second ...
ethread::sleepMilliSeconds(1000*(20));
std::this_thread::sleep_for(std::chrono::seconds(20));
m_interface->stop();
}
};
@ -97,7 +88,7 @@ namespace river_test_record_callback {
ememory::SharedPtr<testInCallback> process = ememory::makeShared<testInCallback>(manager);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}

View File

@ -1,22 +0,0 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
namespace river_test_record_read {
};

11
test/testRecordRead.hpp Normal file
View File

@ -0,0 +1,11 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
namespace river_test_record_read {
};

View File

@ -1,24 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2015, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <test-debug/debug.hpp>
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <etest/etest.hpp>
#include <etk/etk.hpp>
extern "C" {
#include <math.h>
}
#include <ethread/Thread.hpp>
#include <ethread/tools.hpp>
#pragma once
namespace river_test_volume {
static const etk::String configurationRiver =
static const std::string configurationRiver =
"{\n"
" speaker:{\n"
" io:'output',\n"
@ -44,26 +32,26 @@ namespace river_test_volume {
m_manager(_manager),
m_phase(0) {
//Set stereo output:
etk::Vector<audio::channel> channelMap;
channelMap.pushBack(audio::channel_frontLeft);
channelMap.pushBack(audio::channel_frontRight);
std::vector<audio::channel> channelMap;
channelMap.push_back(audio::channel_frontLeft);
channelMap.push_back(audio::channel_frontRight);
m_interface = m_manager->createOutput(48000,
channelMap,
audio::format_int16,
"speaker");
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interface->setOutputCallback([=](void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataNeeded(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interface->setOutputCallback(std::bind(&testCallbackVolume::onDataNeeded,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
m_interface->addVolumeGroup("MEDIA");
m_interface->addVolumeGroup("FLOW");
}
@ -72,7 +60,7 @@ namespace river_test_volume {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
const std::vector<audio::channel>& _map) {
int16_t* data = static_cast<int16_t*>(_data);
double baseCycle = 2.0*M_PI/(double)48000 * (double)550;
for (int32_t iii=0; iii<_nbChunk; iii++) {
@ -86,45 +74,45 @@ namespace river_test_volume {
}
}
void run() {
if(m_interface == null) {
TEST_ERROR("null interface");
if(m_interface == nullptr) {
TEST_ERROR("nullptr interface");
return;
}
m_interface->start();
ethread::sleepMilliSeconds(1000*(1));
std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->setParameter("volume", "FLOW", "-3dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-6dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-9dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-12dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "-3dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "3dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "6dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "9dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_interface->setParameter("volume", "FLOW", "0dB");
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_manager->setVolume("MASTER", -3.0f);
TEST_INFO("get volume MASTER: " << m_manager->getVolume("MASTER") );
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
m_manager->setVolume("MEDIA", -3.0f);
TEST_INFO("get volume MEDIA: " << m_manager->getVolume("MEDIA") );
ethread::sleepMilliSeconds(1000*(1));
std::this_thread::sleep_for(std::chrono::seconds(1));
m_interface->stop();
}
};
@ -136,7 +124,7 @@ namespace river_test_volume {
ememory::SharedPtr<testCallbackVolume> process = ememory::makeShared<testCallbackVolume>(manager);
process->run();
process.reset();
ethread::sleepMilliSeconds((500));
std::this_thread::sleep_for(std::chrono::milliseconds(500));
audio::river::unInit();
}

View File

@ -1 +1 @@
1.0.0
0.4.0

View File

@ -1,13 +1,12 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/widget/debug.hpp>
#include <audio/river/widget/TemporalViewer.hpp>
#include <etk/tool.hpp>
#include <ewol/object/Manager.hpp>
static const int32_t nbSecond = 3;
@ -38,15 +37,15 @@ void audio::river::widget::TemporalViewer::onDataReceived(const void* _data,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
ethread::UniqueLock lock(m_mutex);
const std::vector<audio::channel>& _map) {
std::unique_lock<std::mutex> lock(m_mutex);
if (_format != audio::format_float) {
ARW_ERROR("call wrong type ... (need int16_t)");
std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl;
}
// get the curent power of the signal.
const float* data = static_cast<const float*>(_data);
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
m_data.pushBack(data[iii]);
m_data.push_back(data[iii]);
}
/*
if (m_data.size()>m_sampleRate*nbSecond*10) {
@ -57,35 +56,35 @@ void audio::river::widget::TemporalViewer::onDataReceived(const void* _data,
}
void audio::river::widget::TemporalViewer::recordToggle() {
ethread::UniqueLock lock(m_mutex);
if (m_interface == null) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_interface == nullptr) {
//Get the generic input:
etk::Vector<audio::channel> channel;
channel.pushBack(audio::channel_frontLeft);
std::vector<audio::channel> channel;
channel.push_back(audio::channel_frontLeft);
m_interface = m_manager->createInput(m_sampleRate,
channel,
audio::format_float,
"microphone");
if(m_interface == null) {
ARW_ERROR("null interface");
if(m_interface == nullptr) {
ARW_ERROR("nullptr interface");
return;
}
// set callback mode ...
m_interface->setInputCallback([&](const void* _data,
const audio::Time& _time,
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map) {
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map);
});
m_interface->setInputCallback(std::bind(&audio::river::widget::TemporalViewer::onDataReceived,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3,
std::placeholders::_4,
std::placeholders::_5,
std::placeholders::_6));
// start the stream
m_interface->start();
m_PCH = getObjectManager().periodicCall.connect(this, &audio::river::widget::TemporalViewer::periodicCall);
periodicCallEnable();
} else {
m_interface->stop();
m_interface.reset();
m_PCH.disconnect();
periodicCallDisable();
}
}
@ -105,14 +104,14 @@ void audio::river::widget::TemporalViewer::onRegenerateDisplay() {
m_draw.setColor(etk::color::black);
m_draw.setPos(vec2(0,0));
m_draw.rectangleWidth(m_size);
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
if (m_data.size() == 0) {
return;
}
// create n section for display:
int32_t nbSlot = m_size.x();
int32_t sizeSlot = m_size.x()/nbSlot;
etk::Vector<float> list;
std::vector<float> list;
//ARW_INFO("nbSlot : " << nbSlot << " sizeSlot=" << sizeSlot << " m_size=" << m_size);
list.resize(nbSlot,0.0f);
int32_t step = m_sampleRate*nbSecond/nbSlot;
@ -120,7 +119,7 @@ void audio::river::widget::TemporalViewer::onRegenerateDisplay() {
int32_t id = kkk/step;
if (id < list.size()) {
if (kkk < m_data.size()) {
list[id] = etk::max(list[id],m_data[kkk]);
list[id] = std::max(list[id],m_data[kkk]);
}
}
}
@ -144,7 +143,7 @@ void audio::river::widget::TemporalViewer::onRegenerateDisplay() {
void audio::river::widget::TemporalViewer::periodicCall(const ewol::event::Time& _event) {
ethread::UniqueLock lock(m_mutex);
std::unique_lock<std::mutex> lock(m_mutex);
int32_t nbSampleDelta = _event.getDeltaCall() * float(m_sampleRate);
if (m_data.size()>m_sampleRate*nbSecond) {
if (nbSampleDelta < m_data.size()) {

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once
@ -10,14 +10,14 @@
#include <audio/river/river.hpp>
#include <audio/river/Manager.hpp>
#include <audio/river/Interface.hpp>
#include <ethread/Mutex.hpp>
#include <mutex>
namespace audio {
namespace river {
namespace widget {
class TemporalViewer : public ewol::Widget {
private:
mutable ethread::Mutex m_mutex;
mutable std::mutex m_mutex;
private:
ewol::compositing::Drawing m_draw; //!< drawing instance
protected:
@ -34,19 +34,13 @@ namespace audio {
// ...
}
private:
etk::Vector<float> m_data;
std::vector<float> m_data;
private:
float m_minVal; //!< display minimum value
float m_maxVal; //!< display maximum value
public: // herited function
virtual void onDraw();
virtual void onRegenerateDisplay();
protected:
esignal::Connection m_PCH; //!< Periodic Call Handle to remove it when needed
/**
* @brief Periodic call to update grapgic display
* @param[in] _event Time generic event
*/
virtual void periodicCall(const ewol::event::Time& _event);
private:
ememory::SharedPtr<audio::river::Manager> m_manager;
@ -56,7 +50,7 @@ namespace audio {
size_t _nbChunk,
enum audio::format _format,
uint32_t _frequency,
const etk::Vector<audio::channel>& _map);
const std::vector<audio::channel>& _map);
int32_t m_sampleRate;
};
}

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#include <audio/river/widget/debug.hpp>

View File

@ -1,7 +1,7 @@
/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
* @license APACHE v2.0 (see license file)
*/
#pragma once

View File

@ -1,5 +1,5 @@
#!/usr/bin/python
import realog.debug as debug
import lutin.debug as debug
import lutin.tools as tools
import os
@ -11,7 +11,7 @@ def get_desc():
return "audio specific widget"
def get_licence():
return "MPL-2"
return "APACHE-2"
def get_compagny_type():
return "com"