Compare commits
17 Commits
b114de5f1d
...
6dfa58dedd
Author | SHA1 | Date | |
---|---|---|---|
6dfa58dedd | |||
121602813e | |||
b53e67044f | |||
715598a0ae | |||
1773297dab | |||
965df2ee2f | |||
9a21d57c1f | |||
be4f6217d0 | |||
38c9a69e1e | |||
0c57614b64 | |||
c3d78cf387 | |||
2ee24d5baa | |||
0e175ad23c | |||
c3b5ba2bdd | |||
ddc9150179 | |||
5fe729f4dc | |||
8fef74e061 |
373
LICENSE
Normal file
373
LICENSE
Normal file
@ -0,0 +1,373 @@
|
||||
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.
|
@ -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 (APACHE v2.0)
|
||||
License (MPL v2.0)
|
||||
=====================
|
||||
Copyright audio-river Edouard DUPIN
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
Licensed under the Mozilla Public License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
https://www.mozilla.org/MPL/2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -1,37 +1,35 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "Interface.hpp"
|
||||
#include "io/Node.hpp"
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/river/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) :
|
||||
m_node(),
|
||||
m_name("") {
|
||||
audio::river::Interface::Interface(void) {
|
||||
static uint32_t uid = 0;
|
||||
m_uid = uid++;
|
||||
|
||||
}
|
||||
|
||||
bool audio::river::Interface::init(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
ememory::SharedPtr<audio::river::io::Node> _node,
|
||||
const ejson::Object& _config) {
|
||||
std::vector<audio::channel> map(_map);
|
||||
etk::Vector<audio::channel> map(_map);
|
||||
m_node = _node;
|
||||
m_config = _config;
|
||||
m_mode = audio::river::modeInterface_unknow;
|
||||
std::string type = m_config["io"].toString().get("error");
|
||||
etk::String type = m_config["io"].toString().get("error");
|
||||
static int32_t uid=0;
|
||||
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::to_string(uid++);
|
||||
m_name = _node->getName() + "__" + (_node->isInput()==true?"input":"output") + "__" + type + "__" + etk::toString(uid++);
|
||||
if (type == "output") {
|
||||
m_mode = audio::river::modeInterface_output;
|
||||
} else if (type == "input") {
|
||||
@ -54,7 +52,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 != nullptr) {
|
||||
if (tmpVolume != null) {
|
||||
// add all time the volume stage :
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
|
||||
//algo->setInputFormat(m_node->getInterfaceFormat());
|
||||
@ -69,7 +67,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 != nullptr) {
|
||||
if (tmpVolume != null) {
|
||||
// add all time the volume stage :
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
|
||||
//algo->setOutputFormat(m_node->getInterfaceFormat());
|
||||
@ -92,18 +90,18 @@ bool audio::river::Interface::init(float _freq,
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Interface::create(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
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>(new audio::river::Interface());
|
||||
ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(ETK_NEW(audio::river::Interface));
|
||||
out->init(_freq, _map, _format, _node, _config);
|
||||
return out;
|
||||
}
|
||||
|
||||
audio::river::Interface::~Interface() {
|
||||
//stop(true, true);
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
//m_node->interfaceRemove(sharedFromThis());
|
||||
}
|
||||
/*
|
||||
@ -112,12 +110,13 @@ bool audio::river::Interface::hasEndPoint() {
|
||||
}
|
||||
*/
|
||||
void audio::river::Interface::setReadwrite() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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();
|
||||
@ -130,11 +129,12 @@ void audio::river::Interface::setReadwrite() {
|
||||
}
|
||||
|
||||
void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _function) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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,11 +142,12 @@ void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _
|
||||
}
|
||||
|
||||
void audio::river::Interface::setInputCallback(audio::drain::recordFunction _function) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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);
|
||||
@ -154,21 +155,22 @@ void audio::river::Interface::setInputCallback(audio::drain::recordFunction _fun
|
||||
}
|
||||
|
||||
void audio::river::Interface::setWriteCallback(audio::drain::playbackFunctionWrite _function) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
return;
|
||||
}
|
||||
algo->setCallback(_function);
|
||||
}
|
||||
|
||||
void audio::river::Interface::start(const audio::Time& _time) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("start [BEGIN]");
|
||||
m_process.updateInterAlgo();
|
||||
m_node->interfaceAdd(sharedFromThis());
|
||||
@ -176,20 +178,20 @@ void audio::river::Interface::start(const audio::Time& _time) {
|
||||
}
|
||||
|
||||
void audio::river::Interface::stop(bool _fast, bool _abort) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("stop [BEGIN]");
|
||||
m_node->interfaceRemove(sharedFromThis());
|
||||
RIVER_DEBUG("stop [ END]");
|
||||
}
|
||||
|
||||
void audio::river::Interface::abort() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("abort [BEGIN]");
|
||||
// TODO :...
|
||||
RIVER_DEBUG("abort [ END ]");
|
||||
}
|
||||
|
||||
bool audio::river::Interface::setParameter(const std::string& _filter, const std::string& _parameter, const std::string& _value) {
|
||||
bool audio::river::Interface::setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value) {
|
||||
RIVER_DEBUG("setParameter [BEGIN] : '" << _filter << "':'" << _parameter << "':'" << _value << "'");
|
||||
bool out = false;
|
||||
if ( _filter == "volume"
|
||||
@ -198,7 +200,7 @@ bool audio::river::Interface::setParameter(const std::string& _filter, const std
|
||||
return false;
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::Algo> algo = m_process.get<audio::drain::Algo>(_filter);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
|
||||
return false;
|
||||
}
|
||||
@ -206,11 +208,11 @@ bool audio::river::Interface::setParameter(const std::string& _filter, const std
|
||||
RIVER_DEBUG("setParameter [ END ] : '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
std::string audio::river::Interface::getParameter(const std::string& _filter, const std::string& _parameter) const {
|
||||
etk::String audio::river::Interface::getParameter(const etk::String& _filter, const etk::String& _parameter) const {
|
||||
RIVER_DEBUG("getParameter [BEGIN] : '" << _filter << "':'" << _parameter << "'");
|
||||
std::string out;
|
||||
etk::String out;
|
||||
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
|
||||
return "[ERROR]";
|
||||
}
|
||||
@ -218,11 +220,11 @@ std::string audio::river::Interface::getParameter(const std::string& _filter, co
|
||||
RIVER_DEBUG("getParameter [ END ] : '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
std::string audio::river::Interface::getParameterProperty(const std::string& _filter, const std::string& _parameter) const {
|
||||
etk::String audio::river::Interface::getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const {
|
||||
RIVER_DEBUG("getParameterProperty [BEGIN] : '" << _filter << "':'" << _parameter << "'");
|
||||
std::string out;
|
||||
etk::String out;
|
||||
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
|
||||
return "[ERROR]";
|
||||
}
|
||||
@ -232,10 +234,10 @@ std::string audio::river::Interface::getParameterProperty(const std::string& _fi
|
||||
}
|
||||
|
||||
void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_process.updateInterAlgo();
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
return;
|
||||
}
|
||||
algo->write(_value, _nbChunk);
|
||||
@ -243,16 +245,16 @@ void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
|
||||
|
||||
#if 0
|
||||
// TODO : add API aCCess mutex for Read and write...
|
||||
std::vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
|
||||
etk::Vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
|
||||
// TODO :...
|
||||
std::vector<int16_t> data;
|
||||
etk::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) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
ethread::sleepMilliSeconds((1));
|
||||
nbChunkBuffer = m_circularBuffer.size() / m_map.size();
|
||||
}
|
||||
m_mutex.lock();
|
||||
@ -267,14 +269,14 @@ std::vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
|
||||
#endif
|
||||
|
||||
void audio::river::Interface::read(void* _value, size_t _nbChunk) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_process.updateInterAlgo();
|
||||
// TODO :...
|
||||
|
||||
}
|
||||
|
||||
size_t audio::river::Interface::size() const {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
// TODO :...
|
||||
return 0;
|
||||
}
|
||||
@ -284,10 +286,10 @@ size_t audio::river::Interface::size() const {
|
||||
|
||||
|
||||
void audio::river::Interface::setBufferSize(size_t _nbChunk) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return;
|
||||
}
|
||||
@ -295,18 +297,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 == nullptr) {
|
||||
if (algo == null) {
|
||||
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 std::chrono::microseconds& _time) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
void audio::river::Interface::setBufferSize(const echrono::microseconds& _time) {
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return;
|
||||
}
|
||||
@ -314,7 +316,7 @@ void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _ti
|
||||
return;
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return;
|
||||
}
|
||||
@ -322,53 +324,53 @@ void audio::river::Interface::setBufferSize(const std::chrono::microseconds& _ti
|
||||
}
|
||||
|
||||
size_t audio::river::Interface::getBufferSize() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
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 == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return 0;
|
||||
}
|
||||
return algo->getBufferSize();
|
||||
}
|
||||
|
||||
std::chrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
echrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return std::chrono::microseconds(0);
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferSizeMicrosecond();
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return std::chrono::microseconds(0);
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferSizeMicrosecond();
|
||||
}
|
||||
|
||||
size_t audio::river::Interface::getBufferFillSize() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
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 == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return 0;
|
||||
}
|
||||
@ -376,20 +378,20 @@ size_t audio::river::Interface::getBufferFillSize() {
|
||||
|
||||
}
|
||||
|
||||
std::chrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
echrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond() {
|
||||
ethread::RecursiveLock 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 == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return std::chrono::microseconds(0);
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferFillSizeMicrosecond();
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return std::chrono::microseconds(0);
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferFillSizeMicrosecond();
|
||||
}
|
||||
@ -397,24 +399,24 @@ std::chrono::microseconds audio::river::Interface::getBufferFillSizeMicrosecond(
|
||||
|
||||
|
||||
void audio::river::Interface::clearInternalBuffer() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_process.updateInterAlgo();
|
||||
// TODO :...
|
||||
|
||||
}
|
||||
|
||||
audio::Time audio::river::Interface::getCurrentTime() const {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
// TODO :...
|
||||
return audio::Time();
|
||||
return audio::Time::now();
|
||||
}
|
||||
|
||||
void audio::river::Interface::addVolumeGroup(const std::string& _name) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
void audio::river::Interface::addVolumeGroup(const etk::String& _name) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("addVolumeGroup(" << _name << ")");
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
m_process.removeAlgoDynamic();
|
||||
// add all time the volume stage :
|
||||
algo = audio::drain::Volume::create();
|
||||
@ -436,85 +438,85 @@ void audio::river::Interface::addVolumeGroup(const std::string& _name) {
|
||||
}
|
||||
|
||||
void audio::river::Interface::systemNewInputData(audio::Time _time, const void* _data, size_t _nbChunk) {
|
||||
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
|
||||
ethread::RecursiveLock 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) {
|
||||
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
|
||||
ethread::RecursiveLock lockProcess(m_mutex);
|
||||
//RIVER_INFO("time : " << _time);
|
||||
m_process.pull(_time, _data, _nbChunk, _chunkSize);
|
||||
}
|
||||
|
||||
void audio::river::Interface::systemVolumeChange() {
|
||||
std::unique_lock<std::recursive_mutex> lockProcess(m_mutex);
|
||||
ethread::RecursiveLock lockProcess(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
|
||||
if (algo == nullptr) {
|
||||
if (algo == null) {
|
||||
return;
|
||||
}
|
||||
algo->volumeChange();
|
||||
}
|
||||
|
||||
static void link(etk::FSNode& _node, const std::string& _first, const std::string& _op, const std::string& _second, bool _isLink=true) {
|
||||
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second, bool _isLink=true) {
|
||||
if (_op == "->") {
|
||||
if (_isLink) {
|
||||
_node << " " << _first << " -> " << _second << ";\n";
|
||||
*_io << " " << _first << " -> " << _second << ";\n";
|
||||
} else {
|
||||
_node << " " << _first << " -> " << _second << " [style=dashed];\n";
|
||||
*_io << " " << _first << " -> " << _second << " [style=dashed];\n";
|
||||
}
|
||||
} else if (_op == "<-") {
|
||||
_node << " " << _first << " -> " <<_second<< " [color=transparent];\n";
|
||||
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
|
||||
if (_isLink) {
|
||||
_node << " " << _second << " -> " << _first << " [constraint=false];\n";
|
||||
*_io << " " << _second << " -> " << _first << " [constraint=false];\n";
|
||||
} else {
|
||||
_node << " " << _second << " -> " << _first << " [constraint=false, style=dashed];\n";
|
||||
*_io << " " << _second << " -> " << _first << " [constraint=false, style=dashed];\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string audio::river::Interface::getDotNodeName() const {
|
||||
etk::String audio::river::Interface::getDotNodeName() const {
|
||||
if (m_mode == audio::river::modeInterface_input) {
|
||||
return "API_" + etk::to_string(m_uid) + "_input";
|
||||
return "API_" + etk::toString(m_uid) + "_input";
|
||||
} else if (m_mode == audio::river::modeInterface_feedback) {
|
||||
return "API_" + etk::to_string(m_uid) + "_feedback";
|
||||
return "API_" + etk::toString(m_uid) + "_feedback";
|
||||
} else if (m_mode == audio::river::modeInterface_output) {
|
||||
return "API_" + etk::to_string(m_uid) + "_output";
|
||||
return "API_" + etk::toString(m_uid) + "_output";
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
if ( m_mode == audio::river::modeInterface_input
|
||||
|| m_mode == audio::river::modeInterface_feedback) {
|
||||
m_process.generateDot(_node, 3, 10000+m_uid, nameIn, nameOut, false);
|
||||
m_process.generateDot(_io, 3, 10000+m_uid, nameIn, nameOut, false);
|
||||
} else {
|
||||
m_process.generateDot(_node, 3, 10000+m_uid, nameIn, nameOut, true);
|
||||
m_process.generateDot(_io, 3, 10000+m_uid, nameOut, nameIn, true);
|
||||
}
|
||||
|
||||
|
||||
if ( m_mode == audio::river::modeInterface_input
|
||||
|| m_mode == audio::river::modeInterface_feedback) {
|
||||
link(_node, _nameIO, "->", nameIn, _isLink);
|
||||
link(_io, _nameIO, "->", nameIn, _isLink);
|
||||
} else {
|
||||
link(_node, _nameIO, "<-", nameOut, _isLink);
|
||||
link(_io, _nameIO, "<-", nameOut, _isLink);
|
||||
}
|
||||
_node << " node [shape=Mdiamond];\n";
|
||||
*_io << " node [shape=Mdiamond];\n";
|
||||
if (m_mode == audio::river::modeInterface_input) {
|
||||
_node << " " << getDotNodeName() << " [ label=\"API\\nINPUT\" ];\n";
|
||||
link(_node, nameOut, "->", getDotNodeName());
|
||||
*_io << " " << getDotNodeName() << " [ label=\"API\\nINPUT\" ];\n";
|
||||
link(_io, nameOut, "->", getDotNodeName());
|
||||
} else if (m_mode == audio::river::modeInterface_feedback) {
|
||||
_node << " " << getDotNodeName() << " [ label=\"API\\nFEEDBACK\" ];\n";
|
||||
link(_node, nameOut, "->", getDotNodeName());
|
||||
*_io << " " << getDotNodeName() << " [ label=\"API\\nFEEDBACK\" ];\n";
|
||||
link(_io, nameOut, "->", getDotNodeName());
|
||||
} else if (m_mode == audio::river::modeInterface_output) {
|
||||
_node << " " << getDotNodeName() << " [ label=\"API\\nOUTPUT\" ];\n";
|
||||
link(_node, nameIn, "<-", getDotNodeName());
|
||||
*_io << " " << getDotNodeName() << " [ label=\"API\\nOUTPUT\" ];\n";
|
||||
link(_io, nameIn, "<-", getDotNodeName());
|
||||
}
|
||||
_node << " }\n \n";
|
||||
*_io << " }\n \n";
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#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 <ememory/memory.hpp>
|
||||
#include <audio/format.hpp>
|
||||
#include <audio/channel.hpp>
|
||||
@ -18,7 +18,6 @@
|
||||
#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 {
|
||||
@ -63,7 +62,7 @@ namespace audio {
|
||||
* @return false the configuration has an error.
|
||||
*/
|
||||
bool init(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
ememory::SharedPtr<audio::river::io::Node> _node,
|
||||
const ejson::Object& _config);
|
||||
@ -74,11 +73,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 nullptr The configuration does not work.
|
||||
* @return null The configuration does not work.
|
||||
* @return pointer The interface has been corectly created.
|
||||
*/
|
||||
static ememory::SharedPtr<Interface> create(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const ememory::SharedPtr<audio::river::io::Node>& _node,
|
||||
const ejson::Object& _config);
|
||||
@ -88,7 +87,7 @@ namespace audio {
|
||||
*/
|
||||
virtual ~Interface();
|
||||
protected:
|
||||
mutable std::recursive_mutex m_mutex; //!< Local mutex to protect data
|
||||
mutable ethread::MutexRecursive 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)
|
||||
@ -118,20 +117,20 @@ namespace audio {
|
||||
protected:
|
||||
ememory::SharedPtr<audio::river::io::Node> m_node; //!< Hardware interface to/from stream audio flow.
|
||||
protected:
|
||||
std::string m_name; //!< Name of the interface.
|
||||
etk::String m_name; //!< Name of the interface.
|
||||
public:
|
||||
/**
|
||||
* @brief Get interface name.
|
||||
* @return The current name.
|
||||
*/
|
||||
virtual std::string getName() {
|
||||
virtual etk::String getName() {
|
||||
return m_name;
|
||||
};
|
||||
/**
|
||||
* @brief Set the interface name
|
||||
* @param[in] _name new name of the interface
|
||||
*/
|
||||
virtual void setName(const std::string& _name) {
|
||||
virtual void setName(const etk::String& _name) {
|
||||
m_name = _name;
|
||||
};
|
||||
/**
|
||||
@ -169,7 +168,7 @@ namespace audio {
|
||||
* - NOTIFICATION for urgent notification volume control.
|
||||
* - NOISE for small noise volume control.
|
||||
*/
|
||||
virtual void addVolumeGroup(const std::string& _name);
|
||||
virtual void addVolumeGroup(const etk::String& _name);
|
||||
public:
|
||||
/**
|
||||
* @brief Start the Audio interface flow.
|
||||
@ -198,7 +197,7 @@ namespace audio {
|
||||
* @example : setParameter("volume", "FLOW", "-3dB");
|
||||
* @example : setParameter("LowPassFilter", "cutFrequency", "1000Hz");
|
||||
*/
|
||||
virtual bool setParameter(const std::string& _filter, const std::string& _parameter, const std::string& _value);
|
||||
virtual bool setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value);
|
||||
/**
|
||||
* @brief Get a parameter value
|
||||
* @param[in] _filter name of the filter (if you added some personels)
|
||||
@ -207,7 +206,7 @@ namespace audio {
|
||||
* @example : getParameter("volume", "FLOW"); can return something like "-3dB"
|
||||
* @example : getParameter("LowPassFilter", "cutFrequency"); can return something like "[-120..0]dB"
|
||||
*/
|
||||
virtual std::string getParameter(const std::string& _filter, const std::string& _parameter) const;
|
||||
virtual etk::String getParameter(const etk::String& _filter, const etk::String& _parameter) const;
|
||||
/**
|
||||
* @brief Get a parameter value
|
||||
* @param[in] _filter name of the filter (if you added some personels)
|
||||
@ -216,7 +215,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 std::string getParameterProperty(const std::string& _filter, const std::string& _parameter) const;
|
||||
virtual etk::String getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const;
|
||||
/**
|
||||
* @brief write some audio sample in the speakers
|
||||
* @param[in] _value Data To write on output
|
||||
@ -245,7 +244,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 std::chrono::microseconds& _time);
|
||||
virtual void setBufferSize(const echrono::microseconds& _time);
|
||||
/**
|
||||
* @brief get buffer size in chunk number
|
||||
* @return Number of chunk that can be written in the buffer
|
||||
@ -255,7 +254,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 std::chrono::microseconds getBufferSizeMicrosecond();
|
||||
virtual echrono::microseconds getBufferSizeMicrosecond();
|
||||
/**
|
||||
* @brief Get buffer size filled in chunk number
|
||||
* @return Number of chunk in the buffer (that might be read/write)
|
||||
@ -265,7 +264,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 std::chrono::microseconds getBufferFillSizeMicrosecond();
|
||||
virtual echrono::microseconds getBufferFillSizeMicrosecond();
|
||||
/**
|
||||
* @brief Remove internal Buffer
|
||||
*/
|
||||
@ -298,23 +297,23 @@ namespace audio {
|
||||
public:
|
||||
/**
|
||||
* @brief Create the dot in the FileNode stream.
|
||||
* @param[in,out] _node File node to write data.
|
||||
* @param[in,out] _io File interafce to write data.
|
||||
* @param[in] _nameIO Name to link the interface node
|
||||
* @param[in] _isLink True if the node is connected on the current interface.
|
||||
*/
|
||||
virtual void generateDot(etk::FSNode& _node, const std::string& _nameIO, bool _isLink=true);
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _nameIO, bool _isLink=true);
|
||||
/**
|
||||
* @brief Get the current 'dot' name of the interface
|
||||
* @return The anme requested.
|
||||
*/
|
||||
virtual std::string getDotNodeName() const;
|
||||
virtual etk::String getDotNodeName() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief Interfanel generate of status
|
||||
* @param[in] _origin status source
|
||||
* @param[in] _status Event status
|
||||
*/
|
||||
void generateStatus(const std::string& _origin, const std::string& _status) {
|
||||
void generateStatus(const etk::String& _origin, const etk::String& _status) {
|
||||
m_process.generateStatus(_origin, _status);
|
||||
}
|
||||
public:
|
||||
|
@ -1,26 +1,24 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 std::mutex g_mutex;
|
||||
static std::vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
|
||||
static ethread::Mutex g_mutex;
|
||||
static etk::Vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
|
||||
|
||||
ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const std::string& _applicationUniqueId) {
|
||||
std::unique_lock<std::mutex> lock(g_mutex);
|
||||
ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const etk::String& _applicationUniqueId) {
|
||||
ethread::UniqueLock 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 == nullptr) {
|
||||
if (tmp == null) {
|
||||
continue;
|
||||
}
|
||||
if (tmp->m_applicationUniqueId == _applicationUniqueId) {
|
||||
@ -28,7 +26,7 @@ ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const st
|
||||
}
|
||||
}
|
||||
// create a new one:
|
||||
ememory::SharedPtr<audio::river::Manager> out = ememory::SharedPtr<audio::river::Manager>(new audio::river::Manager(_applicationUniqueId));
|
||||
ememory::SharedPtr<audio::river::Manager> out = ememory::SharedPtr<audio::river::Manager>(ETK_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) {
|
||||
@ -36,11 +34,11 @@ ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const st
|
||||
return out;
|
||||
}
|
||||
}
|
||||
g_listOfAllManager.push_back(out);
|
||||
g_listOfAllManager.pushBack(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
audio::river::Manager::Manager(const std::string& _applicationUniqueId) :
|
||||
audio::river::Manager::Manager(const etk::String& _applicationUniqueId) :
|
||||
m_applicationUniqueId(_applicationUniqueId),
|
||||
m_listOpenInterface() {
|
||||
|
||||
@ -51,10 +49,10 @@ audio::river::Manager::~Manager() {
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::string> audio::river::Manager::getListStreamInput() {
|
||||
std::vector<std::string> output;
|
||||
etk::Vector<etk::String> audio::river::Manager::getListStreamInput() {
|
||||
etk::Vector<etk::String> output;
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStreamInput();
|
||||
@ -62,10 +60,10 @@ std::vector<std::string> audio::river::Manager::getListStreamInput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<std::string> audio::river::Manager::getListStreamOutput() {
|
||||
std::vector<std::string> output;
|
||||
etk::Vector<etk::String> audio::river::Manager::getListStreamOutput() {
|
||||
etk::Vector<etk::String> output;
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStreamOutput();
|
||||
@ -73,10 +71,10 @@ std::vector<std::string> audio::river::Manager::getListStreamOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<std::string> audio::river::Manager::getListStreamVirtual() {
|
||||
std::vector<std::string> output;
|
||||
etk::Vector<etk::String> audio::river::Manager::getListStreamVirtual() {
|
||||
etk::Vector<etk::String> output;
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStreamVirtual();
|
||||
@ -84,10 +82,10 @@ std::vector<std::string> audio::river::Manager::getListStreamVirtual() {
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<std::string> audio::river::Manager::getListStream() {
|
||||
std::vector<std::string> output;
|
||||
etk::Vector<etk::String> audio::river::Manager::getListStream() {
|
||||
etk::Vector<etk::String> output;
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStream();
|
||||
@ -95,45 +93,45 @@ std::vector<std::string> audio::river::Manager::getListStream() {
|
||||
return output;
|
||||
}
|
||||
|
||||
bool audio::river::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
|
||||
bool audio::river::Manager::setVolume(const etk::String& _volumeName, float _valuedB) {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return false;
|
||||
}
|
||||
return manager->setVolume(_volumeName, _valuedB);
|
||||
}
|
||||
|
||||
float audio::river::Manager::getVolume(const std::string& _volumeName) const {
|
||||
float audio::river::Manager::getVolume(const etk::String& _volumeName) const {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return false;
|
||||
}
|
||||
return manager->getVolume(_volumeName);
|
||||
}
|
||||
|
||||
std::pair<float,float> audio::river::Manager::getVolumeRange(const std::string& _volumeName) const {
|
||||
etk::Pair<float,float> audio::river::Manager::getVolumeRange(const etk::String& _volumeName) const {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return std::make_pair<float,float>(0.0f,0.0f);
|
||||
return etk::makePair<float,float>(0.0f,0.0f);
|
||||
}
|
||||
return manager->getVolumeRange(_volumeName);
|
||||
}
|
||||
|
||||
void audio::river::Manager::setMute(const std::string& _volumeName, bool _mute) {
|
||||
void audio::river::Manager::setMute(const etk::String& _volumeName, bool _mute) {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return;
|
||||
}
|
||||
manager->setMute(_volumeName, _mute);
|
||||
}
|
||||
|
||||
bool audio::river::Manager::getMute(const std::string& _volumeName) const {
|
||||
bool audio::river::Manager::getMute(const etk::String& _volumeName) const {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return false;
|
||||
}
|
||||
@ -141,19 +139,19 @@ bool audio::river::Manager::getMute(const std::string& _volumeName) const {
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createOutput(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _options) {
|
||||
const etk::String& _streamName,
|
||||
const etk::String& _options) {
|
||||
// get global hardware interface:
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
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 == nullptr) {
|
||||
if (node == null) {
|
||||
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
@ -167,24 +165,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.push_back(interface);
|
||||
m_listOpenInterface.pushBack(interface);
|
||||
return interface;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createInput(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _options) {
|
||||
const etk::String& _streamName,
|
||||
const etk::String& _options) {
|
||||
// get global hardware interface:
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
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 == nullptr) {
|
||||
if (node == null) {
|
||||
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
@ -198,25 +196,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.push_back(interface);
|
||||
m_listOpenInterface.pushBack(interface);
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createFeedback(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _options) {
|
||||
const etk::String& _streamName,
|
||||
const etk::String& _options) {
|
||||
// get global hardware interface:
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
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 == nullptr) {
|
||||
if (node == null) {
|
||||
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
@ -230,14 +228,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.push_back(interface);
|
||||
m_listOpenInterface.pushBack(interface);
|
||||
return interface;
|
||||
}
|
||||
|
||||
void audio::river::Manager::generateDotAll(const std::string& _filename) {
|
||||
void audio::river::Manager::generateDotAll(const etk::String& _filename) {
|
||||
// get global hardware interface:
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == nullptr) {
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Can not get the harware manager");
|
||||
return;
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <etk/String.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/format.hpp>
|
||||
@ -20,20 +19,20 @@ namespace audio {
|
||||
*/
|
||||
class Manager : public ememory::EnableSharedFromThis<Manager> {
|
||||
private:
|
||||
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.
|
||||
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.
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Manager(const std::string& _applicationUniqueId);
|
||||
Manager(const etk::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 nullptr if an error occured
|
||||
* @return Pointer on the manager or null if an error occured
|
||||
*/
|
||||
static ememory::SharedPtr<audio::river::Manager> create(const std::string& _applicationUniqueId);
|
||||
static ememory::SharedPtr<audio::river::Manager> create(const etk::String& _applicationUniqueId);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
@ -43,22 +42,22 @@ namespace audio {
|
||||
* @brief Get all input audio stream.
|
||||
* @return a list of all availlables input stream name
|
||||
*/
|
||||
std::vector<std::string> getListStreamInput();
|
||||
etk::Vector<etk::String> getListStreamInput();
|
||||
/**
|
||||
* @brief Get all output audio stream.
|
||||
* @return a list of all availlables output stream name
|
||||
*/
|
||||
std::vector<std::string> getListStreamOutput();
|
||||
etk::Vector<etk::String> getListStreamOutput();
|
||||
/**
|
||||
* @brief Get all audio virtual stream.
|
||||
* @return a list of all availlables virtual stream name
|
||||
*/
|
||||
std::vector<std::string> getListStreamVirtual();
|
||||
etk::Vector<etk::String> getListStreamVirtual();
|
||||
/**
|
||||
* @brief Get all audio stream.
|
||||
* @return a list of all availlables stream name
|
||||
*/
|
||||
std::vector<std::string> getListStream();
|
||||
etk::Vector<etk::String> getListStream();
|
||||
|
||||
/**
|
||||
* @brief Set a volume for a specific group
|
||||
@ -68,14 +67,14 @@ namespace audio {
|
||||
* @return false An error occured
|
||||
* @example : setVolume("MASTER", -3.0f);
|
||||
*/
|
||||
virtual bool setVolume(const std::string& _volumeName, float _valuedB);
|
||||
virtual bool setVolume(const etk::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 std::string& _volumeName) const;
|
||||
virtual float getVolume(const etk::String& _volumeName) const;
|
||||
|
||||
/**
|
||||
* @brief Get a parameter value
|
||||
@ -83,19 +82,19 @@ namespace audio {
|
||||
* @return The requested value Range.
|
||||
* @example ret = getVolumeRange("MASTER"); can return something like ret=(-120.0f,0.0f)
|
||||
*/
|
||||
virtual std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
|
||||
virtual etk::Pair<float,float> getVolumeRange(const etk::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 std::string& _volumeName, bool _mute);
|
||||
virtual void setMute(const etk::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 std::string& _volumeName) const;
|
||||
virtual bool getMute(const etk::String& _volumeName) const;
|
||||
|
||||
/**
|
||||
* @brief Create output Interface
|
||||
@ -107,10 +106,10 @@ namespace audio {
|
||||
* @return a pointer on the interface
|
||||
*/
|
||||
virtual ememory::SharedPtr<Interface> createOutput(float _freq = 48000,
|
||||
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
|
||||
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
|
||||
audio::format _format = audio::format_int16,
|
||||
const std::string& _streamName = "",
|
||||
const std::string& _options = "");
|
||||
const etk::String& _streamName = "",
|
||||
const etk::String& _options = "");
|
||||
/**
|
||||
* @brief Create input Interface
|
||||
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
|
||||
@ -121,10 +120,10 @@ namespace audio {
|
||||
* @return a pointer on the interface
|
||||
*/
|
||||
virtual ememory::SharedPtr<Interface> createInput(float _freq = 48000,
|
||||
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
|
||||
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
|
||||
audio::format _format = audio::format_int16,
|
||||
const std::string& _streamName = "",
|
||||
const std::string& _options = "");
|
||||
const etk::String& _streamName = "",
|
||||
const etk::String& _options = "");
|
||||
/**
|
||||
* @brief Create input Feedback Interface
|
||||
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
|
||||
@ -135,15 +134,15 @@ namespace audio {
|
||||
* @return a pointer on the interface
|
||||
*/
|
||||
virtual ememory::SharedPtr<Interface> createFeedback(float _freq = 48000,
|
||||
const std::vector<audio::channel>& _map = std::vector<audio::channel>(),
|
||||
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
|
||||
audio::format _format = audio::format_int16,
|
||||
const std::string& _streamName = "",
|
||||
const std::string& _options = "");
|
||||
const etk::String& _streamName = "",
|
||||
const etk::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 std::string& _filename);
|
||||
virtual void generateDotAll(const etk::String& _filename);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/debug.hpp>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 = nullptr; \
|
||||
static FILE *pointerOnFile = null; \
|
||||
static bool errorOpen = false; \
|
||||
if (pointerOnFile == nullptr) { \
|
||||
if (pointerOnFile == null) { \
|
||||
RIVER_WARNING("open file '" << fileName << "' type=" << #type); \
|
||||
pointerOnFile = fopen(fileName,"w"); \
|
||||
if ( errorOpen == false \
|
||||
&& pointerOnFile == nullptr) { \
|
||||
&& pointerOnFile == null) { \
|
||||
RIVER_ERROR("ERROR OPEN file ... '" << fileName << "' type=" << #type); \
|
||||
errorOpen=true; \
|
||||
} \
|
||||
} \
|
||||
if (pointerOnFile != nullptr) { \
|
||||
if (pointerOnFile != null) { \
|
||||
fwrite((dataPointer), sizeof(type), (nbElement), pointerOnFile); \
|
||||
/* fflush(pointerOnFile);*/ \
|
||||
} \
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -1,35 +1,35 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/io/Group.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include "Node.hpp"
|
||||
#include "NodeAEC.hpp"
|
||||
#include "NodeOrchestra.hpp"
|
||||
#include "NodePortAudio.hpp"
|
||||
#include "Node.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>
|
||||
|
||||
void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std::string& _name) {
|
||||
void audio::river::io::Group::createFrom(const ejson::Document& _obj, const etk::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;
|
||||
}
|
||||
std::string groupName = tmpObject["group"].toString().get();
|
||||
etk::String groupName = tmpObject["group"].toString().get();
|
||||
if (groupName == _name) {
|
||||
RIVER_INFO("Add element in Group[" << _name << "]: " << _obj.getKey(iii));
|
||||
// get type : io
|
||||
std::string ioType = tmpObject["io"].toString().get("error");
|
||||
etk::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.push_back(tmp);
|
||||
m_list.pushBack(tmp);
|
||||
}
|
||||
#endif
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
@ -37,7 +37,7 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std:
|
||||
|| ioType == "PAoutput") {
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_obj.getKey(iii), tmpObject);
|
||||
tmp->setGroup(sharedFromThis());
|
||||
m_list.push_back(tmp);
|
||||
m_list.pushBack(tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -48,7 +48,7 @@ void audio::river::io::Group::createFrom(const ejson::Document& _obj, const std:
|
||||
#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] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
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 std:
|
||||
}
|
||||
/*
|
||||
// manage Link Between Nodes :
|
||||
if (m_link != nullptr) {
|
||||
if (m_link != null) {
|
||||
RIVER_INFO("******** START LINK ************");
|
||||
ememory::SharedPtr<audio::river::io::NodeOrchestra> link = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_link);
|
||||
if (link == nullptr) {
|
||||
if (link == null) {
|
||||
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 std:
|
||||
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] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
RIVER_INFO(" " << m_list[iii]->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Group::getNode(const std::string& _name) {
|
||||
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Group::getNode(const etk::String& _name) {
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
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] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
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] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
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] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
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] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
m_list[iii]->stop();
|
||||
}
|
||||
}
|
||||
@ -130,11 +130,11 @@ void audio::river::io::Group::stop() {
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Group::generateDot(etk::FSNode& _node, bool _hardwareNode) {
|
||||
void audio::river::io::Group::generateDot(ememory::SharedPtr<etk::io::Interface>& _io, bool _hardwareNode) {
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != nullptr) {
|
||||
if (m_list[iii] != null) {
|
||||
if (m_list[iii]->isHarwareNode() == _hardwareNode) {
|
||||
m_list[iii]->generateDot(_node);
|
||||
m_list[iii]->generateDot(_io);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <ejson/ejson.hpp>
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <etk/io/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@ -32,25 +32,23 @@ namespace audio {
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Group() {
|
||||
// TODO : ...
|
||||
}
|
||||
~Group() = default;
|
||||
private:
|
||||
std::vector< ememory::SharedPtr<Node> > m_list; //!< List of all node in the group
|
||||
etk::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 std::string& _name);
|
||||
void createFrom(const ejson::Document& _obj, const etk::String& _name);
|
||||
/**
|
||||
* @brief Get a node in the group (if the node is not in the group nothing append).
|
||||
* @param[in] _name Name of the node requested.
|
||||
* @return nullptr The node named _name was not found.
|
||||
* @return null The node named _name was not found.
|
||||
* @return pointer The node was find in this group.
|
||||
*/
|
||||
ememory::SharedPtr<audio::river::io::Node> getNode(const std::string& _name);
|
||||
ememory::SharedPtr<audio::river::io::Node> getNode(const etk::String& _name);
|
||||
/**
|
||||
* @brief Start the group.
|
||||
* @note all sub-node will be started.
|
||||
@ -67,7 +65,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(etk::FSNode& _node, bool _hardwareNode);
|
||||
void generateDot(ememory::SharedPtr<etk::io::Interface>& _node, bool _hardwareNode);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/io/Manager.hpp>
|
||||
@ -12,16 +12,18 @@
|
||||
#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 <utility>
|
||||
#include <etk/path/fileSystem.hpp>
|
||||
#include <etk/uri/uri.hpp>
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
extern "C" {
|
||||
#include <portaudio/portaudio.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string basicAutoConfig =
|
||||
static etk::String basicAutoConfig =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
@ -55,6 +57,7 @@ static std::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
|
||||
@ -65,23 +68,28 @@ audio::river::io::Manager::Manager() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::init(const std::string& _filename) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
if (_filename == "") {
|
||||
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 if (m_config.load(_filename) == false) {
|
||||
RIVER_ERROR("you must set a basic configuration file for harware configuration: '" << _filename << "'");
|
||||
} 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::initString(const std::string& _data) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
void audio::river::io::Manager::initString(const etk::String& _data) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_config.parse(_data);
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::unInit() {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
// TODO : ...
|
||||
}
|
||||
|
||||
@ -98,88 +106,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(new Manager());
|
||||
static ememory::SharedPtr<audio::river::io::Manager> manager(ETK_NEW(Manager));
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
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();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
std::string type = tmppp["io"].toString().get("error");
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type == "input"
|
||||
|| type == "PAinput") {
|
||||
output.push_back(it);
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
std::string type = tmppp["io"].toString().get("error");
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type == "output"
|
||||
|| type == "PAoutput") {
|
||||
output.push_back(it);
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
std::string type = tmppp["io"].toString().get("error");
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type != "input"
|
||||
&& type != "PAinput"
|
||||
&& type != "output"
|
||||
&& type != "PAoutput"
|
||||
&& type != "error") {
|
||||
output.push_back(it);
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
std::string type = tmppp["io"].toString().get("error");
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if (type != "error") {
|
||||
output.push_back(it);
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(const std::string& _name) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(const etk::String& _name) {
|
||||
ethread::RecursiveLock 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 != nullptr
|
||||
if ( tmppp != null
|
||||
&& _name == tmppp->getName()) {
|
||||
RIVER_WARNING(" find it ... in standalone");
|
||||
return tmppp;
|
||||
@ -187,12 +195,12 @@ ememory::SharedPtr<audio::river::io::Node> audio::river::io::Manager::getNode(co
|
||||
}
|
||||
// search in the group list:
|
||||
{
|
||||
for (std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it(m_listGroup.begin());
|
||||
for (etk::Map<etk::String, ememory::SharedPtr<audio::river::io::Group> >::Iterator it(m_listGroup.begin());
|
||||
it != m_listGroup.end();
|
||||
++it) {
|
||||
if (it->second != nullptr) {
|
||||
if (it->second != null) {
|
||||
ememory::SharedPtr<audio::river::io::Node> node = it->second->getNode(_name);
|
||||
if (node != nullptr) {
|
||||
if (node != null) {
|
||||
RIVER_WARNING(" find it ... in group: " << it->first);
|
||||
return node;
|
||||
}
|
||||
@ -204,16 +212,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:
|
||||
std::string groupName = tmpObject["group"].toString().get();
|
||||
etk::String groupName = tmpObject["group"].toString().get();
|
||||
// get type : io
|
||||
std::string ioType = tmpObject["io"].toString().get("error");
|
||||
etk::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 == nullptr) {
|
||||
if (tmpGroup == null) {
|
||||
RIVER_WARNING("Can not get group ... '" << groupName << "'");
|
||||
return ememory::SharedPtr<audio::river::io::Node>();
|
||||
}
|
||||
@ -228,7 +236,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.push_back(tmp);
|
||||
m_list.pushBack(tmp);
|
||||
return tmp;
|
||||
#else
|
||||
RIVER_WARNING("not present interface");
|
||||
@ -238,7 +246,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.push_back(tmp);
|
||||
m_list.pushBack(tmp);
|
||||
return tmp;
|
||||
#else
|
||||
RIVER_WARNING("not present interface");
|
||||
@ -246,12 +254,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.push_back(tmp);
|
||||
m_list.pushBack(tmp);
|
||||
return tmp;
|
||||
}
|
||||
if (ioType == "muxer") {
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeMuxer::create(_name, tmpObject);
|
||||
m_list.push_back(tmp);
|
||||
m_list.pushBack(tmp);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
@ -260,14 +268,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 std::string& _name) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> audio::river::io::Manager::getVolumeGroup(const etk::String& _name) {
|
||||
ethread::RecursiveLock 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] == nullptr) {
|
||||
if (m_volumeGroup[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_volumeGroup[iii]->getName() == _name) {
|
||||
@ -276,14 +284,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.push_back(tmpVolume);
|
||||
m_volumeGroup.pushBack(tmpVolume);
|
||||
return tmpVolume;
|
||||
}
|
||||
|
||||
bool audio::river::io::Manager::setVolume(const std::string& _volumeName, float _valuedB) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
bool audio::river::io::Manager::setVolume(const etk::String& _volumeName, float _valuedB) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
|
||||
if (volume == nullptr) {
|
||||
if (volume == null) {
|
||||
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'");
|
||||
return false;
|
||||
}
|
||||
@ -295,79 +303,79 @@ bool audio::river::io::Manager::setVolume(const std::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 != nullptr) {
|
||||
if (val != null) {
|
||||
val->volumeChange();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
float audio::river::io::Manager::getVolume(const std::string& _volumeName) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
float audio::river::io::Manager::getVolume(const etk::String& _volumeName) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
|
||||
if (volume == nullptr) {
|
||||
if (volume == null) {
|
||||
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
|
||||
return 0.0f;
|
||||
}
|
||||
return volume->getVolume();
|
||||
}
|
||||
|
||||
std::pair<float,float> audio::river::io::Manager::getVolumeRange(const std::string& _volumeName) const {
|
||||
return std::make_pair<float,float>(-300, 300);
|
||||
etk::Pair<float,float> audio::river::io::Manager::getVolumeRange(const etk::String& _volumeName) const {
|
||||
return etk::makePair<float,float>(-300, 300);
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::setMute(const std::string& _volumeName, bool _mute) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
void audio::river::io::Manager::setMute(const etk::String& _volumeName, bool _mute) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
|
||||
if (volume == nullptr) {
|
||||
if (volume == null) {
|
||||
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 != nullptr) {
|
||||
if (val != null) {
|
||||
val->volumeChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool audio::river::io::Manager::getMute(const std::string& _volumeName) {
|
||||
std::unique_lock<std::recursive_mutex> lock(m_mutex);
|
||||
bool audio::river::io::Manager::getMute(const etk::String& _volumeName) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> volume = getVolumeGroup(_volumeName);
|
||||
if (volume == nullptr) {
|
||||
if (volume == null) {
|
||||
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
|
||||
return false;
|
||||
}
|
||||
return volume->getMute();
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
node << "digraph G {" << "\n";
|
||||
node << " rankdir=\"LR\";\n";
|
||||
*ioFile << "digraph G {" << "\n";
|
||||
*ioFile << " 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 != nullptr) {
|
||||
if (val != null) {
|
||||
if (val->isHarwareNode() == true) {
|
||||
val->generateDot(node);
|
||||
val->generateDot(ioFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it(m_listGroup.begin());
|
||||
for (etk::Map<etk::String, ememory::SharedPtr<audio::river::io::Group> >::Iterator it(m_listGroup.begin());
|
||||
it != m_listGroup.end();
|
||||
++it) {
|
||||
if (it->second != nullptr) {
|
||||
it->second->generateDot(node, true);
|
||||
if (it->second != null) {
|
||||
it->second->generateDot(ioFile, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -376,37 +384,36 @@ void audio::river::io::Manager::generateDot(const std::string& _filename) {
|
||||
// standalone
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
|
||||
if (val != nullptr) {
|
||||
if (val != null) {
|
||||
if (val->isHarwareNode() == false) {
|
||||
val->generateDot(node);
|
||||
val->generateDot(ioFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it(m_listGroup.begin());
|
||||
for (etk::Map<etk::String, ememory::SharedPtr<audio::river::io::Group> >::Iterator it(m_listGroup.begin());
|
||||
it != m_listGroup.end();
|
||||
++it) {
|
||||
if (it->second != nullptr) {
|
||||
it->second->generateDot(node, false);
|
||||
if (it->second != null) {
|
||||
it->second->generateDot(ioFile, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node << "}" << "\n";
|
||||
node.fileClose();
|
||||
RIVER_INFO("Generate the DOT files: " << node << " (DONE)");
|
||||
*ioFile << "}" << "\n";
|
||||
ioFile->close();
|
||||
RIVER_INFO("Generate the DOT files: " << _uri << " (DONE)");
|
||||
}
|
||||
|
||||
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> audio::river::io::Manager::getGroup(const etk::String& _name) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<audio::river::io::Group> out;
|
||||
std::map<std::string, ememory::SharedPtr<audio::river::io::Group> >::iterator it = m_listGroup.find(_name);
|
||||
etk::Map<etk::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 != nullptr) {
|
||||
if (out != null) {
|
||||
out->createFrom(m_config, _name);
|
||||
std::pair<std::string, ememory::SharedPtr<audio::river::io::Group> > plop(std::string(_name), out);
|
||||
m_listGroup.insert(plop);
|
||||
m_listGroup.add(_name, out);
|
||||
RIVER_INFO("Create a new group: " << _name << " ( END )");
|
||||
} else {
|
||||
RIVER_ERROR("Can not create new group: " << _name << " ( END )");
|
||||
|
@ -1,24 +1,22 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/Map.hpp>
|
||||
#include <ethread/Mutex.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
#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 {
|
||||
@ -30,7 +28,7 @@ namespace audio {
|
||||
*/
|
||||
class Manager : public ememory::EnableSharedFromThis<Manager> {
|
||||
private:
|
||||
mutable std::recursive_mutex m_mutex; //!< prevent multiple access
|
||||
mutable ethread::MutexRecursive m_mutex; //!< prevent multiple access
|
||||
private:
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -44,58 +42,58 @@ namespace audio {
|
||||
~Manager();
|
||||
/**
|
||||
* @brief Called by audio::river::init() to set the hardware configuration file.
|
||||
* @param[in] _filename Name of the file to initialize.
|
||||
* @param[in] _uri Uri file to initialize.
|
||||
*/
|
||||
void init(const std::string& _filename);
|
||||
void init(const etk::Uri& _uri);
|
||||
/**
|
||||
* @brief Called by audio::river::initString() to set the hardware configuration string.
|
||||
* @param[in] _data json configuration string.
|
||||
*/
|
||||
void initString(const std::string& _data);
|
||||
void initString(const etk::String& _data);
|
||||
/**
|
||||
* @brief Called by audio::river::inInit() to uninitialize all the low level interface.
|
||||
*/
|
||||
void unInit();
|
||||
private:
|
||||
ejson::Document m_config; //!< harware configuration
|
||||
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
|
||||
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
|
||||
public:
|
||||
/**
|
||||
* @brief Get a node with his name (the name is set in the description file.
|
||||
* @param[in] _name Name of the node
|
||||
* @return Pointer on the noe or a nullptr if the node does not exist in the file or an error occured.
|
||||
* @return Pointer on the noe or a null if the node does not exist in the file or an error occured.
|
||||
*/
|
||||
ememory::SharedPtr<audio::river::io::Node> getNode(const std::string& _name);
|
||||
ememory::SharedPtr<audio::river::io::Node> getNode(const etk::String& _name);
|
||||
private:
|
||||
std::vector<ememory::SharedPtr<audio::drain::VolumeElement> > m_volumeGroup; //!< List of All global volume in the Low level interface.
|
||||
etk::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). nullptr if the name is empty.
|
||||
* @return pointer on the requested volume (create it if does not exist). null if the name is empty.
|
||||
*/
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> getVolumeGroup(const std::string& _name);
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> getVolumeGroup(const etk::String& _name);
|
||||
/**
|
||||
* @brief Get all input audio stream.
|
||||
* @return a list of all availlables input stream name
|
||||
*/
|
||||
std::vector<std::string> getListStreamInput();
|
||||
etk::Vector<etk::String> getListStreamInput();
|
||||
/**
|
||||
* @brief Get all output audio stream.
|
||||
* @return a list of all availlables output stream name
|
||||
*/
|
||||
std::vector<std::string> getListStreamOutput();
|
||||
etk::Vector<etk::String> getListStreamOutput();
|
||||
/**
|
||||
* @brief Get all audio virtual stream.
|
||||
* @return a list of all availlables virtual stream name
|
||||
*/
|
||||
std::vector<std::string> getListStreamVirtual();
|
||||
etk::Vector<etk::String> getListStreamVirtual();
|
||||
/**
|
||||
* @brief Get all audio stream.
|
||||
* @return a list of all availlables stream name
|
||||
*/
|
||||
std::vector<std::string> getListStream();
|
||||
etk::Vector<etk::String> getListStream();
|
||||
|
||||
/**
|
||||
* @brief Set a volume for a specific group
|
||||
@ -105,46 +103,46 @@ namespace audio {
|
||||
* @return false An error occured
|
||||
* @example : setVolume("MASTER", -3.0f);
|
||||
*/
|
||||
bool setVolume(const std::string& _volumeName, float _valuedB);
|
||||
bool setVolume(const etk::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 std::string& _volumeName);
|
||||
float getVolume(const etk::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)
|
||||
*/
|
||||
std::pair<float,float> getVolumeRange(const std::string& _volumeName) const;
|
||||
etk::Pair<float,float> getVolumeRange(const etk::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 std::string& _volumeName, bool _mute);
|
||||
void setMute(const etk::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 std::string& _volumeName);
|
||||
bool getMute(const etk::String& _volumeName);
|
||||
/**
|
||||
* @brief Generate the dot file corresponding at the actif nodes.
|
||||
* @param[in] _filename Name of the file to write data.
|
||||
* @param[in] _uri Uri of the file to write data.
|
||||
*/
|
||||
void generateDot(const std::string& _filename);
|
||||
void generateDot(const etk::Uri& _uri);
|
||||
private:
|
||||
std::map<std::string, ememory::SharedPtr<audio::river::io::Group> > m_listGroup; //!< List of all groups
|
||||
etk::Map<etk::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 nullptr if the group does not existed.
|
||||
* @return Pointer on the requested group or null if the group does not existed.
|
||||
*/
|
||||
ememory::SharedPtr<audio::river::io::Group> getGroup(const std::string& _name);
|
||||
ememory::SharedPtr<audio::river::io::Group> getGroup(const etk::String& _name);
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include "Node.hpp"
|
||||
#include <audio/river/debug.hpp>
|
||||
|
||||
audio::river::io::Node::Node(const std::string& _name, const ejson::Object& _config) :
|
||||
audio::river::io::Node::Node(const etk::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 std::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",
|
||||
*/
|
||||
std::string interfaceType = m_config["io"].toString().get();
|
||||
etk::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 std::string& _name, const ejson::Object& _con
|
||||
|
||||
int32_t frequency = m_config["frequency"].toNumber().get(1);
|
||||
// Get audio format type:
|
||||
std::string type = m_config["type"].toString().get("int16");
|
||||
etk::String type = m_config["type"].toString().get("int16");
|
||||
enum audio::format formatType = audio::getFormatFromString(type);
|
||||
// Get volume stage :
|
||||
std::string volumeName = m_config["volume-name"].toString().get();
|
||||
etk::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 :
|
||||
std::vector<audio::channel> map;
|
||||
etk::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.push_back(audio::channel_frontLeft);
|
||||
map.push_back(audio::channel_frontRight);
|
||||
map.pushBack(audio::channel_frontLeft);
|
||||
map.pushBack(audio::channel_frontRight);
|
||||
} else {
|
||||
for (auto it : listChannelMap) {
|
||||
std::string value = it.toString().get();
|
||||
map.push_back(audio::getChannelFromString(value));
|
||||
etk::String value = it.toString().get();
|
||||
map.pushBack(audio::getChannelFromString(value));
|
||||
}
|
||||
}
|
||||
hardwareFormat.set(map, formatType, frequency);
|
||||
|
||||
|
||||
std::string muxerDemuxerConfig;
|
||||
etk::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] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
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) {
|
||||
ememory::SharedPtr<audio::river::Interface> element = m_listAvaillable[iii].lock();
|
||||
if (element == nullptr) {
|
||||
auto element = m_listAvaillable[iii].lock();
|
||||
if (element == null) {
|
||||
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) {
|
||||
std::vector<ememory::WeakPtr<audio::river::Interface> >::iterator it = m_listAvaillable.begin();
|
||||
auto 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.push_back(_interface);
|
||||
m_listAvaillable.pushBack(_interface);
|
||||
}
|
||||
|
||||
void audio::river::io::Node::interfaceAdd(const ememory::SharedPtr<audio::river::Interface>& _interface) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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.push_back(_interface);
|
||||
m_list.pushBack(_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) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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,14 +175,13 @@ 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) {
|
||||
ememory::SharedPtr<audio::river::Interface> node = m_listAvaillable[iii].lock();
|
||||
if (node != nullptr) {
|
||||
auto node = m_listAvaillable[iii].lock();
|
||||
if (node != null) {
|
||||
node->systemVolumeChange();
|
||||
}
|
||||
}
|
||||
@ -191,11 +190,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 == nullptr) {
|
||||
if (_inputBuffer == null) {
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_input) {
|
||||
@ -211,11 +210,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 == nullptr) {
|
||||
if (_outputBuffer == null) {
|
||||
return;
|
||||
}
|
||||
enum audio::format muxerFormatType = m_process.getInputConfig().getFormat();
|
||||
std::vector<uint8_t> outputTmp2;
|
||||
etk::Vector<uint8_t> outputTmp2;
|
||||
uint32_t nbByteTmpBuffer = audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size()*_nbChunk;
|
||||
RIVER_VERBOSE("resize=" << nbByteTmpBuffer);
|
||||
outputTmp2.resize(nbByteTmpBuffer);
|
||||
@ -225,13 +224,13 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
// process 16 bits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// $$$$ change the int16
|
||||
std::vector<int16_t> output;
|
||||
etk::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 = nullptr;
|
||||
const int16_t* outputTmp = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
@ -258,12 +257,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 32 bits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector<int32_t> output;
|
||||
etk::Vector<int32_t> output;
|
||||
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
|
||||
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
|
||||
const int32_t* outputTmp = nullptr;
|
||||
const int32_t* outputTmp = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
@ -288,12 +287,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 64 bits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector<int64_t> output;
|
||||
etk::Vector<int64_t> output;
|
||||
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
|
||||
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
|
||||
const int64_t* outputTmp = nullptr;
|
||||
const int64_t* outputTmp = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
@ -318,12 +317,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 32 bits FLOAT
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector<float> output;
|
||||
etk::Vector<float> output;
|
||||
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
|
||||
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
|
||||
const float* outputTmp = nullptr;
|
||||
const float* outputTmp = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
@ -347,12 +346,12 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 64 bits FLOAT
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector<double> output;
|
||||
etk::Vector<double> output;
|
||||
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
|
||||
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
|
||||
const double* outputTmp = nullptr;
|
||||
const double* outputTmp = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
@ -379,7 +378,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] == nullptr) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_feedback) {
|
||||
@ -392,70 +391,70 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
return;
|
||||
}
|
||||
|
||||
static void link(etk::FSNode& _node, const std::string& _first, const std::string& _op, const std::string& _second) {
|
||||
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second) {
|
||||
if (_op == "->") {
|
||||
_node << " " << _first << " -> " << _second << ";\n";
|
||||
*_io << " " << _first << " -> " << _second << ";\n";
|
||||
} else if (_op == "<-") {
|
||||
_node << " " << _first << " -> " <<_second<< " [color=transparent];\n";
|
||||
_node << " " << _second << " -> " << _first << " [constraint=false];\n";
|
||||
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
|
||||
*_io << " " << _second << " -> " << _first << " [constraint=false];\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";
|
||||
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";
|
||||
if (m_isInput == true) {
|
||||
_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";
|
||||
*_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";
|
||||
// Link all nodes :
|
||||
_node << " NODE_" << m_uid << "_HW_interface -> " << nameIn << " [arrowhead=\"open\"];\n";
|
||||
_node << " " << nameOut << " -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
|
||||
*_io << " NODE_" << m_uid << "_HW_interface -> " << nameIn << " [arrowhead=\"open\"];\n";
|
||||
*_io << " " << 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);
|
||||
_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;
|
||||
*_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;
|
||||
if (nbOutput>0) {
|
||||
m_process.generateDotProcess(_node, 3, m_uid, nameIn, nameOut, true);
|
||||
m_process.generateDotProcess(_io, 3, m_uid, nameIn, nameOut, true);
|
||||
}
|
||||
_node << " node [shape=square];\n";
|
||||
*_io << " node [shape=square];\n";
|
||||
if (nbOutput>0) {
|
||||
_node << " NODE_" << m_uid << "_muxer [ label=\"MUXER\\n format=" << etk::to_string(m_process.getInputConfig().getFormat()) << "\" ];\n";
|
||||
*_io << " NODE_" << m_uid << "_muxer [ label=\"MUXER\\n format=" << etk::toString(m_process.getInputConfig().getFormat()) << "\" ];\n";
|
||||
}
|
||||
if (nbfeedback>0) {
|
||||
_node << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::to_string(m_process.getOutputConfig().getFormat()) << "\" ];\n";
|
||||
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
|
||||
}
|
||||
// Link all nodes :
|
||||
if (nbOutput>0) {
|
||||
link(_node, "NODE_" + etk::to_string(m_uid) + "_HW_interface", "<-", nameOut);
|
||||
link(_node, nameIn, "<-", "NODE_" + etk::to_string(m_uid) + "_muxer");
|
||||
link(_io, "NODE_" + etk::toString(m_uid) + "_HW_interface", "<-", nameOut);
|
||||
link(_io, nameIn, "<-", "NODE_" + etk::toString(m_uid) + "_muxer");
|
||||
}
|
||||
if (nbfeedback>0) {
|
||||
_node << " NODE_" << m_uid << "_HW_interface -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
|
||||
*_io << " NODE_" << m_uid << "_HW_interface -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
|
||||
}
|
||||
if ( nbOutput>0
|
||||
&& nbfeedback>0) {
|
||||
_node << " { rank=same; NODE_" << m_uid << "_demuxer; NODE_" << m_uid << "_muxer }\n";
|
||||
*_io << " { rank=same; NODE_" << m_uid << "_demuxer; NODE_" << m_uid << "_muxer }\n";
|
||||
}
|
||||
|
||||
}
|
||||
_node << " }\n \n";
|
||||
*_io << " }\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 == nullptr) {
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
bool isLink = false;
|
||||
@ -464,13 +463,13 @@ void audio::river::io::Node::generateDot(etk::FSNode& _node) {
|
||||
isLink = true;
|
||||
}
|
||||
}
|
||||
if (element != nullptr) {
|
||||
if (element != null) {
|
||||
if (element->getMode() == modeInterface_input) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_output) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_muxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_feedback) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else {
|
||||
|
||||
}
|
||||
@ -481,7 +480,7 @@ void audio::river::io::Node::generateDot(etk::FSNode& _node) {
|
||||
|
||||
void audio::river::io::Node::startInGroup() {
|
||||
ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
|
||||
if (group != nullptr) {
|
||||
if (group != null) {
|
||||
group->start();
|
||||
} else {
|
||||
start();
|
||||
@ -490,7 +489,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 != nullptr) {
|
||||
if (group != null) {
|
||||
group->stop();
|
||||
} else {
|
||||
stop();
|
||||
|
@ -1,16 +1,13 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <audio/format.hpp>
|
||||
#include <audio/channel.hpp>
|
||||
@ -18,7 +15,7 @@
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/drain/IOFormatInterface.hpp>
|
||||
#include <audio/drain/Volume.hpp>
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <etk/io/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@ -39,7 +36,7 @@ namespace audio {
|
||||
* @param[in] _name Name of the node.
|
||||
* @param[in] _config Configuration of the node.
|
||||
*/
|
||||
Node(const std::string& _name, const ejson::Object& _config);
|
||||
Node(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
@ -54,7 +51,7 @@ namespace audio {
|
||||
return false;
|
||||
};
|
||||
protected:
|
||||
mutable std::mutex m_mutex; //!< prevent open/close/write/read access that is multi-threaded.
|
||||
mutable ethread::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
|
||||
@ -84,8 +81,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:
|
||||
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.
|
||||
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.
|
||||
/**
|
||||
* @brief Get the number of interface with a specific type.
|
||||
* @param[in] _interfaceType Type of the interface.
|
||||
@ -124,13 +121,13 @@ namespace audio {
|
||||
*/
|
||||
void interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface);
|
||||
protected:
|
||||
std::string m_name; //!< Name of the interface
|
||||
etk::String m_name; //!< Name of the interface
|
||||
public:
|
||||
/**
|
||||
* @brief Get the interface name.
|
||||
* @return Current name.
|
||||
*/
|
||||
const std::string& getName() {
|
||||
const etk::String& getName() {
|
||||
return m_name;
|
||||
}
|
||||
protected:
|
||||
@ -212,9 +209,9 @@ namespace audio {
|
||||
public:
|
||||
/**
|
||||
* @brief Generate the node dot file section
|
||||
* @param[in] _node File node to generate the data.
|
||||
* @param[in] _io File interface to dump data.
|
||||
*/
|
||||
virtual void generateDot(etk::FSNode& _node);
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,35 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 <functional>
|
||||
#include <etk/Function.hpp>
|
||||
|
||||
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::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::Interface> audio::river::io::NodeAEC::createInput(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _objectName,
|
||||
const std::string& _name) {
|
||||
const etk::String& _objectName,
|
||||
const etk::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>();
|
||||
}
|
||||
std::string streamName = tmppp["map-on"].toString().get("error");
|
||||
etk::String streamName = tmppp["map-on"].toString().get("error");
|
||||
|
||||
m_nbChunk = m_config["nb-chunk"].toNumber().get(1024);
|
||||
// check if it is an Output:
|
||||
std::string type = tmppp["io"].toString().get("error");
|
||||
etk::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 != nullptr) {
|
||||
if (interface != null) {
|
||||
interface->setName(_name);
|
||||
}
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
audio::river::io::NodeAEC::NodeAEC(const std::string& _name, const ejson::Object& _config) :
|
||||
audio::river::io::NodeAEC::NodeAEC(const etk::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 std::string& _name, const ejson::Object
|
||||
algo:"river-remover",
|
||||
algo-mode:"cutter",
|
||||
*/
|
||||
std::vector<audio::channel> feedbackMap;
|
||||
feedbackMap.push_back(audio::channel_frontCenter);
|
||||
etk::Vector<audio::channel> feedbackMap;
|
||||
feedbackMap.pushBack(audio::channel_frontCenter);
|
||||
RIVER_INFO("Create FEEDBACK : ");
|
||||
m_interfaceFeedBack = createInput(hardwareFormat.getFrequency(),
|
||||
feedbackMap,
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-feedback",
|
||||
_name + "-AEC-feedback");
|
||||
if (m_interfaceFeedBack == nullptr) {
|
||||
if (m_interfaceFeedBack == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-feedback in " << _name);
|
||||
return;
|
||||
}
|
||||
@ -97,34 +97,33 @@ audio::river::io::NodeAEC::NodeAEC(const std::string& _name, const ejson::Object
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-microphone",
|
||||
_name + "-AEC-microphone");
|
||||
if (m_interfaceMicrophone == nullptr) {
|
||||
if (m_interfaceMicrophone == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-microphone in " << _name);
|
||||
return;
|
||||
}
|
||||
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
// set callback mode ...
|
||||
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),
|
||||
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),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat())*hardwareFormat.getMap().size(),
|
||||
hardwareFormat.getFrequency());
|
||||
m_bufferFeedBack.setCapacity(std::chrono::milliseconds(1000),
|
||||
m_bufferFeedBack.setCapacity(echrono::milliseconds(1000),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat()), // only one channel ...
|
||||
hardwareFormat.getFrequency());
|
||||
|
||||
@ -139,24 +138,24 @@ audio::river::io::NodeAEC::~NodeAEC() {
|
||||
};
|
||||
|
||||
void audio::river::io::NodeAEC::start() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
|
||||
if (m_interfaceFeedBack != nullptr) {
|
||||
if (m_interfaceFeedBack != null) {
|
||||
RIVER_INFO("Start FEEDBACK : ");
|
||||
m_interfaceFeedBack->start();
|
||||
}
|
||||
if (m_interfaceMicrophone != nullptr) {
|
||||
if (m_interfaceMicrophone != null) {
|
||||
RIVER_INFO("Start Microphone : ");
|
||||
m_interfaceMicrophone->start();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodeAEC::stop() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (m_interfaceFeedBack != nullptr) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (m_interfaceFeedBack != null) {
|
||||
m_interfaceFeedBack->stop();
|
||||
}
|
||||
if (m_interfaceMicrophone != nullptr) {
|
||||
if (m_interfaceMicrophone != null) {
|
||||
m_interfaceMicrophone->stop();
|
||||
}
|
||||
}
|
||||
@ -167,14 +166,14 @@ void audio::river::io::NodeAEC::onDataReceivedMicrophone(const void* _data,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
m_bufferMicrophone.write(_data, _nbChunk, _time);
|
||||
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_Microphone.raw", _data, _nbChunk*_map.size());
|
||||
process();
|
||||
@ -185,14 +184,14 @@ void audio::river::io::NodeAEC::onDataReceivedFeedBack(const void* _data,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
m_bufferFeedBack.write(_data, _nbChunk, _time);
|
||||
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_FeedBack.raw", _data, _nbChunk*_map.size());
|
||||
process();
|
||||
@ -212,7 +211,7 @@ void audio::river::io::NodeAEC::process() {
|
||||
delta = MicTime - fbTime;
|
||||
}
|
||||
|
||||
RIVER_INFO("check delta " << delta.count() << " > " << m_sampleTime.count());
|
||||
RIVER_INFO("check delta " << delta << " > " << m_sampleTime);
|
||||
if (delta > m_sampleTime) {
|
||||
// Synchronize if possible
|
||||
if (MicTime < fbTime) {
|
||||
@ -238,17 +237,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).count()/1000 << " µs");
|
||||
RIVER_ERROR("Can not synchronize flow ... : " << MicTime << " != " << fbTime << " delta = " << (MicTime-fbTime));
|
||||
return;
|
||||
}
|
||||
std::vector<uint8_t> dataMic;
|
||||
std::vector<uint8_t> dataFB;
|
||||
etk::Vector<uint8_t> dataMic;
|
||||
etk::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).count());
|
||||
RIVER_INFO(" process 256 samples ... micTime=" << MicTime << " fbTime=" << fbTime << " delta = " << (MicTime-fbTime));
|
||||
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());
|
||||
@ -266,12 +265,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 = 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 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 latencyTime = std::min(std::max(0,m_P_latencyTime),1000);
|
||||
int32_t latencyTime = etk::min(etk::max(0,m_P_latencyTime),1000);
|
||||
int32_t nb_sample_latency = (hardwareFormat.getFrequency()/1000)*latencyTime;
|
||||
|
||||
int32_t increaseSample = 32767;
|
||||
@ -317,34 +316,34 @@ void audio::river::io::NodeAEC::processAEC(void* _dataMic, void* _dataFB, uint32
|
||||
}
|
||||
|
||||
|
||||
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";
|
||||
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";
|
||||
// Link all nodes :
|
||||
_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";
|
||||
*_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";
|
||||
}
|
||||
if (m_interfaceFeedBack != nullptr) {
|
||||
_node << " " << m_interfaceFeedBack->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\n";
|
||||
if (m_interfaceFeedBack != null) {
|
||||
*_io << " " << m_interfaceFeedBack->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\n";
|
||||
}
|
||||
_node << " \n";
|
||||
*_io << " \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 == nullptr) {
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
bool isLink = false;
|
||||
@ -353,13 +352,13 @@ void audio::river::io::NodeAEC::generateDot(etk::FSNode& _node) {
|
||||
isLink = true;
|
||||
}
|
||||
}
|
||||
if (element != nullptr) {
|
||||
if (element != null) {
|
||||
if (element->getMode() == modeInterface_input) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_output) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_muxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_feedback) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else {
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -18,14 +18,14 @@ namespace audio {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeAEC(const std::string& _name, const ejson::Object& _config);
|
||||
NodeAEC(const etk::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 std::string& _name, const ejson::Object& _config);
|
||||
static ememory::SharedPtr<NodeAEC> create(const etk::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 std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _name);
|
||||
const etk::String& _streamName,
|
||||
const etk::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 std::vector<audio::channel>& _map);
|
||||
const etk::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 std::vector<audio::channel>& _map);
|
||||
const etk::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(etk::FSNode& _node);
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
|
||||
private:
|
||||
int32_t m_nbChunk;
|
||||
int32_t m_gainValue;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 std::vector<audio::orchestra::status>& _status) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
const etk::Vector<audio::orchestra::status>& _status) {
|
||||
ethread::UniqueLock 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 std::vector<audio::orchestra::status>& _status) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
const etk::Vector<audio::orchestra::status>& _status) {
|
||||
ethread::UniqueLock 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 std::string& _name, const ejson::Object& _config) {
|
||||
return ememory::SharedPtr<audio::river::io::NodeFile>(new audio::river::io::NodeFile(_name, _config));
|
||||
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));
|
||||
}
|
||||
|
||||
audio::river::io::NodeFile::NodeFile(const std::string& _name, const ejson::Object& _config) :
|
||||
Node(_name, _config) {
|
||||
audio::river::io::NodeFile::NodeFile(const etk::Path& _path, const ejson::Object& _config) :
|
||||
Node(_path.getString(), _config) {
|
||||
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
||||
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||
/**
|
||||
@ -49,8 +49,8 @@ audio::river::io::NodeFile::NodeFile(const std::string& _name, const ejson::Obje
|
||||
},
|
||||
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
|
||||
*/
|
||||
std::string typeInterface = audio::orchestra::type::undefined;
|
||||
std::string streamName = "default";
|
||||
etk::String typeInterface = audio::orchestra::type::undefined;
|
||||
etk::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 std::string& _name, const ejson::Obje
|
||||
m_interface.instanciate(typeInterface);
|
||||
m_interface.setName(_name);
|
||||
// TODO : Check return ...
|
||||
std::string type = m_config.getStringValue("type", "int16");
|
||||
etk::String type = m_config.getStringValue("type", "int16");
|
||||
if (streamName == "") {
|
||||
streamName = "default";
|
||||
}
|
||||
@ -197,27 +197,39 @@ audio::river::io::NodeFile::NodeFile(const std::string& _name, const ejson::Obje
|
||||
if (m_isInput == true) {
|
||||
m_process.setInputConfig(hardwareFormat);
|
||||
m_process.setOutputConfig(interfaceFormat);
|
||||
err = m_interface.openStream(nullptr, ¶ms,
|
||||
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),
|
||||
err = m_interface.openStream(null,
|
||||
¶ms,
|
||||
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
|
||||
);
|
||||
} else {
|
||||
m_process.setInputConfig(interfaceFormat);
|
||||
m_process.setOutputConfig(hardwareFormat);
|
||||
err = m_interface.openStream(¶ms, 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),
|
||||
err = m_interface.openStream(¶ms,
|
||||
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
|
||||
);
|
||||
}
|
||||
@ -228,7 +240,7 @@ audio::river::io::NodeFile::NodeFile(const std::string& _name, const ejson::Obje
|
||||
}
|
||||
|
||||
audio::river::io::NodeFile::~NodeFile() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("close input stream");
|
||||
if (m_interface.isStreamOpen() ) {
|
||||
m_interface.closeStream();
|
||||
@ -240,25 +252,25 @@ void audio::river::io::NodeFile::threadCallback() {
|
||||
// open the file
|
||||
|
||||
while (m_alive == true) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
ethread::sleepMilliSeconds((100));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void audio::river::io::NodeFile::start() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (m_thread != nullptr) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (m_thread != null) {
|
||||
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<std::thread>(&audio::river::io::NodeFile::threadCallback2, this);
|
||||
m_thread = ememory::makeShared<ethread::Thread>(&audio::river::io::NodeFile::threadCallback2, this);
|
||||
m_time = audio::Time::now();
|
||||
}
|
||||
|
||||
void audio::river::io::NodeFile::stop() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
m_alive = false;
|
||||
RIVER_INFO("Stop stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") );
|
||||
// TODO : Need join ...
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -24,9 +24,9 @@ namespace audio {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeFile(const std::string& _name, const ejson::Object& _config);
|
||||
NodeFile(const etk::Path& _path, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodeFile> create(const std::string& _name, const ejson::Object& _config);
|
||||
static ememory::SharedPtr<NodeFile> create(const etk::Path& _path, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
@ -36,13 +36,13 @@ namespace audio {
|
||||
};
|
||||
protected:
|
||||
audio::Time m_time; //!< time of the flow
|
||||
etk::FSNode m_file; //!< File interface
|
||||
ememory::SharedPtr<etk::io::Interface>& 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
|
||||
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
|
||||
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
|
||||
protected:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
@ -1,35 +1,35 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 <functional>
|
||||
#include <etk/Function.hpp>
|
||||
|
||||
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::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::Interface> audio::river::io::NodeMuxer::createInput(float _freq,
|
||||
const std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _objectName,
|
||||
const std::string& _name) {
|
||||
const etk::String& _objectName,
|
||||
const etk::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>();
|
||||
}
|
||||
std::string streamName = tmppp["map-on"].toString().get("error");
|
||||
etk::String streamName = tmppp["map-on"].toString().get("error");
|
||||
|
||||
|
||||
// check if it is an Output:
|
||||
std::string type = tmppp["io"].toString().get("error");
|
||||
etk::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 != nullptr) {
|
||||
if (interface != null) {
|
||||
interface->setName(_name);
|
||||
}
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const ejson::Object& _config) :
|
||||
audio::river::io::NodeMuxer::NodeMuxer(const etk::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 std::string& _name, const ejson::Ob
|
||||
*/
|
||||
RIVER_INFO("Create IN 1 : ");
|
||||
m_interfaceInput1 = createInput(hardwareFormat.getFrequency(),
|
||||
std::vector<audio::channel>(),
|
||||
etk::Vector<audio::channel>(),
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-input-1",
|
||||
_name + "-muxer-in1");
|
||||
if (m_interfaceInput1 == nullptr) {
|
||||
if (m_interfaceInput1 == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-input-1 in " << _name);
|
||||
return;
|
||||
}
|
||||
@ -92,8 +92,8 @@ audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const ejson::Ob
|
||||
} else {
|
||||
m_mapInput1.clear();
|
||||
for (const auto it : listChannelMap) {
|
||||
std::string value = it.toString().get();
|
||||
m_mapInput1.push_back(audio::getChannelFromString(value));
|
||||
etk::String value = it.toString().get();
|
||||
m_mapInput1.pushBack(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 std::string& _name, const ejson::Ob
|
||||
|
||||
RIVER_INFO("Create IN 2 : ");
|
||||
m_interfaceInput2 = createInput(hardwareFormat.getFrequency(),
|
||||
std::vector<audio::channel>(),
|
||||
etk::Vector<audio::channel>(),
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-input-2",
|
||||
_name + "-muxer-in2");
|
||||
if (m_interfaceInput2 == nullptr) {
|
||||
if (m_interfaceInput2 == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-input-2 in " << _name);
|
||||
return;
|
||||
}
|
||||
@ -118,8 +118,8 @@ audio::river::io::NodeMuxer::NodeMuxer(const std::string& _name, const ejson::Ob
|
||||
} else {
|
||||
m_mapInput2.clear();
|
||||
for (const auto it : listChannelMap2) {
|
||||
std::string value = it.toString().get();
|
||||
m_mapInput2.push_back(audio::getChannelFromString(value));
|
||||
etk::String value = it.toString().get();
|
||||
m_mapInput2.pushBack(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 std::string& _name, const ejson::Ob
|
||||
}
|
||||
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
// set callback mode ...
|
||||
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_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_bufferInput1.setCapacity(std::chrono::milliseconds(1000),
|
||||
m_bufferInput1.setCapacity(echrono::milliseconds(1000),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat())*m_mapInput1.size(),
|
||||
hardwareFormat.getFrequency());
|
||||
m_bufferInput2.setCapacity(std::chrono::milliseconds(1000),
|
||||
m_bufferInput2.setCapacity(echrono::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() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
|
||||
if (m_interfaceInput1 != nullptr) {
|
||||
if (m_interfaceInput1 != null) {
|
||||
RIVER_INFO("Start FEEDBACK : ");
|
||||
m_interfaceInput1->start();
|
||||
}
|
||||
if (m_interfaceInput2 != nullptr) {
|
||||
if (m_interfaceInput2 != null) {
|
||||
RIVER_INFO("Start Microphone : ");
|
||||
m_interfaceInput2->start();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodeMuxer::stop() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (m_interfaceInput1 != nullptr) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (m_interfaceInput1 != null) {
|
||||
m_interfaceInput1->stop();
|
||||
}
|
||||
if (m_interfaceInput2 != nullptr) {
|
||||
if (m_interfaceInput2 != null) {
|
||||
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 std::vector<audio::channel>& _map) {
|
||||
const etk::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
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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 std::vector<audio::channel>& _map) {
|
||||
const etk::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
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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.count() << " > " << m_sampleTime.count());
|
||||
RIVER_VERBOSE("check delta " << delta << " > " << m_sampleTime);
|
||||
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).count()/1000 << " µs");
|
||||
RIVER_ERROR("Can not synchronize flow ... : " << in1Time << " != " << in2Time << " delta = " << (in1Time-in2Time));
|
||||
return;
|
||||
}
|
||||
std::vector<uint8_t> dataIn1;
|
||||
std::vector<uint8_t> dataIn2;
|
||||
etk::Vector<uint8_t> dataIn1;
|
||||
etk::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).count());
|
||||
//RIVER_INFO(" process 256 samples ... in1Time=" << in1Time << " in2Time=" << in2Time << " delta = " << (in1Time-in2Time));
|
||||
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 std::vector<audio::channel>& _mapInput) {
|
||||
void audio::river::io::NodeMuxer::reorder(void* _output, uint32_t _nbChunk, void* _input, const etk::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(etk::FSNode& _node) {
|
||||
_node << " subgraph clusterNode_" << m_uid << " {\n";
|
||||
_node << " color=blue;\n";
|
||||
_node << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
|
||||
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";
|
||||
|
||||
_node << " node [shape=box];\n";
|
||||
*_io << " node [shape=box];\n";
|
||||
// TODO : Create a structure ...
|
||||
_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";
|
||||
*_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";
|
||||
// Link all nodes :
|
||||
_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";
|
||||
*_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";
|
||||
}
|
||||
if (m_interfaceInput1 != nullptr) {
|
||||
_node << " " << m_interfaceInput1->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
|
||||
if (m_interfaceInput1 != null) {
|
||||
*_io << " " << m_interfaceInput1->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
|
||||
}
|
||||
_node << " \n";
|
||||
*_io << " \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 == nullptr) {
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
bool isLink = false;
|
||||
@ -471,17 +471,17 @@ void audio::river::io::NodeMuxer::generateDot(etk::FSNode& _node) {
|
||||
isLink = true;
|
||||
}
|
||||
}
|
||||
if (element != nullptr) {
|
||||
if (element != null) {
|
||||
if (element->getMode() == modeInterface_input) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_output) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_muxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_feedback) {
|
||||
element->generateDot(_node, "NODE_" + etk::to_string(m_uid) + "_demuxer", isLink);
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
_node << "\n";
|
||||
*_io << "\n";
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -18,9 +18,9 @@ namespace audio {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeMuxer(const std::string& _name, const ejson::Object& _config);
|
||||
NodeMuxer(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodeMuxer> create(const std::string& _name, const ejson::Object& _config);
|
||||
static ememory::SharedPtr<NodeMuxer> create(const etk::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 std::vector<audio::channel>& _map,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _name);
|
||||
const etk::String& _streamName,
|
||||
const etk::String& _name);
|
||||
void onDataReceivedInput1(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map);
|
||||
const etk::Vector<audio::channel>& _map);
|
||||
void onDataReceivedInput2(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map);
|
||||
std::vector<audio::channel> m_mapInput1;
|
||||
std::vector<audio::channel> m_mapInput2;
|
||||
const etk::Vector<audio::channel>& _map);
|
||||
etk::Vector<audio::channel> m_mapInput1;
|
||||
etk::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);
|
||||
std::vector<uint8_t> m_data;
|
||||
etk::Vector<uint8_t> m_data;
|
||||
public:
|
||||
virtual void generateDot(etk::FSNode& _node);
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
|
||||
private:
|
||||
void reorder(void* _output, uint32_t _nbChunk, void* _input, const std::vector<audio::channel>& _mapInput);
|
||||
void reorder(void* _output, uint32_t _nbChunk, void* _input, const etk::Vector<audio::channel>& _mapInput);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 std::vector<audio::orchestra::status>& _status) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
const etk::Vector<audio::orchestra::status>& _status) {
|
||||
ethread::UniqueLock 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 std::vector<audio::orchestra::status>& _status) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
const etk::Vector<audio::orchestra::status>& _status) {
|
||||
ethread::UniqueLock 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 std::string& _name, const ejson::Object& _config) {
|
||||
return ememory::SharedPtr<audio::river::io::NodeOrchestra>(new audio::river::io::NodeOrchestra(_name, _config));
|
||||
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));
|
||||
}
|
||||
|
||||
audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const ejson::Object& _config) :
|
||||
audio::river::io::NodeOrchestra::NodeOrchestra(const etk::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 std::string& _name, const e
|
||||
},
|
||||
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
|
||||
*/
|
||||
std::string typeInterface = audio::orchestra::typeUndefined;
|
||||
std::string streamName = "default";
|
||||
etk::String typeInterface = audio::orchestra::typeUndefined;
|
||||
etk::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 std::string& _name, const e
|
||||
m_interface.instanciate(typeInterface);
|
||||
m_interface.setName(_name);
|
||||
// TODO : Check return ...
|
||||
std::string type = m_config["type"].toString().get("int16");
|
||||
etk::String type = m_config["type"].toString().get("int16");
|
||||
if (streamName == "") {
|
||||
streamName = "default";
|
||||
}
|
||||
@ -198,27 +198,37 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const e
|
||||
if (m_isInput == true) {
|
||||
m_process.setInputConfig(hardwareFormat);
|
||||
m_process.setOutputConfig(interfaceFormat);
|
||||
err = m_interface.openStream(nullptr, ¶ms,
|
||||
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),
|
||||
err = m_interface.openStream(null,
|
||||
¶ms,
|
||||
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
|
||||
);
|
||||
} else {
|
||||
m_process.setInputConfig(interfaceFormat);
|
||||
m_process.setOutputConfig(hardwareFormat);
|
||||
err = m_interface.openStream(¶ms, 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),
|
||||
err = m_interface.openStream(¶ms,
|
||||
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
|
||||
);
|
||||
}
|
||||
@ -229,7 +239,7 @@ audio::river::io::NodeOrchestra::NodeOrchestra(const std::string& _name, const e
|
||||
}
|
||||
|
||||
audio::river::io::NodeOrchestra::~NodeOrchestra() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("close input stream");
|
||||
if (m_interface.isStreamOpen() ) {
|
||||
m_interface.closeStream();
|
||||
@ -237,7 +247,7 @@ audio::river::io::NodeOrchestra::~NodeOrchestra() {
|
||||
};
|
||||
|
||||
void audio::river::io::NodeOrchestra::start() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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) {
|
||||
@ -246,7 +256,7 @@ void audio::river::io::NodeOrchestra::start() {
|
||||
}
|
||||
|
||||
void audio::river::io::NodeOrchestra::stop() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -24,9 +24,9 @@ namespace audio {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeOrchestra(const std::string& _name, const ejson::Object& _config);
|
||||
NodeOrchestra(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodeOrchestra> create(const std::string& _name, const ejson::Object& _config);
|
||||
static ememory::SharedPtr<NodeOrchestra> create(const etk::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 std::vector<audio::orchestra::status>& _status);
|
||||
const etk::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 std::vector<audio::orchestra::status>& _status);
|
||||
const etk::Vector<audio::orchestra::status>& _status);
|
||||
protected:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
// TODO : Manage status ...
|
||||
if (_inputBuffer != nullptr) {
|
||||
if (_inputBuffer != null) {
|
||||
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
|
||||
newInput(_inputBuffer, _nbChunk, _timeInput);
|
||||
}
|
||||
if (_outputBuffer != nullptr) {
|
||||
if (_outputBuffer != null) {
|
||||
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 std::string& _name, const ejson::Object& _config) {
|
||||
return ememory::SharedPtr<audio::river::io::NodePortAudio>(new audio::river::io::NodePortAudio(_name, _config));
|
||||
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));
|
||||
}
|
||||
|
||||
audio::river::io::NodePortAudio::NodePortAudio(const std::string& _name, const ejson::Object& _config) :
|
||||
audio::river::io::NodePortAudio::NodePortAudio(const etk::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 std::string& _name, const e
|
||||
},
|
||||
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
|
||||
*/
|
||||
std::string streamName = "default";
|
||||
etk::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 {
|
||||
std::string value = tmpObject.getStringValue("interface", "default");
|
||||
etk::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 std::string& _name, const e
|
||||
}
|
||||
|
||||
audio::river::io::NodePortAudio::~NodePortAudio() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("Stop stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
|
||||
PaError err = Pa_StopStream(m_stream);
|
||||
if( err != paNoError ) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -21,9 +21,9 @@ namespace audio {
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodePortAudio(const std::string& _name, const ejson::Object& _config);
|
||||
NodePortAudio(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodePortAudio> create(const std::string& _name, const ejson::Object& _config);
|
||||
static ememory::SharedPtr<NodePortAudio> create(const etk::String& _name, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 std::string river_configFile = "";
|
||||
static etk::String river_configFile = "";
|
||||
|
||||
|
||||
|
||||
void audio::river::init(const std::string& _filename) {
|
||||
void audio::river::init(const etk::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 != nullptr) {
|
||||
if (mng != null) {
|
||||
mng->init(river_configFile);
|
||||
}
|
||||
} else {
|
||||
@ -27,13 +27,13 @@ void audio::river::init(const std::string& _filename) {
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::initString(const std::string& _config) {
|
||||
void audio::river::initString(const etk::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 != nullptr) {
|
||||
if (mng != null) {
|
||||
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 != nullptr) {
|
||||
if (mng != null) {
|
||||
RIVER_ERROR("Can not get on the RIVER hardware manager !!!");
|
||||
mng->unInit();
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/String.hpp>
|
||||
/**
|
||||
* @brief Audio library namespace
|
||||
*/
|
||||
@ -18,12 +19,12 @@ namespace audio {
|
||||
* @brief Initialize the River Library
|
||||
* @param[in] _filename Name of the configuration file (if "" ==> default config file)
|
||||
*/
|
||||
void init(const std::string& _filename = "");
|
||||
void init(const etk::String& _filename = "");
|
||||
/**
|
||||
* @brief Initialize the River Library with a json data string
|
||||
* @param[in] _config json sting data
|
||||
*/
|
||||
void initString(const std::string& _config);
|
||||
void initString(const etk::String& _config);
|
||||
/**
|
||||
* @brief Un-initialize the River Library
|
||||
* @note this close all stream of all interfaces.
|
||||
|
@ -74,4 +74,46 @@ 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
|
||||
|
||||
|
@ -21,7 +21,7 @@ What change:
|
||||
```{.cpp}
|
||||
//Get the generic feedback on speaker:
|
||||
interface = manager->createFeedback(48000,
|
||||
std::vector<audio::channel>(),
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
```
|
||||
|
@ -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 (APACHE-2.0) {#audio_river_mainpage_license}
|
||||
====================
|
||||
License (MPL v2.0) {#audio_river_mainpage_license}
|
||||
==================
|
||||
|
||||
Copyright AUDIO-RIVER Edouard DUPIN
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
Licensed under the Mozilla Public License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
<http://www.apache.org/licenses/LICENSE-2.0>
|
||||
<https://www.mozilla.org/MPL/2.0>
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -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:
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.debug as debug
|
||||
import realog.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 "APACHE-2"
|
||||
return "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
@ -26,11 +26,20 @@ def get_maintainer():
|
||||
|
||||
def configure(target, my_module):
|
||||
my_module.add_src_file([
|
||||
'test/main.cpp'
|
||||
'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',
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio-river',
|
||||
'gtest',
|
||||
'etest',
|
||||
'etk',
|
||||
'test-debug'
|
||||
])
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.debug as debug
|
||||
import realog.debug as debug
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ def get_desc():
|
||||
return "Multi-nodal audio interface"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
return "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <ewol/ewol.hpp>
|
||||
@ -13,14 +13,14 @@
|
||||
#include <etk/tool.hpp>
|
||||
|
||||
appl::Windows::Windows() :
|
||||
m_composer(nullptr) {
|
||||
m_composer(null) {
|
||||
addObjectType("appl::Windows");
|
||||
propertyTitle.setDirectCheck("River IO viewer");
|
||||
}
|
||||
|
||||
void appl::Windows::init() {
|
||||
ewol::widget::Windows::init();
|
||||
std::string composition = std::string("");
|
||||
etk::String composition = etk::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 == nullptr) {
|
||||
if (m_composer == null) {
|
||||
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 != nullptr) {
|
||||
if (tmpDisp != null) {
|
||||
tmpDisp->recordToggle();
|
||||
}
|
||||
}
|
||||
|
||||
void appl::Windows::onCallbackGenerate() {
|
||||
ememory::SharedPtr<audio::river::widget::TemporalViewer> tmpDisp = ememory::dynamicPointerCast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer"));
|
||||
if (tmpDisp != nullptr) {
|
||||
if (tmpDisp != null) {
|
||||
tmpDisp->generateToggle();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <appl/debug.hpp>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @copyright 2019, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
|
||||
@ -15,8 +15,9 @@
|
||||
#include <ewol/widget/Manager.hpp>
|
||||
#include <ewol/context/Context.hpp>
|
||||
#include <audio/river/widget/TemporalViewer.hpp>
|
||||
#include <etk/theme/theme.hpp>
|
||||
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
@ -34,9 +35,38 @@ static const std::string configurationRiver =
|
||||
|
||||
class MainApplication : public ewol::context::Application {
|
||||
public:
|
||||
bool init(ewol::Context& _context, size_t _initId) {
|
||||
APPL_INFO("==> Init APPL (START) [" << ewol::getBoardType() << "] (" << ewol::getCompilationMode() << ")");
|
||||
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/");
|
||||
|
||||
_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));
|
||||
@ -48,15 +78,54 @@ 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);
|
||||
APPL_INFO("==> Init APPL (END)");
|
||||
return true;
|
||||
}
|
||||
void unInit(ewol::Context& _context) {
|
||||
APPL_INFO("==> Un-Init APPL (START)");
|
||||
|
||||
// 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 ...
|
||||
APPL_INFO("==> Un-Init APPL (END)");
|
||||
} 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;
|
||||
}
|
||||
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)");
|
||||
}
|
||||
};
|
||||
|
||||
@ -67,5 +136,5 @@ class MainApplication : public ewol::context::Application {
|
||||
*/
|
||||
int main(int _argc, const char *_argv[]) {
|
||||
// second possibility
|
||||
return ewol::run(new MainApplication(), _argc, _argv);
|
||||
return ewol::run(ETK_NEW(MainApplication), _argc, _argv);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.debug as debug
|
||||
import realog.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 "APACHE-2"
|
||||
return "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.debug as debug
|
||||
import realog.debug as debug
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ def get_desc():
|
||||
return "Read some data"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
return "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
@ -30,6 +30,7 @@ def configure(target, my_module):
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio-river',
|
||||
'test-debug',
|
||||
'etk'
|
||||
])
|
||||
return True
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
//! [audio_river_sample_read_all]
|
||||
@ -10,14 +10,16 @@
|
||||
#include <audio/river/Manager.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
//! [audio_river_sample_include]
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <etk/etk.hpp>
|
||||
#include <thread>
|
||||
#include <ethread/Thread.hpp>
|
||||
#include <ethread/tools.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
#include <etk/uri/uri.hpp>
|
||||
|
||||
|
||||
|
||||
//! [audio_river_sample_read_config_file]
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
@ -41,38 +43,38 @@ void onDataReceived(const void* _data,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map,
|
||||
etk::FSNode* _outputNode) {
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
ememory::SharedPtr<etk::io::Interface> _fileIO) {
|
||||
if ( _format != audio::format_int16
|
||||
&& _format != audio::format_float) {
|
||||
std::cout << "[ERROR] call wrong type ... (need int16_t.float)" << std::endl;
|
||||
TEST_ERROR("Call wrong type ... (need int16_t.float)");
|
||||
return;
|
||||
}
|
||||
//! [audio_river_sample_callback_implement]
|
||||
if (_outputNode->fileIsOpen() == false) {
|
||||
if (_fileIO->isOpen() == 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 += std::abs(data[iii]);
|
||||
value += etk::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
std::cout << "Get data ... average=" << int32_t(value) << std::endl;
|
||||
TEST_PRINT("Get data ... average=" << int32_t(value));
|
||||
} else {
|
||||
// get the curent power of the signal.
|
||||
const float* data = static_cast<const float*>(_data);
|
||||
float value = 0;
|
||||
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
|
||||
value += std::abs(data[iii]);
|
||||
value += etk::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
std::cout << "Get data ... average=" << float(value) << std::endl;
|
||||
TEST_PRINT("Get data ... average=" << float(value));
|
||||
}
|
||||
} else {
|
||||
// just write data
|
||||
//std::cout << "Get data ... chunks=" << _nbChunk << " time=" << _time << std::endl;
|
||||
_outputNode->fileWrite(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
|
||||
TEST_VERBOSE("Get data ... chunks=" << _nbChunk << " time=" << _time);
|
||||
_fileIO->write(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,27 +84,27 @@ int main(int _argc, const char **_argv) {
|
||||
etk::init(_argc, _argv);
|
||||
//! [audio_river_sample_init]
|
||||
// local parameter:
|
||||
std::string configFile;
|
||||
std::string ioName="microphone";
|
||||
std::string outputFileName = "";
|
||||
etk::String configFile;
|
||||
etk::String ioName="microphone";
|
||||
etk::Path outputFileName = "";
|
||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||
std::string data = _argv[iii];
|
||||
etk::String data = _argv[iii];
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
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;
|
||||
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");
|
||||
exit(0);
|
||||
} else if (etk::start_with(data, "--conf=") == true) {
|
||||
configFile = std::string(data.begin()+7, data.end());
|
||||
std::cout << "Select config: " << configFile << std::endl;
|
||||
configFile = etk::String(data.begin()+7, data.end());
|
||||
TEST_PRINT("Select config: " << configFile);
|
||||
} else if (etk::start_with(data, "--io=") == true) {
|
||||
ioName = std::string(data.begin()+5, data.end());
|
||||
std::cout << "Select io: " << ioName << std::endl;
|
||||
ioName = etk::String(data.begin()+5, data.end());
|
||||
TEST_PRINT("Select io: " << ioName);
|
||||
} else if (etk::start_with(data, "--file=") == true) {
|
||||
outputFileName = std::string(data.begin()+7, data.end());
|
||||
std::cout << "Select output file name: " << outputFileName << std::endl;
|
||||
outputFileName = etk::String(data.begin()+7, data.end());
|
||||
TEST_PRINT("Select output file name: " << outputFileName);
|
||||
}
|
||||
}
|
||||
// initialize river interface
|
||||
@ -120,36 +122,35 @@ int main(int _argc, const char **_argv) {
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
//Get the generic input:
|
||||
interface = manager->createInput(48000,
|
||||
std::vector<audio::channel>(),
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
ioName);
|
||||
if(interface == nullptr) {
|
||||
std::cout << "nullptr interface" << std::endl;
|
||||
if(interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return -1;
|
||||
}
|
||||
//! [audio_river_sample_create_read_interface]
|
||||
etk::FSNode outputNode;
|
||||
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(outputFileName);
|
||||
// open output file if needed:
|
||||
if (outputFileName != "") {
|
||||
outputNode.setName(outputFileName);
|
||||
outputNode.fileOpenWrite();
|
||||
if (outputFileName.isEmpty() == false) {
|
||||
fileIO->open(etk::io::OpenMode::Write);
|
||||
}
|
||||
//! [audio_river_sample_set_callback]
|
||||
// set callback mode ...
|
||||
interface->setInputCallback(std::bind(&onDataReceived,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3,
|
||||
std::placeholders::_4,
|
||||
std::placeholders::_5,
|
||||
std::placeholders::_6,
|
||||
&outputNode));
|
||||
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);
|
||||
});
|
||||
//! [audio_river_sample_set_callback]
|
||||
//! [audio_river_sample_read_start_stop]
|
||||
// start the stream
|
||||
interface->start();
|
||||
// wait 10 second ...
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
//! [audio_river_sample_read_start_stop]
|
||||
@ -160,7 +161,7 @@ int main(int _argc, const char **_argv) {
|
||||
//! [audio_river_sample_read_reset]
|
||||
// close the output file
|
||||
if (outputFileName != "") {
|
||||
outputNode.fileClose();
|
||||
fileIO->close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.debug as debug
|
||||
import realog.debug as debug
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ def get_desc():
|
||||
return "Write some data"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
return "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
@ -30,6 +30,7 @@ def configure(target, my_module):
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio-river',
|
||||
'test-debug',
|
||||
'etk'
|
||||
])
|
||||
return True
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
//! [audio_river_sample_write_all]
|
||||
@ -10,17 +10,19 @@
|
||||
#include <audio/river/Manager.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <etk/etk.hpp>
|
||||
#include <thread>
|
||||
#include <ethread/Thread.hpp>
|
||||
#include <ethread/tools.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
|
||||
|
||||
//! [audio_river_sample_write_config_file]
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'alsa',\n"
|
||||
" name:'hw:0,0',\n"
|
||||
" name:'hw:0,3',\n"
|
||||
" },\n"
|
||||
" frequency:48000,\n"
|
||||
//" channel-map:['front-left', 'front-right', 'rear-left', 'rear-right'],\n"
|
||||
@ -39,14 +41,14 @@ void onDataNeeded(void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
uint32_t _sampleRate,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
static double phase[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
if (_format != audio::format_int16) {
|
||||
std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl;
|
||||
TEST_ERROR("Call wrong type ... (need int16_t)");
|
||||
}
|
||||
//std::cout << "Map " << _map << std::endl;
|
||||
//TEST_VERBOSE("Map " << _map);
|
||||
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++) {
|
||||
@ -65,11 +67,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) {
|
||||
std::string data = _argv[iii];
|
||||
etk::String data = _argv[iii];
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
std::cout << "Help : " << std::endl;
|
||||
std::cout << " ./xxx ---" << std::endl;
|
||||
TEST_PRINT("Help:");
|
||||
TEST_PRINT(" ./xxx ---");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
@ -82,28 +84,29 @@ int main(int _argc, const char **_argv) {
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
//Get the generic input:
|
||||
interface = manager->createOutput(48000,
|
||||
std::vector<audio::channel>(),
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(interface == nullptr) {
|
||||
std::cout << "nullptr interface" << std::endl;
|
||||
if(interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return -1;
|
||||
}
|
||||
//! [audio_river_sample_create_write_interface]
|
||||
//! [audio_river_sample_set_callback]
|
||||
// set callback mode ...
|
||||
interface->setOutputCallback(std::bind(&onDataNeeded,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3,
|
||||
std::placeholders::_4,
|
||||
std::placeholders::_5,
|
||||
std::placeholders::_6));
|
||||
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);
|
||||
});
|
||||
//! [audio_river_sample_set_callback]
|
||||
// start the stream
|
||||
interface->start();
|
||||
// wait 10 second ...
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
// remove interface and manager.
|
||||
|
@ -1,25 +1,25 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <test-debug/debug.hpp>
|
||||
|
||||
#define TEST_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \
|
||||
do { \
|
||||
static FILE *pointerOnFile = nullptr; \
|
||||
static FILE *pointerOnFile = null; \
|
||||
static bool errorOpen = false; \
|
||||
if (pointerOnFile == nullptr) { \
|
||||
if (pointerOnFile == null) { \
|
||||
TEST_WARNING("open file '" << fileName << "' type=" << #type); \
|
||||
pointerOnFile = fopen(fileName,"w"); \
|
||||
if ( errorOpen == false \
|
||||
&& pointerOnFile == nullptr) { \
|
||||
&& pointerOnFile == null) { \
|
||||
TEST_ERROR("ERROR OPEN file ... '" << fileName << "' type=" << #type); \
|
||||
errorOpen=true; \
|
||||
} \
|
||||
} \
|
||||
if (pointerOnFile != nullptr) { \
|
||||
if (pointerOnFile != null) { \
|
||||
fwrite((dataPointer), sizeof(type), (nbElement), pointerOnFile); \
|
||||
/* fflush(pointerOnFile);*/ \
|
||||
} \
|
||||
@ -30,30 +30,18 @@
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/Manager.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <etest/etest.hpp>
|
||||
#include <etk/etk.hpp>
|
||||
#include <etk/os/FSNode.hpp>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
extern "C" {
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
#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"
|
||||
#include <ethread/Thread.hpp>
|
||||
|
||||
int main(int _argc, const char** _argv) {
|
||||
// init Google test :
|
||||
::testing::InitGoogleTest(&_argc, const_cast<char **>(_argv));
|
||||
// the only one init for etk:
|
||||
etk::init(_argc, _argv);
|
||||
etest::init(_argc, _argv);
|
||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||
std::string data = _argv[iii];
|
||||
etk::String data = _argv[iii];
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
TEST_PRINT("Help : ");
|
||||
|
@ -1,11 +1,21 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 {
|
||||
|
||||
@ -16,35 +26,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 std::string& _input, const std::string& _output) :
|
||||
Linker(ememory::SharedPtr<audio::river::Manager> _manager, const etk::String& _input, const etk::String& _output) :
|
||||
m_manager(_manager) {
|
||||
//Set stereo output:
|
||||
std::vector<audio::channel> channelMap;
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
if (false) { //"speaker" == _output) {
|
||||
channelMap.push_back(audio::channel_frontCenter);
|
||||
channelMap.pushBack(audio::channel_frontCenter);
|
||||
} else {
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
}
|
||||
m_buffer.setCapacity(std::chrono::milliseconds(2000), sizeof(int16_t)*channelMap.size(), 48000);
|
||||
m_buffer.setCapacity(echrono::milliseconds(2000), sizeof(int16_t)*channelMap.size(), 48000);
|
||||
|
||||
m_interfaceOut = m_manager->createOutput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
_output);
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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->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->addVolumeGroup("FLOW");
|
||||
if ("speaker" == _output) {
|
||||
m_interfaceOut->setParameter("volume", "FLOW", "0dB");
|
||||
@ -54,19 +64,19 @@ namespace river_test_aec {
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
_input);
|
||||
if(m_interfaceIn == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
|
||||
}
|
||||
void onDataNeeded(void* _data,
|
||||
@ -74,7 +84,7 @@ namespace river_test_aec {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
if (_format != audio::format_int16) {
|
||||
TEST_ERROR("call wrong type ... (need int16_t)");
|
||||
}
|
||||
@ -85,31 +95,31 @@ namespace river_test_aec {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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 == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interfaceOut->start();
|
||||
m_interfaceIn->start();
|
||||
}
|
||||
void stop() {
|
||||
if(m_interfaceIn == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_manager->generateDotAll("activeProcess.dot");
|
||||
@ -118,7 +128,7 @@ namespace river_test_aec {
|
||||
}
|
||||
};
|
||||
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -203,7 +213,7 @@ namespace river_test_aec {
|
||||
ememory::SharedPtr<Linker> processLink2 = ememory::makeShared<Linker>(manager, "microphone", "speaker-test");
|
||||
processLink1->start();
|
||||
processLink2->start();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(20));
|
||||
ethread::sleepMilliSeconds(1000*(20));
|
||||
processLink1->stop();
|
||||
processLink2->stop();
|
||||
|
@ -1,11 +1,21 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 {
|
||||
@ -17,12 +27,12 @@ namespace river_test_echo_delay {
|
||||
double m_phase;
|
||||
double m_freq;
|
||||
int32_t m_nextSampleCount;
|
||||
std::chrono::milliseconds m_delayBetweenEvent;
|
||||
echrono::milliseconds m_delayBetweenEvent;
|
||||
audio::Time m_nextTick;
|
||||
audio::Time m_currentTick;
|
||||
int32_t m_stateFB;
|
||||
int32_t m_stateMic;
|
||||
std::vector<uint64_t> m_delayListMic;
|
||||
etk::Vector<uint64_t> m_delayListMic;
|
||||
bool m_estimateVolumeInput;
|
||||
int16_t m_volumeInputMax;
|
||||
int16_t m_volumeInputMin;
|
||||
@ -39,62 +49,62 @@ namespace river_test_echo_delay {
|
||||
m_estimateVolumeInput(true),
|
||||
m_gain(-40) {
|
||||
//Set stereo output:
|
||||
std::vector<audio::channel> channelMap;
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
m_interfaceOut = m_manager->createOutput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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->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->addVolumeGroup("FLOW");
|
||||
m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB");
|
||||
m_interfaceOut->setParameter("volume", "FLOW", etk::toString(m_gain) + "dB");
|
||||
|
||||
m_interfaceIn = m_manager->createInput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
"microphone");
|
||||
if(m_interfaceIn == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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_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_interfaceFB = m_manager->createFeedback(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(m_interfaceFB == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceFB == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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_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_manager->generateDotAll("activeProcess.dot");
|
||||
}
|
||||
@ -103,7 +113,7 @@ namespace river_test_echo_delay {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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) {
|
||||
@ -127,7 +137,7 @@ namespace river_test_echo_delay {
|
||||
}
|
||||
if (m_nextTick == audio::Time()) {
|
||||
m_nextTick = _time + m_delayBetweenEvent;
|
||||
m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000;
|
||||
m_nextSampleCount = m_delayBetweenEvent.get()*int64_t(_frequency)/1000;
|
||||
m_phase = -1;
|
||||
}
|
||||
//TEST_INFO("sample : " << m_nextSampleCount);
|
||||
@ -136,7 +146,7 @@ namespace river_test_echo_delay {
|
||||
m_nextSampleCount--;
|
||||
} else {
|
||||
m_phase = 0;
|
||||
m_nextSampleCount = m_delayBetweenEvent.count()*int64_t(_frequency)/1000;
|
||||
m_nextSampleCount = m_delayBetweenEvent.get()*int64_t(_frequency)/1000;
|
||||
m_currentTick = m_nextTick;
|
||||
m_nextTick += m_delayBetweenEvent;
|
||||
}
|
||||
@ -186,11 +196,11 @@ namespace river_test_echo_delay {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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 {
|
||||
@ -216,7 +226,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).count())/1000.0f << "µs");
|
||||
TEST_WARNING("FB: 1 time detected: " << time << " delay = " << float((time-m_currentTick).get())/1000.0f << "µs");
|
||||
}
|
||||
} else if (m_stateFB == 2) {
|
||||
// inverse phase
|
||||
@ -226,7 +236,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).count())/1000.0f << "µs");
|
||||
TEST_WARNING("FB: 2 time detected: " << time << " delay = " << float((time-m_currentTick).get())/1000.0f << "µs");
|
||||
}
|
||||
} else if (m_stateFB == 3) {
|
||||
// TODO : Detect the pic ...
|
||||
@ -241,11 +251,11 @@ namespace river_test_echo_delay {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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 ++;
|
||||
@ -253,8 +263,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 = std::max(int16_t(data[iii]), m_volumeInputMax);
|
||||
m_volumeInputMin = std::min(int16_t(data[iii]), m_volumeInputMin);
|
||||
m_volumeInputMax = etk::max(int16_t(data[iii]), m_volumeInputMax);
|
||||
m_volumeInputMin = etk::min(int16_t(data[iii]), m_volumeInputMin);
|
||||
}
|
||||
if (m_stateMic == 40) {
|
||||
m_volumeInputMax *= 2;
|
||||
@ -265,8 +275,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 = std::max(int16_t(data[iii]), valueMax);
|
||||
valueMin = std::min(int16_t(data[iii]), valueMin);
|
||||
valueMax = etk::max(int16_t(data[iii]), valueMax);
|
||||
valueMin = etk::min(int16_t(data[iii]), valueMin);
|
||||
}
|
||||
if ( valueMax > m_volumeInputMax
|
||||
&& valueMin < m_volumeInputMin
|
||||
@ -277,8 +287,8 @@ namespace river_test_echo_delay {
|
||||
)
|
||||
) {
|
||||
m_gain += 3.0f;
|
||||
m_gain = std::min(m_gain, 0.0f);
|
||||
m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB");
|
||||
m_gain = etk::min(m_gain, 0.0f);
|
||||
m_interfaceOut->setParameter("volume", "FLOW", etk::toString(m_gain) + "dB");
|
||||
TEST_INFO("Set detection volume : " << m_gain << " m_stateMic=" << m_stateMic);
|
||||
m_stateMic = 3;
|
||||
m_phase = -1;
|
||||
@ -291,8 +301,8 @@ namespace river_test_echo_delay {
|
||||
}
|
||||
// just update volume
|
||||
m_gain += 1.0f;
|
||||
m_gain = std::min(m_gain, 0.0f);
|
||||
m_interfaceOut->setParameter("volume", "FLOW", etk::to_string(m_gain) + "dB");
|
||||
m_gain = etk::min(m_gain, 0.0f);
|
||||
m_interfaceOut->setParameter("volume", "FLOW", etk::toString(m_gain) + "dB");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -318,9 +328,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.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());
|
||||
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());
|
||||
}
|
||||
} else if (m_stateMic == 2) {
|
||||
// inverse phase
|
||||
@ -331,9 +341,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.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());
|
||||
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());
|
||||
}
|
||||
} else if (m_stateMic == 3) {
|
||||
// TODO : Detect the pic ...
|
||||
@ -344,25 +354,25 @@ namespace river_test_echo_delay {
|
||||
}
|
||||
}
|
||||
void run() {
|
||||
if(m_interfaceIn == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
if(m_interfaceFB == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceFB == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interfaceOut->start();
|
||||
m_interfaceIn->start();
|
||||
//m_interfaceFB->start();
|
||||
while (m_estimateVolumeInput == true) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
ethread::sleepMilliSeconds((10));
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
//m_interfaceFB->stop();
|
||||
m_interfaceIn->stop();
|
||||
m_interfaceOut->stop();
|
||||
@ -379,7 +389,7 @@ namespace river_test_echo_delay {
|
||||
}
|
||||
};
|
||||
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -418,7 +428,7 @@ namespace river_test_echo_delay {
|
||||
ememory::SharedPtr<TestClass> process = ememory::makeShared<TestClass>(manager);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
};
|
@ -1,12 +1,24 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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_format {
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -41,17 +53,17 @@ namespace river_test_format {
|
||||
m_nbChannels(_nbChannels),
|
||||
m_generateFreq(550.0f) {
|
||||
//Set stereo output:
|
||||
std::vector<audio::channel> channelMap;
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
if (m_nbChannels == 1) {
|
||||
channelMap.push_back(audio::channel_frontCenter);
|
||||
channelMap.pushBack(audio::channel_frontCenter);
|
||||
} else if (m_nbChannels == 2) {
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
} else if (m_nbChannels == 4) {
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
channelMap.push_back(audio::channel_rearLeft);
|
||||
channelMap.push_back(audio::channel_rearRight);
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
channelMap.pushBack(audio::channel_rearLeft);
|
||||
channelMap.pushBack(audio::channel_rearRight);
|
||||
} else {
|
||||
TEST_ERROR("Can not generate with channel != 1,2,4");
|
||||
return;
|
||||
@ -61,26 +73,26 @@ namespace river_test_format {
|
||||
_format,
|
||||
"speaker",
|
||||
"WriteModeCallbackType");
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
}
|
||||
void onDataNeeded(void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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) {
|
||||
@ -130,108 +142,78 @@ namespace river_test_format {
|
||||
}
|
||||
}
|
||||
void run() {
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->start();
|
||||
// wait 2 second ...
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
ethread::sleepMilliSeconds(1000*(1));
|
||||
m_interface->stop();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
ethread::sleepMilliSeconds((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};
|
||||
|
||||
|
||||
class testResampling : public ::testing::TestWithParam<float> {};
|
||||
TEST_P(testResampling, base) {
|
||||
TEST(testResampling, 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, GetParam(), 2, audio::format_int16);
|
||||
for (auto itFrequency: listFreq) {
|
||||
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, itFrequency, 2, audio::format_int16);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
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));
|
||||
|
||||
|
||||
class testFormat : public ::testing::TestWithParam<audio::format> {};
|
||||
TEST_P(testFormat, base) {
|
||||
TEST(testFormat, 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, 2, GetParam());
|
||||
for (auto itFormat: listFormat) {
|
||||
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, 2, itFormat);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((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) {
|
||||
TEST(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);
|
||||
for (auto itChannel: listChannel) {
|
||||
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, itChannel, audio::format_int16);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((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)");
|
||||
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]);
|
||||
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);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
}
|
||||
}
|
||||
}
|
||||
audio::river::unInit();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,20 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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_muxer {
|
||||
class TestClass {
|
||||
@ -18,47 +27,47 @@ namespace river_test_muxer {
|
||||
TestClass(ememory::SharedPtr<audio::river::Manager> _manager) :
|
||||
m_manager(_manager),
|
||||
m_phase(0) {
|
||||
std::vector<audio::channel> channelMap;
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
m_interfaceOut = m_manager->createOutput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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->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->addVolumeGroup("FLOW");
|
||||
//m_interfaceOut->setParameter("volume", "FLOW", "-6dB");
|
||||
|
||||
//Set stereo output:
|
||||
m_interfaceIn = m_manager->createInput(48000,
|
||||
std::vector<audio::channel>(),
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"microphone-muxed");
|
||||
if(m_interfaceIn == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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_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_manager->generateDotAll("activeProcess.dot");
|
||||
}
|
||||
|
||||
@ -67,7 +76,7 @@ namespace river_test_muxer {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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++) {
|
||||
@ -85,31 +94,31 @@ namespace river_test_muxer {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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 == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceIn == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
if(m_interfaceOut == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interfaceOut == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interfaceOut->start();
|
||||
m_interfaceIn->start();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
m_interfaceIn->stop();
|
||||
m_interfaceOut->stop();
|
||||
}
|
||||
};
|
||||
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -168,7 +177,7 @@ namespace river_test_muxer {
|
||||
ememory::SharedPtr<TestClass> process = ememory::makeShared<TestClass>(manager);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
};
|
@ -1,9 +1,21 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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_playback_callback {
|
||||
|
||||
@ -13,37 +25,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 std::string& _io="speaker") :
|
||||
testOutCallback(ememory::SharedPtr<audio::river::Manager> _manager, const etk::String& _io="speaker") :
|
||||
m_manager(_manager),
|
||||
m_phase(0) {
|
||||
//Set stereo output:
|
||||
std::vector<audio::channel> channelMap;
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
m_interface = m_manager->createOutput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
_io);
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
}
|
||||
void onDataNeeded(void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
if (_format != audio::format_int16) {
|
||||
TEST_ERROR("call wrong type ... (need int16_t)");
|
||||
}
|
||||
@ -60,18 +72,18 @@ namespace river_test_playback_callback {
|
||||
}
|
||||
}
|
||||
void run() {
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->start();
|
||||
// wait 2 second ...
|
||||
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||
ethread::sleepMilliSeconds(1000*(2));
|
||||
m_interface->stop();
|
||||
}
|
||||
};
|
||||
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -94,10 +106,10 @@ namespace river_test_playback_callback {
|
||||
|
||||
TEST_INFO("test output (callback mode)");
|
||||
ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker");
|
||||
ASSERT_NE(process, nullptr);
|
||||
ASSERT_NE(process, null);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
||||
@ -110,7 +122,7 @@ namespace river_test_playback_callback {
|
||||
ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker-pulse");
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
||||
@ -123,7 +135,7 @@ namespace river_test_playback_callback {
|
||||
ememory::SharedPtr<testOutCallback> process = ememory::makeShared<testOutCallback>(manager, "speaker-jack");
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
};
|
@ -1,12 +1,24 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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_playback_write {
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -24,32 +36,32 @@ namespace river_test_playback_write {
|
||||
|
||||
class testOutWrite {
|
||||
public:
|
||||
std::vector<audio::channel> m_channelMap;
|
||||
etk::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.push_back(audio::channel_frontLeft);
|
||||
m_channelMap.push_back(audio::channel_frontRight);
|
||||
m_channelMap.pushBack(audio::channel_frontLeft);
|
||||
m_channelMap.pushBack(audio::channel_frontRight);
|
||||
m_interface = m_manager->createOutput(48000,
|
||||
m_channelMap,
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->setReadwrite();
|
||||
}
|
||||
void run() {
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
double phase=0;
|
||||
std::vector<int16_t> data;
|
||||
etk::Vector<int16_t> data;
|
||||
data.resize(1024*m_channelMap.size());
|
||||
double baseCycle = 2.0*M_PI/48000.0 * 440.0;
|
||||
// start fill buffer
|
||||
@ -78,7 +90,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 ...
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(15));
|
||||
ethread::sleepMilliSeconds((15));
|
||||
}
|
||||
m_interface->stop();
|
||||
}
|
||||
@ -93,7 +105,7 @@ namespace river_test_playback_write {
|
||||
ememory::SharedPtr<testOutWrite> process = ememory::makeShared<testOutWrite>(manager);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
||||
@ -106,36 +118,36 @@ namespace river_test_playback_write {
|
||||
testOutWriteCallback(ememory::SharedPtr<audio::river::Manager> _manager) :
|
||||
m_manager(_manager),
|
||||
m_phase(0) {
|
||||
std::vector<audio::channel> channelMap;
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
//Set stereo output:
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
m_interface = m_manager->createOutput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->setReadwrite();
|
||||
m_interface->setWriteCallback(std::bind(&testOutWriteCallback::onDataNeeded,
|
||||
this,
|
||||
std::placeholders::_1,
|
||||
std::placeholders::_2,
|
||||
std::placeholders::_3,
|
||||
std::placeholders::_4,
|
||||
std::placeholders::_5));
|
||||
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);
|
||||
});
|
||||
}
|
||||
void onDataNeeded(const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
if (_format != audio::format_int16) {
|
||||
TEST_ERROR("call wrong type ... (need int16_t)");
|
||||
}
|
||||
std::vector<int16_t> data;
|
||||
etk::Vector<int16_t> data;
|
||||
data.resize(1024*_map.size());
|
||||
double baseCycle = 2.0*M_PI/48000.0 * 440.0;
|
||||
// start fill buffer
|
||||
@ -151,12 +163,12 @@ namespace river_test_playback_write {
|
||||
m_interface->write(&data[0], data.size()/_map.size());
|
||||
}
|
||||
void run() {
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->start();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
ethread::sleepMilliSeconds(1000*(1));
|
||||
m_interface->stop();
|
||||
}
|
||||
};
|
||||
@ -170,7 +182,7 @@ namespace river_test_playback_write {
|
||||
ememory::SharedPtr<testOutWriteCallback> process = ememory::makeShared<testOutWriteCallback>(manager);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
@ -1,14 +1,23 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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_record_callback {
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
@ -28,54 +37,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 std::string& _input="microphone") :
|
||||
testInCallback(ememory::SharedPtr<audio::river::Manager> _manager, const etk::String& _input="microphone") :
|
||||
m_manager(_manager) {
|
||||
//Set stereo output:
|
||||
std::vector<audio::channel> channelMap;
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
m_interface = m_manager->createInput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
_input);
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
}
|
||||
void onDataReceived(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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 += std::abs(data[iii]);
|
||||
value += etk::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
TEST_INFO("Get data ... average=" << int32_t(value));
|
||||
}
|
||||
void run() {
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->start();
|
||||
// wait 2 second ...
|
||||
std::this_thread::sleep_for(std::chrono::seconds(20));
|
||||
ethread::sleepMilliSeconds(1000*(20));
|
||||
m_interface->stop();
|
||||
}
|
||||
};
|
||||
@ -88,7 +97,7 @@ namespace river_test_record_callback {
|
||||
ememory::SharedPtr<testInCallback> process = ememory::makeShared<testInCallback>(manager);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
22
test/testRecordRead.cpp
Normal file
22
test/testRecordRead.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
/** @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 {
|
||||
|
||||
};
|
||||
|
@ -1,11 +0,0 @@
|
||||
/** @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 {
|
||||
|
||||
};
|
||||
|
@ -1,12 +1,24 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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_volume {
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@ -32,26 +44,26 @@ namespace river_test_volume {
|
||||
m_manager(_manager),
|
||||
m_phase(0) {
|
||||
//Set stereo output:
|
||||
std::vector<audio::channel> channelMap;
|
||||
channelMap.push_back(audio::channel_frontLeft);
|
||||
channelMap.push_back(audio::channel_frontRight);
|
||||
etk::Vector<audio::channel> channelMap;
|
||||
channelMap.pushBack(audio::channel_frontLeft);
|
||||
channelMap.pushBack(audio::channel_frontRight);
|
||||
m_interface = m_manager->createOutput(48000,
|
||||
channelMap,
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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->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->addVolumeGroup("MEDIA");
|
||||
m_interface->addVolumeGroup("FLOW");
|
||||
}
|
||||
@ -60,7 +72,7 @@ namespace river_test_volume {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
const etk::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++) {
|
||||
@ -74,45 +86,45 @@ namespace river_test_volume {
|
||||
}
|
||||
}
|
||||
void run() {
|
||||
if(m_interface == nullptr) {
|
||||
TEST_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
m_interface->start();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
ethread::sleepMilliSeconds(1000*(1));
|
||||
m_interface->setParameter("volume", "FLOW", "-3dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-6dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-9dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-12dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-3dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "3dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "6dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "9dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "0dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_manager->setVolume("MASTER", -3.0f);
|
||||
TEST_INFO("get volume MASTER: " << m_manager->getVolume("MASTER") );
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_manager->setVolume("MEDIA", -3.0f);
|
||||
TEST_INFO("get volume MEDIA: " << m_manager->getVolume("MEDIA") );
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
ethread::sleepMilliSeconds(1000*(1));
|
||||
m_interface->stop();
|
||||
}
|
||||
};
|
||||
@ -124,7 +136,7 @@ namespace river_test_volume {
|
||||
ememory::SharedPtr<testCallbackVolume> process = ememory::makeShared<testCallbackVolume>(manager);
|
||||
process->run();
|
||||
process.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
0.4.0
|
||||
1.0.0
|
@ -1,12 +1,13 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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;
|
||||
|
||||
@ -37,15 +38,15 @@ void audio::river::widget::TemporalViewer::onDataReceived(const void* _data,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (_format != audio::format_float) {
|
||||
std::cout << "[ERROR] call wrong type ... (need int16_t)" << std::endl;
|
||||
ARW_ERROR("call wrong type ... (need int16_t)");
|
||||
}
|
||||
// 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.push_back(data[iii]);
|
||||
m_data.pushBack(data[iii]);
|
||||
}
|
||||
/*
|
||||
if (m_data.size()>m_sampleRate*nbSecond*10) {
|
||||
@ -56,35 +57,35 @@ void audio::river::widget::TemporalViewer::onDataReceived(const void* _data,
|
||||
}
|
||||
|
||||
void audio::river::widget::TemporalViewer::recordToggle() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (m_interface == nullptr) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (m_interface == null) {
|
||||
//Get the generic input:
|
||||
std::vector<audio::channel> channel;
|
||||
channel.push_back(audio::channel_frontLeft);
|
||||
etk::Vector<audio::channel> channel;
|
||||
channel.pushBack(audio::channel_frontLeft);
|
||||
m_interface = m_manager->createInput(m_sampleRate,
|
||||
channel,
|
||||
audio::format_float,
|
||||
"microphone");
|
||||
if(m_interface == nullptr) {
|
||||
ARW_ERROR("nullptr interface");
|
||||
if(m_interface == null) {
|
||||
ARW_ERROR("null interface");
|
||||
return;
|
||||
}
|
||||
// set callback mode ...
|
||||
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));
|
||||
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);
|
||||
});
|
||||
// start the stream
|
||||
m_interface->start();
|
||||
periodicCallEnable();
|
||||
m_PCH = getObjectManager().periodicCall.connect(this, &audio::river::widget::TemporalViewer::periodicCall);
|
||||
} else {
|
||||
m_interface->stop();
|
||||
m_interface.reset();
|
||||
periodicCallDisable();
|
||||
m_PCH.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,14 +105,14 @@ void audio::river::widget::TemporalViewer::onRegenerateDisplay() {
|
||||
m_draw.setColor(etk::color::black);
|
||||
m_draw.setPos(vec2(0,0));
|
||||
m_draw.rectangleWidth(m_size);
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock 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;
|
||||
std::vector<float> list;
|
||||
etk::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;
|
||||
@ -119,7 +120,7 @@ void audio::river::widget::TemporalViewer::onRegenerateDisplay() {
|
||||
int32_t id = kkk/step;
|
||||
if (id < list.size()) {
|
||||
if (kkk < m_data.size()) {
|
||||
list[id] = std::max(list[id],m_data[kkk]);
|
||||
list[id] = etk::max(list[id],m_data[kkk]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,7 +144,7 @@ void audio::river::widget::TemporalViewer::onRegenerateDisplay() {
|
||||
|
||||
|
||||
void audio::river::widget::TemporalViewer::periodicCall(const ewol::event::Time& _event) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
int32_t nbSampleDelta = _event.getDeltaCall() * float(m_sampleRate);
|
||||
if (m_data.size()>m_sampleRate*nbSecond) {
|
||||
if (nbSampleDelta < m_data.size()) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL 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 <mutex>
|
||||
#include <ethread/Mutex.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace widget {
|
||||
class TemporalViewer : public ewol::Widget {
|
||||
private:
|
||||
mutable std::mutex m_mutex;
|
||||
mutable ethread::Mutex m_mutex;
|
||||
private:
|
||||
ewol::compositing::Drawing m_draw; //!< drawing instance
|
||||
protected:
|
||||
@ -34,13 +34,19 @@ namespace audio {
|
||||
// ...
|
||||
}
|
||||
private:
|
||||
std::vector<float> m_data;
|
||||
etk::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;
|
||||
@ -50,7 +56,7 @@ namespace audio {
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map);
|
||||
const etk::Vector<audio::channel>& _map);
|
||||
int32_t m_sampleRate;
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/widget/debug.hpp>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.debug as debug
|
||||
import realog.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 "APACHE-2"
|
||||
return "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
Loading…
x
Reference in New Issue
Block a user