Compare commits
No commits in common. "main" and "gh-pages" have entirely different histories.
32
.gitignore
vendored
32
.gitignore
vendored
@ -1,32 +0,0 @@
|
||||
###################################
|
||||
# backup files
|
||||
###################################
|
||||
*~
|
||||
*.swp
|
||||
*.old
|
||||
*.bck
|
||||
|
||||
###################################
|
||||
# compiled files
|
||||
###################################
|
||||
*.pyc
|
||||
|
||||
###################################
|
||||
# Packages #
|
||||
###################################
|
||||
# it's better to unpack these files and commit the raw source
|
||||
# git has its own built in compression methods
|
||||
*.7z
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
|
||||
|
||||
###################################
|
||||
# out folder
|
||||
###################################
|
||||
out/
|
96
.travis.yml
96
.travis.yml
@ -1,7 +1,11 @@
|
||||
language: cpp
|
||||
language:
|
||||
- cpp
|
||||
|
||||
sudo: required
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
branches:
|
||||
only:
|
||||
@ -14,83 +18,39 @@ 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
|
||||
- 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 -
|
||||
|
||||
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
|
||||
|
||||
before_script:
|
||||
- cd ..
|
||||
- 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
|
||||
- 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/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
|
||||
- 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
|
||||
- pwd
|
||||
- ls -l
|
||||
- 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;
|
||||
- if [ "$BUILDER" == "gcc" ]; then COMPILATOR_OPTION="--compilator-version=4.9"; else COMPILATOR_OPTION=""; fi
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
36
Doxyfile
36
Doxyfile
@ -1,36 +0,0 @@
|
||||
PROJECT_NAME = river
|
||||
PROJECT_NUMBER = latest
|
||||
OUTPUT_DIRECTORY = dox/
|
||||
SORT_MEMBERS_CTORS_1ST = YES
|
||||
SORT_GROUP_NAMES = YES
|
||||
SORT_BY_SCOPE_NAME = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
RECURSIVE = YES
|
||||
EXTRACT_ALL = NO
|
||||
EXCLUDE_PATTERNS = */examples/*
|
||||
SOURCE_BROWSER = NO
|
||||
ALPHABETICAL_INDEX = NO
|
||||
GENERATE_HTML = YES
|
||||
#HTML_HEADER = /home/edupin/work/master-2015-02-04/doc/templates/doxygen/header.html
|
||||
#HTML_FOOTER = /home/edupin/work/master-2015-02-04/doc/templates/doxygen/footer.html
|
||||
#HTML_STYLESHEET = /home/edupin/work/master-2015-02-04/doc/templates/doxygen/doxygen.css
|
||||
GENERATE_TREEVIEW = YES
|
||||
CLASS_DIAGRAMS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = NO
|
||||
INCLUDE_GRAPH = NO
|
||||
INCLUDED_BY_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = NO
|
||||
DOT_MULTI_TARGETS = YES
|
||||
INPUT = river/
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = YES
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
BRIEF_MEMBER_DESC = NO
|
||||
VERBATIM_HEADERS = NO
|
||||
TAB_SIZE = 4
|
||||
#EXAMPLE_PATH = sample/
|
||||
GENERATE_XML = YES
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_TAGFILE = dox/ruver-doc.tag
|
373
LICENSE
373
LICENSE
@ -1,373 +0,0 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
88
README.md
88
README.md
@ -1,88 +1,4 @@
|
||||
audio-river
|
||||
===========
|
||||
------------------------------
|
||||
|
||||
`audio-river` is a High level hardware audio interface that connect to orchestra (multi-platform backend)
|
||||
|
||||
Release (master)
|
||||
----------------
|
||||
|
||||
[![Build Status](https://travis-ci.org/musicdsp/audio-river.svg?branch=master)](https://travis-ci.org/musicdsp/audio-river)
|
||||
[![Coverage Status](http://musicdsp.com/ci/coverage/musicdsp/audio-river.svg?branch=master)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Test Status](http://musicdsp.com/ci/test/musicdsp/audio-river.svg?branch=master)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Warning Status](http://musicdsp.com/ci/warning/musicdsp/audio-river.svg?branch=master)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=Linux)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=MacOs)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=Mingw)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=Android)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=master&tag=IOs)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
Developement (dev)
|
||||
------------------
|
||||
|
||||
[![Build Status](https://travis-ci.org/musicdsp/audio-river.svg?branch=dev)](https://travis-ci.org/musicdsp/audio-river)
|
||||
[![Coverage Status](http://musicdsp.com/ci/coverage/musicdsp/audio-river.svg?branch=dev)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Test Status](http://musicdsp.com/ci/test/musicdsp/audio-river.svg?branch=dev)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Warning Status](http://musicdsp.com/ci/warning/musicdsp/audio-river.svg?branch=dev)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=Linux)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=MacOs)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=Mingw)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=Android)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
[![Build Status](http://musicdsp.com/ci/build/musicdsp/audio-river.svg?branch=dev&tag=IOs)](http://musicdsp.com/ci/musicdsp/audio-river)
|
||||
|
||||
|
||||
Instructions
|
||||
============
|
||||
|
||||
download Build system:
|
||||
----------------------
|
||||
|
||||
sudo pip install lutin
|
||||
sudo pip install pillow
|
||||
|
||||
download the software:
|
||||
----------------------
|
||||
|
||||
mkdir WORKING_DIRECTORY
|
||||
cd WORKING_DIRECTORY
|
||||
git clone https://github.com/atria-soft/etk.git
|
||||
git clone https://github.com/atria-soft/elog.git
|
||||
git clone https://github.com/atria-soft/ememory.git
|
||||
git clone https://github.com/atria-soft/ethread.git
|
||||
git clone https://github.com/atria-soft/ejson.git
|
||||
git clone https://github.com/musicdsp/audio.git
|
||||
git clone https://github.com/musicdsp/audio-algo-drain.git
|
||||
git clone https://github.com/musicdsp/audio-algo-river.git
|
||||
git clone https://github.com/musicdsp/audio-algo-speex.git
|
||||
git clone https://github.com/musicdsp/audio-drain.git
|
||||
git clone https://github.com/musicdsp/audio-orchestra.git
|
||||
git clone https://github.com/musicdsp/audio-river.git
|
||||
git clone https://github.com/generic-library/gtest-lutin.git --recursive
|
||||
git clone https://github.com/generic-library/z-lutin.git --recursive
|
||||
git clone https://github.com/generic-library/speex-dsp-lutin.git --recursive
|
||||
|
||||
Compile software:
|
||||
-----------------
|
||||
|
||||
cd WORKING_DIRECTORY
|
||||
lutin -C -P audio-river-test?build?run
|
||||
|
||||
License (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.
|
||||
Nothing else ...
|
||||
|
||||
|
@ -1,522 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#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) {
|
||||
static uint32_t uid = 0;
|
||||
m_uid = uid++;
|
||||
|
||||
}
|
||||
|
||||
bool audio::river::Interface::init(float _freq,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
ememory::SharedPtr<audio::river::io::Node> _node,
|
||||
const ejson::Object& _config) {
|
||||
etk::Vector<audio::channel> map(_map);
|
||||
m_node = _node;
|
||||
m_config = _config;
|
||||
m_mode = audio::river::modeInterface_unknow;
|
||||
etk::String type = m_config["io"].toString().get("error");
|
||||
static int32_t uid=0;
|
||||
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") {
|
||||
m_mode = audio::river::modeInterface_input;
|
||||
} else if (type == "feedback") {
|
||||
m_mode = audio::river::modeInterface_feedback;
|
||||
}
|
||||
// register interface to be notify from the volume change.
|
||||
m_node->registerAsRemote(sharedFromThis());
|
||||
|
||||
if (map.size() == 0) {
|
||||
RIVER_INFO("Select auto map system ...");
|
||||
map = m_node->getInterfaceFormat().getMap();
|
||||
RIVER_INFO(" ==> " << map);
|
||||
}
|
||||
|
||||
// Create convertion interface
|
||||
if ( m_node->isInput() == true
|
||||
&& m_mode == audio::river::modeInterface_input) {
|
||||
m_process.setInputConfig(m_node->getInterfaceFormat());
|
||||
// Add volume only if the Low level has a volume (otherwise it will be added by the application)
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
|
||||
if (tmpVolume != null) {
|
||||
// add all time the volume stage :
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
|
||||
//algo->setInputFormat(m_node->getInterfaceFormat());
|
||||
algo->setName("volume");
|
||||
m_process.pushBack(algo);
|
||||
RIVER_INFO(" add volume for node");
|
||||
algo->addVolumeStage(tmpVolume);
|
||||
}
|
||||
m_process.setOutputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
|
||||
} else if ( m_node->isOutput() == true
|
||||
&& m_mode == audio::river::modeInterface_output) {
|
||||
m_process.setInputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
|
||||
// Add volume only if the Low level has a volume (otherwise it will be added by the application)
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = m_node->getVolume();
|
||||
if (tmpVolume != null) {
|
||||
// add all time the volume stage :
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = audio::drain::Volume::create();
|
||||
//algo->setOutputFormat(m_node->getInterfaceFormat());
|
||||
algo->setName("volume");
|
||||
m_process.pushBack(algo);
|
||||
RIVER_INFO(" add volume for node");
|
||||
algo->addVolumeStage(tmpVolume);
|
||||
}
|
||||
m_process.setOutputConfig(m_node->getInterfaceFormat());
|
||||
} else if ( m_node->isOutput() == true
|
||||
&& m_mode == audio::river::modeInterface_feedback) {
|
||||
m_process.setInputConfig(m_node->getHarwareFormat());
|
||||
// note : feedback has no volume stage ...
|
||||
m_process.setOutputConfig(audio::drain::IOFormatInterface(map, _format, _freq));
|
||||
} else {
|
||||
RIVER_ERROR("Can not link virtual interface with type : " << m_mode << " to a hardware interface " << (m_node->isInput()==true?"input":"output"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Interface::create(float _freq,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const ememory::SharedPtr<audio::river::io::Node>& _node,
|
||||
const ejson::Object& _config) {
|
||||
ememory::SharedPtr<audio::river::Interface> out = ememory::SharedPtr<audio::river::Interface>(ETK_NEW(audio::river::Interface));
|
||||
out->init(_freq, _map, _format, _node, _config);
|
||||
return out;
|
||||
}
|
||||
|
||||
audio::river::Interface::~Interface() {
|
||||
//stop(true, true);
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
//m_node->interfaceRemove(sharedFromThis());
|
||||
}
|
||||
/*
|
||||
bool audio::river::Interface::hasEndPoint() {
|
||||
|
||||
}
|
||||
*/
|
||||
void audio::river::Interface::setReadwrite() {
|
||||
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();
|
||||
m_process.pushBack(algo);
|
||||
} else {
|
||||
m_process.removeIfFirst<audio::drain::EndPoint>();
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = audio::drain::EndPointWrite::create();
|
||||
m_process.pushFront(algo);
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::Interface::setOutputCallback(audio::drain::playbackFunction _function) {
|
||||
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);
|
||||
m_process.pushFront(algo);
|
||||
}
|
||||
|
||||
void audio::river::Interface::setInputCallback(audio::drain::recordFunction _function) {
|
||||
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);
|
||||
m_process.pushBack(algo);
|
||||
}
|
||||
|
||||
void audio::river::Interface::setWriteCallback(audio::drain::playbackFunctionWrite _function) {
|
||||
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 == null) {
|
||||
return;
|
||||
}
|
||||
algo->setCallback(_function);
|
||||
}
|
||||
|
||||
void audio::river::Interface::start(const audio::Time& _time) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("start [BEGIN]");
|
||||
m_process.updateInterAlgo();
|
||||
m_node->interfaceAdd(sharedFromThis());
|
||||
RIVER_DEBUG("start [ END ]");
|
||||
}
|
||||
|
||||
void audio::river::Interface::stop(bool _fast, bool _abort) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("stop [BEGIN]");
|
||||
m_node->interfaceRemove(sharedFromThis());
|
||||
RIVER_DEBUG("stop [ END]");
|
||||
}
|
||||
|
||||
void audio::river::Interface::abort() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("abort [BEGIN]");
|
||||
// TODO :...
|
||||
RIVER_DEBUG("abort [ END ]");
|
||||
}
|
||||
|
||||
bool audio::river::Interface::setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value) {
|
||||
RIVER_DEBUG("setParameter [BEGIN] : '" << _filter << "':'" << _parameter << "':'" << _value << "'");
|
||||
bool out = false;
|
||||
if ( _filter == "volume"
|
||||
&& _parameter != "FLOW") {
|
||||
RIVER_ERROR("Interface is not allowed to modify '" << _parameter << "' Volume just allowed to modify 'FLOW' volume");
|
||||
return false;
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::Algo> algo = m_process.get<audio::drain::Algo>(_filter);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
|
||||
return false;
|
||||
}
|
||||
out = algo->setParameter(_parameter, _value);
|
||||
RIVER_DEBUG("setParameter [ END ] : '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
etk::String audio::river::Interface::getParameter(const etk::String& _filter, const etk::String& _parameter) const {
|
||||
RIVER_DEBUG("getParameter [BEGIN] : '" << _filter << "':'" << _parameter << "'");
|
||||
etk::String out;
|
||||
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
|
||||
return "[ERROR]";
|
||||
}
|
||||
out = algo->getParameter(_parameter);
|
||||
RIVER_DEBUG("getParameter [ END ] : '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
etk::String audio::river::Interface::getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const {
|
||||
RIVER_DEBUG("getParameterProperty [BEGIN] : '" << _filter << "':'" << _parameter << "'");
|
||||
etk::String out;
|
||||
ememory::SharedPtr<const audio::drain::Algo> algo = m_process.get<const audio::drain::Algo>(_filter);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("setParameter(" << _filter << ") ==> no filter named like this ...");
|
||||
return "[ERROR]";
|
||||
}
|
||||
out = algo->getParameterProperty(_parameter);
|
||||
RIVER_DEBUG("getParameterProperty [ END ] : '" << out << "'");
|
||||
return out;
|
||||
}
|
||||
|
||||
void audio::river::Interface::write(const void* _value, size_t _nbChunk) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_process.updateInterAlgo();
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == null) {
|
||||
return;
|
||||
}
|
||||
algo->write(_value, _nbChunk);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// TODO : add API aCCess mutex for Read and write...
|
||||
etk::Vector<int16_t> audio::river::Interface::read(size_t _nbChunk) {
|
||||
// TODO :...
|
||||
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) {
|
||||
ethread::sleepMilliSeconds((1));
|
||||
nbChunkBuffer = m_circularBuffer.size() / m_map.size();
|
||||
}
|
||||
m_mutex.lock();
|
||||
for (size_t iii = 0; iii<data.size(); ++iii) {
|
||||
data[iii] = m_circularBuffer[iii];
|
||||
}
|
||||
m_circularBuffer.erase(m_circularBuffer.begin(), m_circularBuffer.begin()+data.size());
|
||||
m_mutex.unlock();
|
||||
*/
|
||||
return data;
|
||||
}
|
||||
#endif
|
||||
|
||||
void audio::river::Interface::read(void* _value, size_t _nbChunk) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_process.updateInterAlgo();
|
||||
// TODO :...
|
||||
|
||||
}
|
||||
|
||||
size_t audio::river::Interface::size() const {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
// TODO :...
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void audio::river::Interface::setBufferSize(size_t _nbChunk) {
|
||||
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 == null) {
|
||||
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return;
|
||||
}
|
||||
algo->setBufferSize(_nbChunk);
|
||||
return;
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
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 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 == null) {
|
||||
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return;
|
||||
}
|
||||
algo->setBufferSize(_time);
|
||||
return;
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request set buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return;
|
||||
}
|
||||
algo->setBufferSize(_time);
|
||||
}
|
||||
|
||||
size_t audio::river::Interface::getBufferSize() {
|
||||
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 == 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 == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return 0;
|
||||
}
|
||||
return algo->getBufferSize();
|
||||
}
|
||||
|
||||
echrono::microseconds audio::river::Interface::getBufferSizeMicrosecond() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
if (m_node->isInput() == true) {
|
||||
ememory::SharedPtr<audio::drain::EndPointRead> algo = m_process.get<audio::drain::EndPointRead>(m_process.size()-1);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferSizeMicrosecond();
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferSizeMicrosecond();
|
||||
}
|
||||
|
||||
size_t audio::river::Interface::getBufferFillSize() {
|
||||
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 == 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 == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return 0;
|
||||
}
|
||||
return algo->getBufferFillSize();
|
||||
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferFillSizeMicrosecond();
|
||||
}
|
||||
ememory::SharedPtr<audio::drain::EndPointWrite> algo = m_process.get<audio::drain::EndPointWrite>(0);
|
||||
if (algo == null) {
|
||||
RIVER_ERROR("Request get buffer size for Interface that is not READ or WRITE mode ...");
|
||||
return echrono::microseconds(0);
|
||||
}
|
||||
return algo->getBufferFillSizeMicrosecond();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void audio::river::Interface::clearInternalBuffer() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_process.updateInterAlgo();
|
||||
// TODO :...
|
||||
|
||||
}
|
||||
|
||||
audio::Time audio::river::Interface::getCurrentTime() const {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
// TODO :...
|
||||
return audio::Time();
|
||||
return audio::Time::now();
|
||||
}
|
||||
|
||||
void audio::river::Interface::addVolumeGroup(const etk::String& _name) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
RIVER_DEBUG("addVolumeGroup(" << _name << ")");
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
|
||||
if (algo == null) {
|
||||
m_process.removeAlgoDynamic();
|
||||
// add all time the volume stage :
|
||||
algo = audio::drain::Volume::create();
|
||||
algo->setName("volume");
|
||||
if (m_node->isInput() == true) {
|
||||
m_process.pushFront(algo);
|
||||
} else {
|
||||
m_process.pushBack(algo);
|
||||
}
|
||||
}
|
||||
if (_name == "FLOW") {
|
||||
// Local volume name
|
||||
algo->addVolumeStage(ememory::makeShared<audio::drain::VolumeElement>(_name));
|
||||
} else {
|
||||
// get manager unique instance:
|
||||
ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
|
||||
algo->addVolumeStage(mng->getVolumeGroup(_name));
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::Interface::systemNewInputData(audio::Time _time, const void* _data, size_t _nbChunk) {
|
||||
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) {
|
||||
ethread::RecursiveLock lockProcess(m_mutex);
|
||||
//RIVER_INFO("time : " << _time);
|
||||
m_process.pull(_time, _data, _nbChunk, _chunkSize);
|
||||
}
|
||||
|
||||
void audio::river::Interface::systemVolumeChange() {
|
||||
ethread::RecursiveLock lockProcess(m_mutex);
|
||||
ememory::SharedPtr<audio::drain::Volume> algo = m_process.get<audio::drain::Volume>("volume");
|
||||
if (algo == null) {
|
||||
return;
|
||||
}
|
||||
algo->volumeChange();
|
||||
}
|
||||
|
||||
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second, bool _isLink=true) {
|
||||
if (_op == "->") {
|
||||
if (_isLink) {
|
||||
*_io << " " << _first << " -> " << _second << ";\n";
|
||||
} else {
|
||||
*_io << " " << _first << " -> " << _second << " [style=dashed];\n";
|
||||
}
|
||||
} else if (_op == "<-") {
|
||||
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
|
||||
if (_isLink) {
|
||||
*_io << " " << _second << " -> " << _first << " [constraint=false];\n";
|
||||
} else {
|
||||
*_io << " " << _second << " -> " << _first << " [constraint=false, style=dashed];\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
etk::String audio::river::Interface::getDotNodeName() const {
|
||||
if (m_mode == audio::river::modeInterface_input) {
|
||||
return "API_" + etk::toString(m_uid) + "_input";
|
||||
} else if (m_mode == audio::river::modeInterface_feedback) {
|
||||
return "API_" + etk::toString(m_uid) + "_feedback";
|
||||
} else if (m_mode == audio::river::modeInterface_output) {
|
||||
return "API_" + etk::toString(m_uid) + "_output";
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
void audio::river::Interface::generateDot(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _nameIO, bool _isLink) {
|
||||
*_io << " subgraph clusterInterface_" << m_uid << " {\n";
|
||||
*_io << " color=orange;\n";
|
||||
*_io << " label=\"[" << m_uid << "] Interface : " << m_name << "\";\n";
|
||||
etk::String nameIn;
|
||||
etk::String nameOut;
|
||||
if ( m_mode == audio::river::modeInterface_input
|
||||
|| m_mode == audio::river::modeInterface_feedback) {
|
||||
m_process.generateDot(_io, 3, 10000+m_uid, nameIn, nameOut, false);
|
||||
} else {
|
||||
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(_io, _nameIO, "->", nameIn, _isLink);
|
||||
} else {
|
||||
link(_io, _nameIO, "<-", nameOut, _isLink);
|
||||
}
|
||||
*_io << " node [shape=Mdiamond];\n";
|
||||
if (m_mode == audio::river::modeInterface_input) {
|
||||
*_io << " " << getDotNodeName() << " [ label=\"API\\nINPUT\" ];\n";
|
||||
link(_io, nameOut, "->", getDotNodeName());
|
||||
} else if (m_mode == audio::river::modeInterface_feedback) {
|
||||
*_io << " " << getDotNodeName() << " [ label=\"API\\nFEEDBACK\" ];\n";
|
||||
link(_io, nameOut, "->", getDotNodeName());
|
||||
} else if (m_mode == audio::river::modeInterface_output) {
|
||||
*_io << " " << getDotNodeName() << " [ label=\"API\\nOUTPUT\" ];\n";
|
||||
link(_io, nameIn, "<-", getDotNodeName());
|
||||
}
|
||||
*_io << " }\n \n";
|
||||
}
|
||||
|
@ -1,329 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <ethread/Mutex.hpp>
|
||||
#include <ethread/MutexRecursive.hpp>
|
||||
#include <echrono/echrono.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
#include <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 {
|
||||
namespace io {
|
||||
class Node;
|
||||
class NodeAirTAudio;
|
||||
class NodeAEC;
|
||||
class NodeMuxer;
|
||||
}
|
||||
enum modeInterface {
|
||||
modeInterface_unknow,
|
||||
modeInterface_input,
|
||||
modeInterface_output,
|
||||
modeInterface_feedback,
|
||||
};
|
||||
/**
|
||||
* @brief Interface is the basic handle to manage the input output stream
|
||||
* @note To create this class see @ref audio::river::Manager class
|
||||
*/
|
||||
class Interface : public ememory::EnableSharedFromThis<Interface> {
|
||||
friend class io::Node;
|
||||
friend class io::NodeAirTAudio;
|
||||
friend class io::NodeAEC;
|
||||
friend class io::NodeMuxer;
|
||||
friend class Manager;
|
||||
protected:
|
||||
uint32_t m_uid; //!< unique ID for interface
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor (use factory)
|
||||
*/
|
||||
Interface();
|
||||
/**
|
||||
* @brief Initilize the Class (do all that is not manage by constructor) Call by factory.
|
||||
* @param[in] _freq Frequency.
|
||||
* @param[in] _map Channel map organization.
|
||||
* @param[in] _format Sample format
|
||||
* @param[in] _node Low level interface to connect the flow.
|
||||
* @param[in] _config Special configuration of this interface.
|
||||
* @return true Configuration done corectly.
|
||||
* @return false the configuration has an error.
|
||||
*/
|
||||
bool init(float _freq,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
ememory::SharedPtr<audio::river::io::Node> _node,
|
||||
const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Factory of this interface (called by class audio::river::Manager)
|
||||
* @param[in] _freq Frequency.
|
||||
* @param[in] _map Channel map organization.
|
||||
* @param[in] _format Sample format
|
||||
* @param[in] _node Low level interface to connect the flow.
|
||||
* @param[in] _config Special configuration of this interface.
|
||||
* @return null The configuration does not work.
|
||||
* @return pointer The interface has been corectly created.
|
||||
*/
|
||||
static ememory::SharedPtr<Interface> create(float _freq,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const ememory::SharedPtr<audio::river::io::Node>& _node,
|
||||
const ejson::Object& _config);
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~Interface();
|
||||
protected:
|
||||
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)
|
||||
public:
|
||||
/**
|
||||
* @brief Get mode type of the current interface.
|
||||
* @return The mode requested.
|
||||
*/
|
||||
enum modeInterface getMode() {
|
||||
return m_mode;
|
||||
}
|
||||
protected:
|
||||
audio::drain::Process m_process; //!< Algorithme processing engine
|
||||
public:
|
||||
/**
|
||||
* @brief Get the interface format configuration.
|
||||
* @return The current format.
|
||||
*/
|
||||
const audio::drain::IOFormatInterface& getInterfaceFormat() {
|
||||
if ( m_mode == modeInterface_input
|
||||
|| m_mode == modeInterface_feedback) {
|
||||
return m_process.getOutputConfig();
|
||||
} else {
|
||||
return m_process.getInputConfig();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
ememory::SharedPtr<audio::river::io::Node> m_node; //!< Hardware interface to/from stream audio flow.
|
||||
protected:
|
||||
etk::String m_name; //!< Name of the interface.
|
||||
public:
|
||||
/**
|
||||
* @brief Get interface name.
|
||||
* @return The current name.
|
||||
*/
|
||||
virtual etk::String getName() {
|
||||
return m_name;
|
||||
};
|
||||
/**
|
||||
* @brief Set the interface name
|
||||
* @param[in] _name new name of the interface
|
||||
*/
|
||||
virtual void setName(const etk::String& _name) {
|
||||
m_name = _name;
|
||||
};
|
||||
/**
|
||||
* @brief set the read/write mode enable.
|
||||
* @note If you not set a output/input callback you must call this function.
|
||||
*/
|
||||
virtual void setReadwrite();
|
||||
/**
|
||||
* @brief When we want to implement a Callback Mode:
|
||||
*/
|
||||
/**
|
||||
* @brief Set a callback on the write mode interface to know when data is needed in the buffer
|
||||
* @param[in] _function Function to call
|
||||
*/
|
||||
virtual void setWriteCallback(audio::drain::playbackFunctionWrite _function);
|
||||
/**
|
||||
* @brief Set Output callback mode with the specify callback.
|
||||
* @param[in] _function Function to call
|
||||
*/
|
||||
virtual void setOutputCallback(audio::drain::playbackFunction _function);
|
||||
/**
|
||||
* @brief Set Input callback mode with the specify callback.
|
||||
* @param[in] _function Function to call
|
||||
*/
|
||||
virtual void setInputCallback(audio::drain::recordFunction _function);
|
||||
/**
|
||||
* @brief Add a volume group of the current channel.
|
||||
* @note If you do not call this function with the group "FLOW" you chan not have a channel volume.
|
||||
* @note the set volume stage can not be set after the start.
|
||||
* @param[in] _name Name of the group classicle common group:
|
||||
* - FLOW for channel volume.
|
||||
* - MEDIA for multimedia volume control (audio player, player video, web streaming ...).
|
||||
* - TTS for Test-to-speech volume control.
|
||||
* - COMMUNICATION for user communication volume control.
|
||||
* - NOTIFICATION for urgent notification volume control.
|
||||
* - NOISE for small noise volume control.
|
||||
*/
|
||||
virtual void addVolumeGroup(const etk::String& _name);
|
||||
public:
|
||||
/**
|
||||
* @brief Start the Audio interface flow.
|
||||
* @param[in] _time Time to start the flow (0) to start as fast as possible...
|
||||
* @note _time to play buffer when output interface (if possible)
|
||||
* @note _time to read buffer when inut interface (if possible)
|
||||
*/
|
||||
virtual void start(const audio::Time& _time = audio::Time());
|
||||
/**
|
||||
* @brief Stop the current flow.
|
||||
* @param[in] _fast The stream stop as fast as possible (not write all the buffer in speaker) but apply cross fade out.
|
||||
* @param[in] _abort The stream stop whith no garenty of good audio stop.
|
||||
*/
|
||||
virtual void stop(bool _fast=false, bool _abort=false);
|
||||
/**
|
||||
* @brief Abort flow (no audio garenty)
|
||||
*/
|
||||
virtual void abort();
|
||||
/**
|
||||
* @brief Set a parameter in the stream flow
|
||||
* @param[in] _filter name of the filter (if you added some personels)
|
||||
* @param[in] _parameter Parameter name.
|
||||
* @param[in] _value Value to set.
|
||||
* @return true set done
|
||||
* @return false An error occured
|
||||
* @example : setParameter("volume", "FLOW", "-3dB");
|
||||
* @example : setParameter("LowPassFilter", "cutFrequency", "1000Hz");
|
||||
*/
|
||||
virtual bool setParameter(const etk::String& _filter, const etk::String& _parameter, const etk::String& _value);
|
||||
/**
|
||||
* @brief Get a parameter value
|
||||
* @param[in] _filter name of the filter (if you added some personels)
|
||||
* @param[in] _parameter Parameter name.
|
||||
* @return The requested value.
|
||||
* @example : getParameter("volume", "FLOW"); can return something like "-3dB"
|
||||
* @example : getParameter("LowPassFilter", "cutFrequency"); can return something like "[-120..0]dB"
|
||||
*/
|
||||
virtual etk::String getParameter(const etk::String& _filter, const etk::String& _parameter) const;
|
||||
/**
|
||||
* @brief Get a parameter value
|
||||
* @param[in] _filter name of the filter (if you added some personels)
|
||||
* @param[in] _parameter Parameter name.
|
||||
* @return The requested value.
|
||||
* @example : getParameter("volume", "FLOW"); can return something like "[-120..0]dB"
|
||||
* @example : getParameter("LowPassFilter", "cutFreqiency"); can return something like "]100..10000]Hz"
|
||||
*/
|
||||
virtual etk::String getParameterProperty(const etk::String& _filter, const etk::String& _parameter) const;
|
||||
/**
|
||||
* @brief write some audio sample in the speakers
|
||||
* @param[in] _value Data To write on output
|
||||
* @param[in] _nbChunk Number of audio chunk to write
|
||||
*/
|
||||
// TODO : TimeOut ???
|
||||
virtual void write(const void* _value, size_t _nbChunk);
|
||||
/**
|
||||
* @brief read some audio sample from Microphone
|
||||
* @param[in] _value Data To write on output
|
||||
* @param[in] _nbChunk Number of audio chunk to write
|
||||
*/
|
||||
// TODO : TimeOut ???
|
||||
virtual void read(void* _value, size_t _nbChunk);
|
||||
/**
|
||||
* @brief Get number of chunk in the local buffer
|
||||
* @return Number of chunk
|
||||
*/
|
||||
virtual size_t size() const;
|
||||
/**
|
||||
* @brief Set buffer size in chunk number
|
||||
* @param[in] _nbChunk Number of chunk in the buffer
|
||||
*/
|
||||
virtual void setBufferSize(size_t _nbChunk);
|
||||
/**
|
||||
* @brief Set buffer size size of the buffer with the stored time in µs
|
||||
* @param[in] _time Time in microsecond of the buffer
|
||||
*/
|
||||
virtual void setBufferSize(const echrono::microseconds& _time);
|
||||
/**
|
||||
* @brief get buffer size in chunk number
|
||||
* @return Number of chunk that can be written in the buffer
|
||||
*/
|
||||
virtual size_t getBufferSize();
|
||||
/**
|
||||
* @brief Set buffer size size of the buffer with the stored time in µs
|
||||
* @return Time in microsecond that can be written in the buffer
|
||||
*/
|
||||
virtual echrono::microseconds getBufferSizeMicrosecond();
|
||||
/**
|
||||
* @brief Get buffer size filled in chunk number
|
||||
* @return Number of chunk in the buffer (that might be read/write)
|
||||
*/
|
||||
virtual size_t getBufferFillSize();
|
||||
/**
|
||||
* @brief Set buffer size size of the buffer with the stored time in µs
|
||||
* @return Time in microsecond of the buffer (that might be read/write)
|
||||
*/
|
||||
virtual echrono::microseconds getBufferFillSizeMicrosecond();
|
||||
/**
|
||||
* @brief Remove internal Buffer
|
||||
*/
|
||||
virtual void clearInternalBuffer();
|
||||
/**
|
||||
* @brief Write : Get the time of the next sample time to write in the local buffer
|
||||
* @brief Read : Get the time of the next sample time to read in the local buffer
|
||||
*/
|
||||
virtual audio::Time getCurrentTime() const;
|
||||
private:
|
||||
/**
|
||||
* @brief Node Call interface : Input interface node has new data.
|
||||
* @param[in] _time Time where the first sample has been capture.
|
||||
* @param[in] _data Pointer on the new data.
|
||||
* @param[in] _nbChunk Number of chunk in the buffer.
|
||||
*/
|
||||
virtual void systemNewInputData(audio::Time _time, const void* _data, size_t _nbChunk);
|
||||
/**
|
||||
* @brief Node Call interface: Output interface node need new data.
|
||||
* @param[in] _time Time where the data might be played
|
||||
* @param[in] _data Pointer on the data.
|
||||
* @param[in] _nbChunk Number of chunk that might be write
|
||||
* @param[in] _chunkSize Chunk size.
|
||||
*/
|
||||
virtual void systemNeedOutputData(audio::Time _time, void* _data, size_t _nbChunk, size_t _chunkSize);
|
||||
/**
|
||||
* @brief Node Call interface: A volume has change.
|
||||
*/
|
||||
virtual void systemVolumeChange();
|
||||
public:
|
||||
/**
|
||||
* @brief Create the dot in the FileNode stream.
|
||||
* @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(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 etk::String getDotNodeName() const;
|
||||
protected:
|
||||
/**
|
||||
* @brief Interfanel generate of status
|
||||
* @param[in] _origin status source
|
||||
* @param[in] _status Event status
|
||||
*/
|
||||
void generateStatus(const etk::String& _origin, const etk::String& _status) {
|
||||
m_process.generateStatus(_origin, _status);
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Set status callback
|
||||
* @param[in] _newFunction Function to call
|
||||
*/
|
||||
void setStatusFunction(audio::drain::statusFunction _newFunction) {
|
||||
m_process.setStatusFunction(_newFunction);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,243 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include "Manager.hpp"
|
||||
#include "Interface.hpp"
|
||||
#include "io/Manager.hpp"
|
||||
#include "io/Node.hpp"
|
||||
#include "debug.hpp"
|
||||
#include <ejson/ejson.hpp>
|
||||
|
||||
static ethread::Mutex g_mutex;
|
||||
static etk::Vector<ememory::WeakPtr<audio::river::Manager> > g_listOfAllManager;
|
||||
|
||||
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 == null) {
|
||||
continue;
|
||||
}
|
||||
if (tmp->m_applicationUniqueId == _applicationUniqueId) {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
// create a new one:
|
||||
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) {
|
||||
g_listOfAllManager[iii] = out;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
g_listOfAllManager.pushBack(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
audio::river::Manager::Manager(const etk::String& _applicationUniqueId) :
|
||||
m_applicationUniqueId(_applicationUniqueId),
|
||||
m_listOpenInterface() {
|
||||
|
||||
}
|
||||
|
||||
audio::river::Manager::~Manager() {
|
||||
// TODO : Stop all interfaces...
|
||||
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStreamInput();
|
||||
}
|
||||
return 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 == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStreamOutput();
|
||||
}
|
||||
return 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 == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStreamVirtual();
|
||||
}
|
||||
return 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 == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
} else {
|
||||
output = manager->getListStream();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return false;
|
||||
}
|
||||
return manager->setVolume(_volumeName, _valuedB);
|
||||
}
|
||||
|
||||
float audio::river::Manager::getVolume(const etk::String& _volumeName) const {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return false;
|
||||
}
|
||||
return manager->getVolume(_volumeName);
|
||||
}
|
||||
|
||||
etk::Pair<float,float> audio::river::Manager::getVolumeRange(const etk::String& _volumeName) const {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return etk::makePair<float,float>(0.0f,0.0f);
|
||||
}
|
||||
return manager->getVolumeRange(_volumeName);
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return;
|
||||
}
|
||||
manager->setMute(_volumeName, _mute);
|
||||
}
|
||||
|
||||
bool audio::river::Manager::getMute(const etk::String& _volumeName) const {
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
if (manager == null) {
|
||||
RIVER_ERROR("Unable to load harware IO manager ... ");
|
||||
return false;
|
||||
}
|
||||
return manager->getMute(_volumeName);
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createOutput(float _freq,
|
||||
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 == 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 == null) {
|
||||
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
if (node->isOutput() != true) {
|
||||
RIVER_ERROR("Can not Connect output on other thing than output ... for stream '" << _streamName << "'");;
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
// create user iterface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
ejson::Object tmpOption = ejson::Object(_options);
|
||||
tmpOption.add("io", ejson::String("output"));
|
||||
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption);
|
||||
// store it in a list (needed to apply some parameters).
|
||||
m_listOpenInterface.pushBack(interface);
|
||||
return interface;
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createInput(float _freq,
|
||||
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 == 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 == null) {
|
||||
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
if (node->isInput() != true) {
|
||||
RIVER_ERROR("Can not Connect input on other thing than input ... for stream '" << _streamName << "'");;
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
// create user iterface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
ejson::Object tmpOption = ejson::Object(_options);
|
||||
tmpOption.add("io", ejson::String("input"));
|
||||
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption);
|
||||
// store it in a list (needed to apply some parameters).
|
||||
m_listOpenInterface.pushBack(interface);
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
ememory::SharedPtr<audio::river::Interface> audio::river::Manager::createFeedback(float _freq,
|
||||
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 == 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 == null) {
|
||||
RIVER_ERROR("Can not get the Requested stream '" << _streamName << "' ==> not listed in : " << manager->getListStream());
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
if (node->isOutput() != true) {
|
||||
RIVER_ERROR("Can not Connect feedback on other thing than output ... for stream '" << _streamName << "'");;
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
// create user iterface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
ejson::Object tmpOption = ejson::Object(_options);
|
||||
tmpOption.add("io", ejson::String("feedback"));
|
||||
interface = audio::river::Interface::create(_freq, _map, _format, node, tmpOption);
|
||||
// store it in a list (needed to apply some parameters).
|
||||
m_listOpenInterface.pushBack(interface);
|
||||
return interface;
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Can not get the harware manager");
|
||||
return;
|
||||
}
|
||||
manager->generateDot(_filename);
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#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 {
|
||||
/**
|
||||
* @brief Audio interface manager : Single interface for every application that want to access on the Audio input/output
|
||||
*/
|
||||
class Manager : public ememory::EnableSharedFromThis<Manager> {
|
||||
private:
|
||||
const etk::String& m_applicationUniqueId; //!< name of the application that open the Audio Interface.
|
||||
etk::Vector<ememory::WeakPtr<audio::river::Interface> > m_listOpenInterface; //!< List of all open Stream.
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
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 null if an error occured
|
||||
*/
|
||||
static ememory::SharedPtr<audio::river::Manager> create(const etk::String& _applicationUniqueId);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~Manager();
|
||||
public:
|
||||
/**
|
||||
* @brief Get all input audio stream.
|
||||
* @return a list of all availlables input stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStreamInput();
|
||||
/**
|
||||
* @brief Get all output audio stream.
|
||||
* @return a list of all availlables output stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStreamOutput();
|
||||
/**
|
||||
* @brief Get all audio virtual stream.
|
||||
* @return a list of all availlables virtual stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStreamVirtual();
|
||||
/**
|
||||
* @brief Get all audio stream.
|
||||
* @return a list of all availlables stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStream();
|
||||
|
||||
/**
|
||||
* @brief Set a volume for a specific group
|
||||
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
|
||||
* @param[in] _value Volume in dB to set.
|
||||
* @return true set done
|
||||
* @return false An error occured
|
||||
* @example : setVolume("MASTER", -3.0f);
|
||||
*/
|
||||
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 etk::String& _volumeName) const;
|
||||
|
||||
/**
|
||||
* @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)
|
||||
*/
|
||||
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 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 etk::String& _volumeName) const;
|
||||
|
||||
/**
|
||||
* @brief Create output Interface
|
||||
* @param[in] _freq Frequency to open Interface [8,16,22,32,48] kHz
|
||||
* @param[in] _map ChannelMap of the Output
|
||||
* @param[in] _format Sample Format to open the stream [int8_t, int16_t, ...]
|
||||
* @param[in] _streamName Stream name to open: "" or "default" open current selected output
|
||||
* @param[in] _options Json option to configure default resampling and many other things.
|
||||
* @return a pointer on the interface
|
||||
*/
|
||||
virtual ememory::SharedPtr<Interface> createOutput(float _freq = 48000,
|
||||
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
|
||||
audio::format _format = audio::format_int16,
|
||||
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
|
||||
* @param[in] _map ChannelMap of the Output
|
||||
* @param[in] _format Sample Format to open the stream [int8_t, int16_t, ...]
|
||||
* @param[in] _streamName Stream name to open: "" or "default" open current selected input
|
||||
* @param[in] _options Json option to configure default resampling and many other things.
|
||||
* @return a pointer on the interface
|
||||
*/
|
||||
virtual ememory::SharedPtr<Interface> createInput(float _freq = 48000,
|
||||
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
|
||||
audio::format _format = audio::format_int16,
|
||||
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
|
||||
* @param[in] _map ChannelMap of the Output
|
||||
* @param[in] _format Sample Format to open the stream [int8_t, int16_t, ...]
|
||||
* @param[in] _streamName Stream name to open: "" or "default" open current selected input
|
||||
* @param[in] _options Json option to configure default resampling and many other things.
|
||||
* @return a pointer on the interface
|
||||
*/
|
||||
virtual ememory::SharedPtr<Interface> createFeedback(float _freq = 48000,
|
||||
const etk::Vector<audio::channel>& _map = etk::Vector<audio::channel>(),
|
||||
audio::format _format = audio::format_int16,
|
||||
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 etk::String& _filename);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/debug.hpp>
|
||||
|
||||
|
||||
int32_t audio::river::getLogId() {
|
||||
static int32_t g_val = elog::registerInstance("river");
|
||||
return g_val;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <elog/log.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
int32_t getLogId();
|
||||
}
|
||||
}
|
||||
#define RIVER_BASE(info,data) ELOG_BASE(audio::river::getLogId(),info,data)
|
||||
|
||||
#define RIVER_PRINT(data) RIVER_BASE(-1, data)
|
||||
#define RIVER_CRITICAL(data) RIVER_BASE(1, data)
|
||||
#define RIVER_ERROR(data) RIVER_BASE(2, data)
|
||||
#define RIVER_WARNING(data) RIVER_BASE(3, data)
|
||||
#ifdef DEBUG
|
||||
#define RIVER_INFO(data) RIVER_BASE(4, data)
|
||||
#define RIVER_DEBUG(data) RIVER_BASE(5, data)
|
||||
#define RIVER_VERBOSE(data) RIVER_BASE(6, data)
|
||||
#define RIVER_TODO(data) RIVER_BASE(4, "TODO : " << data)
|
||||
#else
|
||||
#define RIVER_INFO(data) do { } while(false)
|
||||
#define RIVER_DEBUG(data) do { } while(false)
|
||||
#define RIVER_VERBOSE(data) do { } while(false)
|
||||
#define RIVER_TODO(data) do { } while(false)
|
||||
#endif
|
||||
|
||||
#define RIVER_ASSERT(cond,data) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
RIVER_CRITICAL(data); \
|
||||
assert(!#cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define RIVER_SAVE_FILE_MACRO(type,fileName,dataPointer,nbElement) \
|
||||
do { \
|
||||
static FILE *pointerOnFile = null; \
|
||||
static bool errorOpen = false; \
|
||||
if (pointerOnFile == null) { \
|
||||
RIVER_WARNING("open file '" << fileName << "' type=" << #type); \
|
||||
pointerOnFile = fopen(fileName,"w"); \
|
||||
if ( errorOpen == false \
|
||||
&& pointerOnFile == null) { \
|
||||
RIVER_ERROR("ERROR OPEN file ... '" << fileName << "' type=" << #type); \
|
||||
errorOpen=true; \
|
||||
} \
|
||||
} \
|
||||
if (pointerOnFile != null) { \
|
||||
fwrite((dataPointer), sizeof(type), (nbElement), pointerOnFile); \
|
||||
/* fflush(pointerOnFile);*/ \
|
||||
} \
|
||||
}while(0)
|
||||
|
@ -1,17 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#undef RIVER_BASE
|
||||
#undef RIVER_CRITICAL
|
||||
#undef RIVER_ERROR
|
||||
#undef RIVER_WARNING
|
||||
#undef RIVER_INFO
|
||||
#undef RIVER_DEBUG
|
||||
#undef RIVER_VERBOSE
|
||||
#undef RIVER_TODO
|
||||
#undef RIVER_ASSERT
|
||||
|
@ -1,142 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/io/Group.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/io/NodeAEC.hpp>
|
||||
#include <audio/river/io/NodeOrchestra.hpp>
|
||||
#include <audio/river/io/NodePortAudio.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
etk::String groupName = tmpObject["group"].toString().get();
|
||||
if (groupName == _name) {
|
||||
RIVER_INFO("Add element in Group[" << _name << "]: " << _obj.getKey(iii));
|
||||
// get type : io
|
||||
etk::String ioType = tmpObject["io"].toString().get("error");
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
if ( ioType == "input"
|
||||
|| ioType == "output") {
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_obj.getKey(iii), tmpObject);
|
||||
tmp->setGroup(sharedFromThis());
|
||||
m_list.pushBack(tmp);
|
||||
}
|
||||
#endif
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
if ( ioType == "PAinput"
|
||||
|| ioType == "PAoutput") {
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_obj.getKey(iii), tmpObject);
|
||||
tmp->setGroup(sharedFromThis());
|
||||
m_list.pushBack(tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// Link all the IO together : (not needed if one device ...
|
||||
// Note : The interlink work only for alsa (NOW) and with AirTAudio...
|
||||
if(m_list.size() > 1) {
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
ememory::SharedPtr<audio::river::io::NodeOrchestra> linkRef = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_list[0]);
|
||||
for (size_t iii=1; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != null) {
|
||||
ememory::SharedPtr<audio::river::io::NodeOrchestra> link = ememory::dynamicPointerCast<audio::river::io::NodeOrchestra>(m_list[iii]);
|
||||
linkRef->m_interface.isMasterOf(link->m_interface);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
// manage Link Between Nodes :
|
||||
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 == null) {
|
||||
RIVER_ERROR("Can not link 2 Interface with not the same type (reserved for HW interface)");
|
||||
return;
|
||||
}
|
||||
link->m_adac.isMasterOf(m_adac);
|
||||
// TODO : Add return ...
|
||||
RIVER_INFO("******** LINK might be done ************");
|
||||
}
|
||||
*/
|
||||
RIVER_INFO("Create Group[" << _name << "] ( END ) ___________________________");
|
||||
RIVER_INFO("Group[" << _name << "] List elements : ");
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != null) {
|
||||
RIVER_INFO(" " << m_list[iii]->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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] != null) {
|
||||
if (m_list[iii]->getName() == _name) {
|
||||
return m_list[iii];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ememory::SharedPtr<audio::river::io::Node>();
|
||||
}
|
||||
|
||||
void audio::river::io::Group::start() {
|
||||
RIVER_ERROR("request start ");
|
||||
int32_t count = 0;
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != null) {
|
||||
count += m_list[iii]->getNumberOfInterface();
|
||||
}
|
||||
}
|
||||
RIVER_ERROR(" have " << count << " interfaces ...");
|
||||
if (count == 1) {
|
||||
RIVER_ERROR("GROUP :::::::::::: START() [START]");
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != null) {
|
||||
m_list[iii]->start();
|
||||
}
|
||||
}
|
||||
RIVER_ERROR("GROUP :::::::::::: START() [DONE]");
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Group::stop() {
|
||||
RIVER_ERROR("request stop ");
|
||||
int32_t count = 0;
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] != null) {
|
||||
count += m_list[iii]->getNumberOfInterface();
|
||||
}
|
||||
}
|
||||
RIVER_ERROR(" have " << count << " interfaces ...");
|
||||
if (count == 0) {
|
||||
RIVER_ERROR("GROUP :::::::::::: STOP() [START]");
|
||||
for (int32_t iii=m_list.size()-1; iii>=0; --iii) {
|
||||
if (m_list[iii] != null) {
|
||||
m_list[iii]->stop();
|
||||
}
|
||||
}
|
||||
RIVER_ERROR("GROUP :::::::::::: STOP() [DONE]");
|
||||
}
|
||||
}
|
||||
|
||||
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] != null) {
|
||||
if (m_list[iii]->isHarwareNode() == _hardwareNode) {
|
||||
m_list[iii]->generateDot(_io);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <ejson/ejson.hpp>
|
||||
#include <etk/io/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace io {
|
||||
class Node;
|
||||
class Manager;
|
||||
/**
|
||||
* @brief Group is contituate to manage some input and output in the same start and stop.
|
||||
* It link N interface in a group. The start and the sopt is requested in Node inside the
|
||||
* group they will start and stop when the first start is requested and stop when the last
|
||||
* is stopped.
|
||||
* @note For the Alsa interface a low level link is availlable with AirTAudio for Alsa (One thread)
|
||||
*/
|
||||
class Group : public ememory::EnableSharedFromThis<Group> {
|
||||
public:
|
||||
/**
|
||||
* @brief Contructor. No special thing to do.
|
||||
*/
|
||||
Group() {}
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Group() = default;
|
||||
private:
|
||||
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 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 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 etk::String& _name);
|
||||
/**
|
||||
* @brief Start the group.
|
||||
* @note all sub-node will be started.
|
||||
*/
|
||||
void start();
|
||||
/**
|
||||
* @brief Stop the group.
|
||||
* @note All sub-node will be stopped at the reserve order that they start.
|
||||
*/
|
||||
void stop();
|
||||
/**
|
||||
* @brief Create the dot in the FileNode stream.
|
||||
* @param[in,out] _node File node to write data.
|
||||
* @param[in] _hardwareNode true if user want only display the hardware
|
||||
* node and not the software node. false The oposite.
|
||||
*/
|
||||
void generateDot(ememory::SharedPtr<etk::io::Interface>& _node, bool _hardwareNode);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,426 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#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
|
||||
extern "C" {
|
||||
#include <portaudio/portaudio.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
static etk::String basicAutoConfig =
|
||||
"{\n"
|
||||
" microphone:{\n"
|
||||
" io:'input',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'auto',\n"
|
||||
" name:'default',\n"
|
||||
" },\n"
|
||||
" frequency:0,\n"
|
||||
" channel-map:[\n"
|
||||
" 'front-left', 'front-right'\n"
|
||||
" ],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024,\n"
|
||||
" mux-demux-type:'float'\n"
|
||||
" },\n"
|
||||
" speaker:{\n"
|
||||
" io:'output',\n"
|
||||
" map-on:{\n"
|
||||
" interface:'auto',\n"
|
||||
" name:'default',\n"
|
||||
" },\n"
|
||||
" frequency:0,\n"
|
||||
" channel-map:[\n"
|
||||
" 'front-left', 'front-right',\n"
|
||||
" ],\n"
|
||||
" type:'auto',\n"
|
||||
" nb-chunk:1024,\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
|
||||
PaError err = Pa_Initialize();
|
||||
if(err != paNoError) {
|
||||
RIVER_WARNING("Can not initialize portaudio : " << Pa_GetErrorText(err));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::init(const etk::Uri& _uri) {
|
||||
RIVER_ERROR("kjqsdhfkjqshdfkjqhsdskjdfhfkqjshqhskdjfhqsdfqsdqsdfqsdqsdfqsdfqsdfqsdfqsdfqsd");
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
if (_uri.isEmpty() == true) {
|
||||
if (m_config.load(pathToTheRiverConfigInHome) == false) {
|
||||
RIVER_INFO("Load default config");
|
||||
m_config.parse(basicAutoConfig);
|
||||
} else {
|
||||
RIVER_INFO("Load default user configuration: " << pathToTheRiverConfigInHome);
|
||||
}
|
||||
} else if (m_config.load(_uri) == false) {
|
||||
RIVER_ERROR("you must set a basic configuration file for harware configuration: " << _uri);
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::initString(const etk::String& _data) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
m_config.parse(_data);
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::unInit() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
// TODO : ...
|
||||
}
|
||||
|
||||
audio::river::io::Manager::~Manager() {
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
PaError err = Pa_Terminate();
|
||||
if(err != paNoError) {
|
||||
RIVER_WARNING("Can not initialize portaudio : " << Pa_GetErrorText(err));
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
ememory::SharedPtr<audio::river::io::Manager> audio::river::io::Manager::getInstance() {
|
||||
if (audio::river::isInit() == false) {
|
||||
return ememory::SharedPtr<audio::river::io::Manager>();
|
||||
}
|
||||
static ememory::SharedPtr<audio::river::io::Manager> manager(ETK_NEW(Manager));
|
||||
return manager;
|
||||
}
|
||||
|
||||
|
||||
etk::Vector<etk::String> audio::river::io::Manager::getListStreamInput() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
etk::Vector<etk::String> output;
|
||||
etk::Vector<etk::String> keys = m_config.getKeys();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type == "input"
|
||||
|| type == "PAinput") {
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
etk::Vector<etk::String> audio::river::io::Manager::getListStreamOutput() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
etk::Vector<etk::String> output;
|
||||
etk::Vector<etk::String> keys = m_config.getKeys();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type == "output"
|
||||
|| type == "PAoutput") {
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
etk::Vector<etk::String> audio::river::io::Manager::getListStreamVirtual() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
etk::Vector<etk::String> output;
|
||||
etk::Vector<etk::String> keys = m_config.getKeys();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type != "input"
|
||||
&& type != "PAinput"
|
||||
&& type != "output"
|
||||
&& type != "PAoutput"
|
||||
&& type != "error") {
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
etk::Vector<etk::String> audio::river::io::Manager::getListStream() {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
etk::Vector<etk::String> output;
|
||||
etk::Vector<etk::String> keys = m_config.getKeys();
|
||||
for (auto &it : keys) {
|
||||
const ejson::Object tmppp = m_config[it].toObject();
|
||||
if (tmppp.exist() == true) {
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if (type != "error") {
|
||||
output.pushBack(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
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 != null
|
||||
&& _name == tmppp->getName()) {
|
||||
RIVER_WARNING(" find it ... in standalone");
|
||||
return tmppp;
|
||||
}
|
||||
}
|
||||
// search in the group list:
|
||||
{
|
||||
for (etk::Map<etk::String, ememory::SharedPtr<audio::river::io::Group> >::Iterator it(m_listGroup.begin());
|
||||
it != m_listGroup.end();
|
||||
++it) {
|
||||
if (it->second != null) {
|
||||
ememory::SharedPtr<audio::river::io::Node> node = it->second->getNode(_name);
|
||||
if (node != null) {
|
||||
RIVER_WARNING(" find it ... in group: " << it->first);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RIVER_WARNING("Try create a new one : " << _name);
|
||||
// check if the node can be open :
|
||||
const ejson::Object tmpObject = m_config[_name].toObject();
|
||||
if (tmpObject.exist() == true) {
|
||||
//Check if it is in a group:
|
||||
etk::String groupName = tmpObject["group"].toString().get();
|
||||
// get type : io
|
||||
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 == null) {
|
||||
RIVER_WARNING("Can not get group ... '" << groupName << "'");
|
||||
return ememory::SharedPtr<audio::river::io::Node>();
|
||||
}
|
||||
return tmpGroup->getNode(_name);
|
||||
} else {
|
||||
if (groupName != "") {
|
||||
RIVER_WARNING("Group is only availlable for Hardware interface ... '" << _name << "'");
|
||||
}
|
||||
// TODO : Create a standalone group for every single element ==> simplify understanding ... but not for virtual interface ...
|
||||
|
||||
if ( ioType == "input"
|
||||
|| ioType == "output") {
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeOrchestra::create(_name, tmpObject);
|
||||
m_list.pushBack(tmp);
|
||||
return tmp;
|
||||
#else
|
||||
RIVER_WARNING("not present interface");
|
||||
#endif
|
||||
}
|
||||
if ( ioType == "PAinput"
|
||||
|| ioType == "PAoutput") {
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodePortAudio::create(_name, tmpObject);
|
||||
m_list.pushBack(tmp);
|
||||
return tmp;
|
||||
#else
|
||||
RIVER_WARNING("not present interface");
|
||||
#endif
|
||||
}
|
||||
if (ioType == "aec") {
|
||||
ememory::SharedPtr<audio::river::io::Node> tmp = audio::river::io::NodeAEC::create(_name, tmpObject);
|
||||
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.pushBack(tmp);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
RIVER_ERROR("Can not create the interface : '" << _name << "' the node is not DEFINED in the configuration file availlable : " << m_config.getKeys());
|
||||
return ememory::SharedPtr<audio::river::io::Node>();
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> audio::river::io::Manager::getVolumeGroup(const etk::String& _name) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
if (_name == "") {
|
||||
RIVER_ERROR("Try to create an audio group with no name ...");
|
||||
return ememory::SharedPtr<audio::drain::VolumeElement>();
|
||||
}
|
||||
for (size_t iii=0; iii<m_volumeGroup.size(); ++iii) {
|
||||
if (m_volumeGroup[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_volumeGroup[iii]->getName() == _name) {
|
||||
return m_volumeGroup[iii];
|
||||
}
|
||||
}
|
||||
RIVER_DEBUG("Add a new volume group : '" << _name << "'");
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> tmpVolume = ememory::makeShared<audio::drain::VolumeElement>(_name);
|
||||
m_volumeGroup.pushBack(tmpVolume);
|
||||
return tmpVolume;
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "'");
|
||||
return false;
|
||||
}
|
||||
if ( _valuedB < -300
|
||||
|| _valuedB > 300) {
|
||||
RIVER_ERROR("Can not set volume ... : '" << _volumeName << "' out of range : [-300..300]");
|
||||
return false;
|
||||
}
|
||||
volume->setVolume(_valuedB);
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
|
||||
if (val != null) {
|
||||
val->volumeChange();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
|
||||
return 0.0f;
|
||||
}
|
||||
return volume->getVolume();
|
||||
}
|
||||
|
||||
etk::Pair<float,float> audio::river::io::Manager::getVolumeRange(const etk::String& _volumeName) const {
|
||||
return etk::makePair<float,float>(-300, 300);
|
||||
}
|
||||
|
||||
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 == 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 != null) {
|
||||
val->volumeChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 == null) {
|
||||
RIVER_ERROR("Can not get volume ... : '" << _volumeName << "'");
|
||||
return false;
|
||||
}
|
||||
return volume->getMute();
|
||||
}
|
||||
|
||||
void audio::river::io::Manager::generateDot(const etk::Uri& _uri) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<etk::io::Interface> ioFile = etk::uri::get(_uri);
|
||||
RIVER_INFO("Generate the DOT files: " << _uri);
|
||||
if (ioFile->open(etk::io::OpenMode::Write) == false) {
|
||||
RIVER_ERROR("Can not Write the dot file (fail to open) : " << _uri);
|
||||
return;
|
||||
}
|
||||
*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 != null) {
|
||||
if (val->isHarwareNode() == true) {
|
||||
val->generateDot(ioFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (etk::Map<etk::String, ememory::SharedPtr<audio::river::io::Group> >::Iterator it(m_listGroup.begin());
|
||||
it != m_listGroup.end();
|
||||
++it) {
|
||||
if (it->second != null) {
|
||||
it->second->generateDot(ioFile, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// All other ...
|
||||
{
|
||||
// standalone
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
ememory::SharedPtr<audio::river::io::Node> val = m_list[iii].lock();
|
||||
if (val != null) {
|
||||
if (val->isHarwareNode() == false) {
|
||||
val->generateDot(ioFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (etk::Map<etk::String, ememory::SharedPtr<audio::river::io::Group> >::Iterator it(m_listGroup.begin());
|
||||
it != m_listGroup.end();
|
||||
++it) {
|
||||
if (it->second != null) {
|
||||
it->second->generateDot(ioFile, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ioFile << "}" << "\n";
|
||||
ioFile->close();
|
||||
RIVER_INFO("Generate the DOT files: " << _uri << " (DONE)");
|
||||
}
|
||||
|
||||
ememory::SharedPtr<audio::river::io::Group> audio::river::io::Manager::getGroup(const etk::String& _name) {
|
||||
ethread::RecursiveLock lock(m_mutex);
|
||||
ememory::SharedPtr<audio::river::io::Group> out;
|
||||
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 != null) {
|
||||
out->createFrom(m_config, _name);
|
||||
m_listGroup.add(_name, out);
|
||||
RIVER_INFO("Create a new group: " << _name << " ( END )");
|
||||
} else {
|
||||
RIVER_ERROR("Can not create new group: " << _name << " ( END )");
|
||||
}
|
||||
} else {
|
||||
out = it->second;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <etk/String.hpp>
|
||||
#include <etk/Vector.hpp>
|
||||
#include <etk/Map.hpp>
|
||||
#include <ethread/Mutex.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
#include <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 {
|
||||
namespace io {
|
||||
class Node;
|
||||
/**
|
||||
* @brief Internal sigleton of all Flow hadware and virtuals.
|
||||
* @note this class will be initialize by the audio::river::init() function at the start of the application.
|
||||
*/
|
||||
class Manager : public ememory::EnableSharedFromThis<Manager> {
|
||||
private:
|
||||
mutable ethread::MutexRecursive m_mutex; //!< prevent multiple access
|
||||
private:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
Manager();
|
||||
public:
|
||||
static ememory::SharedPtr<Manager> getInstance();
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~Manager();
|
||||
/**
|
||||
* @brief Called by audio::river::init() to set the hardware configuration file.
|
||||
* @param[in] _uri Uri file to initialize.
|
||||
*/
|
||||
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 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
|
||||
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 null if the node does not exist in the file or an error occured.
|
||||
*/
|
||||
ememory::SharedPtr<audio::river::io::Node> getNode(const etk::String& _name);
|
||||
private:
|
||||
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). null if the name is empty.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
etk::Vector<etk::String> getListStreamInput();
|
||||
/**
|
||||
* @brief Get all output audio stream.
|
||||
* @return a list of all availlables output stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStreamOutput();
|
||||
/**
|
||||
* @brief Get all audio virtual stream.
|
||||
* @return a list of all availlables virtual stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStreamVirtual();
|
||||
/**
|
||||
* @brief Get all audio stream.
|
||||
* @return a list of all availlables stream name
|
||||
*/
|
||||
etk::Vector<etk::String> getListStream();
|
||||
|
||||
/**
|
||||
* @brief Set a volume for a specific group
|
||||
* @param[in] _volumeName Name of the volume (MASTER, MATER_BT ...)
|
||||
* @param[in] _value Volume in dB to set.
|
||||
* @return true set done
|
||||
* @return false An error occured
|
||||
* @example : setVolume("MASTER", -3.0f);
|
||||
*/
|
||||
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 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)
|
||||
*/
|
||||
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 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 etk::String& _volumeName);
|
||||
/**
|
||||
* @brief Generate the dot file corresponding at the actif nodes.
|
||||
* @param[in] _uri Uri of the file to write data.
|
||||
*/
|
||||
void generateDot(const etk::Uri& _uri);
|
||||
private:
|
||||
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 null if the group does not existed.
|
||||
*/
|
||||
ememory::SharedPtr<audio::river::io::Group> getGroup(const etk::String& _name);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,497 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include "Node.hpp"
|
||||
#include <audio/river/debug.hpp>
|
||||
|
||||
audio::river::io::Node::Node(const etk::String& _name, const ejson::Object& _config) :
|
||||
m_config(_config),
|
||||
m_name(_name),
|
||||
m_isInput(false) {
|
||||
static uint32_t uid=0;
|
||||
m_uid = uid++;
|
||||
RIVER_INFO("-----------------------------------------------------------------");
|
||||
RIVER_INFO("-- CREATE NODE --");
|
||||
RIVER_INFO("-----------------------------------------------------------------");
|
||||
audio::drain::IOFormatInterface interfaceFormat;
|
||||
audio::drain::IOFormatInterface hardwareFormat;
|
||||
/**
|
||||
io:"input", # input, output or aec
|
||||
frequency:48000, # frequency to open device
|
||||
channel-map:[ # mapping of the harware device (to change map if needed)
|
||||
"front-left", "front-right",
|
||||
"read-left", "rear-right",
|
||||
],
|
||||
# format to open device (int8, int16, int16-on-ont32, int24, int32, float)
|
||||
type:"int16",
|
||||
# muxer/demuxer format type (int8-on-int16, int16-on-int32, int24-on-int32, int32-on-int64, float)
|
||||
mux-demux-type:"int16_on_int32",
|
||||
*/
|
||||
etk::String interfaceType = m_config["io"].toString().get();
|
||||
RIVER_INFO("interfaceType=" << interfaceType);
|
||||
if ( interfaceType == "input"
|
||||
|| interfaceType == "PAinput"
|
||||
|| interfaceType == "aec"
|
||||
|| interfaceType == "muxer") {
|
||||
m_isInput = true;
|
||||
} else {
|
||||
m_isInput = false;
|
||||
}
|
||||
|
||||
int32_t frequency = m_config["frequency"].toNumber().get(1);
|
||||
// Get audio format type:
|
||||
etk::String type = m_config["type"].toString().get("int16");
|
||||
enum audio::format formatType = audio::getFormatFromString(type);
|
||||
// Get volume stage :
|
||||
etk::String volumeName = m_config["volume-name"].toString().get();
|
||||
if (volumeName != "") {
|
||||
RIVER_INFO("add node volume stage : '" << volumeName << "'");
|
||||
// use global manager for volume ...
|
||||
m_volume = audio::river::io::Manager::getInstance()->getVolumeGroup(volumeName);
|
||||
}
|
||||
// Get map type :
|
||||
etk::Vector<audio::channel> map;
|
||||
const ejson::Array listChannelMap = m_config["channel-map"].toArray();
|
||||
if ( listChannelMap.exist() == false
|
||||
|| listChannelMap.size() == 0) {
|
||||
// set default channel property:
|
||||
map.pushBack(audio::channel_frontLeft);
|
||||
map.pushBack(audio::channel_frontRight);
|
||||
} else {
|
||||
for (auto it : listChannelMap) {
|
||||
etk::String value = it.toString().get();
|
||||
map.pushBack(audio::getChannelFromString(value));
|
||||
}
|
||||
}
|
||||
hardwareFormat.set(map, formatType, frequency);
|
||||
|
||||
|
||||
etk::String muxerDemuxerConfig;
|
||||
if (m_isInput == true) {
|
||||
muxerDemuxerConfig = m_config["mux-demux-type"].toString().get("int16");
|
||||
} else {
|
||||
muxerDemuxerConfig = m_config["mux-demux-type"].toString().get("int16-on-int32");
|
||||
}
|
||||
enum audio::format muxerFormatType = audio::getFormatFromString(muxerDemuxerConfig);
|
||||
if (m_isInput == true) {
|
||||
// Support all ...
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
// no map change and no frequency change ...
|
||||
interfaceFormat.set(map, muxerFormatType, frequency);
|
||||
// configure process interface
|
||||
if (m_isInput == true) {
|
||||
m_process.setInputConfig(hardwareFormat);
|
||||
m_process.setOutputConfig(interfaceFormat);
|
||||
} else {
|
||||
m_process.setOutputConfig(hardwareFormat);
|
||||
m_process.setInputConfig(interfaceFormat);
|
||||
}
|
||||
//m_process.updateInterAlgo();
|
||||
}
|
||||
|
||||
audio::river::io::Node::~Node() {
|
||||
RIVER_INFO("-----------------------------------------------------------------");
|
||||
RIVER_INFO("-- DESTROY NODE --");
|
||||
RIVER_INFO("-----------------------------------------------------------------");
|
||||
};
|
||||
|
||||
size_t audio::river::io::Node::getNumberOfInterface(enum audio::river::modeInterface _interfaceType) {
|
||||
size_t out = 0;
|
||||
for (size_t iii=0; iii<m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() == _interfaceType) {
|
||||
out++;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
size_t audio::river::io::Node::getNumberOfInterfaceAvaillable(enum audio::river::modeInterface _interfaceType) {
|
||||
size_t out = 0;
|
||||
for (size_t iii=0; iii<m_listAvaillable.size(); ++iii) {
|
||||
auto element = m_listAvaillable[iii].lock();
|
||||
if (element == null) {
|
||||
continue;
|
||||
}
|
||||
if (element->getMode() == _interfaceType) {
|
||||
out++;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void audio::river::io::Node::registerAsRemote(const ememory::SharedPtr<audio::river::Interface>& _interface) {
|
||||
auto it = m_listAvaillable.begin();
|
||||
while (it != m_listAvaillable.end()) {
|
||||
if (it->expired() == true) {
|
||||
it = m_listAvaillable.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
m_listAvaillable.pushBack(_interface);
|
||||
}
|
||||
|
||||
void audio::river::io::Node::interfaceAdd(const ememory::SharedPtr<audio::river::Interface>& _interface) {
|
||||
{
|
||||
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.pushBack(_interface);
|
||||
}
|
||||
if (m_list.size() == 1) {
|
||||
startInGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Node::interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface) {
|
||||
{
|
||||
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);
|
||||
RIVER_INFO("RM interface for stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_list.size() == 0) {
|
||||
stopInGroup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio::river::io::Node::volumeChange() {
|
||||
for (size_t iii=0; iii< m_listAvaillable.size(); ++iii) {
|
||||
auto node = m_listAvaillable[iii].lock();
|
||||
if (node != null) {
|
||||
node->systemVolumeChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Node::newInput(const void* _inputBuffer,
|
||||
uint32_t _nbChunk,
|
||||
const audio::Time& _time) {
|
||||
if (_inputBuffer == null) {
|
||||
return;
|
||||
}
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_input) {
|
||||
continue;
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName());
|
||||
m_list[iii]->systemNewInputData(_time, _inputBuffer, _nbChunk);
|
||||
}
|
||||
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [ END ]");
|
||||
return;
|
||||
}
|
||||
|
||||
void audio::river::io::Node::newOutput(void* _outputBuffer,
|
||||
uint32_t _nbChunk,
|
||||
const audio::Time& _time) {
|
||||
if (_outputBuffer == null) {
|
||||
return;
|
||||
}
|
||||
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] == 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());
|
||||
// $$$$ 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:
|
||||
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;
|
||||
}
|
||||
// The feedback get the real output data (after processing ...==> then no nneed to specify for each channels
|
||||
RIVER_VERBOSE(" Feedback :");
|
||||
for (size_t iii=0; iii< m_list.size(); ++iii) {
|
||||
if (m_list[iii] == null) {
|
||||
continue;
|
||||
}
|
||||
if (m_list[iii]->getMode() != audio::river::modeInterface_feedback) {
|
||||
continue;
|
||||
}
|
||||
RIVER_VERBOSE(" IO name="<< m_list[iii]->getName() << " (feedback) time=" << _time);
|
||||
m_list[iii]->systemNewInputData(_time, _outputBuffer, _nbChunk);
|
||||
}
|
||||
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [ END ]");
|
||||
return;
|
||||
}
|
||||
|
||||
static void link(ememory::SharedPtr<etk::io::Interface>& _io, const etk::String& _first, const etk::String& _op, const etk::String& _second) {
|
||||
if (_op == "->") {
|
||||
*_io << " " << _first << " -> " << _second << ";\n";
|
||||
} else if (_op == "<-") {
|
||||
*_io << " " << _first << " -> " <<_second<< " [color=transparent];\n";
|
||||
*_io << " " << _second << " -> " << _first << " [constraint=false];\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio::river::io::Node::generateDot(ememory::SharedPtr<etk::io::Interface>& _io) {
|
||||
*_io << " subgraph clusterNode_" << m_uid << " {\n";
|
||||
*_io << " color=blue;\n";
|
||||
*_io << " label=\"[" << m_uid << "] IO::Node : " << m_name << "\";\n";
|
||||
if (m_isInput == true) {
|
||||
*_io << " node [shape=rarrow];\n";
|
||||
*_io << " NODE_" << m_uid << "_HW_interface [ label=\"HW interface\\n interface=ALSA\\n stream=" << m_name << "\\n type=input\" ];\n";
|
||||
etk::String nameIn;
|
||||
etk::String nameOut;
|
||||
m_process.generateDotProcess(_io, 3, m_uid, nameIn, nameOut, false);
|
||||
*_io << " node [shape=square];\n";
|
||||
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
|
||||
// Link all nodes :
|
||||
*_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);
|
||||
*_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(_io, 3, m_uid, nameIn, nameOut, true);
|
||||
}
|
||||
*_io << " node [shape=square];\n";
|
||||
if (nbOutput>0) {
|
||||
*_io << " NODE_" << m_uid << "_muxer [ label=\"MUXER\\n format=" << etk::toString(m_process.getInputConfig().getFormat()) << "\" ];\n";
|
||||
}
|
||||
if (nbfeedback>0) {
|
||||
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
|
||||
}
|
||||
// Link all nodes :
|
||||
if (nbOutput>0) {
|
||||
link(_io, "NODE_" + etk::toString(m_uid) + "_HW_interface", "<-", nameOut);
|
||||
link(_io, nameIn, "<-", "NODE_" + etk::toString(m_uid) + "_muxer");
|
||||
}
|
||||
if (nbfeedback>0) {
|
||||
*_io << " NODE_" << m_uid << "_HW_interface -> NODE_" << m_uid << "_demuxer [arrowhead=\"open\"];\n";
|
||||
}
|
||||
if ( nbOutput>0
|
||||
&& nbfeedback>0) {
|
||||
*_io << " { rank=same; NODE_" << m_uid << "_demuxer; NODE_" << m_uid << "_muxer }\n";
|
||||
}
|
||||
|
||||
}
|
||||
*_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 == null) {
|
||||
continue;
|
||||
}
|
||||
bool isLink = false;
|
||||
for (size_t jjj=0; jjj<m_list.size(); ++jjj) {
|
||||
if (element == m_list[jjj]) {
|
||||
isLink = true;
|
||||
}
|
||||
}
|
||||
if (element != null) {
|
||||
if (element->getMode() == modeInterface_input) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_output) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_feedback) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio::river::io::Node::startInGroup() {
|
||||
ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
|
||||
if (group != null) {
|
||||
group->start();
|
||||
} else {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::Node::stopInGroup() {
|
||||
ememory::SharedPtr<audio::river::io::Group> group = m_group.lock();
|
||||
if (group != null) {
|
||||
group->stop();
|
||||
} else {
|
||||
stop();
|
||||
}
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#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 {
|
||||
namespace io {
|
||||
class Manager;
|
||||
class Group;
|
||||
/**
|
||||
* @brief A node is the base for input/output interface. When a output id declared, we automaticly have a feedback associated.
|
||||
* this manage the muxing of data for output an the demuxing for input.
|
||||
*/
|
||||
class Node : public ememory::EnableSharedFromThis<Node> {
|
||||
friend class audio::river::io::Group;
|
||||
protected:
|
||||
uint32_t m_uid; //!< uniqueNodeID use for debug an dot generation.
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param[in] _name Name of the node.
|
||||
* @param[in] _config Configuration of the node.
|
||||
*/
|
||||
Node(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~Node();
|
||||
/**
|
||||
* @brief Get the status of this node acces on harware or acces on other node (virtual).
|
||||
* @return true This is an harware interface.
|
||||
* @return false this is a virtual interface.
|
||||
*/
|
||||
virtual bool isHarwareNode() {
|
||||
return false;
|
||||
};
|
||||
protected:
|
||||
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
|
||||
public:
|
||||
/**
|
||||
* @brief Get the uper client interface configuration.
|
||||
* @return process configuration.
|
||||
*/
|
||||
const audio::drain::IOFormatInterface& getInterfaceFormat() {
|
||||
if (m_isInput == true) {
|
||||
return m_process.getOutputConfig();
|
||||
} else {
|
||||
return m_process.getInputConfig();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief Get the harware client interface configuration.
|
||||
* @return process configuration.
|
||||
*/
|
||||
const audio::drain::IOFormatInterface& getHarwareFormat() {
|
||||
if (m_isInput == true) {
|
||||
return m_process.getInputConfig();
|
||||
} else {
|
||||
return m_process.getOutputConfig();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
ememory::SharedPtr<audio::drain::VolumeElement> m_volume; //!< if a volume is set it is set here ... for hardware interface only.
|
||||
protected:
|
||||
etk::Vector<ememory::WeakPtr<audio::river::Interface> > m_listAvaillable; //!< List of all interface that exist on this Node
|
||||
etk::Vector<ememory::SharedPtr<audio::river::Interface> > m_list; //!< List of all connected interface at this node.
|
||||
/**
|
||||
* @brief Get the number of interface with a specific type.
|
||||
* @param[in] _interfaceType Type of the interface.
|
||||
* @return Number of interface connected.
|
||||
*/
|
||||
size_t getNumberOfInterface(enum audio::river::modeInterface _interfaceType);
|
||||
/**
|
||||
* @brief Get the number of interface with a specific type that can connect on the Node.
|
||||
* @param[in] _interfaceType Type of the interface.
|
||||
* @return Number of interface that can connect.
|
||||
*/
|
||||
size_t getNumberOfInterfaceAvaillable(enum audio::river::modeInterface _interfaceType);
|
||||
public:
|
||||
/**
|
||||
* @brief Get the number of interface connected
|
||||
* @return Number of interfaces.
|
||||
*/
|
||||
size_t getNumberOfInterface() {
|
||||
return m_list.size();
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Register an interface that can connect on it. (might be done in the Interface Init)
|
||||
* @note We keep a ememory::WeakPtr. this is the reason why we do not have a remove.
|
||||
* @param[in] _interface Pointer on the interface to register.
|
||||
*/
|
||||
void registerAsRemote(const ememory::SharedPtr<audio::river::Interface>& _interface);
|
||||
/**
|
||||
* @brief Request this interface might receve/send dat on the flow. (start/resume)
|
||||
* @param[in] _interface Pointer on the interface to register.
|
||||
*/
|
||||
void interfaceAdd(const ememory::SharedPtr<audio::river::Interface>& _interface);
|
||||
/**
|
||||
* @brief Un-register the interface as an availlable read/write interface. (suspend/stop)
|
||||
* @param[in] _interface Pointer on the interface to register.
|
||||
*/
|
||||
void interfaceRemove(const ememory::SharedPtr<audio::river::Interface>& _interface);
|
||||
protected:
|
||||
etk::String m_name; //!< Name of the interface
|
||||
public:
|
||||
/**
|
||||
* @brief Get the interface name.
|
||||
* @return Current name.
|
||||
*/
|
||||
const etk::String& getName() {
|
||||
return m_name;
|
||||
}
|
||||
protected:
|
||||
bool m_isInput; //!< sense of the stream
|
||||
public:
|
||||
/**
|
||||
* @brief Check if it is an input stream
|
||||
* @return true if it is an input/ false otherwise
|
||||
*/
|
||||
bool isInput() {
|
||||
return m_isInput;
|
||||
}
|
||||
/**
|
||||
* @brief Check if it is an output stream
|
||||
* @return true if it is an output/ false otherwise
|
||||
*/
|
||||
bool isOutput() {
|
||||
return !m_isInput;
|
||||
}
|
||||
protected:
|
||||
ememory::WeakPtr<audio::river::io::Group> m_group; //!< reference on the group. If available.
|
||||
public:
|
||||
/**
|
||||
* @brief Set this node in a low level group.
|
||||
* @param[in] _group Group reference.
|
||||
*/
|
||||
void setGroup(ememory::SharedPtr<audio::river::io::Group> _group) {
|
||||
m_group = _group;
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* @brief Start the flow in the group (start if no group)
|
||||
*/
|
||||
void startInGroup();
|
||||
/**
|
||||
* @brief Stop the flow in the group (stop if no group)
|
||||
*/
|
||||
void stopInGroup();
|
||||
/**
|
||||
* @brief Real start of the stream
|
||||
*/
|
||||
virtual void start() = 0;
|
||||
/**
|
||||
* @brief Real stop of the stream
|
||||
*/
|
||||
virtual void stop() = 0;
|
||||
public:
|
||||
/**
|
||||
* @brief If this iss an hardware interface we can have a resuest of the volume stage:
|
||||
* @return pointer on the requested volume.
|
||||
*/
|
||||
const ememory::SharedPtr<audio::drain::VolumeElement>& getVolume() {
|
||||
return m_volume;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Called when a group wolume has been change to update all volume stage.
|
||||
*/
|
||||
void volumeChange();
|
||||
protected:
|
||||
/**
|
||||
* @brief Call by child classes to process data in all interface linked on the current Node. Have new input to process.
|
||||
* @param[in] _inputBuffer Pointer on the data.
|
||||
* @param[in] _nbChunk Number of chunk in the buffer.
|
||||
* @param[in] _time Time where the first sample has been capture.
|
||||
*/
|
||||
void newInput(const void* _inputBuffer,
|
||||
uint32_t _nbChunk,
|
||||
const audio::Time& _time);
|
||||
/**
|
||||
* @brief Call by child classes to process data in all interface linked on the current Node. Have new output to get. this call the feedback too.
|
||||
* @param[in,out] _outputBuffer Pointer on the buffer to write the data.
|
||||
* @param[in] _nbChunk Number of chunk to write in the buffer.
|
||||
* @param[in] _time Time where the data might be played.
|
||||
*/
|
||||
void newOutput(void* _outputBuffer,
|
||||
uint32_t _nbChunk,
|
||||
const audio::Time& _time);
|
||||
public:
|
||||
/**
|
||||
* @brief Generate the node dot file section
|
||||
* @param[in] _io File interface to dump data.
|
||||
*/
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,367 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/io/NodeAEC.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
|
||||
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 etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
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>();
|
||||
}
|
||||
etk::String streamName = tmppp["map-on"].toString().get("error");
|
||||
|
||||
m_nbChunk = m_config["nb-chunk"].toNumber().get(1024);
|
||||
// check if it is an Output:
|
||||
etk::String type = tmppp["io"].toString().get("error");
|
||||
if ( type != "input"
|
||||
&& type != "feedback") {
|
||||
RIVER_ERROR("can not open in output a virtual interface: '" << streamName << "' configured has : " << type);
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
// get global hardware interface:
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
// get the output or input channel :
|
||||
ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(streamName);
|
||||
// create user iterface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp);
|
||||
if (interface != null) {
|
||||
interface->setName(_name);
|
||||
}
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
audio::river::io::NodeAEC::NodeAEC(const etk::String& _name, const ejson::Object& _config) :
|
||||
Node(_name, _config),
|
||||
m_P_attaqueTime(1),
|
||||
m_P_releaseTime(100),
|
||||
m_P_minimumGain(10),
|
||||
m_P_threshold(2),
|
||||
m_P_latencyTime(100) {
|
||||
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
||||
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||
m_sampleTime = audio::Duration(1000000000/int64_t(hardwareFormat.getFrequency()));
|
||||
/**
|
||||
# connect in input mode
|
||||
map-on-microphone:{
|
||||
# generic virtual definition
|
||||
io:"input",
|
||||
map-on:"microphone",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10"
|
||||
},
|
||||
# connect in feedback mode
|
||||
map-on-feedback:{
|
||||
io:"feedback",
|
||||
map-on:"speaker",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10",
|
||||
},
|
||||
# AEC algo definition
|
||||
algo:"river-remover",
|
||||
algo-mode:"cutter",
|
||||
*/
|
||||
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 == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-feedback in " << _name);
|
||||
return;
|
||||
}
|
||||
RIVER_INFO("Create MICROPHONE : ");
|
||||
m_interfaceMicrophone = createInput(hardwareFormat.getFrequency(),
|
||||
hardwareFormat.getMap(),
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-microphone",
|
||||
_name + "-AEC-microphone");
|
||||
if (m_interfaceMicrophone == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-microphone in " << _name);
|
||||
return;
|
||||
}
|
||||
|
||||
// set callback mode ...
|
||||
m_interfaceFeedBack->setInputCallback([=](const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
onDataReceivedFeedBack(_data, _time, _nbChunk, _format, _frequency, _map);
|
||||
});
|
||||
// set callback mode ...
|
||||
m_interfaceMicrophone->setInputCallback([=](const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
onDataReceivedMicrophone(_data, _time, _nbChunk, _format, _frequency, _map);
|
||||
});
|
||||
m_bufferMicrophone.setCapacity(echrono::milliseconds(1000),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat())*hardwareFormat.getMap().size(),
|
||||
hardwareFormat.getFrequency());
|
||||
m_bufferFeedBack.setCapacity(echrono::milliseconds(1000),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat()), // only one channel ...
|
||||
hardwareFormat.getFrequency());
|
||||
|
||||
m_process.updateInterAlgo();
|
||||
}
|
||||
|
||||
audio::river::io::NodeAEC::~NodeAEC() {
|
||||
RIVER_INFO("close input stream");
|
||||
stop();
|
||||
m_interfaceFeedBack.reset();
|
||||
m_interfaceMicrophone.reset();
|
||||
};
|
||||
|
||||
void audio::river::io::NodeAEC::start() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
|
||||
if (m_interfaceFeedBack != null) {
|
||||
RIVER_INFO("Start FEEDBACK : ");
|
||||
m_interfaceFeedBack->start();
|
||||
}
|
||||
if (m_interfaceMicrophone != null) {
|
||||
RIVER_INFO("Start Microphone : ");
|
||||
m_interfaceMicrophone->start();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodeAEC::stop() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (m_interfaceFeedBack != null) {
|
||||
m_interfaceFeedBack->stop();
|
||||
}
|
||||
if (m_interfaceMicrophone != null) {
|
||||
m_interfaceMicrophone->stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio::river::io::NodeAEC::onDataReceivedMicrophone(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
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
|
||||
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();
|
||||
}
|
||||
|
||||
void audio::river::io::NodeAEC::onDataReceivedFeedBack(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
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
|
||||
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();
|
||||
}
|
||||
|
||||
void audio::river::io::NodeAEC::process() {
|
||||
if ( m_bufferMicrophone.getSize() <= m_nbChunk
|
||||
|| m_bufferFeedBack.getSize() <= m_nbChunk) {
|
||||
return;
|
||||
}
|
||||
audio::Time MicTime = m_bufferMicrophone.getReadTimeStamp();
|
||||
audio::Time fbTime = m_bufferFeedBack.getReadTimeStamp();
|
||||
audio::Duration delta;
|
||||
if (MicTime < fbTime) {
|
||||
delta = fbTime - MicTime;
|
||||
} else {
|
||||
delta = MicTime - fbTime;
|
||||
}
|
||||
|
||||
RIVER_INFO("check delta " << delta << " > " << m_sampleTime);
|
||||
if (delta > m_sampleTime) {
|
||||
// Synchronize if possible
|
||||
if (MicTime < fbTime) {
|
||||
RIVER_INFO("micTime < fbTime : Change Microphone time start " << fbTime);
|
||||
RIVER_INFO(" old time stamp=" << m_bufferMicrophone.getReadTimeStamp());
|
||||
m_bufferMicrophone.setReadPosition(fbTime);
|
||||
RIVER_INFO(" new time stamp=" << m_bufferMicrophone.getReadTimeStamp());
|
||||
}
|
||||
if (MicTime > fbTime) {
|
||||
RIVER_INFO("micTime > fbTime : Change FeedBack time start " << MicTime);
|
||||
RIVER_INFO(" old time stamp=" << m_bufferFeedBack.getReadTimeStamp());
|
||||
m_bufferFeedBack.setReadPosition(MicTime);
|
||||
RIVER_INFO(" new time stamp=" << m_bufferFeedBack.getReadTimeStamp());
|
||||
}
|
||||
}
|
||||
// check if enought time after synchronisation ...
|
||||
if ( m_bufferMicrophone.getSize() <= m_nbChunk
|
||||
|| m_bufferFeedBack.getSize() <= m_nbChunk) {
|
||||
return;
|
||||
}
|
||||
|
||||
MicTime = m_bufferMicrophone.getReadTimeStamp();
|
||||
fbTime = m_bufferFeedBack.getReadTimeStamp();
|
||||
|
||||
if (MicTime-fbTime > m_sampleTime) {
|
||||
RIVER_ERROR("Can not synchronize flow ... : " << MicTime << " != " << fbTime << " delta = " << (MicTime-fbTime));
|
||||
return;
|
||||
}
|
||||
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));
|
||||
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());
|
||||
RIVER_SAVE_FILE_MACRO(int16_t, "REC_FeedBack_sync.raw", &dataFB[0], m_nbChunk);
|
||||
// if threaded : send event / otherwise, process ...
|
||||
processAEC(&dataMic[0], &dataFB[0], m_nbChunk, MicTime);
|
||||
if ( m_bufferMicrophone.getSize() <= m_nbChunk
|
||||
|| m_bufferFeedBack.getSize() <= m_nbChunk) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio::river::io::NodeAEC::processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const audio::Time& _time) {
|
||||
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||
// TODO : Set all these parameter in the parameter configuration section ...
|
||||
int32_t attaqueTime = etk::min(etk::max(0,m_P_attaqueTime),1000);
|
||||
int32_t releaseTime = etk::min(etk::max(0,m_P_releaseTime),1000);
|
||||
int32_t min_gain = 32767 * etk::min(etk::max(0,m_P_minimumGain),1000) / 1000;
|
||||
int32_t threshold = 32767 * etk::min(etk::max(0,m_P_threshold),1000) / 1000;
|
||||
|
||||
int32_t latencyTime = etk::min(etk::max(0,m_P_latencyTime),1000);
|
||||
int32_t nb_sample_latency = (hardwareFormat.getFrequency()/1000)*latencyTime;
|
||||
|
||||
int32_t increaseSample = 32767;
|
||||
if (attaqueTime != 0) {
|
||||
increaseSample = 32767/(hardwareFormat.getFrequency() * attaqueTime / 1000);
|
||||
}
|
||||
int32_t decreaseSample = 32767;
|
||||
if (attaqueTime != 0) {
|
||||
decreaseSample = 32767/(hardwareFormat.getFrequency() * releaseTime / 1000);
|
||||
}
|
||||
// Process section:
|
||||
int16_t* dataMic = static_cast<int16_t*>(_dataMic);
|
||||
int16_t* dataFB = static_cast<int16_t*>(_dataFB);
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
if (abs(*dataFB++) > threshold) {
|
||||
m_sampleCount = 0;
|
||||
} else {
|
||||
m_sampleCount++;
|
||||
}
|
||||
if (m_sampleCount > nb_sample_latency) {
|
||||
m_gainValue += decreaseSample;
|
||||
if (m_gainValue >= 32767) {
|
||||
m_gainValue = 32767;
|
||||
}
|
||||
} else {
|
||||
if (m_gainValue <= increaseSample) {
|
||||
m_gainValue = 0;
|
||||
} else {
|
||||
m_gainValue -= increaseSample;
|
||||
}
|
||||
if (m_gainValue < min_gain) {
|
||||
m_gainValue = min_gain;
|
||||
}
|
||||
}
|
||||
for (size_t jjj=0; jjj<hardwareFormat.getMap().size(); ++jjj) {
|
||||
*dataMic = static_cast<int16_t>((*dataMic * m_gainValue) >> 15);
|
||||
dataMic++;
|
||||
}
|
||||
}
|
||||
RIVER_SAVE_FILE_MACRO(int16_t, "REC_Microphone_clean.raw", _dataMic, _nbChunk*getHarwareFormat().getMap().size());
|
||||
// simply send to upper requester...
|
||||
newInput(_dataMic, _nbChunk, _time);
|
||||
}
|
||||
|
||||
|
||||
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 :
|
||||
*_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 != null) {
|
||||
*_io << " " << m_interfaceFeedBack->getDotNodeName() << " -> NODE_" << m_uid << "_HW_AEC;\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 == null) {
|
||||
continue;
|
||||
}
|
||||
bool isLink = false;
|
||||
for (size_t jjj=0; jjj<m_list.size(); ++jjj) {
|
||||
if (element == m_list[jjj]) {
|
||||
isLink = true;
|
||||
}
|
||||
}
|
||||
if (element != null) {
|
||||
if (element->getMode() == modeInterface_input) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_output) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_feedback) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/drain/CircularBuffer.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace io {
|
||||
class Manager;
|
||||
class NodeAEC : public Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
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 etk::String& _name, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~NodeAEC();
|
||||
protected:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
ememory::SharedPtr<audio::river::Interface> m_interfaceMicrophone; //!< Interface on the Microphone.
|
||||
ememory::SharedPtr<audio::river::Interface> m_interfaceFeedBack; //!< Interface on the feedback of speaker.
|
||||
/**
|
||||
* @brief Internal: create an input with the specific parameter:
|
||||
* @param[in] _freq Frequency.
|
||||
* @param[in] _map Channel map organization.
|
||||
* @param[in] _format Sample format
|
||||
* @param[in] _streamName
|
||||
* @param[in] _name
|
||||
* @return Interfae Pointer.
|
||||
*/
|
||||
ememory::SharedPtr<audio::river::Interface> createInput(float _freq,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
const etk::String& _streamName,
|
||||
const etk::String& _name);
|
||||
/**
|
||||
* @brief Stream data input callback
|
||||
* @todo : copy doc ..
|
||||
*/
|
||||
void onDataReceivedMicrophone(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map);
|
||||
/**
|
||||
* @brief Stream data input callback
|
||||
* @todo : copy doc ..
|
||||
*/
|
||||
void onDataReceivedFeedBack(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
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.
|
||||
audio::Duration m_sampleTime; //!< represent the sample time at the specify frequency.
|
||||
/**
|
||||
* @brief Process synchronization on the 2 flow.
|
||||
*/
|
||||
void process();
|
||||
/**
|
||||
* @brief Process algorithm on the current 2 syncronize flow.
|
||||
* @param[in] _dataMic Pointer in the Microphione interface.
|
||||
* @param[in] _dataFB Pointer on the beedback buffer.
|
||||
* @param[in] _nbChunk Number of chunk to process.
|
||||
* @param[in] _time Time on the firsta sample that data has been captured.
|
||||
* @return
|
||||
*/
|
||||
void processAEC(void* _dataMic, void* _dataFB, uint32_t _nbChunk, const audio::Time& _time);
|
||||
public:
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
|
||||
private:
|
||||
int32_t m_nbChunk;
|
||||
int32_t m_gainValue;
|
||||
int32_t m_sampleCount;
|
||||
|
||||
int32_t m_P_attaqueTime; //ms
|
||||
int32_t m_P_releaseTime; //ms
|
||||
int32_t m_P_minimumGain; // %
|
||||
int32_t m_P_threshold; // %
|
||||
int32_t m_P_latencyTime; // ms
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,281 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_FILE
|
||||
|
||||
#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 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t audio::river::io::NodeFile::playbackCallback(void* _outputBuffer,
|
||||
const audio::Time& _timeOutput,
|
||||
uint32_t _nbChunk,
|
||||
const etk::Vector<audio::orchestra::status>& _status) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
// TODO : Manage status ...
|
||||
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
|
||||
newOutput(_outputBuffer, _nbChunk, _timeOutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 etk::Path& _path, const ejson::Object& _config) :
|
||||
Node(_path.getString(), _config) {
|
||||
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
||||
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||
/**
|
||||
map-on:{ # select hardware interface and name
|
||||
interface:"alsa", # interface : "alsa", "pulse", "core", ...
|
||||
name:"default", # name of the interface
|
||||
},
|
||||
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
|
||||
*/
|
||||
etk::String typeInterface = audio::orchestra::type::undefined;
|
||||
etk::String streamName = "default";
|
||||
const ejson::Object tmpObject = m_config["map-on"].toObject();
|
||||
if (tmpObject.exist() == false) {
|
||||
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
|
||||
} else {
|
||||
typeInterface = tmpObject.getStringValue("interface", audio::orchestra::type::undefined);
|
||||
if (typeInterface == "auto") {
|
||||
typeInterface = audio::orchestra::type::undefined;
|
||||
}
|
||||
streamName = tmpObject.getStringValue("name", "default");
|
||||
}
|
||||
int32_t nbChunk = m_config.getNumberValue("nb-chunk", 1024);
|
||||
|
||||
// intanciate specific API ...
|
||||
m_interface.instanciate(typeInterface);
|
||||
m_interface.setName(_name);
|
||||
// TODO : Check return ...
|
||||
etk::String type = m_config.getStringValue("type", "int16");
|
||||
if (streamName == "") {
|
||||
streamName = "default";
|
||||
}
|
||||
|
||||
// search device ID :
|
||||
RIVER_INFO("Open :");
|
||||
RIVER_INFO(" m_streamName=" << streamName);
|
||||
RIVER_INFO(" m_freq=" << hardwareFormat.getFrequency());
|
||||
RIVER_INFO(" m_map=" << hardwareFormat.getMap());
|
||||
RIVER_INFO(" m_format=" << hardwareFormat.getFormat());
|
||||
RIVER_INFO(" m_isInput=" << m_isInput);
|
||||
int32_t deviceId = -1;
|
||||
/*
|
||||
// TODO : Remove this from here (create an extern interface ...)
|
||||
RIVER_INFO("Device list:");
|
||||
for (int32_t iii=0; iii<m_interface.getDeviceCount(); ++iii) {
|
||||
m_info = m_interface.getDeviceInfo(iii);
|
||||
RIVER_INFO(" " << iii << " name :" << m_info.name);
|
||||
m_info.display(2);
|
||||
}
|
||||
*/
|
||||
// special case for default IO:
|
||||
if (streamName == "default") {
|
||||
if (m_isInput == true) {
|
||||
deviceId = m_interface.getDefaultInputDevice();
|
||||
} else {
|
||||
deviceId = m_interface.getDefaultOutputDevice();
|
||||
}
|
||||
} else {
|
||||
for (int32_t iii=0; iii<m_interface.getDeviceCount(); ++iii) {
|
||||
m_info = m_interface.getDeviceInfo(iii);
|
||||
if (m_info.name == streamName) {
|
||||
RIVER_INFO(" Select ... id =" << iii);
|
||||
deviceId = iii;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO : Check if the devace with the specific name exist ...
|
||||
/*
|
||||
if (deviceId == -1) {
|
||||
RIVER_ERROR("Can not find the " << streamName << " audio interface ... (use O default ...)");
|
||||
deviceId = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Open specific ID :
|
||||
if (deviceId == -1) {
|
||||
m_info = m_interface.getDeviceInfo(streamName);
|
||||
} else {
|
||||
m_info = m_interface.getDeviceInfo(deviceId);
|
||||
}
|
||||
// display property :
|
||||
{
|
||||
RIVER_INFO("Device " << deviceId << " - '" << streamName << "' property :");
|
||||
m_info.display();
|
||||
|
||||
if (etk::isIn(hardwareFormat.getFormat(), m_info.nativeFormats) == false) {
|
||||
if (type == "auto") {
|
||||
if (etk::isIn(audio::format_int16, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_int16);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (etk::isIn(audio::format_float, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_float);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (etk::isIn(audio::format_int16_on_int32, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_int16_on_int32);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (etk::isIn(audio::format_int24, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_int24);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (m_info.nativeFormats.size() != 0) {
|
||||
hardwareFormat.setFormat(m_info.nativeFormats[0]);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else {
|
||||
RIVER_CRITICAL("auto set format no element in the configuration: " << m_info.nativeFormats);
|
||||
}
|
||||
} else {
|
||||
RIVER_CRITICAL("Can not manage input transforamtion: " << hardwareFormat.getFormat() << " not in " << m_info.nativeFormats);
|
||||
}
|
||||
}
|
||||
if (etk::isIn(hardwareFormat.getFrequency(), m_info.sampleRates) == false) {
|
||||
if (etk::isIn(48000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(48000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(44100, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(44100);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(32000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(32000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(16000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(16000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(8000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(8000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(96000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(96000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (m_info.sampleRates.size() != 0) {
|
||||
hardwareFormat.setFrequency(m_info.sampleRates[0]);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency() << "(first element in list) in " << m_info.sampleRates);
|
||||
} else {
|
||||
RIVER_CRITICAL("Can not manage input transforamtion:" << hardwareFormat.getFrequency() << " not in " << m_info.sampleRates);
|
||||
}
|
||||
interfaceFormat.setFrequency(hardwareFormat.getFrequency());
|
||||
}
|
||||
}
|
||||
|
||||
// open Audio device:
|
||||
audio::orchestra::StreamParameters params;
|
||||
params.deviceId = deviceId;
|
||||
params.deviceName = streamName;
|
||||
params.nChannels = hardwareFormat.getMap().size();
|
||||
if (m_info.channels.size() < params.nChannels) {
|
||||
RIVER_CRITICAL("Can not open hardware device with more channel (" << params.nChannels << ") that is autorized by hardware (" << m_info.channels.size() << ").");
|
||||
}
|
||||
audio::orchestra::StreamOptions option;
|
||||
etk::from_string(option.mode, tmpObject->getStringValue("timestamp-mode", "soft"));
|
||||
|
||||
RIVER_DEBUG("interfaceFormat=" << interfaceFormat);
|
||||
RIVER_DEBUG("hardwareFormat=" << hardwareFormat);
|
||||
|
||||
m_rtaudioFrameSize = nbChunk;
|
||||
RIVER_INFO("Open output stream nbChannels=" << params.nChannels);
|
||||
enum audio::orchestra::error err = audio::orchestra::error_none;
|
||||
if (m_isInput == true) {
|
||||
m_process.setInputConfig(hardwareFormat);
|
||||
m_process.setOutputConfig(interfaceFormat);
|
||||
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,
|
||||
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) {
|
||||
RIVER_ERROR("Create stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not create stream " << err);
|
||||
}
|
||||
m_process.updateInterAlgo();
|
||||
}
|
||||
|
||||
audio::river::io::NodeFile::~NodeFile() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("close input stream");
|
||||
if (m_interface.isStreamOpen() ) {
|
||||
m_interface.closeStream();
|
||||
}
|
||||
};
|
||||
|
||||
void audio::river::io::NodeFile::threadCallback() {
|
||||
etk::thread::setName("RIVER file-IO");
|
||||
// open the file
|
||||
|
||||
while (m_alive == true) {
|
||||
ethread::sleepMilliSeconds((100));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void audio::river::io::NodeFile::start() {
|
||||
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<ethread::Thread>(&audio::river::io::NodeFile::threadCallback2, this);
|
||||
m_time = audio::Time::now();
|
||||
}
|
||||
|
||||
void audio::river::io::NodeFile::stop() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
m_alive = false;
|
||||
RIVER_INFO("Stop stream : '" << m_name << "' mode=" << (m_isInput?"read":"write") );
|
||||
// TODO : Need join ...
|
||||
m_thread->join();
|
||||
m_thread.reset();
|
||||
}
|
||||
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_FILE
|
||||
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/orchestra/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace io {
|
||||
class Manager;
|
||||
class Group;
|
||||
/**
|
||||
* @brief Low level node that is manage on the interface with the extern lib airtaudio
|
||||
*/
|
||||
class NodeFile : public audio::river::io::Node {
|
||||
friend class audio::river::io::Group;
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeFile(const etk::Path& _path, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodeFile> create(const etk::Path& _path, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~NodeFile();
|
||||
virtual bool isHarwareNode() {
|
||||
return true;
|
||||
};
|
||||
protected:
|
||||
audio::Time m_time; //!< time of the flow
|
||||
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
|
||||
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();
|
||||
virtual void threadCallback():
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,487 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/io/NodeMuxer.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <etk/types.hpp>
|
||||
#include <ememory/memory.hpp>
|
||||
#include <etk/Function.hpp>
|
||||
|
||||
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 etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
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>();
|
||||
}
|
||||
etk::String streamName = tmppp["map-on"].toString().get("error");
|
||||
|
||||
|
||||
// check if it is an Output:
|
||||
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);
|
||||
return ememory::SharedPtr<audio::river::Interface>();
|
||||
}
|
||||
// get global hardware interface:
|
||||
ememory::SharedPtr<audio::river::io::Manager> manager = audio::river::io::Manager::getInstance();
|
||||
// get the output or input channel :
|
||||
ememory::SharedPtr<audio::river::io::Node> node = manager->getNode(streamName);
|
||||
// create user iterface:
|
||||
ememory::SharedPtr<audio::river::Interface> interface;
|
||||
interface = audio::river::Interface::create(_freq, _map, _format, node, tmppp);
|
||||
if (interface != null) {
|
||||
interface->setName(_name);
|
||||
}
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
m_sampleTime = audio::Duration(1000000000/int64_t(hardwareFormat.getFrequency()));
|
||||
/**
|
||||
# connect in input mode
|
||||
map-on-input-1:{
|
||||
# generic virtual definition
|
||||
io:"input",
|
||||
map-on:"microphone",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10"
|
||||
},
|
||||
# connect in feedback mode
|
||||
map-on-input-2:{
|
||||
io:"feedback",
|
||||
map-on:"speaker",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10",
|
||||
},
|
||||
input-2-remap:["rear-left", "rear-right"], # remap the IO inputs ...
|
||||
# AEC algo definition
|
||||
algo:"river-remover",
|
||||
algo-mode:"cutter",
|
||||
*/
|
||||
RIVER_INFO("Create IN 1 : ");
|
||||
m_interfaceInput1 = createInput(hardwareFormat.getFrequency(),
|
||||
etk::Vector<audio::channel>(),
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-input-1",
|
||||
_name + "-muxer-in1");
|
||||
if (m_interfaceInput1 == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-input-1 in " << _name);
|
||||
return;
|
||||
}
|
||||
const ejson::Array listChannelMap = m_config["input-1-remap"].toArray();
|
||||
if ( listChannelMap.exist() == false
|
||||
|| listChannelMap.size() == 0) {
|
||||
m_mapInput1 = m_interfaceInput1->getInterfaceFormat().getMap();
|
||||
} else {
|
||||
m_mapInput1.clear();
|
||||
for (const auto it : listChannelMap) {
|
||||
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=");
|
||||
m_mapInput1 = m_interfaceInput1->getInterfaceFormat().getMap();
|
||||
}
|
||||
}
|
||||
|
||||
RIVER_INFO("Create IN 2 : ");
|
||||
m_interfaceInput2 = createInput(hardwareFormat.getFrequency(),
|
||||
etk::Vector<audio::channel>(),
|
||||
hardwareFormat.getFormat(),
|
||||
"map-on-input-2",
|
||||
_name + "-muxer-in2");
|
||||
if (m_interfaceInput2 == null) {
|
||||
RIVER_ERROR("Can not opne virtual device ... map-on-input-2 in " << _name);
|
||||
return;
|
||||
}
|
||||
const ejson::Array listChannelMap2 = m_config["input-2-remap"].toArray();
|
||||
if ( listChannelMap2.exist() == false
|
||||
|| listChannelMap2.size() == 0) {
|
||||
m_mapInput2 = m_interfaceInput2->getInterfaceFormat().getMap();
|
||||
} else {
|
||||
m_mapInput2.clear();
|
||||
for (const auto it : listChannelMap2) {
|
||||
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=");
|
||||
m_mapInput2 = m_interfaceInput2->getInterfaceFormat().getMap();
|
||||
}
|
||||
}
|
||||
|
||||
// set callback mode ...
|
||||
m_interfaceInput1->setInputCallback([=](const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
onDataReceivedInput1(_data, _time, _nbChunk, _format, _frequency, _map);
|
||||
});
|
||||
// set callback mode ...
|
||||
m_interfaceInput2->setInputCallback([=](const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
onDataReceivedInput2(_data, _time, _nbChunk, _format, _frequency, _map);
|
||||
});
|
||||
|
||||
m_bufferInput1.setCapacity(echrono::milliseconds(1000),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat())*m_mapInput1.size(),
|
||||
hardwareFormat.getFrequency());
|
||||
m_bufferInput2.setCapacity(echrono::milliseconds(1000),
|
||||
audio::getFormatBytes(hardwareFormat.getFormat())*m_mapInput2.size(),
|
||||
hardwareFormat.getFrequency());
|
||||
|
||||
m_process.updateInterAlgo();
|
||||
}
|
||||
|
||||
audio::river::io::NodeMuxer::~NodeMuxer() {
|
||||
RIVER_INFO("close input stream");
|
||||
stop();
|
||||
m_interfaceInput1.reset();
|
||||
m_interfaceInput2.reset();
|
||||
};
|
||||
|
||||
void audio::river::io::NodeMuxer::start() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") );
|
||||
if (m_interfaceInput1 != null) {
|
||||
RIVER_INFO("Start FEEDBACK : ");
|
||||
m_interfaceInput1->start();
|
||||
}
|
||||
if (m_interfaceInput2 != null) {
|
||||
RIVER_INFO("Start Microphone : ");
|
||||
m_interfaceInput2->start();
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodeMuxer::stop() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
if (m_interfaceInput1 != null) {
|
||||
m_interfaceInput1->stop();
|
||||
}
|
||||
if (m_interfaceInput2 != null) {
|
||||
m_interfaceInput2->stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void audio::river::io::NodeMuxer::onDataReceivedInput1(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
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)) );
|
||||
/*
|
||||
if (_format != audio::format_int16) {
|
||||
RIVER_ERROR("call wrong type ... (need int16_t)");
|
||||
}
|
||||
*/
|
||||
// push data synchronize
|
||||
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();
|
||||
}
|
||||
|
||||
void audio::river::io::NodeMuxer::onDataReceivedInput2(const void* _data,
|
||||
const audio::Time& _time,
|
||||
size_t _nbChunk,
|
||||
enum audio::format _format,
|
||||
uint32_t _frequency,
|
||||
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)) );
|
||||
/*
|
||||
if (_format != audio::format_int16) {
|
||||
RIVER_ERROR("call wrong type ... (need int16_t)");
|
||||
}
|
||||
*/
|
||||
// push data synchronize
|
||||
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();
|
||||
}
|
||||
|
||||
void audio::river::io::NodeMuxer::process() {
|
||||
if (m_bufferInput1.getSize() <= 256) {
|
||||
return;
|
||||
}
|
||||
if (m_bufferInput2.getSize() <= 256) {
|
||||
return;
|
||||
}
|
||||
RIVER_PRINT("process : s1=" << m_bufferInput1.getSize() << " s2=" << m_bufferInput2.getSize());
|
||||
audio::Time in1Time = m_bufferInput1.getReadTimeStamp();
|
||||
audio::Time in2Time = m_bufferInput2.getReadTimeStamp();
|
||||
audio::Duration delta;
|
||||
if (in1Time < in2Time) {
|
||||
delta = in2Time - in1Time;
|
||||
} else {
|
||||
delta = in1Time - in2Time;
|
||||
}
|
||||
RIVER_VERBOSE("check delta " << delta << " > " << m_sampleTime);
|
||||
if (delta > m_sampleTime) {
|
||||
// Synchronize if possible
|
||||
if (in1Time < in2Time) {
|
||||
RIVER_INFO("in1Time < in2Time : Change Input-1 time start " << in2Time);
|
||||
RIVER_INFO(" old time stamp=" << m_bufferInput1.getReadTimeStamp());
|
||||
m_bufferInput1.setReadPosition(in2Time);
|
||||
RIVER_INFO(" new time stamp=" << m_bufferInput1.getReadTimeStamp());
|
||||
}
|
||||
if (in1Time > in2Time) {
|
||||
RIVER_INFO("in1Time > in2Time : Change Input-2 time start " << in1Time);
|
||||
RIVER_INFO(" old time stamp=" << m_bufferInput2.getReadTimeStamp());
|
||||
m_bufferInput2.setReadPosition(in1Time);
|
||||
RIVER_INFO(" new time stamp=" << m_bufferInput2.getReadTimeStamp());
|
||||
}
|
||||
}
|
||||
// check if enought time after synchronisation ...
|
||||
if (m_bufferInput1.getSize() <= 256) {
|
||||
return;
|
||||
}
|
||||
if (m_bufferInput2.getSize() <= 256) {
|
||||
return;
|
||||
}
|
||||
|
||||
in1Time = m_bufferInput1.getReadTimeStamp();
|
||||
in2Time = m_bufferInput2.getReadTimeStamp();
|
||||
|
||||
if (in1Time-in2Time > m_sampleTime) {
|
||||
RIVER_ERROR("Can not synchronize flow ... : " << in1Time << " != " << in2Time << " delta = " << (in1Time-in2Time));
|
||||
return;
|
||||
}
|
||||
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));
|
||||
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());
|
||||
//RIVER_SAVE_FILE_MACRO(int16_t, "REC_muxer_output_2.raw", &dataIn2[0], 256 * m_mapInput2.size());
|
||||
// if threaded : send event / otherwise, process ...
|
||||
processMuxer(&dataIn1[0], &dataIn2[0], 256, in1Time);
|
||||
if ( m_bufferInput1.getSize() <= 256
|
||||
|| m_bufferInput2.getSize() <= 256) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
{
|
||||
RIVER_VERBOSE("convert " << _mapInput << " ==> " << getInterfaceFormat().getMap());
|
||||
int8_t* in = static_cast<int8_t*>(_input);
|
||||
int8_t* out = static_cast<int8_t*>(_output);
|
||||
for (size_t kkk=0; kkk<getInterfaceFormat().getMap().size(); ++kkk) {
|
||||
int32_t convertId = -1;
|
||||
if ( _mapInput.size() == 1
|
||||
&& _mapInput[0] == audio::channel_frontCenter) {
|
||||
convertId = 0;
|
||||
} else {
|
||||
for (size_t jjj=0; jjj<_mapInput.size(); ++jjj) {
|
||||
if (getInterfaceFormat().getMap()[kkk] == _mapInput[jjj]) {
|
||||
convertId = jjj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
RIVER_VERBOSE(" " << convertId << " ==> " << kkk);
|
||||
if (convertId != -1) {
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
out[iii*getInterfaceFormat().getMap().size()+kkk] = in[iii*_mapInput.size()+convertId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case audio::format_int16:
|
||||
if (getInterfaceFormat().getMap().size() == 1) {
|
||||
RIVER_VERBOSE("convert " << _mapInput << " ==> " << getInterfaceFormat().getMap());
|
||||
int16_t* in = static_cast<int16_t*>(_input);
|
||||
int16_t* out = static_cast<int16_t*>(_output);
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
int32_t val = 0;
|
||||
for (size_t jjj=0; jjj<_mapInput.size(); ++jjj) {
|
||||
val += in[iii*_mapInput.size()+jjj];
|
||||
}
|
||||
out[iii] = val/_mapInput.size();
|
||||
}
|
||||
} else {
|
||||
RIVER_VERBOSE("convert " << _mapInput << " ==> " << getInterfaceFormat().getMap());
|
||||
int16_t* in = static_cast<int16_t*>(_input);
|
||||
int16_t* out = static_cast<int16_t*>(_output);
|
||||
for (size_t kkk=0; kkk<getInterfaceFormat().getMap().size(); ++kkk) {
|
||||
int32_t convertId = -1;
|
||||
if ( _mapInput.size() == 1
|
||||
&& _mapInput[0] == audio::channel_frontCenter) {
|
||||
convertId = 0;
|
||||
} else {
|
||||
for (size_t jjj=0; jjj<_mapInput.size(); ++jjj) {
|
||||
if (getInterfaceFormat().getMap()[kkk] == _mapInput[jjj]) {
|
||||
convertId = jjj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
RIVER_VERBOSE(" " << convertId << " ==> " << kkk);
|
||||
if (convertId != -1) {
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
out[iii*getInterfaceFormat().getMap().size()+kkk] = in[iii*_mapInput.size()+convertId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case audio::format_int16_on_int32:
|
||||
case audio::format_int24:
|
||||
case audio::format_int32:
|
||||
case audio::format_float:
|
||||
{
|
||||
RIVER_VERBOSE("convert (2) " << _mapInput << " ==> " << getInterfaceFormat().getMap());
|
||||
uint32_t* in = static_cast<uint32_t*>(_input);
|
||||
uint32_t* out = static_cast<uint32_t*>(_output);
|
||||
for (size_t kkk=0; kkk<getInterfaceFormat().getMap().size(); ++kkk) {
|
||||
int32_t convertId = -1;
|
||||
if ( _mapInput.size() == 1
|
||||
&& _mapInput[0] == audio::channel_frontCenter) {
|
||||
convertId = 0;
|
||||
} else {
|
||||
for (size_t jjj=0; jjj<_mapInput.size(); ++jjj) {
|
||||
if (getInterfaceFormat().getMap()[kkk] == _mapInput[jjj]) {
|
||||
convertId = jjj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (convertId != -1) {
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
out[iii*getInterfaceFormat().getMap().size()+kkk] = in[iii*_mapInput.size()+convertId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case audio::format_double:
|
||||
{
|
||||
RIVER_VERBOSE("convert (2) " << _mapInput << " ==> " << getInterfaceFormat().getMap());
|
||||
uint64_t* in = static_cast<uint64_t*>(_input);
|
||||
uint64_t* out = static_cast<uint64_t*>(_output);
|
||||
for (size_t kkk=0; kkk<getInterfaceFormat().getMap().size(); ++kkk) {
|
||||
int32_t convertId = -1;
|
||||
if ( _mapInput.size() == 1
|
||||
&& _mapInput[0] == audio::channel_frontCenter) {
|
||||
convertId = 0;
|
||||
} else {
|
||||
for (size_t jjj=0; jjj<_mapInput.size(); ++jjj) {
|
||||
if (getInterfaceFormat().getMap()[kkk] == _mapInput[jjj]) {
|
||||
convertId = jjj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (convertId != -1) {
|
||||
for (size_t iii=0; iii<_nbChunk; ++iii) {
|
||||
out[iii*getInterfaceFormat().getMap().size()+kkk] = in[iii*_mapInput.size()+convertId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodeMuxer::processMuxer(void* _dataIn1, void* _dataIn2, uint32_t _nbChunk, const audio::Time& _time) {
|
||||
//RIVER_INFO("must Mux data : " << m_mapInput1 << " + " << m_mapInput2 << " ==> " << getInterfaceFormat().getMap());
|
||||
memset(&m_data[0], 0, m_data.size());
|
||||
reorder(&m_data[0], _nbChunk, _dataIn1, m_mapInput1);
|
||||
reorder(&m_data[0], _nbChunk, _dataIn2, m_mapInput2);
|
||||
newInput(&m_data[0], _nbChunk, _time);
|
||||
}
|
||||
|
||||
|
||||
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";
|
||||
|
||||
*_io << " node [shape=box];\n";
|
||||
// TODO : Create a structure ...
|
||||
*_io << " NODE_" << m_uid << "_HW_MUXER [ label=\"Muxer\\n channelMap=" << etk::toString(getInterfaceFormat().getMap()) << "\" ];\n";
|
||||
etk::String nameIn;
|
||||
etk::String nameOut;
|
||||
m_process.generateDot(_io, 3, m_uid, nameIn, nameOut, false);
|
||||
*_io << " node [shape=square];\n";
|
||||
*_io << " NODE_" << m_uid << "_demuxer [ label=\"DEMUXER\\n format=" << etk::toString(m_process.getOutputConfig().getFormat()) << "\" ];\n";
|
||||
// Link all nodes :
|
||||
*_io << " NODE_" << m_uid << "_HW_MUXER -> " << nameIn << ";\n";
|
||||
*_io << " " << nameOut << " -> NODE_" << m_uid << "_demuxer;\n";
|
||||
*_io << " }\n";
|
||||
if (m_interfaceInput2 != null) {
|
||||
*_io << " " << m_interfaceInput2->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\n";
|
||||
}
|
||||
if (m_interfaceInput1 != null) {
|
||||
*_io << " " << m_interfaceInput1->getDotNodeName() << " -> NODE_" << m_uid << "_HW_MUXER;\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 == null) {
|
||||
continue;
|
||||
}
|
||||
bool isLink = false;
|
||||
for (size_t jjj=0; jjj<m_list.size(); ++jjj) {
|
||||
if (element == m_list[jjj]) {
|
||||
isLink = true;
|
||||
}
|
||||
}
|
||||
if (element != null) {
|
||||
if (element->getMode() == modeInterface_input) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_output) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_muxer", isLink);
|
||||
} else if (element->getMode() == modeInterface_feedback) {
|
||||
element->generateDot(_io, "NODE_" + etk::toString(m_uid) + "_demuxer", isLink);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
*_io << "\n";
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/drain/CircularBuffer.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace io {
|
||||
class Manager;
|
||||
class NodeMuxer : public Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeMuxer(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodeMuxer> create(const etk::String& _name, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~NodeMuxer();
|
||||
protected:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
ememory::SharedPtr<audio::river::Interface> m_interfaceInput1;
|
||||
ememory::SharedPtr<audio::river::Interface> m_interfaceInput2;
|
||||
ememory::SharedPtr<audio::river::Interface> createInput(float _freq,
|
||||
const etk::Vector<audio::channel>& _map,
|
||||
audio::format _format,
|
||||
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 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 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);
|
||||
etk::Vector<uint8_t> m_data;
|
||||
public:
|
||||
virtual void generateDot(ememory::SharedPtr<etk::io::Interface>& _io);
|
||||
private:
|
||||
void reorder(void* _output, uint32_t _nbChunk, void* _input, const etk::Vector<audio::channel>& _mapInput);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,267 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
|
||||
#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 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t audio::river::io::NodeOrchestra::playbackCallback(void* _outputBuffer,
|
||||
const audio::Time& _timeOutput,
|
||||
uint32_t _nbChunk,
|
||||
const etk::Vector<audio::orchestra::status>& _status) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
// TODO : Manage status ...
|
||||
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size() << " data=" << uint64_t(_outputBuffer));
|
||||
newOutput(_outputBuffer, _nbChunk, _timeOutput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 etk::String& _name, const ejson::Object& _config) :
|
||||
Node(_name, _config) {
|
||||
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
||||
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||
/**
|
||||
map-on:{ # select hardware interface and name
|
||||
interface:"alsa", # interface : "alsa", "pulse", "core", ...
|
||||
name:"default", # name of the interface
|
||||
},
|
||||
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
|
||||
*/
|
||||
etk::String typeInterface = audio::orchestra::typeUndefined;
|
||||
etk::String streamName = "default";
|
||||
const ejson::Object tmpObject = m_config["map-on"].toObject();
|
||||
if (tmpObject.exist() == false) {
|
||||
RIVER_WARNING("missing node : 'map-on' ==> auto map : 'auto:default'");
|
||||
} else {
|
||||
typeInterface = tmpObject["interface"].toString().get(audio::orchestra::typeUndefined);
|
||||
if (typeInterface == "auto") {
|
||||
typeInterface = audio::orchestra::typeUndefined;
|
||||
}
|
||||
streamName = tmpObject["name"].toString().get("default");
|
||||
}
|
||||
int32_t nbChunk = m_config["nb-chunk"].toNumber().get(1024);
|
||||
|
||||
// intanciate specific API ...
|
||||
m_interface.instanciate(typeInterface);
|
||||
m_interface.setName(_name);
|
||||
// TODO : Check return ...
|
||||
etk::String type = m_config["type"].toString().get("int16");
|
||||
if (streamName == "") {
|
||||
streamName = "default";
|
||||
}
|
||||
|
||||
// search device ID :
|
||||
RIVER_INFO("Open :");
|
||||
RIVER_INFO(" m_streamName=" << streamName);
|
||||
RIVER_INFO(" m_freq=" << hardwareFormat.getFrequency());
|
||||
RIVER_INFO(" m_map=" << hardwareFormat.getMap());
|
||||
RIVER_INFO(" m_format=" << hardwareFormat.getFormat());
|
||||
RIVER_INFO(" m_isInput=" << m_isInput);
|
||||
int32_t deviceId = -1;
|
||||
/*
|
||||
// TODO : Remove this from here (create an extern interface ...)
|
||||
RIVER_INFO("Device list:");
|
||||
for (int32_t iii=0; iii<m_interface.getDeviceCount(); ++iii) {
|
||||
m_info = m_interface.getDeviceInfo(iii);
|
||||
RIVER_INFO(" " << iii << " name :" << m_info.name);
|
||||
m_info.display(2);
|
||||
}
|
||||
*/
|
||||
// special case for default IO:
|
||||
if (streamName == "default") {
|
||||
if (m_isInput == true) {
|
||||
deviceId = m_interface.getDefaultInputDevice();
|
||||
} else {
|
||||
deviceId = m_interface.getDefaultOutputDevice();
|
||||
}
|
||||
} else {
|
||||
for (int32_t iii=0; iii<m_interface.getDeviceCount(); ++iii) {
|
||||
m_info = m_interface.getDeviceInfo(iii);
|
||||
if (m_info.name == streamName) {
|
||||
RIVER_INFO(" Select ... id =" << iii);
|
||||
deviceId = iii;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO : Check if the devace with the specific name exist ...
|
||||
/*
|
||||
if (deviceId == -1) {
|
||||
RIVER_ERROR("Can not find the " << streamName << " audio interface ... (use O default ...)");
|
||||
deviceId = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Open specific ID :
|
||||
if (deviceId == -1) {
|
||||
m_info = m_interface.getDeviceInfo(streamName);
|
||||
} else {
|
||||
m_info = m_interface.getDeviceInfo(deviceId);
|
||||
}
|
||||
// display property :
|
||||
{
|
||||
RIVER_INFO("Device " << deviceId << " - '" << streamName << "' property :");
|
||||
m_info.display();
|
||||
|
||||
if (etk::isIn(hardwareFormat.getFormat(), m_info.nativeFormats) == false) {
|
||||
if (type == "auto") {
|
||||
if (etk::isIn(audio::format_int16, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_int16);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (etk::isIn(audio::format_float, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_float);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (etk::isIn(audio::format_int16_on_int32, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_int16_on_int32);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (etk::isIn(audio::format_int24, m_info.nativeFormats) == true) {
|
||||
hardwareFormat.setFormat(audio::format_int24);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else if (m_info.nativeFormats.size() != 0) {
|
||||
hardwareFormat.setFormat(m_info.nativeFormats[0]);
|
||||
RIVER_INFO("auto set format: " << hardwareFormat.getFormat());
|
||||
} else {
|
||||
RIVER_CRITICAL("auto set format no element in the configuration: " << m_info.nativeFormats);
|
||||
}
|
||||
} else {
|
||||
RIVER_ERROR("Can not manage input transforamtion: " << hardwareFormat.getFormat() << " not in " << m_info.nativeFormats);
|
||||
hardwareFormat.setFormat(hardwareFormat.getFormat());
|
||||
}
|
||||
}
|
||||
if (etk::isIn(hardwareFormat.getFrequency(), m_info.sampleRates) == false) {
|
||||
if (etk::isIn(48000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(48000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(44100, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(44100);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(32000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(32000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(16000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(16000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(8000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(8000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (etk::isIn(96000, m_info.sampleRates) == true) {
|
||||
hardwareFormat.setFrequency(96000);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency());
|
||||
} else if (m_info.sampleRates.size() != 0) {
|
||||
hardwareFormat.setFrequency(m_info.sampleRates[0]);
|
||||
RIVER_INFO("auto set frequency: " << hardwareFormat.getFrequency() << "(first element in list) in " << m_info.sampleRates);
|
||||
} else {
|
||||
RIVER_ERROR("Can not manage input transforamtion:" << hardwareFormat.getFrequency() << " not in " << m_info.sampleRates);
|
||||
}
|
||||
interfaceFormat.setFrequency(hardwareFormat.getFrequency());
|
||||
}
|
||||
}
|
||||
|
||||
// open Audio device:
|
||||
audio::orchestra::StreamParameters params;
|
||||
params.deviceId = deviceId;
|
||||
params.deviceName = streamName;
|
||||
params.nChannels = hardwareFormat.getMap().size();
|
||||
if (m_info.channels.size() < params.nChannels) {
|
||||
RIVER_ERROR("Can not open hardware device with more channel (" << params.nChannels << ") that is autorized by hardware (" << m_info.channels.size() << ").");
|
||||
}
|
||||
audio::orchestra::StreamOptions option;
|
||||
etk::from_string(option.mode, tmpObject["timestamp-mode"].toString().get("soft"));
|
||||
|
||||
RIVER_DEBUG("interfaceFormat=" << interfaceFormat);
|
||||
RIVER_DEBUG("hardwareFormat=" << hardwareFormat);
|
||||
|
||||
m_rtaudioFrameSize = nbChunk;
|
||||
RIVER_INFO("Open output stream nbChannels=" << params.nChannels);
|
||||
enum audio::orchestra::error err = audio::orchestra::error_none;
|
||||
if (m_isInput == true) {
|
||||
m_process.setInputConfig(hardwareFormat);
|
||||
m_process.setOutputConfig(interfaceFormat);
|
||||
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,
|
||||
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);
|
||||
}
|
||||
m_process.updateInterAlgo();
|
||||
}
|
||||
|
||||
audio::river::io::NodeOrchestra::~NodeOrchestra() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("close input stream");
|
||||
if (m_interface.isStreamOpen() ) {
|
||||
m_interface.closeStream();
|
||||
}
|
||||
};
|
||||
|
||||
void audio::river::io::NodeOrchestra::start() {
|
||||
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) {
|
||||
RIVER_ERROR("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not start stream ... " << err);
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodeOrchestra::stop() {
|
||||
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) {
|
||||
RIVER_ERROR("Stop stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not stop stream ... " << err);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,73 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_ORCHESTRA
|
||||
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <audio/orchestra/Interface.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace io {
|
||||
class Manager;
|
||||
class Group;
|
||||
/**
|
||||
* @brief Low level node that is manage on the interface with the extern lib airtaudio
|
||||
*/
|
||||
class NodeOrchestra : public audio::river::io::Node {
|
||||
friend class audio::river::io::Group;
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodeOrchestra(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodeOrchestra> create(const etk::String& _name, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~NodeOrchestra();
|
||||
virtual bool isHarwareNode() {
|
||||
return true;
|
||||
};
|
||||
protected:
|
||||
audio::orchestra::Interface m_interface; //!< Real airtaudio interface
|
||||
audio::orchestra::DeviceInfo m_info; //!< information on the stream.
|
||||
unsigned int m_rtaudioFrameSize; // DEPRECATED soon...
|
||||
public:
|
||||
/**
|
||||
* @brief Input Callback . Have recaive new data to process.
|
||||
* @param[in] _inputBuffer Pointer on the data buffer.
|
||||
* @param[in] _timeInput Time on the fist sample has been recorded.
|
||||
* @param[in] _nbChunk Number of chunk in the buffer
|
||||
* @param[in] _status DEPRECATED soon
|
||||
* @return DEPRECATED soon
|
||||
*/
|
||||
int32_t recordCallback(const void* _inputBuffer,
|
||||
const audio::Time& _timeInput,
|
||||
uint32_t _nbChunk,
|
||||
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.
|
||||
* @param[in] _timeOutput Time on wich the data might be played.
|
||||
* @param[in] _nbChunk Number of chunk in the buffer
|
||||
* @param[in] _status DEPRECATED soon
|
||||
* @return DEPRECATED soon
|
||||
*/
|
||||
int32_t playbackCallback(void* _outputBuffer,
|
||||
const audio::Time& _timeOutput,
|
||||
uint32_t _nbChunk,
|
||||
const etk::Vector<audio::orchestra::status>& _status);
|
||||
protected:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,134 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
|
||||
#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,
|
||||
unsigned long _frameCount,
|
||||
const PaStreamCallbackTimeInfo* _timeInfo,
|
||||
PaStreamCallbackFlags _statusFlags,
|
||||
void *_userData) {
|
||||
audio::river::io::NodePortAudio* myClass = reinterpret_cast<audio::river::io::NodePortAudio*>(_userData);
|
||||
int64_t sec = int64_t(_timeInfo->inputBufferAdcTime);
|
||||
int64_t nsec = (_timeInfo->inputBufferAdcTime-double(sec))*1000000000LL;
|
||||
audio::Time timeInput(sec, nsec);
|
||||
sec = int64_t(_timeInfo->outputBufferDacTime);
|
||||
nsec = (_timeInfo->outputBufferDacTime-double(sec))*1000000000LL;
|
||||
audio::Time timeOutput(sec, nsec);
|
||||
return myClass->duplexCallback(_input,
|
||||
timeInput,
|
||||
_output,
|
||||
timeOutput,
|
||||
_frameCount,
|
||||
_statusFlags);
|
||||
}
|
||||
|
||||
int32_t audio::river::io::NodePortAudio::duplexCallback(const void* _inputBuffer,
|
||||
const audio::Time& _timeInput,
|
||||
void* _outputBuffer,
|
||||
const audio::Time& _timeOutput,
|
||||
uint32_t _nbChunk,
|
||||
PaStreamCallbackFlags _status) {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
// TODO : Manage status ...
|
||||
if (_inputBuffer != null) {
|
||||
RIVER_VERBOSE("data Input size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
|
||||
newInput(_inputBuffer, _nbChunk, _timeInput);
|
||||
}
|
||||
if (_outputBuffer != null) {
|
||||
RIVER_VERBOSE("data Output size request :" << _nbChunk << " [BEGIN] status=" << _status << " nbIO=" << m_list.size());
|
||||
newOutput(_outputBuffer, _nbChunk, _timeOutput);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 etk::String& _name, const ejson::Object& _config) :
|
||||
Node(_name, _config) {
|
||||
audio::drain::IOFormatInterface interfaceFormat = getInterfaceFormat();
|
||||
audio::drain::IOFormatInterface hardwareFormat = getHarwareFormat();
|
||||
/**
|
||||
map-on:{ # select hardware interface and name
|
||||
interface:"alsa", # interface : "alsa", "pulse", "core", ...
|
||||
name:"default", # name of the interface
|
||||
},
|
||||
nb-chunk:1024 # number of chunk to open device (create the latency anf the frequency to call user)
|
||||
*/
|
||||
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 {
|
||||
etk::String value = tmpObject.getStringValue("interface", "default");
|
||||
streamName = tmpObject.getStringValue("name", "default");
|
||||
}
|
||||
int32_t nbChunk = m_config.getNumberValue("nb-chunk", 1024);
|
||||
|
||||
PaError err = 0;
|
||||
if (m_isInput == true) {
|
||||
err = Pa_OpenDefaultStream(&m_stream,
|
||||
hardwareFormat.getMap().size(),
|
||||
0,
|
||||
paInt16,
|
||||
hardwareFormat.getFrequency(),
|
||||
nbChunk,
|
||||
&portAudioStreamCallback,
|
||||
this);
|
||||
} else {
|
||||
err = Pa_OpenDefaultStream(&m_stream,
|
||||
0,
|
||||
hardwareFormat.getMap().size(),
|
||||
paInt16,
|
||||
hardwareFormat.getFrequency(),
|
||||
nbChunk,
|
||||
&portAudioStreamCallback,
|
||||
this);
|
||||
}
|
||||
if( err != paNoError ) {
|
||||
RIVER_ERROR("Can not create Stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " err : " << Pa_GetErrorText(err));
|
||||
}
|
||||
m_process.updateInterAlgo();
|
||||
}
|
||||
|
||||
audio::river::io::NodePortAudio::~NodePortAudio() {
|
||||
ethread::UniqueLock lock(m_mutex);
|
||||
RIVER_INFO("close input stream");
|
||||
PaError err = Pa_CloseStream( m_stream );
|
||||
if( err != paNoError ) {
|
||||
RIVER_ERROR("Remove stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not Remove stream ... " << Pa_GetErrorText(err));
|
||||
}
|
||||
};
|
||||
|
||||
void audio::river::io::NodePortAudio::start() {
|
||||
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 ) {
|
||||
RIVER_ERROR("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not start stream ... " << Pa_GetErrorText(err));
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::io::NodePortAudio::stop() {
|
||||
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 ) {
|
||||
RIVER_ERROR("Start stream : '" << m_name << "' mode=" << (m_isInput?"input":"output") << " can not stop stream ... " << Pa_GetErrorText(err));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,51 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef AUDIO_RIVER_BUILD_PORTAUDIO
|
||||
|
||||
#include <audio/river/Interface.hpp>
|
||||
#include <audio/river/io/Node.hpp>
|
||||
#include <portaudio/portaudio.hpp>
|
||||
|
||||
namespace audio {
|
||||
namespace river {
|
||||
namespace io {
|
||||
class Manager;
|
||||
//! @not_in_doc
|
||||
class NodePortAudio : public Node {
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
NodePortAudio(const etk::String& _name, const ejson::Object& _config);
|
||||
public:
|
||||
static ememory::SharedPtr<NodePortAudio> create(const etk::String& _name, const ejson::Object& _config);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~NodePortAudio();
|
||||
virtual bool isHarwareNode() {
|
||||
return true;
|
||||
};
|
||||
protected:
|
||||
PaStream* m_stream;
|
||||
public:
|
||||
int32_t duplexCallback(const void* _inputBuffer,
|
||||
const audio::Time& _timeInput,
|
||||
void* _outputBuffer,
|
||||
const audio::Time& _timeOutput,
|
||||
uint32_t _nbChunk,
|
||||
PaStreamCallbackFlags _status);
|
||||
protected:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1,59 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <audio/river/river.hpp>
|
||||
#include <audio/river/debug.hpp>
|
||||
#include <audio/river/io/Manager.hpp>
|
||||
|
||||
static bool river_isInit = false;
|
||||
static etk::String river_configFile = "";
|
||||
|
||||
|
||||
|
||||
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 != null) {
|
||||
mng->init(river_configFile);
|
||||
}
|
||||
} else {
|
||||
RIVER_ERROR("River is already init not use : " << _filename);
|
||||
}
|
||||
}
|
||||
|
||||
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 != null) {
|
||||
mng->initString(river_configFile);
|
||||
}
|
||||
} else {
|
||||
RIVER_ERROR("River is already init not use Data ...");
|
||||
}
|
||||
}
|
||||
|
||||
void audio::river::unInit() {
|
||||
if (river_isInit == true) {
|
||||
river_isInit = false;
|
||||
RIVER_DEBUG("un-init RIVER.");
|
||||
ememory::SharedPtr<audio::river::io::Manager> mng = audio::river::io::Manager::getInstance();
|
||||
if (mng != null) {
|
||||
RIVER_ERROR("Can not get on the RIVER hardware manager !!!");
|
||||
mng->unInit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool audio::river::isInit() {
|
||||
return river_isInit;
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#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 etk::String& _filename = "");
|
||||
/**
|
||||
* @brief Initialize the River Library with a json data string
|
||||
* @param[in] _config json sting data
|
||||
*/
|
||||
void initString(const etk::String& _config);
|
||||
/**
|
||||
* @brief Un-initialize the River Library
|
||||
* @note this close all stream of all interfaces.
|
||||
* @note really good for test.
|
||||
*/
|
||||
void unInit();
|
||||
/**
|
||||
* @brief Get the status of initialisation
|
||||
* @return true River is init
|
||||
* @return false River is NOT init
|
||||
*/
|
||||
bool isInit();
|
||||
}
|
||||
}
|
||||
|
186
audio_river_build.html
Normal file
186
audio_river_build.html
Normal file
@ -0,0 +1,186 @@
|
||||
<!-- HTML header for doxygen 1.8.8-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- For Mobile Devices -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<title>audio-river: Multi-nodal audio interface: Build lib & build sample</title>
|
||||
<!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="search/searchdata.js"></script>
|
||||
<script type="text/javascript" src="search/search.js"></script>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||||
<link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">audio-river: Multi-nodal audio interface 0.4.0</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Main Page</a></li>
|
||||
<li><a href="pages.html">Related Pages</a></li>
|
||||
<li><a href="namespaces.html">Namespaces</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="files.html">Files</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Link-libs<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://HeeroYui.github.io/lutin">lutin</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ewol">ewol</a></li>
|
||||
<li><a href="http://atria-soft.github.io/echrono">echrono</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etk">etk</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ejson">ejson</a></li>
|
||||
<li><a href="http://atria-soft.github.io/exml">exml</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esvg">esvg</a></li>
|
||||
<li><a href="http://atria-soft.github.io/egami">egami</a></li>
|
||||
<li><a href="http://atria-soft.github.io/gale">gale</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ege">ege</a></li>
|
||||
<li><a href="http://atria-soft.github.io/elog">elog</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ememory">ememory</a></li>
|
||||
<li><a href="http://atria-soft.github.io/enet">enet</a></li>
|
||||
<li><a href="http://atria-soft.github.io/eproperty">eproperty</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esignal">esignal</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etranslate">etranslate</a></li>
|
||||
<li><a href="http://atria-soft.github.io/zeus">zeus</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-ess">audio-ess</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio">audio</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-drain">audio-drain</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-orchestra">audio-orchestra</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-river">audio-river</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="search-box" class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button aria-expanded="false" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="glyphicon glyphicon-search"></span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">All</a></li>
|
||||
<li><a href="#">Classes</a></li>
|
||||
<li><a href="#">Namespaces</a></li>
|
||||
<li><a href="#">Files</a></li>
|
||||
<li><a href="#">Functions</a></li>
|
||||
<li><a href="#">Variables</a></li>
|
||||
<li><a href="#">Typedefs</a></li>
|
||||
<li><a href="#">Enumerations</a></li>
|
||||
<li><a href="#">Enumerator</a></li>
|
||||
<li><a href="#">Friends</a></li>
|
||||
<li><a href="#">Macros</a></li>
|
||||
<li><a href="#">Pages</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button id="search-close" type="button" class="close" aria-label="Close">
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
<input id="search-field" class="form-control" accesskey="S" onkeydown="searchBox.OnSearchFieldChange(event);" placeholder="Search ..." type="text">
|
||||
</div>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="content" id="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
||||
<div style="margin-bottom: 15px;margin-top: 60px;">
|
||||
<!-- end header part -->
|
||||
<!-- Generated by Doxygen 1.8.12 -->
|
||||
<script type="text/javascript">
|
||||
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
||||
</script>
|
||||
<script type="text/javascript" src="menudata.js"></script>
|
||||
<script type="text/javascript" src="menu.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
initMenu('',true,false,'search.php','Search');
|
||||
$(document).ready(function() { init_search(); });
|
||||
});
|
||||
</script>
|
||||
<div id="main-nav"></div>
|
||||
<!-- window showing the filter options -->
|
||||
<div id="MSearchSelectWindow"
|
||||
onmouseover="return searchBox.OnSearchSelectShow()"
|
||||
onmouseout="return searchBox.OnSearchSelectHide()"
|
||||
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||||
</div>
|
||||
|
||||
<!-- iframe showing the search results (closed by default) -->
|
||||
<div id="MSearchResultsWindow">
|
||||
<iframe src="javascript:void(0)" frameborder="0"
|
||||
name="MSearchResults" id="MSearchResults">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
</div><!-- top -->
|
||||
<div class="header">
|
||||
<div class="headertitle">
|
||||
<div class="title">Build lib & build sample </div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="toc"><h3>Table of Contents</h3>
|
||||
<ul><li class="level1"><a href="#audio_river_build_download">Download: </a><ul><li class="level2"><a href="#audio_river_build_download_repo">need google repo: </a></li>
|
||||
<li class="level2"><a href="#audio_river_build_download_lutin">lutin (build-system): </a></li>
|
||||
<li class="level2"><a href="#audio_river_build_download_dependency">dependency: </a></li>
|
||||
<li class="level2"><a href="#audio_river_build_download_sources">sources: </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="level1"><a href="#audio_river_build_build">Build: </a><ul><li class="level2"><a href="#audio_river_build_build_library">library: </a></li>
|
||||
<li class="level2"><a href="#audio_river_build_build_sample">Sample: </a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="level1"><a href="#audio_river_build_run_sample">Run sample: </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="textblock"><h1><a class="anchor" id="audio_river_build_download"></a>
|
||||
Download: </h1>
|
||||
<p>ege use some tools to manage source and build it:</p>
|
||||
<h2><a class="anchor" id="audio_river_build_download_repo"></a>
|
||||
need google repo: </h2>
|
||||
<p>see: <a href="http://source.android.com/source/downloading.html#installing-repo">http://source.android.com/source/downloading.html#installing-repo</a></p>
|
||||
<p>On all platform: </p><div class="fragment"><div class="line">mkdir ~/.bin</div><div class="line">PATH=~/.bin:$PATH</div><div class="line">curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo</div><div class="line">chmod a+x ~/.bin/repo</div></div><!-- fragment --><p>On ubuntu </p><div class="fragment"><div class="line">sudo apt-get install repo</div></div><!-- fragment --><p>On archlinux </p><div class="fragment"><div class="line">sudo pacman -S repo</div></div><!-- fragment --><h2><a class="anchor" id="audio_river_build_download_lutin"></a>
|
||||
lutin (build-system): </h2>
|
||||
<div class="fragment"><div class="line">pip install lutin --user</div><div class="line"># optionnal dependency of lutin (manage image changing size for application release)</div><div class="line">pip install pillow --user</div></div><!-- fragment --><h2><a class="anchor" id="audio_river_build_download_dependency"></a>
|
||||
dependency: </h2>
|
||||
<div class="fragment"><div class="line">mkdir -p WORKING_DIRECTORY/framework</div><div class="line">cd WORKING_DIRECTORY/framework</div><div class="line">repo init -u git://github.com/atria-soft/manifest.git</div><div class="line">repo sync -j8</div><div class="line">cd ../..</div></div><!-- fragment --><h2><a class="anchor" id="audio_river_build_download_sources"></a>
|
||||
sources: </h2>
|
||||
<p>They are already download in the repo manifest in:</p>
|
||||
<div class="fragment"><div class="line">cd WORKING_DIRECTORY/framework/musicdsp/audio-river</div></div><!-- fragment --><h1><a class="anchor" id="audio_river_build_build"></a>
|
||||
Build: </h1>
|
||||
<p>you must stay in zour working directory... </p><div class="fragment"><div class="line">cd WORKING_DIRECTORY</div></div><!-- fragment --><h2><a class="anchor" id="audio_river_build_build_library"></a>
|
||||
library: </h2>
|
||||
<div class="fragment"><div class="line">lutin -mdebug audio-river</div></div><!-- fragment --><h2><a class="anchor" id="audio_river_build_build_sample"></a>
|
||||
Sample: </h2>
|
||||
<div class="fragment"><div class="line">lutin -mdebug audio-river-sample-read?run</div><div class="line">lutin -mdebug audio-river-sample-write?run</div></div><!-- fragment --><p>A fast way: </p><div class="fragment"><div class="line">lutin -mdebug audio-river-*</div></div><!-- fragment --><h1><a class="anchor" id="audio_river_build_run_sample"></a>
|
||||
Run sample: </h1>
|
||||
<p>in distinct bash: </p><div class="fragment"><div class="line">lutin -mdebug audio-river-sample-read?run</div><div class="line">lutin -mdebug audio-river-sample-write?run</div></div><!-- fragment --> </div></div><!-- contents -->
|
||||
<!-- HTML footer for doxygen 1.8.8-->
|
||||
<!-- start footer part -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
Generated on Mon Oct 24 2016 15:35:48 for audio-river: Multi-nodal audio interface by  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="doxygen.png" alt="doxygen"/>
|
||||
</a> 1.8.12
|
||||
</small></address>
|
||||
</body>
|
||||
</html>
|
205
audio_river_config_file.html
Normal file
205
audio_river_config_file.html
Normal file
@ -0,0 +1,205 @@
|
||||
<!-- HTML header for doxygen 1.8.8-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- For Mobile Devices -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<title>audio-river: Multi-nodal audio interface: River configuration file</title>
|
||||
<!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="search/searchdata.js"></script>
|
||||
<script type="text/javascript" src="search/search.js"></script>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||||
<link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">audio-river: Multi-nodal audio interface 0.4.0</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Main Page</a></li>
|
||||
<li><a href="pages.html">Related Pages</a></li>
|
||||
<li><a href="namespaces.html">Namespaces</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="files.html">Files</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Link-libs<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://HeeroYui.github.io/lutin">lutin</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ewol">ewol</a></li>
|
||||
<li><a href="http://atria-soft.github.io/echrono">echrono</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etk">etk</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ejson">ejson</a></li>
|
||||
<li><a href="http://atria-soft.github.io/exml">exml</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esvg">esvg</a></li>
|
||||
<li><a href="http://atria-soft.github.io/egami">egami</a></li>
|
||||
<li><a href="http://atria-soft.github.io/gale">gale</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ege">ege</a></li>
|
||||
<li><a href="http://atria-soft.github.io/elog">elog</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ememory">ememory</a></li>
|
||||
<li><a href="http://atria-soft.github.io/enet">enet</a></li>
|
||||
<li><a href="http://atria-soft.github.io/eproperty">eproperty</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esignal">esignal</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etranslate">etranslate</a></li>
|
||||
<li><a href="http://atria-soft.github.io/zeus">zeus</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-ess">audio-ess</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio">audio</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-drain">audio-drain</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-orchestra">audio-orchestra</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-river">audio-river</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="search-box" class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button aria-expanded="false" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="glyphicon glyphicon-search"></span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">All</a></li>
|
||||
<li><a href="#">Classes</a></li>
|
||||
<li><a href="#">Namespaces</a></li>
|
||||
<li><a href="#">Files</a></li>
|
||||
<li><a href="#">Functions</a></li>
|
||||
<li><a href="#">Variables</a></li>
|
||||
<li><a href="#">Typedefs</a></li>
|
||||
<li><a href="#">Enumerations</a></li>
|
||||
<li><a href="#">Enumerator</a></li>
|
||||
<li><a href="#">Friends</a></li>
|
||||
<li><a href="#">Macros</a></li>
|
||||
<li><a href="#">Pages</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button id="search-close" type="button" class="close" aria-label="Close">
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
<input id="search-field" class="form-control" accesskey="S" onkeydown="searchBox.OnSearchFieldChange(event);" placeholder="Search ..." type="text">
|
||||
</div>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="content" id="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
||||
<div style="margin-bottom: 15px;margin-top: 60px;">
|
||||
<!-- end header part -->
|
||||
<!-- Generated by Doxygen 1.8.12 -->
|
||||
<script type="text/javascript">
|
||||
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
||||
</script>
|
||||
<script type="text/javascript" src="menudata.js"></script>
|
||||
<script type="text/javascript" src="menu.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
initMenu('',true,false,'search.php','Search');
|
||||
$(document).ready(function() { init_search(); });
|
||||
});
|
||||
</script>
|
||||
<div id="main-nav"></div>
|
||||
<!-- window showing the filter options -->
|
||||
<div id="MSearchSelectWindow"
|
||||
onmouseover="return searchBox.OnSearchSelectShow()"
|
||||
onmouseout="return searchBox.OnSearchSelectHide()"
|
||||
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||||
</div>
|
||||
|
||||
<!-- iframe showing the search results (closed by default) -->
|
||||
<div id="MSearchResultsWindow">
|
||||
<iframe src="javascript:void(0)" frameborder="0"
|
||||
name="MSearchResults" id="MSearchResults">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
</div><!-- top -->
|
||||
<div class="header">
|
||||
<div class="headertitle">
|
||||
<div class="title">River configuration file </div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="toc"><h3>Table of Contents</h3>
|
||||
<ul><li class="level1"><a href="#audio_river_config_file_objectif">Objectifs: </a></li>
|
||||
<li class="level1"><a href="#audio_river_config_file_bases">Basis: </a></li>
|
||||
<li class="level1"><a href="#audio_river_config_file_hw_config">Harware configuration: </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="textblock"><h1><a class="anchor" id="audio_river_config_file_objectif"></a>
|
||||
Objectifs: </h1>
|
||||
<ul>
|
||||
<li>Understand the architecture of the configuration file.</li>
|
||||
<li>all that can be done with it.</li>
|
||||
</ul>
|
||||
<h1><a class="anchor" id="audio_river_config_file_bases"></a>
|
||||
Basis: </h1>
|
||||
<p>The river configuration file is a json file. We use <a class="elRef" doxygen="/home/heero/dev/perso/out/doc/release/ejson.tag:http://atria-soft.github.io/ejson/" href="http://atria-soft.github.io/ejson/index.html#ejson_mainpage_what">What is EJSON: </a> to parse it then we have some writing facilities.</p>
|
||||
<p>River provide a list a harware interface and virtual interface.</p>
|
||||
<p>The hardware interface are provided by <a class="elRef" doxygen="/home/heero/dev/perso/out/doc/release/audio-orchestra.tag:http://musicdsp.github.io/audio-orchestra/" href="http://musicdsp.github.io/audio-orchestra/index.html#audio_orchestra_mainpage_what">What is AUDIO-ORCHESTRA: </a> then we will plug on every platform.</p>
|
||||
<p>The file is simply architecture around a list of object:</p>
|
||||
<div class="fragment"><div class="line">{</div><div class="line"> "speaker":{</div><div class="line"></div><div class="line"> },</div><div class="line"> "microphone":{</div><div class="line"></div><div class="line"> },</div><div class="line"> "mixed-in-out":{</div><div class="line"></div><div class="line"> },</div><div class="line">}</div></div><!-- fragment --><p>With this config we declare 3 interfaces : speaker, microphone and mixed-in-out.</p>
|
||||
<h1><a class="anchor" id="audio_river_config_file_hw_config"></a>
|
||||
Harware configuration: </h1>
|
||||
<p>In every interface we need to define some Element:</p><ul>
|
||||
<li>"io" : Can be input/output/... depending of virtual interface...</li>
|
||||
<li>"map-on": An object to configure airtaudio interface.</li>
|
||||
<li>"frequency": 0 to automatic select one. Or the frequency to open harware device</li>
|
||||
<li>"channel-map": List of all channel in the stream:<ul>
|
||||
<li>"front-left"</li>
|
||||
<li>"front-center"</li>
|
||||
<li>"front-right"</li>
|
||||
<li>"rear-left"</li>
|
||||
<li>"rear-center"</li>
|
||||
<li>"rear-right"</li>
|
||||
<li>"surround-left",</li>
|
||||
<li>"surround-right",</li>
|
||||
<li>"sub-woofer",</li>
|
||||
<li>"lfe"</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>"type": Fomat to open the stream:<ul>
|
||||
<li>"auto": Detect the best type</li>
|
||||
<li>"int8",</li>
|
||||
<li>"int8-on-int16",</li>
|
||||
<li>"int16",</li>
|
||||
<li>"int16-on-int32",</li>
|
||||
<li>"int24",</li>
|
||||
<li>"int32",</li>
|
||||
<li>"int32-on-int64",</li>
|
||||
<li>"int64",</li>
|
||||
<li>"float",</li>
|
||||
<li>"double"</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>"nb-chunk": Number of chunk to open the stream. </li>
|
||||
</ul>
|
||||
</div></div><!-- contents -->
|
||||
<!-- HTML footer for doxygen 1.8.8-->
|
||||
<!-- start footer part -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
Generated on Mon Oct 24 2016 15:35:48 for audio-river: Multi-nodal audio interface by  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="doxygen.png" alt="doxygen"/>
|
||||
</a> 1.8.12
|
||||
</small></address>
|
||||
</body>
|
||||
</html>
|
167
audio_river_feedback.html
Normal file
167
audio_river_feedback.html
Normal file
@ -0,0 +1,167 @@
|
||||
<!-- HTML header for doxygen 1.8.8-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- For Mobile Devices -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<title>audio-river: Multi-nodal audio interface: Read stream feedback</title>
|
||||
<!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="search/searchdata.js"></script>
|
||||
<script type="text/javascript" src="search/search.js"></script>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||||
<link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">audio-river: Multi-nodal audio interface 0.4.0</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Main Page</a></li>
|
||||
<li><a href="pages.html">Related Pages</a></li>
|
||||
<li><a href="namespaces.html">Namespaces</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="files.html">Files</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Link-libs<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://HeeroYui.github.io/lutin">lutin</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ewol">ewol</a></li>
|
||||
<li><a href="http://atria-soft.github.io/echrono">echrono</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etk">etk</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ejson">ejson</a></li>
|
||||
<li><a href="http://atria-soft.github.io/exml">exml</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esvg">esvg</a></li>
|
||||
<li><a href="http://atria-soft.github.io/egami">egami</a></li>
|
||||
<li><a href="http://atria-soft.github.io/gale">gale</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ege">ege</a></li>
|
||||
<li><a href="http://atria-soft.github.io/elog">elog</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ememory">ememory</a></li>
|
||||
<li><a href="http://atria-soft.github.io/enet">enet</a></li>
|
||||
<li><a href="http://atria-soft.github.io/eproperty">eproperty</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esignal">esignal</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etranslate">etranslate</a></li>
|
||||
<li><a href="http://atria-soft.github.io/zeus">zeus</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-ess">audio-ess</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio">audio</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-drain">audio-drain</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-orchestra">audio-orchestra</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-river">audio-river</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="search-box" class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button aria-expanded="false" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="glyphicon glyphicon-search"></span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">All</a></li>
|
||||
<li><a href="#">Classes</a></li>
|
||||
<li><a href="#">Namespaces</a></li>
|
||||
<li><a href="#">Files</a></li>
|
||||
<li><a href="#">Functions</a></li>
|
||||
<li><a href="#">Variables</a></li>
|
||||
<li><a href="#">Typedefs</a></li>
|
||||
<li><a href="#">Enumerations</a></li>
|
||||
<li><a href="#">Enumerator</a></li>
|
||||
<li><a href="#">Friends</a></li>
|
||||
<li><a href="#">Macros</a></li>
|
||||
<li><a href="#">Pages</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button id="search-close" type="button" class="close" aria-label="Close">
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
<input id="search-field" class="form-control" accesskey="S" onkeydown="searchBox.OnSearchFieldChange(event);" placeholder="Search ..." type="text">
|
||||
</div>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="content" id="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
||||
<div style="margin-bottom: 15px;margin-top: 60px;">
|
||||
<!-- end header part -->
|
||||
<!-- Generated by Doxygen 1.8.12 -->
|
||||
<script type="text/javascript">
|
||||
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
||||
</script>
|
||||
<script type="text/javascript" src="menudata.js"></script>
|
||||
<script type="text/javascript" src="menu.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
initMenu('',true,false,'search.php','Search');
|
||||
$(document).ready(function() { init_search(); });
|
||||
});
|
||||
</script>
|
||||
<div id="main-nav"></div>
|
||||
<!-- window showing the filter options -->
|
||||
<div id="MSearchSelectWindow"
|
||||
onmouseover="return searchBox.OnSearchSelectShow()"
|
||||
onmouseout="return searchBox.OnSearchSelectHide()"
|
||||
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||||
</div>
|
||||
|
||||
<!-- iframe showing the search results (closed by default) -->
|
||||
<div id="MSearchResultsWindow">
|
||||
<iframe src="javascript:void(0)" frameborder="0"
|
||||
name="MSearchResults" id="MSearchResults">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
</div><!-- top -->
|
||||
<div class="header">
|
||||
<div class="headertitle">
|
||||
<div class="title">Read stream feedback </div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="toc"><h3>Table of Contents</h3>
|
||||
<ul><li class="level1"><a href="#audio_river_feedback_objectif">Objectifs: </a></li>
|
||||
<li class="level1"><a href="#audio_river_feedback_base">Bases: </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="textblock"><h1><a class="anchor" id="audio_river_feedback_objectif"></a>
|
||||
Objectifs: </h1>
|
||||
<ul>
|
||||
<li>Implement a feedback.</li>
|
||||
</ul>
|
||||
<h1><a class="anchor" id="audio_river_feedback_base"></a>
|
||||
Bases: </h1>
|
||||
<p>A feedback is a stream that is generated by an output.</p>
|
||||
<p>To get a feedback this is the same implementation of an input and link it on an output.</p>
|
||||
<p>What change:</p>
|
||||
<div class="fragment"><div class="line"><span class="comment">//Get the generic feedback on speaker:</span></div><div class="line"><span class="keyword">interface </span>= manager->createFeedback(48000,</div><div class="line"> <a class="code" href="namespacestd.html">std</a>::vector<audio::channel>(),</div><div class="line"> <a class="codeRef" doxygen="/home/heero/dev/perso/out/doc/release/audio.tag:http://musicdsp.github.io/audio/" href="http://musicdsp.github.io/audio/namespaceaudio.html#a2e69fde0e376bc9b0b6fa91fb93105cba7ed7669dfdfed5d7ec2626caafbad9d7">audio::format_int16</a>,</div><div class="line"> "speaker");</div></div><!-- fragment --><p><b>Note:</b> Input interface does not provide feedback. </p>
|
||||
</div></div><!-- contents -->
|
||||
<!-- HTML footer for doxygen 1.8.8-->
|
||||
<!-- start footer part -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
Generated on Mon Oct 24 2016 15:35:48 for audio-river: Multi-nodal audio interface by  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="doxygen.png" alt="doxygen"/>
|
||||
</a> 1.8.12
|
||||
</small></address>
|
||||
</body>
|
||||
</html>
|
208
audio_river_read.html
Normal file
208
audio_river_read.html
Normal file
File diff suppressed because one or more lines are too long
184
audio_river_write.html
Normal file
184
audio_river_write.html
Normal file
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
MR Edouard DUPIN <yui.heero@gmail.com>
|
BIN
closed.png
Normal file
BIN
closed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 132 B |
377
customdoxygen.css
Normal file
377
customdoxygen.css
Normal file
@ -0,0 +1,377 @@
|
||||
|
||||
#navrow1, #navrow2, #navrow3, #navrow4, #navrow5{
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
}
|
||||
|
||||
.adjust-right {
|
||||
margin-left: 30px !important;
|
||||
font-size: 1.15em !important;
|
||||
}
|
||||
.navbar{
|
||||
border: 0px solid #222 !important;
|
||||
}
|
||||
|
||||
|
||||
/* Sticky footer styles
|
||||
-------------------------------------------------- */
|
||||
html,
|
||||
body {
|
||||
counter-reset: h1counter;
|
||||
height: 100%;
|
||||
/* The html and body elements cannot have any padding or margin. */
|
||||
}
|
||||
h1, .h1, h2, .h2, h3, .h3{
|
||||
font-weight: bold !important;
|
||||
}
|
||||
h1:before {
|
||||
content: counter(h1counter) ".\0000a0\0000a0";
|
||||
counter-increment: h1counter;
|
||||
counter-reset: h2counter;
|
||||
}
|
||||
h2:before {
|
||||
content: counter(h1counter) "." counter(h2counter) ".\0000a0\0000a0";
|
||||
counter-increment: h2counter;
|
||||
counter-reset: h3counter;
|
||||
}
|
||||
h3:before {
|
||||
content: counter(h1counter) "." counter(h2counter) "." counter(h3counter) ".\0000a0\0000a0";
|
||||
counter-increment: h3counter;
|
||||
}
|
||||
|
||||
/* Wrapper for page content to push down footer */
|
||||
#wrap {
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
/* Negative indent footer by its height */
|
||||
margin: 0 auto -60px;
|
||||
/* Pad bottom by footer height */
|
||||
padding: 0 0 60px;
|
||||
}
|
||||
|
||||
/* Set the fixed height of the footer here */
|
||||
#footer {
|
||||
font-size: 0.9em;
|
||||
padding: 8px 0px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.footer-row {
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
#footer > .container {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.footer-follow-icon {
|
||||
margin-left: 3px;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.footer-follow-icon img {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.footer-link {
|
||||
padding-top: 5px;
|
||||
display: inline-block;
|
||||
color: #999999;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-copyright {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.footer-row {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.footer-icons {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@media (max-width: 991px) {
|
||||
.footer-row {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer-icons {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* DOXYGEN Code Styles
|
||||
----------------------------------- */
|
||||
|
||||
|
||||
a.qindex {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.qindexHL {
|
||||
font-weight: bold;
|
||||
background-color: #9CAFD4;
|
||||
color: #ffffff;
|
||||
border: 1px double #869DCA;
|
||||
}
|
||||
|
||||
.contents a.qindexHL:visited {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.code, a.code:visited, a.line, a.line:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
dl.el {
|
||||
margin-left: -1cm;
|
||||
}
|
||||
|
||||
pre.fragment {
|
||||
border: 1px solid #C4CFE5;
|
||||
background-color: #FBFCFD;
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
overflow: auto;
|
||||
word-wrap: break-word;
|
||||
font-size: 9pt;
|
||||
line-height: 125%;
|
||||
font-family: monospace, fixed;
|
||||
font-size: 105%;
|
||||
}
|
||||
|
||||
div.fragment {
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
border: 1px solid #C4CFE5;
|
||||
}
|
||||
|
||||
div.line {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 13px;
|
||||
min-height: 13px;
|
||||
line-height: 1.0;
|
||||
text-wrap: unrestricted;
|
||||
white-space: -moz-pre-wrap; /* Moz */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
white-space: pre-wrap; /* CSS3 */
|
||||
word-wrap: break-word; /* IE 5.5+ */
|
||||
text-indent: -53px;
|
||||
padding-left: 53px;
|
||||
padding-bottom: 0px;
|
||||
margin: 0px;
|
||||
-webkit-transition-property: background-color, box-shadow;
|
||||
-webkit-transition-duration: 0.5s;
|
||||
-moz-transition-property: background-color, box-shadow;
|
||||
-moz-transition-duration: 0.5s;
|
||||
-ms-transition-property: background-color, box-shadow;
|
||||
-ms-transition-duration: 0.5s;
|
||||
-o-transition-property: background-color, box-shadow;
|
||||
-o-transition-duration: 0.5s;
|
||||
transition-property: background-color, box-shadow;
|
||||
transition-duration: 0.5s;
|
||||
}
|
||||
|
||||
div.line.glow {
|
||||
background-color: cyan;
|
||||
box-shadow: 0 0 10px cyan;
|
||||
}
|
||||
|
||||
|
||||
span.lineno {
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
border-right: 2px solid #0F0;
|
||||
background-color: #E8E8E8;
|
||||
white-space: pre;
|
||||
}
|
||||
span.lineno a {
|
||||
background-color: #D8D8D8;
|
||||
}
|
||||
|
||||
span.lineno a:hover {
|
||||
background-color: #C8C8C8;
|
||||
}
|
||||
|
||||
div.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.groupText {
|
||||
margin-left: 16px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* @group Code Colorization */
|
||||
|
||||
span.keyword {
|
||||
color: #008000
|
||||
}
|
||||
|
||||
span.keywordtype {
|
||||
color: #604020
|
||||
}
|
||||
|
||||
span.keywordflow {
|
||||
color: #e08000
|
||||
}
|
||||
|
||||
span.comment {
|
||||
color: #800000
|
||||
}
|
||||
|
||||
span.preprocessor {
|
||||
color: #806020
|
||||
}
|
||||
|
||||
span.stringliteral {
|
||||
color: #002080
|
||||
}
|
||||
|
||||
span.charliteral {
|
||||
color: #008080
|
||||
}
|
||||
|
||||
span.vhdldigit {
|
||||
color: #ff00ff
|
||||
}
|
||||
|
||||
span.vhdlchar {
|
||||
color: #000000
|
||||
}
|
||||
|
||||
span.vhdlkeyword {
|
||||
color: #700070
|
||||
}
|
||||
|
||||
span.vhdllogic {
|
||||
color: #ff0000
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background-color: #F7F8FB;
|
||||
border-left: 2px solid #9CAFD4;
|
||||
margin: 0 24px 0 4px;
|
||||
padding: 0 12px 0 16px;
|
||||
}
|
||||
|
||||
/*---------------- Search Box */
|
||||
|
||||
#search-box {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
#search-box .close {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
padding: 6px 12px;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/*---------------- Search results window */
|
||||
|
||||
#search-results-window {
|
||||
display: none;
|
||||
}
|
||||
|
||||
iframe#MSearchResults {
|
||||
width: 100%;
|
||||
height: 15em;
|
||||
}
|
||||
|
||||
.SRChildren {
|
||||
padding-left: 3ex; padding-bottom: .5em
|
||||
}
|
||||
.SRPage .SRChildren {
|
||||
display: none;
|
||||
}
|
||||
a.SRScope {
|
||||
display: block;
|
||||
}
|
||||
a.SRSymbol:focus, a.SRSymbol:active,
|
||||
a.SRScope:focus, a.SRScope:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
span.SRScope {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.SRResult {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* class and file list */
|
||||
.directory .icona,
|
||||
.directory .arrow {
|
||||
height: auto;
|
||||
}
|
||||
.directory .icona .icon {
|
||||
height: 16px;
|
||||
}
|
||||
.directory .icondoc {
|
||||
background-position: 0px 0px;
|
||||
height: 20px;
|
||||
}
|
||||
.directory .iconfopen {
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
.directory td.entry {
|
||||
padding: 7px 8px 6px 8px;
|
||||
}
|
||||
|
||||
.table > tbody > tr > td.memSeparator {
|
||||
line-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.memItemLeft, .memTemplItemLeft {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/* enumerations */
|
||||
.panel-body thead > tr {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* todo lists */
|
||||
.todoname,
|
||||
.todoname a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Class title */
|
||||
.summary {
|
||||
margin-top: 25px;
|
||||
}
|
||||
.page-header {
|
||||
margin: 20px 0px !important;
|
||||
}
|
||||
.page-header {
|
||||
#display: inline-block;
|
||||
}
|
||||
.title {
|
||||
text-align: center;
|
||||
color: orange;
|
||||
}
|
||||
.page-header .pull-right {
|
||||
margin-top: 0.3em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.page-header .label {
|
||||
font-size: 50%;
|
||||
}
|
||||
|
||||
#main-nav {
|
||||
display: none;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
microphone:{
|
||||
io:"input",
|
||||
map-on:{
|
||||
interface:"coreIOS",
|
||||
name:"default",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024
|
||||
},
|
||||
speaker:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"coreIOS",
|
||||
name:"default",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER"
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
{
|
||||
speaker:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"alsa",
|
||||
#name:"default",
|
||||
name:"hw:0,0",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
group:"baseIOSynchrone",
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER",
|
||||
mux-demux-type:"int16-on-int32",
|
||||
},
|
||||
# name of the device
|
||||
microphone:{
|
||||
# input or output
|
||||
io:"input",
|
||||
# select hardware interface and name
|
||||
map-on:{
|
||||
# interface : "alsa", "pulse", "core", ...
|
||||
interface:"alsa",
|
||||
# name of the interface
|
||||
# name:"default",
|
||||
name:"hw:0,0",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
# Link 2 ios with the same time in low level (named group) :
|
||||
group:"baseIOSynchrone",
|
||||
# frequency to open device
|
||||
frequency:48000,
|
||||
# mapping of the harware device (mapping is not get under)
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
],
|
||||
# format to open device (int8, int16, int16-on-ont32, int24, int32, float)
|
||||
type:"int16",
|
||||
# number of chunk to open device (create the latency anf the frequency to call user)
|
||||
nb-chunk:1024,
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
speaker-pulse:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"pulse",
|
||||
name:"default",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER",
|
||||
mux-demux-type:"int16-on-int32",
|
||||
},
|
||||
speaker-jack:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"jack",
|
||||
name:"default",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"float",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER",
|
||||
mux-demux-type:"float",
|
||||
},
|
||||
# virtual Nodes :
|
||||
microphone-clean:{
|
||||
io:"aec",
|
||||
# connect in input mode
|
||||
map-on-microphone:{
|
||||
# generic virtual definition
|
||||
io:"input",
|
||||
map-on:"microphone",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10"
|
||||
},
|
||||
# connect in feedback mode
|
||||
map-on-feedback:{
|
||||
io:"feedback",
|
||||
map-on:"speaker",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10",
|
||||
},
|
||||
#classical format configuration:
|
||||
frequency:16000,
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
],
|
||||
type:"int16",
|
||||
# AEC algo definition
|
||||
algo:"river-remover",
|
||||
algo-mode:"cutter",
|
||||
feedback-delay:10000, # in nanosecond
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
# virtual Nodes :
|
||||
microphone-muxed:{
|
||||
io:"muxer",
|
||||
# connect in input mode
|
||||
map-on-input-1:{
|
||||
# generic virtual definition
|
||||
io:"input",
|
||||
map-on:"microphone",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10"
|
||||
},
|
||||
# connect in feedback mode
|
||||
map-on-input-2:{
|
||||
io:"feedback",
|
||||
map-on:"speaker",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10",
|
||||
},
|
||||
input-2-remap:["rear-left", "rear-right"],
|
||||
#classical format configuration:
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right", "rear-left", "rear-right"
|
||||
],
|
||||
type:"int16",
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
{
|
||||
microphone:{
|
||||
io:"input",
|
||||
map-on:{
|
||||
interface:"coreOSX",
|
||||
name:"Apple Inc.: Built-in Input",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
],
|
||||
type:"float",
|
||||
nb-chunk:1024
|
||||
},
|
||||
speaker:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"coreOSX",
|
||||
#name:"Apple Inc.: Built-in Output",
|
||||
name:"Apple Inc.: HDMI",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"float",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER"
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
{
|
||||
speaker:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"alsa",
|
||||
name:"hw:0,0",
|
||||
#name:"default",
|
||||
#name:"AD1989A_outputs",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
#group:"baseIOSynchrone",
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:6000,
|
||||
#volume-name:"MASTER",
|
||||
mux-demux-type:"int16-on-int32",
|
||||
},
|
||||
microphone-virtual-alsa:{
|
||||
io:"input",
|
||||
map-on:{
|
||||
interface:"alsa",
|
||||
name:"AD1989A_inputs",
|
||||
#name:"hw:0,0",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
, "rear-left", "rear-right"
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:6000,
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
speakerGroup:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"alsa",
|
||||
name:"hw:0,0",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
group:"baseIOSynchrone",
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER",
|
||||
mux-demux-type:"int16-on-int32",
|
||||
},
|
||||
microphone-front:{
|
||||
io:"input",
|
||||
map-on:{
|
||||
interface:"alsa",
|
||||
name:"hw:0,0,1",
|
||||
#name:"AD1989A_inputs",
|
||||
#name:"default",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
#group:"baseIOSynchrone",
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:128,
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
microphone-rear:{
|
||||
io:"input",
|
||||
map-on:{
|
||||
interface:"alsa",
|
||||
name:"hw:0,0,0",
|
||||
timestamp-mode:"trigered",
|
||||
},
|
||||
#group:"baseIOSynchrone",
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"rear-left", "rear-right"
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024,
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
# virtual Nodes :
|
||||
microphone-clean:{
|
||||
io:"aec",
|
||||
# connect in input mode
|
||||
map-on-microphone:{
|
||||
# generic virtual definition
|
||||
io:"input",
|
||||
map-on:"microphone-muxed",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10"
|
||||
},
|
||||
# connect in feedback mode
|
||||
map-on-feedback:{
|
||||
io:"feedback",
|
||||
map-on:"speaker",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10",
|
||||
},
|
||||
#classical format configuration:
|
||||
frequency:16000,
|
||||
channel-map:[
|
||||
"front-left", "front-right", "rear-left", "rear-right"
|
||||
],
|
||||
type:"int16",
|
||||
# AEC algo definition
|
||||
algo:"river-remover",
|
||||
algo-mode:"cutter",
|
||||
feedback-delay:10000, # in nanosecond
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
microphone-muxed:{
|
||||
io:"muxer",
|
||||
map-on-input-1:{
|
||||
# generic virtual definition
|
||||
io:"input",
|
||||
map-on:"microphone-front",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10"
|
||||
},
|
||||
map-on-input-2:{
|
||||
io:"input",
|
||||
map-on:"microphone-rear",
|
||||
resampling-type:"speexdsp",
|
||||
resampling-option:"quality=10",
|
||||
},
|
||||
frequency:48000,
|
||||
channel-map:[
|
||||
"front-left", "front-right", "rear-left", "rear-right"
|
||||
],
|
||||
type:"int16",
|
||||
mux-demux-type:"int16",
|
||||
},
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
{
|
||||
microphone:{
|
||||
io:"input",
|
||||
map-on:{
|
||||
interface:"ds",
|
||||
name:"default",
|
||||
},
|
||||
frequency:44100,
|
||||
channel-map:[
|
||||
"front-left", "front-right"
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024
|
||||
},
|
||||
speaker:{
|
||||
io:"output",
|
||||
map-on:{
|
||||
interface:"ds",
|
||||
name:"default",
|
||||
},
|
||||
frequency:44100,
|
||||
channel-map:[
|
||||
"front-left", "front-right",
|
||||
],
|
||||
type:"int16",
|
||||
nb-chunk:1024,
|
||||
volume-name:"MASTER"
|
||||
}
|
||||
}
|
100
doc/build.md
100
doc/build.md
@ -1,100 +0,0 @@
|
||||
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
|
||||
```
|
@ -1,119 +0,0 @@
|
||||
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
|
||||
|
@ -1,30 +0,0 @@
|
||||
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.
|
||||
|
@ -1,92 +0,0 @@
|
||||
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
115
doc/read.md
@ -1,115 +0,0 @@
|
||||
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
|
53
doc/write.md
53
doc/write.md
@ -1,53 +0,0 @@
|
||||
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
|
264
doxy-boot.js
Normal file
264
doxy-boot.js
Normal file
@ -0,0 +1,264 @@
|
||||
$( document ).ready(function() {
|
||||
|
||||
$("div.headertitle").addClass("page-header");
|
||||
$("div.title").addClass("h1");
|
||||
|
||||
$('li > a[href="index.html"] > span').before("<i class='fa fa-cog'></i> ");
|
||||
$('li > a[href="modules.html"] > span').before("<i class='fa fa-square'></i> ");
|
||||
$('li > a[href="namespaces.html"] > span').before("<i class='fa fa-bars'></i> ");
|
||||
$('li > a[href="annotated.html"] > span').before("<i class='fa fa-list-ul'></i> ");
|
||||
$('li > a[href="classes.html"] > span').before("<i class='fa fa-book'></i> ");
|
||||
$('li > a[href="inherits.html"] > span').before("<i class='fa fa-sitemap'></i> ");
|
||||
$('li > a[href="functions.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||
$('li > a[href="functions_func.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||
$('li > a[href="functions_vars.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||
$('li > a[href="functions_enum.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||
$('li > a[href="functions_eval.html"] > span').before("<i class='fa fa-list'></i> ");
|
||||
$('img[src="ftv2ns.png"]').replaceWith('<span class="label label-danger">N</span> ');
|
||||
$('img[src="ftv2cl.png"]').replaceWith('<span class="label label-danger">C</span> ');
|
||||
|
||||
$("ul.tablist").addClass("nav nav-pills nav-justified");
|
||||
$("ul.tablist").css("margin-top", "0.5em");
|
||||
$("ul.tablist").css("margin-bottom", "0.5em");
|
||||
$("li.current").addClass("active");
|
||||
$("iframe").attr("scrolling", "yes");
|
||||
|
||||
$("#nav-path > ul").addClass("breadcrumb");
|
||||
|
||||
$("table.params").addClass("table");
|
||||
$("div.ingroups").wrapInner("<small></small>");
|
||||
$("div.levels").css("margin", "0.5em");
|
||||
$("div.levels > span").addClass("btn btn-default btn-xs");
|
||||
$("div.levels > span").css("margin-right", "0.25em");
|
||||
|
||||
$("table.directory").addClass("table table-striped");
|
||||
$("div.summary > a").addClass("btn btn-default btn-xs");
|
||||
$("table.fieldtable").addClass("table");
|
||||
$(".fragment").addClass("well");
|
||||
$(".memitem").addClass("panel panel-default");
|
||||
$(".memproto").addClass("panel-heading");
|
||||
$(".memdoc").addClass("panel-body");
|
||||
$("span.mlabel").addClass("label label-info");
|
||||
|
||||
$("table.memberdecls").addClass("table");
|
||||
$("[class^=memitem]").addClass("active");
|
||||
|
||||
$("div.ah").addClass("btn btn-default");
|
||||
$("span.mlabels").addClass("pull-right");
|
||||
$("table.mlabels").css("width", "100%")
|
||||
$("td.mlabels-right").addClass("pull-right");
|
||||
|
||||
$("div.ttc").addClass("panel panel-primary");
|
||||
$("div.ttname").addClass("panel-heading");
|
||||
$("div.ttname a").css("color", 'white');
|
||||
$("div.ttdef,div.ttdoc,div.ttdeci").addClass("panel-body");
|
||||
|
||||
$('div.fragment.well div.line:first').css('margin-top', '15px');
|
||||
$('div.fragment.well div.line:last').css('margin-bottom', '15px');
|
||||
|
||||
$('table.doxtable').removeClass('doxtable').addClass('table table-striped table-bordered').each(function(){
|
||||
$(this).prepend('<thead></thead>');
|
||||
$(this).find('tbody > tr:first').prependTo($(this).find('thead'));
|
||||
|
||||
$(this).find('td > span.success').parent().addClass('success');
|
||||
$(this).find('td > span.warning').parent().addClass('warning');
|
||||
$(this).find('td > span.danger').parent().addClass('danger');
|
||||
});
|
||||
|
||||
|
||||
|
||||
if($('div.fragment.well div.ttc').length > 0)
|
||||
{
|
||||
$('div.fragment.well div.line:first').parent().removeClass('fragment well');
|
||||
}
|
||||
//merge left ad right element in the fuction table item
|
||||
/*
|
||||
$('table.memberdecls').find('.memItemRight').each(function(){
|
||||
$(this).contents().appendTo($(this).siblings('.memItemLeft'));
|
||||
$(this).siblings('.memItemLeft').attr('align', 'left');
|
||||
});
|
||||
*/
|
||||
|
||||
function getOriginalWidthOfImg(img_element) {
|
||||
var t = new Image();
|
||||
t.src = (img_element.getAttribute ? img_element.getAttribute("src") : false) || img_element.src;
|
||||
return t.width;
|
||||
}
|
||||
|
||||
$('div.dyncontent').find('img').each(function(){
|
||||
if(getOriginalWidthOfImg($(this)[0]) > $('#content>div.container').width())
|
||||
$(this).css('width', '100%');
|
||||
});
|
||||
|
||||
|
||||
/* responsive search box */
|
||||
|
||||
$('#MSearchBox').parent().remove();
|
||||
|
||||
var nav_container = $('<div class="row"></div>');
|
||||
$('#navrow1').parent().prepend(nav_container);
|
||||
|
||||
var left_nav = $('<div class="col-md-9"></div>');
|
||||
for (i = 0; i < 6; i++) {
|
||||
var navrow = $('#navrow' + i + ' > ul.tablist').detach();
|
||||
left_nav.append(navrow);
|
||||
$('#navrow' + i).remove();
|
||||
}
|
||||
var right_nav = $('<div class="col-md-3"></div>').append('\
|
||||
<div id="search-box" class="input-group">\
|
||||
<div class="input-group-btn">\
|
||||
<button aria-expanded="false" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">\
|
||||
<span class="glyphicon glyphicon-search"></span> <span class="caret"></span>\
|
||||
</button>\
|
||||
<ul class="dropdown-menu">\
|
||||
</ul>\
|
||||
</div>\
|
||||
<button id="search-close" type="button" class="close" aria-label="Close"><span aria-hidden="true">×</span></button>\
|
||||
<input id="search-field" class="form-control" accesskey="S" onkeydown="searchBox.OnSearchFieldChange(event);" placeholder="Search ..." type="text">\
|
||||
</div>');
|
||||
$(nav_container).append(left_nav);
|
||||
$(nav_container).append(right_nav);
|
||||
|
||||
$('#MSearchSelectWindow .SelectionMark').remove();
|
||||
var search_selectors = $('#MSearchSelectWindow .SelectItem');
|
||||
for (var i = 0; i < search_selectors.length; i += 1) {
|
||||
var element_a = $('<a href="#"></a>').text($(search_selectors[i]).text());
|
||||
|
||||
element_a.click(function(){
|
||||
$('#search-box .dropdown-menu li').removeClass('active');
|
||||
$(this).parent().addClass('active');
|
||||
searchBox.OnSelectItem($('#search-box li a').index(this));
|
||||
searchBox.Search();
|
||||
return false;
|
||||
});
|
||||
|
||||
var element = $('<li></li>').append(element_a);
|
||||
$('#search-box .dropdown-menu').append(element);
|
||||
}
|
||||
$('#MSearchSelectWindow').remove();
|
||||
|
||||
$('#search-box .close').click(function (){
|
||||
searchBox.CloseResultsWindow();
|
||||
});
|
||||
|
||||
$('body').append('<div id="MSearchClose"></div>');
|
||||
$('body').append('<div id="MSearchBox"></div>');
|
||||
$('body').append('<div id="MSearchSelectWindow"></div>');
|
||||
|
||||
searchBox.searchLabel = '';
|
||||
searchBox.DOMSearchField = function() {
|
||||
return document.getElementById("search-field");
|
||||
}
|
||||
searchBox.DOMSearchClose = function(){
|
||||
return document.getElementById("search-close");
|
||||
}
|
||||
|
||||
|
||||
/* search results */
|
||||
var results_iframe = $('#MSearchResults').detach();
|
||||
$('#MSearchResultsWindow')
|
||||
.attr('id', 'search-results-window')
|
||||
.addClass('panel panel-default')
|
||||
.append(
|
||||
'<div class="panel-heading">\
|
||||
<h3 class="panel-title">Search Results</h3>\
|
||||
</div>\
|
||||
<div class="panel-body"></div>'
|
||||
);
|
||||
$('#search-results-window .panel-body').append(results_iframe);
|
||||
|
||||
searchBox.DOMPopupSearchResultsWindow = function() {
|
||||
return document.getElementById("search-results-window");
|
||||
}
|
||||
|
||||
function update_search_results_window() {
|
||||
$('#search-results-window').removeClass('panel-default panel-success panel-warning panel-danger')
|
||||
var status = $('#MSearchResults').contents().find('.SRStatus:visible');
|
||||
if (status.length > 0) {
|
||||
switch(status.attr('id')) {
|
||||
case 'Loading':
|
||||
case 'Searching':
|
||||
$('#search-results-window').addClass('panel-warning');
|
||||
break;
|
||||
case 'NoMatches':
|
||||
$('#search-results-window').addClass('panel-danger');
|
||||
break;
|
||||
default:
|
||||
$('#search-results-window').addClass('panel-default');
|
||||
}
|
||||
} else {
|
||||
$('#search-results-window').addClass('panel-success');
|
||||
}
|
||||
}
|
||||
$('#MSearchResults').load(function() {
|
||||
$('#MSearchResults').contents().find('link[href="search.css"]').attr('href','../doxygen.css');
|
||||
$('#MSearchResults').contents().find('head').append(
|
||||
'<link href="../customdoxygen.css" rel="stylesheet" type="text/css">');
|
||||
|
||||
update_search_results_window();
|
||||
|
||||
// detect status changes (only for search with external search backend)
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
update_search_results_window();
|
||||
});
|
||||
var config = {
|
||||
attributes: true
|
||||
};
|
||||
|
||||
var targets = $('#MSearchResults').contents().find('.SRStatus');
|
||||
for (i = 0; i < targets.length; i++) {
|
||||
observer.observe(targets[i], config);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* enumerations */
|
||||
$('table.fieldtable').removeClass('fieldtable').addClass('table table-striped table-bordered').each(function(){
|
||||
$(this).prepend('<thead></thead>');
|
||||
$(this).find('tbody > tr:first').prependTo($(this).find('thead'));
|
||||
|
||||
$(this).find('td > span.success').parent().addClass('success');
|
||||
$(this).find('td > span.warning').parent().addClass('warning');
|
||||
$(this).find('td > span.danger').parent().addClass('danger');
|
||||
});
|
||||
|
||||
/* todo list */
|
||||
var todoelements = $('.contents > .textblock > dl.reflist > dt, .contents > .textblock > dl.reflist > dd');
|
||||
for (var i = 0; i < todoelements.length; i += 2) {
|
||||
$('.contents > .textblock').append(
|
||||
'<div class="panel panel-default active">'
|
||||
+ "<div class=\"panel-heading todoname\">" + $(todoelements[i]).html() + "</div>"
|
||||
+ "<div class=\"panel-body\">" + $(todoelements[i+1]).html() + "</div>"
|
||||
+ '</div>');
|
||||
}
|
||||
$('.contents > .textblock > dl').remove();
|
||||
|
||||
|
||||
$(".memitem").removeClass('memitem');
|
||||
$(".memproto").removeClass('memproto');
|
||||
$(".memdoc").removeClass('memdoc');
|
||||
$("span.mlabel").removeClass('mlabel');
|
||||
$("table.memberdecls").removeClass('memberdecls');
|
||||
$("[class^=memitem]").removeClass('memitem');
|
||||
$("span.mlabels").removeClass('mlabels');
|
||||
$("table.mlabels").removeClass('mlabels');
|
||||
$("td.mlabels-right").removeClass('mlabels-right');
|
||||
$(".navpath").removeClass('navpath');
|
||||
$("li.navelem").removeClass('navelem');
|
||||
$("a.el").removeClass('el');
|
||||
$("div.ah").removeClass('ah');
|
||||
$("div.header").removeClass("header");
|
||||
|
||||
$('.mdescLeft').each(function(){
|
||||
if($(this).html()==" ") {
|
||||
$(this).siblings('.mdescRight').attr('colspan', 2);
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
$('td.memItemLeft').each(function(){
|
||||
if($(this).siblings('.memItemRight').html()=="") {
|
||||
$(this).attr('colspan', 2);
|
||||
$(this).siblings('.memItemRight').remove();
|
||||
}
|
||||
});
|
||||
});
|
@ -1,37 +0,0 @@
|
||||
#!/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
|
1508
doxygen.css
Normal file
1508
doxygen.css
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doxygen.png
Normal file
BIN
doxygen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
97
dynsections.js
Normal file
97
dynsections.js
Normal file
@ -0,0 +1,97 @@
|
||||
function toggleVisibility(linkObj)
|
||||
{
|
||||
var base = $(linkObj).attr('id');
|
||||
var summary = $('#'+base+'-summary');
|
||||
var content = $('#'+base+'-content');
|
||||
var trigger = $('#'+base+'-trigger');
|
||||
var src=$(trigger).attr('src');
|
||||
if (content.is(':visible')===true) {
|
||||
content.hide();
|
||||
summary.show();
|
||||
$(linkObj).addClass('closed').removeClass('opened');
|
||||
$(trigger).attr('src',src.substring(0,src.length-8)+'closed.png');
|
||||
} else {
|
||||
content.show();
|
||||
summary.hide();
|
||||
$(linkObj).removeClass('closed').addClass('opened');
|
||||
$(trigger).attr('src',src.substring(0,src.length-10)+'open.png');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateStripes()
|
||||
{
|
||||
$('table.directory tr').
|
||||
removeClass('even').filter(':visible:even').addClass('even');
|
||||
}
|
||||
|
||||
function toggleLevel(level)
|
||||
{
|
||||
$('table.directory tr').each(function() {
|
||||
var l = this.id.split('_').length-1;
|
||||
var i = $('#img'+this.id.substring(3));
|
||||
var a = $('#arr'+this.id.substring(3));
|
||||
if (l<level+1) {
|
||||
i.removeClass('iconfopen iconfclosed').addClass('iconfopen');
|
||||
a.html('▼');
|
||||
$(this).show();
|
||||
} else if (l==level+1) {
|
||||
i.removeClass('iconfclosed iconfopen').addClass('iconfclosed');
|
||||
a.html('►');
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
updateStripes();
|
||||
}
|
||||
|
||||
function toggleFolder(id)
|
||||
{
|
||||
// the clicked row
|
||||
var currentRow = $('#row_'+id);
|
||||
|
||||
// all rows after the clicked row
|
||||
var rows = currentRow.nextAll("tr");
|
||||
|
||||
var re = new RegExp('^row_'+id+'\\d+_$', "i"); //only one sub
|
||||
|
||||
// only match elements AFTER this one (can't hide elements before)
|
||||
var childRows = rows.filter(function() { return this.id.match(re); });
|
||||
|
||||
// first row is visible we are HIDING
|
||||
if (childRows.filter(':first').is(':visible')===true) {
|
||||
// replace down arrow by right arrow for current row
|
||||
var currentRowSpans = currentRow.find("span");
|
||||
currentRowSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
|
||||
currentRowSpans.filter(".arrow").html('►');
|
||||
rows.filter("[id^=row_"+id+"]").hide(); // hide all children
|
||||
} else { // we are SHOWING
|
||||
// replace right arrow by down arrow for current row
|
||||
var currentRowSpans = currentRow.find("span");
|
||||
currentRowSpans.filter(".iconfclosed").removeClass("iconfclosed").addClass("iconfopen");
|
||||
currentRowSpans.filter(".arrow").html('▼');
|
||||
// replace down arrows by right arrows for child rows
|
||||
var childRowsSpans = childRows.find("span");
|
||||
childRowsSpans.filter(".iconfopen").removeClass("iconfopen").addClass("iconfclosed");
|
||||
childRowsSpans.filter(".arrow").html('►');
|
||||
childRows.show(); //show all children
|
||||
}
|
||||
updateStripes();
|
||||
}
|
||||
|
||||
|
||||
function toggleInherit(id)
|
||||
{
|
||||
var rows = $('tr.inherit.'+id);
|
||||
var img = $('tr.inherit_header.'+id+' img');
|
||||
var src = $(img).attr('src');
|
||||
if (rows.filter(':first').is(':visible')===true) {
|
||||
rows.css('display','none');
|
||||
$(img).attr('src',src.substring(0,src.length-8)+'closed.png');
|
||||
} else {
|
||||
rows.css('display','table-row'); // using show() causes jump in firefox
|
||||
$(img).attr('src',src.substring(0,src.length-10)+'open.png');
|
||||
}
|
||||
}
|
||||
|
BIN
folderclosed.png
Normal file
BIN
folderclosed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 616 B |
BIN
folderopen.png
Normal file
BIN
folderopen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 597 B |
211
index.html
Normal file
211
index.html
Normal file
@ -0,0 +1,211 @@
|
||||
<!-- HTML header for doxygen 1.8.8-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- For Mobile Devices -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<title>audio-river: Multi-nodal audio interface: AUDIO-RIVER library</title>
|
||||
<!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="search/searchdata.js"></script>
|
||||
<script type="text/javascript" src="search/search.js"></script>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||||
<link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">audio-river: Multi-nodal audio interface 0.4.0</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Main Page</a></li>
|
||||
<li><a href="pages.html">Related Pages</a></li>
|
||||
<li><a href="namespaces.html">Namespaces</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="files.html">Files</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Link-libs<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://HeeroYui.github.io/lutin">lutin</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ewol">ewol</a></li>
|
||||
<li><a href="http://atria-soft.github.io/echrono">echrono</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etk">etk</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ejson">ejson</a></li>
|
||||
<li><a href="http://atria-soft.github.io/exml">exml</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esvg">esvg</a></li>
|
||||
<li><a href="http://atria-soft.github.io/egami">egami</a></li>
|
||||
<li><a href="http://atria-soft.github.io/gale">gale</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ege">ege</a></li>
|
||||
<li><a href="http://atria-soft.github.io/elog">elog</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ememory">ememory</a></li>
|
||||
<li><a href="http://atria-soft.github.io/enet">enet</a></li>
|
||||
<li><a href="http://atria-soft.github.io/eproperty">eproperty</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esignal">esignal</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etranslate">etranslate</a></li>
|
||||
<li><a href="http://atria-soft.github.io/zeus">zeus</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-ess">audio-ess</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio">audio</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-drain">audio-drain</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-orchestra">audio-orchestra</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-river">audio-river</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="search-box" class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button aria-expanded="false" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="glyphicon glyphicon-search"></span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">All</a></li>
|
||||
<li><a href="#">Classes</a></li>
|
||||
<li><a href="#">Namespaces</a></li>
|
||||
<li><a href="#">Files</a></li>
|
||||
<li><a href="#">Functions</a></li>
|
||||
<li><a href="#">Variables</a></li>
|
||||
<li><a href="#">Typedefs</a></li>
|
||||
<li><a href="#">Enumerations</a></li>
|
||||
<li><a href="#">Enumerator</a></li>
|
||||
<li><a href="#">Friends</a></li>
|
||||
<li><a href="#">Macros</a></li>
|
||||
<li><a href="#">Pages</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button id="search-close" type="button" class="close" aria-label="Close">
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
<input id="search-field" class="form-control" accesskey="S" onkeydown="searchBox.OnSearchFieldChange(event);" placeholder="Search ..." type="text">
|
||||
</div>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="content" id="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
||||
<div style="margin-bottom: 15px;margin-top: 60px;">
|
||||
<!-- end header part -->
|
||||
<!-- Generated by Doxygen 1.8.12 -->
|
||||
<script type="text/javascript">
|
||||
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
||||
</script>
|
||||
<script type="text/javascript" src="menudata.js"></script>
|
||||
<script type="text/javascript" src="menu.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
initMenu('',true,false,'search.php','Search');
|
||||
$(document).ready(function() { init_search(); });
|
||||
});
|
||||
</script>
|
||||
<div id="main-nav"></div>
|
||||
</div><!-- top -->
|
||||
<!-- window showing the filter options -->
|
||||
<div id="MSearchSelectWindow"
|
||||
onmouseover="return searchBox.OnSearchSelectShow()"
|
||||
onmouseout="return searchBox.OnSearchSelectHide()"
|
||||
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||||
</div>
|
||||
|
||||
<!-- iframe showing the search results (closed by default) -->
|
||||
<div id="MSearchResultsWindow">
|
||||
<iframe src="javascript:void(0)" frameborder="0"
|
||||
name="MSearchResults" id="MSearchResults">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<div class="headertitle">
|
||||
<div class="title">AUDIO-RIVER library </div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="toc"><h3>Table of Contents</h3>
|
||||
<ul><li class="level1"><a href="#audio_river_mainpage_what">What is AUDIO-RIVER: </a></li>
|
||||
<li class="level1"><a href="#audio_river_mainpage_what_it_does">What it does: </a></li>
|
||||
<li class="level1"><a href="#audio_river_mainpage_language">What languages are supported? </a></li>
|
||||
<li class="level1"><a href="#audio_river_mainpage_license_restriction">Are there any licensing restrictions? </a></li>
|
||||
<li class="level1"><a href="#audio_river_mainpage_license">License (APACHE-2.0) </a></li>
|
||||
<li class="level1"><a href="#audio_river_mainpage_sub_page">Other pages </a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="textblock"><h1><a class="anchor" id="audio_river_mainpage_what"></a>
|
||||
What is AUDIO-RIVER: </h1>
|
||||
<p>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.</p>
|
||||
<h1><a class="anchor" id="audio_river_mainpage_what_it_does"></a>
|
||||
What it does: </h1>
|
||||
<p>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)</p>
|
||||
<p>AUDIO-RIVER is dependent of the STL (compatible with MacOs stl (CXX))</p>
|
||||
<h2>Architecture: </h2>
|
||||
<p>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).</p>
|
||||
<p>Start at this point we will have simple objectives :</p><ul>
|
||||
<li>Manage multiple Low level interface: <a class="elRef" doxygen="/home/heero/dev/perso/out/doc/release/audio-orchestra.tag:http://musicdsp.github.io/audio-orchestra/" href="http://musicdsp.github.io/audio-orchestra/index.html#audio_orchestra_mainpage_what">What is AUDIO-ORCHESTRA: </a><ul>
|
||||
<li>for linux (Alsa, Pulse, Oss)</li>
|
||||
<li>for Mac-OsX (CoreAudio)</li>
|
||||
<li>for IOs (coreAudio (embended version))</li>
|
||||
<li>for Windows (ASIO)</li>
|
||||
<li>For Android (Java (JDK...))</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Synchronous interface ==> no delay and reduce latency</li>
|
||||
<li>Manage the thread priority (need sometimes to be more reactive)</li>
|
||||
<li>manage mixing of some flow (2 inputs stereo and the user want 1 input quad)</li>
|
||||
<li>AEC Acoustic Echo Cancelation (TODO : in the current implementation we have a simple sound cutter)</li>
|
||||
<li>Equalizer (done with audio_drain_mainpage_what)</li>
|
||||
<li>Resmpling (done by the libspeexDSP)</li>
|
||||
<li>Correct volume management (and configurable)</li>
|
||||
<li>Fade-in and Fade-out audio_drain_mainpage_what</li>
|
||||
<li>Channel reorganisation audio_drain_mainpage_what</li>
|
||||
<li>A correct feedback interface</li>
|
||||
</ul>
|
||||
<h1><a class="anchor" id="audio_river_mainpage_language"></a>
|
||||
What languages are supported? </h1>
|
||||
<p>AUDIO-RIVER is written in C++.</p>
|
||||
<h1><a class="anchor" id="audio_river_mainpage_license_restriction"></a>
|
||||
Are there any licensing restrictions? </h1>
|
||||
<p>AUDIO-RIVER is <b>FREE software</b> and <em>all sub-library are FREE and staticly linkable !!!</em></p>
|
||||
<h1><a class="anchor" id="audio_river_mainpage_license"></a>
|
||||
License (APACHE-2.0) </h1>
|
||||
<p>Copyright AUDIO-RIVER Edouard DUPIN</p>
|
||||
<p>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</p>
|
||||
<p><a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a></p>
|
||||
<p>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.</p>
|
||||
<h1><a class="anchor" id="audio_river_mainpage_sub_page"></a>
|
||||
Other pages </h1>
|
||||
<ul>
|
||||
<li><a class="el" href="audio_river_build.html">Build lib & build sample</a></li>
|
||||
<li><a class="el" href="audio_river_read.html">Read stream form Audio input</a></li>
|
||||
<li><a class="el" href="audio_river_write.html">Write stream to Audio output</a></li>
|
||||
<li><a class="el" href="audio_river_feedback.html">Read stream feedback</a></li>
|
||||
<li><a class="el" href="audio_river_config_file.html">River configuration file</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ewol/ewol_coding_style.html"><b>ewol coding style</b></a> </li>
|
||||
</ul>
|
||||
</div></div><!-- contents -->
|
||||
<!-- HTML footer for doxygen 1.8.8-->
|
||||
<!-- start footer part -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
Generated on Mon Oct 24 2016 15:35:48 for audio-river: Multi-nodal audio interface by  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="doxygen.png" alt="doxygen"/>
|
||||
</a> 1.8.12
|
||||
</small></address>
|
||||
</body>
|
||||
</html>
|
87
jquery.js
vendored
Normal file
87
jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import realog.debug as debug
|
||||
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 "MPL-2"
|
||||
|
||||
def get_compagny_type():
|
||||
return "com"
|
||||
|
||||
def get_compagny_name():
|
||||
return "atria-soft"
|
||||
|
||||
def get_maintainer():
|
||||
return "authors.txt"
|
||||
|
||||
def configure(target, my_module):
|
||||
my_module.add_src_file([
|
||||
'test/main.cpp',
|
||||
'test/testAEC.cpp',
|
||||
'test/testEchoDelay.cpp',
|
||||
'test/testFormat.cpp',
|
||||
'test/testMuxer.cpp',
|
||||
'test/testPlaybackCallback.cpp',
|
||||
'test/testPlaybackWrite.cpp',
|
||||
'test/testRecordCallback.cpp',
|
||||
'test/testRecordRead.cpp',
|
||||
'test/testVolume.cpp',
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio-river',
|
||||
'etest',
|
||||
'etk',
|
||||
'test-debug'
|
||||
])
|
||||
return True
|
||||
|
||||
|
@ -1,66 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import realog.debug as debug
|
||||
import lutin.tools as tools
|
||||
|
||||
|
||||
def get_type():
|
||||
return "LIBRARY"
|
||||
|
||||
def get_desc():
|
||||
return "Multi-nodal audio interface"
|
||||
|
||||
def get_licence():
|
||||
return "MPL-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 configure(target, my_module):
|
||||
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.hpp',
|
||||
'audio/river/Manager.hpp',
|
||||
'audio/river/Interface.hpp',
|
||||
'audio/river/io/Group.hpp',
|
||||
'audio/river/io/Node.hpp',
|
||||
'audio/river/io/Manager.hpp'
|
||||
])
|
||||
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(".")
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
26
menu.js
Normal file
26
menu.js
Normal file
@ -0,0 +1,26 @@
|
||||
function initMenu(relPath,searchEnabled,serverSide,searchPage,search) {
|
||||
function makeTree(data,relPath) {
|
||||
var result='';
|
||||
if ('children' in data) {
|
||||
result+='<ul>';
|
||||
for (var i in data.children) {
|
||||
result+='<li><a href="'+relPath+data.children[i].url+'">'+
|
||||
data.children[i].text+'</a>'+
|
||||
makeTree(data.children[i],relPath)+'</li>';
|
||||
}
|
||||
result+='</ul>';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
$('#main-nav').append(makeTree(menudata,relPath));
|
||||
$('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu');
|
||||
if (searchEnabled) {
|
||||
if (serverSide) {
|
||||
$('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><div class="left"><form id="FSearchBox" action="'+searchPage+'" method="get"><img id="MSearchSelect" src="'+relPath+'search/mag.png" alt=""/><input type="text" id="MSearchField" name="query" value="'+search+'" size="20" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)"></form></div><div class="right"></div></div></li>');
|
||||
} else {
|
||||
$('#main-menu').append('<li style="float:right"><div id="MSearchBox" class="MSearchBoxInactive"><span class="left"><img id="MSearchSelect" src="'+relPath+'search/mag_sel.png" onmouseover="return searchBox.OnSearchSelectShow()" onmouseout="return searchBox.OnSearchSelectHide()" alt=""/><input type="text" id="MSearchField" value="'+search+'" accesskey="S" onfocus="searchBox.OnSearchFieldFocus(true)" onblur="searchBox.OnSearchFieldFocus(false)" onkeyup="searchBox.OnSearchFieldChange(event)"/></span><span class="right"><a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="'+relPath+'search/close.png" alt=""/></a></span></div></li>');
|
||||
}
|
||||
}
|
||||
$('#main-menu').smartmenus();
|
||||
}
|
3
menudata.js
Normal file
3
menudata.js
Normal file
@ -0,0 +1,3 @@
|
||||
var menudata={children:[
|
||||
{text:'Main Page',url:'index.html'},
|
||||
{text:'Related Pages',url:'pages.html'}]}
|
160
pages.html
Normal file
160
pages.html
Normal file
@ -0,0 +1,160 @@
|
||||
<!-- HTML header for doxygen 1.8.8-->
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- For Mobile Devices -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
<title>audio-river: Multi-nodal audio interface: Related Pages</title>
|
||||
<!--<link href="tabs.css" rel="stylesheet" type="text/css"/>-->
|
||||
<script type="text/javascript" src="dynsections.js"></script>
|
||||
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||||
<script type="text/javascript" src="search/searchdata.js"></script>
|
||||
<script type="text/javascript" src="search/search.js"></script>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||||
<link href="customdoxygen.css" rel="stylesheet" type="text/css"/>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="doxy-boot.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">audio-river: Multi-nodal audio interface 0.4.0</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="index.html">Main Page</a></li>
|
||||
<li><a href="pages.html">Related Pages</a></li>
|
||||
<li><a href="namespaces.html">Namespaces</a></li>
|
||||
<li><a href="annotated.html">Classes</a></li>
|
||||
<li><a href="files.html">Files</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
||||
Link-libs<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://HeeroYui.github.io/lutin">lutin</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ewol">ewol</a></li>
|
||||
<li><a href="http://atria-soft.github.io/echrono">echrono</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etk">etk</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ejson">ejson</a></li>
|
||||
<li><a href="http://atria-soft.github.io/exml">exml</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esvg">esvg</a></li>
|
||||
<li><a href="http://atria-soft.github.io/egami">egami</a></li>
|
||||
<li><a href="http://atria-soft.github.io/gale">gale</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ege">ege</a></li>
|
||||
<li><a href="http://atria-soft.github.io/elog">elog</a></li>
|
||||
<li><a href="http://atria-soft.github.io/ememory">ememory</a></li>
|
||||
<li><a href="http://atria-soft.github.io/enet">enet</a></li>
|
||||
<li><a href="http://atria-soft.github.io/eproperty">eproperty</a></li>
|
||||
<li><a href="http://atria-soft.github.io/esignal">esignal</a></li>
|
||||
<li><a href="http://atria-soft.github.io/etranslate">etranslate</a></li>
|
||||
<li><a href="http://atria-soft.github.io/zeus">zeus</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-ess">audio-ess</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio">audio</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-drain">audio-drain</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-orchestra">audio-orchestra</a></li>
|
||||
<li><a href="http://musicdsp.github.io/audio-river">audio-river</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="search-box" class="input-group">
|
||||
<div class="input-group-btn">
|
||||
<button aria-expanded="false" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="glyphicon glyphicon-search"></span>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">All</a></li>
|
||||
<li><a href="#">Classes</a></li>
|
||||
<li><a href="#">Namespaces</a></li>
|
||||
<li><a href="#">Files</a></li>
|
||||
<li><a href="#">Functions</a></li>
|
||||
<li><a href="#">Variables</a></li>
|
||||
<li><a href="#">Typedefs</a></li>
|
||||
<li><a href="#">Enumerations</a></li>
|
||||
<li><a href="#">Enumerator</a></li>
|
||||
<li><a href="#">Friends</a></li>
|
||||
<li><a href="#">Macros</a></li>
|
||||
<li><a href="#">Pages</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button id="search-close" type="button" class="close" aria-label="Close">
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
<input id="search-field" class="form-control" accesskey="S" onkeydown="searchBox.OnSearchFieldChange(event);" placeholder="Search ..." type="text">
|
||||
</div>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||
<div class="content" id="content">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 panel panel-default" style="padding-bottom: 15px;">
|
||||
<div style="margin-bottom: 15px;margin-top: 60px;">
|
||||
<!-- end header part -->
|
||||
<!-- Generated by Doxygen 1.8.12 -->
|
||||
<script type="text/javascript">
|
||||
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
||||
</script>
|
||||
<script type="text/javascript" src="menudata.js"></script>
|
||||
<script type="text/javascript" src="menu.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
initMenu('',true,false,'search.php','Search');
|
||||
$(document).ready(function() { init_search(); });
|
||||
});
|
||||
</script>
|
||||
<div id="main-nav"></div>
|
||||
</div><!-- top -->
|
||||
<!-- window showing the filter options -->
|
||||
<div id="MSearchSelectWindow"
|
||||
onmouseover="return searchBox.OnSearchSelectShow()"
|
||||
onmouseout="return searchBox.OnSearchSelectHide()"
|
||||
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||||
</div>
|
||||
|
||||
<!-- iframe showing the search results (closed by default) -->
|
||||
<div id="MSearchResultsWindow">
|
||||
<iframe src="javascript:void(0)" frameborder="0"
|
||||
name="MSearchResults" id="MSearchResults">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<div class="headertitle">
|
||||
<div class="title">Related Pages</div> </div>
|
||||
</div><!--header-->
|
||||
<div class="contents">
|
||||
<div class="textblock">Here is a list of all related documentation pages:</div><div class="directory">
|
||||
<table class="directory">
|
||||
<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="audio_river_build.html" target="_self">Build lib & build sample</a></td><td class="desc"></td></tr>
|
||||
<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="audio_river_config_file.html" target="_self">River configuration file</a></td><td class="desc"></td></tr>
|
||||
<tr id="row_2_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="audio_river_feedback.html" target="_self">Read stream feedback</a></td><td class="desc"></td></tr>
|
||||
<tr id="row_3_"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="audio_river_read.html" target="_self">Read stream form Audio input</a></td><td class="desc"></td></tr>
|
||||
<tr id="row_4_" class="even"><td class="entry"><span style="width:16px;display:inline-block;"> </span><a class="el" href="audio_river_write.html" target="_self">Write stream to Audio output</a></td><td class="desc"></td></tr>
|
||||
</table>
|
||||
</div><!-- directory -->
|
||||
</div><!-- contents -->
|
||||
<!-- HTML footer for doxygen 1.8.8-->
|
||||
<!-- start footer part -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="footer"/><address class="footer"><small>
|
||||
Generated on Mon Oct 24 2016 15:35:48 for audio-river: Multi-nodal audio interface by  <a href="http://www.doxygen.org/index.html">
|
||||
<img class="footer" src="doxygen.png" alt="doxygen"/>
|
||||
</a> 1.8.12
|
||||
</small></address>
|
||||
</body>
|
||||
</html>
|
@ -1,64 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#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(null) {
|
||||
addObjectType("appl::Windows");
|
||||
propertyTitle.setDirectCheck("River IO viewer");
|
||||
}
|
||||
|
||||
void appl::Windows::init() {
|
||||
ewol::widget::Windows::init();
|
||||
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";
|
||||
composition += " <label>\n";
|
||||
composition += " Start/Stop record\n";
|
||||
composition += " </label>\n";
|
||||
composition += " </button>\n";
|
||||
composition += " <button name='bt-generate' expend='true' fill='true'>\n";
|
||||
composition += " <label>\n";
|
||||
composition += " Start/Stop Generate\n";
|
||||
composition += " </label>\n";
|
||||
composition += " </button>\n";
|
||||
composition += " </sizer>\n";
|
||||
composition += " <TemporalViewer name='displayer' expand='true' fill='true'/>\n";
|
||||
composition += "</sizer>\n";
|
||||
|
||||
m_composer = ewol::widget::Composer::create();
|
||||
if (m_composer == null) {
|
||||
APPL_CRITICAL(" An error occured ... in the windows creatrion ...");
|
||||
return;
|
||||
}
|
||||
m_composer->loadFromString(composition);
|
||||
setSubWidget(m_composer);
|
||||
subBind(ewol::widget::Button, "bt-record", signalPressed, sharedFromThis(), &appl::Windows::onCallbackRecord);
|
||||
subBind(ewol::widget::Button, "bt-generate", signalPressed, sharedFromThis(), &appl::Windows::onCallbackGenerate);
|
||||
}
|
||||
|
||||
void appl::Windows::onCallbackRecord() {
|
||||
ememory::SharedPtr<audio::river::widget::TemporalViewer> tmpDisp = ememory::dynamicPointerCast<audio::river::widget::TemporalViewer>(getSubObjectNamed("displayer"));
|
||||
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 != null) {
|
||||
tmpDisp->generateToggle();
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ewol/widget/Windows.hpp>
|
||||
#include <ewol/widget/Composer.hpp>
|
||||
|
||||
namespace appl {
|
||||
class Windows : public ewol::widget::Windows {
|
||||
private:
|
||||
ememory::SharedPtr<ewol::widget::Composer> m_composer;
|
||||
protected:
|
||||
Windows();
|
||||
void init();
|
||||
public:
|
||||
DECLARE_FACTORY(Windows);
|
||||
public: // callback functions
|
||||
void onCallbackRecord();
|
||||
void onCallbackGenerate();
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
#include <appl/debug.hpp>
|
||||
|
||||
|
||||
int32_t appl::getLogId() {
|
||||
static int32_t g_val = elog::registerInstance("ioViewer");
|
||||
return g_val;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <elog/log.hpp>
|
||||
|
||||
namespace appl {
|
||||
int32_t getLogId();
|
||||
}
|
||||
|
||||
#define APPL_BASE(info,data) ELOG_BASE(appl::getLogId(),info,data)
|
||||
|
||||
#define APPL_PRINT(data) APPL_BASE(-1, data)
|
||||
#define APPL_CRITICAL(data) APPL_BASE(1, data)
|
||||
#define APPL_ERROR(data) APPL_BASE(2, data)
|
||||
#define APPL_WARNING(data) APPL_BASE(3, data)
|
||||
#ifdef DEBUG
|
||||
#define APPL_INFO(data) APPL_BASE(4, data)
|
||||
#define APPL_DEBUG(data) APPL_BASE(5, data)
|
||||
#define APPL_VERBOSE(data) APPL_BASE(6, data)
|
||||
#define APPL_TODO(data) APPL_BASE(4, "TODO : " << data)
|
||||
#else
|
||||
#define APPL_INFO(data) do { } while(false)
|
||||
#define APPL_DEBUG(data) do { } while(false)
|
||||
#define APPL_VERBOSE(data) do { } while(false)
|
||||
#define APPL_TODO(data) do { } while(false)
|
||||
#endif
|
||||
|
||||
#define APPL_ASSERT(cond,data) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
APPL_CRITICAL(data); \
|
||||
assert(!#cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
@ -1,140 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2019, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
|
||||
#include <etk/types.hpp>
|
||||
#include <ewol/ewol.hpp>
|
||||
#include <gale/context/commandLine.hpp>
|
||||
|
||||
#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 etk::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";
|
||||
|
||||
|
||||
class MainApplication : public ewol::context::Application {
|
||||
public:
|
||||
virtual void onCreate(ewol::Context& _context) override {
|
||||
APPL_INFO(" == > CREATE ... (START) [" << gale::getBoardType() << "] (" << gale::getCompilationMode() << ") (BEGIN)");
|
||||
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
|
||||
etk::String tmpppp = _context.getCmd().get(iii);
|
||||
if ( tmpppp == "-h"
|
||||
|| tmpppp == "--help") {
|
||||
//APPL_PRINT(" --ctags=xxx c-flags-file-name" );
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
etk::theme::setName("COLOR", "color/white/");
|
||||
|
||||
_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));
|
||||
|
||||
// select internal data for font ...
|
||||
_context.getFontDefault().setUseExternal(true);
|
||||
_context.getFontDefault().setSize(19);
|
||||
|
||||
audio::river::widget::TemporalViewer::createManagerWidget(_context.getWidgetManager());
|
||||
|
||||
ememory::SharedPtr<ewol::widget::Windows> basicWindows = appl::Windows::create();
|
||||
if (basicWindows == null) {
|
||||
APPL_ERROR("Can not allocate the basic windows");
|
||||
_context.exit(-1);
|
||||
return;
|
||||
}
|
||||
// create the specific windows
|
||||
_context.setWindows(basicWindows);
|
||||
|
||||
// add files
|
||||
APPL_INFO("show list of files : ");
|
||||
/*
|
||||
for( int32_t iii=0 ; iii<_context.getCmd().size(); iii++) {
|
||||
etk::String tmpppp = _context.getCmd().get(iii);
|
||||
if (tmpppp.startWith("--ctags=") == true) {
|
||||
etk::String name = tmpppp.extract(8);
|
||||
APPL_INFO("Load ctag file : \"" << name << "\"" );
|
||||
appl::setCtagsFileName(name);
|
||||
} else if ( tmpppp == "-h"
|
||||
|| tmpppp == "--help") {
|
||||
// nothing to do ...
|
||||
} else {
|
||||
etk::Path file(tmpppp);
|
||||
if (etk::path::isFile(file) == true) {
|
||||
APPL_INFO("need load file : \"" << file << "\"" );
|
||||
m_bufferManager->open(file);
|
||||
} else if (etk::path::isDirectory(file) == true) {
|
||||
etk::Vector<etk::Path> listOfFiles = etk::path::list(file, etk::path::LIST_FILE);
|
||||
for (auto &it: listOfFiles) {
|
||||
if (etk::path::isFile(it) == true) {
|
||||
APPL_INFO("need load file : \"" << it << "\"" );
|
||||
m_bufferManager->open(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
APPL_INFO("==> START ... (END)");
|
||||
return;
|
||||
}
|
||||
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)");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Main of the program (This can be set in every case, but it is not used in Andoid...).
|
||||
* @param std IO
|
||||
* @return std IO
|
||||
*/
|
||||
int main(int _argc, const char *_argv[]) {
|
||||
// second possibility
|
||||
return ewol::run(ETK_NEW(MainApplication), _argc, _argv);
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import realog.debug as debug
|
||||
import lutin.tools as tools
|
||||
import os
|
||||
|
||||
|
||||
def get_type():
|
||||
return "BINARY"
|
||||
|
||||
def get_desc():
|
||||
return "Simpleaudio IO viewer and test ..."
|
||||
|
||||
def get_licence():
|
||||
return "MPL-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 configure(target, my_module):
|
||||
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(".")
|
||||
# set the package properties :
|
||||
my_module.set_pkg("SECTION", ["Development"])
|
||||
my_module.set_pkg("PRIORITY", "optional")
|
||||
|
||||
my_module.add_pkg("RIGHT", "RECORD_AUDIO")
|
||||
return True
|
||||
|
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import realog.debug as debug
|
||||
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 "MPL-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 configure(target, my_module):
|
||||
my_module.add_src_file([
|
||||
'read.cpp',
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio-river',
|
||||
'test-debug',
|
||||
'etk'
|
||||
])
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,170 +0,0 @@
|
||||
/** @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]
|
@ -1,45 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import realog.debug as debug
|
||||
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 "MPL-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 configure(target, my_module):
|
||||
my_module.add_src_file([
|
||||
'write.cpp',
|
||||
])
|
||||
my_module.add_depend([
|
||||
'audio-river',
|
||||
'test-debug',
|
||||
'etk'
|
||||
])
|
||||
return True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,119 +0,0 @@
|
||||
/** @file
|
||||
* @author Edouard DUPIN
|
||||
* @copyright 2015, Edouard DUPIN, all right reserved
|
||||
* @license MPL v2.0 (see license file)
|
||||
*/
|
||||
|
||||
//! [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>
|
||||
|
||||
|
||||
//! [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,3',\n"
|
||||
" },\n"
|
||||
" frequency:48000,\n"
|
||||
//" channel-map:['front-left', 'front-right', 'rear-left', 'rear-right'],\n"
|
||||
" channel-map:['front-left', 'front-right'],\n"
|
||||
" type:'int16',\n"
|
||||
" nb-chunk:1024,\n"
|
||||
" 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 _sampleRate,
|
||||
const etk::Vector<audio::channel>& _map) {
|
||||
static double phase[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
if (_format != audio::format_int16) {
|
||||
TEST_ERROR("Call wrong type ... (need int16_t)");
|
||||
}
|
||||
//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++) {
|
||||
for (int32_t jjj=0; jjj<_map.size(); jjj++) {
|
||||
data[_map.size()*iii+jjj] = cos(phase[jjj]) * 30000;
|
||||
phase[jjj] += baseCycle*jjj;
|
||||
if (phase[jjj] >= 2*M_PI) {
|
||||
phase[jjj] -= 2*M_PI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//! [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) {
|
||||
etk::String data = _argv[iii];
|
||||
if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
TEST_PRINT("Help:");
|
||||
TEST_PRINT(" ./xxx ---");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
// initialize river interface
|
||||
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,
|
||||
etk::Vector<audio::channel>(),
|
||||
audio::format_int16,
|
||||
"speaker");
|
||||
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([=](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 ...
|
||||
ethread::sleepMilliSeconds(1000*(10));
|
||||
// stop the stream
|
||||
interface->stop();
|
||||
// remove interface and manager.
|
||||
interface.reset();
|
||||
manager.reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! [audio_river_sample_write_all]
|
||||
|
26
search/all_0.html
Normal file
26
search/all_0.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_0.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
27
search/all_0.js
Normal file
27
search/all_0.js
Normal file
@ -0,0 +1,27 @@
|
||||
var searchData=
|
||||
[
|
||||
['a',['a',['http://atria-soft.github.io/etk/classetk_1_1_color.html#a772e2882d3a9f91c6f73c0c70c8f3130',1,'etk::Color']]],
|
||||
['absolute',['absolute',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a0f1734db865e5a9c69d896bc237de133',1,'etk::Vector2D::absolute()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a0f1734db865e5a9c69d896bc237de133',1,'Vector2D< int32_t >::absolute()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a0f1734db865e5a9c69d896bc237de133',1,'Vector2D< uint32_t >::absolute()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a5b9733cd0928920ccc8e34d89e980b82',1,'etk::Vector3D::absolute()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#ab8a9feace5794c5a8a02e4b0e124408a',1,'etk::Vector4D::absolute()']]],
|
||||
['add',['add',['http://atria-soft.github.io/etk/classetk_1_1_hash.html#a723e93ae06d3d612dc4ebf2e1e7ffd5a',1,'etk::Hash::add()'],['http://atria-soft.github.io/ejson/classejson_1_1_array.html#af5bb12b12c4fc35869a32192539c7beb',1,'ejson::Array::add()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_array.html#ade4f0bf9db6c5f3dd14cab34815d175a',1,'ejson::internal::Array::add()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_object.html#a0248c96fa66e30adfb84249def2c4c94',1,'ejson::internal::Object::add()'],['http://atria-soft.github.io/ejson/classejson_1_1_object.html#a8cec54f55c2b5fb497e6bfc59ea4be13',1,'ejson::Object::add()']]],
|
||||
['addindent',['addIndent',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_value.html#a6119b75406b5648629b8eaa20948d224',1,'ejson::internal::Value']]],
|
||||
['aliceblue',['aliceBlue',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#adcf86ef9c7918dcb094a0783761899f1',1,'etk::color']]],
|
||||
['all',['all',['http://atria-soft.github.io/ememory/classememory_1_1_counter.html#a1614d672880eb19b18a98ea9babe723eaa181a603769c1f98ad927e7367c7aa51',1,'ememory::Counter']]],
|
||||
['angle',['angle',['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a3b403b529d49082265f3655aff656a7e',1,'etk::Vector3D']]],
|
||||
['antiquewhite',['antiqueWhite',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a88abb6eca9c1ba0f346fb697683fa836',1,'etk::color']]],
|
||||
['applyscalerotation',['applyScaleRotation',['http://atria-soft.github.io/etk/classetk_1_1_matrix2.html#aaafd3d4f83d6fd021b76a54f6a31b010',1,'etk::Matrix2']]],
|
||||
['aqua',['aqua',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a2cef110e71ce12876fcfd6605e57f716',1,'etk::color']]],
|
||||
['aquamarine',['aquamarine',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a8b69f67ed3e2db9915acde652a1cff80',1,'etk::color']]],
|
||||
['archive',['Archive',['http://atria-soft.github.io/etk/classetk_1_1_archive.html',1,'etk']]],
|
||||
['archive',['Archive',['http://atria-soft.github.io/etk/classetk_1_1_archive.html#a5991c05535749c9ed04eeec185f675ac',1,'etk::Archive']]],
|
||||
['archive_2ehpp',['Archive.hpp',['http://atria-soft.github.io/etk/__archive__8hpp.html',1,'']]],
|
||||
['archivecontent',['ArchiveContent',['http://atria-soft.github.io/etk/classetk_1_1_archive_content.html#aac29f8265fa496ca9576f21e13a704d4',1,'etk::ArchiveContent']]],
|
||||
['archivecontent',['ArchiveContent',['http://atria-soft.github.io/etk/classetk_1_1_archive_content.html',1,'etk']]],
|
||||
['array',['Array',['http://atria-soft.github.io/ejson/classejson_1_1_array.html',1,'ejson']]],
|
||||
['array',['Array',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_array.html',1,'ejson::internal']]],
|
||||
['array',['Array',['http://atria-soft.github.io/ejson/classejson_1_1_array.html#a918d2bded14bafde7809d9485659d58f',1,'ejson::Array::Array(ememory::SharedPtr< ejson::internal::Value > _internalValue)'],['http://atria-soft.github.io/ejson/classejson_1_1_array.html#a36e158041e827b534ce245b18ddf5cc7',1,'ejson::Array::Array(const ejson::Array &_obj)'],['http://atria-soft.github.io/ejson/classejson_1_1_array.html#a8ad8561622a2f641fb45b9650061ce68',1,'ejson::Array::Array()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_array.html#aac1462e570bd26f53b95621b6626e4cf',1,'ejson::internal::Array::Array()'],['http://atria-soft.github.io/ejson/namespaceejson.html#a6a37b3ae20a2b7bc207b268ab1439709af1f713c9e000f5d3f280adbd124df4f5',1,'ejson::array()']]],
|
||||
['array_2ehpp',['Array.hpp',['http://atria-soft.github.io/ejson/__array__8hpp.html',1,'(Global Namespace)'],['http://atria-soft.github.io/ejson/internal__2__array__8hpp.html',1,'(Global Namespace)']]],
|
||||
['audio',['audio',['http://musicdsp.github.io/audio/namespaceaudio.html',1,'']]],
|
||||
['avg',['avg',['http://atria-soft.github.io/etk/namespaceetk.html#a4397d293209affffd0c2f6832ebe2aea',1,'etk']]],
|
||||
['azure',['azure',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a51cb04e4a5b927ec82ceef2676b781f7',1,'etk::color']]],
|
||||
['audio_2driver_20library',['AUDIO-RIVER library',['../index.html',1,'']]]
|
||||
];
|
26
search/all_1.html
Normal file
26
search/all_1.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_1.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
26
search/all_1.js
Normal file
26
search/all_1.js
Normal file
@ -0,0 +1,26 @@
|
||||
var searchData=
|
||||
[
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['http://musicdsp.github.io/audio-drain/audio_algo_build.html',1,'']]],
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['http://musicdsp.github.io/audio/audio_build.html',1,'']]],
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['http://musicdsp.github.io/audio-orchestra/audio_orchestra_build.html',1,'']]],
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['../audio_river_build.html',1,'']]],
|
||||
['b',['b',['http://atria-soft.github.io/etk/classetk_1_1_color.html#ac6be77ac33983d040a2ede58bc631d94',1,'etk::Color']]],
|
||||
['basenoise',['BaseNoise',['http://atria-soft.github.io/etk/classetk_1_1_base_noise.html',1,'etk']]],
|
||||
['basenoise',['BaseNoise',['http://atria-soft.github.io/etk/classetk_1_1_base_noise.html#ad5cbfcc2d967af185c264744de04cf15',1,'etk::BaseNoise']]],
|
||||
['begin',['begin',['http://atria-soft.github.io/ejson/classejson_1_1_array.html#a9b61949e81e838c6e1123ff26614d20d',1,'ejson::Array::begin()'],['http://atria-soft.github.io/ejson/classejson_1_1_array.html#a36fa8883af25afed6025178f95815927',1,'ejson::Array::begin() const'],['http://atria-soft.github.io/ejson/classejson_1_1_object.html#a06584f41d23a3abc88a474da1e037437',1,'ejson::Object::begin()'],['http://atria-soft.github.io/ejson/classejson_1_1_object.html#a53091d4f1ba52eb463bc51af48597821',1,'ejson::Object::begin() const']]],
|
||||
['beige',['beige',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a68244b2fa52245487cec1154155d0e03',1,'etk::color']]],
|
||||
['bisque',['bisque',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#ad03e04b97263a2c64dedfc405ff983ee',1,'etk::color']]],
|
||||
['black',['black',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a4198b330ccb2e9008665733eee338f73',1,'etk::color']]],
|
||||
['blanchedalmond',['blanchedAlmond',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a12e8ba075411585a68aece7d0fead4cc',1,'etk::color']]],
|
||||
['blue',['blue',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a50f114c6849684e9984ae1322493572c',1,'etk::color']]],
|
||||
['blueviolet',['blueViolet',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#ac91bcec9a0a115d1070397f86cfdee4d',1,'etk::color']]],
|
||||
['boolean',['Boolean',['http://atria-soft.github.io/ejson/classejson_1_1_boolean.html#a58e8f164a9e58444b362e3e174d54e56',1,'ejson::Boolean::Boolean(ememory::SharedPtr< ejson::internal::Value > _internalValue)'],['http://atria-soft.github.io/ejson/classejson_1_1_boolean.html#a7672591c1c29e25a18b41cfb5d7dd33b',1,'ejson::Boolean::Boolean(const ejson::Boolean &_obj)'],['http://atria-soft.github.io/ejson/classejson_1_1_boolean.html#aa7bd97c43d0d0ceea89a041162203654',1,'ejson::Boolean::Boolean(bool _value=false)'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_boolean.html#a2fe50827d84a523f9c3a107394389c11',1,'ejson::internal::Boolean::Boolean()'],['http://atria-soft.github.io/ejson/namespaceejson.html#a6a37b3ae20a2b7bc207b268ab1439709a84e2c64f38f78ba3ea5c905ab5a2da27',1,'ejson::boolean()']]],
|
||||
['boolean',['Boolean',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_boolean.html',1,'ejson::internal']]],
|
||||
['boolean',['Boolean',['http://atria-soft.github.io/ejson/classejson_1_1_boolean.html',1,'ejson']]],
|
||||
['boolean_2ehpp',['Boolean.hpp',['http://atria-soft.github.io/ejson/__boolean__8hpp.html',1,'(Global Namespace)'],['http://atria-soft.github.io/ejson/internal__2__boolean__8hpp.html',1,'(Global Namespace)']]],
|
||||
['brown',['brown',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#af3dff0347662115abb89c6ddb8447227',1,'etk::color']]],
|
||||
['burlywood',['burlyWood',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a1920dd335710c842ea4706e2383ef784',1,'etk::color']]],
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['http://atria-soft.github.io/ejson/ejson_build.html',1,'']]],
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['http://atria-soft.github.io/elog/elog_build.html',1,'']]],
|
||||
['build_20lib_20_26_20build_20sample',['Build lib & build sample',['http://atria-soft.github.io/etk/etk_build.html',1,'']]]
|
||||
];
|
26
search/all_10.html
Normal file
26
search/all_10.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_10.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
86
search/all_10.js
Normal file
86
search/all_10.js
Normal file
@ -0,0 +1,86 @@
|
||||
var searchData=
|
||||
[
|
||||
['saddlebrown',['saddleBrown',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a5407ca00d7f7bf3815a72616e0be95ae',1,'etk::color']]],
|
||||
['safenormalize',['safeNormalize',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a245ccd3b57812316fc1ec98ea5c19434',1,'etk::Vector2D::safeNormalize()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a245ccd3b57812316fc1ec98ea5c19434',1,'Vector2D< int32_t >::safeNormalize()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a245ccd3b57812316fc1ec98ea5c19434',1,'Vector2D< uint32_t >::safeNormalize()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#abee6d22d509043f24a5aedb208ba1019',1,'etk::Vector3D::safeNormalize()']]],
|
||||
['salmon',['salmon',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#ad324737686a8c6ec9208a93e727710d8',1,'etk::color']]],
|
||||
['sandybrown',['sandyBrown',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#affd1d87686e7d4fb1a720d4cb5c354cb',1,'etk::color']]],
|
||||
['scale',['scale',['http://atria-soft.github.io/etk/classetk_1_1_matrix2.html#aacc34d6c0be39b22fed735cd09ffed84',1,'etk::Matrix2::scale(const vec2 &_vect)'],['http://atria-soft.github.io/etk/classetk_1_1_matrix2.html#adaa317393ef799d0ab49c3b10cf47231',1,'etk::Matrix2::scale(float _value)'],['http://atria-soft.github.io/etk/classetk_1_1_matrix4.html#aa3121f90430c2e2d80bc967d4b94c114',1,'etk::Matrix4::scale(const vec3 &_vect)'],['http://atria-soft.github.io/etk/classetk_1_1_matrix4.html#a41eb56d343978f32caa64dfda50cd6a5',1,'etk::Matrix4::scale(float _sx, float _sy, float _sz)']]],
|
||||
['seagreen',['seaGreen',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a3d3d8140130f2383e7740b4cea443470',1,'etk::color']]],
|
||||
['seashell',['seaShell',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a6b50105504f9be5dcf7ae59cbb115051',1,'etk::color']]],
|
||||
['seeknode',['seekNode',['http://atria-soft.github.io/etk/namespaceetk.html#a4a0133c254ab2433999c1b61fd9d993e',1,'etk']]],
|
||||
['seeknode_5fcurrent',['seekNode_current',['http://atria-soft.github.io/etk/namespaceetk.html#a4a0133c254ab2433999c1b61fd9d993ea8da2a40c899dc80a97a96999766d1598',1,'etk']]],
|
||||
['seeknode_5fend',['seekNode_end',['http://atria-soft.github.io/etk/namespaceetk.html#a4a0133c254ab2433999c1b61fd9d993ea981349cc2910e974472575409d19f0b6',1,'etk']]],
|
||||
['seeknode_5fstart',['seekNode_start',['http://atria-soft.github.io/etk/namespaceetk.html#a4a0133c254ab2433999c1b61fd9d993ea9019d83f9a109a54ab84067c2aa8abcd',1,'etk']]],
|
||||
['select',['select',['http://atria-soft.github.io/etk/classetk_1_1_matrix.html#a1c8f1bb6f8d14c0fb9d4d39dac67b07b',1,'etk::Matrix']]],
|
||||
['set',['set',['http://atria-soft.github.io/etk/classetk_1_1_color.html#a0955ac7d80e3886afa872d47e0cc1415',1,'etk::Color::set(MY_TYPE _r, MY_TYPE _g, MY_TYPE _b, MY_TYPE _a)'],['http://atria-soft.github.io/etk/classetk_1_1_color.html#a0f663138f780f134ae07957f5a9fef57',1,'etk::Color::set(MY_TYPE _r, MY_TYPE _g, MY_TYPE _b)'],['http://atria-soft.github.io/etk/classetk_1_1_color.html#a7de7eef4b78f10829066af98be02f27b',1,'etk::Color::set(MY_TYPE _r, MY_TYPE _g)'],['http://atria-soft.github.io/etk/classetk_1_1_color.html#a5063a9ee59f18fbeb7172f833617d8eb',1,'etk::Color::set(MY_TYPE _r)'],['http://atria-soft.github.io/etk/classetk_1_1_hash.html#af372b733bfbccd0d67f4df1fbfb62ad7',1,'etk::Hash::set()'],['http://atria-soft.github.io/ejson/classejson_1_1_boolean.html#aab7e29c6cf8553d1b396a8b5251df37d',1,'ejson::Boolean::set()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_boolean.html#af666327146a16819bc97b8bd2ef59ac6',1,'ejson::internal::Boolean::set()'],['http://atria-soft.github.io/ejson/classejson_1_1_file_pos.html#aed1081e2d1f561d566a8cc77b3a90777',1,'ejson::FilePos::set()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_number.html#ad8f10de8af236c264bf4989709d347c6',1,'ejson::internal::Number::set(double _value)'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_number.html#a8003c9060afbadb9d7e0e1c7d18a2387',1,'ejson::internal::Number::set(int64_t _value)'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_number.html#acabc53b7d1370b35e39a610847fa5b1c',1,'ejson::internal::Number::set(uint64_t _value)'],['http://atria-soft.github.io/ejson/classejson_1_1_number.html#a428ee4a3b855eb654f39e51426795a98',1,'ejson::Number::set(double _value)'],['http://atria-soft.github.io/ejson/classejson_1_1_number.html#a3562766c4a35aaf4f4dfc8bc8ae1335c',1,'ejson::Number::set(uint64_t _value)'],['http://atria-soft.github.io/ejson/classejson_1_1_number.html#a9efe3f43c2dabb2a950a4d817990ac16',1,'ejson::Number::set(int64_t _value)'],['http://atria-soft.github.io/ejson/classejson_1_1_string.html#a7ddb0ed5b9ce5591eddd698551cf1ddb',1,'ejson::String::set()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_string.html#a5ed7163d078e1b44d101451f5b40fb75',1,'ejson::internal::String::set()']]],
|
||||
['seta',['setA',['http://atria-soft.github.io/etk/classetk_1_1_color.html#a1d24c054b6d64d2a73c6cef57d91c31a',1,'etk::Color']]],
|
||||
['setargzero',['setArgZero',['http://atria-soft.github.io/etk/namespaceetk.html#a5eda91763c9f02f0e7e16c099092695d',1,'etk']]],
|
||||
['setb',['setB',['http://atria-soft.github.io/etk/classetk_1_1_color.html#ae8078ca64701dbc1b5080589037743f1',1,'etk::Color']]],
|
||||
['setbacktrace',['setBackTrace',['http://atria-soft.github.io/elog/namespaceelog.html#aae6ff218b5e851513cfc29d030b865fb',1,'elog']]],
|
||||
['setbasefoldercache',['setBaseFolderCache',['http://atria-soft.github.io/etk/namespaceetk.html#a6cdcbe0aeba288278c89a995481b9e6f',1,'etk']]],
|
||||
['setbasefolderdata',['setBaseFolderData',['http://atria-soft.github.io/etk/namespaceetk.html#ab8546560f91d95e2df5f176f5ec0fc99',1,'etk']]],
|
||||
['setbasefolderdatauser',['setBaseFolderDataUser',['http://atria-soft.github.io/etk/namespaceetk.html#a91fb8f53bc0d3ad4ed2061b3f5af7734',1,'etk']]],
|
||||
['setcallbacklog',['setCallbackLog',['http://atria-soft.github.io/elog/namespaceelog.html#a8c02ad11df203c22c7e65c759b43efdd',1,'elog']]],
|
||||
['setcolor',['setColor',['http://atria-soft.github.io/elog/namespaceelog.html#a157a0ce2993c115906b8a2607f6a9133',1,'elog']]],
|
||||
['setdisplayerror',['setDisplayError',['http://atria-soft.github.io/ejson/classejson_1_1_document.html#a75cc1ee77adccb81e611a4ed09eaa6a8',1,'ejson::Document::setDisplayError()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_document.html#a265d3edbd88a85e8d6650d785e599eb2',1,'ejson::internal::Document::setDisplayError()']]],
|
||||
['setfrompoints',['setFromPoints',['http://atria-soft.github.io/etk/classetk_1_1_plane.html#a69b4871efd25fa204a3917360bfb8cc9',1,'etk::Plane']]],
|
||||
['setfunction',['setFunction',['http://atria-soft.github.io/elog/namespaceelog.html#aed76a2bba4f8c0f51633fa64ab08362d',1,'elog']]],
|
||||
['setg',['setG',['http://atria-soft.github.io/etk/classetk_1_1_color.html#a724b243ffc1ba471eab6b04f6ca6ecd4',1,'etk::Color']]],
|
||||
['setgroupreadable',['setGroupReadable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#acca31813653f621d4859d5c837f057a5',1,'etk::FSNodeRight']]],
|
||||
['setgrouprunable',['setGroupRunable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#a5184205ed51108dd9bf3ed4ad141588e',1,'etk::FSNodeRight']]],
|
||||
['setgroupwritable',['setGroupWritable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#acc834eeef2e84b9e7cceac38b3a59389',1,'etk::FSNodeRight']]],
|
||||
['setintercept',['setIntercept',['http://atria-soft.github.io/etk/classetk_1_1_plane.html#a691582e68a6ee38b0c7c9ccf2a6734f3',1,'etk::Plane']]],
|
||||
['setinterpolate3',['setInterpolate3',['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a3e59820b3cc3f9138e69d8aee9a448c8',1,'etk::Vector3D']]],
|
||||
['setlevel',['setLevel',['http://atria-soft.github.io/elog/namespaceelog.html#a3afe4089acb36e88d7266c1ce85ddc7b',1,'elog::setLevel(const std::string &_name, enum elog::level _level)'],['http://atria-soft.github.io/elog/namespaceelog.html#a423b95c78b78e98de35c8f176b9efbdc',1,'elog::setLevel(int32_t _id, enum elog::level _level)'],['http://atria-soft.github.io/elog/namespaceelog.html#a600189d0be9885f63d651201ab0c3688',1,'elog::setLevel(enum elog::level _level)']]],
|
||||
['setlibname',['setLibName',['http://atria-soft.github.io/elog/namespaceelog.html#a98f690a8538d4726fa0060331e021a08',1,'elog']]],
|
||||
['setline',['setLine',['http://atria-soft.github.io/elog/namespaceelog.html#a2591d4ba7e3136ff84c0b81289000b79',1,'elog']]],
|
||||
['setloginfile',['setLogInFile',['http://atria-soft.github.io/elog/namespaceelog.html#a78083b9d6ef033e329b788f8fa22f3f3',1,'elog']]],
|
||||
['setmax',['setMax',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a72ae52d19423c46bad955ad1a9f59041',1,'etk::Vector2D::setMax()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a72ae52d19423c46bad955ad1a9f59041',1,'Vector2D< int32_t >::setMax()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a72ae52d19423c46bad955ad1a9f59041',1,'Vector2D< uint32_t >::setMax()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a7b9a94f71854f5ad89ef23ef22dcb321',1,'etk::Vector3D::setMax()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a2469c42527ead691f479a9a573709e5f',1,'etk::Vector4D::setMax()']]],
|
||||
['setmin',['setMin',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#aa087eeec653b538d166c0d2794737fb1',1,'etk::Vector2D::setMin()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#aa087eeec653b538d166c0d2794737fb1',1,'Vector2D< int32_t >::setMin()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#aa087eeec653b538d166c0d2794737fb1',1,'Vector2D< uint32_t >::setMin()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a7c2e3d0042a62791b1c653d5081577c2',1,'etk::Vector3D::setMin()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#aa647808a65613af0e1e757f27444f0a6',1,'etk::Vector4D::setMin()']]],
|
||||
['setname',['setName',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a6e787e7f3148dae0c74139be7b05ab43',1,'etk::FSNode']]],
|
||||
['setnormal',['setNormal',['http://atria-soft.github.io/etk/classetk_1_1_plane.html#a202b3335b2b71cc84726a1b57b8e1e70',1,'etk::Plane']]],
|
||||
['setotherreadable',['setOtherReadable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#a6ad46a56d871f5925a826a6fd3071b78',1,'etk::FSNodeRight']]],
|
||||
['setotherrunable',['setOtherRunable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#a290708c849f5b58714dad5a1926cfe1c',1,'etk::FSNodeRight']]],
|
||||
['setotherwritable',['setOtherWritable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#a931050b25db28423f1a2899f8ec188a0',1,'etk::FSNodeRight']]],
|
||||
['setr',['setR',['http://atria-soft.github.io/etk/classetk_1_1_color.html#a96c8b12779776562c2fa0dfdc4d1b242',1,'etk::Color']]],
|
||||
['setright',['setRight',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a65bce1c8887edad87a90c8c7ffb861d3',1,'etk::FSNode']]],
|
||||
['setthreadid',['setThreadId',['http://atria-soft.github.io/elog/namespaceelog.html#a9b835d4980949026a8883570ea3837af',1,'elog']]],
|
||||
['setthreadnameenable',['setThreadNameEnable',['http://atria-soft.github.io/elog/namespaceelog.html#ae64b5abf2ea03562679668e6242c49a2',1,'elog']]],
|
||||
['settime',['setTime',['http://atria-soft.github.io/elog/namespaceelog.html#a15e30e61e8db5a43e72358d2c02be6a4',1,'elog']]],
|
||||
['setuserreadable',['setUserReadable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#acadd7b9c2c632f9805569ff4f592bda9',1,'etk::FSNodeRight']]],
|
||||
['setuserrunable',['setUserRunable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#a0ee76ec4897c406ab67ea25659953070',1,'etk::FSNodeRight']]],
|
||||
['setuserwritable',['setUserWritable',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node_right.html#a9e5e2e4c7926c22101e6955b3d8c9139',1,'etk::FSNodeRight']]],
|
||||
['setvalue',['setValue',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ade86675814738c6b7a6a797ee128a2b2',1,'etk::Vector2D::setValue()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ade86675814738c6b7a6a797ee128a2b2',1,'Vector2D< int32_t >::setValue()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ade86675814738c6b7a6a797ee128a2b2',1,'Vector2D< uint32_t >::setValue()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a96d02449aaa2dfeb4e60320da667ab92',1,'etk::Vector3D::setValue()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a9b164290093d948905fab0f56fbe22fc',1,'etk::Vector4D::setValue()']]],
|
||||
['setw',['setW',['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a1750c9d1b91d67b8b2bc9d0cce759944',1,'etk::Vector4D']]],
|
||||
['setx',['setX',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ae2acd7c10cdd510ce23ff11839c95c04',1,'etk::Vector2D::setX()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ae2acd7c10cdd510ce23ff11839c95c04',1,'Vector2D< int32_t >::setX()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ae2acd7c10cdd510ce23ff11839c95c04',1,'Vector2D< uint32_t >::setX()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#ab7ab9d9ce1138ffafebaff3001bb7d29',1,'etk::Vector3D::setX()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a238d966b077394ff118f2088479fb620',1,'etk::Vector4D::setX()']]],
|
||||
['sety',['setY',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a35a3f35ed049b7193ca67ea815efd465',1,'etk::Vector2D::setY()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a35a3f35ed049b7193ca67ea815efd465',1,'Vector2D< int32_t >::setY()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a35a3f35ed049b7193ca67ea815efd465',1,'Vector2D< uint32_t >::setY()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a10c41fb516fb33ef56201f06992462d1',1,'etk::Vector3D::setY()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a7489a0c8d592c9464a8e378bbb7e570e',1,'etk::Vector4D::setY()']]],
|
||||
['setz',['setZ',['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a9a5c1d69fd9066daae0a759831ba0e30',1,'etk::Vector3D::setZ()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#ae5bbc387ea4199ea535d4d033cfc40d1',1,'etk::Vector4D::setZ()']]],
|
||||
['setzero',['setZero',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ab2e921e0009f0e0de78d06d16f6a78e0',1,'etk::Vector2D::setZero()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ab2e921e0009f0e0de78d06d16f6a78e0',1,'Vector2D< int32_t >::setZero()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ab2e921e0009f0e0de78d06d16f6a78e0',1,'Vector2D< uint32_t >::setZero()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a7ddb707a7a1609bcbd8c092186a6db19',1,'etk::Vector3D::setZero()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a978b0511ade11701ffdbd7974de6932e',1,'etk::Vector4D::setZero()']]],
|
||||
['sharedfromthis',['sharedFromThis',['http://atria-soft.github.io/ememory/classememory_1_1_enable_shared_from_this.html#ab9c576f893c44cbf8163b1ddf6f86b38',1,'ememory::EnableSharedFromThis::sharedFromThis()'],['http://atria-soft.github.io/ememory/classememory_1_1_enable_shared_from_this.html#ad16c98c2383b23adffa8db309bc1ca11',1,'ememory::EnableSharedFromThis::sharedFromThis() const']]],
|
||||
['sharedptr',['SharedPtr',['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#a7b017780895f0a9d32e753574ae82010',1,'ememory::SharedPtr::SharedPtr(EMEMORY_TYPE2 *_element)'],['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#aef65a1bba18c17a8a13e05aa5d702b1e',1,'ememory::SharedPtr::SharedPtr(std::nullptr_t)'],['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#a6b448ecd7740c97551e8afd65acaca6f',1,'ememory::SharedPtr::SharedPtr()'],['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#ab5052506642bddd3aa5e6fb44ec1a173',1,'ememory::SharedPtr::SharedPtr(EMEMORY_TYPE *_obj, ememory::Counter *_counter)'],['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#ab91fe50ba210a0545fa41e993df9beea',1,'ememory::SharedPtr::SharedPtr(const SharedPtr< EMEMORY_TYPE > &_obj)'],['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#ab46f51a66327265bbc94ee89b603ca71',1,'ememory::SharedPtr::SharedPtr(SharedPtr< EMEMORY_TYPE > &&_obj)']]],
|
||||
['sharedptr',['SharedPtr',['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html',1,'ememory']]],
|
||||
['sharedptr_2ehpp',['SharedPtr.hpp',['http://atria-soft.github.io/ememory/__shared__ptr__8hpp.html',1,'']]],
|
||||
['sharedptr_3c_20ejson_3a_3ainternal_3a_3aejson_3a_3avalue_20_3e',['SharedPtr< ejson::internal::ejson::Value >',['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html',1,'ememory']]],
|
||||
['sienna',['sienna',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a0a8eaf790795f7b5fc63c81ade8652ce',1,'etk::color']]],
|
||||
['silver',['silver',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#aca25e934d9d1ac1538a4a0c7011c6d0c',1,'etk::color']]],
|
||||
['simplifypath',['simplifyPath',['http://atria-soft.github.io/etk/namespaceetk.html#a0087446ff0e9b533ea70b3043ae2addc',1,'etk']]],
|
||||
['size',['size',['http://atria-soft.github.io/etk/classetk_1_1_archive.html#a17d06497d98be15f6080cf84010d35a0',1,'etk::Archive::size()'],['http://atria-soft.github.io/etk/classetk_1_1_archive_content.html#a36dc83c35ebdacdce11e04dbcba4334c',1,'etk::ArchiveContent::size()'],['http://atria-soft.github.io/etk/classetk_1_1_hash.html#a4d639eb19c25b1ff76d34c225a132deb',1,'etk::Hash::size()'],['http://atria-soft.github.io/ejson/classejson_1_1_array.html#a94267e806e4df82be54a73a7ef591c03',1,'ejson::Array::size()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_array.html#a56b469d5860feb6d2d73c51b87188051',1,'ejson::internal::Array::size()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_object.html#a11f6d2ca0e58ebccdbdac6120ea377ab',1,'ejson::internal::Object::size()'],['http://atria-soft.github.io/ejson/classejson_1_1_object.html#a5e33daf982a3bae085b3d8e9d0d48089',1,'ejson::Object::size()']]],
|
||||
['skyblue',['skyBlue',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a1576fd8ed2c3fe5ed5a10f8147d0ed1d',1,'etk::color']]],
|
||||
['slateblue',['slateBlue',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a4f605302a82a6173de726e797c3edf0d',1,'etk::color']]],
|
||||
['slategray',['slateGray',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a5d3c48d14e696bc1b8d9d43158dfa0b2',1,'etk::color']]],
|
||||
['slategrey',['slateGrey',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a9cefc035f467790176ba159bb6255c6e',1,'etk::color']]],
|
||||
['snow',['snow',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#ae312c38fc6be5178a4ff63921f162723',1,'etk::color']]],
|
||||
['space',['Space',['http://atria-soft.github.io/etk/namespaceu32char.html#a7a114cf0424bb72fd7f3f10c9cd017e8',1,'u32char']]],
|
||||
['springgreen',['springGreen',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#ab3b6e2028b00791f15ddff7f9a1fe703',1,'etk::color']]],
|
||||
['staticpointercast',['staticPointerCast',['http://atria-soft.github.io/ememory/namespaceememory.html#a9a5a8c52dbbb1cb7121231de10dec3b2',1,'ememory::staticPointerCast(ememory::SharedPtr< EMEMORY_TYPE > &_obj)'],['http://atria-soft.github.io/ememory/namespaceememory.html#ad67a9361b7aa47b38ef5366f9ec2c712',1,'ememory::staticPointerCast(const ememory::SharedPtr< EMEMORY_TYPE > &_obj)']]],
|
||||
['stdtools_2ehpp',['stdTools.hpp',['http://atria-soft.github.io/etk/std__tools__8hpp.html',1,'']]],
|
||||
['steelblue',['steelBlue',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a9162b466a59a0bbe420b49c565e9dd6f',1,'etk::color']]],
|
||||
['store',['store',['http://atria-soft.github.io/ejson/classejson_1_1_document.html#a2a058bdb1bbd4e151e08e719bbbe2560',1,'ejson::Document::store()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_document.html#a35d7de9cf4987da51028e3bf7f9edde6',1,'ejson::internal::Document::store()']]],
|
||||
['storesafe',['storeSafe',['http://atria-soft.github.io/ejson/classejson_1_1_document.html#a3fb19ca6aefe86a86c43bf6bb8d133c9',1,'ejson::Document']]],
|
||||
['string',['String',['http://atria-soft.github.io/ejson/classejson_1_1_string.html#a2343d871cc75be25eee5381ba34dfd37',1,'ejson::String::String(ememory::SharedPtr< ejson::internal::Value > _internalValue)'],['http://atria-soft.github.io/ejson/classejson_1_1_string.html#ac5074aad1b24c1045b27e30aaefe6ebe',1,'ejson::String::String(const ejson::String &_obj)'],['http://atria-soft.github.io/ejson/classejson_1_1_string.html#afdae63446f3a9fb02245636c352a91e4',1,'ejson::String::String(const std::string &_value="")'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_string.html#a1ce856e42efbcfe0e76294ae113c0e67',1,'ejson::internal::String::String()'],['http://atria-soft.github.io/ejson/namespaceejson.html#a6a37b3ae20a2b7bc207b268ab1439709ab45cffe084dd3d20d928bee85e7b0f21',1,'ejson::string()']]],
|
||||
['string',['String',['http://atria-soft.github.io/ejson/classejson_1_1_string.html',1,'ejson']]],
|
||||
['string',['String',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_string.html',1,'ejson::internal']]],
|
||||
['string_2ehpp',['String.hpp',['http://atria-soft.github.io/ejson/internal__2__string__8hpp.html',1,'(Global Namespace)'],['http://atria-soft.github.io/ejson/__string__8hpp.html',1,'(Global Namespace)']]],
|
||||
['suppress',['Suppress',['http://atria-soft.github.io/etk/namespaceu32char.html#a9cff086787b8b0321e36251a27c40321',1,'u32char']]],
|
||||
['swap',['swap',['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#ad7a06dd2042312f6f94da526adddfc48',1,'ememory::SharedPtr::swap()'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#ab138aa24ae18beedf25cbbe9d99ba0b4',1,'ememory::WeakPtr::swap()']]]
|
||||
];
|
26
search/all_11.html
Normal file
26
search/all_11.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_11.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
44
search/all_11.js
Normal file
44
search/all_11.js
Normal file
@ -0,0 +1,44 @@
|
||||
var searchData=
|
||||
[
|
||||
['tutorials',['Tutorials',['http://atria-soft.github.io/elog/elog_tutorial.html',1,'']]],
|
||||
['tabulation',['Tabulation',['http://atria-soft.github.io/etk/namespaceu32char.html#ad7a0c42ea443e20bfceb69f863bebc6a',1,'u32char']]],
|
||||
['tan',['tan',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a923b2869775837088eabdb48681f4b1e',1,'etk::color']]],
|
||||
['teal',['teal',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a9b28dace6aa8c81c0c59a7343875d2b5',1,'etk::color']]],
|
||||
['theoricfirst',['theoricFirst',['http://atria-soft.github.io/etk/namespaceutf8.html#a52043c6c7cf75da5f8e8812ffb4ffc1c',1,'utf8']]],
|
||||
['theoriclen',['theoricLen',['http://atria-soft.github.io/etk/namespaceutf8.html#ad408da64c12fe3345b9576ab487bd7e3',1,'utf8']]],
|
||||
['thistle',['thistle',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a729d8532a3b7c147fcaa726ce2d887b8',1,'etk::color']]],
|
||||
['time_2ehpp',['Time.hpp',['http://musicdsp.github.io/audio/__time__8hpp.html',1,'']]],
|
||||
['timeaccessed',['timeAccessed',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a43c3b946ef91744dd2991734166c1d87',1,'etk::FSNode']]],
|
||||
['timeaccessedstring',['timeAccessedString',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a17022f6598927b1b9f169cbcd99099e6',1,'etk::FSNode']]],
|
||||
['timecreated',['timeCreated',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a46fe9a1916400ca932d31a847dff0f21',1,'etk::FSNode']]],
|
||||
['timecreatedstring',['timeCreatedString',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a30a497f2d095469b5846756a1b51a749',1,'etk::FSNode']]],
|
||||
['timemodified',['timeModified',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#afa84341a6764252f5fb70eb48540f496',1,'etk::FSNode']]],
|
||||
['timemodifiedstring',['timeModifiedString',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a3cdee551ca80df9597a408b42b4f7210',1,'etk::FSNode']]],
|
||||
['to_5fstring',['to_string',['http://atria-soft.github.io/etk/namespaceetk.html#a48ed31a00f989f5b188d7254e6945a74',1,'etk::to_string(const TYPE &_variable)'],['http://atria-soft.github.io/etk/namespaceetk.html#a17aa4febea213096442bcb8e7ca80805',1,'etk::to_string(const std::vector< TYPE > &_list)']]],
|
||||
['toarray',['toArray',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#abf67a6a98c2fb657cff4290cef39b658',1,'ejson::Value::toArray()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a7bd84110f49d0b4252d3b919e74e3831',1,'ejson::Value::toArray() const']]],
|
||||
['toboolean',['toBoolean',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#ab759dc22259f15b487a4437df60baf1a',1,'ejson::Value::toBoolean()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#ac7b37ebf5bcabf12feb589968770b3f4',1,'ejson::Value::toBoolean() const']]],
|
||||
['todocument',['toDocument',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a58ec04b1804d2502c0621c9a4108b6c3',1,'ejson::Value::toDocument()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a6b5eed0d3b14a3fc1a75357bda165e33',1,'ejson::Value::toDocument() const']]],
|
||||
['toint',['toInt',['http://atria-soft.github.io/etk/namespaceu32char.html#afc40d527459e3869ea8dc54d3b5ef225',1,'u32char']]],
|
||||
['tomato',['tomato',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a9f3fe621ef99b1b452a5a11af1a06ae0',1,'etk::color']]],
|
||||
['tonull',['toNull',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a157597cbc30f00eabc62d8724fccd61f',1,'ejson::Value::toNull()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#aa50ce25748b4164eac425a74aa3a9990',1,'ejson::Value::toNull() const']]],
|
||||
['tonumber',['toNumber',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a40e63375796266399a4297b8d2b96f2c',1,'ejson::Value::toNumber()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a49736f1d74a125b0e9fb3e9a18a793ad',1,'ejson::Value::toNumber() const']]],
|
||||
['toobject',['toObject',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a91236630d37cad7a8d1256835a9448c8',1,'ejson::Value::toObject()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#ae27978be6397ed84518ae23eaed23cd5',1,'ejson::Value::toObject() const']]],
|
||||
['tool_2ehpp',['tool.hpp',['http://atria-soft.github.io/etk/tool__8hpp.html',1,'']]],
|
||||
['tostring',['toString',['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a43a3bf8ff0d02f92e8751ea8a16fcaa1',1,'ejson::Value::toString()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a65587aee04eba5882f306b46e5b3c9ce',1,'ejson::Value::toString() const']]],
|
||||
['touch',['touch',['http://atria-soft.github.io/etk/classetk_1_1_f_s_node.html#a6fd01aeb7f84399ad99573e0a7e2f8fc',1,'etk::FSNode']]],
|
||||
['transfertin',['transfertIn',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_array.html#ad82736867e1bbf1ef9cda98ee22b2215',1,'ejson::internal::Array::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_boolean.html#af30b2342a4c91705dceb2434f2f06d47',1,'ejson::internal::Boolean::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_null.html#a3e57cb8cf21c84258ed5024a8d40fc23',1,'ejson::internal::Null::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_number.html#ab753d1a2d0919737a566b7e3fc06b080',1,'ejson::internal::Number::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_object.html#aee25bea3065759780a3f63d2f5c0458e',1,'ejson::internal::Object::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_string.html#a3ee2d34d468baec8d347add7d590e7db',1,'ejson::internal::String::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_value.html#ad0d5a680f032ce3d97f87468fdd448df',1,'ejson::internal::Value::transfertIn()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a03ca08ba192ba578df15b6f90cb96970',1,'ejson::Value::transfertIn()']]],
|
||||
['translate',['translate',['http://atria-soft.github.io/etk/classetk_1_1_matrix2.html#abd22ba1cbe8dc53c0446abcb55d8551a',1,'etk::Matrix2::translate()'],['http://atria-soft.github.io/etk/classetk_1_1_matrix4.html#aa6cd07f3a802c5a57bddbf5a6db95c4d',1,'etk::Matrix4::translate()']]],
|
||||
['transpose',['transpose',['http://atria-soft.github.io/etk/classetk_1_1_matrix.html#ab05c8b14ec68367d0391c23b77870a3b',1,'etk::Matrix::transpose()'],['http://atria-soft.github.io/etk/classetk_1_1_matrix4.html#a8214b2300ebdc4b42bde1efe93e84fae',1,'etk::Matrix4::transpose()']]],
|
||||
['triple',['triple',['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#af1e591712d4a15bd21ad6fd22d72df97',1,'etk::Vector3D']]],
|
||||
['turquoise',['turquoise',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a8162f21fcdb858a4c5017a20db4c5830',1,'etk::color']]],
|
||||
['typenode',['typeNode',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8',1,'etk']]],
|
||||
['typenode_5fblock',['typeNode_block',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a18f1c41a5c9bc4842a512954af23d630',1,'etk']]],
|
||||
['typenode_5fcharacter',['typeNode_character',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a07f61c5191a0e393871ecf69f4f32eed',1,'etk']]],
|
||||
['typenode_5ffifo',['typeNode_fifo',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8af5a5a8cef27d1c2abf4c6b7b9a893890',1,'etk']]],
|
||||
['typenode_5ffile',['typeNode_file',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a4bb596537f408d12f89da085cac752c6',1,'etk']]],
|
||||
['typenode_5ffolder',['typeNode_folder',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a67fbbfd55ff1568df12ca9719bc73680',1,'etk']]],
|
||||
['typenode_5flink',['typeNode_link',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a73f8fdd1c9f08183be017f372935cf14',1,'etk']]],
|
||||
['typenode_5fsocket',['typeNode_socket',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a9b46f1f9d230b9490b2c17af379c61bc',1,'etk']]],
|
||||
['typenode_5funknow',['typeNode_unknow',['http://atria-soft.github.io/etk/namespaceetk.html#a99c2dd948d6da85ed816fa0c267862e8a4c85a6b7dccfd424a20b383e5dbe63bf',1,'etk']]],
|
||||
['types_2ehpp',['types.hpp',['http://atria-soft.github.io/etk/types__8hpp.html',1,'(Global Namespace)'],['http://musicdsp.github.io/audio/types__8hpp.html',1,'(Global Namespace)']]]
|
||||
];
|
26
search/all_12.html
Normal file
26
search/all_12.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_12.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
8
search/all_12.js
Normal file
8
search/all_12.js
Normal file
@ -0,0 +1,8 @@
|
||||
var searchData=
|
||||
[
|
||||
['u32char',['u32char',['http://atria-soft.github.io/etk/namespaceu32char.html',1,'']]],
|
||||
['unknow',['unknow',['http://atria-soft.github.io/ejson/namespaceejson.html#a6a37b3ae20a2b7bc207b268ab1439709a5c940de9c166a32dc1f63d9dafc6822f',1,'ejson']]],
|
||||
['unsetloginfile',['unsetLogInFile',['http://atria-soft.github.io/elog/namespaceelog.html#a496120feb0c59449a46057559c6c8a1a',1,'elog']]],
|
||||
['usecount',['useCount',['http://atria-soft.github.io/ememory/classememory_1_1_shared_ptr.html#a74070b8ebda543021108e0df4b1e825b',1,'ememory::SharedPtr::useCount()'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#a41fa587a2ee7a4bddd76688b94133af3',1,'ememory::WeakPtr::useCount()']]],
|
||||
['utf8',['utf8',['http://atria-soft.github.io/etk/namespaceutf8.html',1,'']]]
|
||||
];
|
26
search/all_13.html
Normal file
26
search/all_13.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_13.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
22
search/all_13.js
Normal file
22
search/all_13.js
Normal file
@ -0,0 +1,22 @@
|
||||
var searchData=
|
||||
[
|
||||
['value',['Value',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_value.html',1,'ejson::internal']]],
|
||||
['value',['Value',['http://atria-soft.github.io/ejson/classejson_1_1_value.html',1,'ejson']]],
|
||||
['value',['Value',['http://atria-soft.github.io/ejson/classejson_1_1internal_1_1_value.html#a57471d92a92936793f1844e36d3b115a',1,'ejson::internal::Value::Value()'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#a0510ab7719ab2388f447f7b0c2972ff7',1,'ejson::Value::Value(const ememory::SharedPtr< ejson::internal::Value > &_internalValue)'],['http://atria-soft.github.io/ejson/classejson_1_1_value.html#ad0eee5841f21b81556e93c28915ffbc1',1,'ejson::Value::Value()'],['http://atria-soft.github.io/ejson/namespaceejson.html#a6a37b3ae20a2b7bc207b268ab1439709a2063c1608d6e0baf80249c42e2be5804',1,'ejson::value()']]],
|
||||
['value_2ehpp',['Value.hpp',['http://atria-soft.github.io/ejson/internal__2__value__8hpp.html',1,'(Global Namespace)'],['http://atria-soft.github.io/ejson/__value__8hpp.html',1,'(Global Namespace)']]],
|
||||
['valueexist',['valueExist',['http://atria-soft.github.io/ejson/classejson_1_1_object.html#a5a8e982824bad7d0a0f28cfb9eff5a07',1,'ejson::Object']]],
|
||||
['valuetype',['valueType',['http://atria-soft.github.io/ejson/namespaceejson.html#a6a37b3ae20a2b7bc207b268ab1439709',1,'ejson']]],
|
||||
['valuetype_2ehpp',['valueType.hpp',['http://atria-soft.github.io/ejson/value__type__8hpp.html',1,'']]],
|
||||
['vector2d',['Vector2D',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html',1,'etk']]],
|
||||
['vector2d',['Vector2D',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a09b5e26eacb50a8059d0e0c65405eb82',1,'etk::Vector2D::Vector2D(T _xxx, T _yyy)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#aaece962e3caa1d70afe0b1682ce8212e',1,'etk::Vector2D::Vector2D(const Vector2D< double > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#acab36ec2f778107bc89f4e5c9463191b',1,'etk::Vector2D::Vector2D(const Vector2D< float > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ab07ef273334d86b96dd13a4ce4c19137',1,'etk::Vector2D::Vector2D(const Vector2D< int32_t > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a187bb96fc68cb5d5dadc99f573674b98',1,'etk::Vector2D::Vector2D(const std::string &_str)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a09b5e26eacb50a8059d0e0c65405eb82',1,'Vector2D< int32_t >::Vector2D(int32_t _xxx, int32_t _yyy)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#aaece962e3caa1d70afe0b1682ce8212e',1,'Vector2D< int32_t >::Vector2D(const Vector2D< double > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#acab36ec2f778107bc89f4e5c9463191b',1,'Vector2D< int32_t >::Vector2D(const Vector2D< float > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ab07ef273334d86b96dd13a4ce4c19137',1,'Vector2D< int32_t >::Vector2D(const Vector2D< int32_t > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a187bb96fc68cb5d5dadc99f573674b98',1,'Vector2D< int32_t >::Vector2D(const std::string &_str)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a09b5e26eacb50a8059d0e0c65405eb82',1,'Vector2D< uint32_t >::Vector2D(uint32_t _xxx, uint32_t _yyy)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#aaece962e3caa1d70afe0b1682ce8212e',1,'Vector2D< uint32_t >::Vector2D(const Vector2D< double > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#acab36ec2f778107bc89f4e5c9463191b',1,'Vector2D< uint32_t >::Vector2D(const Vector2D< float > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#ab07ef273334d86b96dd13a4ce4c19137',1,'Vector2D< uint32_t >::Vector2D(const Vector2D< int32_t > &_obj)'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a187bb96fc68cb5d5dadc99f573674b98',1,'Vector2D< uint32_t >::Vector2D(const std::string &_str)']]],
|
||||
['vector2d_2ehpp',['Vector2D.hpp',['http://atria-soft.github.io/etk/__vector2__d__8hpp.html',1,'']]],
|
||||
['vector2d_3c_20int32_5ft_20_3e',['Vector2D< int32_t >',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html',1,'']]],
|
||||
['vector2d_3c_20uint32_5ft_20_3e',['Vector2D< uint32_t >',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html',1,'']]],
|
||||
['vector3d',['Vector3D',['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a409169c1781cae5220b9f7bd078e05d9',1,'etk::Vector3D::Vector3D()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#a7f5d02301a551e7f686092d7b9a5b269',1,'etk::Vector3D::Vector3D(const T &_xxx, const T &_yyy, const T &_zzz)']]],
|
||||
['vector3d',['Vector3D',['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html',1,'etk']]],
|
||||
['vector3d_2ehpp',['Vector3D.hpp',['http://atria-soft.github.io/etk/__vector3__d__8hpp.html',1,'']]],
|
||||
['vector4d',['Vector4D',['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html',1,'etk']]],
|
||||
['vector4d',['Vector4D',['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a0e140dec4eca4f3695f19fb92dc3e1ae',1,'etk::Vector4D::Vector4D()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a7a41fd47b438cc43849a2b2c0f308db2',1,'etk::Vector4D::Vector4D(const T &_xxx, const T &_yyy, const T &_zzz, const T &_www)']]],
|
||||
['vector4d_2ehpp',['Vector4D.hpp',['http://atria-soft.github.io/etk/__vector4__d__8hpp.html',1,'']]],
|
||||
['violet',['violet',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#ac86b1f752bb46992b83000f1b48957ec',1,'etk::color']]]
|
||||
];
|
26
search/all_14.html
Normal file
26
search/all_14.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_14.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
14
search/all_14.js
Normal file
14
search/all_14.js
Normal file
@ -0,0 +1,14 @@
|
||||
var searchData=
|
||||
[
|
||||
['write_20stream_20to_20audio_20output',['Write stream to Audio output',['../audio_river_write.html',1,'']]],
|
||||
['write_20an_20json_20content',['Write an JSON content',['http://atria-soft.github.io/ejson/ejson_tutorial_write.html',1,'']]],
|
||||
['w',['w',['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a0ede53650faf9183b87a3592e8be142d',1,'etk::Vector4D']]],
|
||||
['wait',['wait',['http://atria-soft.github.io/etk/classetk_1_1_fifo.html#a0693f87b2886e553ccdafdac112ebbd5',1,'etk::Fifo::wait(MY_TYPE &_data)'],['http://atria-soft.github.io/etk/classetk_1_1_fifo.html#aa08e5c57d91bc54ea08f377a6e2653e3',1,'etk::Fifo::wait(MY_TYPE &_data, uint32_t _timeOutInUs)']]],
|
||||
['weakfromthis',['weakFromThis',['http://atria-soft.github.io/ememory/classememory_1_1_enable_shared_from_this.html#aa2ce5703d70b211bae31fd40a5514c19',1,'ememory::EnableSharedFromThis::weakFromThis()'],['http://atria-soft.github.io/ememory/classememory_1_1_enable_shared_from_this.html#a6be22e13e06d0f679ff03c6ee817386f',1,'ememory::EnableSharedFromThis::weakFromThis() const']]],
|
||||
['weakptr',['WeakPtr',['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html',1,'ememory']]],
|
||||
['weakptr',['WeakPtr',['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#a7ca8af1a20e2bce96d5c65ea1fd72ec1',1,'ememory::WeakPtr::WeakPtr()'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#a1fb089b0b5bd76e33bf54d32cd3bb369',1,'ememory::WeakPtr::WeakPtr(std::nullptr_t)'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#adb31ca52a0b8dfe8c876a9fd297eca83',1,'ememory::WeakPtr::WeakPtr(const WeakPtr< EMEMORY_TYPE > &_obj)'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#adbfcc73329e43b1e37fd8b19220d752e',1,'ememory::WeakPtr::WeakPtr(WeakPtr &&_obj)'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#a3a30b756ccdc34bf96a4c7e2e4fb87c4',1,'ememory::WeakPtr::WeakPtr(const SharedPtr< EMEMORY_TYPE > &_obj)'],['http://atria-soft.github.io/ememory/classememory_1_1_weak_ptr.html#a9233c621eaf744a4b6d3f53afb77f33f',1,'ememory::WeakPtr::WeakPtr(const SharedPtr< EMEMORY_TYPE2 > &_obj)']]],
|
||||
['weakptr_2ehpp',['WeakPtr.hpp',['http://atria-soft.github.io/ememory/__weak__ptr__8hpp.html',1,'']]],
|
||||
['wheat',['wheat',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a0fee5d2cd67adc3c4a5d820616854cde',1,'etk::color']]],
|
||||
['white',['white',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a6559ba632982f84ab6215281bd431b9c',1,'etk::color']]],
|
||||
['whitesmoke',['whiteSmoke',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a1b012cf56fb3a1c63e55aa2d83f7472b',1,'etk::color']]]
|
||||
];
|
26
search/all_15.html
Normal file
26
search/all_15.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_15.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
4
search/all_15.js
Normal file
4
search/all_15.js
Normal file
@ -0,0 +1,4 @@
|
||||
var searchData=
|
||||
[
|
||||
['x',['x',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a8409de5d430e5cdcb7326aee94176873',1,'etk::Vector2D::x()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a8409de5d430e5cdcb7326aee94176873',1,'Vector2D< int32_t >::x()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#a8409de5d430e5cdcb7326aee94176873',1,'Vector2D< uint32_t >::x()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#af2bda50fefea08fb49c04b15a61bcb6a',1,'etk::Vector3D::x()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a98cef087b46916c257dc7b7e39230e74',1,'etk::Vector4D::x()']]]
|
||||
];
|
26
search/all_16.html
Normal file
26
search/all_16.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_16.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
6
search/all_16.js
Normal file
6
search/all_16.js
Normal file
@ -0,0 +1,6 @@
|
||||
var searchData=
|
||||
[
|
||||
['y',['y',['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#abc8a9a46cb0bf2c32916bfa3a35dfb22',1,'etk::Vector2D::y()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#abc8a9a46cb0bf2c32916bfa3a35dfb22',1,'Vector2D< int32_t >::y()'],['http://atria-soft.github.io/etk/classetk_1_1_vector2_d.html#abc8a9a46cb0bf2c32916bfa3a35dfb22',1,'Vector2D< uint32_t >::y()'],['http://atria-soft.github.io/etk/classetk_1_1_vector3_d.html#ad949b7843b6212277927f0b973ef502b',1,'etk::Vector3D::y()'],['http://atria-soft.github.io/etk/classetk_1_1_vector4_d.html#a5c604a37b7503594d4b69d286751b12d',1,'etk::Vector4D::y()']]],
|
||||
['yellow',['yellow',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a002d237cb06c35ec373b454af2cbb072',1,'etk::color']]],
|
||||
['yellowgreen',['yellowGreen',['http://atria-soft.github.io/etk/namespaceetk_1_1color.html#a88244e18c7bcefe71c7f9fbca047125b',1,'etk::color']]]
|
||||
];
|
26
search/all_17.html
Normal file
26
search/all_17.html
Normal file
@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html><head><title></title>
|
||||
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||
<meta name="generator" content="Doxygen 1.8.12"/>
|
||||
<link rel="stylesheet" type="text/css" href="search.css"/>
|
||||
<script type="text/javascript" src="all_17.js"></script>
|
||||
<script type="text/javascript" src="search.js"></script>
|
||||
</head>
|
||||
<body class="SRPage">
|
||||
<div id="SRIndex">
|
||||
<div class="SRStatus" id="Loading">Loading...</div>
|
||||
<div id="SRResults"></div>
|
||||
<script type="text/javascript"><!--
|
||||
createResults();
|
||||
--></script>
|
||||
<div class="SRStatus" id="Searching">Searching...</div>
|
||||
<div class="SRStatus" id="NoMatches">No Matches</div>
|
||||
<script type="text/javascript"><!--
|
||||
document.getElementById("Loading").style.display="none";
|
||||
document.getElementById("NoMatches").style.display="none";
|
||||
var searchResults = new SearchResults("searchResults");
|
||||
searchResults.Search();
|
||||
--></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user