Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
f5be7b35a8 | |||
71e6089a40 | |||
6dfa58dedd | |||
121602813e | |||
b53e67044f | |||
715598a0ae | |||
1773297dab | |||
965df2ee2f | |||
9a21d57c1f | |||
be4f6217d0 | |||
38c9a69e1e | |||
0c57614b64 | |||
c3d78cf387 | |||
2ee24d5baa | |||
0e175ad23c | |||
c3b5ba2bdd | |||
ddc9150179 | |||
5fe729f4dc | |||
8fef74e061 | |||
b114de5f1d | |||
d13298acf9 | |||
a5ca43b7dd | |||
abc2ce6a49 | |||
6a2e12c2ad | |||
7d38eb190d | |||
bc47714cff | |||
6ecf73bb11 | |||
417845abc2 | |||
5acf1ead90 | |||
e80670fd0c | |||
77241b828d |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,8 @@
|
||||
__pycache__
|
||||
.bck
|
||||
out
|
||||
target
|
||||
build
|
||||
###################################
|
||||
# backup files
|
||||
###################################
|
||||
|
96
.travis.yml
96
.travis.yml
@@ -1,11 +1,7 @@
|
||||
language:
|
||||
- cpp
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
branches:
|
||||
only:
|
||||
@@ -18,39 +14,83 @@ addons:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.9
|
||||
- expect
|
||||
- binutils-mingw-w64-x86-64 # 64bit MinGW
|
||||
- gcc-mingw-w64-x86-64
|
||||
- g++-mingw-w64-x86-64
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: CONF=release BUILDER=gcc TARGET=Linux TAG=Linux COMPILATOR_OPTION="--compilator-version=4.9" GCOV=--gcov
|
||||
compiler: gcc
|
||||
- os: linux
|
||||
env: CONF=debug BUILDER=clang TARGET=Linux
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env: CONF=release BUILDER=gcc TARGET=Windows TAG=Mingw
|
||||
compiler: x86_64-w64-mingw32-gcc
|
||||
- os: linux
|
||||
env: CONF=release BUILDER=gcc TARGET=Android TAG=Android DISABLE_PACKAGE=-p
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
env: CONF=release BUILDER=clang TARGET=MacOs TAG=MacOs
|
||||
compiler: clang
|
||||
- os: osx
|
||||
env: CONF=release BUILDER=clang TARGET=IOs TAG=IOs
|
||||
compiler: clang
|
||||
|
||||
|
||||
install:
|
||||
- cd ..
|
||||
- pip install --user lutin
|
||||
|
||||
env:
|
||||
- CONF=debug BOARD=Linux BUILDER=clang GCOV=
|
||||
- CONF=release BOARD=Linux BUILDER=clang GCOV=
|
||||
- CONF=debug BOARD=Linux BUILDER=gcc GCOV=
|
||||
- CONF=release BOARD=Linux BUILDER=gcc GCOV=
|
||||
- CONF=debug BOARD=Linux BUILDER=gcc GCOV=--gcov
|
||||
- if [ "$TAG" == "Android" ]; then
|
||||
git clone --depth 1 --branch master https://github.com/HeeroYui/android-download-tool;
|
||||
./android-download-tool/dl-android.sh;
|
||||
fi
|
||||
- git clone --depth 1 --branch master https://github.com/atria-soft/ci.git
|
||||
- cd -
|
||||
|
||||
before_script:
|
||||
- cd ..
|
||||
- wget http://atria-soft.com/ci/coverage_send.py
|
||||
- wget http://atria-soft.com/ci/test_send.py
|
||||
- wget http://atria-soft.com/ci/warning_send.py
|
||||
- git clone https://github.com/atria-soft/etk.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/atria-soft/elog.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/atria-soft/ememory.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/atria-soft/echrono.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/atria-soft/ethread.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/atria-soft/ejson.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/atria-soft/jvm-basics.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/musicdsp/audio.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/musicdsp/audio-algo-drain.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/musicdsp/audio-algo-river.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/musicdsp/audio-algo-speex.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/musicdsp/audio-drain.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/musicdsp/audio-orchestra.git -b $TRAVIS_BRANCH
|
||||
- git clone https://github.com/generic-library/gtest-lutin.git --recursive
|
||||
- git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
|
||||
- git clone https://github.com/generic-library/z-lutin.git --recursive
|
||||
- git clone https://github.com/atria-soft/etk.git
|
||||
- git clone https://github.com/atria-soft/ejson.git
|
||||
- git clone https://github.com/musicdsp/audio.git
|
||||
- git clone https://github.com/musicdsp/audio-algo-drain.git
|
||||
- git clone https://github.com/musicdsp/audio-drain.git
|
||||
- git clone https://github.com/musicdsp/audio-orchestra.git
|
||||
- git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
|
||||
- pwd
|
||||
- ls -l
|
||||
- if [ "$BUILDER" == "gcc" ]; then COMPILATOR_OPTION="--compilator-version=4.9"; else COMPILATOR_OPTION=""; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
export PATH=$PATH:/Users/travis/Library/Python/2.7/bin/;
|
||||
fi
|
||||
- ./ci/build_send.py --tag=$TAG --status=START;
|
||||
|
||||
|
||||
script:
|
||||
- lutin -w -j4 -C -P -c $BUILDER $COMPILATOR_OPTION -m $CONF $GCOV -p audio-river-test
|
||||
# - ./out/Linux_x86_64/$CONF/staging/$BUILDER/audio-river-test/usr/bin/audio-river-test -l6
|
||||
script:
|
||||
- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE audio-river-test*; STATUS=$?
|
||||
- ./ci/build_send.py --tag=$TAG --status="$STATUS";
|
||||
|
||||
after_script:
|
||||
- if [ "$GCOV" != "" ]; then
|
||||
./ci/warning_send.py --find-path ./out/Linux_x86_64/$CONF/build/$BUILDER/audio-river/;
|
||||
fi
|
||||
#- lutin -w -j4 -C -P -t$TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF $GCOV $DISABLE_PACKAGE audio-river-test?run:--elog-level=3 | tee out_test.txt
|
||||
#- if [ "$GCOV" != "" ]; then
|
||||
# ./ci/test_send.py --file=out_test.txt;
|
||||
# lutin -C -P -t $TARGET -c $BUILDER $COMPILATOR_OPTION $BUS -m $CONF -p audio-river?gcov;
|
||||
# ./ci/coverage_send.py --json=out/Linux_x86_64/$CONF/build/$BUILDER/audio-river/audio-river_coverage.json;
|
||||
# fi
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
34
GLD_audio-river-test.json
Normal file
34
GLD_audio-river-test.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"type":"BINARY",
|
||||
"sub-type":"TEST",
|
||||
"group-id":"com.atria-soft",
|
||||
"description":"Multi-nodal audio interface test",
|
||||
"license":"MPL-2",
|
||||
"license-file":"file://LICENSE",
|
||||
"maintainer":"file://authors.txt",
|
||||
"author":"file://authors.txt",
|
||||
"version":"file://version.txt",
|
||||
"code-quality":"MEDIUM",
|
||||
|
||||
"source": [
|
||||
"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"
|
||||
],
|
||||
"compilation-version": {
|
||||
"c++": 2017
|
||||
},
|
||||
"dependency": [
|
||||
"audio-river",
|
||||
"etest",
|
||||
"etk",
|
||||
"test-debug"
|
||||
]
|
||||
}
|
58
GLD_audio-river.json
Normal file
58
GLD_audio-river.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"type":"LIBRARY",
|
||||
"group-id":"com.atria-soft",
|
||||
"description":"Multi-nodal audio interface",
|
||||
"license":"MPL-2",
|
||||
"license-file":"file://LICENSE",
|
||||
"maintainer":"file://authors.txt",
|
||||
"author":"file://authors.txt",
|
||||
"version":"file://version.txt",
|
||||
"code-quality":"MEDIUM",
|
||||
|
||||
"source": [
|
||||
"audio/river/debug.cpp",
|
||||
"audio/river/river.cpp",
|
||||
"audio/river/Manager.cpp",
|
||||
"audio/river/Interface.cpp",
|
||||
"audio/river/io/Group.cpp",
|
||||
"audio/river/io/Node.cpp",
|
||||
"audio/river/io/NodeOrchestra.cpp",
|
||||
"audio/river/io/NodePortAudio.cpp",
|
||||
"audio/river/io/NodeAEC.cpp",
|
||||
"audio/river/io/NodeMuxer.cpp",
|
||||
"audio/river/io/Manager.cpp"
|
||||
],
|
||||
"header": [
|
||||
"audio/river/river.hpp",
|
||||
"audio/river/Manager.hpp",
|
||||
"audio/river/Interface.hpp",
|
||||
"audio/river/io/Group.hpp",
|
||||
"audio/river/io/Node.hpp",
|
||||
"audio/river/io/Manager.hpp"
|
||||
],
|
||||
"path":[
|
||||
"."
|
||||
],
|
||||
"compilation-version": {
|
||||
"c++": 2017
|
||||
},
|
||||
"dependency": [
|
||||
"audio",
|
||||
"audio-drain",
|
||||
"ejson",{
|
||||
"name": "audio-orchestra",
|
||||
"optional": true,
|
||||
"export": true,
|
||||
"flag": {
|
||||
"c++": "-DAUDIO_RIVER_BUILD_ORCHESTRA"
|
||||
}
|
||||
},{
|
||||
"name": "portaudio",
|
||||
"optional": true,
|
||||
"export": true,
|
||||
"flag": {
|
||||
"c++": "-DAUDIO_RIVER_BUILD_PORTAUDIO"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
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.
|
88
README.md
88
README.md
@@ -1,4 +1,88 @@
|
||||
# audio-river
|
||||
(APACHE v2.0) audio: virtualisation of hardware interface
|
||||
audio-river
|
||||
===========
|
||||
|
||||
`audio-river` is a High level hardware audio interface that connect to orchestra (multi-platform backend)
|
||||
|
||||
Release (master)
|
||||
----------------
|
||||
|
||||
[](https://travis-ci.org/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
Developement (dev)
|
||||
------------------
|
||||
|
||||
[](https://travis-ci.org/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
|
||||
Instructions
|
||||
============
|
||||
|
||||
download Build system:
|
||||
----------------------
|
||||
|
||||
sudo pip install lutin
|
||||
sudo pip install pillow
|
||||
|
||||
download the software:
|
||||
----------------------
|
||||
|
||||
mkdir WORKING_DIRECTORY
|
||||
cd WORKING_DIRECTORY
|
||||
git clone https://github.com/atria-soft/etk.git
|
||||
git clone https://github.com/atria-soft/elog.git
|
||||
git clone https://github.com/atria-soft/ememory.git
|
||||
git clone https://github.com/atria-soft/ethread.git
|
||||
git clone https://github.com/atria-soft/ejson.git
|
||||
git clone https://github.com/musicdsp/audio.git
|
||||
git clone https://github.com/musicdsp/audio-algo-drain.git
|
||||
git clone https://github.com/musicdsp/audio-algo-river.git
|
||||
git clone https://github.com/musicdsp/audio-algo-speex.git
|
||||
git clone https://github.com/musicdsp/audio-drain.git
|
||||
git clone https://github.com/musicdsp/audio-orchestra.git
|
||||
git clone https://github.com/musicdsp/audio-river.git
|
||||
git clone https://github.com/generic-library/gtest-lutin.git --recursive
|
||||
git clone https://github.com/generic-library/z-lutin.git --recursive
|
||||
git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
|
||||
|
||||
Compile software:
|
||||
-----------------
|
||||
|
||||
cd WORKING_DIRECTORY
|
||||
lutin -C -P audio-river-test?build?run
|
||||
|
||||
License (MPL v2.0)
|
||||
=====================
|
||||
Copyright audio-river Edouard DUPIN
|
||||
|
||||
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
|
||||
|
||||
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,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
@@ -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.h"
|
||||
#include "Interface.h"
|
||||
#include "io/Node.h"
|
||||
#include <audio/drain/EndPointCallback.h>
|
||||
#include <audio/drain/EndPointWrite.h>
|
||||
#include <audio/drain/EndPointRead.h>
|
||||
#include <audio/drain/Volume.h>
|
||||
#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,
|
||||
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());
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const ememory::SharedPtr<audio::river::io::Node>& _node,
|
||||
const ejson::Object& _config) {
|
||||
ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(ETK_NEW(audio::river::Interface));
|
||||
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) {
|
||||
usleep(1000);
|
||||
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,25 +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 <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/format.h>
|
||||
#include <audio/channel.h>
|
||||
#include <audio/drain/Process.h>
|
||||
#include <audio/drain/EndPointCallback.h>
|
||||
#include <audio/drain/EndPointWrite.h>
|
||||
#include <ejson/ejson.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <audio/Time.h>
|
||||
#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>
|
||||
#include <audio/drain/Process.hpp>
|
||||
#include <audio/drain/EndPointCallback.hpp>
|
||||
#include <audio/drain/EndPointWrite.hpp>
|
||||
#include <ejson/ejson.hpp>
|
||||
#include <audio/Time.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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.h"
|
||||
#include "Interface.h"
|
||||
#include <stdexcept>
|
||||
#include "Manager.hpp"
|
||||
#include "Interface.hpp"
|
||||
#include "io/Manager.hpp"
|
||||
#include "io/Node.hpp"
|
||||
#include "debug.hpp"
|
||||
#include <ejson/ejson.hpp>
|
||||
|
||||
#include "io/Manager.h"
|
||||
#include "io/Node.h"
|
||||
#include "debug.h"
|
||||
#include <ejson/ejson.h>
|
||||
static ethread::Mutex g_mutex;
|
||||
static etk::Vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
|
||||
|
||||
static std::mutex g_mutex;
|
||||
static std::vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
|
||||
|
||||
ememory::SharedPtr<audio::river::Manager> audio::river::Manager::create(const 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,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _options) {
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
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,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _options) {
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
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,
|
||||
audio::format _format,
|
||||
const std::string& _streamName,
|
||||
const std::string& _options) {
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
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,17 +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 <stdint.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <audio/format.h>
|
||||
#include <audio/channel.h>
|
||||
#include <ejson/ejson.h>
|
||||
#include <etk/String.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/format.hpp>
|
||||
#include <audio/channel.hpp>
|
||||
#include <ejson/ejson.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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,10 +1,10 @@
|
||||
/** @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.h>
|
||||
#include <audio/river/debug.hpp>
|
||||
|
||||
|
||||
int32_t audio::river::getLogId() {
|
||||
|
@@ -1,11 +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 <elog/log.h>
|
||||
#include <elog/log.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include "Node.h"
|
||||
#include "NodeAEC.h"
|
||||
#include "NodeOrchestra.h"
|
||||
#include "NodePortAudio.h"
|
||||
#include "Node.h"
|
||||
#include <audio/river/io/Group.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/io/NodeAEC.hpp>
|
||||
#include <audio/river/io/NodeOrchestra.hpp>
|
||||
#include <audio/river/io/NodePortAudio.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
|
||||
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 <ejson/ejson.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <ejson/ejson.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,27 +1,29 @@
|
||||
/** @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.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <audio/river/river.h>
|
||||
#include <audio/river/io/Node.h>
|
||||
#include <audio/river/io/NodeAEC.h>
|
||||
#include <audio/river/io/NodeMuxer.h>
|
||||
#include <audio/river/io/NodeOrchestra.h>
|
||||
#include <audio/river/io/NodePortAudio.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <etk/types.h>
|
||||
#include <utility>
|
||||
#include <audio/river/io/Manager.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/io/NodeAEC.hpp>
|
||||
#include <audio/river/io/NodeMuxer.hpp>
|
||||
#include <audio/river/io/NodeOrchestra.hpp>
|
||||
#include <audio/river/io/NodePortAudio.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/path/fileSystem.hpp>
|
||||
#include <etk/uri/uri.hpp>
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
#include <portaudio/portaudio.h>
|
||||
extern "C" {
|
||||
#include <portaudio/portaudio.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string basicAutoConfig =
|
||||
static etk::String basicAutoConfig =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
@@ -34,7 +36,8 @@ static std::string basicAutoConfig =
|
||||
" 'front-left', 'front-right'\n"
|
||||
" ],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024\n"
|
||||
" nb-chunk:1024,\n"
|
||||
" mux-demux-type:'float'\n"
|
||||
" },\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@@ -48,11 +51,13 @@ static std::string basicAutoConfig =
|
||||
" ],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024,\n"
|
||||
" volume-name:'MASTER'\n"
|
||||
" volume-name:'MASTER',\n"
|
||||
" mux-demux-type:'float'\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
static etk::Uri pathToTheRiverConfigInHome(etk::path::getHomePath() / ".local" / "share" / "audio-river" / "config.json");
|
||||
|
||||
audio::river::io::Manager::Manager() {
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
@@ -63,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 == "") {
|
||||
RIVER_INFO("Load default config");
|
||||
m_config.parse(basicAutoConfig);
|
||||
} else if (m_config.load(_filename) == false) {
|
||||
RIVER_ERROR("you must set a basic configuration file for harware configuration: '" << _filename << "'");
|
||||
void audio::river::io::Manager::init(const etk::Uri& _uri) {
|
||||
RIVER_ERROR("kjqsdhfkjqshdfkjqhsdskjdfhfkqjshqhskdjfhqsdfqsdqsdfqsdqsdfqsdfqsdfqsdfqsdfqsd");
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
if (_uri.isEmpty() == true) {
|
||||
if (m_config.load(pathToTheRiverConfigInHome) == false) {
|
||||
RIVER_INFO("Load default config");
|
||||
m_config.parse(basicAutoConfig);
|
||||
} else {
|
||||
RIVER_INFO("Load default user configuration: " << pathToTheRiverConfigInHome);
|
||||
}
|
||||
} else if (m_config.load(_uri) == false) {
|
||||
RIVER_ERROR("you must set a basic configuration file for harware configuration: " << _uri);
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::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 : ...
|
||||
}
|
||||
|
||||
@@ -96,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;
|
||||
@@ -185,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;
|
||||
}
|
||||
@@ -202,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>();
|
||||
}
|
||||
@@ -226,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");
|
||||
@@ -236,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");
|
||||
@@ -244,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;
|
||||
}
|
||||
}
|
||||
@@ -258,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) {
|
||||
@@ -274,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;
|
||||
}
|
||||
@@ -293,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,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 <stdint.h>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/format.h>
|
||||
#include <audio/channel.h>
|
||||
#include <ejson/ejson.h>
|
||||
#include <audio/drain/Volume.h>
|
||||
#include <audio/river/io/Group.h>
|
||||
#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.h"
|
||||
#include <audio/river/debug.h>
|
||||
#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 {
|
||||
@@ -79,7 +79,12 @@ audio::river::io::Node::Node(const std::string& _name, const ejson::Object& _con
|
||||
if (m_isInput == true) {
|
||||
// Support all ...
|
||||
} else {
|
||||
if (muxerFormatType != audio::format_int16_on_int32) {
|
||||
if ( muxerFormatType != audio::format_int8_on_int16
|
||||
&& muxerFormatType != audio::format_int16_on_int32
|
||||
&& muxerFormatType != audio::format_int24_on_int32
|
||||
&& muxerFormatType != audio::format_int32_on_int64
|
||||
&& muxerFormatType != audio::format_float
|
||||
&& muxerFormatType != audio::format_double) {
|
||||
RIVER_CRITICAL("not supported demuxer type ... " << muxerFormatType << " for OUTPUT set in file:" << muxerDemuxerConfig);
|
||||
}
|
||||
}
|
||||
@@ -105,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) {
|
||||
@@ -117,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) {
|
||||
@@ -129,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);
|
||||
@@ -137,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();
|
||||
@@ -158,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);
|
||||
@@ -170,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();
|
||||
}
|
||||
}
|
||||
@@ -186,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) {
|
||||
@@ -206,20 +210,27 @@ 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;
|
||||
}
|
||||
std::vector<int32_t> output;
|
||||
RIVER_VERBOSE("resize=" << _nbChunk*m_process.getInputConfig().getMap().size());
|
||||
output.resize(_nbChunk*m_process.getInputConfig().getMap().size(), 0);
|
||||
// TODO : set here the mixer selection ...
|
||||
if (true) {
|
||||
const int32_t* outputTmp = nullptr;
|
||||
std::vector<uint8_t> outputTmp2;
|
||||
RIVER_VERBOSE("resize=" << sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk);
|
||||
outputTmp2.resize(sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk, 0);
|
||||
enum audio::format muxerFormatType = m_process.getInputConfig().getFormat();
|
||||
etk::Vector<uint8_t> outputTmp2;
|
||||
uint32_t nbByteTmpBuffer = audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size()*_nbChunk;
|
||||
RIVER_VERBOSE("resize=" << nbByteTmpBuffer);
|
||||
outputTmp2.resize(nbByteTmpBuffer);
|
||||
|
||||
if (muxerFormatType == audio::format_int8_on_int16) {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 16 bits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// $$$$ change the int16
|
||||
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 = 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) {
|
||||
@@ -227,22 +238,147 @@ void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
|
||||
// clear datas ...
|
||||
memset(&outputTmp2[0], 0, sizeof(int32_t)*m_process.getInputConfig().getMap().size()*_nbChunk);
|
||||
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
|
||||
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
|
||||
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, sizeof(int32_t)*m_process.getInputConfig().getMap().size());
|
||||
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
|
||||
// $$$$ change the int16
|
||||
outputTmp = reinterpret_cast<const int16_t*>(&outputTmp2[0]);
|
||||
RIVER_VERBOSE(" Mix it ...");
|
||||
// Add data to the output tmp buffer:
|
||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
||||
output[kkk] += outputTmp[kkk];
|
||||
}
|
||||
// TODO : if a signal is upper than 256* the maximum of 1 it can create a real problem ...
|
||||
}
|
||||
RIVER_VERBOSE(" End stack process data ...");
|
||||
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
|
||||
} else if ( muxerFormatType == audio::format_int16_on_int32
|
||||
|| muxerFormatType == audio::format_int24_on_int32) {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 32 bits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
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 = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
continue;
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
|
||||
// clear datas ...
|
||||
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
|
||||
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
|
||||
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
|
||||
outputTmp = reinterpret_cast<const int32_t*>(&outputTmp2[0]);
|
||||
RIVER_VERBOSE(" Mix it ...");
|
||||
// Add data to the output tmp buffer :
|
||||
// Add data to the output tmp buffer:
|
||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
||||
output[kkk] += outputTmp[kkk];
|
||||
}
|
||||
// TODO : if a signal is upper than 256* (for 24 bits) or 65335* (for 16 bits) the maximum of 1 it can create a real problem ...
|
||||
}
|
||||
RIVER_VERBOSE(" End stack process data ...");
|
||||
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
|
||||
} else if (muxerFormatType == audio::format_int32_on_int64) {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 64 bits
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
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 = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
continue;
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
|
||||
// clear datas ...
|
||||
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
|
||||
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
|
||||
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
|
||||
outputTmp = reinterpret_cast<const int64_t*>(&outputTmp2[0]);
|
||||
RIVER_VERBOSE(" Mix it ...");
|
||||
// Add data to the output tmp buffer:
|
||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
||||
output[kkk] += outputTmp[kkk];
|
||||
}
|
||||
// TODO : if a signal is upper than 2000000000* the maximum of 1 it can create a real problem ...
|
||||
}
|
||||
RIVER_VERBOSE(" End stack process data ...");
|
||||
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
|
||||
} else if (muxerFormatType == audio::format_float) {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 32 bits FLOAT
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
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 = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
continue;
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
|
||||
// clear datas ...
|
||||
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
|
||||
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
|
||||
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
|
||||
outputTmp = reinterpret_cast<const float*>(&outputTmp2[0]);
|
||||
RIVER_VERBOSE(" Mix it ...");
|
||||
// Add data to the output tmp buffer:
|
||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
||||
output[kkk] += outputTmp[kkk];
|
||||
}
|
||||
}
|
||||
RIVER_VERBOSE(" End stack process data ...");
|
||||
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
|
||||
} else if (muxerFormatType == audio::format_double) {
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// process 64 bits FLOAT
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
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 = null;
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_output) {
|
||||
continue;
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " " << iii);
|
||||
// clear datas ...
|
||||
memset(&outputTmp2[0], 0, nbByteTmpBuffer);
|
||||
RIVER_VERBOSE(" request Data="<< _nbChunk << " time=" << _time);
|
||||
m_list[iii]->systemNeedOutputData(_time, &outputTmp2[0], _nbChunk, audio::getFormatBytes(muxerFormatType)*m_process.getInputConfig().getMap().size());
|
||||
outputTmp = reinterpret_cast<const double*>(&outputTmp2[0]);
|
||||
RIVER_VERBOSE(" Mix it ...");
|
||||
// Add data to the output tmp buffer:
|
||||
for (size_t kkk=0; kkk<output.size(); ++kkk) {
|
||||
output[kkk] += outputTmp[kkk];
|
||||
}
|
||||
}
|
||||
RIVER_VERBOSE(" End stack process data ...");
|
||||
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
|
||||
} else {
|
||||
RIVER_ERROR("Wrong demuxer type: " << muxerFormatType);
|
||||
return;
|
||||
}
|
||||
RIVER_VERBOSE(" End stack process data ...");
|
||||
m_process.processIn(&output[0], _nbChunk, _outputBuffer, _nbChunk);
|
||||
// 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) {
|
||||
@@ -255,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;
|
||||
@@ -327,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 {
|
||||
|
||||
}
|
||||
@@ -344,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();
|
||||
@@ -353,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,24 +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 <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/format.h>
|
||||
#include <audio/channel.h>
|
||||
#include "Manager.h"
|
||||
#include <audio/river/Interface.h>
|
||||
#include <audio/drain/IOFormatInterface.h>
|
||||
#include <audio/drain/Volume.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <audio/format.hpp>
|
||||
#include <audio/channel.hpp>
|
||||
#include "Manager.hpp"
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/drain/IOFormatInterface.hpp>
|
||||
#include <audio/drain/Volume.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.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <etk/types.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <functional>
|
||||
#include <audio/river/io/NodeAEC.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#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,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)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <audio/river/io/Node.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <audio/drain/CircularBuffer.h>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/drain/CircularBuffer.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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,20 +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)
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_FILE
|
||||
|
||||
#include <audio/river/io/NodeFile.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/river/io/NodeFile.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
|
||||
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,28 +197,40 @@ 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),
|
||||
option
|
||||
);
|
||||
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),
|
||||
option
|
||||
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
|
||||
);
|
||||
}
|
||||
if (err != audio::orchestra::error_none) {
|
||||
@@ -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,14 +1,14 @@
|
||||
/** @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
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_FILE
|
||||
|
||||
#include <audio/river/io/Node.h>
|
||||
#include <audio/orchestra/Interface.h>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/orchestra/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <etk/types.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <functional>
|
||||
#include <audio/river/io/NodeMuxer.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#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,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)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <audio/river/io/Node.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <audio/drain/CircularBuffer.h>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/drain/CircularBuffer.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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,20 +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)
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
|
||||
#include <audio/river/io/NodeOrchestra.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/river/io/NodeOrchestra.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
|
||||
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,21 +24,21 @@ 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());
|
||||
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size() << " data=" << uint64_t(_outputBuffer));
|
||||
newOutput(_outputBuffer, _nbChunk, _timeOutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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,29 +198,39 @@ 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),
|
||||
option
|
||||
);
|
||||
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),
|
||||
option
|
||||
);
|
||||
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
|
||||
);
|
||||
}
|
||||
if (err != audio::orchestra::error_none) {
|
||||
RIVER_ERROR("Create stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not create stream " << err);
|
||||
@@ -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,14 +1,14 @@
|
||||
/** @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
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
|
||||
#include <audio/river/io/Node.h>
|
||||
#include <audio/orchestra/Interface.h>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/orchestra/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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,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)
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
|
||||
#include <audio/river/io/NodePortAudio.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <ememory/memory.h>
|
||||
#include <audio/Time.h>
|
||||
#include <audio/Duration.h>
|
||||
#include <audio/river/io/NodePortAudio.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <audio/Time.hpp>
|
||||
#include <audio/Duration.hpp>
|
||||
|
||||
static int portAudioStreamCallback(const void *_input,
|
||||
void *_output,
|
||||
@@ -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,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
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
|
||||
#include <audio/river/Interface.h>
|
||||
#include <audio/river/io/Node.h>
|
||||
#include <portaudio/portaudio.h>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <portaudio/portaudio.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
@@ -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,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 <audio/river/river.h>
|
||||
#include <audio/river/debug.h>
|
||||
#include <audio/river/io/Manager.h>
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#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,24 +1,30 @@
|
||||
/** @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.h>
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <etk/String.hpp>
|
||||
/**
|
||||
* @brief Audio library namespace
|
||||
*/
|
||||
namespace audio {
|
||||
/**
|
||||
* @brief Audio-river library namespace
|
||||
*/
|
||||
namespace river {
|
||||
/**
|
||||
* @brief Initialize the River Library
|
||||
* @param[in] _filename Name of the configuration file (if "" ==> default config file)
|
||||
*/
|
||||
void init(const std::string& _filename = "");
|
||||
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.
|
@@ -1,79 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(audio_river)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
audio_drain
|
||||
audio
|
||||
audio_orchestra
|
||||
ejson
|
||||
)
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
INCLUDE_DIRS ../
|
||||
LIBRARIES ${PROJECT_NAME}
|
||||
CATKIN_DEPENDS audio_orchestra audio audio_drain ejson
|
||||
DEPENDS system_lib
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
include_directories(
|
||||
..
|
||||
${catkin_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
## Declare a cpp library
|
||||
add_library(${PROJECT_NAME}
|
||||
../audio/river/debug.cpp
|
||||
../audio/river/river.cpp
|
||||
../audio/river/Manager.cpp
|
||||
../audio/river/Interface.cpp
|
||||
../audio/river/io/Group.cpp
|
||||
../audio/river/io/Node.cpp
|
||||
../audio/river/io/NodeOrchestra.cpp
|
||||
../audio/river/io/NodePortAudio.cpp
|
||||
../audio/river/io/NodeAEC.cpp
|
||||
../audio/river/io/NodeMuxer.cpp
|
||||
../audio/river/io/Manager.cpp
|
||||
)
|
||||
|
||||
add_definitions(-DAUDIO_RIVER_BUILD_ORCHESTRA)
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${catkin_LIBRARIES}
|
||||
)
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
)
|
||||
|
||||
## Mark cpp header files for installation
|
||||
install(DIRECTORY ../audio/river/
|
||||
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
)
|
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>audio_river</name>
|
||||
<version>0.3.0</version>
|
||||
<description>Ewol River Intrerface : Is to multiple acces on different format on Audio IO</description>
|
||||
<maintainer email="yui.heero@gmail.com">Edouard DUPIN</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
<build_depend>ejson</build_depend>
|
||||
<build_depend>audio</build_depend>
|
||||
<build_depend>audio_orchestra</build_depend>
|
||||
<build_depend>audio_drain</build_depend>
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<run_depend>ejson</run_depend>
|
||||
<run_depend>audio</run_depend>
|
||||
<run_depend>audio_orchestra</run_depend>
|
||||
<run_depend>audio_drain</run_depend>
|
||||
</package>
|
@@ -1,41 +0,0 @@
|
||||
=?=RIVER: Bases =?=
|
||||
__________________________________________________
|
||||
[right][tutorial[000_Build | Next: Tutorals]][/right]
|
||||
|
||||
=== Overview:===
|
||||
|
||||
===User requires:===
|
||||
To use ewol you need to know only C++ language. It could be usefull to know:
|
||||
:** [b]Python[/b] for all build tool.
|
||||
:** [b]git[/b] for all version management
|
||||
:** [b]Audio[/b] Basic knowlege of audio streaming af data organisation.
|
||||
|
||||
=== Architecture:===
|
||||
River has been designed to replace the pulseAudio basic asyncronous interface that create
|
||||
more problem that it will solve. The second point is that is not enougth portable to be
|
||||
embended in a proprietary software without distributing all the sources (Ios).
|
||||
|
||||
Start at this point we will have simple objectives :
|
||||
:** manage multiple Low level interface: (done by the [lib[airtaudio | AirTAudio]] interface):
|
||||
::** for linux
|
||||
:::** Alsa
|
||||
:::** Pulse
|
||||
:::** Oss
|
||||
::** for Mac-OsX
|
||||
:::** CoreAudio
|
||||
::** for IOs
|
||||
:::** CoreAudio (embended version)
|
||||
::** for Windows
|
||||
:::** ASIO
|
||||
::** For Android
|
||||
:::** Java (JDK-6)
|
||||
:** Synchronous interface ==> no delay and reduce latency
|
||||
:** Manage the thread priority (need sometimes to be more reactive)
|
||||
:** manage mixing of some flow (2 inputs stereo and the user want 1 input quad)
|
||||
:** AEC Acoustic Echo Cancelation (TODO : in the current implementation we have a simple sound cutter)
|
||||
:** Equalizer (done with [lib[drain | Drain])
|
||||
:** Resmpling (done by the libspeexDSP)
|
||||
:** Correct volume management (and configurable)
|
||||
:** Fade-in and Fade-out (done with [lib[drain | Drain])
|
||||
:** Channel reorganisation (done with [lib[drain | Drain])
|
||||
:** A correct feedback interface
|
100
doc/build.md
Normal file
100
doc/build.md
Normal file
@@ -0,0 +1,100 @@
|
||||
Build lib & build sample {#audio_river_build}
|
||||
========================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
Download: {#audio_river_build_download}
|
||||
=========
|
||||
|
||||
ege use some tools to manage source and build it:
|
||||
|
||||
need google repo: {#audio_river_build_download_repo}
|
||||
-----------------
|
||||
|
||||
see: http://source.android.com/source/downloading.html#installing-repo
|
||||
|
||||
On all platform:
|
||||
```{.sh}
|
||||
mkdir ~/.bin
|
||||
PATH=~/.bin:$PATH
|
||||
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
|
||||
chmod a+x ~/.bin/repo
|
||||
```
|
||||
|
||||
On ubuntu
|
||||
```{.sh}
|
||||
sudo apt-get install repo
|
||||
```
|
||||
|
||||
On archlinux
|
||||
```{.sh}
|
||||
sudo pacman -S repo
|
||||
```
|
||||
|
||||
lutin (build-system): {#audio_river_build_download_lutin}
|
||||
---------------------
|
||||
|
||||
```{.sh}
|
||||
pip install lutin --user
|
||||
# optionnal dependency of lutin (manage image changing size for application release)
|
||||
pip install pillow --user
|
||||
```
|
||||
|
||||
|
||||
dependency: {#audio_river_build_download_dependency}
|
||||
-----------
|
||||
|
||||
```{.sh}
|
||||
mkdir -p WORKING_DIRECTORY/framework
|
||||
cd WORKING_DIRECTORY/framework
|
||||
repo init -u git://github.com/atria-soft/manifest.git
|
||||
repo sync -j8
|
||||
cd ../..
|
||||
```
|
||||
|
||||
sources: {#audio_river_build_download_sources}
|
||||
--------
|
||||
|
||||
They are already download in the repo manifest in:
|
||||
|
||||
```{.sh}
|
||||
cd WORKING_DIRECTORY/framework/musicdsp/audio-river
|
||||
```
|
||||
|
||||
Build: {#audio_river_build_build}
|
||||
======
|
||||
|
||||
you must stay in zour working directory...
|
||||
```{.sh}
|
||||
cd WORKING_DIRECTORY
|
||||
```
|
||||
|
||||
library: {#audio_river_build_build_library}
|
||||
--------
|
||||
|
||||
```{.sh}
|
||||
lutin -mdebug audio-river
|
||||
```
|
||||
|
||||
Sample: {#audio_river_build_build_sample}
|
||||
-------
|
||||
|
||||
```{.sh}
|
||||
lutin -mdebug audio-river-sample-read?run
|
||||
lutin -mdebug audio-river-sample-write?run
|
||||
```
|
||||
|
||||
A fast way:
|
||||
```{.sh}
|
||||
lutin -mdebug audio-river-*
|
||||
```
|
||||
|
||||
|
||||
Run sample: {#audio_river_build_run_sample}
|
||||
===========
|
||||
|
||||
in distinct bash:
|
||||
```{.sh}
|
||||
lutin -mdebug audio-river-sample-read?run
|
||||
lutin -mdebug audio-river-sample-write?run
|
||||
```
|
119
doc/configFile.md
Normal file
119
doc/configFile.md
Normal file
@@ -0,0 +1,119 @@
|
||||
River configuration file {#audio_river_config_file}
|
||||
========================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
Objectifs: {#audio_river_config_file_objectif}
|
||||
==========
|
||||
|
||||
- Understand the architecture of the configuration file.
|
||||
- all that can be done with it.
|
||||
|
||||
|
||||
Basis: {#audio_river_config_file_bases}
|
||||
======
|
||||
|
||||
The river configuration file is a json file. We use @ref ejson_mainpage_what to parse it then we have some writing facilities.
|
||||
|
||||
|
||||
River provide a list a harware interface and virtual interface.
|
||||
|
||||
|
||||
The hardware interface are provided by @ref audio_orchestra_mainpage_what then we will plug on every platform.
|
||||
|
||||
|
||||
The file is simply architecture around a list of object:
|
||||
|
||||
```{.json}
|
||||
{
|
||||
"speaker":{
|
||||
|
||||
},
|
||||
"microphone":{
|
||||
|
||||
},
|
||||
"mixed-in-out":{
|
||||
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
With this config we declare 3 interfaces : speaker, microphone and mixed-in-out.
|
||||
|
||||
|
||||
Harware configuration: {#audio_river_config_file_hw_config}
|
||||
======================
|
||||
|
||||
In every interface we need to define some Element:
|
||||
- "io" : Can be input/output/... depending of virtual interface...
|
||||
- "map-on": An object to configure airtaudio interface.
|
||||
- "frequency": 0 to automatic select one. Or the frequency to open harware device
|
||||
- "channel-map": List of all channel in the stream:
|
||||
* "front-left"
|
||||
* "front-center"
|
||||
* "front-right"
|
||||
* "rear-left"
|
||||
* "rear-center"
|
||||
* "rear-right"
|
||||
* "surround-left",
|
||||
* "surround-right",
|
||||
* "sub-woofer",
|
||||
* "lfe"
|
||||
- "type": Fomat to open the stream:
|
||||
* "auto": Detect the best type
|
||||
* "int8",
|
||||
* "int8-on-int16",
|
||||
* "int16",
|
||||
* "int16-on-int32",
|
||||
* "int24",
|
||||
* "int32",
|
||||
* "int32-on-int64",
|
||||
* "int64",
|
||||
* "float",
|
||||
* "double"
|
||||
- "nb-chunk": Number of chunk to open the stream.
|
||||
|
||||
|
||||
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
|
||||
|
36
doc/faq.bb
36
doc/faq.bb
@@ -1,36 +0,0 @@
|
||||
=?= FAQ =?=
|
||||
|
||||
== What is ewol licence ==
|
||||
|
||||
This is really simple : APACHE-2 :
|
||||
|
||||
Copyright ewol Edouard DUPIN
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
[[http://www.apache.org/licenses/LICENSE-2.0]]
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
|
||||
|
||||
== Why we use "DECLARE_FACTORY" Macro ? ==
|
||||
|
||||
For some reason!!! But everything might be clear:
|
||||
:** In ewol we masively use std::shared_ptr<xxx> (I have create my own but it is not "standard" (I like when we use genecic system)).
|
||||
:** The main class : [class[ewol::Object]] herited from [i]std::enable_shared_from_this<Object>[/i] to permit to access at his own [i]std::shared_ptr[/i].
|
||||
:** Acces At his own [i]std::shared_ptr[/i] is not allowed in the class contructor/destructor.
|
||||
:** Many time for meta-widget we need to propagate our [i]std::shared_ptr[/i] in child.
|
||||
|
||||
Then for all these reasons, I have create a simple MACRO that create a static template funtion that create the object and just after
|
||||
creation call the init(...) function to permit to create a complex widget or others with some writing convinience.
|
||||
|
||||
|
||||
|
30
doc/feedback.md
Normal file
30
doc/feedback.md
Normal file
@@ -0,0 +1,30 @@
|
||||
Read stream feedback {#audio_river_feedback}
|
||||
====================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
Objectifs: {#audio_river_feedback_objectif}
|
||||
==========
|
||||
|
||||
- Implement a feedback.
|
||||
|
||||
Bases: {#audio_river_feedback_base}
|
||||
======
|
||||
|
||||
A feedback is a stream that is generated by an output.
|
||||
|
||||
To get a feedback this is the same implementation of an input and link it on an output.
|
||||
|
||||
|
||||
What change:
|
||||
|
||||
```{.cpp}
|
||||
//Get the generic feedback on speaker:
|
||||
interface = manager->createFeedback(48000,
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
```
|
||||
|
||||
**Note:** Input interface does not provide feedback.
|
||||
|
69
doc/index.bb
69
doc/index.bb
@@ -1,69 +0,0 @@
|
||||
== [center]RIVER library[/center] ==
|
||||
__________________________________________________
|
||||
|
||||
===What is RIVER, and how can I use it?===
|
||||
RIVER is a multi-platform library to manage the input and output audio flow.
|
||||
It can be compared with PulseAudio or Jack, but at the difference at the 2 interfaces
|
||||
it is designed to be multi-platform and is based on licence that permit to integrate it
|
||||
on every program we want.
|
||||
|
||||
===Where can I use it?===
|
||||
Everywhere! RIVER is cross-platform devolopped to support bases OS:
|
||||
: ** Linux (over Alsa, Pulseaudio, JackD)
|
||||
: ** Windows (over ASIO)
|
||||
: ** MacOs (over CoreAudio)
|
||||
: ** Android (Over Ewol wrapper little complicated need to be change later)
|
||||
: ** IOs (over CoreAudio for ios)
|
||||
|
||||
===What languages are supported?===
|
||||
RIVER is written in C++11 with posibilities to compile it with C++03 + Boost
|
||||
|
||||
===Are there any licensing restrictions?===
|
||||
RIVER is [b]FREE software[/b] and [i]all sub-library are FREE and staticly linkable !!![/i]
|
||||
|
||||
That allow you to use it for every program you want, including those developing proprietary software, without any license fees or royalties.
|
||||
|
||||
[note]The static support is important for some platform like IOs, and this limit the external library use at some license like :
|
||||
:** BSD*
|
||||
:** MIT
|
||||
:** APPACHE-2
|
||||
:** PNG
|
||||
:** ZLIB
|
||||
This exclude the classical extern library with licence:
|
||||
:** L-GPL
|
||||
:** GPL
|
||||
[/note]
|
||||
|
||||
==== License (APACHE 2) ====
|
||||
Copyright ewol Edouard DUPIN
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
[[http://www.apache.org/licenses/LICENSE-2.0]]
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
==== Depends library: ====
|
||||
===== License: =====
|
||||
:** [b][lib[etk | e-tk]][/b] : APACHE-2
|
||||
:** [b][lib[airtaudio | airtaudio]][/b] : MIT/APACHE-2
|
||||
:** [b][lib[ejson | e-json]][/b] : APACHE-2
|
||||
:** [b][lib[drain | Drain]][/b] : APACHE-2
|
||||
|
||||
|
||||
===== Program Using RIVER =====
|
||||
:** [b][[http://play.google.com/store/apps/details?id=com.edouarddupin.worddown | worddown]][/b] : (Proprietary) Worddown is a simple word game threw [lib[ewolsa | ewol-simple-audio]].
|
||||
|
||||
== Main documentation: ==
|
||||
|
||||
[doc[001_bases | Global Documantation]]
|
||||
|
||||
[tutorial[000_Build | Tutorials]]
|
||||
|
92
doc/mainpage.md
Normal file
92
doc/mainpage.md
Normal file
@@ -0,0 +1,92 @@
|
||||
AUDIO-RIVER library {#mainpage}
|
||||
===================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
What is AUDIO-RIVER: {#audio_river_mainpage_what}
|
||||
====================
|
||||
|
||||
AUDIO-RIVER, is a multi-platform library to manage the input and output audio flow.
|
||||
It can be compared with PulseAudio or Jack, but at the difference at the 2 interfaces
|
||||
it is designed to be multi-platform and is based on licence that permit to integrate it
|
||||
on every program we want.
|
||||
|
||||
|
||||
What it does: {#audio_river_mainpage_what_it_does}
|
||||
=============
|
||||
|
||||
Everywhere! RIVER is cross-platform devolopped to support bases OS:
|
||||
: ** Linux (over Alsa, Pulseaudio, JackD)
|
||||
: ** Windows (over ASIO)
|
||||
: ** MacOs (over CoreAudio)
|
||||
: ** Android (Over Ewol wrapper little complicated need to be change later)
|
||||
: ** IOs (over CoreAudio for ios)
|
||||
|
||||
AUDIO-RIVER is dependent of the STL (compatible with MacOs stl (CXX))
|
||||
|
||||
Architecture:
|
||||
-------------
|
||||
|
||||
River has been designed to replace the pulseAudio basic asyncronous interface that create
|
||||
more problem that it will solve. The second point is that is not enougth portable to be
|
||||
embended in a proprietary software without distributing all the sources (Ios).
|
||||
|
||||
Start at this point we will have simple objectives :
|
||||
- Manage multiple Low level interface: @ref audio_orchestra_mainpage_what
|
||||
* for linux (Alsa, Pulse, Oss)
|
||||
* for Mac-OsX (CoreAudio)
|
||||
* for IOs (coreAudio (embended version))
|
||||
* for Windows (ASIO)
|
||||
* For Android (Java (JDK...))
|
||||
- Synchronous interface ==> no delay and reduce latency
|
||||
- Manage the thread priority (need sometimes to be more reactive)
|
||||
- manage mixing of some flow (2 inputs stereo and the user want 1 input quad)
|
||||
- AEC Acoustic Echo Cancelation (TODO : in the current implementation we have a simple sound cutter)
|
||||
- Equalizer (done with @ref audio_drain_mainpage_what)
|
||||
- Resmpling (done by the libspeexDSP)
|
||||
- Correct volume management (and configurable)
|
||||
- Fade-in and Fade-out @ref audio_drain_mainpage_what
|
||||
- Channel reorganisation @ref audio_drain_mainpage_what
|
||||
- A correct feedback interface
|
||||
|
||||
|
||||
What languages are supported? {#audio_river_mainpage_language}
|
||||
=============================
|
||||
|
||||
AUDIO-RIVER is written in C++.
|
||||
|
||||
|
||||
Are there any licensing restrictions? {#audio_river_mainpage_license_restriction}
|
||||
=====================================
|
||||
|
||||
AUDIO-RIVER is **FREE software** and _all sub-library are FREE and staticly linkable !!!_
|
||||
|
||||
|
||||
License (MPL v2.0) {#audio_river_mainpage_license}
|
||||
==================
|
||||
|
||||
Copyright AUDIO-RIVER Edouard DUPIN
|
||||
|
||||
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
|
||||
|
||||
<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,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Other pages {#audio_river_mainpage_sub_page}
|
||||
===========
|
||||
|
||||
- @ref audio_river_build
|
||||
- @ref audio_river_read
|
||||
- @ref audio_river_write
|
||||
- @ref audio_river_feedback
|
||||
- @ref audio_river_config_file
|
||||
- [**ewol coding style**](http://atria-soft.github.io/ewol/ewol_coding_style.html)
|
||||
|
115
doc/read.md
Normal file
115
doc/read.md
Normal file
@@ -0,0 +1,115 @@
|
||||
Read stream form Audio input {#audio_river_read}
|
||||
============================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
Objectifs: {#audio_river_read_objectif}
|
||||
==========
|
||||
|
||||
- Understand basis of river
|
||||
- Create a simple recording interface that print the average of sample absolute value.
|
||||
|
||||
|
||||
When you will create an application based on the river audio interface you need :
|
||||
|
||||
Include: {#audio_river_read_include}
|
||||
========
|
||||
|
||||
Include manager and interface node
|
||||
@snippet read.cpp audio_river_sample_include
|
||||
|
||||
Initilize the River library: {#audio_river_read_init}
|
||||
============================
|
||||
|
||||
We first need to initialize etk sub library (needed to select the log level of sub-libraries and file access abstraction
|
||||
@snippet read.cpp audio_river_sample_init
|
||||
|
||||
Now we will initilaize the river library.
|
||||
To do this We have 2 posibilities:
|
||||
With a file:
|
||||
------------
|
||||
|
||||
```{.cpp}
|
||||
// initialize river interface
|
||||
river::init("DATA:///configFileName.json");
|
||||
```
|
||||
|
||||
With a json string:
|
||||
-------------------
|
||||
|
||||
@snippet read.cpp audio_river_sample_read_config_file
|
||||
|
||||
```{.cpp}
|
||||
// initialize river interface
|
||||
river::initString(configurationRiver);
|
||||
```
|
||||
|
||||
For the example we select the second solution (faster to implement example and resource at the same position.
|
||||
|
||||
river::init / river::initString must be called only one time for all the application, this represent the hardware configuration.
|
||||
It is NOT dynamic
|
||||
|
||||
To understand the configuration file Please see @ref audio_river_config_file
|
||||
|
||||
This json is parsed by the @ref {#ejson_mainpage_what} it contain some update like:
|
||||
- Optionnal " in the name of element.
|
||||
- The possibilities to remplace " with '.
|
||||
|
||||
|
||||
|
||||
Get the river interface manager: {#audio_river_read_river_interface}
|
||||
================================
|
||||
|
||||
An application can have many interface and only one Manager. And a process can contain many application.
|
||||
|
||||
Then, we will get the first application manager handle.
|
||||
@snippet read.cpp audio_river_sample_get_interface
|
||||
|
||||
*Note:* You can get back the application handle when you create a new one with the same name.
|
||||
|
||||
Create your read interface: {#audio_river_read_river_read_interface}
|
||||
===========================
|
||||
|
||||
Generic code:
|
||||
@snippet read.cpp audio_river_sample_create_read_interface
|
||||
|
||||
Here we create an interface with:
|
||||
- The frequency of 48000 Hz.
|
||||
- The default Low level definition channel
|
||||
- A data interface of 16 bits samples coded in [-32768..32767]
|
||||
- Select input interaface name "microphone"
|
||||
|
||||
|
||||
set data callback: {#audio_river_read_get_data}
|
||||
==================
|
||||
|
||||
The best way to get data is to instanciate a simple callback.
|
||||
The callback is called when sample arrive and you have the nbChunk/frequency
|
||||
to process the data, otherwise you can generate error in data stream.
|
||||
|
||||
@snippet read.cpp audio_river_sample_set_callback
|
||||
|
||||
Callback inplementation: {#audio_river_read_callback}
|
||||
========================
|
||||
|
||||
Simply declare your function and do what you want inside.
|
||||
|
||||
@snippet read.cpp audio_river_sample_callback_implement
|
||||
|
||||
start and stop the stream: {#audio_river_read_start_stop}
|
||||
==========================
|
||||
|
||||
@snippet read.cpp audio_river_sample_read_start_stop
|
||||
|
||||
Remove interfaces: {#audio_river_read_reset}
|
||||
==================
|
||||
|
||||
@snippet read.cpp audio_river_sample_read_reset
|
||||
|
||||
|
||||
|
||||
|
||||
Full Sample: {#audio_river_read_full_sample}
|
||||
============
|
||||
|
||||
@snippet read.cpp audio_river_sample_read_all
|
@@ -1,57 +0,0 @@
|
||||
=?=River extract and build examples an example=?=
|
||||
|
||||
All developpement software will start by getting the dependency and the sources.
|
||||
|
||||
=== Linux dependency packages ===
|
||||
[code style=shell]
|
||||
sudo apt-get install g++ zlib1g-dev libasound2-dev
|
||||
# if you want to compile with clang :
|
||||
sudo apt-get install clang
|
||||
[/code]
|
||||
|
||||
|
||||
=== Download instructions ===
|
||||
|
||||
Download the software : This is the simple way You really need only a part of the ewol framework
|
||||
[code style=shell]
|
||||
# create a working directory path
|
||||
mkdir your_workspace_path
|
||||
cd your_workspace_path
|
||||
# clone ewol and all sub-library
|
||||
git clone git://github.com/HeeroYui/ewol.git
|
||||
cd ewol
|
||||
git submodule init
|
||||
git submodule update
|
||||
cd ..
|
||||
[/code]
|
||||
|
||||
If you prefer creating with the packege you needed :
|
||||
[code style=shell]
|
||||
mkdir -p your_workspace_path
|
||||
cd your_workspace_path
|
||||
# download all you needs
|
||||
git clone git://github.com/HeeroYui/lutin.git
|
||||
git clone git://github.com/HeeroYui/etk.git
|
||||
git clone git://github.com/HeeroYui/audio.git
|
||||
git clone git://github.com/HeeroYui/ejson.git
|
||||
git clone git://github.com/HeeroYui/airtaudio.git
|
||||
git clone git://github.com/HeeroYui/drain.git
|
||||
git clone git://github.com/HeeroYui/river.git
|
||||
[/code]
|
||||
|
||||
[note]
|
||||
The full build tool documentation is availlable here : [[http://heeroyui.github.io/lutin/ | lutin]]
|
||||
[/note]
|
||||
|
||||
=== Common build instructions ===
|
||||
|
||||
Build the basic examples & test:
|
||||
[code style=shell]
|
||||
./ewol/build/lutin.py -mdebug river_sample_read
|
||||
[/code]
|
||||
|
||||
To run an application you will find it directly on the out 'staging' tree :
|
||||
[code style=shell]
|
||||
./out/Linux/debug/staging/clang/river_sample_read/usr/bin/river_sample_read -l4
|
||||
[/code]
|
||||
|
@@ -1,158 +0,0 @@
|
||||
|
||||
=== Objectif ===
|
||||
:** Understand basis of river
|
||||
:** Create a simple recording interface that print the average of sample absolute value.
|
||||
|
||||
=== sample source: ===
|
||||
[[http://github.com/HeeroYui/river.git/sample/read/ | sample source]]
|
||||
|
||||
=== Bases: ===
|
||||
|
||||
When you will create an application based on the river audio interface you need :
|
||||
|
||||
==== Include: ====
|
||||
|
||||
Include manager and interface node
|
||||
|
||||
[code style=c++]
|
||||
#include <river/river.h>
|
||||
#include <river/Manager.h>
|
||||
#include <river/Interface.h>
|
||||
[/code]
|
||||
|
||||
==== Initilize the River library: ====
|
||||
|
||||
We first need to initialize etk sub library (needed to select the log level of sub-libraries and file access abstraction
|
||||
[code style=c++]
|
||||
// the only one init for etk:
|
||||
etk::init(_argc, _argv);
|
||||
[/code]
|
||||
|
||||
Now we will initilaize the river library.
|
||||
To do this We have 2 posibilities:
|
||||
:** With a file:
|
||||
[code style=c++]
|
||||
// initialize river interface
|
||||
river::init("DATA:configFileName.json");
|
||||
[/code]
|
||||
:** With a json string:
|
||||
[code style=c++]
|
||||
static const std::string configurationRiver =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'auto',\n"
|
||||
" name:'default',\n"
|
||||
" },\n"
|
||||
" frequency:0,\n"
|
||||
" channel-map:['front-left', 'front-right'],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
// initialize river interface
|
||||
river::initString(configurationRiver);
|
||||
[/code]
|
||||
|
||||
For the example we select the second solution (faster to implement example and resource at the same position.
|
||||
|
||||
river::init / river::initString must be called only one time for all the application, this represent the hardware configuration.
|
||||
It is Nearly not dynamic
|
||||
|
||||
To understand the configuration file Please see [tutorial[004_ConfigurationFile | Configuration file]]
|
||||
|
||||
[note]
|
||||
This json is parsed by the [lib[ejson | e-json library]] it containe some update like:
|
||||
:** Optionnal " in the name of element.
|
||||
:** The possibilities to remplace " with '.
|
||||
[/note]
|
||||
|
||||
|
||||
==== Get the river interface manager: ====
|
||||
|
||||
An application can have many interface and only one Manager, And a process can contain many application.
|
||||
|
||||
Then, we will get the first application manager handle.
|
||||
|
||||
[code style=c++]
|
||||
// Create the River manager for tha application or part of the application.
|
||||
std11::shared_ptr<river::Manager> manager = river::Manager::create("river_sample_read");
|
||||
[/code]
|
||||
|
||||
[note]
|
||||
You can get back the application handle when you create a new one with the same name.
|
||||
[/note]
|
||||
|
||||
==== Create your read interface: ====
|
||||
|
||||
[code style=c++]
|
||||
// create interface:
|
||||
std11::shared_ptr<river::Interface> interface;
|
||||
//Get the generic input:
|
||||
interface = manager->createInput(48000,
|
||||
std::vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"microphone");
|
||||
[/code]
|
||||
|
||||
Here we create an interface with:
|
||||
:** The frequency of 48000 Hz.
|
||||
:** The default Low level definition channel
|
||||
:** A data interface of 16 bits samples coded in [-32768..32767]
|
||||
:** Select input interaface name "microphone"
|
||||
|
||||
|
||||
==== Get datas: ====
|
||||
|
||||
The best way to get data is to instanciate a simple callback.
|
||||
The callback is called when sample arrive and you have the nbChunk/frequency
|
||||
to process the data, otherwise you can generate error in data stream.
|
||||
|
||||
|
||||
[code style=c++]
|
||||
// set callback mode ...
|
||||
interface->setInputCallback(std11::bind(&onDataReceived,
|
||||
std11::placeholders::_1,
|
||||
std11::placeholders::_2,
|
||||
std11::placeholders::_3,
|
||||
std11::placeholders::_4,
|
||||
std11::placeholders::_5,
|
||||
std11::placeholders::_6));
|
||||
[/code]
|
||||
|
||||
==== Callback inplementation: ====
|
||||
|
||||
Simply declare your function and do what you want inside.
|
||||
|
||||
[code style=c++]
|
||||
void onDataReceived(const void* _data,
|
||||
const std11::chrono::system_clock::time_point& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
if (_format == audio::format_int16) {
|
||||
// stuff here
|
||||
}
|
||||
}
|
||||
[/code]
|
||||
|
||||
==== start and stop: ====
|
||||
|
||||
[code style=c++]
|
||||
// start the stream
|
||||
interface->start();
|
||||
// wait 10 second ...
|
||||
sleep(10);
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
[/code]
|
||||
|
||||
==== Remove interfaces: ====
|
||||
|
||||
[code style=c++]
|
||||
// remove interface and manager.
|
||||
interface.reset();
|
||||
manager.reset();
|
||||
[/code]
|
@@ -1,84 +0,0 @@
|
||||
|
||||
=== Objectif ===
|
||||
:** Understand write audio stream
|
||||
|
||||
=== sample source: ===
|
||||
[[http://github.com/HeeroYui/river.git/sample/write/ | sample source]]
|
||||
|
||||
=== Bases: ===
|
||||
|
||||
The writing work nearly like the read turoral. Then we will just see what has change.
|
||||
|
||||
==== File configuration: ====
|
||||
|
||||
[code style=c++]
|
||||
static const std::string configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'auto',\n"
|
||||
" name:'default',\n"
|
||||
" },\n"
|
||||
" frequency:0,\n"
|
||||
" channel-map:['front-left', 'front-right'],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024,\n"
|
||||
" volume-name:'MASTER'\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
[/code]
|
||||
|
||||
==== Create your write interface: ====
|
||||
|
||||
[code style=c++]
|
||||
// create interface:
|
||||
std11::shared_ptr<river::Interface> interface;
|
||||
//Get the generic input:
|
||||
interface = manager->createOutput(48000,
|
||||
std::vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
[/code]
|
||||
|
||||
Here we create an interface with:
|
||||
:** The frequency of 48000 Hz.
|
||||
:** The default Low level definition channel
|
||||
:** A data interface of 16 bits samples coded in [-32768..32767]
|
||||
:** Select input interaface name "speaker"
|
||||
|
||||
|
||||
==== write datas: ====
|
||||
|
||||
The best way to get data is to instanciate a simple callback.
|
||||
The callback is called when sample are needed and you have the nbChunk/frequency
|
||||
to generate the data, otherwise you can generate error in data stream.
|
||||
|
||||
|
||||
[code style=c++]
|
||||
// set callback mode ...
|
||||
interface->setOutputCallback(std11::bind(&onDataNeeded,
|
||||
std11::placeholders::_1,
|
||||
std11::placeholders::_2,
|
||||
std11::placeholders::_3,
|
||||
std11::placeholders::_4,
|
||||
std11::placeholders::_5,
|
||||
std11::placeholders::_6));
|
||||
[/code]
|
||||
|
||||
==== Callback inplementation: ====
|
||||
|
||||
Simply declare your function and do what you want inside.
|
||||
|
||||
[code style=c++]
|
||||
void onDataNeeded(void* _data,
|
||||
const std11::chrono::system_clock::time_point& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const std::vector<audio::channel>& _map) {
|
||||
if (_format == audio::format_int16) {
|
||||
// stuff here
|
||||
}
|
||||
}
|
||||
[/code]
|
@@ -1,25 +0,0 @@
|
||||
|
||||
=== Objectif ===
|
||||
:** Implement a feedback.
|
||||
|
||||
=== Bases: ===
|
||||
|
||||
A feedback is a stream that is generated by an output.
|
||||
|
||||
To get a feedback this is the same implementation of an input and link it on an output.
|
||||
|
||||
|
||||
What change :
|
||||
|
||||
[code style=c++]
|
||||
//Get the generic feedback on speaker:
|
||||
interface = manager->createFeedback(48000,
|
||||
std::vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
[/code]
|
||||
|
||||
[note]
|
||||
Input interface does not provide feedback.
|
||||
[/note]
|
||||
|
@@ -1,70 +0,0 @@
|
||||
|
||||
=== Objectif ===
|
||||
:** Understand the architecture of the configuration file.
|
||||
:** all that can be done with it.
|
||||
|
||||
|
||||
=== Basis: ===
|
||||
|
||||
The river configuration file is a json file. We use [lib[ejson | e-json library]] to parse it then we have some writing facilities.
|
||||
|
||||
|
||||
River provide a list a harware interface and virtual interface.
|
||||
|
||||
|
||||
The hardware interface are provided by [lib[airtaudio | AirTAudio library]] then we will plug on every platform.
|
||||
|
||||
|
||||
The file is simply architecture around a list of object:
|
||||
|
||||
[code style=json]
|
||||
{
|
||||
"speaker":{
|
||||
|
||||
},
|
||||
"microphone":{
|
||||
|
||||
},
|
||||
"mixed-in-out":{
|
||||
|
||||
},
|
||||
}
|
||||
[/code]
|
||||
|
||||
With this config we declare 3 interfaces : speaker, microphone and mixed-in-out.
|
||||
|
||||
|
||||
=== Harware configuration: ===
|
||||
|
||||
In every interface we need to define some Element:
|
||||
:** "io" :
|
||||
:: Can be input/output/... depending of virtual interface...
|
||||
:** "map-on": An object to configure airtaudio interface.
|
||||
:** "frequency": 0 to automatic select one. Or the frequency to open harware device
|
||||
:** "channel-map": List of all channel in the stream:
|
||||
::** "front-left"
|
||||
::** "front-center"
|
||||
::** "front-right"
|
||||
::** "rear-left"
|
||||
::** "rear-center"
|
||||
::** "rear-right"
|
||||
::** "surround-left",
|
||||
::** "surround-right",
|
||||
::** "sub-woofer",
|
||||
::** "lfe"
|
||||
:** "type": Fomat to open the stream:
|
||||
::** "auto": Detect the best type
|
||||
::** "int8",
|
||||
::** "int8-on-int16",
|
||||
::** "int16",
|
||||
::** "int16-on-int32",
|
||||
::** "int24",
|
||||
::** "int32",
|
||||
::** "int32-on-int64",
|
||||
::** "int64",
|
||||
::** "float",
|
||||
::** "double"
|
||||
:** "nb-chunk": Number of chunk to open the stream.
|
||||
|
||||
|
||||
|
53
doc/write.md
Normal file
53
doc/write.md
Normal file
@@ -0,0 +1,53 @@
|
||||
Write stream to Audio output {#audio_river_write}
|
||||
============================
|
||||
|
||||
@tableofcontents
|
||||
|
||||
Objectifs: {#audio_river_write_objectif}
|
||||
==========
|
||||
|
||||
- Understand write audio stream
|
||||
|
||||
The writing work nearly like the read turoral. Then we will just see what has change.
|
||||
|
||||
File configuration: {#audio_river_write_config}
|
||||
===================
|
||||
|
||||
@snippet write.cpp audio_river_sample_write_config_file
|
||||
|
||||
|
||||
Create your write interface: {#audio_river_write_interface}
|
||||
============================
|
||||
|
||||
Generic code:
|
||||
@snippet write.cpp audio_river_sample_create_write_interface
|
||||
|
||||
Here we create an interface with:
|
||||
- The frequency of 48000 Hz.
|
||||
- The default Low level definition channel
|
||||
- A data interface of 16 bits samples coded in [-32768..32767]
|
||||
- Select input interaface name "speaker"
|
||||
|
||||
|
||||
set data callback: {#audio_river_write_get_data}
|
||||
==================
|
||||
|
||||
The best way to get data is to instanciate a simple callback.
|
||||
The callback is called when sample are needed and you have the nbChunk/frequency
|
||||
to generate the data, otherwise you can generate error in data stream.
|
||||
|
||||
@snippet write.cpp audio_river_sample_set_callback
|
||||
|
||||
Callback inplementation: {#audio_river_write_callback}
|
||||
========================
|
||||
|
||||
Simply declare your function and do what you want inside.
|
||||
|
||||
@snippet write.cpp audio_river_sample_callback_implement
|
||||
|
||||
|
||||
|
||||
Full Sample: {#audio_river_write_full_sample}
|
||||
============
|
||||
|
||||
@snippet write.cpp audio_river_sample_write_all
|
37
doxy_audio-river.py
Normal file
37
doxy_audio-river.py
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/python
|
||||
import os
|
||||
import doxy.module as module
|
||||
import doxy.debug as debug
|
||||
import doxy.tools as tools
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name)
|
||||
my_module.set_version("version.txt")
|
||||
my_module.set_title("audio-river: Multi-nodal audio interface")
|
||||
my_module.set_website("http://musicdsp.github.io/" + module_name)
|
||||
my_module.set_website_sources("http://github.com/musicdsp/" + module_name)
|
||||
my_module.add_path([
|
||||
"audio",
|
||||
"doc"
|
||||
])
|
||||
my_module.add_sample_path([
|
||||
"sample",
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio',
|
||||
'audio-drain',
|
||||
'audio-orchestra',
|
||||
'ejson'
|
||||
])
|
||||
my_module.add_exclude_symbols([
|
||||
'*operator<<*',
|
||||
])
|
||||
my_module.add_exclude_file([
|
||||
'debug.h',
|
||||
])
|
||||
my_module.add_file_patterns([
|
||||
'*.h',
|
||||
'*.md',
|
||||
])
|
||||
|
||||
return my_module
|
@@ -1,35 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_sub_type():
|
||||
return "TEST"
|
||||
|
||||
def get_desc():
|
||||
return "Multi-nodal audio interface test"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return "authors.txt"
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'test/main.cpp'
|
||||
])
|
||||
my_module.add_depend(['audio-river', 'gtest', 'etk', 'test-debug'])
|
||||
return my_module
|
||||
|
||||
|
@@ -1,63 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
def get_type():
|
||||
return "LIBRARY"
|
||||
|
||||
def get_desc():
|
||||
return "Multi-nodal audio interface"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return "authors.txt"
|
||||
|
||||
def get_version():
|
||||
return "version.txt"
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'audio/river/debug.cpp',
|
||||
'audio/river/river.cpp',
|
||||
'audio/river/Manager.cpp',
|
||||
'audio/river/Interface.cpp',
|
||||
'audio/river/io/Group.cpp',
|
||||
'audio/river/io/Node.cpp',
|
||||
'audio/river/io/NodeOrchestra.cpp',
|
||||
'audio/river/io/NodePortAudio.cpp',
|
||||
'audio/river/io/NodeAEC.cpp',
|
||||
'audio/river/io/NodeMuxer.cpp',
|
||||
'audio/river/io/Manager.cpp'
|
||||
])
|
||||
my_module.add_header_file([
|
||||
'audio/river/river.h',
|
||||
'audio/river/Manager.h',
|
||||
'audio/river/Interface.h',
|
||||
'audio/river/io/Group.h',
|
||||
'audio/river/io/Node.h',
|
||||
'audio/river/io/Manager.h'
|
||||
])
|
||||
my_module.add_optionnal_depend('audio-orchestra', ["c++", "-DAUDIO_RIVER_BUILD_ORCHESTRA"])
|
||||
my_module.add_optionnal_depend('portaudio', ["c++", "-DAUDIO_RIVER_BUILD_PORTAUDIO"])
|
||||
my_module.add_depend(['audio', 'audio-drain', 'ejson'])
|
||||
my_module.add_path(tools.get_current_path(__file__))
|
||||
return my_module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import monkModule as module
|
||||
import monkTools as tools
|
||||
|
||||
def get_desc():
|
||||
return "river : Multiple flow input output audio"
|
||||
|
||||
|
||||
def create():
|
||||
# module name is 'edn' and type binary.
|
||||
myModule = module.Module(__file__, 'river', 'LIBRARY')
|
||||
# enable doculentation :
|
||||
myModule.set_website("http://heeroyui.github.io/river/")
|
||||
myModule.set_website_sources("http://github.com/heeroyui/river/")
|
||||
myModule.set_path(tools.get_current_path(__file__) + "/river/")
|
||||
myModule.set_path_general_doc(tools.get_current_path(__file__) + "/doc/")
|
||||
# add the currrent module at the
|
||||
return myModule
|
||||
|
31
sample/ioViewer/GLD_ioViewer.json
Normal file
31
sample/ioViewer/GLD_ioViewer.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"type":"BINARY",
|
||||
"sub-type":"TEST",
|
||||
"group-id":"com.atria-soft",
|
||||
"description":"Simpleaudio IO viewer and test ...",
|
||||
"license":"MPL-2",
|
||||
"license-file":"file://../../LICENSE",
|
||||
"maintainer":"file://../../authors.txt",
|
||||
"author":"file://../../authors.txt",
|
||||
"version":"file://../../version.txt",
|
||||
"code-quality":"MEDIUM",
|
||||
|
||||
"source": [
|
||||
"appl/debug.cpp",
|
||||
"appl/main.cpp",
|
||||
"appl/Windows.cpp"
|
||||
],
|
||||
"compilation-version": {
|
||||
"c++": 2017
|
||||
},
|
||||
"path": [
|
||||
"."
|
||||
],
|
||||
"dependency": [
|
||||
"ewol",
|
||||
"audio-river",
|
||||
"audio-river-widget"
|
||||
],
|
||||
"comment": "# set the package properties \n my_module.set_pkg(SECTION, [Development]) \n my_module.set_pkg(PRIORITY, optional) \n my_module.add_pkg(RIGHT, RECORD_AUDIO)"
|
||||
}
|
||||
|
@@ -1,26 +1,26 @@
|
||||
/** @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.h>
|
||||
#include <appl/debug.h>
|
||||
#include <appl/Windows.h>
|
||||
#include <ewol/widget/Label.h>
|
||||
#include <ewol/widget/Button.h>
|
||||
#include <audio/river/widget/TemporalViewer.h>
|
||||
#include <etk/tool.h>
|
||||
#include <ewol/ewol.hpp>
|
||||
#include <appl/debug.hpp>
|
||||
#include <appl/Windows.hpp>
|
||||
#include <ewol/widget/Label.hpp>
|
||||
#include <ewol/widget/Button.hpp>
|
||||
#include <audio/river/widget/TemporalViewer.hpp>
|
||||
#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,12 +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 <ewol/widget/Windows.h>
|
||||
#include <ewol/widget/Composer.h>
|
||||
#include <ewol/widget/Windows.hpp>
|
||||
#include <ewol/widget/Composer.hpp>
|
||||
|
||||
namespace appl {
|
||||
class Windows : public ewol::widget::Windows {
|
@@ -1,10 +1,10 @@
|
||||
/** @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.h>
|
||||
#include <appl/debug.hpp>
|
||||
|
||||
|
||||
int32_t appl::getLogId() {
|
||||
|
@@ -1,11 +1,11 @@
|
||||
/** @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
|
||||
|
||||
#include <elog/log.h>
|
||||
#include <elog/log.hpp>
|
||||
|
||||
namespace appl {
|
||||
int32_t getLogId();
|
@@ -1,22 +1,23 @@
|
||||
/** @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)
|
||||
*/
|
||||
|
||||
|
||||
#include <etk/types.h>
|
||||
#include <ewol/ewol.h>
|
||||
#include <gale/context/commandLine.h>
|
||||
#include <etk/types.hpp>
|
||||
#include <ewol/ewol.hpp>
|
||||
#include <gale/context/commandLine.hpp>
|
||||
|
||||
#include <appl/debug.h>
|
||||
#include <appl/Windows.h>
|
||||
#include <ewol/object/Object.h>
|
||||
#include <ewol/widget/Manager.h>
|
||||
#include <ewol/context/Context.h>
|
||||
#include <audio/river/widget/TemporalViewer.h>
|
||||
#include <appl/debug.hpp>
|
||||
#include <appl/Windows.hpp>
|
||||
#include <ewol/object/Object.hpp>
|
||||
#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;
|
||||
|
||||
// add files
|
||||
APPL_INFO("show list of files : ");
|
||||
/*
|
||||
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
|
||||
etk::String tmpppp = _context.getCmd().get(iii);
|
||||
if (tmpppp.startWith("--ctags=") == true) {
|
||||
etk::String name = tmpppp.extract(8);
|
||||
APPL_INFO("Load ctag file : \"" << name << "\"" );
|
||||
appl::setCtagsFileName(name);
|
||||
} else if ( tmpppp == "-h"
|
||||
|| tmpppp == "--help") {
|
||||
// nothing to do ...
|
||||
} else {
|
||||
etk::Path file(tmpppp);
|
||||
if (etk::path::isFile(file) == true) {
|
||||
APPL_INFO("need load file : \"" << file << "\"" );
|
||||
m_bufferManager->open(file);
|
||||
} else if (etk::path::isDirectory(file) == true) {
|
||||
etk::Vector<etk::Path> listOfFiles = etk::path::list(file, etk::path::LIST_FILE);
|
||||
for (auto &it: listOfFiles) {
|
||||
if (etk::path::isFile(it) == true) {
|
||||
APPL_INFO("need load file : \"" << it << "\"" );
|
||||
m_bufferManager->open(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
APPL_INFO("==> START ... (END)");
|
||||
return;
|
||||
}
|
||||
void unInit(ewol::Context& _context) {
|
||||
APPL_INFO("==> Un-Init APPL (START)");
|
||||
// nothing to do...
|
||||
APPL_INFO("==> Un-Init APPL (END)");
|
||||
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,48 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
import datetime
|
||||
import os
|
||||
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_desc():
|
||||
return "Simpleaudio IO viewer and test ..."
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_extra_flags()
|
||||
my_module.add_src_file([
|
||||
'appl/debug.cpp',
|
||||
'appl/main.cpp',
|
||||
'appl/Windows.cpp'])
|
||||
my_module.add_depend(['ewol', 'audio-river', 'audio-river-widget'])
|
||||
my_module.add_path(tools.get_current_path(__file__))
|
||||
# set the package properties :
|
||||
my_module.set_pkg("VERSION", "1.0.0")
|
||||
my_module.set_pkg("VERSION_CODE", "1")
|
||||
my_module.set_pkg("COMPAGNY_TYPE", "org")
|
||||
my_module.set_pkg("COMPAGNY_NAME", "Edouard DUPIN")
|
||||
my_module.set_pkg("MAINTAINER", ["Mr DUPIN Edouard <yui.heero@gmail.com>"])
|
||||
my_module.set_pkg("SECTION", ["Development"])
|
||||
my_module.set_pkg("PRIORITY", "optional")
|
||||
my_module.set_pkg("DESCRIPTION", "Simple wiewer")
|
||||
my_module.set_pkg("NAME", "ioViewer")
|
||||
|
||||
my_module.add_pkg("RIGHT", "RECORD_AUDIO")
|
||||
return my_module
|
||||
|
24
sample/read/GLD_river-sample-read.json
Normal file
24
sample/read/GLD_river-sample-read.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"type":"BINARY",
|
||||
"sub-type":"TEST",
|
||||
"group-id":"com.atria-soft",
|
||||
"description":"Read some data",
|
||||
"license":"MPL-2",
|
||||
"license-file":"file://../../LICENSE",
|
||||
"maintainer":"file://../../authors.txt",
|
||||
"author":"file://../../authors.txt",
|
||||
"version":"file://../../version.txt",
|
||||
"code-quality":"MEDIUM",
|
||||
|
||||
"source": [
|
||||
"read.cpp"
|
||||
],
|
||||
"compilation-version": {
|
||||
"c++": 2017
|
||||
},
|
||||
"dependency": [
|
||||
"audio-river",
|
||||
"test-debug",
|
||||
"etk"
|
||||
]
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_sub_type():
|
||||
return "SAMPLE"
|
||||
|
||||
def get_desc():
|
||||
return "Read some data"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'main.cpp',
|
||||
])
|
||||
my_module.add_depend(['audio-river', 'etk'])
|
||||
return my_module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,147 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license APACHE v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/river.h>
|
||||
#include <audio/river/Manager.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <etk/etk.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
static const std::string configurationRiver =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'auto',\n"
|
||||
" name:'default',\n"
|
||||
//" timestamp-mode:'trigered',\n"
|
||||
" },\n"
|
||||
" frequency:0,\n"
|
||||
" channel-map:['front-left', 'front-right'],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
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,
|
||||
etk::FSNode* _outputNode) {
|
||||
if ( _format != audio::format_int16
|
||||
&& _format != audio::format_float) {
|
||||
std::cout << "[ERROR] call wrong type ... (need int16_t.float)" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (_outputNode->fileIsOpen() == false) {
|
||||
if (_format != audio::format_int16) {
|
||||
// get the curent power of the signal.
|
||||
const int16_t* data = static_cast<const int16_t*>(_data);
|
||||
int64_t value = 0;
|
||||
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
|
||||
value += std::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
std::cout << "Get data ... average=" << int32_t(value) << std::endl;
|
||||
} else {
|
||||
// get the curent power of the signal.
|
||||
const float* data = static_cast<const float*>(_data);
|
||||
float value = 0;
|
||||
for (size_t iii=0; iii<_nbChunk*_map.size(); ++iii) {
|
||||
value += std::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
std::cout << "Get data ... average=" << float(value) << std::endl;
|
||||
}
|
||||
} else {
|
||||
// just write data
|
||||
//std::cout << "Get data ... chunks=" << _nbChunk << " time=" << _time << std::endl;
|
||||
_outputNode->fileWrite(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int _argc, const char **_argv) {
|
||||
// the only one init for etk:
|
||||
etk::init(_argc, _argv);
|
||||
// local parameter:
|
||||
std::string configFile;
|
||||
std::string ioName="microphone";
|
||||
std::string outputFileName = "";
|
||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||
std::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;
|
||||
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;
|
||||
} else if (etk::start_with(data, "--io=") == true) {
|
||||
ioName = std::string(data.begin()+5, data.end());
|
||||
std::cout << "Select io: " << ioName << std::endl;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
// initialize river interface
|
||||
if (configFile == "") {
|
||||
audio::river::initString(configurationRiver);
|
||||
} else {
|
||||
audio::river::init(configFile);
|
||||
}
|
||||
// Create the River manager for tha application or part of the application.
|
||||
ememory::SharedPtr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read");
|
||||
// create interface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
//Get the generic input:
|
||||
interface = manager->createInput(48000,
|
||||
std::vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
ioName);
|
||||
if(interface == nullptr) {
|
||||
std::cout << "nullptr interface" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
etk::FSNode outputNode;
|
||||
// open output file if needed:
|
||||
if (outputFileName != "") {
|
||||
outputNode.setName(outputFileName);
|
||||
outputNode.fileOpenWrite();
|
||||
}
|
||||
// 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));
|
||||
// start the stream
|
||||
interface->start();
|
||||
// wait 10 second ...
|
||||
sleep(10);
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
// remove interface and manager.
|
||||
interface.reset();
|
||||
manager.reset();
|
||||
// close the output file
|
||||
if (outputFileName != "") {
|
||||
outputNode.fileClose();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
170
sample/read/read.cpp
Normal file
170
sample/read/read.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
//! [audio_river_sample_read_all]
|
||||
//! [audio_river_sample_include]
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/Manager.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
//! [audio_river_sample_include]
|
||||
#include <etk/etk.hpp>
|
||||
#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 etk::String configurationRiver =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'auto',\n"
|
||||
" name:'default',\n"
|
||||
//" timestamp-mode:'trigered',\n"
|
||||
" },\n"
|
||||
" frequency:0,\n"
|
||||
" channel-map:['front-left', 'front-right'],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
//! [audio_river_sample_read_config_file]
|
||||
|
||||
|
||||
//! [audio_river_sample_callback_implement]
|
||||
void onDataReceived(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
ememory::SharedPtr<etk::io::Interface> _fileIO) {
|
||||
if ( _format != audio::format_int16
|
||||
&& _format != audio::format_float) {
|
||||
TEST_ERROR("Call wrong type ... (need int16_t.float)");
|
||||
return;
|
||||
}
|
||||
//! [audio_river_sample_callback_implement]
|
||||
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 += etk::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
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 += etk::abs(data[iii]);
|
||||
}
|
||||
value /= (_nbChunk*_map.size());
|
||||
TEST_PRINT("Get data ... average=" << float(value));
|
||||
}
|
||||
} else {
|
||||
// just write data
|
||||
TEST_VERBOSE("Get data ... chunks=" << _nbChunk << " time=" << _time);
|
||||
_fileIO->write(_data, _map.size()*audio::getFormatBytes(_format), _nbChunk);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int _argc, const char **_argv) {
|
||||
//! [audio_river_sample_init]
|
||||
// the only one init for etk:
|
||||
etk::init(_argc, _argv);
|
||||
//! [audio_river_sample_init]
|
||||
// local parameter:
|
||||
etk::String configFile;
|
||||
etk::String ioName="microphone";
|
||||
etk::Path outputFileName = "";
|
||||
for (int32_t iii=0; iii<_argc ; ++iii) {
|
||||
etk::String data = _argv[iii];
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
TEST_PRINT("Help : ");
|
||||
TEST_PRINT(" --conf=xxx.json Input/output configuration");
|
||||
TEST_PRINT(" --io=xxx name configuration input");
|
||||
TEST_PRINT(" --file=yyy.raw File name to store data");
|
||||
exit(0);
|
||||
} else if (etk::start_with(data, "--conf=") == true) {
|
||||
configFile = etk::String(data.begin()+7, data.end());
|
||||
TEST_PRINT("Select config: " << configFile);
|
||||
} else if (etk::start_with(data, "--io=") == true) {
|
||||
ioName = etk::String(data.begin()+5, data.end());
|
||||
TEST_PRINT("Select io: " << ioName);
|
||||
} else if (etk::start_with(data, "--file=") == true) {
|
||||
outputFileName = etk::String(data.begin()+7, data.end());
|
||||
TEST_PRINT("Select output file name: " << outputFileName);
|
||||
}
|
||||
}
|
||||
// initialize river interface
|
||||
if (configFile == "") {
|
||||
audio::river::initString(configurationRiver);
|
||||
} else {
|
||||
audio::river::init(configFile);
|
||||
}
|
||||
//! [audio_river_sample_get_interface]
|
||||
// Create the River manager for tha application or part of the application.
|
||||
ememory::SharedPtr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read");
|
||||
//! [audio_river_sample_get_interface]
|
||||
//! [audio_river_sample_create_read_interface]
|
||||
// create interface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
//Get the generic input:
|
||||
interface = manager->createInput(48000,
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
ioName);
|
||||
if(interface == null) {
|
||||
TEST_ERROR("null interface");
|
||||
return -1;
|
||||
}
|
||||
//! [audio_river_sample_create_read_interface]
|
||||
ememory::SharedPtr<etk::io::Interface> fileIO = etk::uri::get(outputFileName);
|
||||
// open output file if needed:
|
||||
if (outputFileName.isEmpty() == false) {
|
||||
fileIO->open(etk::io::OpenMode::Write);
|
||||
}
|
||||
//! [audio_river_sample_set_callback]
|
||||
// set callback mode ...
|
||||
interface->setInputCallback([&](const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
onDataReceived(_data, _time, _nbChunk, _format, _frequency, _map, fileIO);
|
||||
});
|
||||
//! [audio_river_sample_set_callback]
|
||||
//! [audio_river_sample_read_start_stop]
|
||||
// start the stream
|
||||
interface->start();
|
||||
// wait 10 second ...
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
//! [audio_river_sample_read_start_stop]
|
||||
//! [audio_river_sample_read_reset]
|
||||
// remove interface and manager.
|
||||
interface.reset();
|
||||
manager.reset();
|
||||
//! [audio_river_sample_read_reset]
|
||||
// close the output file
|
||||
if (outputFileName != "") {
|
||||
fileIO->close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! [audio_river_sample_read_all]
|
24
sample/write/GLD_river-sample-write.json
Normal file
24
sample/write/GLD_river-sample-write.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"type":"BINARY",
|
||||
"sub-type":"TEST",
|
||||
"group-id":"com.atria-soft",
|
||||
"description":"Write some data",
|
||||
"license":"MPL-2",
|
||||
"license-file":"file://../../LICENSE",
|
||||
"maintainer":"file://../../authors.txt",
|
||||
"author":"file://../../authors.txt",
|
||||
"version":"file://../../version.txt",
|
||||
"code-quality":"MEDIUM",
|
||||
|
||||
"source": [
|
||||
"write.cpp"
|
||||
],
|
||||
"compilation-version": {
|
||||
"c++": 2017
|
||||
},
|
||||
"dependency": [
|
||||
"audio-river",
|
||||
"test-debug",
|
||||
"etk"
|
||||
]
|
||||
}
|
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_sub_type():
|
||||
return "SAMPLE"
|
||||
|
||||
def get_desc():
|
||||
return "Write some data"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'main.cpp',
|
||||
])
|
||||
my_module.add_depend(['audio-river', 'etk'])
|
||||
return my_module
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,23 +1,28 @@
|
||||
/** @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.h>
|
||||
#include <audio/river/Manager.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <etk/etk.h>
|
||||
#include <unistd.h>
|
||||
//! [audio_river_sample_write_all]
|
||||
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/Manager.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <etk/etk.hpp>
|
||||
#include <ethread/Thread.hpp>
|
||||
#include <ethread/tools.hpp>
|
||||
#include <test-debug/debug.hpp>
|
||||
|
||||
|
||||
static const std::string configurationRiver =
|
||||
//! [audio_river_sample_write_config_file]
|
||||
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"
|
||||
@@ -27,21 +32,23 @@ static const std::string configurationRiver =
|
||||
" volume-name:'MASTER'\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
//! [audio_river_sample_write_config_file]
|
||||
|
||||
static const int32_t nbChannelMax=8;
|
||||
|
||||
//! [audio_river_sample_callback_implement]
|
||||
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++) {
|
||||
@@ -54,16 +61,17 @@ void onDataNeeded(void* _data,
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [audio_river_sample_callback_implement]
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -71,29 +79,34 @@ int main(int _argc, const char **_argv) {
|
||||
audio::river::initString(configurationRiver);
|
||||
// Create the River manager for tha application or part of the application.
|
||||
ememory::SharedPtr<audio::river::Manager> manager = audio::river::Manager::create("river_sample_read");
|
||||
//! [audio_river_sample_create_write_interface]
|
||||
// create interface:
|
||||
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 ...
|
||||
sleep(10);
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
// remove interface and manager.
|
||||
@@ -102,3 +115,5 @@ int main(int _argc, const char **_argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! [audio_river_sample_write_all]
|
||||
|
@@ -1,55 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(audio_river_test)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
audio_river
|
||||
rosconsole
|
||||
)
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package()
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
include_directories(
|
||||
..
|
||||
${catkin_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
## Declare a cpp library
|
||||
catkin_add_gtest(${PROJECT_NAME}
|
||||
../debug.cpp
|
||||
../main.cpp
|
||||
)
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
${catkin_LIBRARIES}
|
||||
)
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
#install(TARGETS ${PROJECT_NAME}
|
||||
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
#)
|
||||
|
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>audio_river_test</name>
|
||||
<version>0.3.0</version>
|
||||
<description>Ewol River test</description>
|
||||
<maintainer email="yui.heero@gmail.com">Edouard DUPIN</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
<build_depend>gtest</build_depend>
|
||||
<build_depend>audio_river</build_depend>
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<run_depend>audio_river</run_depend>
|
||||
<run_depend>gtest</run_depend>
|
||||
</package>
|
@@ -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.h>
|
||||
#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);*/ \
|
||||
} \
|
||||
@@ -27,33 +27,21 @@
|
||||
|
||||
|
||||
|
||||
#include <audio/river/river.h>
|
||||
#include <audio/river/Manager.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <etk/etk.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
#include "testAEC.h"
|
||||
#include "testEchoDelay.h"
|
||||
#include "testFormat.h"
|
||||
#include "testMuxer.h"
|
||||
#include "testPlaybackCallback.h"
|
||||
#include "testPlaybackWrite.h"
|
||||
#include "testRecordCallback.h"
|
||||
#include "testRecordRead.h"
|
||||
#include "testVolume.h"
|
||||
#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>
|
||||
|
||||
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,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_aec {
|
||||
|
||||
@@ -14,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");
|
||||
@@ -52,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,
|
||||
@@ -72,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)");
|
||||
}
|
||||
@@ -83,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");
|
||||
@@ -116,7 +128,7 @@ namespace river_test_aec {
|
||||
}
|
||||
};
|
||||
|
||||
static const std::string configurationRiver =
|
||||
static const etk::String configurationRiver =
|
||||
"{\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
@@ -201,7 +213,7 @@ namespace river_test_aec {
|
||||
ememory::SharedPtr<Linker> processLink2 = ememory::makeShared<Linker>(manager, "microphone", "speaker-test");
|
||||
processLink1->start();
|
||||
processLink2->start();
|
||||
sleep(30);
|
||||
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.h>
|
||||
#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) {
|
||||
usleep(10000);
|
||||
ethread::sleepMilliSeconds((10));
|
||||
}
|
||||
usleep(10000000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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 ...
|
||||
usleep(1000000);
|
||||
ethread::sleepMilliSeconds(1000*(1));
|
||||
m_interface->stop();
|
||||
usleep(100000);
|
||||
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);
|
||||
process->run();
|
||||
process.reset();
|
||||
usleep(500000);
|
||||
for (auto itFrequency: listFreq) {
|
||||
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, itFrequency, 2, audio::format_int16);
|
||||
process->run();
|
||||
process.reset();
|
||||
ethread::sleepMilliSeconds((500));
|
||||
}
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(InstantiationName,
|
||||
testResampling,
|
||||
::testing::Values(4000, 8000, 16000, 32000, 48000, 48001, 64000, 96000, 11250, 2250, 44100, 88200));
|
||||
|
||||
|
||||
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());
|
||||
process->run();
|
||||
process.reset();
|
||||
usleep(500000);
|
||||
for (auto itFormat: listFormat) {
|
||||
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, 2, itFormat);
|
||||
process->run();
|
||||
process.reset();
|
||||
ethread::sleepMilliSeconds((500));
|
||||
}
|
||||
audio::river::unInit();
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(InstantiationName,
|
||||
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);
|
||||
process->run();
|
||||
process.reset();
|
||||
usleep(500000);
|
||||
for (auto itChannel: listChannel) {
|
||||
ememory::SharedPtr<testOutCallbackType> process = ememory::makeShared<testOutCallbackType>(manager, 48000, itChannel, audio::format_int16);
|
||||
process->run();
|
||||
process.reset();
|
||||
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();
|
||||
usleep(500000);
|
||||
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 <test-debug/debug.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();
|
||||
usleep(10000000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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 ...
|
||||
usleep(2000000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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 ...
|
||||
usleep(15000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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();
|
||||
usleep(1000000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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 <test-debug/debug.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 ...
|
||||
usleep(20000000);
|
||||
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();
|
||||
usleep(500000);
|
||||
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();
|
||||
usleep(1000000);
|
||||
ethread::sleepMilliSeconds(1000*(1));
|
||||
m_interface->setParameter("volume", "FLOW", "-3dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-6dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-9dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-12dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "-3dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "3dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "6dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "9dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_interface->setParameter("volume", "FLOW", "0dB");
|
||||
TEST_INFO(" get volume : " << m_interface->getParameter("volume", "FLOW") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_manager->setVolume("MASTER", -3.0f);
|
||||
TEST_INFO("get volume MASTER: " << m_manager->getVolume("MASTER") );
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
m_manager->setVolume("MEDIA", -3.0f);
|
||||
TEST_INFO("get volume MEDIA: " << m_manager->getVolume("MEDIA") );
|
||||
usleep(1000000);
|
||||
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();
|
||||
usleep(500000);
|
||||
ethread::sleepMilliSeconds((500));
|
||||
audio::river::unInit();
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
0.3.1
|
||||
1.0.0-dev
|
29
widget/GLD_audio-river-widget.json
Normal file
29
widget/GLD_audio-river-widget.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"type":"LIBRARY",
|
||||
"group-id":"com.atria-soft",
|
||||
"description":"audio specific widget",
|
||||
"license":"MPL-2",
|
||||
"license-file":"file://../LICENSE",
|
||||
"maintainer":"file://../authors.txt",
|
||||
"author":"file://../authors.txt",
|
||||
"version":"file://../version.txt",
|
||||
"code-quality":"MEDIUM",
|
||||
|
||||
"source": [
|
||||
"audio/river/widget/TemporalViewer.cpp",
|
||||
"audio/river/widget/debug.cpp"
|
||||
],
|
||||
"header": [
|
||||
"audio/river/widget/TemporalViewer.hpp"
|
||||
],
|
||||
"compilation-version": {
|
||||
"c++": 2017
|
||||
},
|
||||
"path":[
|
||||
"."
|
||||
],
|
||||
"dependency": [
|
||||
"ewol",
|
||||
"audio-river"
|
||||
]
|
||||
}
|
@@ -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.h>
|
||||
#include <audio/river/widget/TemporalViewer.h>
|
||||
#include <etk/tool.h>
|
||||
#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,23 +1,23 @@
|
||||
/** @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
|
||||
|
||||
#include <ewol/widget/Widget.h>
|
||||
#include <ewol/compositing/Drawing.h>
|
||||
#include <audio/river/river.h>
|
||||
#include <audio/river/Manager.h>
|
||||
#include <audio/river/Interface.h>
|
||||
#include <mutex>
|
||||
#include <ewol/widget/Widget.hpp>
|
||||
#include <ewol/compositing/Drawing.hpp>
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/Manager.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#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,10 +1,10 @@
|
||||
/** @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.h>
|
||||
#include <audio/river/widget/debug.hpp>
|
||||
|
||||
|
||||
int32_t audio::river::widget::getLogId() {
|
||||
|
@@ -1,11 +1,11 @@
|
||||
/** @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
|
||||
|
||||
#include <elog/log.h>
|
||||
#include <elog/log.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import lutin.module as module
|
||||
import lutin.tools as tools
|
||||
import lutin.debug as debug
|
||||
import os
|
||||
|
||||
|
||||
def get_type():
|
||||
return "LIBRARY"
|
||||
|
||||
def get_desc():
|
||||
return "audio specific widget"
|
||||
|
||||
def get_licence():
|
||||
return "APACHE-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return ["Mr DUPIN Edouard <yui.heero@gmail.com>"]
|
||||
|
||||
def get_version():
|
||||
return [0,0,0]
|
||||
|
||||
def create(target, module_name):
|
||||
my_module = module.Module(__file__, module_name, get_type())
|
||||
my_module.add_src_file([
|
||||
'audio/river/widget/TemporalViewer.cpp',
|
||||
'audio/river/widget/debug.cpp'
|
||||
])
|
||||
my_module.add_header_file([
|
||||
'audio/river/widget/TemporalViewer.h'
|
||||
])
|
||||
my_module.add_depend(['ewol', 'audio-river'])
|
||||
my_module.add_path(tools.get_current_path(__file__))
|
||||
return my_module
|
||||
|
||||
|
Reference in New Issue
Block a user