[SCM] libambix/master: New upstream version 0.1
umlaeute at users.alioth.debian.org
umlaeute at users.alioth.debian.org
Wed Oct 5 21:12:10 UTC 2016
The following commit has been merged in the master branch:
commit ecb0a034b940c6d3b4103cd0cf5cb6fa5c069a0d
Author: IOhannes m zmölnig <zmoelnig at umlautQ.umlaeute.mur.at>
Date: Wed Oct 5 22:56:14 2016 +0200
New upstream version 0.1
diff --git a/.deploy-documentation.sh b/.deploy-documentation.sh
new file mode 100755
index 0000000..31d17fc
--- /dev/null
+++ b/.deploy-documentation.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+WD=$(pwd)
+INPUTDIR="${WD}/doc/apiref"
+INPUT2DIR="${WD}/coverage"
+OUTPUTDIR="${WD}/gh-pages"
+REMOTE=https://github.com/iem-projects/ambix
+
+error() {
+ echo "$@" 1>&2
+}
+
+if [ -e "${INPUTDIR}/index.html" ]; then
+ :
+else
+ error "missing {INPUTDIR}/index.html"
+ exit 0
+fi
+if [ "x${REMOTE}" = "x" ]; then
+ error "no remote"
+ exit 0
+fi
+COMMIT=$(git describe --always)
+
+commit_msg() {
+echo "Deploy code docs to GitHub Pages"
+echo ""
+if [ "x${COMMIT}" != x ]; then
+ echo "Commit: ${COMMIT}"
+fi
+if [ "x${TRAVIS_BUILD_NUMBER}" != "x" ]; then
+ echo "Travis build: ${TRAVIS_BUILD_NUMBER}"
+fi
+if [ "x${TRAVIS_COMMIT}" != "x" ]; then
+ echo "Travis commit: ${TRAVIS_COMMIT}"
+fi
+}
+
+git clone -b gh-pages "${REMOTE}" "${OUTPUTDIR}"
+cd "${OUTPUTDIR}" || exit 1
+
+##### Configure git.
+# Set the push default to simple i.e. push only the current branch.
+git config push.default simple
+# Pretend to be an user called Travis CI.
+git config user.name "Travis CI"
+git config user.email "travis at travis-ci.org"
+
+## clean gh-pages
+rm -rf "${INPUTDIR##*/}"
+
+## copy the doxygen documentation
+cp -rav "${INPUTDIR}" "${INPUTDIR##*/}"
+
+## add and commit to git
+git add --all "${INPUTDIR##*/}"
+
+## add coverage info (if it is there)
+if [ -d "${INPUT2DIR}" ]; then
+ error "adding coverage info ${INPUT2DIR##*/}"
+ rm -rf "${INPUT2DIR##*/}"
+ cp -rav "${INPUT2DIR}" "${INPUT2DIR##*/}"
+ git add --all "${INPUT2DIR##*/}"
+fi
+
+error "committing to git"
+commit_msg | git commit -F - .
+
+
+# and push
+error "pushing to git"
+if [ "x${GH_REPO_TOKEN}" != "x" ]; then
+ GH_REPO_REF=${REMOTE#*@}
+ GH_REPO_REF=${GH_REPO_REF#*//}
+ git push --force "https://${GH_REPO_TOKEN}@${GH_REPO_REF}" > /dev/null
+else
+ git push --force > /dev/null
+fi
+
+rm -rf "${OUTPUTDIR}"
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 189502d..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,43 +0,0 @@
-# backup copies
-*~
-# build products
-*\.la
-*\.lo
-*\.o
-*\.so
-*\.dll
-*\.pd_*
-\.deps/
-\.libs/
-# autotools byproducts
-Makefile
-Makefile\.in
-aclocal\.m4
-autom4te\.cache/
-configure
-config\.guess
-config\.log
-config\.status
-config\.sub
-missing
-install-sh
-stamp-h1
-libtool
-depcomp
-ltmain\.sh
-config\.h
-config\.h\.in
-m4/libtool\.m4
-m4/ltoptions\.m4
-m4/ltsugar\.m4
-m4/ltversion\.m4
-m4/lt~obsolete\.m4
-## w32 build projects
-build/w32-vs*/*
-*.vcproj.*.*.user
-!*.dsw
-!*.dsp
-!*.sln
-!*.vcproj
-!*.vsprops
-!Makefile.am
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..db98016
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,59 @@
+language: c
+sudo: required
+dist: trusty
+
+env:
+ global:
+ - secure: "nAc3WvwtJBm+hLIYxp4srwgM7qDWRovkEpsza+UITEE8TUqeZND2543xMZlWz1w5qn8V/F/1yX1oYl7Ot0ymmu9Uh41b1NBr3cvo2U8RLDSM9SBoqtyS1pSCnJ2qiSk+hg5GxObWug/ph3TkEgZaDmYCDAgHiv1I9WXVRxeR144="
+ - COVERITY_SCAN_BRANCH_PATTERN="(master|coverity-.*)"
+ - COVERITY_SCAN_NOTIFICATION_EMAIL="dev at umlaeute.mur.at"
+ - COVERITY_SCAN_BUILD_COMMAND="make"
+ - LIBSNDFILE_URL="http://www.mega-nerd.com/libsndfile/files/libsndfile-1.0.26.tar.gz"
+
+addons:
+ apt:
+ packages:
+ - libvorbis-dev
+ - libflac-dev
+ - libasound2-dev
+ - doxygen
+ - lcov
+ - ca-certificates
+
+matrix:
+ include:
+ - compiler: clang
+ env:
+ - COVERITY_SCAN_PROJECT_NAME="$TRAVIS_REPO_SLUG"
+ - compiler: gcc
+ env:
+ - DO_COVERAGE="yes"
+
+install:
+ ## build libsndfile
+ - mkdir -p libsndfile/build && curl "$LIBSNDFILE_URL" | tar --strip-components=1 -C libsndfile -xvzf -
+ - cd libsndfile/build && ../configure --disable-silent-rules && make && sudo make install
+ ## remove libtool libs
+ - find /usr/local/lib -type f -name "*.la" -exec sudo rm -f {} \+
+before_script:
+ - cd "$TRAVIS_BUILD_DIR"
+ - ./autogen.sh
+ - ./configure --disable-silent-rules
+ # OMG, Coverity scan uses a certificate not supported by travis-ci
+ - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-certificates.crt
+ # implement Coverity Scan with before_script instead of addons.coverity_scan
+ # to work around too-early quota check by the coverity_scan addon
+ - if [[ -n $COVERITY_SCAN_PROJECT_NAME ]] ; then curl -s 'https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh' | bash || true ; fi
+
+script:
+- make
+- LD_LIBRARY_PATH=/usr/local/lib make distcheck
+
+after_success:
+ - if [[ "x${DO_COVERAGE}" = "xyes" ]] ; then LD_LIBRARY_PATH=/usr/local/lib ./coverage.sh; fi
+ - if [[ "yes.${TRAVIS_BRANCH}.${TRAVIS_PULLREQUEST}" = "yes.master." ]]; then ./.deploy-documentation.sh ; fi
+ - bash <(curl -s https://codecov.io/bash)
+
+after_failure:
+ # spit out any test-suite results...
+ - find . -name test-suite.log -exec grep . {} \+
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..3573ba6
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,104 @@
+Contributing to libambix development
+====================================
+
+Contribution should be done via
+- Merge Requests / Pull Requests
+OR
+- via git patchsets (`git format-patch`)
+
+# GIT
+
+## Canonical Repositories
+
+MAIN repository
+- https://git.iem.at/ambisonics/libambix
+
+secondary repository
+- https://github.com/iem-projects/ambix
+
+Please *do not use* these legacy repositories:
+- ~~https://github.com/umlaeute/ambix~~
+- ~~https://git.code.sf.net/p/iem/ambix~~ (SourceForge)
+
+## Commits
+
+- make small, atomic commits
+- commit often
+- be sure that the description matches the actual changeset
+- do not mix unrelated changes into a single commit (*"fixed bug BAR, added
+ feature FOO"* is **bad**)
+- never mix changes to different components
+ (e.g. changes to `libambix/` should go in different commits as changes to `utils/`
+ and changes to `samples/pd/`)
+ - even if this temporarily breaks compilation! (e.g. if you are changing the
+ API of the libambix library, you have to update any code that uses this API;
+ in this case, first commit the changes to libambix, and then commit the
+ required changes in the utilities. the latter should be a single commit that
+ only adapts the code to the new API)
+ - make small, atomic commits
+
+# Coding Style
+
+- libambix is written in `ANSI-C` (aka `C89`)
+
+- function names use underscores to separate names (e.g. `ambix_open`)
+- *public* functions
+ - each *public* function **MUST** be declared in `libambix/ambix/ambi.h`
+ - each *public* function **MUST** be declared with the `AMBIX_API` decorator
+ - each *public* function **MUST** start with the `ambix_` prefix (to avoid nameclashes with other libraries)
+- *non-public* functions
+ - *non-public* functions that are only used within a single source file **MUST** be declared `static`
+ - *non-public* functions that are used within the entire libambix library **MUST** be prefixed with `_ambix`
+ - *non-public* functions that are used within the entire libambix library **SHOULD** be declared in `libambix/src/private.h` file
+
+- type names use underscores to separate names (e.g. `ambix_matrix_t`)
+- type names have a `_t` suffix (and an `ambix_` prefix if they are non-trivial)
+- *public* types
+ - complex types (aka `struct`s) should always be opaque (the actual `struct` is kept as an implementation detail)
+ - if needed, use (public) accessor functions (`get`/`set`) for the elements of a complex type
+
+-
+
+## Code Formatting
+
+TODO (follow mine :-))
+- no whitespace at the end-of-line
+- no empty line at the end-of-file
+
+
+# Code Testing
+
+## Unit Tests
+
+See `libambix/tests/` for example tests.
+
+All public functionality (and as far as possible all private functionality)
+should be tested via unit tests.
+The testing "framework" in use is provided by autotools.
+
+When testing private interfaces (non-public functions), the unit tests
+need to be compiled in debug-mode (using the `--enable-debug` configure option)
+and the tests should be protected by an `if DEBUG / endif` clause
+`libambix/tests/Makefile.am`.
+
+## Checking for memory leaks
+The unit tests can be instrumented to be run through valgrind:
+
+ cd libambix/tests
+ make check-valgrind
+
+The above will run the tests through the standard `memcheck` tool.
+If you want to use another valgrind tool, You can specify that as well:
+
+ cd libambix/tests
+ make check-valgrind-tool VALGRIND_TOOL=memcheck
+
+## Continuous Integration
+The library is automatically built and tested via
+[Travis-CI](https://travis-ci.org/iem-projects/ambix) whenever new code is
+committed.
+
+If you do not have write access to the main repository of libambix, you can
+Trigger a CI build for your contribution simply by creating a *Pull Request*
+against the [iem-projects/ambix](https://github.com/iem-projects/ambix)
+repository on GitHub.
diff --git a/README b/README
deleted file mode 100644
index 7656a44..0000000
--- a/README
+++ /dev/null
@@ -1,95 +0,0 @@
-This is ambix 0.0.1
-
-libambix is a library of C routines for reading and writing
-files following the "ambix" (AMBIsonics eXchange) conventions.
-
-
-Directory layout
-----------------
-libambix/
- all components of the libambix library
-libambix/src
- the source code for library itself.
-libambix/ambix
- public header files for the library
-libambix/tests
- programs which link against libambix and test its functionality.
-utils/
- utility programs using libambix
-
-
-NOTES
------
-libambix is a reads and writes soundfiles following the "ambix" specificiation.
-such files are:
-- CAF (Core Audio Format) files
-- with a special UUID-chunk
-
-Audio data as output by libambix will follow the following specification:
-- sample format is either PCM16, PCM24 or float32 (the latter being best tested)
-- audio data is interleaved
-- ambisonics channels are
- - normalization : SN3D
- - channel ordering : ACN
-
-It is planned to provide conversion matrices to present the audio data in other
-(common) formats namely
-- Furse-Malham set
-- other normalizations (N3D)
-- other ordering (SID)
-
-
-
-DEPENDENCIES
-------------
-Currently libambix uses libsndfile to read the actual file.
-Due to some advanced functionality, you need at least libsndfile-1.0.26.
-At the time of writing, libsndfile-1.0.26 has not yet been released. so
-you need the current development version of libsndfile
- https://github.com/erikd/libsndfile
-
-
-LINUX
------
-Whereever possible, you should use the packages supplied by your Linux
-distribution.
-
-If you really do need to compile from source it should be as easy as:
-
- $ ./configure
- $ make
- $ make install
-
-if you want to compile the development version of libambix, you might need
-to run
- $ ./autogen.sh
-_before_ any of the above.
-
-UNIX
-----
-Compile as for Linux.
-
-
-Win32/Win64
------------
-The default Windows compilers (Microsoft's Visual Studio) are nowhere near
-compliant with the 1999 ISO C Standard and hence not able to compile libambix.
-
-Please use the libambix binaries available on the ambix web site.
-
-
-MacOSX
-------
-Building on MacOSX should be the same as building it on any other Unix.
-
-
-CONTACTS
---------
-
-libambix was written by IOhannes m zmölnig at the Institute of Electronic Music
-and Acoustics (IEM), andthe University of Music and Performing Arts (KUG), Graz,
-Austria
-The libambix home page is at :
-
- http://ambisonics.iem.at/xchange/format
-
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bdd5d0b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,107 @@
+libambix - The AMBIsonics eXchange library
+==========================================
+
+This is libambix `0.0.1`
+
+libambix is a library of C routines for reading and writing
+files following the "ambix" (AMBIsonics eXchange) conventions.
+
+# Status
+
+| *Check* | *Health* |
+| :--------------------- | :------------------------------------------------------------------ |
+| Continuous Integration |  |
+| Static Code Analysis |  |
+| Test Coverage | [](https://codecov.io/gh/iem-projects/ambix) |
+
+
+# INTRODUCTION
+libambix is a library that reads and writes soundfiles following the "ambix"
+specificiation.
+Such files are:
+- `CAF` (Core Audio Format) files
+- *with* a special `UUID-chunk`
+
+Audio data as output (and accepted as input) by libambix will follow the following specification:
+- sample format is either `PCM16`, `PCM24`, `float32` (this one being best
+ tested) and `float64`
+- audio data is *interleaved*
+- ambisonics channels are
+ - normalization : `SN3D`
+ - channel ordering : `ACN`
+
+It is planned to provide conversion matrices to present the audio data in other
+(common) formats namely
+- Furse-Malham set (*FuMa*)
+- other normalizations (*N3D*)
+- other ordering (*SID*)
+
+# Download
+
+Get the source code (and releases) from
+ https://git.iem.at/ambisonics/libambix
+
+The source code is also mirrored to
+ [GitHub](https://github.com/iem-projects/ambix/)
+and (less often) to
+ [SourceForge](https://sourceforge.net/p/iem/ambix/)
+
+# API Documentation
+
+An up-to-date API Documentation can be found at
+ http://iem-projects.github.io/ambix/apiref/
+
+# Directory layout
+- `libambix/` - all components of the libambix library
+- `libambix/src` - the source code for library itself.
+- `libambix/ambix` - public header files for the library
+- `libambix/tests` - programs which link against libambix and test its functionality.
+- `utils/` - utility programs using libambix
+
+# BUILDING from source
+
+## DEPENDENCIES
+Currently libambix uses libsndfile to read the actual file.
+Due to some advanced functionality, you need at least libsndfile-1.0.26.
+The current version of libsndfile can be obtained from
+ https://github.com/erikd/libsndfile
+
+
+## LINUX
+Wherever possible, you should use the packages supplied by your Linux
+distribution.
+
+If you really do need to compile from source it should be as easy as:
+
+ $ ./configure
+ $ make
+ $ make install
+
+if you want to compile the development version of libambix, you might need
+to run the following *before* any of the above:
+
+ $ ./autogen.sh
+
+## UNIX
+Compile as for Linux.
+
+
+## Win32/Win64
+The default Windows compilers (Microsoft's Visual Studio) are nowhere near
+compliant with the 1999 ISO C Standard and hence not able to compile libambix.
+
+Please use the libambix binaries available on the ambix web site.
+
+
+## MacOSX
+Building on MacOSX should be the same as building it on any other Unix.
+
+
+# CONTACT
+
+libambix was written by IOhannes m zmölnig at the Institute of Electronic Music
+and Acoustics (IEM), and the University of Music and Performing Arts (KUG), Graz,
+Austria
+The libambix home page is at :
+
+ http://git.iem.at/ambisonics/libambix
diff --git a/configure.ac b/configure.ac
index d296de4..685f4bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
-AC_INIT([ambix],[0.0.1],[zmoelnig at iem.at],
+AC_INIT([ambix],[0.1],[zmoelnig at iem.at],
[libambix],[http://ambisonics.iem.at/xchange/format])
-AM_INIT_AUTOMAKE
+AM_INIT_AUTOMAKE([foreign])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@@ -11,7 +11,7 @@ AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
-AC_CONFIG_FILES([libambix/Makefile libambix/src/Makefile libambix/tests/Makefile])
+AC_CONFIG_FILES([libambix/Makefile libambix/src/Makefile libambix/tests/Makefile libambix/tests/data/Makefile])
AC_CONFIG_FILES([libambix/libambix.pc])
AC_CONFIG_FILES([utils/Makefile utils/jcommon/Makefile])
AC_CONFIG_FILES([doc/Makefile])
@@ -65,6 +65,18 @@ AC_HEADER_STDC
AM_CONDITIONAL(DISABLED, [test "xno" = "xyes"])
AM_CONDITIONAL(ENABLED, [test "xyes" = "xyes"])
+
+AC_ARG_ENABLE(debug,
+AS_HELP_STRING([--enable-debug],
+ [enable debugging build, default: no]),
+ AS_CASE(["$enableval"],
+ yes, debug=true,
+ no, debug=false,
+ AC_MSG_ERROR([bad value ${enableval} for --enable-debug])),
+ [debug=false])
+AM_CONDITIONAL(DEBUG, test x"$debug" = x"true")
+
+
## check for math
AC_CHECK_LIB([m],[sqrt])
@@ -160,5 +172,8 @@ AC_CHECK_FUNCS([strndup])
AX_PTHREAD
+# run unitttests in valgrind
+AC_SUBST(VALGRIND_CHECK_RULES)
+m4_ifdef([AX_VALGRIND_CHECK], [AX_VALGRIND_CHECK])
AC_OUTPUT
diff --git a/coverage.sh b/coverage.sh
index b50b51b..67c1e3a 100755
--- a/coverage.sh
+++ b/coverage.sh
@@ -7,7 +7,8 @@ MAKE=make
${MAKE} clean
# Reconfigure with gcov support
-CXXFLAGS="-g -O0 --coverage" CFLAGS="-g -O0 --coverage" ./configure || exit 1
+CFLAGS="-g -O0 --coverage" CXXFLAGS="-g -O0 --coverage" LDFLAGS="--coverage" \
+ ./configure --enable-debug --disable-silent-rules || exit 1
# Generate gcov output
${MAKE} || exit 1
diff --git a/doc/Makefile.am b/doc/Makefile.am
index b879dcf..ded5b11 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -6,10 +6,12 @@ if HAVE_DOXYGEN
html_DATA+=apiref/*
endif
+DOXYFILE=$(srcdir)/libambix.doxy
+
apiref/*: all-local
all-local:
- $(DOXYGEN) $(srcdir)/libambix.doxy
+ $(DOXYGEN) $(DOXYFILE)
clean-local:
-rm -rf apiref
diff --git a/doc/libambix.doxy b/doc/libambix.doxy
index 0cb6968..338a4a8 100644
--- a/doc/libambix.doxy
+++ b/doc/libambix.doxy
@@ -38,7 +38,7 @@ PROJECT_NUMBER =
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF =
+PROJECT_BRIEF = "the AMBIsonics eXchange library"
# With the PROJECT_LOGO tag one can specify an logo or icon that is
# included in the documentation. The maximum height of the logo should not
@@ -926,7 +926,7 @@ HTML_COLORSTYLE_GAMMA = 80
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.
-HTML_TIMESTAMP = YES
+HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
@@ -1160,7 +1160,7 @@ USE_MATHJAX = YES
# MathJax, but it is strongly recommended to install a local copy of MathJax
# before deployment.
-MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
# names that should be enabled during MathJax rendering.
diff --git a/doc/libambix.incl b/doc/libambix.incl
index 6d3bd3a..3ae7646 100644
--- a/doc/libambix.incl
+++ b/doc/libambix.incl
@@ -103,6 +103,7 @@
free(ambidata);
free(extradata);
}
+ free(info);
* @endcode
*
*
@@ -119,7 +120,9 @@
ambix_t*ambix = NULL;
ambix_info_t*info = calloc(1, sizeof(ambix_info_t));
- // setting the fileformat to AMBIX_EXTENDED forces the ambi data to be delivered as stored in the file
+ /* setting the fileformat to AMBIX_EXTENDED forces the ambi data
+ * be delivered as stored in the file
+ */
ambix->fileformat = AMBIX_EXTENDED;
ambix = ambix_open("ambixfile.caf", AMBIX_READ, info);
@@ -152,17 +155,18 @@
free(ambidata);
free(extradata);
}
+ free(info);
* @endcode
*
*
* @subsection readunknown_usage Reading any ambix files
*
- * If you don't specify the format prior to opening, you can query the format of the file
+ * If you do not specify the format prior to opening, you can query the format of the file
* from the ambix_info_t struct.
*
* @code
ambix_t*ambix = NULL;
- ambix_info_t*info = calloc(1, sizeof(ambix_info_t)); // initialize the format field (among others) to 0
+ ambix_info_t*info = calloc(1, sizeof(ambix_info_t)); /* initialize the format field (among others) to 0 */
ambix = ambix_open("ambixfile.caf", AMBIX_READ, info);
@@ -181,11 +185,9 @@
printf("this file is of unknown format...\n");
}
- // using the adaptormatrix
- // ...
-
ambix_close(ambix);
}
+ free(info);
* @endcode
*
*
@@ -203,8 +205,9 @@
* ambix_info_t struct to @ref AMBIX_BASIC prior to opening the file.
*
* You will need to provide a full set of ambisonics channels when writing data
- * to the file, and must not set an adaptor matrix. A full set of ambisonics
- * must always satisfy the formula @f$channels=(order_{ambi}+1)^2 at f$.
+ * to the file, and must not set an adaptor matrix (see also @ref writebasic2extended_usage).
+ * A full set of ambisonics must always satisfy the formula
+ * @f$channels=(order_{ambi}+1)^2 at f$.
*
* You cannot write extra audio channels into a "BASIC" ambix file.
*
@@ -212,11 +215,11 @@
ambix_t*ambix = NULL;
ambix_info_t*info = calloc(1, sizeof(ambix_info_t));
- // need to specify samplerate and sampleformat
+ /* need to specify samplerate and sampleformat */
ambix->samplerate = 44100;
- ambix->sampleformat = AMBIX_SAMPLEFORMAT_PCM16;
+ ambix->sampleformat = AMBIX_SAMPLEFORMAT_PCM24;
ambix->fileformat = AMBIX_BASIC;
- ambix->ambichannels = 16; // 16 channels means 3rd order ambisonics, according to L=(2N+1)^2
+ ambix->ambichannels = 16; /* 16 channels means 3rd order ambisonics, according to L=(2N+1)^2 */
ambix = ambix_open("ambixfile.caf", AMBIX_WRITE, info);
if(ambix) {
@@ -237,6 +240,7 @@
ambix_close(ambix);
free(ambidata);
}
+ free(info);
* @endcode
*
* @subsection writeextended_usage Writing EXTENDED ambix files
@@ -253,12 +257,12 @@
ambix_t*ambix = NULL;
ambix_info_t*info = calloc(1, sizeof(ambix_info_t));
- // need to specify samplerate and sampleformat
+ /* need to specify samplerate and sampleformat */
ambix->samplerate = 44100;
- ambix->sampleformat = AMBIX_SAMPLEFORMAT_PCM16;
+ ambix->sampleformat = AMBIX_SAMPLEFORMAT_PCM24;
ambix->fileformat = AMBIX_EXTENDED;
- ambix->ambichannels = 8; // a reduced ambisonics set
- ambix->extrachannels = 1; // an extrachannel, e.g. click-track
+ ambix->ambichannels = 8; /* a reduced ambisonics set */
+ ambix->extrachannels = 1; /* an extrachannel, e.g. click-track */
ambix = ambix_open("ambixfile.caf", AMBIX_WRITE, info);
if(ambix) {
@@ -267,9 +271,9 @@
uint64_t block;
float32_t*ambidata = calloc(info->ambichannels * blocksize, sizeof(float32_t));
- float32_t*extradata = calloc(info->extrachannels * blocksize, sizeof(float32_t));
+ float32_t*extradata = calloc(info->extrachannels * blocksize, sizeof(float32_t));
- // create an adaptormatrix:
+ /* create an adaptormatrix: */
ambix_matrix_t adaptormatrix = {0, 0, NULL};
ambix_matrix_init(16, 8, &adaptormatrix);
// fill the adaptormatrix, that expands our 8 channels to a full 3D 3rd-order set (16 channels)
@@ -291,8 +295,78 @@
free(ambidata);
free(extradata);
}
+ free(info);
* @endcode
*
+ * @subsection writebasic2extended_usage Writing EXTENDED ambix files using the BASIC interface
+ *
+ * Finally, you can create "EXTENDED" ambix files from a full set of ambisonics channels and an
+ * adaptor matrix.
+ * This can be useful if you have a setup that works with full ambisonics sets (e.g. a DAW project)
+ * and you want to create a size-optimized ambix file that only stores a reduced set.
+ *
+ * This can be achieved by setting the 'fileformat' member of the ambix_info_t struct to
+ * @ref AMBIX_BASIC (because you will provide the full ambisonics set as if the file were opened in
+ * "BASIC" mode) and the 'ambichannels' member to the (reduced) number of ambisonics channel as will
+ * be written to the disk, and then setting an adaptor matrix ambix_set_adaptormatrix(), that will
+ * convert the reduced set back to the full set.
+ * libambix will internally reduce the full ambisonics set (as passed to @ref ambix_writef) using
+ * the (pseudo) inverse of the adaptor-matrix.
+ *
+ * @note You must ensure yourself that the adaptor matrix is inversible.
+ *
+ * The adaptor matrix gets written to disk prior to writing any samples to the file
+ * (or closing the ambix file). It is an error to call ambix_set_adaptormatrix()
+ * after starting to write samples.
+ *
+ * @note If you pass an adaptor matrix that expands a reduced set to full ambisonics
+ * (e.g. converting from 1st order horizontal-only ambisonics set to a 2nd order fully periphonic set)
+ * the reconstructed ambisonics channels (when reading the ambix file later),
+ * might be different from the ambisonics channels you passed in when writing the file
+ * (e.g. channels that contain 3rd-order and/or Z-axis components will be muted).
+ *
+ * @code
+ ambix_t*ambix = NULL;
+ ambix_info_t*info = calloc(1, sizeof(ambix_info_t));
+
+ /* need to specify samplerate and sampleformat */
+ info->samplerate = 44100;
+ info->sampleformat = AMBIX_SAMPLEFORMAT_PCM24;
+ info->fileformat = AMBIX_BASIC;
+ info->ambichannels = 7; /* 3rd-order horizontal-only(!) */
+
+ ambix = ambix_open("ambixfile.caf", AMBIX_WRITE, info);
+ if(ambix) {
+ uint64_t fullambichannels = 16;
+ uint64_t frames = info->frames;
+ uint64_t blocksize = 1024;
+ uint64_t block;
+
+ float32_t*ambidata = calloc(fullambichannels * blocksize, sizeof(float32_t));
+
+ /* on disk, the data is stored as 3rd-order horizontal-only Furse-Malham
+ * set (7 channels); we need to provide an adaptor matrix that converts
+ * from the 7 FuMa-channels to the 16 AMBIX channels
+ */
+ ambix_matrix_t*mtx = NULL;
+ mtx = ambix_matrix_init(fullambichannels, info->ambichannels, mtx);
+ mtx = ambix_matrix_fill(mtx, ABIX_MATRIX_FUMA); /* fuma->ambix matrix [16x7] */
+ ambix_set_adaptormatrix(ambix, mtx);
+ ambix_matrix_destroy(mtx);
+
+ while(haveData) {
+ // acquire blocksize samples of a full set of 3rd order ambisonics data (16 channels)
+ // into ambidata (interleaved)
+ // ...
+
+ block = ambix_write_float32(ambix, ambidata, NULL, blocksize);
+ }
+
+ ambix_close(ambix);
+ free(ambidata);
+ }
+ free(info);
+ * @endcode
*
*/
@@ -315,7 +389,7 @@
*
* @section format_bugfix Bug-fixes for the format-specification
*
- * The original @link http://ambisonics.iem.at/xchange/format/2011_NachbarZotterSontacchiDeleflie_ambix.pdf format proposal at endlink
+ * The original <a href="http://ambisonics.iem.at/xchange/fileformat/2011_nachbarzottersontacchideleflie_ambix.pdf">format proposal</a>
* had a number of flaws and bugs that have been discovered during the implenentation of @em libambix.
* Consequently, these flaws and bugs have been fixed.
*
@@ -376,3 +450,95 @@
* @f$ACN = l * ( l + 1 ) + m at f$
*
*/
+
+/**
+ * @cond
+ * @page utilities ambix commandline utilities
+ *
+ * libambix comes with a number of commandline utilities
+ *
+ * @section informational informational
+ * @subsection ambix-info ambix-info
+ * @subsection ambix-dump ambix-dump
+ * @section ambix-refile file creation
+ * @subsection ambix-interleave ambix-interleave
+ * @subsection ambix-deinterleave ambix-deinterleave
+ * @section recording and playback
+ * @subsection ambix-jplay ambix-jplay
+ * @subsection ambix-jrecord ambix-jrecord
+ * @section tests
+ * @subsection ambix-test ambix-test
+ * @subsection ambix-matrix ambix-matrix
+ * @endcond
+ */
+
+
+/**
+ * @page FAQ Frequently Asked Questions
+ *
+ * @section Terms
+ *
+ * @subsection term-ambix What does libambix stand for?
+ * @c libambix is a <b>lib</b>rary for reading and writing <b>ambi</b>sonics e<b>x</b>change files.
+ *
+ * @subsection basic-vs-extended What is the difference between BASIC and EXTENDED ambix files?
+ * @c BASIC ambix files contain exactly a full set of periphonic ambisonics channels,
+ * using ACN channel ordering and SN3D normalisation.
+ *
+ * @c EXTENDED ambix files contain an additional adaptor matrix at the beginning of the file,
+ * which can be used to turn the actually stored audio channels into a full set of
+ * periphonic ambisonics channels (periphonic, ACN, SN3D).
+ * These files can be used to store a reduced number of channels
+ * (e.g. when your soundfield is horizontal only,
+ * there is no need to store the channels with height-information, as they will be muted anyhow),
+ * while providing a simple and standardized way to play them back on a full ambisonics decoder.
+ *
+ * See @ref format for more information.
+ *
+ * @section HOW-TOs
+ *
+ * @subsection howto-channels2basic How can I create an ambix file from a set of mono soundfiles?
+ * If you have an ambisonics recording as multiple mono soundfiles following the ambix standard
+ * (channel ordering: ACN, normalisation: SN3D), you can merge them into an ambix files
+ * using the `ambix-interleave` command.
+ * @code
+ ambix-interleave -o ambixfile.caf recording-ambi0.wav recording-ambi1.wav recording-ambi2.wav recording-ambi3.wav
+ * @endcode
+ *
+ * @subsection howto-multichannel2basic How can I create an ambix file from a multichannel soundfile?
+ * If you have an ambisonics recording already as a multichannel soundfile, with the channels
+ * following the ambix standard (channel ordering: ACN, normalisation: SN3D),
+ * you can create an ambix file from that using the `ambix-interleave` command.
+ * @code
+ ambix-interleave -o ambixfile.caf recording.wav
+ * @endcode
+ *
+ * @subsection howto-amb2extended How can I convert my .amb files to ambix?
+ * You can use the `ambix-interleave` file to create EXTENDED ambix files from your
+ * old .amb recordings.
+ * If `ambix-interleave` detects that the input is an .amb file, it will
+ * add an adaptor matrix that converts from .amb's Furse-Malham channels to ambix channels,
+ * and will otherwise leave the audio data intact.
+ * @code
+ ambix-interleave -o ambixfile.caf recording.amb
+ * @endcode
+ *
+ * @subsection howto-amb2basic How can I convert my .amb files to ambix?
+ * To create BASIC ambix files (without an adaptor matrix), you can use
+ * `ambix-deinterleave` to convert the .amb file to SN3D/ACN channels, and then
+ * use `ambix-interleave` to merge those files into a single ambix file:
+ * @code
+ ambix-deinterleave recording.amb
+ ambix-interleave -o ambixfile.caf recording-ambi*
+ * @endcode
+ *
+ * @subsection howto-extended2basic How can I convert an EXTENDED ambix file to BASIC?
+ * The easiest way to convert an EXTENDED ambix file to a BASIC file is to first
+ * extract the channels into separate files using `ambix-deinterleave`,
+ * and then merge them back using `ambix-interleave`:
+ * @code
+ ambix-deinterleave ambixextended.caf
+ ambix-interleave -o ambixbasic.caf ambixextended-ambi*
+ * @endcode
+ *
+ */
diff --git a/libambix/ambix/ambix.h b/libambix/ambix/ambix.h
index dd5bf88..966895b 100644
--- a/libambix/ambix/ambix.h
+++ b/libambix/ambix/ambix.h
@@ -21,8 +21,8 @@
*/
/**
- * @file ambix/ambix.h
- * @brief AMBIsonics eXchange Library Interface
+ * @file ambix/ambix.h
+ * @brief AMBIsonics eXchange Library Interface
* @details This file is part of libambix
* @author IOhannes m zmölnig <zmoelnig at iem.at>
* @date 2012
@@ -39,6 +39,9 @@ extern "C" {
/** 32bit floating point number */
typedef float float32_t;
+
+/** 64bit floating point number */
+typedef double float64_t;
#ifdef _MSC_VER
/** 16bit signed integer */
@@ -57,7 +60,7 @@ typedef unsigned long uint64_t;
# include <stdint.h>
#endif
-/** a 32bit number (either float or int), useful for endianess operations */
+/** a 32bit number (either float or int), useful for endianness operations */
typedef union {
/** 32bit floating point */
float32_t f;
@@ -128,6 +131,8 @@ typedef enum {
AMBIX_SAMPLEFORMAT_PCM32,
/** 32 bit floating point */
AMBIX_SAMPLEFORMAT_FLOAT32,
+ /** 64 bit floating point */
+ AMBIX_SAMPLEFORMAT_FLOAT64,
} ambix_sampleformat_t;
/** ambix matrix types */
@@ -143,7 +148,7 @@ typedef enum {
/** matrices with the 0x8000 bit set convert between ambix and other ambisonics formats:
* if the 0x4000 bit is set to 0, the matrix converts to ambix,
- * if the 0x4000 but is set to 1, the matrix converts from ambix.
+ * if the 0x4000 bit is set to 1, the matrix converts from ambix.
* @remark some of the following matrixes might not be implemented yet
* @remark AMBIX_MATRIX_AMBIX converts from ambix to ambix (and is quite useless by itself)
*/
@@ -160,7 +165,7 @@ typedef enum {
/** conversion matrix SN3D -> N3D */
AMBIX_MATRIX_TO_N3D = AMBIX_MATRIX_TO_AMBIX | AMBIX_MATRIX_N3D,
- /** conversion matrix SID -> ACN */
+ /** conversion matrix ACN -> SID */
AMBIX_MATRIX_TO_SID = AMBIX_MATRIX_TO_AMBIX | AMBIX_MATRIX_SID,
/** conversion matrix ambix -> Furse-Malham */
AMBIX_MATRIX_TO_FUMA = AMBIX_MATRIX_TO_AMBIX | AMBIX_MATRIX_FUMA,
@@ -187,7 +192,20 @@ typedef struct ambix_info_t {
double samplerate;
/** sample type of the ambix file */
ambix_sampleformat_t sampleformat;
- /** layout type of the ambix file */
+
+ /** layout type of the ambix file
+ *
+ * When opening a file, this format specifies the format from the
+ * user-perspective. This is not necessarily the same as the actual
+ * format of the file on disk.
+ * E.g. when setting this to @ref AMBIX_BASIC to read an @ref AMBIX_EXTENDED
+ * file, the library will automatically convert the reduced channel set
+ * to the full set (using the embedded adaptor matrix).
+ * Similarly, when setting this to @ref AMBIX_BASIC for writing a file,
+ * and then setting an adaptor matrix (using @ref ambix_set_adaptormatrix())
+ * the actual file will be @ref AMBIX_EXTENDED, but the user has to provide
+ * the full set (and the library will store the reduced set).
+ */
ambix_fileformat_t fileformat;
/** number of non-ambisonics channels in the file
@@ -197,17 +215,43 @@ typedef struct ambix_info_t {
/** number of (raw) ambisonics channels present in the file.
*
- * If the file contains a full set of ambisonics channels (always true if
- * ambixformat==AMBIX_BASIC), then \f$ambichannel=(order_{ambi}+1)^2\f$; if
- * the file contains an adaptor matrix, it has to be used to reconstruct the
- * full set by multiplying the adaptor matrix with the channels present.
+ * If the file contains a full set of ambisonics channels (format==@ref AMBIX_BASIC),
+ * then \f$ambichannel=(order_{ambi}+1)^2\f$; if the file contains an adaptor
+ * matrix, it has to be used to reconstruct the full set by multiplying the
+ * adaptor matrix with the channels present.
+ *
+ * @remark when opening for WRITING an @ref AMBIX_EXTENDED file as
+ * @ref AMBIX_BASIC (by specifying an adaptor matrix via @ref ambix_set_adaptormatrix()),
+ * this value must contain the reduced numer of channels (as stored on disk).
*/
uint32_t ambichannels;
} ambix_info_t;
+/** struct for holding a marker */
+typedef struct ambix_marker_t {
+ /** position in samples */
+ float64_t position;
+ /** name: NULL terminated string with maximum length of 255 */
+ char name[256];
+} ambix_marker_t;
+
+/** struct for holding a region */
+typedef struct ambix_region_t {
+ /** start position in samples */
+ float64_t start_position;
+ /** end position in samples */
+ float64_t end_position;
+ /** name: NULL terminated string with maximum length of 255 */
+ char name[256];
+} ambix_region_t;
+
/*
* @section api_main Main Interface
*/
+/** @defgroup ambix ambix
+ *
+ * @brief handling AmbiX files
+ */
/** @brief Open an ambix file
*
@@ -234,6 +278,8 @@ typedef struct ambix_info_t {
* @ref AMBIX_BASIC, then ambixinfo.ambichannels must be @f$(order_{ambi}+1)^2 at f$
*
* @return A handle to the opened file (or NULL on failure)
+ *
+ * @ingroup ambix
*/
AMBIX_API
ambix_t *ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_t *ambixinfo) ;
@@ -246,6 +292,8 @@ ambix_t *ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_t
* @param ambix The handle to an ambix file
*
* @return an error code indicating success
+ *
+ * @ingroup ambix
*/
AMBIX_API
ambix_err_t ambix_close (ambix_t *ambix) ;
@@ -264,20 +312,12 @@ ambix_err_t ambix_close (ambix_t *ambix) ;
*
* @return the offset in (multichannel) frames from the start of the audio data
* or -1 if an error occurred.
+ *
+ * @ingroup ambix
*/
AMBIX_API
int64_t ambix_seek (ambix_t *ambix, int64_t frames, int whence) ;
-/** @brief Read samples (as 16bit signed integer values) from the ambix file
- * @ingroup ambix_readf
- */
-AMBIX_API
-int64_t ambix_readf_int16 (ambix_t *ambix, int16_t *ambidata, int16_t *otherdata, int64_t frames) ;
-/** @brief Read samples (as 32bit signed integer values) from the ambix file
- * @ingroup ambix_readf
- */
-AMBIX_API
-int64_t ambix_readf_int32 (ambix_t *ambix, int32_t *ambidata, int32_t *otherdata, int64_t frames) ;
/** @brief Read samples from the ambix file
* @defgroup ambix_readf ambix_readf()
*
@@ -301,25 +341,34 @@ int64_t ambix_readf_int32 (ambix_t *ambix, int32_t *ambidata, int32_t *otherdata
* @param frames number of sample frames you want to read
*
* @return the number of sample frames successfully read
+ *
+ * @ingroup ambix
*/
-/** @brief Read samples (as single prevision floating point values) from the
- * ambix file
+/** @brief Read samples (as 16bit signed integer values) from the ambix file
* @ingroup ambix_readf
*/
AMBIX_API
-int64_t ambix_readf_float32 (ambix_t *ambix, float32_t *ambidata, float32_t *otherdata, int64_t frames) ;
-
-/** @brief Write (16bit signed integer) samples to the ambix file
- * @ingroup ambix_writef
+int64_t ambix_readf_int16 (ambix_t *ambix, int16_t *ambidata, int16_t *otherdata, int64_t frames) ;
+/** @brief Read samples (as 32bit signed integer values) from the ambix file
+ * @ingroup ambix_readf
*/
AMBIX_API
-int64_t ambix_writef_int16 (ambix_t *ambix, const int16_t *ambidata, const int16_t *otherdata, int64_t frames) ;
-/** @brief Write (32bit signed integer) samples to the ambix file
- * @ingroup ambix_writef
+int64_t ambix_readf_int32 (ambix_t *ambix, int32_t *ambidata, int32_t *otherdata, int64_t frames) ;
+/** @brief Read samples (as single precision floating point values) from the
+ * ambix file
+ * @ingroup ambix_readf
*/
AMBIX_API
-int64_t ambix_writef_int32 (ambix_t *ambix, const int32_t *ambidata, const int32_t *otherdata, int64_t frames) ;
-/** @brief Write samples to the ambix file
+int64_t ambix_readf_float32 (ambix_t *ambix, float32_t *ambidata, float32_t *otherdata, int64_t frames) ;
+
+/** @brief Read samples (as double precision floating point values) from the
+* ambix file
+* @ingroup ambix_readf
+*/
+AMBIX_API
+int64_t ambix_readf_float64 (ambix_t *ambix, float64_t *ambidata, float64_t *otherdata, int64_t frames) ;
+
+/** @brief Write samples to the ambix file.
* @defgroup ambix_writef ambix_writef()
*
* Writes samples (as single precision floating point values) to an ambix file,
@@ -343,13 +392,29 @@ int64_t ambix_writef_int32 (ambix_t *ambix, const int32_t *ambidata, const int32
* @param frames number of sample frames you want to write
*
* @return the number of sample frames successfully written
+ *
+ * @ingroup ambix
+ */
+/** @brief Write (16bit signed integer) samples to the ambix file
+ * @ingroup ambix_writef
*/
+AMBIX_API
+int64_t ambix_writef_int16 (ambix_t *ambix, const int16_t *ambidata, const int16_t *otherdata, int64_t frames) ;
+/** @brief Write (32bit signed integer) samples to the ambix file
+ * @ingroup ambix_writef
+ */
+AMBIX_API
+int64_t ambix_writef_int32 (ambix_t *ambix, const int32_t *ambidata, const int32_t *otherdata, int64_t frames) ;
/** @brief Write (32bit floating point) samples to the ambix file
* @ingroup ambix_writef
*/
AMBIX_API
int64_t ambix_writef_float32 (ambix_t *ambix, const float32_t *ambidata, const float32_t *otherdata, int64_t frames) ;
-
+/** @brief Write (64bit floating point) samples to the ambix file
+ * @ingroup ambix_writef
+ */
+AMBIX_API
+int64_t ambix_writef_float64 (ambix_t *ambix, const float64_t *ambidata, const float64_t *otherdata, int64_t frames) ;
/**
* typedef from libsndfile
* @private
@@ -359,16 +424,110 @@ struct SNDFILE_tag;
/** @brief Get the libsndfile handle associated with the ambix handle
*
* If possible, require an SNDFILE handle if possible; if the ambix handle is
- * not asociated with SNDFILE (e.g. because libambix is compiled without
+ * not associated with SNDFILE (e.g. because libambix is compiled without
* libsndfile support), NULL is returned.
*
* @param ambix The handle to an ambix file
*
* @return A libsndfile handle or NULL
+ *
+ * @ingroup ambix
*/
AMBIX_API
struct SNDFILE_tag *ambix_get_sndfile (ambix_t *ambix) ;
-
+/** @brief Get the number of stored markers within the ambix file.
+ *
+ * @return number of markers.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+uint32_t ambix_get_num_markers(ambix_t *ambix) ;
+/** @brief Get the number of stored regions within the ambix file.
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @return Number of regions.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+uint32_t ambix_get_num_regions(ambix_t *ambix) ;
+/** @brief Get one marker.
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @param id The id of the marker to retrieve.
+ *
+ * @return The marker requested or NULL in case the marker does not exist.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+ambix_marker_t *ambix_get_marker(ambix_t *ambix, uint32_t id) ;
+/** @brief Get one region.
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @param id The id of the region to retrieve.
+ *
+ * @return The region requested or NULL in case the region does not exist.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+ambix_region_t *ambix_get_region(ambix_t *ambix, uint32_t id) ;
+/** @brief Add a new marker to the ambix file.
+ *
+ * @remark Markers have to be set before sample data is written!
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @param marker A valid marker that should be added to the ambix file.
+ *
+ * @return an errorcode indicating success.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+ambix_err_t ambix_add_marker(ambix_t *ambix, ambix_marker_t *marker) ; // returns id
+/** @brief Add a new region to the ambix file.
+ *
+ * @remark Regions have to be set before sample data is written!
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @param region A valid region that should be added to the ambix file.
+ *
+ * @return an errorcode indicating success.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+ambix_err_t ambix_add_region(ambix_t *ambix, ambix_region_t *region) ; // returns id
+/** @brief Deletes all markers in the ambix file.
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @return an errorcode indicating success.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+ambix_err_t ambix_delete_markers(ambix_t *ambix) ;
+/** @brief Deletes all regions in the ambix file.
+ *
+ * @param ambix The handle to an ambix file
+ *
+ * @return an errorcode indicating success.
+ *
+ * @ingroup ambix
+ */
+AMBIX_API
+ambix_err_t ambix_delete_regions(ambix_t *ambix) ;
+/** @brief Various utilities to handle matrices
+ * @defgroup ambix_matrix ambix_matrix
+ */
/** @brief Get the adaptor matrix
*
* The ambix extended fileformat comes with a adaptor matrix, that can be used
@@ -389,6 +548,8 @@ struct SNDFILE_tag *ambix_get_sndfile (ambix_t *ambix) ;
* @return the adaptor matrix to restore the full ambisonics set from the
* reduced set, or NULL if there is no such matrix; the memory is owned by the
* library and must neither be freed nor used after calling ambix_close().
+ *
+ * @ingroup ambix
*/
AMBIX_API
const ambix_matrix_t *ambix_get_adaptormatrix (ambix_t *ambix) ;
@@ -399,7 +560,7 @@ const ambix_matrix_t *ambix_get_adaptormatrix (ambix_t *ambix) ;
* of operation this can have different meanings! When READing an ambix '@ref
* AMBIX_BASIC' file, this tells the library to do an (additional)
* matrix-multiplication When reconstructing the full ambisonics set; you can
- * use use this to get the ambisonics channels in a format other than SN3D/ACN
+ * use this to get the ambisonics channels in a format other than SN3D/ACN
* (e.g. using an ambix to Furse-Malham adaptor matrix) or getting the
* loudspeaker feeds directly (by supplying a decoder matrix); in this case, the
* matrix MUST have ambix->ambichannels columns. When WRITEing an ambix '@ref
@@ -416,6 +577,8 @@ const ambix_matrix_t *ambix_get_adaptormatrix (ambix_t *ambix) ;
* @remark using this on ambix handles other than @ref AMBIX_READ/@ref
* AMBIX_BASIC or @ref AMBIX_WRITE/@ref AMBIX_EXTENDED
* is an error.
+ *
+ * @ingroup ambix
*/
AMBIX_API
ambix_err_t ambix_set_adaptormatrix (ambix_t *ambix, const ambix_matrix_t *matrix) ;
@@ -430,6 +593,8 @@ ambix_err_t ambix_set_adaptormatrix (ambix_t *ambix, const ambix_matrix_t *matri
* It's equivalent to calling ambix_matrix_init(0, 0, NULL) ;
*
* @return a new matrix object or NULL
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
ambix_matrix_t *ambix_matrix_create (void) ;
@@ -440,6 +605,8 @@ ambix_matrix_t *ambix_matrix_create (void) ;
* It's a shortcut for ambix_matrix_deinit(mtx), free(mtx)
*
* @param mtx matrix object to destroy
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
void ambix_matrix_destroy (ambix_matrix_t *mtx) ;
@@ -457,6 +624,8 @@ void ambix_matrix_destroy (ambix_matrix_t *mtx) ;
*
* @return pointer to a newly initialized (and/or allocated) matrix, or NULL on
* error.
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
ambix_matrix_t *ambix_matrix_init (uint32_t rows, uint32_t cols, ambix_matrix_t *mtx) ;
@@ -466,6 +635,8 @@ ambix_matrix_t *ambix_matrix_init (uint32_t rows, uint32_t cols, ambix_matrix_t
* Frees associated resources and sets rows/columns to 0
*
* @param mtx matrix object to deinitialize
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
void ambix_matrix_deinit (ambix_matrix_t *mtx) ;
@@ -486,6 +657,8 @@ void ambix_matrix_deinit (ambix_matrix_t *mtx) ;
*
* @return pointer to the matrix object, or NULL if the type was not valid (for the
* input matrix)
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
ambix_matrix_t *ambix_matrix_fill (ambix_matrix_t *matrix, ambix_matrixtype_t type) ;
@@ -501,6 +674,8 @@ ambix_matrix_t *ambix_matrix_fill (ambix_matrix_t *matrix, ambix_matrixtype_t ty
* A[rows-1, cols-1])
*
* @return an error code indicating success
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
ambix_err_t ambix_matrix_fill_data (ambix_matrix_t *mtx, const float32_t *data) ;
@@ -514,9 +689,12 @@ ambix_err_t ambix_matrix_fill_data (ambix_matrix_t *mtx, const float32_t *data)
* @param dest the destination matrix (if NULL a new matrix will be created)
*
* @return pointer to the destination matrix
+ *
+ * @ingroup ambix_matrix
*/
AMBIX_API
ambix_matrix_t *ambix_matrix_copy (const ambix_matrix_t *src, ambix_matrix_t *dest) ;
+/** @cond DEPRECATED */
/** @brief Multiply two matrices
*
* Multiply matrices dest=A*B, possibly resizing or creating the destination
@@ -533,12 +711,31 @@ ambix_matrix_t *ambix_matrix_copy (const ambix_matrix_t *src, ambix_matrix_t *de
*
* @remark If this returns a newly allocated matrix object (result!=return
* value), the host has to take care of calling ambix_matrix_destroy().
+ *
+ * @ingroup ambix_matrix
*/
-AMBIX_API
+AMBIX_API AMBIX_DEPRECATED
ambix_matrix_t *ambix_matrix_multiply (const ambix_matrix_t *A, const ambix_matrix_t *B, ambix_matrix_t *result) ;
-
+/** @brief Get the Moore-Penrose pseudoinverse of a matrix.
+ *
+ * Get the Moore-Penrose pseudoinverse of the matrix input and write the result
+ * to pinv
+ *
+ * @param matrix input matrix
+ *
+ * @param pinv pointer to the matrix object that will hold the result or NULL
+ *
+ * @return pointer to the result matrix, or NULL in case the matrix
+ * inversion did not succeed.
+ *
+ * @ingroup ambix_matrix
+ */
+AMBIX_API AMBIX_DEPRECATED
+ambix_matrix_t* ambix_matrix_pinv(const ambix_matrix_t*matrix, ambix_matrix_t*pinv) ;
+/** @endcond */
/** @brief Multiply a matrix with data
* @defgroup ambix_matrix_multiply_data ambix_matrix_multiply_data()
+ * @ingroup ambix_matrix
*
* Multiply a [rows*cols] matrix with an array of [cols*frames] source data to
* get [rows*frames] dest data.
@@ -558,12 +755,19 @@ ambix_matrix_t *ambix_matrix_multiply (const ambix_matrix_t *A, const ambix_matr
* @remark Both source and dest data are arranged column-wise (as is the default
* for interleaved audio-data).
*/
+
/** @brief Multiply a matrix with (32bit floating point) data
*
* @ingroup ambix_matrix_multiply_data
*/
AMBIX_API
ambix_err_t ambix_matrix_multiply_float32(float32_t *dest, const ambix_matrix_t *mtx, const float32_t *source, int64_t frames) ;
+/** @brief Multiply a matrix with (64bit float) data
+ *
+ * @ingroup ambix_matrix_multiply_data
+ */
+AMBIX_API
+ambix_err_t ambix_matrix_multiply_float64(float64_t *dest, const ambix_matrix_t *mtx, const float64_t *source, int64_t frames) ;
/** @brief Multiply a matrix with (32bit signed integer) data
*
* @ingroup ambix_matrix_multiply_data
@@ -577,15 +781,20 @@ ambix_err_t ambix_matrix_multiply_int32(int32_t *dest, const ambix_matrix_t *mtx
AMBIX_API
ambix_err_t ambix_matrix_multiply_int16(int16_t *dest, const ambix_matrix_t *mtx, const int16_t *source, int64_t frames) ;
-/*
+/**
* @section api_utils utility functions
*/
-
+/** @defgroup ambix_utilities ambix_utilities
+ *
+ * @brief utility functions
+ */
/** @brief Calculate the number of channels for a full 3d ambisonics set of a
* given order.
*
* @param order the order of the full set
* @return the number of channels of the full set
+ *
+ * @ingroup ambix_utilities
*/
AMBIX_API
uint32_t ambix_order2channels(uint32_t order) ;
@@ -596,6 +805,8 @@ uint32_t ambix_order2channels(uint32_t order) ;
* @param channels the number of channels of the full set
* @return the order of the full set, or -1 if the channels don't form a full
* set.
+ *
+ * @ingroup ambix_utilities
*/
AMBIX_API
int32_t ambix_channels2order(uint32_t channels) ;
@@ -605,6 +816,8 @@ int32_t ambix_channels2order(uint32_t channels) ;
* @param channels the number of channels supposed to form a full set.
*
* @return TRUE if the channels can form full set, FALSE otherwise.
+ *
+ * @ingroup ambix_utilities
*/
AMBIX_API
int ambix_is_fullset(uint32_t channels) ;
diff --git a/libambix/ambix/exportdefs.h b/libambix/ambix/exportdefs.h
index 5c23515..7a66197 100644
--- a/libambix/ambix/exportdefs.h
+++ b/libambix/ambix/exportdefs.h
@@ -1,4 +1,4 @@
-/* ambix/exportdefs.h - defines for dll import/export -*- c -*-
+/* ambix/exportdefs.h - defines for dll import/export -*- c -*-
Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>
Institute of Electronic Music and Acoustics (IEM),
@@ -22,8 +22,8 @@
*/
/**
- * @file ambix/exportdefs.h
- * @brief export definitions for various compilers
+ * @file ambix/exportdefs.h
+ * @brief export definitions for various compilers
* @details This file is part of libambix
* @author IOhannes m zmölnig <zmoelnig at iem.at>
* @date 2012
diff --git a/libambix/src/Makefile.am b/libambix/src/Makefile.am
index cf821c0..e9a2ede 100644
--- a/libambix/src/Makefile.am
+++ b/libambix/src/Makefile.am
@@ -36,10 +36,18 @@ lib_LTLIBRARIES = libambix.la
# 3. Programs may need to be changed, recompiled, relinked in order to use the
# new version. Bump current, set revision and age to 0.
-libambix_la_LDFLAGS = -version-info 0:0:0 -no-undefined
-libambix_la_CFLAGS = -DAMBIX_INTERNAL
-libambix_la_CFLAGS += -fvisibility=hidden
-libambix_la_LIBADD = $(LIBM)
+libambix_la_CPPFLAGS = $(AM_CPPFLAGS)
+libambix_la_CFLAGS = $(AM_CFLAGS)
+libambix_la_LDFLAGS = $(AM_LDFLAGS)
+
+libambix_la_CPPFLAGS += -DAMBIX_INTERNAL
+if DEBUG
+libambix_la_CPPFLAGS += -DDEBUG=1
+else
+libambix_la_CFLAGS += -fvisibility=hidden
+endif
+libambix_la_LDFLAGS += -version-info 0:0:0 -no-undefined
+libambix_la_LIBADD = $(LIBM)
libambix_la_OBJCFLAGS = $(libambix_la_CFLAGS)
@@ -47,9 +55,10 @@ libambix_la_SOURCES = libambix.c \
adaptor.c \
adaptor_acn.c \
adaptor_fuma.c \
- matrix.c \
+ matrix.c matrix_invert.c \
utils.c \
uuid_chunk.c \
+ marker_region_chunk.c \
private.h
if HAVE_SNDFILE
diff --git a/libambix/src/adaptor.c b/libambix/src/adaptor.c
index 47b1f79..dcc3842 100644
--- a/libambix/src/adaptor.c
+++ b/libambix/src/adaptor.c
@@ -1,6 +1,6 @@
/* adaptor.c - extracting ambisonics data from data using adaptor matrices -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -27,11 +27,14 @@
# include <stdlib.h>
#endif /* HAVE_STDLIB_H */
+static inline uint64_t max_u64(uint64_t a, uint64_t b) {
+ return((a>b)?a:b);
+}
ambix_err_t _ambix_adaptorbuffer_resize(ambix_t*ambix, uint64_t frames, uint16_t itemsize) {
- uint32_t channels=ambix->info.ambichannels + ambix->info.extrachannels;
-
+ uint32_t ambichannels=max_u64(ambix->info.ambichannels,ambix->realinfo.ambichannels);
+ uint32_t extrachannels=max_u64(ambix->info.extrachannels,ambix->realinfo.extrachannels);
+ uint32_t channels=ambichannels + extrachannels;
uint64_t size=channels*frames*itemsize;
-
if(frames<1 || channels<1)
return AMBIX_ERR_SUCCESS;
if(size<1)
@@ -62,7 +65,7 @@ ambix_err_t _ambix_adaptorbuffer_destroy(ambix_t*ambix) {
}
-#define _AMBIX_SPLITADAPTOR(type) \
+#define _AMBIX_SPLITADAPTOR(type) \
ambix_err_t _ambix_splitAdaptor_##type(const type##_t*source, uint32_t sourcechannels, \
uint32_t ambichannels, type##_t*dest_ambi, type##_t*dest_other, \
int64_t frames) { \
@@ -78,6 +81,7 @@ ambix_err_t _ambix_adaptorbuffer_destroy(ambix_t*ambix) {
}
_AMBIX_SPLITADAPTOR(float32);
+_AMBIX_SPLITADAPTOR(float64);
_AMBIX_SPLITADAPTOR(int32);
_AMBIX_SPLITADAPTOR(int16);
@@ -100,7 +104,7 @@ _AMBIX_SPLITADAPTOR(int16);
for(inchan=0; inchan<rawambichannels; inchan++) { \
sum+=mtx[outchan][inchan] * src[inchan]; \
} \
- *dest_ambi++=(type##_t)sum; /* FIXXXME: integer saturation */ \
+ *dest_ambi++=(type##_t)sum; /* FIXXXME: integer saturation */ \
} \
for(inchan=rawambichannels; inchan<sourcechannels; inchan++) \
*dest_other++=src[inchan]; \
@@ -109,6 +113,7 @@ _AMBIX_SPLITADAPTOR(int16);
}
_AMBIX_SPLITADAPTOR_MATRIX(float32);
+_AMBIX_SPLITADAPTOR_MATRIX(float64);
/* both _int16 and _int32 are highly unoptimized!
* LATER: add some fixed point magic to speed things up
*/
@@ -131,7 +136,40 @@ _AMBIX_SPLITADAPTOR_MATRIX(int16);
}
_AMBIX_MERGEADAPTOR(float32);
-
+_AMBIX_MERGEADAPTOR(float64);
_AMBIX_MERGEADAPTOR(int32);
-
_AMBIX_MERGEADAPTOR(int16);
+
+
+//#define _AMBIX_MERGEADAPTOR_MATRIX(type) \
+
+#define _AMBIX_MERGEADAPTOR_MATRIX(type) \
+ ambix_err_t _ambix_mergeAdaptormatrix_##type(const type##_t*ambi_data, const ambix_matrix_t*matrix, \
+ const type##_t*otherdata, uint32_t source2channels, \
+ type##_t*destination, int64_t frames) { \
+ float32_t**mtx=matrix->data; \
+ const uint32_t fullambichannels=matrix->cols; \
+ const uint32_t ambixchannels=matrix->rows; \
+ int64_t f; \
+ for(f=0; f<frames; f++) { \
+ /* encode ambisonics->ambix and store in destination */ \
+ uint32_t outchan, inchan; \
+ const type##_t*src = ambi_data+fullambichannels*f; \
+ for(outchan=0; outchan<ambixchannels; outchan++) { \
+ float32_t sum=0.; \
+ for(inchan=0; inchan<fullambichannels; inchan++) { \
+ sum+=mtx[outchan][inchan] * src[inchan]; \
+ } \
+ *destination++=(type##_t)sum; \
+ } \
+ /* store the otherchannels */ \
+ for(inchan=0; inchan<source2channels; inchan++) \
+ *destination++=*otherdata++; \
+ } \
+ return AMBIX_ERR_SUCCESS; \
+ }
+
+_AMBIX_MERGEADAPTOR_MATRIX(float32);
+_AMBIX_MERGEADAPTOR_MATRIX(float64);
+_AMBIX_MERGEADAPTOR_MATRIX(int32);
+_AMBIX_MERGEADAPTOR_MATRIX(int16);
diff --git a/libambix/src/adaptor_fuma.c b/libambix/src/adaptor_fuma.c
index efb0fc7..7ed25a5 100644
--- a/libambix/src/adaptor_fuma.c
+++ b/libambix/src/adaptor_fuma.c
@@ -1,6 +1,6 @@
/* adaptor_fuma.c - adaptors to/from FUrse-MAlham sets -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -24,15 +24,15 @@
http://members.tripod.com/martin_leese/Ambisonic/B-Format_file_format.html
#chan|fuma| type | xy | z | channels | done
- 3 h horizontal 1 0 WXY X
- 4 f full-sphere 1 1 WXYZ X
- 5 hh horizontal 2 0 WXYUV
- 6 fh mixed-order 2 1 WXYZUV
- 9 ff full-sphere 2 2 WXYZRSTUV X
- 7 hhh horizontal 3 0 WXYUVPQ
- 8 fhh mixed-order 3 1 WXYZUVPQ
- 11 ffh mixed-order 3 2 WXYZRSTUVPQ
- 16 fff full-sphere 3 3 WXYZRSTUVKLMNOPQ X
+ 3 h horizontal 1 0 WXY X
+ 4 f full-sphere 1 1 WXYZ X
+ 5 hh horizontal 2 0 WXYUV
+ 6 fh mixed-order 2 1 WXYZUV
+ 9 ff full-sphere 2 2 WXYZRSTUV X
+ 7 hhh horizontal 3 0 WXYUVPQ
+ 8 fhh mixed-order 3 1 WXYZUVPQ
+ 11 ffh mixed-order 3 2 WXYZRSTUVPQ
+ 16 fff full-sphere 3 3 WXYZRSTUVKLMNOPQ X
*/
#include "private.h"
@@ -68,7 +68,7 @@ fuma2ambix_weightorder(void) {
weight_m=_matrix_diag (weight_m, weights, sizeof(weights)/sizeof(*weights));
order_m =_matrix_router(order_m , order, sizeof(order)/sizeof(*order), 1);
- result_m=ambix_matrix_multiply(weight_m, order_m, result_m);
+ result_m=_ambix_matrix_multiply(weight_m, order_m, result_m);
ambix_matrix_destroy(weight_m);weight_m=NULL;
ambix_matrix_destroy(order_m); order_m=NULL;
@@ -104,7 +104,7 @@ ambix2fuma_weightorder(void) {
weight_m=_matrix_diag (weight_m, weights, sizeof(weights)/sizeof(*weights));
order_m =_matrix_router(order_m , order, sizeof(order)/sizeof(*order), 0);
- result_m=ambix_matrix_multiply(order_m, weight_m, result_m);
+ result_m=_ambix_matrix_multiply(order_m, weight_m, result_m);
ambix_matrix_destroy(weight_m);weight_m=NULL;
ambix_matrix_destroy(order_m); order_m=NULL;
@@ -120,8 +120,8 @@ _matrix_multiply3(ambix_matrix_t*mtx1,
ambix_matrix_t*result) {
ambix_matrix_t*tmp=NULL;
- tmp=ambix_matrix_multiply(mtx1, mtx2, tmp);
- result=ambix_matrix_multiply(tmp, mtx3, result);
+ tmp=_ambix_matrix_multiply(mtx1, mtx2, tmp);
+ result=_ambix_matrix_multiply(tmp, mtx3, result);
ambix_matrix_destroy(tmp);
return result;
diff --git a/libambix/src/coreaudio.m b/libambix/src/coreaudio.m
index 0da629b..8f6dab4 100644
--- a/libambix/src/coreaudio.m
+++ b/libambix/src/coreaudio.m
@@ -496,6 +496,9 @@ int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames) {
int64_t _ambix_readf_float32 (ambix_t*ambix, float32_t*data, int64_t frames) {
return coreaudio_readf(ambix, data, frames, AMBIX_SAMPLEFORMAT_FLOAT32, 4);
}
+int64_t _ambix_readf_float64 (ambix_t*ambix, float64_t*data, int64_t frames) {
+ return coreaudio_readf(ambix, data, frames, AMBIX_SAMPLEFORMAT_FLOAT64, 8);
+}
int64_t coreaudio_writef(ambix_t*ambix, const void*data, int64_t frames, ambix_sampleformat_t sampleformat, UInt32 bytespersample) {
//printf("info:\n");_ambix_print_info(&ambix->info);
@@ -527,6 +530,9 @@ int64_t _ambix_writef_float32 (ambix_t*ambix, const float32_t*data, int64_t fr
//printf("_ambix_writef_float32(%p, %p, %lu)\n", ambix, data);
return coreaudio_writef(ambix, data, frames, AMBIX_SAMPLEFORMAT_FLOAT32, 4);
}
+int64_t _ambix_writef_float64 (ambix_t*ambix, const float64_t*data, int64_t frames) {
+ return coreaudio_writef(ambix, data, frames, AMBIX_SAMPLEFORMAT_FLOAT64, 8);
+}
ambix_err_t _ambix_write_uuidchunk_at(ambix_t*ax, UInt32 index, const void*data, int64_t datasize) {
OSStatus err = AudioFileSetUserData (
PRIVATE(ax)->file,
diff --git a/libambix/src/libambix.c b/libambix/src/libambix.c
index b27d908..ea0b967 100644
--- a/libambix/src/libambix.c
+++ b/libambix/src/libambix.c
@@ -1,6 +1,6 @@
/* libambix.c - AMBIsonics eXchange Library -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -30,9 +30,8 @@
# include <string.h>
#endif /* HAVE_STRING_H */
-
/* forward declarations */
-ambix_err_t _ambix_write_header (ambix_t*ambix);
+ambix_err_t _ambix_write_header (ambix_t*ambix);
static ambix_err_t _check_write_ambixinfo(ambix_info_t*info) {
@@ -56,11 +55,11 @@ static ambix_err_t _check_write_ambixinfo(ambix_info_t*info) {
}
static void _ambix_info_set(ambix_t*ambix
- , ambix_fileformat_t format
- , int32_t otherchannels
- , int32_t ambichannels
- , int32_t fullambichannels
- ) {
+ , ambix_fileformat_t format
+ , int32_t otherchannels
+ , int32_t ambichannels
+ , int32_t fullambichannels
+ ) {
switch(format) {
case AMBIX_NONE:
ambichannels=fullambichannels=0;
@@ -77,10 +76,11 @@ static void _ambix_info_set(ambix_t*ambix
ambix->ambisonics_order=(fullambichannels>0)?ambix_channels2order(fullambichannels):0;
}
-ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_t*ambixinfo) {
+ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_t*ambixinfo) {
ambix_t*ambix=NULL;
ambix_err_t err = AMBIX_ERR_UNKNOWN;
int32_t ambichannels=0, otherchannels=0;
+ int basic2extended = 0; /* writing extended file as basic */
if((AMBIX_WRITE & mode) && (AMBIX_READ & mode)) {
/* RDRW not yet implemented */
@@ -89,21 +89,34 @@ ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_
if(AMBIX_WRITE & mode) {
err=_check_write_ambixinfo(ambixinfo);
- if(err!=AMBIX_ERR_SUCCESS)
- return NULL;
+ if(err!=AMBIX_ERR_SUCCESS) {
+ if (AMBIX_BASIC == ambixinfo->fileformat) {
+ /* the user might actually try to write an EXTENDED file as BASIC:
+ * - ambichannels do not form a full set
+ * - otherchannels>0
+ * LATER add better checks whether this is really the case
+ */
+ ambixinfo->fileformat = AMBIX_EXTENDED;
+ err=_check_write_ambixinfo(ambixinfo);
+ if(err!=AMBIX_ERR_SUCCESS)
+ return NULL;
+ basic2extended = 1;
+ } else
+ return NULL;
+ }
ambichannels=ambixinfo->ambichannels;
otherchannels=ambixinfo->extrachannels;
}
ambix=(ambix_t*)calloc(1, sizeof(ambix_t));
if(AMBIX_ERR_SUCCESS == _ambix_open(ambix, path, mode, ambixinfo)) {
- const ambix_fileformat_t wantformat=ambixinfo->fileformat;
+ const ambix_fileformat_t wantformat=basic2extended?AMBIX_BASIC:ambixinfo->fileformat;
ambix_fileformat_t haveformat;
uint32_t channels = ambix->channels;
/* successfully opened, initialize common stuff... */
if(ambix->is_AMBIX) {
if(AMBIX_WRITE & mode) {
- switch(wantformat) {
+ switch(ambixinfo->fileformat) {
case(AMBIX_NONE):
_ambix_info_set(ambix, AMBIX_NONE, channels, 0, 0);
break;
@@ -112,7 +125,7 @@ ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_
break;
case(AMBIX_EXTENDED):
/* the number of full channels is not clear yet!
- * the user has to call setAdaptorMatrix() first */
+ * the user MUST call set_adaptormatrix() first */
_ambix_info_set(ambix, AMBIX_EXTENDED, otherchannels, ambichannels, 0);
break;
}
@@ -144,6 +157,8 @@ ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_
}
}
}
+ /* retrieve markers/regions/strings*/
+ _ambix_read_markersregions(ambix);
} else {
/* it's not a CAF file.... */
_ambix_info_set(ambix, AMBIX_NONE, channels, 0, 0);
@@ -154,6 +169,14 @@ ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_
ambix->filemode=mode;
memcpy(&ambix->info, &ambix->realinfo, sizeof(ambix->info));
+ if(basic2extended) {
+ /* write EXTENDED files as BASIC */
+#if 0
+ ambix_matrix_init(ambix->info.ambichannels, ambix->realinfo.ambichannels, &ambix->matrix);
+ ambix_matrix_fill(&ambix->matrix, AMBIX_MATRIX_IDENTITY);
+ _ambix_matrix_pinv(&ambix->matrix, &ambix->matrix2);
+#endif
+ }
if(0) {
} else if(AMBIX_BASIC==wantformat && AMBIX_EXTENDED==haveformat) {
ambix->info.fileformat=AMBIX_BASIC;
@@ -176,7 +199,7 @@ ambix_t* ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_
return NULL;
}
-ambix_err_t ambix_close (ambix_t*ambix) {
+ambix_err_t ambix_close (ambix_t*ambix) {
ambix_err_t res=AMBIX_ERR_SUCCESS;
if(NULL==ambix) {
return AMBIX_ERR_INVALID_HANDLE;
@@ -192,6 +215,9 @@ ambix_err_t ambix_close (ambix_t*ambix) {
ambix_matrix_deinit(&ambix->matrix);
ambix_matrix_deinit(&ambix->matrix2);
+ ambix_delete_markers(ambix);
+ ambix_delete_regions(ambix);
+
free(ambix);
ambix=NULL;
return res;
@@ -201,26 +227,111 @@ int64_t ambix_seek (ambix_t* ambix, int64_t frames, int whence) {
return _ambix_seek(ambix, frames, whence);
}
-struct SNDFILE_tag*ambix_get_sndfile (ambix_t*ambix) {
+struct SNDFILE_tag*ambix_get_sndfile (ambix_t*ambix) {
#ifdef HAVE_SNDFILE_H
return _ambix_get_sndfile(ambix);
#endif
return NULL;
}
+uint32_t ambix_get_num_markers (ambix_t*ambix) {
+ return ambix->num_markers;
+}
+uint32_t ambix_get_num_regions(ambix_t *ambix) {
+ return ambix->num_regions;
+}
+ambix_marker_t *ambix_get_marker(ambix_t *ambix, uint32_t id) {
+ if (id < ambix->num_markers)
+ return &ambix->markers[id];
+ else
+ return NULL;
+}
+ambix_region_t *ambix_get_region(ambix_t *ambix, uint32_t id) {
+ if (id < ambix->num_regions)
+ return &ambix->regions[id];
+ else
+ return NULL;
+}
+ambix_err_t ambix_add_marker(ambix_t *ambix, ambix_marker_t *marker) {
+ if(ambix->startedWriting)
+ return AMBIX_ERR_UNKNOWN;
+
+ if (!marker)
+ return AMBIX_ERR_UNKNOWN;
+
+ if (ambix->num_markers > 0)
+ if (ambix->markers)
+ ambix->markers = (ambix_marker_t*)realloc(ambix->markers, (ambix->num_markers+1)*sizeof(ambix_marker_t));
+ else
+ return AMBIX_ERR_UNKNOWN;
+ else
+ ambix->markers = (ambix_marker_t*)calloc(1, sizeof(ambix_marker_t));
+
+ memcpy(&ambix->markers[ambix->num_markers], marker, sizeof(ambix_marker_t));
+ ambix->num_markers += 1;
+
+ ambix->pendingHeaders = 1;
+ return AMBIX_ERR_SUCCESS;
+}
+ambix_err_t ambix_add_region(ambix_t *ambix, ambix_region_t *region) {
+ if(ambix->startedWriting)
+ return AMBIX_ERR_UNKNOWN;
+
+ if (!region)
+ return AMBIX_ERR_UNKNOWN;
+
+ if (ambix->num_regions > 0)
+ if (ambix->regions)
+ ambix->regions = (ambix_region_t*)realloc(ambix->regions, (ambix->num_regions+1)*sizeof(ambix_region_t));
+ else
+ return AMBIX_ERR_UNKNOWN;
+ else
+ ambix->regions = (ambix_region_t*)calloc(1, sizeof(ambix_region_t));
+
+ memcpy(&ambix->regions[ambix->num_regions], region, sizeof(ambix_region_t));
+ ambix->num_regions += 1;
+
+ ambix->pendingHeaders = 1;
+ return AMBIX_ERR_SUCCESS;
+}
+ambix_err_t ambix_delete_markers(ambix_t *ambix) {
+ if (ambix->num_markers > 0) {
+ if (ambix->markers)
+ free (ambix->markers);
+ else
+ return AMBIX_ERR_UNKNOWN;
+
+ ambix->num_markers = 0;
+ return AMBIX_ERR_SUCCESS;
+ }
+
+ return AMBIX_ERR_UNKNOWN;
+}
+ambix_err_t ambix_delete_regions(ambix_t *ambix) {
+ if (ambix->num_regions > 0) {
+ if (ambix->regions)
+ free (ambix->regions);
+ else
+ return AMBIX_ERR_UNKNOWN;
+
+ ambix->num_regions = 0;
+ return AMBIX_ERR_SUCCESS;
+ }
+ return AMBIX_ERR_UNKNOWN;
+}
-const ambix_matrix_t*ambix_get_adaptormatrix (ambix_t*ambix) {
+const ambix_matrix_t*ambix_get_adaptormatrix (ambix_t*ambix) {
if(AMBIX_EXTENDED==ambix->info.fileformat)
return &(ambix->matrix);
return NULL;
}
-ambix_err_t ambix_set_adaptormatrix (ambix_t*ambix, const ambix_matrix_t*matrix) {
+ambix_err_t ambix_set_adaptormatrix (ambix_t*ambix, const ambix_matrix_t*matrix) {
if(0) {
} else if((ambix->filemode & AMBIX_READ ) && (AMBIX_BASIC == ambix->info.fileformat)) {
ambix_matrix_t*mtx=NULL;
/* multiply the matrix with the previous adaptor matrix */
if(AMBIX_EXTENDED == ambix->realinfo.fileformat) {
- mtx=ambix_matrix_multiply(matrix, &ambix->matrix, &ambix->matrix2);
+ mtx=_ambix_matrix_multiply(matrix, &ambix->matrix, &ambix->matrix2);
if(mtx != &ambix->matrix2)
return AMBIX_ERR_UNKNOWN;
ambix->use_matrix=2;
@@ -236,17 +347,48 @@ ambix_err_t ambix_set_adaptormatrix (ambix_t*ambix, const ambix_matrix_t*matrix)
return AMBIX_ERR_UNKNOWN;
}
}
- } else if((ambix->filemode & AMBIX_WRITE) && (AMBIX_EXTENDED == ambix->info.fileformat)) {
+ } else if(ambix->filemode & AMBIX_WRITE) {
+ int basic2extended = AMBIX_BASIC == ambix->info.fileformat;
+ if ((AMBIX_EXTENDED != ambix->info.fileformat) && (AMBIX_BASIC != ambix->info.fileformat))
+ return AMBIX_ERR_UNKNOWN;
/* too late, writing started already */
if(ambix->startedWriting)
return AMBIX_ERR_UNKNOWN;
-
/* check whether the matrix will expand to a full set */
if(!ambix_is_fullset(matrix->rows))
return AMBIX_ERR_INVALID_DIMENSION;
+ if(basic2extended) {
+ ambix_matrix_t*pinv=NULL;
+ /* user requested AMBIX_BASIC, but now sets a matrix...
+ * so we write an ambix-extended format, and create the ambix-channels by
+ * multiplying the full-set with pinv(matrix)
+ */
+
+ /* check whether the reduced set has the same number of channels as we created our file for */
+ if(ambix->realinfo.ambichannels != matrix->cols)
+ return AMBIX_ERR_INVALID_DIMENSION;
+
+ /* check whether the matrix is actually invertible */
+ pinv=_ambix_matrix_pinv(matrix, pinv);
+ if(!pinv)
+ return AMBIX_ERR_INVALID_MATRIX;
+
+ if(!ambix_matrix_copy(pinv, &ambix->matrix2))
+ return AMBIX_ERR_UNKNOWN;
+
+ ambix_matrix_destroy(pinv);
+ }
+
if(!ambix_matrix_copy(matrix, &ambix->matrix))
return AMBIX_ERR_UNKNOWN;
+
+ if(basic2extended) {
+ ambix->realinfo.fileformat=AMBIX_EXTENDED;
+ ambix->info.ambichannels=matrix->rows;
+ ambix->use_matrix=2;
+ }
+
/* ready to write it to file */
ambix->pendingHeaders=1;
return AMBIX_ERR_SUCCESS;
@@ -255,10 +397,11 @@ ambix_err_t ambix_set_adaptormatrix (ambix_t*ambix, const ambix_matrix_t*matrix)
return AMBIX_ERR_UNKNOWN;
}
-ambix_err_t _ambix_write_header (ambix_t*ambix) {
+ambix_err_t _ambix_write_header (ambix_t*ambix) {
void*data=NULL;
if(ambix->filemode & AMBIX_WRITE) {
- if((AMBIX_EXTENDED == ambix->info.fileformat)) {
+ if((AMBIX_EXTENDED == ambix->realinfo.fileformat)) {
+ _ambix_write_markersregions(ambix); // this need to be done in a more elegant way...!
ambix_err_t res;
/* generate UUID-chunk */
uint64_t datalen=_ambix_matrix_to_uuid1(&ambix->matrix, NULL, ambix->byteswap);
@@ -280,8 +423,13 @@ ambix_err_t _ambix_write_header (ambix_t*ambix) {
ambix->pendingHeaders=0;
return res;
+ } else {
+ ambix_err_t res;
+ res = _ambix_write_markersregions(ambix); // this need to be done in a more elegant way...!
+ if(AMBIX_ERR_SUCCESS==res)
+ ambix->pendingHeaders=0;
+ return res;
}
- return AMBIX_ERR_INVALID_FORMAT;
} else
return AMBIX_ERR_INVALID_FILE;
@@ -297,6 +445,7 @@ static ambix_err_t _ambix_check_write(ambix_t*ambix, const void*ambidata, const
if((ambix->realinfo.fileformat==AMBIX_EXTENDED) && !ambix_is_fullset(ambix->matrix.rows))
return AMBIX_ERR_INVALID_DIMENSION;
+ /* write out any headers if we haven't done so yet */
if(ambix->pendingHeaders) {
ambix_err_t res=_ambix_write_header(ambix);
if(AMBIX_ERR_SUCCESS!=res)
@@ -308,21 +457,21 @@ static ambix_err_t _ambix_check_write(ambix_t*ambix, const void*ambidata, const
}
static ambix_err_t _ambix_check_read(ambix_t*ambix, const void*ambidata, const void*otherdata, int64_t frames) {
- /* TODO: add some checks whether writing is feasible
+ /* TODO: add some checks whether reading is feasible
* e.g. format=extended but no (or wrong) matrix present */
ambix->startedReading=1;
return AMBIX_ERR_SUCCESS;
}
-#define AMBIX_READF(type) \
+#define AMBIX_READF(type) \
int64_t ambix_readf_##type (ambix_t*ambix, type##_t*ambidata, type##_t*otherdata, int64_t frames) { \
int64_t realframes; \
type##_t*adaptorbuffer; \
ambix_err_t err= _ambix_check_read(ambix, (const void*)ambidata, (const void*)otherdata, frames); \
- if(AMBIX_ERR_SUCCESS != err) {if (err>0)return -err; return err;} \
+ if(AMBIX_ERR_SUCCESS != err) { return (err>0)?-err:err;} \
err=_ambix_adaptorbuffer_resize(ambix, frames, sizeof(type##_t)); \
- if(AMBIX_ERR_SUCCESS != err) {if (err>0)return -err; return err;} \
+ if(AMBIX_ERR_SUCCESS != err) { return (err>0)?-err:err;} \
adaptorbuffer=(type##_t*)ambix->adaptorbuffer; \
realframes=_ambix_readf_##type(ambix, adaptorbuffer, frames); \
switch(ambix->use_matrix) { \
@@ -338,27 +487,33 @@ static ambix_err_t _ambix_check_read(ambix_t*ambix, const void*ambidata, const v
return realframes; \
}
-#define AMBIX_WRITEF(type) \
+#define AMBIX_WRITEF(type) \
int64_t ambix_writef_##type (ambix_t*ambix, const type##_t *ambidata, const type##_t*otherdata, int64_t frames) { \
type##_t*adaptorbuffer; \
ambix_err_t err= _ambix_check_write(ambix, (const void*)ambidata, (const void*)otherdata, frames); \
- if(AMBIX_ERR_SUCCESS != err) {if (err>0)return -err; return err;} \
+ if(AMBIX_ERR_SUCCESS != err) { return (err>0)?-err:err;} \
err=_ambix_adaptorbuffer_resize(ambix, frames, sizeof(type##_t)); \
- if(AMBIX_ERR_SUCCESS != err) {if (err>0)return -err; return err;} \
+ if(AMBIX_ERR_SUCCESS != err) { return (err>0)?-err:err;} \
adaptorbuffer=(type##_t*)ambix->adaptorbuffer; \
- _ambix_mergeAdaptor_##type(ambidata, ambix->info.ambichannels, otherdata, ambix->info.extrachannels, adaptorbuffer, frames); \
+ switch(ambix->use_matrix) { \
+ case 1: \
+ _ambix_mergeAdaptormatrix_##type(ambidata, &ambix->matrix , otherdata, ambix->info.extrachannels, adaptorbuffer, frames); \
+ break; \
+ case 2: \
+ _ambix_mergeAdaptormatrix_##type(ambidata, &ambix->matrix2, otherdata, ambix->info.extrachannels, adaptorbuffer, frames); \
+ break; \
+ default: \
+ _ambix_mergeAdaptor_##type(ambidata, ambix->info.ambichannels, otherdata, ambix->info.extrachannels, adaptorbuffer, frames); \
+ }; \
return _ambix_writef_##type(ambix, adaptorbuffer, frames); \
}
-
AMBIX_READF(int16);
-
AMBIX_READF(int32);
-
AMBIX_READF(float32);
+AMBIX_READF(float64);
AMBIX_WRITEF(int16);
-
AMBIX_WRITEF(int32);
-
AMBIX_WRITEF(float32);
+AMBIX_WRITEF(float64);
diff --git a/libambix/src/marker_region_chunk.c b/libambix/src/marker_region_chunk.c
new file mode 100644
index 0000000..db6fb21
--- /dev/null
+++ b/libambix/src/marker_region_chunk.c
@@ -0,0 +1,510 @@
+/* marker_region_chunk.c - read/write marker and region chunk -*- c -*-
+
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Institute of Electronic Music and Acoustics (IEM),
+ University of Music and Dramatic Arts, Graz
+
+ Copyright © 2016 Matthias Kronlachner <mail at matthiaskronlachner.com>
+
+ This file is part of libambix
+
+ libambix is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ libambix is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "private.h"
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+/* dense pack all structs */
+/* in a CAF file there are no pad fields to ensure correct byte alignment */
+#pragma pack(push, 1)
+
+/* ------------------------------------------------ */
+/* MARKER CHUNK */
+
+/* this is for the mSMPTETime of CAFMarker */
+typedef struct {
+ unsigned char mHours;
+ unsigned char mMinutes;
+ unsigned char mSeconds;
+ unsigned char mFrames;
+ uint32_t mSubFrameSampleOffset;
+} CAF_SMPTE_Time;
+
+/* this is for the mSMPTE_TimeType of CAFMarkerChunk */
+typedef enum {
+ kCAF_SMPTE_TimeTypeNone = 0,
+ kCAF_SMPTE_TimeType24 = 1,
+ kCAF_SMPTE_TimeType25 = 2,
+ kCAF_SMPTE_TimeType30Drop = 3,
+ kCAF_SMPTE_TimeType30 = 4,
+ kCAF_SMPTE_TimeType2997 = 5,
+ kCAF_SMPTE_TimeType2997Drop = 6,
+ kCAF_SMPTE_TimeType60 = 7,
+ kCAF_SMPTE_TimeType5994 = 8
+} kCAF_SMPTE_TimeType; // uint32_t
+
+/* this is for the mType field of CAFMarker */
+typedef enum {
+ kCAFMarkerType_Generic = 0,
+ kCAFMarkerType_ProgramStart = 'pbeg',
+ kCAFMarkerType_ProgramEnd = 'pend',
+ kCAFMarkerType_TrackStart = 'tbeg',
+ kCAFMarkerType_TrackEnd = 'tend',
+ kCAFMarkerType_Index = 'indx',
+ kCAFMarkerType_RegionStart = 'rbeg',
+ kCAFMarkerType_RegionEnd = 'rend',
+ kCAFMarkerType_RegionSyncPoint = 'rsyc',
+ kCAFMarkerType_SelectionStart = 'sbeg',
+ kCAFMarkerType_SelectionEnd = 'send',
+ kCAFMarkerType_EditSourceBegin = 'cbeg',
+ kCAFMarkerType_EditSourceEnd = 'cend',
+ kCAFMarkerType_EditDestinationBegin = 'dbeg',
+ kCAFMarkerType_EditDestinationEnd = 'dend',
+ kCAFMarkerType_SustainLoopStart = 'slbg',
+ kCAFMarkerType_SustainLoopEnd = 'slen',
+ kCAFMarkerType_ReleaseLoopStart = 'rlbg',
+ kCAFMarkerType_ReleaseLoopEnd = 'rlen'
+} kCAFMarkerType; // uint32_t
+
+/* individual marker struct */
+typedef struct {
+ uint32_t mType;
+ float64_t mFramePosition;
+ uint32_t mMarkerID; // reference to a mStringsIDs for naming
+ CAF_SMPTE_Time mSMPTETime;
+ uint32_t mChannel;
+} CAFMarker;
+
+
+/* chunk holding all markers */
+typedef struct {
+ uint32_t mSMPTE_TimeType;
+ uint32_t mNumberMarkers;
+ CAFMarker* mMarkers;
+} CAFMarkerChunk;
+
+/* ------------------------------------------------ */
+/* REGIONS CHUNK */
+
+/* used for mFlags in CAFRegion */
+typedef enum {
+ kCAFRegionFlag_LoopEnable = 1,
+ kCAFRegionFlag_PlayForward = 2,
+ kCAFRegionFlag_PlayBackward = 4
+} kCAFRegionFlag; // uint32_t
+
+typedef struct {
+ uint32_t mRegionID;
+ uint32_t mFlags;
+ uint32_t mNumberMarkers;
+ CAFMarker* mMarkers;
+} CAFRegion;
+#define SIZEOF_CAFRegion 12
+
+typedef struct {
+ uint32_t mSMPTE_TimeType;
+ uint32_t mNumberRegions;
+ CAFRegion* mRegions;
+} CAFRegionChunk;
+#define SIZEOF_CAFRegionChunk 8
+
+/* ------------------------------------------------ */
+/* STRINGS CHUNK - used as labels for Markers and Regions*/
+
+typedef struct {
+ uint32_t mStringID;
+ int64_t mStringStartByteOffset;
+} CAFStringID;
+
+typedef struct {
+ uint32_t mNumEntries; // The number of strings in the mStrings field.
+ CAFStringID* mStringsIDs; // the marker refers to this id with mMarkerID
+ unsigned char* mStrings; // An array of null-terminated UTF8-encoded text strings.
+} CAFStrings;
+#define SIZEOF_CAFStrings 4
+
+#pragma pack(pop)
+
+union int_chars {
+ uint32_t a;
+ char b[4];
+};
+
+typedef struct {
+ uint32_t num_strings;
+ uint32_t *string_ids;
+ unsigned char **strings;
+} strings_buffer;
+
+void swap_marker_chunk(CAFMarkerChunk* marker_chunk) {
+ _ambix_swap4array(&marker_chunk->mSMPTE_TimeType, 1);
+ _ambix_swap4array(&marker_chunk->mNumberMarkers, 1);
+}
+void swap_marker(CAFMarker* marker) {
+ _ambix_swap4array(&marker->mType, 1);
+ _ambix_swap8array((uint64_t *)&marker->mFramePosition, 1);
+ _ambix_swap4array(&marker->mMarkerID, 1);
+ _ambix_swap4array(&marker->mChannel, 1);
+}
+void swap_region(CAFRegion* region) {
+ _ambix_swap4array(®ion->mRegionID, 1);
+ _ambix_swap4array(®ion->mFlags, 1);
+ _ambix_swap4array(®ion->mNumberMarkers, 1);
+}
+void swap_region_chunk(CAFRegionChunk* region_chunk) {
+ _ambix_swap4array(®ion_chunk->mSMPTE_TimeType, 1);
+ _ambix_swap4array(®ion_chunk->mNumberRegions, 1);
+}
+void swap_stringid(CAFStringID* caf_stringid) {
+ _ambix_swap4array(&caf_stringid->mStringID, 1);
+ _ambix_swap8array((uint64_t *)&caf_stringid->mStringStartByteOffset, 1);
+}
+unsigned char* get_string_from_buffer(strings_buffer* buffer, uint32_t id) {
+ if (buffer) {
+ uint32_t i;
+ for (i=0; i<buffer->num_strings;i++) {
+ if (buffer->string_ids[i] == id)
+ return buffer->strings[i];
+ }
+ return NULL;
+ } else
+ return NULL;
+}
+
+ambix_err_t _ambix_read_markersregions(ambix_t*ambix) {
+ int byteswap = ambix->byteswap;
+ uint32_t chunk_it = 0;
+ uint32_t i;
+
+ int64_t strings_datasize = 1;
+ union int_chars strg_id;
+ strings_buffer mystrings;
+ memset(&mystrings, 0, sizeof(strings_buffer));
+
+ strg_id.b[0] = 's'; strg_id.b[1] = 't'; strg_id.b[2] = 'r'; strg_id.b[3] = 'g';
+
+ /* first parse strings and save into a struct for later usage */
+ while (strings_datasize) {
+ void*strings_data = _ambix_read_chunk(ambix, strg_id.a, chunk_it++, &strings_datasize);
+ if (strings_datasize > SIZEOF_CAFStrings) {
+ uint32_t temp_num_strings = 0;
+ int64_t mstrings_datasize = 0;
+ char *strings_ptr = NULL;
+ CAFStringID* caf_stringid = NULL;
+ CAFStrings* strings_chunk = (CAFStrings*)strings_data;
+ if (byteswap)
+ _ambix_swap4array(&strings_chunk->mNumEntries, 1);
+ if (strings_datasize < (SIZEOF_CAFStrings + strings_chunk->mNumEntries*sizeof(CAFStringID))) {
+ if (strings_data)
+ free(strings_data);
+ break;
+ }
+ temp_num_strings = strings_chunk->mNumEntries;
+ mstrings_datasize = strings_datasize - (SIZEOF_CAFStrings + temp_num_strings*sizeof(CAFStringID));
+ // allocate memory for mystrings
+ if (!mystrings.string_ids) {
+ mystrings.string_ids = malloc((mystrings.num_strings+temp_num_strings)*sizeof(uint32_t));
+ mystrings.strings = malloc((mystrings.num_strings+temp_num_strings)*sizeof(unsigned char*));
+ } else {
+ mystrings.string_ids = realloc(mystrings.string_ids, (mystrings.num_strings+temp_num_strings)*sizeof(uint32_t));
+ mystrings.strings = realloc(mystrings.strings, (mystrings.num_strings+temp_num_strings)*sizeof(unsigned char*));
+ }
+ strings_ptr = strings_data;
+ strings_ptr += (4+temp_num_strings*sizeof(CAFStringID)); // start of mStrings
+ caf_stringid = (CAFStringID*)(&strings_data[4]);
+ for (i=0; i<temp_num_strings; i++) {
+ unsigned char* mString = NULL;
+ uint32_t mString_len = 0;
+ if (byteswap)
+ swap_stringid(&caf_stringid[i]);
+ if (caf_stringid[i].mStringStartByteOffset >= mstrings_datasize)
+ break; // invalid offset!
+ mString = (unsigned char*) (strings_ptr+caf_stringid[i].mStringStartByteOffset);
+ mystrings.string_ids[mystrings.num_strings] = caf_stringid[i].mStringID;
+ mString_len = strlen((const char *)mString);
+ mystrings.strings[mystrings.num_strings] = calloc((mString_len+1), sizeof(unsigned char));
+ memcpy(mystrings.strings[mystrings.num_strings], mString, mString_len*sizeof(unsigned char));
+ mystrings.num_strings++;
+ }
+ }
+ if (strings_data)
+ free(strings_data);
+ }
+
+ /* parse markers */
+ do {
+ int64_t marker_datasize = 1;
+ union int_chars mark_id;
+ chunk_it = 0;
+ mark_id.b[0] = 'm'; mark_id.b[1] = 'a'; mark_id.b[2] = 'r'; mark_id.b[3] = 'k';
+ while (marker_datasize) {
+ void*marker_data = _ambix_read_chunk(ambix, mark_id.a, chunk_it++, &marker_datasize);
+ if (marker_datasize > 2*sizeof(uint32_t)) {
+ CAFMarkerChunk* marker_chunk = (CAFMarkerChunk*)marker_data;
+ unsigned char* bytePtr = NULL;
+ if (byteswap)
+ swap_marker_chunk(marker_chunk);
+ if (marker_datasize < (marker_chunk->mNumberMarkers*(sizeof(CAFMarker)) + 2*sizeof(uint32_t))) {
+ if (marker_data)
+ free(marker_data);
+ break;
+ }
+ bytePtr = (unsigned char*)marker_data;
+ bytePtr += 2*sizeof(uint32_t);
+ for (i=0; i<marker_chunk->mNumberMarkers; i++) {
+ ambix_marker_t new_ambix_marker;
+ CAFMarker *caf_marker = (CAFMarker*)bytePtr;
+ unsigned char* string = NULL;
+ if (byteswap)
+ swap_marker(caf_marker);
+ memset(&new_ambix_marker, 0, sizeof(ambix_marker_t));
+ new_ambix_marker.position = caf_marker->mFramePosition;
+ string = get_string_from_buffer(&mystrings, caf_marker->mMarkerID);
+ if (string) {
+ strncpy(new_ambix_marker.name, (const char *)string, 255);
+ }
+ ambix_add_marker(ambix, &new_ambix_marker);
+ bytePtr += sizeof(CAFMarker);
+ }
+ }
+ if (marker_data)
+ free(marker_data);
+ }
+ } while(0);
+
+ /* parse regions */
+ do {
+ void* region_data = NULL;
+ int64_t region_datasize = 1;
+ union int_chars regn_id;
+ regn_id.b[0] = 'r'; regn_id.b[1] = 'e'; regn_id.b[2] = 'g'; regn_id.b[3] = 'n';
+
+ chunk_it = 0;
+
+ while (region_datasize) {
+ region_data = _ambix_read_chunk(ambix, regn_id.a, chunk_it++, ®ion_datasize);
+ if (region_datasize > 2*sizeof(uint32_t)) {
+ int64_t data_read = 0;
+ unsigned char* bytePtr = NULL;
+ CAFRegionChunk* region_chunk = (CAFRegionChunk*)region_data;
+ if (byteswap)
+ swap_region_chunk(region_chunk);
+ if (region_datasize < (region_chunk->mNumberRegions*(SIZEOF_CAFRegion+sizeof(CAFMarker)) + SIZEOF_CAFRegionChunk)) {
+ if (region_data)
+ free(region_data);
+ break;
+ }
+ bytePtr = (unsigned char*)region_data;
+ data_read += 2*sizeof(uint32_t); // SIZEOF_CAFRegionChunk
+ for (i=0; i<region_chunk->mNumberRegions; i++) {
+ uint32_t j;
+ ambix_region_t new_ambix_region;
+ CAFRegion *caf_region = NULL;
+ if (region_datasize < data_read + SIZEOF_CAFRegion)
+ break;
+ caf_region = (CAFRegion*)&bytePtr[data_read];
+ if (byteswap)
+ swap_region(caf_region);
+ memset(&new_ambix_region, 0, sizeof(ambix_region_t));
+ /* iterate over all markers and find startMarker and endMarker */
+ data_read += SIZEOF_CAFRegion;
+ for (j=0; j<caf_region->mNumberMarkers; j++) {
+ CAFMarker *caf_marker = NULL;
+ if (region_datasize < data_read + sizeof(CAFMarker))
+ break;
+ caf_marker = (CAFMarker*)&bytePtr[data_read];
+ if (byteswap)
+ swap_marker(caf_marker);
+ if (caf_marker->mType == kCAFMarkerType_RegionStart) {
+ unsigned char* string = NULL;
+ new_ambix_region.start_position = caf_marker->mFramePosition;
+ string = get_string_from_buffer(&mystrings, caf_marker->mMarkerID);
+ if (string)
+ strncpy(new_ambix_region.name, (const char *)string, 255);
+ }
+ else if (caf_marker->mType == kCAFMarkerType_RegionEnd)
+ new_ambix_region.end_position = caf_marker->mFramePosition;
+ data_read += sizeof(CAFMarker);
+ }
+ ambix_add_region(ambix, &new_ambix_region);
+ }
+ }
+ if (region_data)
+ free(region_data);
+ }
+ } while(0);
+
+ /* free allocated strings data */
+ if (mystrings.string_ids)
+ free(mystrings.string_ids);
+ for (i=0; i<mystrings.num_strings; i++) {
+ if (mystrings.strings[i])
+ free(mystrings.strings[i]);
+ }
+ if (mystrings.strings)
+ free(mystrings.strings);
+ memset(&mystrings, 0, sizeof(strings_buffer));
+
+ return AMBIX_ERR_UNKNOWN;
+}
+
+void add_string_to_data(int id, unsigned char *byte_ptr_stringid, char *name, int64_t *byteoffset_strings, unsigned char *byte_ptr_strings, uint32_t *datasize_strings, int byteswap) {
+ /* handle the string */
+ CAFStringID* string_id = (CAFStringID*)byte_ptr_stringid;
+ uint32_t name_len = strlen((const char *)name);
+ string_id->mStringID = id;
+ string_id->mStringStartByteOffset = *byteoffset_strings;
+ memcpy(byte_ptr_strings, name, name_len*sizeof(char));
+ byte_ptr_strings[name_len] = 0; // set the last char to NUL
+ *byteoffset_strings += (name_len+1);
+ *datasize_strings += (name_len+1);
+ if (byteswap)
+ swap_stringid(string_id);
+}
+
+ambix_err_t _ambix_write_markersregions(ambix_t*ambix) {
+ uint32_t i;
+ int byteswap = ambix->byteswap;
+
+ void *strings_data = NULL;
+ uint32_t num_strings = ambix->num_markers+ambix->num_regions;
+ uint32_t datasize_strings = 0;
+ unsigned char* byte_ptr_strings = NULL;
+ unsigned char* byte_ptr_stringid = NULL;
+ int64_t byteoffset_strings = 0;
+
+ void *marker_data = NULL;
+ uint32_t datasize_markers = 0;
+
+ /* reserve space for strings */
+ if (num_strings > 0) {
+ CAFStrings *strings_chunk = NULL;
+ datasize_strings = sizeof(uint32_t)+num_strings*sizeof(CAFStringID);
+ strings_data = calloc(1, datasize_strings+256); // reserve a fixed space of 256 bytes for each string
+ byte_ptr_strings = (unsigned char*)strings_data;
+ byte_ptr_strings += (sizeof(uint32_t)+num_strings*(sizeof(CAFStringID)));
+ byte_ptr_stringid = (unsigned char*)strings_data;
+ byte_ptr_stringid += sizeof(uint32_t);
+ strings_chunk = (CAFStrings*)strings_data;
+ strings_chunk->mNumEntries = num_strings;
+ if (byteswap)
+ _ambix_swap4array(&strings_chunk->mNumEntries, 1);
+ }
+ /* markers */
+ if (ambix->num_markers > 0) {
+ CAFMarkerChunk* marker_chunk = NULL;
+ unsigned char* bytePtr = NULL;
+ datasize_markers = 2*sizeof(uint32_t) + ambix->num_markers*sizeof(CAFMarker);
+ marker_data = calloc(1, datasize_markers);
+ bytePtr = (unsigned char*)marker_data;
+
+ marker_chunk = (CAFMarkerChunk*)marker_data;
+ marker_chunk->mSMPTE_TimeType = kCAF_SMPTE_TimeTypeNone;
+ marker_chunk->mNumberMarkers = ambix->num_markers;
+ if (byteswap)
+ swap_marker_chunk(marker_chunk);
+
+ // offset the data pointer by 2*uint32_t to point to start of markers
+ bytePtr += 2*sizeof(uint32_t);
+ for (i=0; i<ambix->num_markers;i++) {
+ CAFMarker* new_marker = (CAFMarker*) bytePtr;
+ new_marker->mType = kCAFMarkerType_Generic;
+ new_marker->mFramePosition = ambix->markers[i].position;
+ new_marker->mMarkerID = i+1; // string ID -> 1...num_markers
+ new_marker->mChannel = 0; // 0 means for all channels
+ if (byteswap) {
+ swap_marker(new_marker);
+ }
+ bytePtr += sizeof(CAFMarker);
+
+ add_string_to_data(i+1, byte_ptr_stringid, ambix->markers[i].name, &byteoffset_strings, byte_ptr_strings, &datasize_strings, byteswap);
+ byte_ptr_strings += (strlen((const char*)ambix->markers[i].name)+1);
+ byte_ptr_stringid += sizeof(CAFStringID);
+ }
+ }
+
+ /* regions */
+ // a region consists of 2 markers (start,end) and region chunk
+ uint32_t datasize_regions = 2*sizeof(uint32_t) + ambix->num_regions*(SIZEOF_CAFRegion + 2*sizeof(CAFMarker));
+ void *region_data = calloc(1, datasize_regions);
+ CAFRegionChunk* region_chunk = (CAFRegionChunk*)region_data;
+ unsigned char* byte_ptr_regions = (unsigned char*)region_data;
+ region_chunk->mSMPTE_TimeType = kCAF_SMPTE_TimeTypeNone;
+ region_chunk->mNumberRegions = ambix->num_regions;
+ if (byteswap)
+ swap_region_chunk(region_chunk);
+ // offset the data pointer by 2*uint32_t to point to start of mRegions
+ byte_ptr_regions += 2*sizeof(uint32_t);
+ for (i=0; i<ambix->num_regions;i++) {
+ CAFRegion *new_region = NULL;
+ CAFMarker *start_marker = NULL, *end_marker = NULL;
+
+ /* region */
+ new_region = (CAFRegion*) byte_ptr_regions;
+ new_region->mRegionID = i+1; // does not have a connection with a string
+ new_region->mFlags = 0;
+ new_region->mNumberMarkers = 2; // start, end marker
+
+ /* start region marker */
+ byte_ptr_regions += SIZEOF_CAFRegion; // offset pointer to start marker
+ start_marker = (CAFMarker*)byte_ptr_regions;// &((new_region->mMarkers)[0]);
+ start_marker->mType = kCAFMarkerType_RegionStart;
+ start_marker->mFramePosition = ambix->regions[i].start_position;
+ start_marker->mMarkerID = ambix->num_markers+i+1; // string ID -> num_markers+1...num_markers+num_regions
+ start_marker->mChannel = 0; // 0 means for all channels
+
+ /* end region marker */
+ byte_ptr_regions += sizeof(CAFMarker); // offset pointer to end marker
+ end_marker = (CAFMarker*)byte_ptr_regions; // &new_region->mMarkers[1];
+ end_marker->mType = kCAFMarkerType_RegionEnd;
+ end_marker->mFramePosition = ambix->regions[i].end_position;
+ end_marker->mMarkerID = ambix->num_markers+i+1; // string ID -> num_markers+1...num_markers+num_regions
+ end_marker->mChannel = 0; // 0 means for all channels
+ if (byteswap) {
+ swap_region(new_region);
+ swap_marker(start_marker);
+ swap_marker(end_marker);
+ }
+ byte_ptr_regions += sizeof(CAFMarker);
+
+ add_string_to_data(ambix->num_markers+i+1, byte_ptr_stringid, ambix->regions[i].name, &byteoffset_strings, byte_ptr_strings, &datasize_strings, byteswap);
+ byte_ptr_strings += (strlen((const char*)ambix->regions[i].name)+1);
+ byte_ptr_stringid += sizeof(CAFStringID);
+ }
+
+ /* add the chunk data */
+ do {
+ union int_chars mark_id, regn_id, strg_id;
+
+ mark_id.b[0] = 'm'; mark_id.b[1] = 'a'; mark_id.b[2] = 'r'; mark_id.b[3] = 'k';
+ _ambix_write_chunk(ambix, mark_id.a, marker_data, datasize_markers);
+ free(marker_data);
+
+ regn_id.b[0] = 'r'; regn_id.b[1] = 'e'; regn_id.b[2] = 'g'; regn_id.b[3] = 'n';
+ _ambix_write_chunk(ambix, regn_id.a, region_data, datasize_regions);
+ free(region_data);
+
+ strg_id.b[0] = 's'; strg_id.b[1] = 't'; strg_id.b[2] = 'r'; strg_id.b[3] = 'g';
+ _ambix_write_chunk(ambix, strg_id.a, strings_data, datasize_strings);
+ free(strings_data);
+ } while(0);
+ return AMBIX_ERR_SUCCESS;
+}
diff --git a/libambix/src/matrix.c b/libambix/src/matrix.c
index 0edb457..d042dee 100644
--- a/libambix/src/matrix.c
+++ b/libambix/src/matrix.c
@@ -1,6 +1,6 @@
/* matrix.c - Matrix handling -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -80,7 +80,7 @@ ambix_matrix_init(uint32_t rows, uint32_t cols, ambix_matrix_t*orgmtx) {
}
ambix_matrix_t*
-ambix_matrix_transpose(const ambix_matrix_t*matrix, ambix_matrix_t*xirtam) {
+_ambix_matrix_transpose(const ambix_matrix_t*matrix, ambix_matrix_t*xirtam) {
uint32_t rows, cols, r, c;
float32_t**mtx, **xtm;
if(!xirtam)
@@ -132,6 +132,7 @@ _ambix_matrix_fill_data_byteswapped(ambix_matrix_t*mtx, const number32_t*data) {
return AMBIX_ERR_SUCCESS;
}
+#if 0
ambix_err_t
ambix_matrix_fill_data_transposed(ambix_matrix_t*mtx, const float32_t*data, int byteswap) {
ambix_err_t err=AMBIX_ERR_SUCCESS;
@@ -146,7 +147,7 @@ ambix_matrix_fill_data_transposed(ambix_matrix_t*mtx, const float32_t*data, int
err=ambix_matrix_fill_data(xtm, data);
if(AMBIX_ERR_SUCCESS==err) {
- ambix_matrix_t*resu=ambix_matrix_transpose(mtx, xtm);
+ ambix_matrix_t*resu=_ambix_matrix_transpose(mtx, xtm);
if(!resu)
err=AMBIX_ERR_UNKNOWN;
}
@@ -154,6 +155,7 @@ ambix_matrix_fill_data_transposed(ambix_matrix_t*mtx, const float32_t*data, int
ambix_matrix_destroy(xtm);
return err;
}
+#endif
@@ -183,7 +185,7 @@ ambix_matrix_copy(const ambix_matrix_t*src, ambix_matrix_t*dest) {
ambix_matrix_t*
-ambix_matrix_multiply(const ambix_matrix_t*left, const ambix_matrix_t*right, ambix_matrix_t*dest) {
+_ambix_matrix_multiply(const ambix_matrix_t*left, const ambix_matrix_t*right, ambix_matrix_t*dest) {
uint32_t r, c, rows, cols, common;
float32_t**ldat,**rdat,**ddat;
float32_t lv, rv;
@@ -325,7 +327,7 @@ ambix_matrix_fill(ambix_matrix_t*matrix, ambix_matrixtype_t typ) {
counter++;
}
}
- matrix=_matrix_diag(matrix, weights, rows);
+ matrix=_matrix_diag(matrix, weights, rows);
free(weights);
}
break;
@@ -335,36 +337,89 @@ ambix_matrix_fill(ambix_matrix_t*matrix, ambix_matrixtype_t typ) {
return matrix;
}
-ambix_err_t ambix_matrix_multiply_float32(float32_t*dest, const ambix_matrix_t*matrix, const float32_t*source, int64_t frames) {
- float32_t**mtx=matrix->data;
- const uint32_t outchannels=matrix->rows;
- const uint32_t inchannels=matrix->cols;
- int64_t frame;
- float32_t*dst=dest;
- const float32_t*src=source;
- for(frame=0; frame<frames; frame++) {
- uint32_t outchan;
- for(outchan=0; outchan<outchannels; outchan++) {
- double sum=0.;
- uint32_t inchan;
- // printf("..output:%d @ %d\n", (int)outchan, (int)frame);
- for(inchan=0; inchan<inchannels; inchan++) {
- double scale=mtx[outchan][inchan];
- double in=src[frame*inchannels+inchan];
- // printf("....%f[%d|%d]*%f\n", (float)scale, (int)outchan, (int)inchan, (float)in);
- sum+=scale*in;
+ambix_matrix_t*
+_ambix_matrix_pinv(const ambix_matrix_t*A, ambix_matrix_t*P) {
+ const float32_t eps=1e-7;
+ ambix_matrix_t *result = NULL;
+
+ /* try cholesky inversion */
+ result=_ambix_matrix_pinvert_cholesky(A, P, eps);
+ if(result)
+ return result;
+
+ /* if that fails (should never happen), fall back to gauss-jordan */
+ if (A->rows==A->cols) {
+ ambix_matrix_t*Ax = ambix_matrix_copy(A, NULL);
+ result = _ambix_matrix_invert_gaussjordan(Ax, P, eps); // do normal inverse if square matrix
+ if(Ax) ambix_matrix_destroy(Ax);
+ } else {
+ /* we'll have to do the pseudo-inverse:
+ * P=A'*inv(A*A') if row<col
+ * P=inv(A'*A)*A' if col<row
+ */
+ ambix_matrix_t *At = NULL;
+ ambix_matrix_t *temp = NULL;
+ ambix_matrix_t *temp2 = NULL;
+ do {
+ At = _ambix_matrix_transpose(A, At);
+
+ if (A->rows > A->cols) {
+ temp = _ambix_matrix_multiply(At, A, NULL);
+ if (!temp)break;
+ temp2 = _ambix_matrix_invert_gaussjordan(temp, temp2, eps);
+ if (!temp2)break;
+
+ result = _ambix_matrix_multiply(temp2, At, P);
+ } else {
+ temp = _ambix_matrix_multiply(A, At, NULL);
+ if (!temp)break;
+ temp2 = _ambix_matrix_invert_gaussjordan(temp, temp2, eps);
+ if (!temp2)break;
+
+ result = _ambix_matrix_multiply(At, temp2, P);
}
- dst[frame*outchannels+outchan]=(float32_t)sum;
- }
+ } while (0);
+ if(At) ambix_matrix_destroy(At);
+ if(temp) ambix_matrix_destroy(temp);
+ if(temp2)ambix_matrix_destroy(temp2);
}
- return AMBIX_ERR_SUCCESS;
+
+ return result;
}
-#define MTXMULTIPLY_DATA_INT(typ) \
+
+#define MTXMULTIPLY_DATA_FLOAT(typ) \
ambix_err_t ambix_matrix_multiply_##typ(typ##_t*dest, const ambix_matrix_t*matrix, const typ##_t*source, int64_t frames) { \
float32_t**mtx=matrix->data; \
const uint32_t outchannels=matrix->rows; \
const uint32_t inchannels=matrix->cols; \
int64_t frame; \
+ typ##_t*dst=dest; \
+ const typ##_t*src=source; \
+ for(frame=0; frame<frames; frame++) { \
+ uint32_t outchan; \
+ for(outchan=0; outchan<outchannels; outchan++) { \
+ double sum=0.; \
+ uint32_t inchan; \
+ for(inchan=0; inchan<inchannels; inchan++) { \
+ double scale=mtx[outchan][inchan]; \
+ double in=src[frame*inchannels+inchan]; \
+ sum+=scale*in; \
+ } \
+ dst[frame*outchannels+outchan]=(typ##_t)sum; \
+ } \
+ } \
+ return AMBIX_ERR_SUCCESS; \
+ } \
+
+MTXMULTIPLY_DATA_FLOAT(float32);
+MTXMULTIPLY_DATA_FLOAT(float64);
+
+#define MTXMULTIPLY_DATA_INT(typ) \
+ ambix_err_t ambix_matrix_multiply_##typ(typ##_t*dest, const ambix_matrix_t*matrix, const typ##_t*source, int64_t frames) { \
+ float32_t**mtx=matrix->data; \
+ const uint32_t outchannels=matrix->rows; \
+ const uint32_t inchannels=matrix->cols; \
+ int64_t frame; \
for(frame=0; frame<frames; frame++) { \
uint32_t outchan; \
typ##_t*dst=dest+frame; \
@@ -377,7 +432,7 @@ ambix_err_t ambix_matrix_multiply_float32(float32_t*dest, const ambix_matrix_t*m
double in=src[inchan*frames]; \
sum+=scale * in; \
} \
- dst[frames*outchan]=(typ##_t)(sum); /* FIXXXME: saturation */ \
+ dst[frames*outchan]=(typ##_t)(sum); /* FIXXXME: saturation */ \
} \
} \
return AMBIX_ERR_SUCCESS; \
@@ -450,3 +505,13 @@ ambix_matrix_t*_matrix_permutate(ambix_matrix_t*matrix, const float32_t*route, i
}
return matrix;
}
+
+
+ambix_matrix_t*
+ambix_matrix_pinv(const ambix_matrix_t*A, ambix_matrix_t*P) {
+ return _ambix_matrix_pinv(A, P);
+}
+ambix_matrix_t*
+ambix_matrix_multiply(const ambix_matrix_t*left, const ambix_matrix_t*right, ambix_matrix_t*dest) {
+ return _ambix_matrix_multiply(left, right, dest);
+}
diff --git a/libambix/src/matrix_invert.c b/libambix/src/matrix_invert.c
new file mode 100644
index 0000000..8012693
--- /dev/null
+++ b/libambix/src/matrix_invert.c
@@ -0,0 +1,258 @@
+/* matrix_invert.c - utilities for matrix inversion -*- c -*-
+
+ Copyright © 2016 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Institute of Electronic Music and Acoustics (IEM),
+ University of Music and Dramatic Arts, Graz
+
+ This file is part of libambix
+
+ libambix is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ libambix is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "private.h"
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif /* HAVE_STDLIB_H */
+
+#include <math.h>
+
+/**
+ * simple matrix inversion of square matrices, using Gauss-Jordan
+ */
+/* this modifies the input matrix! */
+ambix_matrix_t*
+_ambix_matrix_invert_gaussjordan(ambix_matrix_t*input, ambix_matrix_t*inverse, float32_t eps)
+{
+ ambix_matrix_t*inverse_org = inverse;
+ int i, k;
+ float32_t *a1, *b1, *a2, *b2;
+
+ int errors=0; /* error counter */
+
+ if(input==0)
+ { // no input matrix
+ return NULL;
+ }
+
+ if (input->cols != input->rows)
+ {// matrix is not squared
+ return NULL;
+ }
+
+ int col=input->cols, row=input->rows;
+
+ /* 1a reserve space for the inverted matrix */
+ if(!inverse)
+ {
+ inverse=ambix_matrix_init(row, col, NULL);
+ }
+
+ float32_t **original=input->data;
+ float32_t **inverted=inverse->data;
+
+
+ /* 1b make an eye-shaped float-buf for B */
+ ambix_matrix_fill(inverse, AMBIX_MATRIX_IDENTITY);
+
+ /* 2. do the Gauss-Jordan */
+ //printf("GaussJordan\n");
+ for (k=0; k<row; k++) {
+ /* adjust current row */
+ float32_t diagel = original[k][k];
+ float32_t i_diagel = 0;
+ if(diagel>-eps && diagel<eps)
+ errors++;
+ else
+ i_diagel = 1./diagel;
+
+ /* normalize current row (set the diagonal-element to 1 */
+ for (i=0; i < row; i++)
+ {
+ original[k][i] *= i_diagel;
+ inverted[k][i] *= i_diagel;
+ }
+
+ /* eliminate the k-th element in each row by adding the weighted normalized row */
+ for (i=0; i < row; i++)
+ {
+ if (i-k)
+ {
+ float32_t f =-original[i][k];
+ int j;
+ for (j=row-1; j >= 0; j--) {
+ original[i][j] += f * original[k][j];
+ inverted[i][j] += f * inverted[k][j];
+ }
+ }
+ }
+ }
+
+ if (errors > 0) {
+ if(inverse != inverse_org)
+ /* if the 'inverse' was locally allocated, free it */
+ ambix_matrix_destroy(inverse);
+ inverse=NULL;
+ }
+
+ return inverse;
+}
+
+/**
+ * matrix inversion using the Cholesky algorithm
+ *
+ * the functions _am_cholesky2_decomp and _am_cholesky_2_inverse
+ * have been extracted from the "Survival" package for R.
+ * https://cran.r-project.org/web/packages/survival/index.html
+ *
+ * They are distributed under the Lesser Gnu General Public License 2 (or greater)
+ * and are
+ * © 2009 Thomas Lumley
+ * © 2009-2016 Terry M Therneau
+ */
+/** cholesky2 decomposition
+ * \author © -2009 Thomas Lumley
+ * \author © 2009-2016 Terry M Therneau <therneau.terry at mayo.edu>
+ * \copyright LGPL >= 2
+ * \note origin survival 2.39-3 https://cran.r-project.org/web/packages/survival/index.html
+ */
+static int _am_cholesky2_decomp(ambix_matrix_t*mtx, float32_t toler)
+{
+ const uint32_t columns = mtx->cols;
+ float32_t**matrix= mtx->data;
+ float32_t temp;
+ int i, j, k;
+ float32_t eps, pivot;
+ int rank;
+ int nonneg;
+
+ nonneg = 1;
+ eps = 0;
+ for (i = 0; i < columns; i++) {
+ if (matrix[i][i] > eps)
+ eps = matrix[i][i];
+ for (j = (i + 1); j < columns; j++)
+ matrix[j][i] = matrix[i][j];
+ }
+ eps *= toler;
+
+ rank = 0;
+ for (i = 0; i < columns; i++) {
+ pivot = matrix[i][i];
+ if (pivot < eps) {
+ matrix[i][i] = 0;
+ if (pivot < -8 * eps)
+ nonneg = -1;
+ } else {
+ rank++;
+ for (j = (i + 1); j < columns; j++) {
+ temp = matrix[j][i] / pivot;
+ matrix[j][i] = temp;
+ matrix[j][j] -= temp * temp * pivot;
+ for (k = (j + 1); k < columns; k++)
+ matrix[k][j] -= temp * matrix[k][i];
+ }
+ }
+ }
+ return (rank * nonneg);
+}
+/* inplace inverse */
+/** inplace inversion of a cholesky2 decomposed matrix
+ * \author © -2009 Thomas Lumley
+ * \author © 2009-2016 Terry M Therneau <therneau.terry at mayo.edu>
+ * \copyright LGPL >= 2
+ * \note origin survival 2.39-3 https://cran.r-project.org/web/packages/survival/index.html
+ */
+static void _am_cholesky2_inverse(ambix_matrix_t*mtx)
+{
+ const int columns = mtx->cols;;
+ float32_t**matrix = mtx->data;
+ register float32_t temp;
+ register int i, j, k;
+
+ /*
+ ** invert the cholesky in the lower triangle
+ ** take full advantage of the cholesky's diagonal of 1's
+ */
+ for (i = 0; i < columns; i++) {
+ if (matrix[i][i] > 0) {
+ matrix[i][i] = 1 / matrix[i][i]; /*this line inverts D */
+ for (j = (i + 1); j < columns; j++) {
+ matrix[j][i] = -matrix[j][i];
+ for (k = 0; k < i; k++) /* sweep operator */
+ matrix[j][k] += matrix[j][i] * matrix[i][k];
+ }
+ }
+ }
+
+ /*
+ ** lower triangle now contains inverse of cholesky
+ ** calculate F'DF (inverse of cholesky decomp process) to get inverse
+ ** of original matrix
+ */
+ for (i = 0; i < columns; i++) {
+ if (matrix[i][i] == 0) { /* singular row */
+ for (j = 0; j < i; j++)
+ matrix[j][i] = 0;
+ for (j = i; j < columns; j++)
+ matrix[i][j] = 0;
+ } else {
+ for (j = (i + 1); j < columns; j++) {
+ temp = matrix[j][i] * matrix[j][j];
+ if (j != i)
+ matrix[i][j] = temp;
+ for (k = i; k < j; k++)
+ matrix[i][k] += temp * matrix[j][k];
+ }
+ }
+ }
+
+ // ugly fix to return only inverse
+ for (i = 1; i < columns; i++)
+ for (j = 0; j < i; j++)
+ matrix[i][j] = matrix[j][i];
+}
+
+/*
+ * calculate the inverse of any (rectangular) real-valued matrix using cholesky decomposition
+ */
+ambix_matrix_t*
+_ambix_matrix_pinvert_cholesky(const ambix_matrix_t*input, ambix_matrix_t*inverse, float32_t tolerance) {
+ /* (rows>cols)?(inv(x'*x)*x'):(x'*inv(x*x')) */
+ float32_t toler = tolerance;
+ ambix_matrix_t*trans = _ambix_matrix_transpose(input, 0);
+ ambix_matrix_t*chinv=0;
+ ambix_matrix_t*result=0;
+ do {
+ if(!trans)break;
+ if(input->rows > input->cols) {
+ chinv=_ambix_matrix_multiply(trans, input, chinv);
+ if(!chinv)break;
+ _am_cholesky2_decomp(chinv, toler);
+ _am_cholesky2_inverse(chinv);
+ result=_ambix_matrix_multiply(chinv, trans, inverse);
+ } else {
+ chinv=_ambix_matrix_multiply(input, trans, chinv);
+ if(!chinv)break;
+ _am_cholesky2_decomp(chinv, toler);
+ _am_cholesky2_inverse(chinv);
+ result=_ambix_matrix_multiply(trans, chinv, inverse);
+ }
+ } while(0);
+ if(trans)ambix_matrix_destroy(trans);
+ if(chinv)ambix_matrix_destroy(chinv);
+
+ return result;
+}
diff --git a/libambix/src/null.c b/libambix/src/null.c
index 19eebde..5a4d455 100644
--- a/libambix/src/null.c
+++ b/libambix/src/null.c
@@ -22,15 +22,15 @@
#include "private.h"
-ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo) {
+ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo) {
return AMBIX_ERR_INVALID_FILE;
}
-ambix_err_t _ambix_close (ambix_t*ambix) {
+ambix_err_t _ambix_close (ambix_t*ambix) {
return AMBIX_ERR_INVALID_FILE;
}
-struct SNDFILE_tag*_ambix_get_sndfile (ambix_t*ambix) {
+struct SNDFILE_tag*_ambix_get_sndfile (ambix_t*ambix) {
return 0;
}
@@ -43,6 +43,9 @@ int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames) {
int64_t _ambix_readf_float32 (ambix_t*ambix, float32_t*data, int64_t frames) {
return -1;
}
+int64_t _ambix_readf_float64 (ambix_t*ambix, float64_t*data, int64_t frames) {
+ return -1;
+}
int64_t _ambix_writef_int16 (ambix_t*ambix, const int16_t*data, int64_t frames) {
return -1;
@@ -53,6 +56,9 @@ int64_t _ambix_writef_int32 (ambix_t*ambix, const int32_t*data, int64_t frames
int64_t _ambix_writef_float32 (ambix_t*ambix, const float32_t*data, int64_t frames) {
return -1;
}
+int64_t _ambix_writef_float64 (ambix_t*ambix, const float64_t*data, int64_t frames) {
+ return -1;
+}
ambix_err_t _ambix_write_uuidchunk(ambix_t*ax, const void*data, int64_t datasize) {
return AMBIX_ERR_UNKNOWN;
}
diff --git a/libambix/src/private.h b/libambix/src/private.h
index a340c18..404aeb5 100644
--- a/libambix/src/private.h
+++ b/libambix/src/private.h
@@ -89,6 +89,15 @@ struct ambix_t_struct {
/** ambisonics order of the full set */
uint32_t ambisonics_order;
+ /** the number of stored markers */
+ uint32_t num_markers;
+ /** storage for markers */
+ ambix_marker_t *markers;
+ /** the number of stored regions */
+ uint32_t num_regions;
+ /** storage for regions */
+ ambix_region_t *regions;
+
/** whether we already started reading samples */
int startedReading;
/** whether we already started writing samples */
@@ -143,6 +152,10 @@ struct SNDFILE_tag*_ambix_get_sndfile (ambix_t*ambix);
* @return number of sample frames successfully read
*/
int64_t _ambix_readf_float32 (ambix_t*ambix, float32_t*data, int64_t frames);
+/** @see _ambix_readf_float64
+ * @remark this operates on 64bit float data (double)
+ */
+int64_t _ambix_readf_float64 (ambix_t*ambix, float64_t*data, int64_t frames);
/** @see _ambix_readf_float32
* @remark this operates on 32bit integer data
*/
@@ -160,6 +173,10 @@ int64_t _ambix_readf_int16 (ambix_t*ambix, int16_t*data, int64_t frames);
*/
int64_t _ambix_writef_float32 (ambix_t*ambix, const float32_t*data, int64_t frames);
/** @see _ambix_writef_float32
+ * @remark this operates on 64bit float data
+ */
+int64_t _ambix_writef_float64 (ambix_t*ambix, const float64_t*data, int64_t frames);
+/** @see _ambix_writef_float32
* @remark this operates on 32bit integer data
*/
int64_t _ambix_writef_int32 (ambix_t*ambix, const int32_t*data, int64_t frames);
@@ -209,6 +226,37 @@ uint64_t _ambix_matrix_to_uuid1(const ambix_matrix_t*matrix, void*data, int byte
*/
ambix_err_t _ambix_write_uuidchunk(ambix_t*ax, const void*data, int64_t datasize);
+/** @brief read marker, region and corresponding strings chunk from file
+ * @param ambix valid ambix handle
+ * @return error code indicating success
+ */
+ambix_err_t _ambix_read_markersregions(ambix_t*ax);
+/** @brief write marker, region and corresponding strings chunk to file
+ * @param ambix valid ambix handle
+ * @return error code indicating success
+ */
+ambix_err_t _ambix_write_markersregions(ambix_t*ax);
+/** @brief write general chunk to file
+ * @param ambix valid ambix handle
+ * @param id four-character code identifying the chunk
+ * @param data pointer to memory holding the chunk
+ * @param datasize size of data
+ * @return error code indicating success
+ */
+ambix_err_t _ambix_write_chunk(ambix_t*ax, uint32_t id, const void*data, int64_t datasize);
+/** @brief read general chunk to file
+ * @param ambix valid ambix handle
+ * @param id four-character code identifying the chunk
+ * @param chunk_it try to get the chunk_it-th chunk with the specified id
+ * @param datasize returns size of data
+ * @return data pointer to memory holding the chunk
+ *
+ * @remark several chunks with the same id may exist in the file
+ * use chunk_it from 0...n for retrieving all existing chunks
+ *
+ * @remark in case of success the caller has to free the returned data!
+ */
+void* _ambix_read_chunk(ambix_t*ax, uint32_t id, uint32_t chunk_it, int64_t *datasize);
/** @brief Fill a matrix with byteswapped values
*
@@ -221,6 +269,77 @@ ambix_err_t _ambix_write_uuidchunk(ambix_t*ax, const void*data, int64_t datasize
ambix_err_t
_ambix_matrix_fill_data_byteswapped(ambix_matrix_t*mtx, const number32_t*data);
+/** @brief Transpose a matrix
+ *
+ * swap rows/columns: a[i][j] -> a[j][i]
+ *
+ * @param matrix the matrix to transpose
+ * @param xirtam the result matrix (if NULL one will be allocated for you)
+ * @return a pointer to the result matrix (or NULL on failure)
+ */
+ambix_matrix_t*
+_ambix_matrix_transpose(const ambix_matrix_t*matrix, ambix_matrix_t*xirtam);
+/** @brief Multiply two matrices
+ *
+ * Multiply matrices dest=A*B, possibly resizing or creating the destination
+ * matrix.
+ *
+ * @param A left-hand operator
+ *
+ * @param B right-hand operator
+ *
+ * @param result pointer to the matrix object that will hold the result or NULL
+ *
+ * @return pointer to the result matrix, or NULL in case the matrix
+ * multiplication did not succeed.
+ *
+ * @remark If this returns a newly allocated matrix object (result!=return
+ * value), the host has to take care of calling ambix_matrix_destroy().
+ */
+ambix_matrix_t*
+_ambix_matrix_multiply (const ambix_matrix_t *A, const ambix_matrix_t *B, ambix_matrix_t *result) ;
+/** @brief Get the Moore-Penrose pseudoinverse of a matrix.
+ *
+ * Get the Moore-Penrose pseudoinverse of the matrix input and write the result
+ * to pinv
+ *
+ * @param matrix input matrix
+ *
+ * @param pinv pointer to the matrix object that will hold the result or NULL
+ *
+ * @return pointer to the result matrix, or NULL in case the matrix
+ * inversion did not succeed.
+ */
+ambix_matrix_t*
+_ambix_matrix_pinv(const ambix_matrix_t*matrix, ambix_matrix_t*pinv) ;
+
+/** @brief Invert a matrix using Gauss-Jordan
+ *
+ * Invert a square matrix using the Gauss-Jordan algorithm
+ *
+ * @param matrix the matrix to invert
+ * @param result the result matrix (if NULL one will be allocated for you)
+ * @param eps threshold to detect singularities
+ * @return a pointer to the result matrix (or NULL on failure)
+ *
+ * @note the input matrix will be modified!
+ */
+ambix_matrix_t*
+_ambix_matrix_invert_gaussjordan(ambix_matrix_t*matrix, ambix_matrix_t*result, float32_t eps);
+
+/** @brief Invert a matrix using Cholesky
+ *
+ * Invert a matrix using the Cholesky decomposition.
+ * If the matrix is non-square, this computes the pseuo-inverse.
+ *
+ * @param matrix the matrix to invert
+ * @param result the result matrix (if NULL one will be allocated for you)
+ * @param tolerance threshold for pivoting (scaled by the largest matrix values)
+ * @return a pointer to the result matrix (or NULL on failure)
+ *
+ */
+ambix_matrix_t*
+_ambix_matrix_pinvert_cholesky(const ambix_matrix_t*matrix, ambix_matrix_t*result, float32_t tolerance);
/** @brief byte-swap 32bit data
* @param n a 32bit chunk in the wrong byte order
@@ -231,11 +350,31 @@ static inline uint32_t swap4(uint32_t n)
return (((n & 0xff) << 24) | ((n & 0xff00) << 8) |
((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24));
}
+/** @brief byte-swap 64bit data
+ * @param n a 64bit chunk in the wrong byte order
+ * @return byte-swapped data
+ */
+static inline uint64_t swap8(uint64_t n)
+{
+ return ((((n) & 0xff00000000000000ull) >> 56) |
+ (((n) & 0x00ff000000000000ull) >> 40) |
+ (((n) & 0x0000ff0000000000ull) >> 24) |
+ (((n) & 0x000000ff00000000ull) >> 8 ) |
+ (((n) & 0x00000000ff000000ull) << 8 ) |
+ (((n) & 0x0000000000ff0000ull) << 24) |
+ (((n) & 0x000000000000ff00ull) << 40) |
+ (((n) & 0x00000000000000ffull) << 56));
+}
/** @brief byte-swap arrays of 32bit data
* @param data a pointer to an array of 32bit data to be byteswapped
* @param datasize the size of the array
*/
void _ambix_swap4array(uint32_t*data, uint64_t datasize);
+/** @brief byte-swap arrays of 64bit data
+ * @param data a pointer to an array of 64bit data to be byteswapped
+ * @param datasize the size of the array
+ */
+void _ambix_swap8array(uint64_t*data, uint64_t datasize);
/** @brief resize adaptor buffer to given size
*
@@ -269,6 +408,10 @@ ambix_err_t _ambix_adaptorbuffer_destroy(ambix_t*ambix);
* @return error code indicating success
*/
ambix_err_t _ambix_splitAdaptor_float32(const float32_t*source, uint32_t sourcechannels, uint32_t ambichannels, float32_t*dest_ambi, float32_t*dest_other, int64_t frames);
+/** @brief extract ambisonics and non-ambisonics channels from interleaved (64bit float) data
+ * @see _ambix_splitAdaptor_float64
+ */
+ambix_err_t _ambix_splitAdaptor_float64(const float64_t*source, uint32_t sourcechannels, uint32_t ambichannels, float64_t*dest_ambi, float64_t*dest_other, int64_t frames);
/** @brief extract ambisonics and non-ambisonics channels from interleaved (32bit signed integer) data
* @see _ambix_splitAdapator_float32
*/
@@ -293,6 +436,8 @@ ambix_err_t _ambix_splitAdaptor_int16(const int16_t*source, uint32_t sourcechann
*/
ambix_err_t _ambix_splitAdaptormatrix_float32(const float32_t*source, uint32_t sourcechannels, const ambix_matrix_t*matrix, float32_t*dest_ambi, float32_t*dest_other, int64_t frames);
/* @see _ambix_splitAdaptormatrix_float32 */
+ambix_err_t _ambix_splitAdaptormatrix_float64(const float64_t*source, uint32_t sourcechannels, const ambix_matrix_t*matrix, float64_t*dest_ambi, float64_t*dest_other, int64_t frames);
+/* @see _ambix_splitAdaptormatrix_float32 */
ambix_err_t _ambix_splitAdaptormatrix_int32(const int32_t*source, uint32_t sourcechannels, const ambix_matrix_t*matrix, int32_t*dest_ambi, int32_t*dest_other, int64_t frames);
/* @see _ambix_splitAdaptormatrix_float32 */
ambix_err_t _ambix_splitAdaptormatrix_int16(const int16_t*source, uint32_t sourcechannels, const ambix_matrix_t*matrix, int16_t*dest_ambi, int16_t*dest_other, int64_t frames);
@@ -311,6 +456,10 @@ ambix_err_t _ambix_splitAdaptormatrix_int16(const int16_t*source, uint32_t sourc
* @return error code indicating success
*/
ambix_err_t _ambix_mergeAdaptor_float32(const float32_t*source1, uint32_t source1channels, const float32_t*source2, uint32_t source2channels, float32_t*destination, int64_t frames);
+/** @brief merge two separate interleaved (64bit float) audio data blocks into one
+ * @see _ambix_mergeAdapator_float32
+ */
+ambix_err_t _ambix_mergeAdaptor_float64(const float64_t*source1, uint32_t source1channels, const float64_t*source2, uint32_t source2channels, float64_t*destination, int64_t frames);
/** @brief merge two separate interleaved (32bit signed integer) audio data blocks into one
* @see _ambix_mergeAdapator_float32
*/
@@ -321,6 +470,29 @@ ambix_err_t _ambix_mergeAdaptor_int32(const int32_t*source1, uint32_t source1cha
ambix_err_t _ambix_mergeAdaptor_int16(const int16_t*source1, uint32_t source1channels, const int16_t*source2, uint32_t source2channels, int16_t*destination, int64_t frames);
+/** @brief merge interleaved ambisonics and interleaved non-ambisonics channels into a single interleaved audio data block using matrix operations
+ *
+ * multiply matrix.rows ambisonics channels with the matrix to get a (reduced) set of
+ * matrix.cols ambix-extended channels.
+ * append ambix-extended and non-ambisonics channels into one big interleaved chunk
+ *
+ * @param source1 the first interleaved samplebuffer (full ambisonics set) to read from
+ * @param matrix the encoder-matrix
+ * @param source2 the second interleaved samplebuffer to read from
+ * @param source2channels the number of channels in source2
+ * @param destination the samplebuffer to merge the data info; must be big enough to hold frames*(matrix.cols+source2channels) samples
+ * @param frames number of frames to extract
+ * @return error code indicating success
+ */
+ambix_err_t _ambix_mergeAdaptormatrix_float32(const float32_t*source1, const ambix_matrix_t*matrix, const float32_t*source2, uint32_t source2channels, float32_t*destination, int64_t frames);
+/* @see _ambix_mergeAdaptormatrix_float32 */
+ambix_err_t _ambix_mergeAdaptormatrix_float64(const float64_t*source1, const ambix_matrix_t*matrix, const float64_t*source2, uint32_t source2channels, float64_t*destination, int64_t frames);
+/* @see _ambix_mergeAdaptormatrix_float32 */
+ambix_err_t _ambix_mergeAdaptormatrix_int32(const int32_t*source1, const ambix_matrix_t*matrix, const int32_t*source2, uint32_t source2channels, int32_t*destination, int64_t frames);
+/* @see _ambix_mergeAdaptormatrix_float32 */
+ambix_err_t _ambix_mergeAdaptormatrix_int16(const int16_t*source1, const ambix_matrix_t*matrix, const int16_t*source2, uint32_t source2channels, int16_t*destination, int64_t frames);
+
+
/** @brief debugging printout for ambix_info_t
* @param info an ambixinfo struct
*/
@@ -351,7 +523,7 @@ ambix_matrix_t*_matrix_router(ambix_matrix_t*orgmatrix, const float32_t*route, u
* @param permutate permutation vector (if(permutate[1]==4)then{row#1 of output matrix will be [0 0 0 0 1 0 ...]};
* the permutate vector must have matrix->rows elements (matrix->cols if swap is TRUE);
* negative permutation indices will skip the given row (if(permutate[3]=-1)then{row#3 will be [0 0 0 ...]};
- * permutation indicies exceeding the valid range will restult in an error
+ * permutation indices exceeding the valid range will restult in an error
* @param transpose whether the result should be transposed (swapped rows and columns)
* @return pointer to the resulting permutation matrix, or NULL in case something went wrong
*/
diff --git a/libambix/src/sndfile.c b/libambix/src/sndfile.c
index c0984ab..4448fc4 100644
--- a/libambix/src/sndfile.c
+++ b/libambix/src/sndfile.c
@@ -1,6 +1,6 @@
/* sndfile.c - libsndfile support -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -43,6 +43,9 @@
# define snprintf _snprintf
#endif /* _MSC_VER */
+//#define DEBUG_SFINFO
+
+
typedef struct ambixsndfile_private_t {
/** handle to the libsndfile object */
SNDFILE*sf_file;
@@ -51,6 +54,9 @@ typedef struct ambixsndfile_private_t {
#if defined HAVE_SF_CHUNK_INFO
/** for writing uuid chunks */
SF_CHUNK_INFO sf_chunk;
+ /** for writing other kind of chunks */
+ SF_CHUNK_INFO *sf_otherchunks;
+ uint32_t sf_numchunks;
#elif defined HAVE_SF_UUID_INFO
#endif
}ambixsndfile_private_t;
@@ -64,6 +70,7 @@ sndfile2ambix_sampleformat(int sformat) {
case(SF_FORMAT_PCM_24): return AMBIX_SAMPLEFORMAT_PCM24 ;
case(SF_FORMAT_PCM_32): return AMBIX_SAMPLEFORMAT_PCM32 ;
case(SF_FORMAT_FLOAT ): return AMBIX_SAMPLEFORMAT_FLOAT32;
+ case(SF_FORMAT_DOUBLE): return AMBIX_SAMPLEFORMAT_FLOAT64;
}
return AMBIX_SAMPLEFORMAT_NONE;
}
@@ -75,10 +82,12 @@ ambix2sndfile_sampleformat(ambix_sampleformat_t asformat) {
case(AMBIX_SAMPLEFORMAT_PCM24): return SF_FORMAT_PCM_24;
case(AMBIX_SAMPLEFORMAT_PCM32): return SF_FORMAT_PCM_32;
case(AMBIX_SAMPLEFORMAT_FLOAT32): return SF_FORMAT_FLOAT;
+ case(AMBIX_SAMPLEFORMAT_FLOAT64): return SF_FORMAT_DOUBLE;
default:break;
}
return SF_FORMAT_PCM_24;
}
+#ifdef DEBUG_SFINFO
static void print_sfinfo(SF_INFO*info) {
printf("SF_INFO %p\n", info);
printf(" frames\t: %d\n", (int)(info->frames));
@@ -88,6 +97,7 @@ static void print_sfinfo(SF_INFO*info) {
printf(" sections\t: %d\n", info->sections);
printf(" seekable\t: %d\n", info->seekable);
}
+#endif
static void
ambix2sndfile_info(const ambix_info_t*axinfo, SF_INFO *sfinfo) {
@@ -109,16 +119,16 @@ sndfile2ambix_info(const SF_INFO*sfinfo, ambix_info_t*axinfo) {
static int
read_uuidchunk(ambix_t*ax) {
#if defined HAVE_SF_GET_CHUNK_ITERATOR && defined (HAVE_SF_CHUNK_INFO)
- int err ;
- SF_CHUNK_INFO chunk_info ;
+ int err ;
+ SF_CHUNK_INFO chunk_info ;
SNDFILE*file=PRIVATE(ax)->sf_file;
SF_CHUNK_ITERATOR *iterator;
uint32_t chunkver=0;
const char*id="uuid";
- memset (&chunk_info, 0, sizeof (chunk_info)) ;
- snprintf (chunk_info.id, sizeof (chunk_info.id), "%s", id) ;
- chunk_info.id_size = 4 ;
+ memset (&chunk_info, 0, sizeof (chunk_info)) ;
+ snprintf (chunk_info.id, sizeof (chunk_info.id), "%s", id) ;
+ chunk_info.id_size = 4 ;
for(iterator = sf_get_chunk_iterator (file, &chunk_info); NULL!=iterator; iterator=sf_next_chunk_iterator (iterator)) {
if(chunk_info.data)
@@ -146,8 +156,7 @@ read_uuidchunk(ambix_t*ax) {
chunkver=_ambix_checkUUID((const char*)chunk_info.data);
if(1==chunkver) {
if(_ambix_uuid1_to_matrix(((const char*)chunk_info.data+16), chunk_info.datalen-16, &ax->matrix, ax->byteswap)) {
- if(chunk_info.data)
- free(chunk_info.data) ;
+ free(chunk_info.data);
return AMBIX_ERR_SUCCESS;
}
} else
@@ -159,17 +168,17 @@ read_uuidchunk(ambix_t*ax) {
return AMBIX_ERR_UNKNOWN;
#elif defined HAVE_SF_UUID_INFO
- SF_UUID_INFO uuid;
- SNDFILE*file=PRIVATE(ax)->sf_file;
-
- memset(&uuid, 0, sizeof(uuid));
- strncpy(uuid.id, _ambix_getUUID(1), 16);
- if ( !sf_command(file, SFC_GET_UUID, &uuid, sizeof(uuid)) ) {
- // extended
- if(_ambix_uuid1_to_matrix(uuid.data, uuid.data_size, &ax->matrix, ax->byteswap)) {
- return AMBIX_ERR_SUCCESS;
- }
- }
+ SF_UUID_INFO uuid;
+ SNDFILE*file=PRIVATE(ax)->sf_file;
+
+ memset(&uuid, 0, sizeof(uuid));
+ strncpy(uuid.id, _ambix_getUUID(1), 16);
+ if ( !sf_command(file, SFC_GET_UUID, &uuid, sizeof(uuid)) ) {
+ // extended
+ if(_ambix_uuid1_to_matrix(uuid.data, uuid.data_size, &ax->matrix, ax->byteswap)) {
+ return AMBIX_ERR_SUCCESS;
+ }
+ }
#endif
return AMBIX_ERR_UNKNOWN;
}
@@ -177,7 +186,7 @@ read_uuidchunk(ambix_t*ax) {
-ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo) {
+ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo) {
int sfmode=0;
int caf=0;
int is_ambix=0;
@@ -186,11 +195,11 @@ ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t
ambix2sndfile_info(ambixinfo, &PRIVATE(ambix)->sf_info);
if((mode & AMBIX_READ) && (mode & AMBIX_WRITE))
- sfmode= SFM_RDWR;
+ sfmode= SFM_RDWR;
else if (mode & AMBIX_WRITE)
- sfmode= SFM_WRITE;
+ sfmode= SFM_WRITE;
else if (mode & AMBIX_READ)
- sfmode= SFM_READ;
+ sfmode= SFM_READ;
PRIVATE(ambix)->sf_file=sf_open(path, sfmode, &PRIVATE(ambix)->sf_info) ;
if(!PRIVATE(ambix)->sf_file)
@@ -278,14 +287,15 @@ ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t
}
ambix->is_AMBIX=is_ambix;
- if(0) {
+#ifdef DEBUG_SFINFO
print_sfinfo( &PRIVATE(ambix)->sf_info);
- }
+#endif
return AMBIX_ERR_SUCCESS;
}
-ambix_err_t _ambix_close (ambix_t*ambix) {
+ambix_err_t _ambix_close (ambix_t*ambix) {
+ int i;
if(PRIVATE(ambix)->sf_file)
sf_close(PRIVATE(ambix)->sf_file);
PRIVATE(ambix)->sf_file=NULL;
@@ -293,6 +303,11 @@ ambix_err_t _ambix_close (ambix_t*ambix) {
#if defined HAVE_SF_SET_CHUNK && defined (HAVE_SF_CHUNK_INFO)
if((PRIVATE(ambix)->sf_chunk).data)
free((PRIVATE(ambix)->sf_chunk).data);
+ for (i=0;i<PRIVATE(ambix)->sf_numchunks;i++) {
+ if (PRIVATE(ambix)->sf_otherchunks[i].data)
+ free(PRIVATE(ambix)->sf_otherchunks[i].data);
+ }
+ free(PRIVATE(ambix)->sf_otherchunks);
#endif
free(PRIVATE(ambix));
@@ -317,7 +332,7 @@ int64_t _ambix_seek (ambix_t* ambix, int64_t frames, int bias) {
return -1;
}
-SNDFILE*_ambix_get_sndfile (ambix_t*ambix) {
+SNDFILE*_ambix_get_sndfile (ambix_t*ambix) {
return PRIVATE(ambix)->sf_file;
}
int64_t _ambix_readf_int16 (ambix_t*ambix, int16_t*data, int64_t frames) {
@@ -329,6 +344,9 @@ int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames) {
int64_t _ambix_readf_float32 (ambix_t*ambix, float32_t*data, int64_t frames) {
return (int64_t)sf_readf_float(PRIVATE(ambix)->sf_file, (float*)data, frames) ;
}
+int64_t _ambix_readf_float64 (ambix_t*ambix, float64_t*data, int64_t frames) {
+ return (int64_t)sf_readf_double(PRIVATE(ambix)->sf_file, (double*)data, frames) ;
+}
int64_t _ambix_writef_int16 (ambix_t*ambix, const int16_t*data, int64_t frames) {
return (int64_t)sf_writef_short(PRIVATE(ambix)->sf_file, (short*)data, frames) ;
@@ -339,36 +357,121 @@ int64_t _ambix_writef_int32 (ambix_t*ambix, const int32_t*data, int64_t frames
int64_t _ambix_writef_float32 (ambix_t*ambix, const float32_t*data, int64_t frames) {
return (int64_t)sf_writef_float(PRIVATE(ambix)->sf_file, (float*)data, frames) ;
}
+int64_t _ambix_writef_float64 (ambix_t*ambix, const float64_t*data, int64_t frames) {
+ return (int64_t)sf_writef_double(PRIVATE(ambix)->sf_file, (double*)data, frames) ;
+}
ambix_err_t _ambix_write_uuidchunk(ambix_t*ax, const void*data, int64_t datasize) {
#if defined HAVE_SF_SET_CHUNK && defined (HAVE_SF_CHUNK_INFO)
- int err ;
+ int err ;
SF_CHUNK_INFO*chunk=&PRIVATE(ax)->sf_chunk;
int64_t datasize4 = datasize>>2;
if(datasize4*4 < datasize)
datasize4++;
- memset (chunk, 0, sizeof (*chunk)) ;
- snprintf (chunk->id, sizeof (chunk->id), "uuid") ;
- chunk->id_size = 4 ;
+ memset (chunk, 0, sizeof (*chunk)) ;
+ snprintf (chunk->id, sizeof (chunk->id), "uuid") ;
+ chunk->id_size = 4 ;
if(chunk->data)
free(chunk->data);
- chunk->data = calloc(datasize4, 4);
+ chunk->data = calloc(datasize4, 4);
memcpy(chunk->data, data, datasize);
- chunk->datalen = datasize ;
- err = sf_set_chunk (PRIVATE(ax)->sf_file, chunk) ;
+ chunk->datalen = datasize ;
+ err = sf_set_chunk (PRIVATE(ax)->sf_file, chunk) ;
if(SF_ERR_NO_ERROR != err)
return AMBIX_ERR_UNKNOWN;
return AMBIX_ERR_SUCCESS;
#elif defined HAVE_SF_UUID_INFO
- SF_UUID_INFO uuid;
- memcpy(uuid.id, data, 16);
- uuid.data=(void*)(data+16);
- uuid.data_size=datasize-16;
- if(!sf_command(PRIVATE(ax)->sf_file, SFC_SET_UUID, &uuid, sizeof(uuid))) {
- return AMBIX_ERR_SUCCESS;
- }
+ SF_UUID_INFO uuid;
+ memcpy(uuid.id, data, 16);
+ uuid.data=(void*)(data+16);
+ uuid.data_size=datasize-16;
+ if(!sf_command(PRIVATE(ax)->sf_file, SFC_SET_UUID, &uuid, sizeof(uuid))) {
+ return AMBIX_ERR_SUCCESS;
+ }
+#endif
+ return AMBIX_ERR_UNKNOWN;
+}
+ambix_err_t _ambix_write_chunk(ambix_t*ax, uint32_t id, const void*data, int64_t datasize) {
+#if defined (HAVE_SF_SET_CHUNK)
+ int err ;
+ int64_t datasize4 = datasize>>2;
+
+ SF_CHUNK_INFO *chunks = NULL;
+ SF_CHUNK_INFO *chunk = NULL;
+ unsigned int numchunks=(PRIVATE(ax)->sf_numchunks);
+
+ if(datasize4*4 < datasize)
+ datasize4++;
+
+ /* (re-)allocate memory for the new chunk - data has to be kept until file closes! */
+ if (0 == numchunks) {
+ chunks = (SF_CHUNK_INFO*)calloc(1, sizeof(*chunks));
+ } else {
+ chunks = (SF_CHUNK_INFO*)realloc(PRIVATE(ax)->sf_otherchunks, (numchunks+1)*sizeof(*chunks));
+ }
+ if (NULL == chunks)
+ return AMBIX_ERR_UNKNOWN;
+ chunk = chunks + numchunks;
+ memset (chunk, 0, sizeof (*chunk)) ;
+
+ //snprintf (chunk->id, 4, id) ;
+ memcpy(chunk->id, &id, 4);
+ chunk->id_size = 4 ;
+ if(chunk->data)
+ free(chunk->data);
+
+ chunk->data = calloc(datasize4, 4);
+
+ memcpy(chunk->data, data, datasize);
+ chunk->datalen = datasize ;
+ err = sf_set_chunk (PRIVATE(ax)->sf_file, chunk);
+
+ PRIVATE(ax)->sf_numchunks += 1;
+ PRIVATE(ax)->sf_otherchunks = chunks;
+
+ if(SF_ERR_NO_ERROR != err)
+ return AMBIX_ERR_UNKNOWN;
+ return AMBIX_ERR_SUCCESS;
#endif
return AMBIX_ERR_UNKNOWN;
}
+void* _ambix_read_chunk(ambix_t*ax, uint32_t id, uint32_t chunk_it, int64_t *datasize) {
+#if defined HAVE_SF_GET_CHUNK_ITERATOR
+ int err;
+ SF_CHUNK_INFO chunk_info;
+ SF_CHUNK_ITERATOR * iterator;
+ int i;
+ memset (&chunk_info, 0, sizeof (chunk_info));
+ memcpy(chunk_info.id, &id, 4);
+ chunk_info.id_size = 4;
+ iterator = sf_get_chunk_iterator (PRIVATE(ax)->sf_file, &chunk_info);
+ if (!iterator) {
+ *datasize = 0;
+ return NULL;
+ }
+ // jump to wanted iterator
+ for (i=0; i<chunk_it; i++) {
+ iterator = sf_next_chunk_iterator (iterator) ;
+ if (!iterator) {
+ *datasize = 0;
+ return NULL;
+ }
+ }
+ memset (&chunk_info, 0, sizeof (chunk_info));
+ err = sf_get_chunk_size (iterator, &chunk_info);
+ if (!chunk_info.datalen) {
+ *datasize = 0;
+ return NULL;
+ }
+ chunk_info.data = malloc (chunk_info.datalen); // has to be freed later by the caller!
+ err = sf_get_chunk_data (iterator, &chunk_info);
+
+ // free (chunk_info.data);
+ *datasize = chunk_info.datalen;
+ return chunk_info.data;
+#endif
+ *datasize = 0;
+ return NULL;
+}
diff --git a/libambix/src/utils.c b/libambix/src/utils.c
index 891306a..c7a5fad 100644
--- a/libambix/src/utils.c
+++ b/libambix/src/utils.c
@@ -73,6 +73,25 @@ void _ambix_print_matrix(const ambix_matrix_t*mtx) {
}
+void _ambix_print_markers(const ambix_t*ambix)
+{
+ if (ambix->markers) {
+ int i;
+ for (i=0; i < ambix->num_markers; i++) {
+ printf(" marker %d: name: %s position: %f \n", i, ambix->markers[i].name, ambix->markers[i].position);
+ }
+ }
+}
+void _ambix_print_regions(const ambix_t*ambix)
+{
+ if (ambix->regions) {
+ int i;
+ for (i=0; i < ambix->num_regions; i++) {
+ printf(" region %d: name: %s start_position: %f end_position: %f \n", i, ambix->regions[i].name, ambix->regions[i].start_position, ambix->regions[i].end_position);
+ }
+ }
+}
+
void _ambix_print_ambix(const ambix_t*ambix) {
printf("AMBIX %p\n", ambix);
if(!ambix)return;
@@ -95,6 +114,10 @@ void _ambix_print_ambix(const ambix_t*ambix) {
printf(" adaptorbuffer\t: %p\n", ambix->adaptorbuffer);
printf(" adaptorbuffersize\t: %d\n", (int)(ambix->adaptorbuffersize));
printf(" ambisonics_order\t: %d\n", ambix->ambisonics_order);
+ printf(" num_markers\t: %d\n", ambix->num_markers);
+ _ambix_print_markers(ambix);
+ printf(" num_regions\t: %d\n", ambix->num_regions);
+ _ambix_print_regions(ambix);
printf(" startedReading\t: %d\n", ambix->startedReading);
printf(" startedWriting\t: %d\n", ambix->startedWriting);
}
@@ -107,3 +130,10 @@ void _ambix_swap4array(uint32_t*data, uint64_t datasize) {
*data++=swap4(v);
}
}
+void _ambix_swap8array(uint64_t*data, uint64_t datasize) {
+ uint64_t i;
+ for(i=0; i<datasize; i++) {
+ uint64_t v=*data;
+ *data++=swap8(v);
+ }
+}
diff --git a/libambix/src/uuid_chunk.c b/libambix/src/uuid_chunk.c
index d85d76f..8fef5f2 100644
--- a/libambix/src/uuid_chunk.c
+++ b/libambix/src/uuid_chunk.c
@@ -1,6 +1,6 @@
/* uuid_chunk.c - parse an UUID-chunk to extract relevant data -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -48,30 +48,33 @@
*/
#include <stdio.h>
-static void _ambix_printUUID4(const char data[2]) {
- printf("%02x%02x", (signed char)data[0], (signed char)data[1]);
+#if 0
+static void _ambix_printUUID4(const char data[2]) {
+ unsigned char data0=data[0];
+ unsigned char data1=data[1];
+ printf("%02x%02x", data0, data1);
}
static void _ambix_printUUID(const char data[16]) {
- /* 8-4-4-4-12 */
- _ambix_printUUID4(data);data+=2;
- _ambix_printUUID4(data);data+=2;
+ /* 8-4-4-4-12 */
+ _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
printf("-");
- _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
printf("-");
- _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
printf("-");
- _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
printf("-");
- _ambix_printUUID4(data);data+=2;
- _ambix_printUUID4(data);data+=2;
- _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
+ _ambix_printUUID4(data);data+=2;
}
-
- /*
- * uarg, this is not a UUID!
- * (well it is...UUID::Tiny thinks it's a v2 (DCE security) UUID
- */
+#endif
+/*
+ * uarg, this is not a UUID!
+ * (well it is...UUID::Tiny thinks it's a v2 (DCE security) UUID
+ */
static const char _ambix_uuid_v1_[]="IEM.AT/AMBIX/XML";
/*
* that's a better UUID, based on a SHA1-hash of "http://ambisonics.iem.at/xchange/format/1.0"
@@ -138,7 +141,7 @@ _ambix_uuid1_to_matrix(const void*vdata, uint64_t datasize, ambix_matrix_t*orgmt
}
if(!ambix_matrix_init(rows, cols, mtx))
- goto cleanup;
+ goto cleanup;
if(swap) {
if(_ambix_matrix_fill_data_byteswapped(mtx, (number32_t*)(cdata+index)) != AMBIX_ERR_SUCCESS)
diff --git a/libambix/tests/Makefile.am b/libambix/tests/Makefile.am
index 589fd2c..2712dc4 100644
--- a/libambix/tests/Makefile.am
+++ b/libambix/tests/Makefile.am
@@ -1,81 +1,225 @@
-AUTOMAKE_OPTIONS = foreign serial-tests
+#AUTOMAKE_OPTIONS = foreign serial-tests
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS=data
#TESTS_ENVIRONMENT = RUNTESTS_NOLOG=yes TESTDIR=$(srcdir)
-AM_TESTS_ENVIRONMENT = TESTDIR=$(srcdir) ./runtest.sh
+#AM_TESTS_ENVIRONMENT = TESTDIR=$(srcdir) ./runtest.sh
+
+ at VALGRIND_CHECK_RULES@
AM_CPPFLAGS = -I$(top_srcdir)/libambix
+if DEBUG
+AM_CPPFLAGS += -I$(top_srcdir)/libambix/src -DAMBIX_INTERNAL
+endif
LDADD = $(top_builddir)/libambix/src/libambix.la
+check_PROGRAMS =
TESTS = \
pass skip fail
XFAIL_TESTS = fail
-check_PROGRAMS= \
- pass skip fail
-
-SOURCES=common.c common.h
-noinst_HEADERS = common.h
+SOURCES=common.c common.h data.h common_basic2extended.h
+noinst_HEADERS = common.h data.h common_basic2extended.h
pass_SOURCES=pass.c
skip_SOURCES=skip.c
fail_SOURCES=fail.c
+TESTS += pass_if0 pass_if1 skip_if0 skip_if1 fail_if0 fail_if1
+XFAIL_TESTS += fail_if1
+pass_if0_SOURCES=pass_if0.c
+pass_if1_SOURCES=pass_if1.c
+skip_if0_SOURCES=skip_if0.c
+skip_if1_SOURCES=skip_if1.c
+fail_if0_SOURCES=fail_if0.c
+fail_if1_SOURCES=fail_if1.c
+
+
+TESTS += datatest
+datatest_SOURCES = datatest.c common.c
+
TESTS += matrix
-check_PROGRAMS += matrix
-matrix_SOURCES = matrix.c common.c
+matrix_SOURCES = matrixtests.c common.c
TESTS += matrices
-check_PROGRAMS += matrices
matrices_SOURCES = matrices.c common.c
+TESTS += const_matrix
+const_matrix_SOURCES = const_matrix.c common.c
+
+if DEBUG
+TESTS += debug_utils
+debug_utils_SOURCES = debug_utils.c common.c
+endif
+
+TESTS += markers_regions
+markers_regions_SOURCES = markers_regions.c common.c
+
TESTS += none_float32
-check_PROGRAMS += none_float32
-none_float32_SOURCES = none_float32.c ambix_none.c common.c
-
-TESTS += simple_float32 simple_pcm32 simple_pcm16
-check_PROGRAMS += simple_float32 simple_pcm32 simple_pcm16
-simple_float32_SOURCES = simple_float32.c ambix_simple.c common.c
-simple_pcm32_SOURCES = simple_pcm32.c ambix_simple.c common.c
-simple_pcm16_SOURCES = simple_pcm16.c ambix_simple.c common.c
-
-TESTS += extended_float32_0 extended_pcm32_0 extended_pcm16_0
-check_PROGRAMS += extended_float32_0 extended_pcm32_0 extended_pcm16_0
-extended_float32_0_SOURCES = extended_float32_0.c ambix_extended.c common.c
-extended_pcm32_0_SOURCES = extended_pcm32_0.c ambix_extended.c common.c
-extended_pcm16_0_SOURCES = extended_pcm16_0.c ambix_extended.c common.c
-
-TESTS += extended_float32_1024 extended_pcm32_1024 extended_pcm16_1024
-check_PROGRAMS += extended_float32_1024 extended_pcm32_1024 extended_pcm16_1024
-extended_float32_1024_SOURCES = extended_float32_1024.c ambix_extended.c common.c
-extended_pcm32_1024_SOURCES = extended_pcm32_1024.c ambix_extended.c common.c
-extended_pcm16_1024_SOURCES = extended_pcm16_1024.c ambix_extended.c common.c
+none_float32_SOURCES = none_float32.c common_none.c common.c
+TESTS += none_float64
+none_float64_SOURCES = none_float64.c common_none.c common.c
+
+TESTS += basic_float32 basic_float64 basic_pcm32 basic_pcm16
+basic_float32_SOURCES = basic_float32.c common_basic.c common.c
+basic_float64_SOURCES = basic_float64.c common_basic.c common.c
+basic_pcm32_SOURCES = basic_pcm32.c common_basic.c common.c
+basic_pcm16_SOURCES = basic_pcm16.c common_basic.c common.c
+
+TESTS += extended_float32_0 extended_float64_0 extended_pcm32_0 extended_pcm16_0
+extended_float32_0_SOURCES = extended_float32_0.c common_extended.c common.c
+extended_float64_0_SOURCES = extended_float64_0.c common_extended.c common.c
+extended_pcm32_0_SOURCES = extended_pcm32_0.c common_extended.c common.c
+extended_pcm16_0_SOURCES = extended_pcm16_0.c common_extended.c common.c
+
+TESTS += extended_float32_1024 extended_float64_1024 extended_pcm32_1024 extended_pcm16_1024
+extended_float32_1024_SOURCES = extended_float32_1024.c common_extended.c common.c
+extended_float64_1024_SOURCES = extended_float64_1024.c common_extended.c common.c
+extended_pcm32_1024_SOURCES = extended_pcm32_1024.c common_extended.c common.c
+extended_pcm16_1024_SOURCES = extended_pcm16_1024.c common_extended.c common.c
TESTS += ambix_open
-check_PROGRAMS += ambix_open
ambix_open_SOURCES = ambix_open.c
-
TESTS += ambix_close
-check_PROGRAMS += ambix_close
ambix_close_SOURCES = ambix_close.c
+TESTS += ambix_get_sndfile
+ambix_get_sndfile_SOURCES = ambix_get_sndfile.c
+
TESTS += ambix_seek
-check_PROGRAMS += ambix_seek
ambix_seek_SOURCES = ambix_seek.c
TESTS += ambix_seek_read
-check_PROGRAMS += ambix_seek_read
ambix_seek_read_SOURCES = ambix_seek_read.c
TESTS += ambix_readf_int16
-check_PROGRAMS += ambix_readf_int16
ambix_readf_int16_SOURCES = ambix_readf_int16.c
TESTS += ambix_writef_int16
-check_PROGRAMS += ambix_writef_int16
ambix_writef_int16_SOURCES = ambix_writef_int16.c
+common_b2x=common_basic2extended.c common.c
+## float32
+TESTS += \
+ basic2extended_identity4x4_float32 \
+ basic2extended_N3D4x4_float32 \
+ basic2extended_SID4x4_float32 \
+ basic2extended_FUMA4x4_float32 \
+ basic2extended_rand4x9_float32 \
+ basic2extended_rand4x7_float32 \
+ basic2extended_identity4x4_3extra_float32 \
+ basic2extended_N3D4x4_3extra_float32 \
+ basic2extended_SID4x4_3extra_float32 \
+ basic2extended_FUMA4x4_3extra_float32 \
+ basic2extended_rand4x9_3extra_float32 \
+ basic2extended_rand4x7_3extra_float32
+basic2extended_identity4x4_float32_SOURCES = basic2extended_identity4x4_float32.c $(common_b2x)
+basic2extended_N3D4x4_float32_SOURCES = basic2extended_N3D4x4_float32.c $(common_b2x)
+basic2extended_SID4x4_float32_SOURCES = basic2extended_SID4x4_float32.c $(common_b2x)
+basic2extended_FUMA4x4_float32_SOURCES = basic2extended_FUMA4x4_float32.c $(common_b2x)
+basic2extended_rand4x9_float32_SOURCES = basic2extended_rand4x9_float32.c $(common_b2x)
+basic2extended_rand4x7_float32_SOURCES = basic2extended_rand4x7_float32.c $(common_b2x)
+basic2extended_identity4x4_3extra_float32_SOURCES = basic2extended_identity4x4_3extra_float32.c $(common_b2x)
+basic2extended_N3D4x4_3extra_float32_SOURCES = basic2extended_N3D4x4_3extra_float32.c $(common_b2x)
+basic2extended_SID4x4_3extra_float32_SOURCES = basic2extended_SID4x4_3extra_float32.c $(common_b2x)
+basic2extended_FUMA4x4_3extra_float32_SOURCES = basic2extended_FUMA4x4_3extra_float32.c $(common_b2x)
+basic2extended_rand4x9_3extra_float32_SOURCES = basic2extended_rand4x9_3extra_float32.c $(common_b2x)
+basic2extended_rand4x7_3extra_float32_SOURCES = basic2extended_rand4x7_3extra_float32.c $(common_b2x)
+
+TESTS += \
+ basic2extended_identity4x4_float32__f64 \
+ basic2extended_identity4x4_float32__i16 \
+ basic2extended_identity4x4_float32__i32
+basic2extended_identity4x4_float32__f64_SOURCES = basic2extended_identity4x4_float32__f64.c $(common_b2x)
+basic2extended_identity4x4_float32__i16_SOURCES = basic2extended_identity4x4_float32__i16.c $(common_b2x)
+basic2extended_identity4x4_float32__i32_SOURCES = basic2extended_identity4x4_float32__i32.c $(common_b2x)
+
+## float64
+TESTS += \
+ basic2extended_identity4x4_float64 \
+ basic2extended_N3D4x4_float64 \
+ basic2extended_SID4x4_float64 \
+ basic2extended_FUMA4x4_float64 \
+ basic2extended_rand4x9_float64 \
+ basic2extended_rand4x7_float64 \
+ basic2extended_identity4x4_3extra_float64 \
+ basic2extended_N3D4x4_3extra_float64 \
+ basic2extended_SID4x4_3extra_float64 \
+ basic2extended_FUMA4x4_3extra_float64 \
+ basic2extended_rand4x9_3extra_float64 \
+ basic2extended_rand4x7_3extra_float64
+basic2extended_identity4x4_float64_SOURCES = basic2extended_identity4x4_float64.c $(common_b2x)
+basic2extended_N3D4x4_float64_SOURCES = basic2extended_N3D4x4_float64.c $(common_b2x)
+basic2extended_SID4x4_float64_SOURCES = basic2extended_SID4x4_float64.c $(common_b2x)
+basic2extended_FUMA4x4_float64_SOURCES = basic2extended_FUMA4x4_float64.c $(common_b2x)
+basic2extended_rand4x9_float64_SOURCES = basic2extended_rand4x9_float64.c $(common_b2x)
+basic2extended_rand4x7_float64_SOURCES = basic2extended_rand4x7_float64.c $(common_b2x)
+basic2extended_identity4x4_3extra_float64_SOURCES = basic2extended_identity4x4_3extra_float64.c $(common_b2x)
+basic2extended_N3D4x4_3extra_float64_SOURCES = basic2extended_N3D4x4_3extra_float64.c $(common_b2x)
+basic2extended_SID4x4_3extra_float64_SOURCES = basic2extended_SID4x4_3extra_float64.c $(common_b2x)
+basic2extended_FUMA4x4_3extra_float64_SOURCES = basic2extended_FUMA4x4_3extra_float64.c $(common_b2x)
+basic2extended_rand4x9_3extra_float64_SOURCES = basic2extended_rand4x9_3extra_float64.c $(common_b2x)
+basic2extended_rand4x7_3extra_float64_SOURCES = basic2extended_rand4x7_3extra_float64.c $(common_b2x)
+
+## pcm32
+TESTS += \
+ basic2extended_identity4x4_pcm32 \
+ basic2extended_N3D4x4_pcm32 \
+ basic2extended_SID4x4_pcm32 \
+ basic2extended_FUMA4x4_pcm32 \
+ basic2extended_rand4x9_pcm32 \
+ basic2extended_rand4x7_pcm32 \
+ basic2extended_identity4x4_3extra_pcm32 \
+ basic2extended_N3D4x4_3extra_pcm32 \
+ basic2extended_SID4x4_3extra_pcm32 \
+ basic2extended_FUMA4x4_3extra_pcm32 \
+ basic2extended_rand4x9_3extra_pcm32 \
+ basic2extended_rand4x7_3extra_pcm32
+basic2extended_identity4x4_pcm32_SOURCES = basic2extended_identity4x4_pcm32.c $(common_b2x)
+basic2extended_N3D4x4_pcm32_SOURCES = basic2extended_N3D4x4_pcm32.c $(common_b2x)
+basic2extended_SID4x4_pcm32_SOURCES = basic2extended_SID4x4_pcm32.c $(common_b2x)
+basic2extended_FUMA4x4_pcm32_SOURCES = basic2extended_FUMA4x4_pcm32.c $(common_b2x)
+basic2extended_rand4x9_pcm32_SOURCES = basic2extended_rand4x9_pcm32.c $(common_b2x)
+basic2extended_rand4x7_pcm32_SOURCES = basic2extended_rand4x7_pcm32.c $(common_b2x)
+basic2extended_identity4x4_3extra_pcm32_SOURCES = basic2extended_identity4x4_3extra_pcm32.c $(common_b2x)
+basic2extended_N3D4x4_3extra_pcm32_SOURCES = basic2extended_N3D4x4_3extra_pcm32.c $(common_b2x)
+basic2extended_SID4x4_3extra_pcm32_SOURCES = basic2extended_SID4x4_3extra_pcm32.c $(common_b2x)
+basic2extended_FUMA4x4_3extra_pcm32_SOURCES = basic2extended_FUMA4x4_3extra_pcm32.c $(common_b2x)
+basic2extended_rand4x9_3extra_pcm32_SOURCES = basic2extended_rand4x9_3extra_pcm32.c $(common_b2x)
+basic2extended_rand4x7_3extra_pcm32_SOURCES = basic2extended_rand4x7_3extra_pcm32.c $(common_b2x)
+
+## pcm16
+TESTS += \
+ basic2extended_identity4x4_pcm16 \
+ basic2extended_N3D4x4_pcm16 \
+ basic2extended_SID4x4_pcm16 \
+ basic2extended_FUMA4x4_pcm16 \
+ basic2extended_rand4x9_pcm16 \
+ basic2extended_rand4x7_pcm16 \
+ basic2extended_identity4x4_3extra_pcm16 \
+ basic2extended_N3D4x4_3extra_pcm16 \
+ basic2extended_SID4x4_3extra_pcm16 \
+ basic2extended_FUMA4x4_3extra_pcm16 \
+ basic2extended_rand4x9_3extra_pcm16 \
+ basic2extended_rand4x7_3extra_pcm16
+basic2extended_identity4x4_pcm16_SOURCES = basic2extended_identity4x4_pcm16.c $(common_b2x)
+basic2extended_N3D4x4_pcm16_SOURCES = basic2extended_N3D4x4_pcm16.c $(common_b2x)
+basic2extended_SID4x4_pcm16_SOURCES = basic2extended_SID4x4_pcm16.c $(common_b2x)
+basic2extended_FUMA4x4_pcm16_SOURCES = basic2extended_FUMA4x4_pcm16.c $(common_b2x)
+basic2extended_rand4x9_pcm16_SOURCES = basic2extended_rand4x9_pcm16.c $(common_b2x)
+basic2extended_rand4x7_pcm16_SOURCES = basic2extended_rand4x7_pcm16.c $(common_b2x)
+basic2extended_identity4x4_3extra_pcm16_SOURCES = basic2extended_identity4x4_3extra_pcm16.c $(common_b2x)
+basic2extended_N3D4x4_3extra_pcm16_SOURCES = basic2extended_N3D4x4_3extra_pcm16.c $(common_b2x)
+basic2extended_SID4x4_3extra_pcm16_SOURCES = basic2extended_SID4x4_3extra_pcm16.c $(common_b2x)
+basic2extended_FUMA4x4_3extra_pcm16_SOURCES = basic2extended_FUMA4x4_3extra_pcm16.c $(common_b2x)
+basic2extended_rand4x9_3extra_pcm16_SOURCES = basic2extended_rand4x9_3extra_pcm16.c $(common_b2x)
+basic2extended_rand4x7_3extra_pcm16_SOURCES = basic2extended_rand4x7_3extra_pcm16.c $(common_b2x)
+
+
+# ##################################################
+check_PROGRAMS += $(TESTS)
.PHONY: buildtests
buildtests: $(check_PROGRAMS)
diff --git a/libambix/tests/ambix_get_sndfile.c b/libambix/tests/ambix_get_sndfile.c
new file mode 100644
index 0000000..8872f97
--- /dev/null
+++ b/libambix/tests/ambix_get_sndfile.c
@@ -0,0 +1,26 @@
+#include "common.h"
+#include "data.h"
+
+int main()
+{
+ ambix_t*ambix = NULL;
+ struct SNDFILE_tag *sndfile = NULL;
+ ambix_info_t *info= calloc(1, sizeof(ambix_info_t));
+
+ ambix=ambix_open(AMBIXTEST_FILE1, AMBIX_READ, info);
+
+ fail_if(NULL==ambix, __LINE__, "File was not open");
+ sndfile = ambix_get_sndfile (ambix);
+
+#ifdef HAVE_SNDFILE
+#warning LATER: skip, once we have multiple (working) backends
+ /* there is no need to use libsndfile even if libsndfile is present */
+ fail_if(NULL==sndfile, __LINE__, "no sndfile handle despite using libsndfile");
+#else
+ fail_if(NULL!=sndfile, __LINE__, "got sndfile handle without libsndfile!");
+#endif
+
+ ambix_close (ambix);
+ free(info);
+ return 0;
+}
diff --git a/libambix/tests/ambix_readf_int16.c b/libambix/tests/ambix_readf_int16.c
index 4e5c5eb..520768f 100644
--- a/libambix/tests/ambix_readf_int16.c
+++ b/libambix/tests/ambix_readf_int16.c
@@ -2,6 +2,6 @@
int main ()
{
- pass();
- return 0;
+ /* FIXXME: no test yet */
+ return skip();
}
diff --git a/libambix/tests/ambix_seek_read.c b/libambix/tests/ambix_seek_read.c
index 9c6dc1b..3e23a50 100644
--- a/libambix/tests/ambix_seek_read.c
+++ b/libambix/tests/ambix_seek_read.c
@@ -16,8 +16,6 @@ int main()
//ambix_readf_int32 (ambix_t *ambix, int32_t *ambidata, int32_t *otherdata, int64_t frames)
//Read samples (as 32bit signed integer values) from the ambix file.
- pass();
-
//UNCOMMENT WHEN FIXED
/*cmp= ambix_readf_int32(ambix, *ambidata, otherdata, 100);
@@ -32,7 +30,8 @@ int main()
fail_if (result!=100, __LINE__, "File failed to seek correct data");*/
ambix_close(ambix);
-
free(info);
- return 0;
+
+ /* FIXXXME: this test is not working yet */
+ return skip();
}
diff --git a/libambix/tests/ambix_writef_int16.c b/libambix/tests/ambix_writef_int16.c
index af9edbc..00f2f53 100644
--- a/libambix/tests/ambix_writef_int16.c
+++ b/libambix/tests/ambix_writef_int16.c
@@ -26,5 +26,7 @@ int main ()
ambix_close(ambix);
free(info);
- return 0;
+
+ /* FIXXME: no test yet */
+ return skip();
}
diff --git a/libambix/tests/basic2extended_FUMA4x4_3extra_float32.c b/libambix/tests/basic2extended_FUMA4x4_3extra_float32.c
new file mode 100644
index 0000000..83707dd
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_3extra_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 3, 1024, 6e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_3extra_float64.c b/libambix/tests/basic2extended_FUMA4x4_3extra_float64.c
new file mode 100644
index 0000000..74eb42f
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_3extra_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 3, 1024, 6e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_3extra_pcm16.c b/libambix/tests/basic2extended_FUMA4x4_3extra_pcm16.c
new file mode 100644
index 0000000..e502fd8
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_3extra_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 3, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_3extra_pcm32.c b/libambix/tests/basic2extended_FUMA4x4_3extra_pcm32.c
new file mode 100644
index 0000000..6e9dad8
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_3extra_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 3, 1024, 6e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_float32.c b/libambix/tests/basic2extended_FUMA4x4_float32.c
new file mode 100644
index 0000000..52a8bf6
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 0, 1024, 6e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_float64.c b/libambix/tests/basic2extended_FUMA4x4_float64.c
new file mode 100644
index 0000000..ca9240b
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 0, 1024, 6e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_pcm16.c b/libambix/tests/basic2extended_FUMA4x4_pcm16.c
new file mode 100644
index 0000000..aa91c1b
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 5, 4, AMBIX_MATRIX_FUMA , 0, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_FUMA4x4_pcm32.c b/libambix/tests/basic2extended_FUMA4x4_pcm32.c
new file mode 100644
index 0000000..68cc048
--- /dev/null
+++ b/libambix/tests/basic2extended_FUMA4x4_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("FuMa[f]" , 4, 4, AMBIX_MATRIX_FUMA , 0, 1024, 6e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_3extra_float32.c b/libambix/tests/basic2extended_N3D4x4_3extra_float32.c
new file mode 100644
index 0000000..58955d6
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_3extra_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 3, 1024, 3e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_3extra_float64.c b/libambix/tests/basic2extended_N3D4x4_3extra_float64.c
new file mode 100644
index 0000000..d9bc5df
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_3extra_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 3, 1024, 3e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_3extra_pcm16.c b/libambix/tests/basic2extended_N3D4x4_3extra_pcm16.c
new file mode 100644
index 0000000..40069ef
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_3extra_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 3, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_3extra_pcm32.c b/libambix/tests/basic2extended_N3D4x4_3extra_pcm32.c
new file mode 100644
index 0000000..1021c3b
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_3extra_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 3, 1024, 3e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_float32.c b/libambix/tests/basic2extended_N3D4x4_float32.c
new file mode 100644
index 0000000..c7c46c6
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 0, 1024, 3e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_float64.c b/libambix/tests/basic2extended_N3D4x4_float64.c
new file mode 100644
index 0000000..4c5e20e
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 0, 1024, 3e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_pcm16.c b/libambix/tests/basic2extended_N3D4x4_pcm16.c
new file mode 100644
index 0000000..f9e8181
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 0, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_N3D4x4_pcm32.c b/libambix/tests/basic2extended_N3D4x4_pcm32.c
new file mode 100644
index 0000000..0e0ad53
--- /dev/null
+++ b/libambix/tests/basic2extended_N3D4x4_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("N3D" , 4, 4, AMBIX_MATRIX_N3D , 0, 1024, 3e-8);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_3extra_float32.c b/libambix/tests/basic2extended_SID4x4_3extra_float32.c
new file mode 100644
index 0000000..86b2892
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_3extra_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 3, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_3extra_float64.c b/libambix/tests/basic2extended_SID4x4_3extra_float64.c
new file mode 100644
index 0000000..fe136f0
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_3extra_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 3, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_3extra_pcm16.c b/libambix/tests/basic2extended_SID4x4_3extra_pcm16.c
new file mode 100644
index 0000000..dcfd5b6
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_3extra_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 3, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_3extra_pcm32.c b/libambix/tests/basic2extended_SID4x4_3extra_pcm32.c
new file mode 100644
index 0000000..13b5c6c
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_3extra_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 3, 1024, 1e-9);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_float32.c b/libambix/tests/basic2extended_SID4x4_float32.c
new file mode 100644
index 0000000..626d9f5
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 0, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_float64.c b/libambix/tests/basic2extended_SID4x4_float64.c
new file mode 100644
index 0000000..c744976
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 0, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_pcm16.c b/libambix/tests/basic2extended_SID4x4_pcm16.c
new file mode 100644
index 0000000..6d087a8
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 0, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_SID4x4_pcm32.c b/libambix/tests/basic2extended_SID4x4_pcm32.c
new file mode 100644
index 0000000..292ceb9
--- /dev/null
+++ b/libambix/tests/basic2extended_SID4x4_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("SID" , 4, 4, AMBIX_MATRIX_SID , 0, 1024, 1e-9);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_3extra_float32.c b/libambix/tests/basic2extended_identity4x4_3extra_float32.c
new file mode 100644
index 0000000..362602b
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_3extra_float32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 3, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_3extra_float64.c b/libambix/tests/basic2extended_identity4x4_3extra_float64.c
new file mode 100644
index 0000000..42776a3
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_3extra_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 3, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_3extra_pcm16.c b/libambix/tests/basic2extended_identity4x4_3extra_pcm16.c
new file mode 100644
index 0000000..086ecb6
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_3extra_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 3, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_3extra_pcm32.c b/libambix/tests/basic2extended_identity4x4_3extra_pcm32.c
new file mode 100644
index 0000000..9f1a322
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_3extra_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 3, 1024, 1e-9);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_float32.c b/libambix/tests/basic2extended_identity4x4_float32.c
new file mode 100644
index 0000000..28356c2
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_float32.c
@@ -0,0 +1,27 @@
+#include "common_basic2extended.h"
+
+#ifndef FMT
+# define FMT FLOAT32
+#endif
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps, ambixtest_presentationformat_t fmt) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, fmt, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY1024:" STRINGIFY(FMT), 4, 4, AMBIX_MATRIX_IDENTITY, 0, 1024, 0, FMT);
+ err+=test_defaultmatrix("IDENTITY0000:" STRINGIFY(FMT), 4, 4, AMBIX_MATRIX_IDENTITY, 0, 0, 0, FMT);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_float32__f64.c b/libambix/tests/basic2extended_identity4x4_float32__f64.c
new file mode 100644
index 0000000..3cc43b2
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_float32__f64.c
@@ -0,0 +1,2 @@
+#define FMT FLOAT64
+#include "basic2extended_identity4x4_float32.c"
diff --git a/libambix/tests/basic2extended_identity4x4_float32__i16.c b/libambix/tests/basic2extended_identity4x4_float32__i16.c
new file mode 100644
index 0000000..bb52167
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_float32__i16.c
@@ -0,0 +1,2 @@
+#define FMT INT16
+#include "basic2extended_identity4x4_float32.c"
diff --git a/libambix/tests/basic2extended_identity4x4_float32__i32.c b/libambix/tests/basic2extended_identity4x4_float32__i32.c
new file mode 100644
index 0000000..8353436
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_float32__i32.c
@@ -0,0 +1,2 @@
+#define FMT INT32
+#include "basic2extended_identity4x4_float32.c"
diff --git a/libambix/tests/basic2extended_identity4x4_float64.c b/libambix/tests/basic2extended_identity4x4_float64.c
new file mode 100644
index 0000000..f4a350c
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_float64.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 0, 1024, 0);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_pcm16.c b/libambix/tests/basic2extended_identity4x4_pcm16.c
new file mode 100644
index 0000000..f6ae9b0
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_pcm16.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 0, 1024, 4e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_identity4x4_pcm32.c b/libambix/tests/basic2extended_identity4x4_pcm32.c
new file mode 100644
index 0000000..9422c7d
--- /dev/null
+++ b/libambix/tests/basic2extended_identity4x4_pcm32.c
@@ -0,0 +1,22 @@
+#include "common_basic2extended.h"
+
+int test_defaultmatrix(const char*name, uint32_t rows, uint32_t cols, ambix_matrixtype_t mtyp,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill(mtx, mtyp);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_defaultmatrix("IDENTITY", 4, 4, AMBIX_MATRIX_IDENTITY, 0, 1024, 1e-9);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_3extra_float32.c b/libambix/tests/basic2extended_rand4x7_3extra_float32.c
new file mode 100644
index 0000000..63089f6
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_3extra_float32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 3, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_3extra_float64.c b/libambix/tests/basic2extended_rand4x7_3extra_float64.c
new file mode 100644
index 0000000..6c49891
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_3extra_float64.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 3, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_3extra_pcm16.c b/libambix/tests/basic2extended_rand4x7_3extra_pcm16.c
new file mode 100644
index 0000000..4500166
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_3extra_pcm16.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[5x7]", 4, 7, data_4_7 , 3, 1024, 7e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_3extra_pcm32.c b/libambix/tests/basic2extended_rand4x7_3extra_pcm32.c
new file mode 100644
index 0000000..6755ba6
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_3extra_pcm32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 3, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_float32.c b/libambix/tests/basic2extended_rand4x7_float32.c
new file mode 100644
index 0000000..7488f53
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_float32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 0, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_float64.c b/libambix/tests/basic2extended_rand4x7_float64.c
new file mode 100644
index 0000000..74a4006
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_float64.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 0, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_pcm16.c b/libambix/tests/basic2extended_rand4x7_pcm16.c
new file mode 100644
index 0000000..2444488
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_pcm16.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 0, 1024, 7e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x7_pcm32.c b/libambix/tests/basic2extended_rand4x7_pcm32.c
new file mode 100644
index 0000000..cfa1298
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x7_pcm32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_7[]={
+0.588219, 0.758465, 0.240167, 0.827193, 0.899134, 0.121186, 0.974490,
+0.079994, 0.828276, 0.223099, 0.525774, 0.895537, 0.884317, 0.434495,
+0.426266, 0.302895, 0.341656, 0.325299, 0.474342, 0.677271, 0.185883,
+0.183465, 0.654321, 0.243639, 0.779875, 0.250082, 0.939078, 0.449736,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x7]", 4, 7, data_4_7 , 0, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_3extra_float32.c b/libambix/tests/basic2extended_rand4x9_3extra_float32.c
new file mode 100644
index 0000000..4e8c330
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_3extra_float32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 3, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_3extra_float64.c b/libambix/tests/basic2extended_rand4x9_3extra_float64.c
new file mode 100644
index 0000000..aee794a
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_3extra_float64.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 3, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_3extra_pcm16.c b/libambix/tests/basic2extended_rand4x9_3extra_pcm16.c
new file mode 100644
index 0000000..22b2d5c
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_3extra_pcm16.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 3, 1024, 9e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_3extra_pcm32.c b/libambix/tests/basic2extended_rand4x9_3extra_pcm32.c
new file mode 100644
index 0000000..ae733c6
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_3extra_pcm32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 3, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_float32.c b/libambix/tests/basic2extended_rand4x9_float32.c
new file mode 100644
index 0000000..fe62715
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_float32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 0, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_float64.c b/libambix/tests/basic2extended_rand4x9_float64.c
new file mode 100644
index 0000000..1bec76e
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_float64.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 0, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_pcm16.c b/libambix/tests/basic2extended_rand4x9_pcm16.c
new file mode 100644
index 0000000..91fcfa4
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_pcm16.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 0, 1024, 9e-5);
+ return pass();
+}
diff --git a/libambix/tests/basic2extended_rand4x9_pcm32.c b/libambix/tests/basic2extended_rand4x9_pcm32.c
new file mode 100644
index 0000000..7287b50
--- /dev/null
+++ b/libambix/tests/basic2extended_rand4x9_pcm32.c
@@ -0,0 +1,29 @@
+#include "common_basic2extended.h"
+
+float32_t data_4_9[]={
+ 0.519497, 0.101224, 0.775246, 0.219242, 0.795973, 0.649863, 0.190978, 0.837028, 0.763130,
+ 0.165074, 0.276581, 0.220167, 0.383229, 0.937749, 0.381838, 0.025107, 0.846256, 0.773257,
+ 0.546205, 0.501742, 0.476078, 0.539815, 0.671716, 0.069030, 0.748010, 0.369414, 0.667491,
+ 0.192167, 0.936164, 0.792496, 0.447073, 0.689901, 0.618242, 0.769460, 0.815128, 0.466140,
+};
+
+int test_datamatrix(const char*name, uint32_t rows, uint32_t cols, float32_t*data,
+ uint32_t xtrachannels, uint32_t chunksize, float32_t eps) {
+ int result=0;
+ ambix_matrix_t*mtx=0;
+ STARTTEST("%s\n", name);
+ mtx=ambix_matrix_init(rows,cols,mtx);
+ if(!mtx)return 1;
+ ambix_matrix_fill_data(mtx, data);
+ result=check_create_b2e(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32,
+ mtx,xtrachannels,
+ chunksize, FLOAT32, eps);
+ ambix_matrix_destroy(mtx);
+ return result;
+}
+
+int main(int argc, char**argv) {
+ int err=0;
+ err+=test_datamatrix ("'rand'[4x9]", 4, 9, data_4_9 , 0, 1024, 5e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic_float32.c b/libambix/tests/basic_float32.c
new file mode 100644
index 0000000..d469403
--- /dev/null
+++ b/libambix/tests/basic_float32.c
@@ -0,0 +1,7 @@
+#include "common.h"
+void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
+
+int main(int argc, char**argv) {
+ check_create_simple(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32, 1e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic_float64.c b/libambix/tests/basic_float64.c
new file mode 100644
index 0000000..233aea3
--- /dev/null
+++ b/libambix/tests/basic_float64.c
@@ -0,0 +1,7 @@
+#include "common.h"
+void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
+
+int main(int argc, char**argv) {
+ check_create_simple(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64, 1e-7);
+ return pass();
+}
diff --git a/libambix/tests/basic_pcm16.c b/libambix/tests/basic_pcm16.c
new file mode 100644
index 0000000..79804bf
--- /dev/null
+++ b/libambix/tests/basic_pcm16.c
@@ -0,0 +1,7 @@
+#include "common.h"
+void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
+
+int main(int argc, char**argv) {
+ check_create_simple(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16, 1./20000.);
+ return pass();
+}
diff --git a/libambix/tests/basic_pcm32.c b/libambix/tests/basic_pcm32.c
new file mode 100644
index 0000000..3bbddc9
--- /dev/null
+++ b/libambix/tests/basic_pcm32.c
@@ -0,0 +1,7 @@
+#include "common.h"
+void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
+
+int main(int argc, char**argv) {
+ check_create_simple(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32, 1e-5);
+ return pass();
+}
diff --git a/libambix/tests/common.c b/libambix/tests/common.c
index 0ac5d44..91713c4 100644
--- a/libambix/tests/common.c
+++ b/libambix/tests/common.c
@@ -1,6 +1,6 @@
/* common test functionality
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -23,9 +23,36 @@
#include "common.h"
#include <math.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <string.h>
+
+static char* snprintdata(char*out, size_t size, ambixtest_presentationformat_t fmt, const void*data, uint64_t index) {
+ switch(fmt) {
+ case INT16 :
+ snprintf(out, size, "%d", ((int16_t*)data)[index]);
+ break;
+ case INT32 :
+ snprintf(out, size, "%d", ((int32_t*)data)[index]);
+ break;
+ case FLOAT32:
+ snprintf(out, size, "%g", ((float32_t*)data)[index]);
+ break;
+ case FLOAT64:
+ snprintf(out, size, "%g", ((float64_t*)data)[index]);
+ break;
+ default :
+ snprintf(out, size, "???");
+ break;
+ }
+ out[size-1]=0;
+ return out;
+}
void matrix_print(const ambix_matrix_t*mtx) {
- printf("matrix [%dx%d]\n", mtx->rows, mtx->cols);
+ printf("matrix[%p] ", mtx);
+ printf(" [%dx%d]@%p\n", mtx->rows, mtx->cols, mtx->data);
if(mtx->data) {
uint32_t c, r;
for(r=0; r<mtx->rows; r++) {
@@ -55,59 +82,85 @@ float32_t matrix_diff(uint32_t line, const ambix_matrix_t*A, const ambix_matrix_
for(c=0; c<B->cols; c++) {
float32_t v=a[r][c]-b[r][c];
float32_t vabs=(v<0)?-v:v;
- fail_if(isnan(v), line, "[%d|%d] is NaN: %f <-> %f", r, c, a[r][c], b[r][c]);
+ if(isnan(v))return v;
if(vabs>maxdiff)
maxdiff=vabs;
sum+=vabs;
if(vabs>eps) {
overcount++;
if(overcount<MAX_OVER)
- printf("%f - %f=%f @ [%02d|%02d]\n", a[r][c], b[r][c], v, r, c);
+ printf("%+f - %+f = %+g @ [%02d|%02d]\n", a[r][c], b[r][c], v, r, c);
}
}
if(overcount>MAX_OVER)
- printf("accumulated error %f over %d/%d frames\n", sum, (int)overcount, (int)(A->cols*B->rows));
+ printf("[%d] accumulated error %f over %d/%d frames (eps=%g)\n", line, sum, (int)overcount, (int)(A->cols*B->rows), eps);
return maxdiff;
}
-float32_t data_diff(uint32_t line, const float32_t*A, const float32_t*B, uint64_t frames, float32_t eps) {
+float32_t data_diff(uint32_t line,
+ ambixtest_presentationformat_t fmt,
+ const void*A, const void*B, uint64_t frames,
+ float32_t eps) {
uint64_t i;
float32_t sum=0.;
float32_t maxdiff=-1.f;
uint64_t overcount=0;
+ char aout[16];
+ char bout[16];
fail_if((NULL==A), line, "left-hand data of datadiff is NULL");
fail_if((NULL==B), line, "right-hand data of datadiff is NULL");
for(i=0; i<frames; i++) {
- float32_t v=A[i]-B[i];
- float32_t vabs=(v<0)?-v:v;
- fail_if(isnan(v), line, "[%d] is NaN: %f <-> %f", i, A[i], B[i]);
+ float64_t v=0;
+ float64_t vabs=0;
+ switch(fmt) {
+ case INT16 :
+ v=((int16_t*)A)[i]-((int16_t*)B)[i];
+ break;
+ case INT32 :
+ v=((int32_t*)A)[i]-((int32_t*)B)[i];
+ break;
+ case FLOAT32:
+ v=((float32_t*)A)[i]-((float32_t*)B)[i];
+ break;
+ case FLOAT64:
+ v=((float64_t*)A)[i]-((float64_t*)B)[i];
+ break;
+ default: break;
+ }
+ fail_if(isnan(v), line, "[%d] is NaN: %s <-> %s", i,
+ snprintdata(aout, 16, fmt, A, i),
+ snprintdata(bout, 16, fmt, B, i));
+ vabs=(v<0)?-v:v;
if(vabs>maxdiff)
maxdiff=vabs;
sum+=vabs;
if(vabs>eps) {
overcount++;
if(overcount<MAX_OVER)
- printf("%f - %f=%f @ %d\n", A[i], B[i], v, (int)i);
+ printf("%s - %s=%g @ %d\n",
+ snprintdata(aout, 16, fmt, A, i),
+ snprintdata(bout, 16, fmt, B, i),
+ v, (int)i);
}
}
if(overcount>MAX_OVER)
- printf("accumulated error %f over %d/%d frames\n", sum, (int)overcount, (int)frames);
+ printf("[%d] accumulated error %f over %d/%d frames (eps=%g)\n", line, sum, (int)overcount, (int)frames, eps);
return maxdiff;
}
-void data_print(const float32_t*data, uint64_t frames) {
+void data_print(ambixtest_presentationformat_t fmt, const void*data, uint64_t frames) {
uint64_t i;
+ char out[16];
for(i=0; i<frames; i++) {
- float f=*data++;
- printf("%05d: %f\n", (int)i, f);
+ printf("%05d: %s\n", (int)i, snprintdata(out, 16, fmt, data, i));
}
}
@@ -123,37 +176,142 @@ void data_transpose(float32_t*outdata, const float32_t*indata, uint32_t inrows,
}
}
+static void setdata(ambixtest_presentationformat_t fmt, void*data, uint64_t index, float64_t value) {
+ switch(fmt) {
+ case INT16 :
+ ((int16_t*)data)[index]=(int16_t)(value*32768.);
+ break;
+ case INT32 :
+ ((int32_t*)data)[index]=(int32_t)(value*2147483648.);
+ break;
+ case FLOAT32:
+ ((float32_t*)data)[index]=(float32_t)value;
+ break;
+ case FLOAT64:
+ ((float64_t*)data)[index]=(float64_t)value;
+ break;
+ default : break;
+ }
+}
+
+size_t data_size(ambixtest_presentationformat_t fmt) {
+ switch(fmt) {
+ case INT16 : return 2;
+ case INT32 : return 4;
+ case FLOAT32: return 4;
+ case FLOAT64: return 8;
+ default : break;
+ }
+ return 0;
+}
+
+void*data_calloc(ambixtest_presentationformat_t fmt, size_t nmembers) {
+ size_t nmemb=nmembers*data_size(fmt)/sizeof(float64_t)+1;
+ size_t size = sizeof(float64_t);
+ void*data=calloc(nmemb, size);
+ //printf("%dx%d[%d] allocated %d of %d bytes to %p\n", (int)frames, channels, fmt, (int)nmemb, (int)size, data);
+ return data;
+}
-float32_t*data_sine(uint64_t frames, uint32_t channels, float32_t freq) {
- float32_t periods=44100./freq;
- float32_t*data=(float32_t*)calloc(frames*channels, sizeof(float32_t));
- float32_t*datap=data;
+void*data_sine(ambixtest_presentationformat_t fmt, uint64_t frames, uint32_t channels, float32_t freq) {
+ float32_t periods=freq/44100.;
+ void*data=data_calloc(fmt, frames*channels);
int64_t frame;
for(frame=0; frame<frames; frame++) {
- // float f=(float32_t)frame*periods/(float32_t)frames;
- float f=(float32_t)frame*periods;
- float32_t value=0.5*sinf(f);
int32_t chan;
+ float64_t f=(float64_t)frame*periods;
+ float64_t value=0.5*sinf(f);
for(chan=0; chan<channels; chan++)
- *datap++=value;
+ setdata(fmt, data, f*channels+chan, value);
}
return data;
}
-float32_t*data_ramp(uint64_t frames, uint32_t channels) {
- float32_t*data=(float32_t*)calloc(frames*channels, sizeof(float32_t));
- float32_t*datap=data;
+void*data_ramp(ambixtest_presentationformat_t fmt, uint64_t frames, uint32_t channels) {
+ void*data=data_calloc(fmt, frames*channels);
double increment=1./(double)frames;
double value=0.;
int64_t frame;
for(frame=0; frame<frames; frame++) {
- value+=increment;
int32_t chan;
+ float32_t v32=value-0.5;
+ value+=increment;
for(chan=0; chan<channels; chan++)
- *datap++=(value-0.5);
+ setdata(fmt, data, frame*channels+chan, v32);
}
return data;
}
+int64_t ambixtest_readf (ambix_t *ambix, ambixtest_presentationformat_t fmt,
+ void*ambidata , uint64_t ambioffset,
+ void*otherdata, uint64_t otheroffset,
+ int64_t frames) {
+ switch(fmt) {
+ case INT16 :
+ return ambix_readf_int16(ambix, ((int16_t*)ambidata)+ambioffset, ((int16_t*)otherdata)+otheroffset, frames);
+ case INT32 :
+ return ambix_readf_int32(ambix, ((int32_t*)ambidata)+ambioffset, ((int32_t*)otherdata)+otheroffset, frames);
+ case FLOAT32:
+ return ambix_readf_float32(ambix, ((float32_t*)ambidata)+ambioffset, ((float32_t*)otherdata)+otheroffset, frames);
+ case FLOAT64:
+ return ambix_readf_float64(ambix, ((float64_t*)ambidata)+ambioffset, ((float64_t*)otherdata)+otheroffset, frames);
+ default : break;
+ }
+ return -1;
+}
+
+int64_t ambixtest_writef (ambix_t *ambix, ambixtest_presentationformat_t fmt,
+ const void*ambidata , const uint64_t ambioffset,
+ const void*otherdata, const uint64_t otheroffset,
+ int64_t frames) {
+ switch(fmt) {
+ case INT16 :
+ return ambix_writef_int16(ambix,
+ ((const int16_t*)ambidata)+ambioffset, ((const int16_t*)otherdata)+otheroffset,
+ frames);
+ case INT32 :
+ return ambix_writef_int32(ambix,
+ ((const int32_t*)ambidata)+ambioffset, ((const int32_t*)otherdata)+otheroffset,
+ frames);
+ case FLOAT32:
+ return ambix_writef_float32(ambix,
+ ((const float32_t*)ambidata)+ambioffset, ((const float32_t*)otherdata)+otheroffset,
+ frames);
+ case FLOAT64:
+ return ambix_writef_float64(ambix,
+ ((const float64_t*)ambidata)+ambioffset, ((const float64_t*)otherdata)+otheroffset,
+ frames);
+ default : break;
+ }
+ return -1;
+}
+
+int ambixtest_rmfile(const char*path) {
+ /* only remove if AMBIXTEST_KEEPFILES is not set */
+ if(NULL==getenv("AMBIXTEST_KEEPFILES"))return unlink(path);
+ return 0;
+}
+int ambixtest_uniquenumber() {
+#ifdef HAVE_UNISTD_H
+ return getpid();
+#endif
+ return 0;
+}
+const char*getbasename(const char*fullpath) {
+ char*pos=NULL;
+ if(!fullpath)return "";
+ pos=strrchr(fullpath, '/');
+ if(pos)return pos+1;
+ return fullpath;
+}
+char*ambixtest_getfname(char*inbuf, size_t length, const char*path_, const char*basename_, const char*ext_) {
+ static unsigned int count=0;
+ const char*ext=(ext_)?ext_:".caf";
+ const char*path=(path_)?path_:"";
+ const char*basename=getbasename(basename_);
+ snprintf(inbuf, length, "%s%s-%d.%d%s", path, basename, ambixtest_uniquenumber(), count, ext);
+ count++;
+ return inbuf;
+}
diff --git a/libambix/tests/common.h b/libambix/tests/common.h
index 46bb1c6..7dc685f 100644
--- a/libambix/tests/common.h
+++ b/libambix/tests/common.h
@@ -26,16 +26,21 @@
#include <ambix/ambix.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <stdlib.h>
-static inline void pass(void) {exit(0); }
-static inline void fail(void) {exit(1); }
-static inline void skip(void) {exit(77); }
+static inline int my_exit(int i) {exit(i); return i;}
+static inline int pass(void) {return my_exit(0); }
+static inline int fail(void) {return my_exit(1); }
+static inline int skip(void) {return my_exit(77); }
#include <stdio.h>
#include <stdarg.h>
#define MARK() printf("%s:%d[%s]\n", __FILE__, __LINE__, __FUNCTION__)
-static inline void pass_if (int test, int line, const char *format, ...)
+static inline int pass_if (int test, int line, const char *format, ...)
{
if (test) {
va_list argptr ;
@@ -44,10 +49,11 @@ static inline void pass_if (int test, int line, const char *format, ...)
vprintf (format, argptr) ;
va_end (argptr) ;
printf("\n");
- pass();
+ return pass();
} ;
+ return test;
} /* pass_if */
-static inline void skip_if (int test, int line, const char *format, ...)
+static inline int skip_if (int test, int line, const char *format, ...)
{
if (test) {
va_list argptr ;
@@ -56,10 +62,11 @@ static inline void skip_if (int test, int line, const char *format, ...)
vprintf (format, argptr) ;
va_end (argptr) ;
printf("\n");
- skip();
+ return skip();
} ;
+ return test;
} /* skip_if */
-static inline void fail_if (int test, int line, const char *format, ...)
+static inline int fail_if (int test, int line, const char *format, ...)
{
if (test) {
va_list argptr ;
@@ -68,22 +75,62 @@ static inline void fail_if (int test, int line, const char *format, ...)
vprintf (format, argptr) ;
va_end (argptr) ;
printf("\n");
- fail();
+ return fail();
} ;
+ return test;
} /* fail_if */
+static inline int print_if (int test, int line, const char *format, ...)
+{
+ if (test) {
+ va_list argptr ;
+ printf("@%d: ", line);
+ va_start (argptr, format) ;
+ vprintf (format, argptr) ;
+ va_end (argptr) ;
+ printf("\n");
+ }
+ return test;
+} /* print_if */
+
+typedef enum {
+ INT16,
+ INT32,
+ FLOAT32,
+ FLOAT64
+} ambixtest_presentationformat_t;
+
void matrix_print(const ambix_matrix_t*mtx);
float32_t matrix_diff(uint32_t line, const ambix_matrix_t*A, const ambix_matrix_t*B, float32_t eps);
-void data_print(const float32_t*data, uint64_t frames);
-float32_t data_diff(uint32_t line, const float32_t*A, const float32_t*B, uint64_t frames, float32_t eps);
+void data_print(ambixtest_presentationformat_t fmt, const void*data, uint64_t frames);
+float32_t data_diff(uint32_t line, ambixtest_presentationformat_t fmt, const void*A, const void*B, uint64_t frames, float32_t eps);
+size_t data_size(ambixtest_presentationformat_t fmt);
+void*data_calloc(ambixtest_presentationformat_t fmt, size_t nmembers);
void data_transpose(float32_t*outdata, const float32_t*indata, uint32_t inrows, uint32_t incols);
-float32_t*data_sine(uint64_t frames, uint32_t channels, float32_t periods);
-float32_t*data_ramp(uint64_t frames, uint32_t channels);
+void*data_sine(ambixtest_presentationformat_t fmt, uint64_t frames, uint32_t channels, float32_t periods);
+void*data_ramp(ambixtest_presentationformat_t fmt, uint64_t frames, uint32_t channels);
+
+int64_t ambixtest_readf (ambix_t *ambix, ambixtest_presentationformat_t fmt,
+ void*ambidata , uint64_t ambioffset,
+ void*otherdata, uint64_t otheroffset,
+ int64_t frames);
+int64_t ambixtest_writef (ambix_t *ambix, ambixtest_presentationformat_t fmt,
+ const void*ambidata , const uint64_t ambioffset,
+ const void*otherdata, const uint64_t otheroffset,
+ int64_t frames);
+int ambixtest_rmfile(const char*path);
+int ambixtest_uniquenumber(void);
+/* write uniquish filename into 'inbuf' and return a pointer to it
+ * if ext is NULL, it defaults to '.caf'*/
+char*ambixtest_getfname(char*inbuf, size_t length, const char*path, const char*basename, const char*ext);
+#define FILENAME_MAIN ambixtest_getfname(alloca(1024), 1024, 0, argv[0], 0)
+#define FILENAME_FILE ambixtest_getfname(alloca(1024), 1024, 0, __FILE__, 0)
#define STRINGIFY(x) #x
-#define STARTTEST(x) printf("============ %s[%04d]:\t%s '%s'\n", __FILE__, __LINE__, __FUNCTION__, x)
+#define STARTTEST printf("<<< running TEST %s[%04d]:%s\t", __FILE__, __LINE__, __FUNCTION__),printf
+#define STOPTEST printf(">>> test SUCCESS %s[%04d]:%s\t", __FILE__, __LINE__, __FUNCTION__),printf
#endif /* TESTS_COMMON_H */
diff --git a/libambix/tests/ambix_simple.c b/libambix/tests/common_basic.c
similarity index 90%
rename from libambix/tests/ambix_simple.c
rename to libambix/tests/common_basic.c
index 9ed13b4..3d62af9 100644
--- a/libambix/tests/ambix_simple.c
+++ b/libambix/tests/common_basic.c
@@ -1,6 +1,6 @@
/* simple - test ambix simple
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -31,7 +31,7 @@ void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t
float32_t*orgdata,*data,*resultdata;
uint32_t frames=441000;
uint32_t channels=4;
- float32_t periods=20000;
+ float32_t periods=4724;
int64_t err64;
float32_t diff=0.;
uint32_t gotframes;
@@ -55,8 +55,8 @@ void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t
ambix=ambix_open(path, AMBIX_WRITE, &rinfo);
fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path);
- orgdata=data_sine(frames, channels, periods);
- //data_print(orgdata, 100);
+ orgdata=data_sine(FLOAT32, frames, channels, periods);
+ //data_print(FLOAT32, orgdata, 100);
memcpy(data, orgdata, frames*channels*sizeof(float32_t));
@@ -65,7 +65,7 @@ void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t
err64=ambix_writef_float32(ambix, data, NULL, frames);
fail_if((err64!=frames), __LINE__, "wrote only %d frames of %d", (int)err64, (int)frames);
- diff=data_diff(__LINE__, orgdata, data, frames*channels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgdata, data, frames*channels, eps);
fail_if((diff>eps), __LINE__, "data diff %f > %f", diff, eps);
fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix);
@@ -87,7 +87,7 @@ void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t
gotframes+=err64;
} while(err64>0 && gotframes<frames);
- diff=data_diff(__LINE__, orgdata, resultdata, frames*channels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgdata, resultdata, frames*channels, eps);
fail_if((diff>eps), __LINE__, "data diff %f > %f", diff, eps);
fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix);
@@ -97,7 +97,5 @@ void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t
free(resultdata);
free(orgdata);
- unlink(path);
+ ambixtest_rmfile(path);
}
-
-
diff --git a/libambix/tests/common_basic2extended.c b/libambix/tests/common_basic2extended.c
new file mode 100644
index 0000000..d7adb72
--- /dev/null
+++ b/libambix/tests/common_basic2extended.c
@@ -0,0 +1,199 @@
+/* common_simple2exetended - common function for writing extended files as simple files
+
+ Copyright © 2016 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Institute of Electronic Music and Acoustics (IEM),
+ University of Music and Dramatic Arts, Graz
+
+ This file is part of libambix
+
+ libambix is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ libambix is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include <string.h>
+
+uint32_t max_u32(uint32_t a, uint32_t b) { return (a>b)?a:b;}
+
+int check_create_b2e(const char*path, ambix_sampleformat_t format,
+ ambix_matrix_t*matrix, uint32_t extrachannels,
+ uint32_t chunksize, ambixtest_presentationformat_t fmt,float32_t eps) {
+ uint32_t fullambichannels = matrix?matrix->rows:0;
+ uint32_t ambixchannels = matrix?matrix->cols:0;
+ ambix_info_t info, rinfo, winfo;
+ ambix_t*ambix=NULL;
+ void*orgambidata,*ambidata,*resultambidata;
+ void*orgotherdata,*otherdata,*resultotherdata;
+ uint32_t framesize=441000;
+ float32_t periods=8192;
+ const ambix_matrix_t*mtx2=NULL;
+ int64_t err64, gotframes;
+ float32_t diff=0.;
+ ambix_err_t err=0;
+ STARTTEST("ambi=[%dx%d],extra=%d, format=%d datafmt=%d\n",
+ matrix?matrix->rows:-1, matrix?matrix->cols:-1, extrachannels, format, fmt);
+ resultambidata=data_calloc(fmt, max_u32(fullambichannels, ambixchannels)*framesize);
+ ambidata=data_calloc(fmt, fullambichannels*framesize);
+
+ resultotherdata=data_calloc(fmt, extrachannels*framesize);
+ otherdata=data_calloc(fmt, extrachannels*framesize);
+
+ memset(&info, 0, sizeof(info));
+ info.fileformat=AMBIX_EXTENDED;
+ info.ambichannels=ambixchannels;
+ info.extrachannels=extrachannels;
+ info.samplerate=44100;
+ info.sampleformat=format;
+
+ memcpy(&winfo, &info, sizeof(info));
+ /* we want to write an EXTENDED file using the BASIC api (full set) */
+ winfo.fileformat=AMBIX_BASIC;
+
+ ambix=ambix_open(path, AMBIX_WRITE, &winfo);
+ if(fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path))return 1;
+
+ orgambidata =data_sine(fmt, framesize, fullambichannels, periods);
+ orgotherdata=data_ramp(fmt, framesize, extrachannels);
+ if(fail_if((NULL==orgambidata), __LINE__, "couldn't create ambidata %dx%d sine @ %f", (int)framesize, (int)fullambichannels, (float)periods))return 1;
+ if(fail_if((NULL==orgotherdata), __LINE__, "couldn't create otherdata %dx%d sine @ %f", (int)framesize, (int)extrachannels, (float)periods))return 1;
+
+ memcpy(ambidata, orgambidata, framesize*fullambichannels*data_size(fmt));
+ memcpy(otherdata, orgotherdata, framesize*extrachannels*data_size(fmt));
+
+ err=ambix_set_adaptormatrix(ambix, matrix);
+#if 0
+ if(1 || AMBIX_ERR_SUCCESS!=err) {
+ ambix_matrix_t*pinv=0;
+ //printf("adaptor matrix:\n"); matrix_print(matrix);
+ pinv=ambix_matrix_pinv(matrix, pinv);
+ if(pinv) {
+ //printf("pseudo-inverse:\n"); matrix_print(pinv);
+ } else {
+ //printf("no pseudo-inverse!\n");
+ ;
+ }
+ if(pinv)ambix_matrix_destroy(pinv);
+ }
+#endif
+ if(fail_if((AMBIX_ERR_SUCCESS!=err), __LINE__, "failed setting adaptor matrix [%d]", err))return 1;
+
+ if(chunksize>0) {
+ uint32_t subframe=chunksize;
+ uint32_t chunks = framesize/chunksize;
+ uint32_t framesleft=framesize;
+ uint32_t frame;
+ for(frame=0; frame<chunks; frame++) {
+ err64=ambixtest_writef(ambix, fmt,
+ ambidata, fullambichannels*frame*chunksize, otherdata, extrachannels*frame*chunksize,
+ chunksize);
+ if(fail_if((err64!=chunksize), __LINE__, "wrote only %d chunksize of %d", (int)err64, (int)chunksize))return 1;
+ framesleft-=chunksize;
+ }
+ subframe=framesleft;
+ err64=ambixtest_writef(ambix, fmt,
+ ambidata, fullambichannels*frame*chunksize,
+ otherdata,extrachannels*frame*chunksize,
+ subframe);
+ if(fail_if((err64!=subframe), __LINE__, "wrote only %d subframe of %d", (int)err64, (int)subframe))return 1;
+
+ } else {
+ err64=ambixtest_writef(ambix, fmt, ambidata, 0, otherdata, 0, framesize);
+ if(fail_if((err64!=framesize), __LINE__, "wrote only %d frames of %d", (int)err64, (int)framesize))return 1;
+ }
+
+ diff=data_diff(__LINE__, fmt, orgambidata, ambidata, framesize*fullambichannels, eps);
+ if(fail_if((diff>eps), __LINE__, "ambidata diff %f > %f", diff, eps))return 1;
+ diff=data_diff(__LINE__, fmt, orgotherdata, otherdata, framesize*extrachannels, eps);
+ if(fail_if((diff>eps), __LINE__, "otherdata diff %f > %f", diff, eps))return 1;
+
+ if(fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix))return 1;
+ ambix=NULL;
+
+ /* read data back via BASIC */
+ STARTTEST("readback BASIC\n");
+ memset(&rinfo, 0, sizeof(rinfo));
+ rinfo.fileformat = AMBIX_BASIC;
+ ambix=ambix_open(path, AMBIX_READ, &rinfo);
+ if(fail_if((NULL==ambix), __LINE__, "couldn't open ambix file '%s' for reading", path))return 1;
+
+ if(fail_if((AMBIX_BASIC!=rinfo.fileformat), __LINE__, "fileformat mismatch %d!=%d", (int)AMBIX_BASIC, (int)rinfo.fileformat))return 1;
+ if(fail_if((info.samplerate!=rinfo.samplerate), __LINE__, "samplerate mismatch %g!=%g", (float)info.samplerate, (float)rinfo.samplerate))return 1;
+ if(fail_if((info.sampleformat!=rinfo.sampleformat), __LINE__, "sampleformat mismatch %d!=%d", (int)info.sampleformat, (int)rinfo.sampleformat))return 1;
+ if(fail_if((fullambichannels!=rinfo.ambichannels), __LINE__, "ambichannels mismatch %d!=%d", (int)fullambichannels, (int)rinfo.ambichannels))return 1;
+ if(fail_if((info.extrachannels!=rinfo.extrachannels), __LINE__, "extrachannels mismatch %d!=%d", (int)info.extrachannels, (int)rinfo.extrachannels))return 1;
+
+ gotframes=0;
+ do {
+ err64=ambixtest_readf(ambix, fmt,
+ resultambidata,(gotframes*fullambichannels ),
+ resultotherdata,(gotframes*extrachannels),
+ (framesize-gotframes));
+ if(fail_if((err64<0), __LINE__, "reading frames failed after %d/%d frames", (int)gotframes, (int)framesize))return 1;
+ gotframes+=err64;
+ } while(err64>0 && gotframes<framesize);
+
+ diff=data_diff(__LINE__, fmt, orgambidata, resultambidata, framesize*fullambichannels, eps);
+ if(fail_if((diff>eps), __LINE__, "ambidata diff %f > %f", diff, eps))return 1;
+
+ diff=data_diff(__LINE__, fmt, orgotherdata, resultotherdata, framesize*extrachannels, eps);
+ if(fail_if((diff>eps), __LINE__, "otherdata diff %f > %f", diff, eps))return 1;
+
+ if(fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix))return 1;
+ ambix=NULL;
+
+ /* read data back via EXTENDED */
+ STARTTEST("readback EXTENDED\n");
+ memset(&rinfo, 0, sizeof(rinfo));
+ rinfo.fileformat = AMBIX_EXTENDED;
+
+ ambix=ambix_open(path, AMBIX_READ, &rinfo);
+ if(fail_if((NULL==ambix), __LINE__, "couldn't open ambix file '%s' for reading", path))return 1;
+
+ if(fail_if((AMBIX_EXTENDED!=rinfo.fileformat), __LINE__, "fileformat mismatch %d!=%d", (int)info.fileformat, (int)rinfo.fileformat))return 1;
+ if(fail_if((info.samplerate!=rinfo.samplerate), __LINE__, "samplerate mismatch %g!=%g", (float)info.samplerate, (float)rinfo.samplerate))return 1;
+ if(fail_if((info.sampleformat!=rinfo.sampleformat), __LINE__, "sampleformat mismatch %d!=%d", (int)info.sampleformat, (int)rinfo.sampleformat))return 1;
+ if(fail_if((info.ambichannels!=rinfo.ambichannels), __LINE__, "ambichannels mismatch %d!=%d", (int)info.ambichannels, (int)rinfo.ambichannels))return 1;
+ if(fail_if((info.extrachannels!=rinfo.extrachannels), __LINE__, "extrachannels mismatch %d!=%d", (int)info.extrachannels, (int)rinfo.extrachannels))return 1;
+
+ mtx2=ambix_get_adaptormatrix(ambix);
+ if(fail_if((NULL==mtx2), __LINE__, "failed reading adaptor matrix"))return 1;
+
+ diff=matrix_diff(__LINE__, matrix, mtx2, eps);
+ if(fail_if((diff>eps), __LINE__, "adaptormatrix diff %f > %f", diff, eps))return 1;
+
+ gotframes=0;
+ do {
+ err64=ambixtest_readf(ambix, fmt,
+ resultambidata,(gotframes*ambixchannels ),
+ resultotherdata,(gotframes*extrachannels),
+ (framesize-gotframes));
+ if(fail_if((err64<0), __LINE__, "reading frames failed after %d/%d frames", (int)gotframes, (int)framesize))return 1;
+ gotframes+=err64;
+ } while(err64>0 && gotframes<framesize);
+ diff=data_diff(__LINE__, fmt, orgotherdata, resultotherdata, framesize*extrachannels, eps);
+ if(fail_if((diff>eps), __LINE__, "otherdata diff %f > %f", diff, eps))return 1;
+
+ if(fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix))return 1;
+ ambix=NULL;
+
+ free(resultambidata);
+ free(ambidata);
+ free(resultotherdata);
+ free(otherdata);
+
+ free(orgambidata);
+ free(orgotherdata);
+
+ ambixtest_rmfile(path);
+ return 0;
+}
diff --git a/libambix/tests/none_float32.c b/libambix/tests/common_basic2extended.h
similarity index 64%
copy from libambix/tests/none_float32.c
copy to libambix/tests/common_basic2extended.h
index 176a0e8..2c72208 100644
--- a/libambix/tests/none_float32.c
+++ b/libambix/tests/common_basic2extended.h
@@ -1,4 +1,4 @@
-/* none_float32 - test ambix none (FLOAT32)
+/* tests/common_basic2extended.h - AMBIsonics eXchange Library test utilities -*- c -*-
Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
@@ -21,16 +21,17 @@
*/
+#ifndef TESTS_COMMON_BASIC2EXTENDED_H
+#define TESTS_COMMON_BASIC2EXTENDED_H
+
#include "common.h"
-#include <unistd.h>
-#include <string.h>
+
+/* specific helper-functions */
+int check_create_b2e(const char*path, ambix_sampleformat_t format,
+ ambix_matrix_t*matrix, uint32_t extrachannels,
+ uint32_t chunksize, ambixtest_presentationformat_t fmt,float32_t eps);
-void check_create_none(const char*path, ambix_sampleformat_t format);
-int main(int argc, char**argv) {
- check_create_none("test-simple.caf", AMBIX_SAMPLEFORMAT_FLOAT32);
+#endif /* TESTS_COMMON_BASIC2EXTENDED_H */
- pass();
- return 0;
-}
diff --git a/libambix/tests/ambix_extended.c b/libambix/tests/common_extended.c
similarity index 90%
rename from libambix/tests/ambix_extended.c
rename to libambix/tests/common_extended.c
index 7d4b46f..fc5adca 100644
--- a/libambix/tests/ambix_extended.c
+++ b/libambix/tests/common_extended.c
@@ -1,6 +1,6 @@
/* extended - test ambix extended
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -38,7 +38,7 @@ void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_
const ambix_matrix_t*eye2=NULL;
int64_t err64, gotframes;
float32_t diff=0.;
- STARTTEST("");
+ STARTTEST("\n");
printf("test using '%s' [%d] with chunks of %d and eps=%f\n", path, (int)format, (int)chunksize, eps);
@@ -65,9 +65,9 @@ void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_
ambix=ambix_open(path, AMBIX_WRITE, &rinfo);
fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path);
- orgambidata=data_sine(framesize, ambichannels, periods);
- orgotherdata=data_ramp(framesize, extrachannels);
- //data_print(orgdata, 100);
+ orgambidata=data_sine (FLOAT32, framesize, ambichannels, periods);
+ orgotherdata=data_ramp(FLOAT32, framesize, extrachannels);
+ //data_print(FLOAT32, orgdata, 100);
fail_if((NULL==orgambidata), __LINE__, "couldn't create ambidata %dx%d sine @ %f", (int)framesize, (int)ambichannels, (float)periods);
fail_if((NULL==orgotherdata), __LINE__, "couldn't create otherdata %dx%d sine @ %f", (int)framesize, (int)extrachannels, (float)periods);
@@ -98,9 +98,9 @@ void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_
fail_if((err64!=framesize), __LINE__, "wrote only %d frames of %d", (int)err64, (int)framesize);
}
- diff=data_diff(__LINE__, orgambidata, ambidata, framesize*ambichannels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgambidata, ambidata, framesize*ambichannels, eps);
fail_if((diff>eps), __LINE__, "ambidata diff %f > %f", diff, eps);
- diff=data_diff(__LINE__, orgotherdata, otherdata, framesize*extrachannels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgotherdata, otherdata, framesize*extrachannels, eps);
fail_if((diff>eps), __LINE__, "otherdata diff %f > %f", diff, eps);
fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix);
@@ -136,10 +136,10 @@ void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_
gotframes+=err64;
} while(err64>0 && gotframes<framesize);
- diff=data_diff(__LINE__, orgambidata, resultambidata, framesize*ambichannels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgambidata, resultambidata, framesize*ambichannels, eps);
fail_if((diff>eps), __LINE__, "ambidata diff %f > %f", diff, eps);
- diff=data_diff(__LINE__, orgotherdata, resultotherdata, framesize*extrachannels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgotherdata, resultotherdata, framesize*extrachannels, eps);
fail_if((diff>eps), __LINE__, "otherdata diff %f > %f", diff, eps);
fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix);
@@ -155,5 +155,5 @@ void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_
ambix_matrix_deinit(&eye);
- unlink(path);
+ ambixtest_rmfile(path);
}
diff --git a/libambix/tests/ambix_none.c b/libambix/tests/common_none.c
similarity index 91%
rename from libambix/tests/ambix_none.c
rename to libambix/tests/common_none.c
index 13452d2..69380f2 100644
--- a/libambix/tests/ambix_none.c
+++ b/libambix/tests/common_none.c
@@ -1,6 +1,6 @@
/* none - test ambix none
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -53,8 +53,8 @@ void check_create_none(const char*path, ambix_sampleformat_t format) {
ambix=ambix_open(path, AMBIX_WRITE, &rinfo);
fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path);
- orgdata=data_sine(frames, channels, periods);
- //data_print(orgdata, 100);
+ orgdata=data_sine(FLOAT32, frames, channels, periods);
+ //data_print(FLOAT32, orgdata, 100);
memcpy(data, orgdata, frames*channels*sizeof(float32_t));
@@ -63,7 +63,7 @@ void check_create_none(const char*path, ambix_sampleformat_t format) {
err64=ambix_writef_float32(ambix, NULL, data, frames);
fail_if((err64!=frames), __LINE__, "wrote only %d frames of %d", (int)err64, (int)frames);
- diff=data_diff(__LINE__, orgdata, data, frames*channels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgdata, data, frames*channels, eps);
fail_if((diff>eps), __LINE__, "data diff %f > %f", diff, eps);
fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix);
@@ -85,7 +85,7 @@ void check_create_none(const char*path, ambix_sampleformat_t format) {
gotframes+=err64;
} while(err64>0 && gotframes<frames);
- diff=data_diff(__LINE__, orgdata, resultdata, frames*channels, eps);
+ diff=data_diff(__LINE__, FLOAT32, orgdata, resultdata, frames*channels, eps);
fail_if((diff>eps), __LINE__, "data diff %f > %f", diff, eps);
fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix);
@@ -96,7 +96,5 @@ void check_create_none(const char*path, ambix_sampleformat_t format) {
free(data);
free(orgdata);
- unlink(path);
+ ambixtest_rmfile(path);
}
-
-
diff --git a/libambix/tests/const_matrix.c b/libambix/tests/const_matrix.c
new file mode 100644
index 0000000..6cb1678
--- /dev/null
+++ b/libambix/tests/const_matrix.c
@@ -0,0 +1,273 @@
+/* const_matrix - test constness in matrix operations
+
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Institute of Electronic Music and Acoustics (IEM),
+ University of Music and Dramatic Arts, Graz
+
+ This file is part of libambix
+
+ libambix is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ libambix is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "common.h"
+#include <string.h>
+
+static float32_t data_3_2[]= {
+ 0.22, 0.46,
+ 0.36, 0.53,
+ 0.77, 0.85,
+};
+static float32_t data_3_4[]= {
+ 0.320059925923633, -0.616572833442599, -0.758203952544301, 1.397070173352668,
+-0.475395139478048, -2.112396458091558, 1.443108803981482, -0.198593134445739,
+ 0.349719602203337, 2.683861685335670, -0.150602340058839, -0.196372558639406,
+};
+static float32_t data_4_4[]= {
+ 0.7131185686247925, 0.1054799265939327, 0.1882023608287114, 0.1496964665104298,
+ 0.9035382689904633, 0.0958506183093942, 0.1490156537909140, 0.6730762573692578,
+ 0.7110257215280688, 0.4278857180785819, 0.5050723092090162, 0.2342525090113509,
+ 0.1917073427152419, 0.3837280931544647, 0.0397484032568303, 0.5895499716980565,
+};
+static float32_t data_4_3[]= {
+ 0.19, 0.06, 0.14,
+ 0.05, 0.08, 0.44,
+ 0.25, 0.90, 0.77,
+ 0.83, 0.51, 0.58,
+};
+static float32_t data_4_2[]= {
+ 0.1712, 0.2382,
+ 0.3786, 0.4394,
+ 0.9719, 1.2465,
+ 0.8128, 1.1451,
+};
+
+
+static void test__amfd(unsigned int rows, unsigned int cols,
+ const float32_t*orgdata, unsigned long frames,
+ uint32_t line, float32_t eps) {
+ ambix_matrix_t*mtx=ambix_matrix_init(rows, cols, NULL);
+ float32_t*data=calloc(frames, sizeof(*orgdata));
+ float32_t errf=0;
+ STARTTEST("[%dx%d]\n", rows, cols);
+ /* make a copy of the org data, and verify it */
+ memcpy(data, orgdata, frames*sizeof(*orgdata));
+ errf = data_diff(line, FLOAT32, orgdata, data, frames, eps);
+ fail_if(!(errf<eps), line, "orgdata differs from memcpy by %g (>%g)", errf, eps);
+
+ /* fill in the data */
+ ambix_matrix_fill_data(mtx, data);
+
+ /* check if data has been modified */
+ errf = data_diff(line, FLOAT32, orgdata, data, frames, eps);
+ fail_if(!(errf<eps), line, "orgdata differs from filled data by %g (>%g)", errf, eps);
+
+ free(data);
+ ambix_matrix_destroy(mtx);
+}
+static void test_ambix_matrix_fill_data (float32_t eps) {
+ /*
+ ambix_err_t ambix_matrix_fill_data (ambix_matrix_t *mtx, const float32_t *data) ;
+ */
+ test__amfd(3, 2, data_3_2, sizeof(data_3_2)/sizeof(*data_3_2), __LINE__, eps);
+ test__amfd(3, 4, data_3_4, sizeof(data_3_4)/sizeof(*data_3_4), __LINE__, eps);
+ test__amfd(4, 2, data_4_2, sizeof(data_4_2)/sizeof(*data_4_2), __LINE__, eps);
+ test__amfd(4, 3, data_4_3, sizeof(data_4_3)/sizeof(*data_4_3), __LINE__, eps);
+ test__amfd(4, 4, data_4_4, sizeof(data_4_4)/sizeof(*data_4_4), __LINE__, eps);
+ STOPTEST("ALL\n");
+}
+
+static void test__amc(unsigned int rows, unsigned int cols,
+ const float32_t*orgdata, unsigned long frames,
+ uint32_t line, float32_t eps) {
+ ambix_matrix_t org_mtx;
+ float32_t**org_vectors=calloc(rows, sizeof(*org_vectors));
+ float32_t**org_data=calloc(rows, sizeof(*org_data));
+ ambix_matrix_t*mtx=ambix_matrix_init(rows, cols, NULL);
+ ambix_matrix_t*result=0;
+ ambix_matrix_fill_data(mtx, orgdata);
+ uint32_t r;
+
+ STARTTEST("[%dx%d]\n", rows, cols);
+ /* backup the matrix */
+ memcpy(&org_mtx, mtx, sizeof(org_mtx));
+ memcpy(org_vectors, mtx->data, rows*sizeof(*org_data));
+
+ for(r=0; r<rows; r++) {
+ org_data[r]=calloc(cols, sizeof(*org_data[r]));
+ memcpy(org_data[r], mtx->data[r], cols*sizeof(*org_data[r]));
+ }
+
+ /* call something */
+ result=ambix_matrix_copy(mtx, result);
+
+ /* check whether the mtx has been untouched */
+ fail_if(!(org_mtx.rows==mtx->rows && org_mtx.cols==mtx->cols), line,
+ "original matrix [%dx%d] does not match copied-from matrix [%dx%d]",
+ org_mtx.rows, org_mtx.cols, mtx->rows, mtx->cols);
+ fail_if(!(org_mtx.data==mtx->data), line,
+ "original matrix data [%p] does not match copied-from matrix data [%p]",
+ org_mtx.data, mtx->data);
+ for(r=0; r<org_mtx.rows; r++) {
+ float32_t*org_row=org_mtx.data[r];
+ float32_t*row =mtx->data[r];
+ float32_t errf=0;
+ fail_if(!(org_row == row), line,
+ "original matrix row[%d: %p] does not match copied-from matrix row[%d: %p]",
+ r, org_row, r, row);
+ /* compare the actual row-vector */
+ errf=data_diff(line, FLOAT32, org_data[r], mtx->data[r], cols, eps);
+ fail_if(!(errf<eps), line, "orgdata differs from copied-from data by %g (>%g)", errf, eps);
+ }
+
+ /* cleanup */
+ ambix_matrix_destroy(mtx);
+ ambix_matrix_destroy(result);
+ free(org_vectors);
+ for(r=0; r<rows; r++) {
+ free(org_data[r]);
+ }
+ free(org_data);
+}
+static void test_ambix_matrix_copy (float32_t eps) {
+ /*
+ ambix_matrix_t *ambix_matrix_copy (const ambix_matrix_t *src, ambix_matrix_t *dest) ;
+ */
+ test__amc(3, 2, data_3_2, sizeof(data_3_2)/sizeof(*data_3_2), __LINE__, eps);
+ test__amc(3, 4, data_3_4, sizeof(data_3_4)/sizeof(*data_3_4), __LINE__, eps);
+ test__amc(4, 2, data_4_2, sizeof(data_4_2)/sizeof(*data_4_2), __LINE__, eps);
+ test__amc(4, 3, data_4_3, sizeof(data_4_3)/sizeof(*data_4_3), __LINE__, eps);
+ test__amc(4, 4, data_4_4, sizeof(data_4_4)/sizeof(*data_4_4), __LINE__, eps);
+ STOPTEST("ALL\n");
+}
+static void test__amm (unsigned int rows1, unsigned int cols1, const float32_t*data1,
+ unsigned int rows2, unsigned int cols2, const float32_t*data2,
+ uint32_t line, float32_t eps) {
+ ambix_matrix_t*A=0, *B=0, *result=0;
+ ambix_matrix_t*A0=0, *B0=0;
+ float32_t errf=0;
+ STARTTEST("[%dx%d]*[%dx%d]\n", rows1, cols1, rows2, cols2);
+
+ A=ambix_matrix_init(rows1, cols1, A); ambix_matrix_fill_data(A, data1);
+ B=ambix_matrix_init(rows2, cols2, B); ambix_matrix_fill_data(B, data2);
+ A0=ambix_matrix_copy(A, A0); B0=ambix_matrix_copy(B, B0);
+ result=ambix_matrix_multiply(A, B, result);
+
+ errf=matrix_diff(line, A, A0, eps);
+ fail_if(!(errf<eps), line, "left-hand multiplication matrix has changed by %f (>%f)", errf, eps);
+ errf=matrix_diff(line, B, B0, eps);
+ fail_if(!(errf<eps), line, "right-hand multiplication matrix has changed by %f (>%f)", errf, eps);
+
+ if(A )ambix_matrix_destroy(A);
+ if(A0 )ambix_matrix_destroy(A0);
+ if(B )ambix_matrix_destroy(B);
+ if(B0 )ambix_matrix_destroy(B0);
+ if(result)ambix_matrix_destroy(result);
+}
+
+static void test_ambix_matrix_multiply (float32_t eps) {
+ /*
+ ambix_matrix_t *ambix_matrix_multiply (const ambix_matrix_t *A, const ambix_matrix_t *B, ambix_matrix_t *result) ;
+ */
+ test__amm(3,4,data_3_4, 4,4,data_4_4, __LINE__, eps);
+ test__amm(3,4,data_3_4, 4,3,data_4_3, __LINE__, eps);
+ test__amm(3,4,data_3_4, 4,2,data_4_2, __LINE__, eps);
+ test__amm(3,4,data_3_4, 3,2,data_3_4, __LINE__, eps);
+
+ STOPTEST("ALL\n");
+}
+static void test__amp(unsigned int rows, unsigned int cols,
+ const float32_t*data,
+ uint32_t line, float32_t eps) {
+ ambix_matrix_t*A=0, *A0=0, *result=0;
+ float32_t errf=0;
+ STARTTEST("[%dx%d]\n", rows, cols);
+
+ A=ambix_matrix_init(rows, cols, A); ambix_matrix_fill_data(A, data);
+ A0=ambix_matrix_copy(A, A0);
+
+ result=ambix_matrix_pinv(A, result);
+
+ errf=matrix_diff(line, A, A0, eps);
+ fail_if(!(errf<eps), line, "pseudo-inverted matrix has changed by %f (>%f)", errf, eps);
+
+ if(A )ambix_matrix_destroy(A);
+ if(A0 )ambix_matrix_destroy(A0);
+ if(result)ambix_matrix_destroy(result);
+}
+static void test_ambix_matrix_pinv(float32_t eps) {
+ /*
+ ambix_matrix_t* ambix_matrix_pinv(const ambix_matrix_t*matrix, ambix_matrix_t*pinv) ;
+ */
+ test__amp(3, 2, data_3_2, __LINE__, eps);
+ test__amp(3, 4, data_3_4, __LINE__, eps);
+ test__amp(4, 2, data_4_2, __LINE__, eps);
+ test__amp(4, 3, data_4_3, __LINE__, eps);
+ test__amp(4, 4, data_4_4, __LINE__, eps);
+}
+static void test_ambix_matrix_multiply_float32(float32_t eps) {
+ /*
+ ambix_err_t ambix_matrix_multiply_float32(float32_t *dest, const ambix_matrix_t *mtx, const float32_t *source, int64_t frames) ;
+ */
+ STARTTEST("\n");
+ STOPTEST("\n");
+}
+static void test_ambix_matrix_multiply_float64(float32_t eps) {
+ /*
+ ambix_err_t ambix_matrix_multiply_float64(float64_t *dest, const ambix_matrix_t *mtx, const float64_t *source, int64_t frames) ;
+ */
+ STARTTEST("\n");
+ STOPTEST("\n");
+}
+static void test_ambix_matrix_multiply_int32(float32_t eps) {
+ /*
+ ambix_err_t ambix_matrix_multiply_int32(int32_t *dest, const ambix_matrix_t *mtx, const int32_t *source, int64_t frames) ;
+ */
+ STARTTEST("\n");
+ STOPTEST("\n");
+}
+static void test_ambix_matrix_multiply_int16(float32_t eps) {
+ /*
+ ambix_err_t ambix_matrix_multiply_int16(int16_t *dest, const ambix_matrix_t *mtx, const int16_t *source, int64_t frames) ;
+ */
+ STARTTEST("\n");
+ STOPTEST("\n");
+}
+
+
+
+int main(int argc, char**argv) {
+ test_ambix_matrix_fill_data(1e-7);
+ test_ambix_matrix_copy(1e-7);
+ test_ambix_matrix_multiply(1e-7);
+ test_ambix_matrix_pinv(1e-7);
+
+#warning test_ambix_matrix_multiply_float32(1e-7);
+#warning test_ambix_matrix_multiply_float64(1e-7);
+#warning test_ambix_matrix_multiply_int32(1e-7);
+#warning test_ambix_matrix_multiply_int16(1e-7);
+
+ return pass();
+}
+
+#if 0
+/* FIXXME other constness tests */
+ambix_t *ambix_open (const char *path, const ambix_filemode_t mode, ambix_info_t *ambixinfo) ;
+int64_t ambix_writef_int16 (ambix_t *ambix, const int16_t *ambidata, const int16_t *otherdata, int64_t frames) ;
+int64_t ambix_writef_int32 (ambix_t *ambix, const int32_t *ambidata, const int32_t *otherdata, int64_t frames) ;
+int64_t ambix_writef_float32 (ambix_t *ambix, const float32_t *ambidata, const float32_t *otherdata, int64_t frames) ;
+int64_t ambix_writef_float64 (ambix_t *ambix, const float64_t *ambidata, const float64_t *otherdata, int64_t frames) ;
+ambix_err_t ambix_set_adaptormatrix (ambix_t *ambix, const ambix_matrix_t *matrix) ;
+/* need to test for LATER side-effects: e.g. ambix_set_adaptormatrix() might not do anything NOW, but sometimes later... */
+#endif
diff --git a/libambix/tests/data/Makefile.am b/libambix/tests/data/Makefile.am
new file mode 100644
index 0000000..9412cef
--- /dev/null
+++ b/libambix/tests/data/Makefile.am
@@ -0,0 +1,10 @@
+AUTOMAKE_OPTIONS = foreign
+
+EXTRA_DIST = file1.caf.org
+noinst_DATA=$(EXTRA_DIST:%.org=%)
+
+% :: %.org
+ cp $< $@
+
+clean-local:
+ rm -rf $(noinst_DATA)
diff --git a/libambix/tests/data/file1.caf b/libambix/tests/data/file1.caf.org
similarity index 100%
copy from libambix/tests/data/file1.caf
copy to libambix/tests/data/file1.caf.org
diff --git a/libambix/tests/data/foo.pd b/libambix/tests/data/foo.pd
new file mode 100644
index 0000000..8034140
--- /dev/null
+++ b/libambix/tests/data/foo.pd
@@ -0,0 +1,46 @@
+#N canvas 4 49 450 543 10;
+#X obj 183 105 soundfiler;
+#N canvas 8 49 450 300 tables 0;
+#X obj 100 100 table a0;
+#X obj 100 120 table a1;
+#X obj 100 140 table a2;
+#X obj 100 160 table a3;
+#X obj 100 180 table a4;
+#X obj 100 200 table a5;
+#X obj 100 220 table a6;
+#X obj 100 240 table a7;
+#X obj 100 260 table a8;
+#X restore 315 171 pd tables;
+#X msg 153 203 9;
+#X obj 153 247 until;
+#X obj 153 269 i;
+#X obj 153 291 + 1;
+#X msg 209 254 -1;
+#X obj 153 357 + 100;
+#X obj 153 379 pack;
+#X obj 153 423 s pd-tables;
+#X msg 220 367 clear;
+#X obj 152 225 t f b b;
+#X msg 153 401 obj 100 \$1 table a\$2;
+#X obj 153 313 t f f f;
+#X obj 153 335 * 20;
+#X msg 186 64 read -resize foo.wav a0 a1 a2 a3 a4 a5 a6 a7 a8;
+#X floatatom 183 127 5 0 0 0 - - -;
+#X connect 0 0 16 0;
+#X connect 2 0 11 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 13 0;
+#X connect 6 0 4 1;
+#X connect 7 0 8 0;
+#X connect 8 0 12 0;
+#X connect 10 0 9 0;
+#X connect 11 0 3 0;
+#X connect 11 1 6 0;
+#X connect 11 2 10 0;
+#X connect 12 0 9 0;
+#X connect 13 0 14 0;
+#X connect 13 1 8 1;
+#X connect 13 2 4 1;
+#X connect 14 0 7 0;
+#X connect 15 0 0 0;
diff --git a/libambix/tests/data/file1.caf b/libambix/tests/data/foo.wav
similarity index 99%
rename from libambix/tests/data/file1.caf
rename to libambix/tests/data/foo.wav
index 2afd73e..8788b1f 100644
Binary files a/libambix/tests/data/file1.caf and b/libambix/tests/data/foo.wav differ
diff --git a/libambix/tests/datatest.c b/libambix/tests/datatest.c
new file mode 100644
index 0000000..2e21c8a
--- /dev/null
+++ b/libambix/tests/datatest.c
@@ -0,0 +1,114 @@
+/* data - test generic data functionality
+
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Institute of Electronic Music and Acoustics (IEM),
+ University of Music and Dramatic Arts, Graz
+
+ This file is part of libambix
+
+ libambix is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ libambix is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "common.h"
+#include <string.h>
+#include <stdlib.h>
+
+static float32_t left[]= {
+ 0.19, 0.06, 0.14,
+ 0.05, 0.08, 0.44,
+ 0.25, 0.90, 0.77,
+ 0.83, 0.51, 0.58,
+};
+
+void do_diff(float32_t eps) {
+ float32_t errf;
+ unsigned int i;
+ unsigned int size=sizeof(left)/sizeof(*left);
+ float32_t*right=malloc(sizeof(left));
+ float32_t maxeps=eps;
+
+ STARTTEST("\n");
+ data_print(FLOAT32, left, size);
+
+ /* comparisons:
+ - left/right data is NULL
+ - non-failing tests:
+ - all values diff==0
+ - all values diff<eps
+ - few values diff<eps
+ - many values diff<eps
+ */
+ /* compare equal data */
+ STARTTEST("ident\n");
+ errf=data_diff(__LINE__, FLOAT32, left, left, size, eps);
+ fail_if(errf>0.f, __LINE__, "diffing mtx with itself returned %g (>%g)", errf, 0.f);
+
+ /* compare equal data */
+ STARTTEST("equal\n");
+ for(i=0; i<size; i++) {
+ right[i]=left[i];
+ }
+ errf=data_diff(__LINE__, FLOAT32, left, right, size, eps);
+ fail_if(errf>0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f);
+
+ /* compare data where all values differ, but <eps */
+ STARTTEST("all<eps\n");
+ for(i=0; i<size; i++) {
+ right[i]=left[i]+eps*0.5;
+ }
+ errf=data_diff(__LINE__, FLOAT32, left, right, size, eps);
+ fail_if(errf>eps, __LINE__, "diffing mtx with mtx+eps/2 returned %g (>%g)", errf, size, eps);
+ for(i=0; i<size; i++) {
+ right[i]=left[i]-eps*0.5;
+ }
+ errf=data_diff(__LINE__, FLOAT32, left, right, size, eps);
+ fail_if(errf>eps, __LINE__, "diffing mtx with mtx-eps/2 returned %g (>%g)", errf, size, eps);
+
+ /* compare data where many values differ with <eps; but one with >eps */
+ STARTTEST("most<eps;one>eps\n");
+ for(i=0; i<size; i++) {
+ right[i]=left[i];
+ }
+ for(i=0; i<(size/2); i++) {
+ right[i]=left[i]+eps*0.5;
+ }
+ right[0]=left[0]+eps*1.5;
+ errf=data_diff(__LINE__, FLOAT32, left, right, size, eps);
+ fail_if(errf>(eps*2.0), __LINE__, "diffing mtx with one value>eps returned %g (>%g)", errf, size, eps);
+ fail_if(errf<(eps*1.0), __LINE__, "diffing mtx with one value>eps returned %g (>%g)", errf, size, eps);
+
+ /* compare data where most values differ with >eps */
+ STARTTEST("most>eps\n");
+ for(i=0; i<size; i++) {
+ right[i]=left[i];
+ }
+ maxeps=eps*1.5;
+ for(i=0; i<(size-1); i++) {
+ right[i]=left[i]-maxeps;
+ }
+ errf=data_diff(__LINE__, FLOAT32, left, right, size, eps);
+ fail_if(errf<eps*1.0, __LINE__, "diffing mtx with one value>eps returned %g (<%g)", errf, eps*1.0);
+ fail_if(errf>eps*2.0, __LINE__, "diffing mtx with one value>eps returned %g (<%g)", errf, eps*2.0);
+
+ free(right);
+ STOPTEST("\n");
+}
+
+int main(int argc, char**argv) {
+ do_diff(1e-1);
+ do_diff(1e-7);
+
+ return pass();
+}
diff --git a/libambix/tests/debug_utils.c b/libambix/tests/debug_utils.c
new file mode 100644
index 0000000..048665a
--- /dev/null
+++ b/libambix/tests/debug_utils.c
@@ -0,0 +1,32 @@
+#include "common.h"
+#include "data.h"
+
+/* libambix's private header */
+#include "private.h"
+
+int main(int argc, char**argv) {
+ ambix_info_t*info=NULL;
+ ambix_matrix_t*mtx=NULL;
+ ambix_t*ambix=NULL;
+ _ambix_print_info(info);
+ _ambix_print_matrix(mtx);
+ _ambix_print_ambix(ambix);
+
+ info= calloc(1, sizeof(ambix_info_t));
+ ambix=ambix_open(AMBIXTEST_FILE1, AMBIX_READ, info);
+ fail_if(NULL==ambix, __LINE__, "File was not open");
+
+ _ambix_print_info(info);
+ _ambix_print_ambix(ambix);
+
+ ambix_close(ambix);
+ free(info);
+
+ mtx=ambix_matrix_init(4, 5, mtx);
+ _ambix_print_matrix(mtx);
+ mtx=ambix_matrix_fill(mtx, AMBIX_MATRIX_ONE);
+ _ambix_print_matrix(mtx);
+ ambix_matrix_destroy(mtx);
+
+ return pass();
+}
diff --git a/libambix/tests/extended_float32_0.c b/libambix/tests/extended_float32_0.c
index 187a716..7930001 100644
--- a/libambix/tests/extended_float32_0.c
+++ b/libambix/tests/extended_float32_0.c
@@ -1,25 +1,3 @@
-/* extended_float32_0 - test ambix extended (FLOAT32, blocksize 0)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
#include "common.h"
#include <unistd.h>
#include <string.h>
@@ -28,8 +6,7 @@
void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
int main(int argc, char**argv) {
- check_create_extended("test2-float32.caf",AMBIX_SAMPLEFORMAT_FLOAT32, 0, 1e-7);
+ check_create_extended(FILENAME_FILE,AMBIX_SAMPLEFORMAT_FLOAT32, 0, 1e-7);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/extended_float32_1024.c b/libambix/tests/extended_float32_1024.c
index ad0b316..5f899f2 100644
--- a/libambix/tests/extended_float32_1024.c
+++ b/libambix/tests/extended_float32_1024.c
@@ -1,25 +1,3 @@
-/* extended_float32_1024 - test ambix extended (FLOAT32, blocksize 1024)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
#include "common.h"
#include <unistd.h>
#include <string.h>
@@ -28,8 +6,7 @@
void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
int main(int argc, char**argv) {
- check_create_extended("test2-float32.caf",AMBIX_SAMPLEFORMAT_FLOAT32, 1024, 1e-7);
+ check_create_extended(FILENAME_FILE,AMBIX_SAMPLEFORMAT_FLOAT32, 1024, 1e-7);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/extended_float64_0.c b/libambix/tests/extended_float64_0.c
new file mode 100644
index 0000000..0b1600f
--- /dev/null
+++ b/libambix/tests/extended_float64_0.c
@@ -0,0 +1,12 @@
+#include "common.h"
+#include <unistd.h>
+#include <string.h>
+
+
+void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
+
+int main(int argc, char**argv) {
+ check_create_extended(FILENAME_FILE,AMBIX_SAMPLEFORMAT_FLOAT64, 0, 1e-7);
+
+ return pass();
+}
diff --git a/libambix/tests/extended_float64_1024.c b/libambix/tests/extended_float64_1024.c
new file mode 100644
index 0000000..07bb011
--- /dev/null
+++ b/libambix/tests/extended_float64_1024.c
@@ -0,0 +1,12 @@
+#include "common.h"
+#include <unistd.h>
+#include <string.h>
+
+
+void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
+
+int main(int argc, char**argv) {
+ check_create_extended(FILENAME_FILE,AMBIX_SAMPLEFORMAT_FLOAT64, 1024, 1e-7);
+
+ return pass();
+}
diff --git a/libambix/tests/extended_pcm16_0.c b/libambix/tests/extended_pcm16_0.c
index 579b390..b49d65b 100644
--- a/libambix/tests/extended_pcm16_0.c
+++ b/libambix/tests/extended_pcm16_0.c
@@ -1,25 +1,3 @@
-/* extended_pcm16_0 - test ambix extended (PCM16, blocksize 0)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
#include "common.h"
#include <unistd.h>
#include <string.h>
@@ -28,8 +6,7 @@
void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
int main(int argc, char**argv) {
- check_create_extended("test2-pcm16.caf", AMBIX_SAMPLEFORMAT_PCM16, 1024, 1./20000.);
+ check_create_extended(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16, 1024, 1./20000.);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/extended_pcm16_1024.c b/libambix/tests/extended_pcm16_1024.c
index 54cc9aa..b49d65b 100644
--- a/libambix/tests/extended_pcm16_1024.c
+++ b/libambix/tests/extended_pcm16_1024.c
@@ -1,25 +1,3 @@
-/* extended_pcm16_1024 - test ambix extended (PCM16, blocksize 1024)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
#include "common.h"
#include <unistd.h>
#include <string.h>
@@ -28,8 +6,7 @@
void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
int main(int argc, char**argv) {
- check_create_extended("test2-pcm16.caf", AMBIX_SAMPLEFORMAT_PCM16, 1024, 1./20000.);
+ check_create_extended(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM16, 1024, 1./20000.);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/extended_pcm32_0.c b/libambix/tests/extended_pcm32_0.c
index 39dcfb7..1c93bdb 100644
--- a/libambix/tests/extended_pcm32_0.c
+++ b/libambix/tests/extended_pcm32_0.c
@@ -1,25 +1,3 @@
-/* extended_pcm32_0 - test ambix extended (PCM32, blocksize 0)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
#include "common.h"
#include <unistd.h>
#include <string.h>
@@ -28,8 +6,7 @@
void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
int main(int argc, char**argv) {
- check_create_extended("test2-pcm32.caf", AMBIX_SAMPLEFORMAT_PCM32, 0, 1e-5);
+ check_create_extended(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32, 0, 1e-5);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/extended_pcm32_1024.c b/libambix/tests/extended_pcm32_1024.c
index f10e360..ec25d50 100644
--- a/libambix/tests/extended_pcm32_1024.c
+++ b/libambix/tests/extended_pcm32_1024.c
@@ -1,25 +1,3 @@
-/* extended_pcm32_1024 - test ambix extended (PCM32, blocksize 1024)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
#include "common.h"
#include <unistd.h>
#include <string.h>
@@ -28,8 +6,7 @@
void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps);
int main(int argc, char**argv) {
- check_create_extended("test2-pcm32.caf", AMBIX_SAMPLEFORMAT_PCM32, 1024, 1e-5);
+ check_create_extended(FILENAME_FILE, AMBIX_SAMPLEFORMAT_PCM32, 1024, 1e-5);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/fail.c b/libambix/tests/fail.c
index 963418b..e68ad06 100644
--- a/libambix/tests/fail.c
+++ b/libambix/tests/fail.c
@@ -1,30 +1,5 @@
-/* fail - simple test that always fails
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-*/
-
#include "common.h"
int main(int argc, char**argv) {
-
- fail();
- return 0;
+ return fail();
}
diff --git a/libambix/tests/fail_if0.c b/libambix/tests/fail_if0.c
new file mode 100644
index 0000000..ee8feb0
--- /dev/null
+++ b/libambix/tests/fail_if0.c
@@ -0,0 +1,5 @@
+#include "common.h"
+
+int main(int argc, char**argv) {
+ return fail_if(0, __LINE__, "should %s fail", "NOT");
+}
diff --git a/libambix/tests/fail_if1.c b/libambix/tests/fail_if1.c
new file mode 100644
index 0000000..25957a3
--- /dev/null
+++ b/libambix/tests/fail_if1.c
@@ -0,0 +1,5 @@
+#include "common.h"
+
+int main(int argc, char**argv) {
+ return fail_if(1, __LINE__, "should %s fail", "indeed");
+}
diff --git a/libambix/tests/markers_regions.c b/libambix/tests/markers_regions.c
new file mode 100644
index 0000000..f81bfaf
--- /dev/null
+++ b/libambix/tests/markers_regions.c
@@ -0,0 +1,117 @@
+#include "common.h"
+#include "data.h"
+
+#include <string.h>
+
+int main(int argc, char**argv) {
+ const char*markerfile=FILENAME_FILE;
+ ambix_t*ambix=NULL;
+ ambix_info_t info;
+ memset(&info, 0, sizeof(info));
+ uint32_t frames=441000;
+ uint32_t channels=4;
+ int64_t err64;
+ float32_t*data;
+
+ info.fileformat=AMBIX_BASIC;
+ info.ambichannels=channels;
+ info.extrachannels=0;
+ info.samplerate=44100;
+ info.sampleformat=AMBIX_SAMPLEFORMAT_FLOAT32;
+
+ data=(float32_t*)calloc(channels*frames, sizeof(float32_t));
+
+ ambix=ambix_open(markerfile, AMBIX_WRITE, &info);
+ fail_if(NULL==ambix, __LINE__, "File was not open");
+
+ /* add some markers */
+ ambix_marker_t marker_1;
+ memset(&marker_1, 0, sizeof(ambix_marker_t));
+ marker_1.position = 1.0;
+ strncpy(marker_1.name, "this is marker #1", 255);
+
+ ambix_marker_t marker_2;
+ memset(&marker_2, 0, sizeof(ambix_marker_t));
+ marker_2.position = 2.0;
+ strncpy(marker_2.name, "this is marker #2", 255);
+
+
+ ambix_marker_t marker_3;
+ memset(&marker_3, 0, sizeof(ambix_marker_t));
+ marker_3.position = 3.0;
+
+ fail_if(0!=ambix_add_marker(ambix, &marker_1), __LINE__, "Could not add marker");
+ fail_if(0!=ambix_add_marker(ambix, &marker_2), __LINE__, "Could not add marker");
+ fail_if(0!=ambix_add_marker(ambix, &marker_3), __LINE__, "Could not add marker");
+
+ /* add some regions */
+ ambix_region_t region_1;
+ memset(®ion_1, 0, sizeof(ambix_region_t));
+ region_1.start_position = 1.0;
+ region_1.end_position = 2.0;
+ strncpy(region_1.name, "this is region #1", 255);
+
+ ambix_region_t region_2;
+ memset(®ion_2, 0, sizeof(ambix_region_t));
+ region_2.start_position = 3.0;
+ region_2.end_position = 4.0;
+ strncpy(region_2.name, "this is region #2", 255);
+
+ ambix_region_t region_3;
+ memset(®ion_3, 0, sizeof(ambix_region_t));
+ region_3.start_position = 3.0;
+ region_3.end_position = 4.0;
+
+ fail_if(0!=ambix_add_region(ambix, ®ion_1), __LINE__, "Could not add region");
+ fail_if(0!=ambix_add_region(ambix, ®ion_2), __LINE__, "Could not add region");
+ fail_if(0!=ambix_add_region(ambix, ®ion_3), __LINE__, "Could not add region");
+
+ /* write testsamples */
+ err64=ambix_writef_float32(ambix, data, NULL, frames);
+
+ ambix_close(ambix);
+
+
+ /* open the file again and see wheter the markers and regions have been saved and can be read */
+ memset(&info, 0, sizeof(info));
+ ambix=ambix_open(markerfile, AMBIX_READ, &info);
+
+ fail_if(0 == ambix_get_num_markers(ambix), __LINE__, "No markers in file");
+ fail_if(0 == ambix_get_num_regions(ambix), __LINE__, "No regions in file");
+
+ ambix_marker_t *marker_1_retr;
+ ambix_marker_t *marker_2_retr;
+ ambix_marker_t *marker_3_retr;
+
+ ambix_region_t *region_1_retr;
+ ambix_region_t *region_2_retr;
+ ambix_region_t *region_3_retr;
+
+ marker_1_retr=ambix_get_marker(ambix, 0);
+ marker_2_retr=ambix_get_marker(ambix, 1);
+ marker_3_retr=ambix_get_marker(ambix, 2);
+
+ region_1_retr=ambix_get_region(ambix, 0);
+ region_2_retr=ambix_get_region(ambix, 1);
+ region_3_retr=ambix_get_region(ambix, 2);
+
+ fail_if(marker_1_retr==NULL, __LINE__, "Could not retrieve marker 1");
+ fail_if(marker_2_retr==NULL, __LINE__, "Could not retrieve marker 2");
+ fail_if(marker_3_retr==NULL, __LINE__, "Could not retrieve marker 3");
+ fail_if(region_1_retr==NULL, __LINE__, "Could not retrieve region 1");
+ fail_if(region_2_retr==NULL, __LINE__, "Could not retrieve region 2");
+ fail_if(region_3_retr==NULL, __LINE__, "Could not retrieve region 3");
+
+ fail_if(memcmp(&marker_1, marker_1_retr, sizeof(ambix_marker_t)), __LINE__, "Marker 1 does not match");
+ fail_if(memcmp(&marker_2, marker_2_retr, sizeof(ambix_marker_t)), __LINE__, "Marker 2 does not match");
+ fail_if(memcmp(&marker_3, marker_3_retr, sizeof(ambix_marker_t)), __LINE__, "Marker 3 does not match");
+ fail_if(memcmp(®ion_1, region_1_retr, sizeof(ambix_region_t)), __LINE__, "Region 1 does not match");
+ fail_if(memcmp(®ion_2, region_2_retr, sizeof(ambix_region_t)), __LINE__, "Region 2 does not match");
+ fail_if(memcmp(®ion_3, region_3_retr, sizeof(ambix_region_t)), __LINE__, "Region 3 does not match");
+
+ if(data)
+ free(data);
+ ambix_close(ambix);
+ ambixtest_rmfile(markerfile);
+ return pass();
+}
diff --git a/libambix/tests/matrices.c b/libambix/tests/matrices.c
index 98bf649..531e929 100644
--- a/libambix/tests/matrices.c
+++ b/libambix/tests/matrices.c
@@ -1,6 +1,6 @@
/* matrices - test preset matrices
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -79,7 +79,7 @@ void check_inversion(const char*name, ambix_matrixtype_t typ, uint32_t rows, uin
float32_t errf;
float32_t eps=1e-6;
- STARTTEST(name);
+ STARTTEST("%s\n", name);
result=inverse_matrices(typ, rows, cols);
eye=ambix_matrix_init(result->rows, result->cols, eye);
@@ -106,7 +106,7 @@ void check_matrix(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32
float32_t errf=0.f;
float32_t eps=1e-20;
- STARTTEST(name);
+ STARTTEST("%s\n", name);
mtx=ambix_matrix_init(rows, cols, mtx);
skip_if(NULL==mtx, __LINE__, "couldn't create mtx-matrix");
@@ -133,6 +133,21 @@ void check_matrix(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32
ambix_matrix_destroy(mtx);
ambix_matrix_destroy(zeros);
}
+void check_nomatrix(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) {
+ ambix_matrix_t*mtx=NULL;
+ ambix_matrix_t*result=NULL;
+ float32_t errf=0.f;
+ float32_t eps=1e-20;
+
+ STARTTEST("%s\n", name);
+
+ mtx=ambix_matrix_init(rows, cols, mtx);
+ skip_if(NULL==mtx, __LINE__, "couldn't create mtx-matrix");
+ result=ambix_matrix_fill(mtx, typ);
+ fail_if(NULL!=result, __LINE__, "filled illegal result-matrix");
+ ambix_matrix_destroy(mtx);
+}
+
int main(int argc, char**argv) {
uint32_t r, c, o;
@@ -159,8 +174,29 @@ int main(int argc, char**argv) {
check_matrix("FuMa[16, 8]", AMBIX_MATRIX_FUMA, 16, 8);
check_matrix("FuMa[16,11]", AMBIX_MATRIX_FUMA, 16, 11);
check_matrix("FuMa[16,16]", AMBIX_MATRIX_FUMA, 16, 16);
-
-
+ check_nomatrix("FuMa[ 4, 2]", AMBIX_MATRIX_FUMA, 4, 2);
+ check_nomatrix("FuMa[16,10]", AMBIX_MATRIX_FUMA, 16, 10);
+ check_nomatrix("FuMa[16,12]", AMBIX_MATRIX_FUMA, 16, 12);
+ check_nomatrix("FuMa[16,13]", AMBIX_MATRIX_FUMA, 16, 13);
+ check_nomatrix("FuMa[16,14]", AMBIX_MATRIX_FUMA, 16, 14);
+ check_nomatrix("FuMa[16,15]", AMBIX_MATRIX_FUMA, 16, 15);
+ check_nomatrix("FuMa[25,25]", AMBIX_MATRIX_FUMA, 25, 25);
+
+ check_nomatrix("MaFu[ 4, 2]", AMBIX_MATRIX_TO_FUMA, 2, 4);
+ check_nomatrix("MaFu[16,10]", AMBIX_MATRIX_TO_FUMA, 10, 16);
+ check_nomatrix("MaFu[16,12]", AMBIX_MATRIX_TO_FUMA, 12, 16);
+ check_nomatrix("MaFu[16,13]", AMBIX_MATRIX_TO_FUMA, 13, 16);
+ check_nomatrix("MaFu[16,14]", AMBIX_MATRIX_TO_FUMA, 14, 16);
+ check_nomatrix("MaFu[16,15]", AMBIX_MATRIX_TO_FUMA, 15, 16);
+ check_nomatrix("MaFu[25,25]", AMBIX_MATRIX_TO_FUMA, 25, 25);
+
+ check_nomatrix("sid2acn [ 7, 7]", AMBIX_MATRIX_SID, 7, 7);
+ check_nomatrix("acn2sid [ 7, 7]", AMBIX_MATRIX_TO_SID, 7, 7);
+ check_nomatrix("n3d->sn3d [ 7, 7]", AMBIX_MATRIX_N3D, 7, 7);
+ check_nomatrix("sn3d->n3d [ 7, 7]", AMBIX_MATRIX_TO_N3D, 7, 7);
+ check_nomatrix("nada[ 4, 4]", AMBIX_MATRIX_INVALID, 4, 4);
+
+ STOPTEST("matrices\n");
check_inversion("FuMa[ 1, 1]", AMBIX_MATRIX_FUMA, 1, 1);
check_inversion("FuMa[ 4, 3]", AMBIX_MATRIX_FUMA, 4, 3);
@@ -172,6 +208,7 @@ int main(int argc, char**argv) {
check_inversion("FuMa[16, 8]", AMBIX_MATRIX_FUMA, 16, 8);
check_inversion("FuMa[16,11]", AMBIX_MATRIX_FUMA, 16, 11);
check_inversion("FuMa[16,16]", AMBIX_MATRIX_FUMA, 16, 16);
+ STOPTEST("matrix inversion\n");
for(o=1; o<6; o++) {
uint32_t chan=ambix_order2channels(o);
@@ -191,8 +228,7 @@ int main(int argc, char**argv) {
snprintf(name, 63, "sid[%d, %d]", chan, chan);
check_inversion(name, AMBIX_MATRIX_SID, 1, 1);
}
+ STOPTEST("\n");
-
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/matrix.c b/libambix/tests/matrix.c
deleted file mode 100644
index 49164de..0000000
--- a/libambix/tests/matrix.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/* matrix - test matrix functionality
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "common.h"
-#include <string.h>
-
-static float32_t leftdata_4_3[]= {
- 0.19, 0.06, 0.14,
- 0.05, 0.08, 0.44,
- 0.25, 0.9, 0.77,
- 0.83, 0.51, 0.58,
-};
-
-
-static float32_t rightdata_3_2[]= {
- 0.22, 0.46,
- 0.36, 0.53,
- 0.77, 0.85,
-};
-
-static float32_t resultdata_4_2[]= {
- 0.1712, 0.2382,
- 0.3786, 0.4394,
- 0.9719, 1.2465,
- 0.8128, 1.1451,
-};
-
-void mtxmul_tests(float32_t eps) {
- float32_t errf;
- ambix_matrix_t *left, *right, *result, *testresult;
- STARTTEST("");
-
- /* fill in some test data */
- left=ambix_matrix_init(4, 3, NULL);
- ambix_matrix_fill_data(left, leftdata_4_3);
- right=ambix_matrix_init(3, 2, NULL);
- ambix_matrix_fill_data(right, rightdata_3_2);
- testresult=ambix_matrix_init(4, 2, NULL);
- ambix_matrix_fill_data(testresult, resultdata_4_2);
-
- errf=matrix_diff(__LINE__, left, left, eps);
- fail_if(!(errf<eps), __LINE__, "diffing matrix with itself returned %f (>%f)", errf, eps);
-
- /* do some matrix multiplication */
- result=ambix_matrix_multiply(left, right, NULL);
- fail_if((NULL==result), __LINE__, "multiply into NULL did not create matrix");
-
- fail_if((result!=ambix_matrix_multiply(left, right, result)), __LINE__, "multiply into existing matrix returned new matrix");
-
-#if 0
- matrix_print(left);
- matrix_print(right);
- matrix_print(result);
- printf("------------\n");
-#endif
- errf=matrix_diff(__LINE__, testresult, result, eps);
- fail_if((errf>eps), __LINE__, "diffing two results of same multiplication returned %f (>%f)", errf, eps);
-
- ambix_matrix_destroy(left);
- ambix_matrix_destroy(right);
- ambix_matrix_destroy(result);
- ambix_matrix_destroy(testresult);
-}
-void mtxmul_eye_tests(float32_t eps) {
- float32_t errf;
- ambix_matrix_t *left, *result, *eye;
- STARTTEST("");
- eye=ambix_matrix_init(4, 4, NULL);
- fail_if((eye!=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY)), __LINE__, "filling unity matrix %p did not return original matrix %p", eye);
-
- left=ambix_matrix_init(4, 2, NULL);
- fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(left, resultdata_4_2), __LINE__,
- "filling left data failed");
-
- result=ambix_matrix_init(4, 2, NULL);
- fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(result, resultdata_4_2), __LINE__,
- "filling result data failed");
-
- fail_if((result!=ambix_matrix_multiply(eye, left, result)), __LINE__, "multiplication into matrix did not return original matrix");
-#if 0
- matrix_print(eye);
- matrix_print(result);
- matrix_print(left);
-#endif
- errf=matrix_diff(__LINE__, left, result, eps);
- fail_if((errf>eps), __LINE__, "diffing matrix M with E*M returned %f (>%f)", errf, eps);
-
- ambix_matrix_destroy(left);
- ambix_matrix_destroy(result);
- ambix_matrix_destroy(eye);
-}
-void datamul_tests(float32_t eps) {
- float32_t errf;
- float32_t*resultdata = (float32_t*)calloc(2*4, sizeof(float32_t));
- float32_t*resultdataT = (float32_t*)calloc(4*2, sizeof(float32_t));
- float32_t*inputdata = (float32_t*)calloc(2*3, sizeof(float32_t));
-
- fail_if((NULL==resultdata), __LINE__, "couldn't callocate resultdata");
- fail_if((NULL==resultdataT), __LINE__, "couldn't callocate resultdataT");
- fail_if((NULL==inputdata), __LINE__, "couldn't callocate inputdata");
-
- ambix_matrix_t*mtx=NULL;
- STARTTEST("");
-
- mtx=ambix_matrix_init(4, 3, NULL);
- ambix_matrix_fill_data(mtx, leftdata_4_3);
-
- data_transpose(inputdata, rightdata_3_2, 3, 2);
-
- fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(resultdata, mtx, inputdata, 2), __LINE__,
- "data multiplication failed");
-
- data_transpose(resultdataT, resultdata, 2, 4);
-
- errf=data_diff(__LINE__, resultdataT, resultdata_4_2, 4*2, eps);
- if(errf>eps) {
- printf("matrix:\n");
- matrix_print(mtx);
- printf("input:\n");
- data_print(inputdata, 3*2);
-
- printf("expected:\n");
- data_print(resultdata_4_2, 4*2);
- printf("calculated:\n");
- data_print(resultdataT , 4*2);
-
- }
- fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);
-
-#if 0
- printf("matrix:\n");matrix_print(mtx);
- printf("input :\n"); data_print(rightdata_3_2, 3*2);
- printf("output:\n"); data_print(resultdata, 4*2);
-
- printf("target:\n"); data_print(resultdata_4_2, 4*2);
-#endif
-
-
- if(mtx)ambix_matrix_destroy(mtx);
- free(resultdata);
- free(resultdataT);
- free(inputdata);
-}
-
-void datamul_eye_tests(float32_t eps) {
- float32_t errf;
- uint64_t frames=4096;
- uint32_t channels=16;
- float32_t*inputdata;
- float32_t*outputdata;
- float32_t freq=500;
- ambix_matrix_t eye = {0, 0, NULL};
- STARTTEST("");
-
-
- inputdata =data_sine(frames, channels, freq);
- outputdata=(float32_t*)malloc(sizeof(float32_t)*frames*channels);
- fail_if((NULL==outputdata), __LINE__, "couldn't mallocate outputdata");
-
- ambix_matrix_init(channels, channels, &eye);
- ambix_matrix_fill(&eye, AMBIX_MATRIX_IDENTITY);
-
- fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(outputdata, &eye, inputdata, frames),
- __LINE__, "data multilplication failed");
-
- errf=data_diff(__LINE__, inputdata, outputdata, frames*channels, eps);
- fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);
-
-#if 0
- printf("matrix:\n"); matrix_print(&eye);
- printf("input :\n"); data_print(inputdata, frames*channels);
- printf("output:\n"); data_print(outputdata,frames*channels);
-#endif
-
- free(inputdata);
- free(outputdata);
- ambix_matrix_deinit(&eye);
-}
-
-void datamul_4_2_tests(uint32_t chunksize, float32_t eps) {
- uint32_t r, c, rows, cols;
- float32_t errf;
- uint64_t frames=8;
- uint32_t rawchannels=2;
- uint32_t cokchannels=4;
-
- float32_t*inputdata;
- float32_t*outputdata;
- float32_t*targetdata;
-
- float32_t freq=500;
-
- ambix_matrix_t eye = {0, 0, NULL};
- STARTTEST("");
-
-
-
- inputdata =data_sine(frames, rawchannels, freq);
- targetdata=data_sine(frames, cokchannels, freq);
-
- outputdata=(float32_t*)malloc(sizeof(float32_t)*frames*cokchannels);
- fail_if((NULL==outputdata), __LINE__, "couldn't allocate outputdata");
-
- ambix_matrix_init(cokchannels, rawchannels, &eye);
- rows=eye.rows;
- cols=eye.cols;
-
- for(r=0; r<rows; r++) {
- for(c=0; c<cols; c++) {
- eye.data[r][c]=(1+r+c)%2;
- }
- }
-
-#if 0
- matrix_print(&eye);
- printf("input\n");
- data_print(inputdata, rawchannels*frames);
-#endif
-
- fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(outputdata, &eye, inputdata, frames),
- __LINE__, "data multilplication failed");
-
-#if 0
- printf("output\n");
- data_print(outputdata, cokchannels*frames);
-
- printf("target\n");
- data_print(targetdata, cokchannels*frames);
-#endif
-
-
-
- errf=data_diff(__LINE__, targetdata, outputdata, frames*cokchannels, eps);
- fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);
-
-#if 0
- printf("matrix:\n"); matrix_print(&eye);
- printf("input :\n"); data_print(inputdata, frames*channels);
- printf("output:\n"); data_print(outputdata,frames*channels);
-#endif
-
- ambix_matrix_deinit(&eye);
-
- free(inputdata);
- free(outputdata);
- free(targetdata);
-}
-
-
-
-
-
-
-
-void create_tests(float32_t eps) {
- int rows=4;
- int cols=3;
- int cols2=2;
- ambix_matrix_t matrix, *left, *right;
- STARTTEST("");
-
- memset(&matrix, 0, sizeof(matrix));
-
- left=ambix_matrix_create();
- fail_if((left==NULL), __LINE__, "failed to create left matrix");
- fail_if((left->rows || left->cols), __LINE__, "created empty matrix has non-zero size");
- fail_if((left!=ambix_matrix_init(rows, cols, left)), __LINE__, "initializing existing matrix* returned new matrix");
- fail_if((left->rows!=rows || left->cols!=cols), __LINE__, "created matrix [%dx%d] does not match [%dx%d]", left->rows, left->cols, cols, cols2);
-
- right=ambix_matrix_init(cols, cols2, NULL);
- fail_if((right==NULL), __LINE__, "failed to create right matrix");
- fail_if((right->rows!=cols || right->cols!=cols2), __LINE__, "created matrix [%dx%d] does not match [%dx%d]", right->rows, right->cols, cols, cols2);
-
- fail_if((&matrix!=ambix_matrix_init(rows, cols2, &matrix)), __LINE__, "initializing existing matrix returned new matrix");
- fail_if((matrix.rows!=rows || matrix.cols!=cols2), __LINE__, "initialized matrix [%dx%d] does not match [%dx%d]", matrix.rows, matrix.cols, rows, cols2);
-
-
- ambix_matrix_deinit(&matrix);
- fail_if((matrix.rows || matrix.cols), __LINE__, "deinitialized matrix is non-zero");
-
- ambix_matrix_deinit(left);
- fail_if((left->rows || left->cols), __LINE__, "deinitialized matrix is non-zero");
-
- ambix_matrix_destroy(left);
- ambix_matrix_destroy(right);
-}
-
-
-
-int main(int argc, char**argv) {
-#if 1
- create_tests(1e-7);
- mtxmul_tests(1e-7);
- mtxmul_eye_tests(1e-7);
- datamul_tests(1e-7);
- datamul_eye_tests(1e-7);
-#endif
- datamul_4_2_tests(1024, 1e-7);
-
- pass();
- return 0;
-}
diff --git a/libambix/tests/matrixtests.c b/libambix/tests/matrixtests.c
new file mode 100644
index 0000000..c013623
--- /dev/null
+++ b/libambix/tests/matrixtests.c
@@ -0,0 +1,600 @@
+/* matrix - test matrix functionality
+
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Institute of Electronic Music and Acoustics (IEM),
+ University of Music and Dramatic Arts, Graz
+
+ This file is part of libambix
+
+ libambix is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ libambix is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "common.h"
+#include <string.h>
+#include <stdlib.h>
+
+static float32_t leftdata_4_3[]= {
+ 0.19, 0.06, 0.14,
+ 0.05, 0.08, 0.44,
+ 0.25, 0.90, 0.77,
+ 0.83, 0.51, 0.58,
+};
+static float32_t leftdata_4_4[]= {
+ 0.7131185686247925, 0.1054799265939327, 0.1882023608287114, 0.1496964665104298,
+ 0.9035382689904633, 0.0958506183093942, 0.1490156537909140, 0.6730762573692578,
+ 0.7110257215280688, 0.4278857180785819, 0.5050723092090162, 0.2342525090113509,
+ 0.1917073427152419, 0.3837280931544647, 0.0397484032568303, 0.5895499716980565,
+};
+static float32_t rightdata_3_2[]= {
+ 0.22, 0.46,
+ 0.36, 0.53,
+ 0.77, 0.85,
+};
+static float32_t resultdata_4_2[]= {
+ /* leftdata[4,3] * rightdata[3,2] */
+ 0.1712, 0.2382,
+ 0.3786, 0.4394,
+ 0.9719, 1.2465,
+ 0.8128, 1.1451,
+};
+static float32_t resultpinv_4_3[] = {
+ /* (leftdata[4,3])^-1 */
+ 0.320059925923633, -0.616572833442599, -0.758203952544301, 1.397070173352668,
+-0.475395139478048, -2.112396458091558, 1.443108803981482, -0.198593134445739,
+ 0.349719602203337, 2.683861685335670, -0.150602340058839, -0.196372558639406,
+};
+static float32_t resultpinv_4_4[] = {
+ /* (leftdata[4,4])^-1 */
+ 3.260687761423661,-0.750604578051301,-1.027983295100203, 0.437466478433052,
+ 4.478583197847279,-3.527343133136301,-0.883177052786819, 3.240826676373624,
+ -6.751824651655014, 2.959470009112655, 3.874801812795508,-3.203980734335171,
+ -3.520111656963465, 2.340434097800232, 0.647874863173282,-0.339426118611342,
+};
+static void mtxinverse_test(const ambix_matrix_t *mtx, const ambix_matrix_t *result, float32_t eps) {
+ ambix_matrix_t *pinv = 0;
+ ambix_matrix_t *mul=0;
+ ambix_matrix_t *eye=0;
+ float32_t errf;
+ int min_rowcol=(mtx->cols<mtx->rows)?mtx->cols:mtx->rows;
+
+ fail_if((NULL==mtx), __LINE__, "cannot invert NULL-matrix");
+ eye=ambix_matrix_init(min_rowcol, min_rowcol, eye);
+ eye=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY);
+ fail_if((NULL==eye), __LINE__, "cannot create eye-matrix for pinv-verification");
+
+ pinv=ambix_matrix_pinv(mtx, pinv);
+ if(NULL==pinv)matrix_print(mtx);
+ fail_if((NULL==pinv), __LINE__, "could not invert matrix");
+
+ if(mtx->cols < mtx->rows)
+ mul=ambix_matrix_multiply(pinv, mtx, 0);
+ else
+ mul=ambix_matrix_multiply(mtx, pinv, 0);
+
+#if 0
+ matrix_print(mtx);
+ matrix_print(pinv);
+ matrix_print(mul);
+ if(result)matrix_print(result);
+ printf("------------\n");
+#endif
+
+ if(result) {
+ errf=matrix_diff(__LINE__, pinv, result, eps);
+ fail_if((errf>eps), __LINE__, "diffing (pseudo)inverse returned %g (>%g)", errf, eps);
+
+ errf=matrix_diff(__LINE__, mul, eye, eps);
+ fail_if((errf>eps), __LINE__, "diffing mtx*pinv(mtx) returned %g (>%g)", errf, eps);
+ } else {
+ errf=matrix_diff(__LINE__, mul, eye, eps);
+ fail_if((!(isnan(errf) || isinf(errf) || (errf>eps))), __LINE__, "diffing invalid mtx*pinv(mtx) returned %g (!>%g)", errf, eps);
+ }
+
+ ambix_matrix_destroy(pinv);
+ ambix_matrix_destroy(mul);
+ ambix_matrix_destroy(eye);
+}
+void mtxinverse_tests(float32_t eps) {
+ float32_t errf;
+ ambix_matrix_t *mtx=0, *testresult=0;
+ float32_t*transposedata = (float32_t*)calloc(3*4, sizeof(float32_t));
+
+ STARTTEST("\n");
+
+ /* fill in some test data 4x4 */
+ STARTTEST("[4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill_data(mtx, leftdata_4_4);
+ testresult=ambix_matrix_init(4, 4, testresult);
+ ambix_matrix_fill_data(testresult, resultpinv_4_4);
+ mtxinverse_test(mtx, testresult, eps);
+
+ /* fill in some test data 4x3 */
+ STARTTEST("[4x3]\n");
+ mtx=ambix_matrix_init(4, 3, mtx);
+ ambix_matrix_fill_data(mtx, leftdata_4_3);
+ testresult=ambix_matrix_init(3, 4, testresult);
+ ambix_matrix_fill_data(testresult, resultpinv_4_3);
+ mtxinverse_test(mtx, testresult, eps);
+
+ /* fill in some test data 3x4 */
+ STARTTEST("[3x4]\n");
+ data_transpose(transposedata, leftdata_4_3, 4, 3);
+ mtx=ambix_matrix_init(3, 4, mtx);
+ ambix_matrix_fill_data(mtx, transposedata);
+
+ data_transpose(transposedata, resultpinv_4_3, 3, 4);
+ testresult=ambix_matrix_init(4, 3, testresult);
+ ambix_matrix_fill_data(testresult, transposedata);
+ mtxinverse_test(mtx, testresult, eps);
+
+ /* fill in some test data 4x4 */
+ STARTTEST("[identity:4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill(mtx, AMBIX_MATRIX_IDENTITY);
+ testresult=ambix_matrix_init(4, 4, testresult);
+ ambix_matrix_fill(testresult, AMBIX_MATRIX_IDENTITY);
+ mtxinverse_test(mtx, testresult, eps);
+
+ STARTTEST("[one:4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill(mtx, AMBIX_MATRIX_ONE);
+ mtxinverse_test(mtx, NULL, eps);
+ STARTTEST("[zero:4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill(mtx, AMBIX_MATRIX_ZERO);
+ mtxinverse_test(mtx, NULL, eps);
+
+ STARTTEST("[SID:4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill(mtx, AMBIX_MATRIX_SID);
+ testresult=ambix_matrix_init(4, 4, testresult);
+ ambix_matrix_fill(testresult, AMBIX_MATRIX_TO_SID);
+ mtxinverse_test(mtx, testresult, eps);
+
+ STARTTEST("[N3D:4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill(mtx, AMBIX_MATRIX_N3D);
+ testresult=ambix_matrix_init(4, 4, testresult);
+ ambix_matrix_fill(testresult, AMBIX_MATRIX_TO_N3D);
+ mtxinverse_test(mtx, testresult, eps);
+
+ STARTTEST("[FUMA:4x4]\n");
+ mtx=ambix_matrix_init(4, 4, mtx);
+ ambix_matrix_fill(mtx, AMBIX_MATRIX_FUMA);
+ testresult=ambix_matrix_init(4, 4, testresult);
+ ambix_matrix_fill(testresult, AMBIX_MATRIX_TO_FUMA);
+ mtxinverse_test(mtx, testresult, eps);
+
+
+ ambix_matrix_destroy(mtx);
+ ambix_matrix_destroy(testresult);
+ free(transposedata);
+ STOPTEST("\n");
+}
+void mtxmul_tests(float32_t eps) {
+ float32_t errf;
+ ambix_matrix_t *left=NULL, *right=NULL, *result, *testresult;
+ STARTTEST("\n");
+
+ /* fill in some test data */
+ left=ambix_matrix_init(4, 3, NULL);
+ ambix_matrix_fill_data(left, leftdata_4_3);
+ right=ambix_matrix_init(3, 2, NULL);
+ ambix_matrix_fill_data(right, rightdata_3_2);
+ testresult=ambix_matrix_init(4, 2, NULL);
+ ambix_matrix_fill_data(testresult, resultdata_4_2);
+
+ errf=matrix_diff(__LINE__, left, left, eps);
+ fail_if(!(errf<eps), __LINE__, "diffing matrix with itself returned %f (>%f)", errf, eps);
+
+ /* NULL multiplications */
+ result=ambix_matrix_multiply(NULL, NULL, NULL);
+ fail_if(NULL!=result, __LINE__, "multiplying NULL*NULL returned success");
+ result=ambix_matrix_multiply(left, NULL, result);
+ fail_if(NULL!=result, __LINE__, "multiplying left*NULL returned success");
+ result=ambix_matrix_multiply(NULL, left, result);
+ fail_if(NULL!=result, __LINE__, "multiplying NULL*left returned success");
+
+ /* do some matrix multiplication */
+ result=ambix_matrix_multiply(left, right, NULL);
+ fail_if((NULL==result), __LINE__, "multiply into NULL did not create matrix");
+
+ fail_if((result!=ambix_matrix_multiply(left, right, result)), __LINE__, "multiply into existing matrix returned new matrix");
+
+#if 0
+ matrix_print(left);
+ matrix_print(right);
+ matrix_print(result);
+ printf("------------\n");
+#endif
+ errf=matrix_diff(__LINE__, testresult, result, eps);
+ fail_if((errf>eps), __LINE__, "diffing two results of same multiplication returned %f (>%f)", errf, eps);
+
+ ambix_matrix_destroy(left);
+ ambix_matrix_destroy(right);
+ ambix_matrix_destroy(result);
+ ambix_matrix_destroy(testresult);
+ STOPTEST("\n");
+}
+void mtxmul_eye_tests(float32_t eps) {
+ float32_t errf;
+ ambix_matrix_t *left, *result, *eye;
+ STARTTEST("\n");
+ eye=ambix_matrix_init(4, 4, NULL);
+ fail_if((eye!=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY)), __LINE__, "filling unity matrix %p did not return original matrix %p", eye);
+
+ left=ambix_matrix_init(4, 2, NULL);
+ fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(left, resultdata_4_2), __LINE__,
+ "filling left data failed");
+
+ result=ambix_matrix_init(4, 2, NULL);
+ fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(result, resultdata_4_2), __LINE__,
+ "filling result data failed");
+
+ fail_if((result!=ambix_matrix_multiply(eye, left, result)), __LINE__, "multiplication into matrix did not return original matrix");
+#if 0
+ matrix_print(eye);
+ matrix_print(result);
+ matrix_print(left);
+#endif
+ errf=matrix_diff(__LINE__, left, result, eps);
+ fail_if((errf>eps), __LINE__, "diffing matrix M with E*M returned %f (>%f)", errf, eps);
+
+ ambix_matrix_destroy(left);
+ ambix_matrix_destroy(result);
+ ambix_matrix_destroy(eye);
+ STOPTEST("\n");
+}
+void datamul_tests(float32_t eps) {
+ float32_t errf;
+ float32_t*resultdata = (float32_t*)calloc(2*4, sizeof(float32_t));
+ float32_t*resultdataT = (float32_t*)calloc(4*2, sizeof(float32_t));
+ float32_t*inputdata = (float32_t*)calloc(2*3, sizeof(float32_t));
+
+ fail_if((NULL==resultdata), __LINE__, "couldn't callocate resultdata");
+ fail_if((NULL==resultdataT), __LINE__, "couldn't callocate resultdataT");
+ fail_if((NULL==inputdata), __LINE__, "couldn't callocate inputdata");
+
+ ambix_matrix_t*mtx=NULL;
+ STARTTEST("\n");
+
+ mtx=ambix_matrix_init(4, 3, NULL);
+ ambix_matrix_fill_data(mtx, leftdata_4_3);
+
+ data_transpose(inputdata, rightdata_3_2, 3, 2);
+
+ fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(resultdata, mtx, inputdata, 2), __LINE__,
+ "data multiplication failed");
+
+ data_transpose(resultdataT, resultdata, 2, 4);
+
+ errf=data_diff(__LINE__, FLOAT32, resultdataT, resultdata_4_2, 4*2, eps);
+ if(errf>eps) {
+ printf("matrix:\n");
+ matrix_print(mtx);
+ printf("input:\n");
+ data_print(FLOAT32, inputdata, 3*2);
+
+ printf("expected:\n");
+ data_print(FLOAT32, resultdata_4_2, 4*2);
+ printf("calculated:\n");
+ data_print(FLOAT32, resultdataT , 4*2);
+
+ }
+ fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);
+
+#if 0
+ printf("matrix:\n");matrix_print(mtx);
+ printf("input :\n"); data_print(FLOAT32, rightdata_3_2, 3*2);
+ printf("output:\n"); data_print(FLOAT32, resultdata, 4*2);
+
+ printf("target:\n"); data_print(FLOAT32, resultdata_4_2, 4*2);
+#endif
+
+
+ if(mtx)ambix_matrix_destroy(mtx);
+ free(resultdata);
+ free(resultdataT);
+ free(inputdata);
+ STOPTEST("\n");
+}
+
+void datamul_eye_tests(float32_t eps) {
+ float32_t errf;
+ uint64_t frames=4096;
+ uint32_t channels=16;
+ float32_t*inputdata;
+ float32_t*outputdata;
+ float32_t freq=500;
+ ambix_matrix_t eye = {0, 0, NULL};
+ STARTTEST("\n");
+
+ inputdata =data_sine(FLOAT32, frames, channels, freq);
+ outputdata=(float32_t*)malloc(sizeof(float32_t)*frames*channels);
+ fail_if((NULL==outputdata), __LINE__, "couldn't mallocate outputdata");
+
+ ambix_matrix_init(channels, channels, &eye);
+ ambix_matrix_fill(&eye, AMBIX_MATRIX_IDENTITY);
+
+ fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(outputdata, &eye, inputdata, frames),
+ __LINE__, "data multilplication failed");
+
+ errf=data_diff(__LINE__, FLOAT32, inputdata, outputdata, frames*channels, eps);
+ fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);
+
+#if 0
+ printf("matrix:\n"); matrix_print(&eye);
+ printf("input :\n"); data_print(FLOAT32, inputdata, frames*channels);
+ printf("output:\n"); data_print(FLOAT32, outputdata,frames*channels);
+#endif
+
+ free(inputdata);
+ free(outputdata);
+ ambix_matrix_deinit(&eye);
+ STOPTEST("\n");
+}
+
+void datamul_4_2_tests(uint32_t chunksize, float32_t eps) {
+ uint32_t r, c, rows, cols;
+ float32_t errf;
+ uint64_t frames=8;
+ uint32_t rawchannels=2;
+ uint32_t cokchannels=4;
+
+ float32_t*inputdata;
+ float32_t*outputdata;
+ float32_t*targetdata;
+
+ float32_t freq=500;
+
+ ambix_matrix_t eye = {0, 0, NULL};
+ STARTTEST("\n");
+
+ inputdata =data_sine(FLOAT32, frames, rawchannels, freq);
+ targetdata=data_sine(FLOAT32, frames, cokchannels, freq);
+
+ outputdata=(float32_t*)malloc(sizeof(float32_t)*frames*cokchannels);
+ fail_if((NULL==outputdata), __LINE__, "couldn't allocate outputdata");
+
+ ambix_matrix_init(cokchannels, rawchannels, &eye);
+ rows=eye.rows;
+ cols=eye.cols;
+
+ for(r=0; r<rows; r++) {
+ for(c=0; c<cols; c++) {
+ eye.data[r][c]=(1+r+c)%2;
+ }
+ }
+
+#if 0
+ matrix_print(&eye);
+ printf("input\n");
+ data_print(FLOAT32, inputdata, rawchannels*frames);
+#endif
+
+ fail_if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(outputdata, &eye, inputdata, frames),
+ __LINE__, "data multilplication failed");
+
+#if 0
+ printf("output\n");
+ data_print(FLOAT32, outputdata, cokchannels*frames);
+
+ printf("target\n");
+ data_print(FLOAT32, targetdata, cokchannels*frames);
+#endif
+
+
+
+ errf=data_diff(__LINE__, FLOAT32, targetdata, outputdata, frames*cokchannels, eps);
+ fail_if(!(errf<eps), __LINE__, "diffing data multiplication returned %f (>%f)", errf, eps);
+
+#if 0
+ printf("matrix:\n"); matrix_print(&eye);
+ printf("input :\n"); data_print(FLOAT32, inputdata, frames*channels);
+ printf("output:\n"); data_print(FLOAT32, outputdata,frames*channels);
+#endif
+
+ ambix_matrix_deinit(&eye);
+
+ free(inputdata);
+ free(outputdata);
+ free(targetdata);
+ STOPTEST("\n");
+}
+
+void mtx_copy(float32_t eps) {
+ float32_t errf;
+ ambix_matrix_t *left=NULL, *right=NULL;
+ unsigned int i;
+ float32_t maxeps=eps;
+
+ STARTTEST("\n");
+
+ right=ambix_matrix_copy(left, NULL);
+ fail_if((NULL!=right), __LINE__, "copying from NULL matrix erroneously succeeded");
+
+ left=ambix_matrix_create();
+ fail_if((left !=ambix_matrix_init(4, 3, left )), __LINE__, "initializing left matrix failed");
+ ambix_matrix_fill_data(left, leftdata_4_3);
+
+ right=ambix_matrix_copy(left, NULL);
+ fail_if((NULL==right), __LINE__, "copying to NULL matrix failed");
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf>0.f, __LINE__, "diffing mtx with copy0 returned %g (>%g)", errf, 0.f);
+
+ right=ambix_matrix_copy(left, right);
+ fail_if((NULL==right), __LINE__, "copying to right matrix failed");
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf>0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f);
+
+ ambix_matrix_destroy(left);
+ ambix_matrix_destroy(right);
+ STOPTEST("\n");
+
+}
+
+void mtx_diff(float32_t eps) {
+ float32_t errf;
+ ambix_matrix_t *left=NULL, *right=NULL;
+ unsigned int i;
+ const unsigned int rows=4;
+ const unsigned int cols=3;
+ float32_t*leftdata=leftdata_4_3;
+ float32_t*rightdata=malloc(sizeof(leftdata_4_3));
+ float32_t maxeps=eps;
+
+ STARTTEST("\n");
+
+ left=ambix_matrix_create();
+ right=ambix_matrix_create();
+
+ /* comparisons:
+ - failing tests:
+ - different dimensions
+ - left/right matrix is NULL
+ - non-failing tests:
+ - all values diff==0
+ - all values diff<eps
+ - few values diff<eps
+ - many values diff<eps
+ */
+ fail_if((left !=ambix_matrix_init(3, 4, left )), __LINE__, "initializing left matrix failed");
+ fail_if((right!=ambix_matrix_init(3, 4, right)), __LINE__, "initializing right matrix failed");
+
+ /* compare equal matrices */
+ STARTTEST("ident\n");
+ ambix_matrix_fill_data(left, leftdata);
+ errf=matrix_diff(__LINE__, left, left, eps);
+ fail_if(errf>0.f, __LINE__, "diffing mtx with itself returned %g (>%g)", errf, 0.f);
+
+ /* compare equal matrices */
+ STARTTEST("equal\n");
+ for(i=0; i<rows*cols; i++) {
+ rightdata[i]=leftdata[i];
+ }
+ ambix_matrix_fill_data(left , leftdata);
+ ambix_matrix_fill_data(right, rightdata);
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf>0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f);
+
+ /* compare matrices where all values differ, but <eps */
+ STARTTEST("all<eps\n");
+ for(i=0; i<rows*cols; i++) {
+ rightdata[i]=leftdata[i]+eps*0.5;
+ }
+ ambix_matrix_fill_data(left , leftdata);
+ ambix_matrix_fill_data(right, rightdata);
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf>eps, __LINE__, "diffing mtx with mtx+eps/2 returned %g (>%g)", errf, eps);
+ for(i=0; i<rows*cols; i++) {
+ rightdata[i]=leftdata[i]-eps*0.5;
+ }
+ ambix_matrix_fill_data(left , leftdata);
+ ambix_matrix_fill_data(right, rightdata);
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf>eps, __LINE__, "diffing mtx with mtx-eps/2 returned %g (>%g)", errf, eps);
+
+ /* compare matrices where many values differ with <eps; but one with >eps */
+ STARTTEST("most<eps;one>eps\n");
+ for(i=0; i<rows*cols; i++) {
+ rightdata[i]=leftdata[i];
+ }
+ for(i=0; i<rows; i++) {
+ rightdata[i]=leftdata[i]+eps*0.5;
+ }
+ rightdata[0]=leftdata[0]+eps*1.5;
+ ambix_matrix_fill_data(left , leftdata);
+ ambix_matrix_fill_data(right, rightdata);
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf>(eps*2.0), __LINE__, "diffing mtx with one value>eps returned %g (>%g)", errf, eps);
+ fail_if(errf<(eps*1.0), __LINE__, "diffing mtx with one value>eps returned %g (>%g)", errf, eps);
+
+ /* compare matrices where most values differ with >eps */
+ STARTTEST("most>eps\n");
+ for(i=0; i<rows*cols; i++) {
+ rightdata[i]=leftdata[i];
+ }
+ maxeps=eps*1.5;
+ for(i=0; i<(rows*cols)-1; i++) {
+ rightdata[i]=leftdata[i]-maxeps;
+ }
+ ambix_matrix_fill_data(left , leftdata);
+ ambix_matrix_fill_data(right, rightdata);
+ errf=matrix_diff(__LINE__, left, right, eps);
+ fail_if(errf<eps*1.0, __LINE__, "diffing mtx with one value>eps returned %g (<%g)", errf, eps*1.0);
+ fail_if(errf>eps*2.0, __LINE__, "diffing mtx with one value>eps returned %g (<%g)", errf, eps*2.0);
+
+ ambix_matrix_destroy(left);
+ ambix_matrix_destroy(right);
+ free(rightdata);
+ STOPTEST("\n");
+}
+
+void create_tests(float32_t eps) {
+ int rows=4;
+ int cols=3;
+ int cols2=2;
+ ambix_matrix_t matrix, *left, *right;
+ STARTTEST("\n");
+
+ memset(&matrix, 0, sizeof(matrix));
+ matrix_print(&matrix);
+
+ left=ambix_matrix_create();
+ fail_if((left==NULL), __LINE__, "failed to create left matrix");
+ fail_if((left->rows || left->cols), __LINE__, "created empty matrix has non-zero size");
+ fail_if((left!=ambix_matrix_init(rows, cols, left)), __LINE__, "initializing existing matrix* returned new matrix");
+ fail_if((left->rows!=rows || left->cols!=cols), __LINE__, "created matrix [%dx%d] does not match [%dx%d]", left->rows, left->cols, cols, cols2);
+ matrix_print(left);
+
+ right=ambix_matrix_init(cols, cols2, NULL);
+ fail_if((right==NULL), __LINE__, "failed to create right matrix");
+ fail_if((right->rows!=cols || right->cols!=cols2), __LINE__, "created matrix [%dx%d] does not match [%dx%d]", right->rows, right->cols, cols, cols2);
+ matrix_print(right);
+
+ fail_if((&matrix!=ambix_matrix_init(rows, cols2, &matrix)), __LINE__, "initializing existing matrix returned new matrix");
+ fail_if((matrix.rows!=rows || matrix.cols!=cols2), __LINE__, "initialized matrix [%dx%d] does not match [%dx%d]", matrix.rows, matrix.cols, rows, cols2);
+
+
+ ambix_matrix_deinit(&matrix);
+ fail_if((matrix.rows || matrix.cols), __LINE__, "deinitialized matrix is non-zero");
+
+ ambix_matrix_deinit(left);
+ fail_if((left->rows || left->cols), __LINE__, "deinitialized matrix is non-zero");
+
+ ambix_matrix_destroy(left);
+ ambix_matrix_destroy(right);
+ STOPTEST("\n");
+}
+
+
+
+int main(int argc, char**argv) {
+#if 1
+ create_tests(1e-7);
+ mtx_copy(1e-7);
+ mtx_diff(1e-1);
+ mtx_diff(1e-7);
+ mtxmul_tests(1e-7);
+ mtxmul_eye_tests(1e-7);
+ datamul_tests(1e-7);
+ datamul_eye_tests(1e-7);
+#endif
+ datamul_4_2_tests(1024, 1e-7);
+ mtxinverse_tests(1e-5);
+
+ return pass();
+}
diff --git a/libambix/tests/none_float32.c b/libambix/tests/none_float32.c
index 176a0e8..c4111a6 100644
--- a/libambix/tests/none_float32.c
+++ b/libambix/tests/none_float32.c
@@ -29,8 +29,7 @@
void check_create_none(const char*path, ambix_sampleformat_t format);
int main(int argc, char**argv) {
- check_create_none("test-simple.caf", AMBIX_SAMPLEFORMAT_FLOAT32);
+ check_create_none(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/none_float32.c b/libambix/tests/none_float64.c
similarity index 83%
copy from libambix/tests/none_float32.c
copy to libambix/tests/none_float64.c
index 176a0e8..b3cfec3 100644
--- a/libambix/tests/none_float32.c
+++ b/libambix/tests/none_float64.c
@@ -1,6 +1,6 @@
-/* none_float32 - test ambix none (FLOAT32)
+/* none_float32 - test ambix none (FLOAT64)
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -29,8 +29,7 @@
void check_create_none(const char*path, ambix_sampleformat_t format);
int main(int argc, char**argv) {
- check_create_none("test-simple.caf", AMBIX_SAMPLEFORMAT_FLOAT32);
+ check_create_none(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64);
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/pass.c b/libambix/tests/pass.c
index 5505cd7..0d400e9 100644
--- a/libambix/tests/pass.c
+++ b/libambix/tests/pass.c
@@ -25,6 +25,5 @@
int main(int argc, char**argv) {
- pass();
- return 0;
+ return pass();
}
diff --git a/libambix/tests/pass_if0.c b/libambix/tests/pass_if0.c
new file mode 100644
index 0000000..9dd5498
--- /dev/null
+++ b/libambix/tests/pass_if0.c
@@ -0,0 +1,5 @@
+#include "common.h"
+
+int main(int argc, char**argv) {
+ return pass_if(0, __LINE__, "should %s pass", "NOT");
+}
diff --git a/libambix/tests/pass_if1.c b/libambix/tests/pass_if1.c
new file mode 100644
index 0000000..764222c
--- /dev/null
+++ b/libambix/tests/pass_if1.c
@@ -0,0 +1,5 @@
+#include "common.h"
+
+int main(int argc, char**argv) {
+ return pass_if(1, __LINE__, "should %s pass", "indeed");
+}
diff --git a/libambix/tests/runtest.sh b/libambix/tests/runtest.sh
index 36ffce5..fb6600a 100755
--- a/libambix/tests/runtest.sh
+++ b/libambix/tests/runtest.sh
@@ -32,7 +32,6 @@ case "$1" in
echo ${HELGRIND}
;;
*)
-
;;
esac
}
diff --git a/libambix/tests/simple_float32.c b/libambix/tests/simple_float32.c
deleted file mode 100644
index 9bd0834..0000000
--- a/libambix/tests/simple_float32.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* simple_float32 - test ambix simple (FLOAT32)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
-
-int main(int argc, char**argv) {
- check_create_simple("test-float32.caf", AMBIX_SAMPLEFORMAT_FLOAT32, 1e-7);
- pass();
- return 0;
-}
diff --git a/libambix/tests/simple_pcm16.c b/libambix/tests/simple_pcm16.c
deleted file mode 100644
index cd4812d..0000000
--- a/libambix/tests/simple_pcm16.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* simple_pcm16 - test ambix simple (PCM32)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
-
-int main(int argc, char**argv) {
- check_create_simple("test-pcm16.caf", AMBIX_SAMPLEFORMAT_PCM16, 1./20000.);
- pass();
- return 0;
-}
diff --git a/libambix/tests/simple_pcm32.c b/libambix/tests/simple_pcm32.c
deleted file mode 100644
index 4a4f10d..0000000
--- a/libambix/tests/simple_pcm32.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* simple_pcm32 - test ambix simple (PCM32)
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps);
-
-int main(int argc, char**argv) {
- check_create_simple("test-pcm32.caf", AMBIX_SAMPLEFORMAT_PCM32, 1e-5);
- pass();
- return 0;
-}
diff --git a/libambix/tests/skip.c b/libambix/tests/skip.c
index bd9b242..b106115 100644
--- a/libambix/tests/skip.c
+++ b/libambix/tests/skip.c
@@ -1,30 +1,5 @@
-/* skip - simple test that always softfails
-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
- Institute of Electronic Music and Acoustics (IEM),
- University of Music and Dramatic Arts, Graz
-
- This file is part of libambix
-
- libambix is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- libambix is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-*/
-
#include "common.h"
int main(int argc, char**argv) {
-
- skip();
- return 0;
+ return skip();
}
diff --git a/libambix/tests/skip_if0.c b/libambix/tests/skip_if0.c
new file mode 100644
index 0000000..572df55
--- /dev/null
+++ b/libambix/tests/skip_if0.c
@@ -0,0 +1,5 @@
+#include "common.h"
+
+int main(int argc, char**argv) {
+ return skip_if(0, __LINE__, "should %s skip", "NOT");
+}
diff --git a/libambix/tests/skip_if1.c b/libambix/tests/skip_if1.c
new file mode 100644
index 0000000..cefc329
--- /dev/null
+++ b/libambix/tests/skip_if1.c
@@ -0,0 +1,5 @@
+#include "common.h"
+
+int main(int argc, char**argv) {
+ return skip_if(1, __LINE__, "should %s skip", "indeed");
+}
diff --git a/samples/pd/ambix_readX~-help.pd b/samples/pd/ambix_readX~-help.pd
index 7eafb76..ccd7d9f 100644
--- a/samples/pd/ambix_readX~-help.pd
+++ b/samples/pd/ambix_readX~-help.pd
@@ -1,18 +1,18 @@
-#N canvas 200 134 758 600 10;
+#N canvas 775 240 758 600 10;
#X declare -lib iemmatrix;
#X obj 405 363 route bang;
#X obj 405 383 print EOF;
#X obj 535 387 print info;
-#X msg 111 216 1;
+#X msg 95 185 1;
#X obj 495 429 /;
-#X floatatom 495 449 5 0 0 1 seconds - -;
+#X floatatom 495 449 5 0 0 1 seconds - -, f 5;
#X obj 495 387 t a a;
#X obj 495 409 route frames samplerate;
#X obj 264 388 env~;
-#X floatatom 264 408 5 0 0 3 xtra0 - -;
+#X floatatom 264 408 5 0 0 3 xtra0 - -, f 5;
#X obj 299 388 env~;
-#X floatatom 299 408 5 0 0 3 xtra1 - -;
-#X msg 111 245 0;
+#X floatatom 299 408 5 0 0 3 xtra1 - -, f 5;
+#X msg 95 214 0;
#X msg 646 30 \; pd dsp 1;
#X msg 74 161 open \$1;
#X msg 74 49 bang;
@@ -48,16 +48,62 @@ you will get through the 1st outlet (e.g. using iemmatrix' [mtx_*~]
;
#X obj 145 527 ambix_read~;
#X obj 77 372 env~;
-#X floatatom 77 392 5 0 0 3 ACN0 - -;
+#X floatatom 77 392 5 0 0 3 ACN0 - -, f 5;
#X obj 112 406 env~;
-#X floatatom 112 426 5 0 0 3 ACN1 - -;
+#X floatatom 112 426 5 0 0 3 ACN1 - -, f 5;
#X obj 152 406 env~;
-#X floatatom 152 426 5 0 0 3 ACN2 - -;
+#X floatatom 152 426 5 0 0 3 ACN2 - -, f 5;
#X obj 192 406 env~;
-#X floatatom 192 426 5 0 0 3 ACN3 - -;
+#X floatatom 192 426 5 0 0 3 ACN3 - -, f 5;
#X obj 77 350 mtx_*~ 4 4;
#X obj 496 552 declare -lib iemmatrix;
#X obj 232 527 ambix_info;
+#X obj 289 350 s info-\$0;
+#N canvas 923 305 706 352 marker/regions 0;
+#X msg 42 121 get_all_markers;
+#X obj 35 300 outlet;
+#X msg 88 206 get_all_regions;
+#X msg 75 171 get_region \$1;
+#X msg 31 93 get_marker \$1;
+#X floatatom 31 72 5 0 0 0 - - -, f 5;
+#X floatatom 75 151 5 0 0 0 - - -, f 5;
+#X obj 372 90 r info-\$0;
+#X msg 344 267 seek \$1;
+#X obj 372 112 route marker region;
+#X obj 372 139 route 0 1 2;
+#X floatatom 344 236 10 0 0 0 - - -, f 10;
+#X obj 455 139 route 0 1 2;
+#X text 145 119 retrieve all markers;
+#X text 26 9 MARKER/REGION Info is sent to the rightmost outlet;
+#X text 78 70 get a marker with specific id;
+#X text 118 150 get a region with specific id;
+#X text 186 206 retrieve all regions;
+#X text 460 84 parse marker/region info;
+#X text 394 303 and BEFORE starting playback;
+#X text 394 286 this only works AFTER opening a file;
+#X msg 372 170 set \$1;
+#X obj 339 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 399 267 set playhead to a certain position in [samples];
+#X text 27 29 retrieving markers/regions only works AFTER opening a
+file;
+#X connect 0 0 1 0;
+#X connect 2 0 1 0;
+#X connect 3 0 1 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 3 0;
+#X connect 7 0 9 0;
+#X connect 8 0 1 0;
+#X connect 9 0 10 0;
+#X connect 9 1 12 0;
+#X connect 10 0 21 0;
+#X connect 10 1 21 0;
+#X connect 10 2 21 0;
+#X connect 11 0 8 0;
+#X connect 21 0 11 0;
+#X connect 22 0 11 0;
+#X restore 105 242 pd marker/regions;
#X connect 0 0 1 0;
#X connect 0 1 6 0;
#X connect 3 0 30 0;
@@ -83,6 +129,7 @@ you will get through the 1st outlet (e.g. using iemmatrix' [mtx_*~]
#X connect 30 5 8 0;
#X connect 30 6 10 0;
#X connect 30 7 0 0;
+#X connect 30 7 46 0;
#X connect 32 0 31 0;
#X connect 32 1 43 0;
#X connect 35 0 36 0;
@@ -93,3 +140,4 @@ you will get through the 1st outlet (e.g. using iemmatrix' [mtx_*~]
#X connect 43 1 37 0;
#X connect 43 2 39 0;
#X connect 43 3 41 0;
+#X connect 47 0 30 0;
diff --git a/samples/pd/ambix_read~-help.pd b/samples/pd/ambix_read~-help.pd
index f8db0f4..a4ba798 100644
--- a/samples/pd/ambix_read~-help.pd
+++ b/samples/pd/ambix_read~-help.pd
@@ -1,28 +1,28 @@
-#N canvas 518 132 758 533 10;
+#N canvas 307 182 758 533 10;
#X obj 405 333 route bang;
#X obj 405 353 print EOF;
#X obj 535 357 print info;
-#X msg 111 186 1;
+#X msg 94 153 1;
#X obj 74 298 env~;
-#X floatatom 74 318 5 0 0 3 ACN0 - -;
+#X floatatom 74 318 5 0 0 3 ACN0 - -, f 5;
#X obj 495 399 /;
-#X floatatom 495 419 5 0 0 1 seconds - -;
+#X floatatom 495 419 5 0 0 1 seconds - -, f 5;
#X obj 495 357 t a a;
#X obj 495 379 route frames samplerate;
#X obj 109 330 env~;
-#X floatatom 109 350 5 0 0 3 ACN1 - -;
+#X floatatom 109 350 5 0 0 3 ACN1 - -, f 5;
#X obj 149 330 env~;
-#X floatatom 149 350 5 0 0 3 ACN2 - -;
+#X floatatom 149 350 5 0 0 3 ACN2 - -, f 5;
#X obj 189 330 env~;
-#X floatatom 189 350 5 0 0 3 ACN3 - -;
+#X floatatom 189 350 5 0 0 3 ACN3 - -, f 5;
#X obj 74 238 ambix_read~ 4 2;
#X obj 264 358 env~;
-#X floatatom 264 378 5 0 0 3 xtra0 - -;
+#X floatatom 264 378 5 0 0 3 xtra0 - -, f 5;
#X obj 299 358 env~;
-#X floatatom 299 378 5 0 0 3 xtra1 - -;
-#X msg 111 215 0;
+#X floatatom 299 378 5 0 0 3 xtra1 - -, f 5;
+#X msg 99 175 0;
#X msg 646 30 \; pd dsp 1;
-#X msg 74 161 open \$1;
+#X msg 74 122 open \$1;
#X msg 74 49 bang;
#X obj 74 69 openpanel;
#X obj 145 499 readsf~;
@@ -52,6 +52,52 @@ need to transform the output data.;
#X text 215 243 arguments: <#ambioutlet~s:4> <#extraoutlet~s:0> <buffersize>
;
#X obj 242 477 ambix_info;
+#N canvas 923 305 706 352 marker/regions 1;
+#X msg 42 121 get_all_markers;
+#X obj 35 300 outlet;
+#X msg 88 206 get_all_regions;
+#X msg 75 171 get_region \$1;
+#X msg 31 93 get_marker \$1;
+#X floatatom 31 72 5 0 0 0 - - -, f 5;
+#X floatatom 75 151 5 0 0 0 - - -, f 5;
+#X obj 372 90 r info-\$0;
+#X msg 344 267 seek \$1;
+#X obj 372 112 route marker region;
+#X obj 372 139 route 0 1 2;
+#X floatatom 344 236 10 0 0 0 - - -, f 10;
+#X obj 455 139 route 0 1 2;
+#X text 145 119 retrieve all markers;
+#X text 26 9 MARKER/REGION Info is sent to the rightmost outlet;
+#X text 78 70 get a marker with specific id;
+#X text 118 150 get a region with specific id;
+#X text 186 206 retrieve all regions;
+#X text 460 84 parse marker/region info;
+#X text 394 303 and BEFORE starting playback;
+#X text 394 286 this only works AFTER opening a file;
+#X msg 372 170 set \$1;
+#X obj 339 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 399 267 set playhead to a certain position in [samples];
+#X text 27 29 retrieving markers/regions only works AFTER opening a
+file;
+#X connect 0 0 1 0;
+#X connect 2 0 1 0;
+#X connect 3 0 1 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X connect 6 0 3 0;
+#X connect 7 0 9 0;
+#X connect 8 0 1 0;
+#X connect 9 0 10 0;
+#X connect 9 1 12 0;
+#X connect 10 0 21 0;
+#X connect 10 1 21 0;
+#X connect 10 2 21 0;
+#X connect 11 0 8 0;
+#X connect 21 0 11 0;
+#X connect 22 0 11 0;
+#X restore 101 207 pd marker/regions;
+#X obj 300 323 s info-\$0;
#X connect 0 0 1 0;
#X connect 0 1 8 0;
#X connect 3 0 16 0;
@@ -72,6 +118,7 @@ need to transform the output data.;
#X connect 16 4 17 0;
#X connect 16 5 19 0;
#X connect 16 6 0 0;
+#X connect 16 6 44 0;
#X connect 17 0 18 0;
#X connect 19 0 20 0;
#X connect 21 0 16 0;
@@ -80,3 +127,4 @@ need to transform the output data.;
#X connect 25 0 23 0;
#X connect 32 0 34 0;
#X connect 33 0 32 0;
+#X connect 43 0 16 0;
diff --git a/samples/pd/ambix_read~.c b/samples/pd/ambix_read~.c
index a1b04c8..fe72a25 100644
--- a/samples/pd/ambix_read~.c
+++ b/samples/pd/ambix_read~.c
@@ -1,7 +1,8 @@
/* ambix_read~ - read AMBIsonics eXchange files in Pd -*- c -*-
- Copyright © 1997-1999 Miller Puckette <msp at ucsd.edu>.
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 1997-1999, Miller Puckette <msp at ucsd.edu>.
+ Copyright © 2012-2014, IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2016, Matthias Kronlachner
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -200,6 +201,7 @@ typedef struct _ambix_read {
ambix_matrix_t x_matrix;
ambix_info_t x_ambix;
+ ambix_t *x_ambix_t;
int x_fifosize; /* buffer size appropriately rounded down */
int x_fifohead; /* index of next byte to get from file */
@@ -219,7 +221,7 @@ typedef struct _ambix_read {
static void *ambix_read_child_main(void *zz) {
t_ambix_read *x = (t_ambix_read*)zz;
- ambix_t*ambix=NULL;
+ x->x_ambix_t=NULL;
const uint32_t want_ambichannels = x->x_ambichannels;
const uint32_t want_xtrachannels = x->x_xtrachannels;
const ambix_fileformat_t want_fileformat = x->x_fileformat;
@@ -259,15 +261,15 @@ static void *ambix_read_child_main(void *zz) {
memset(&ainfo, 0, sizeof(ainfo));
ainfo.fileformat=want_fileformat;
- if (ambix)
- ambix_close(ambix);
- ambix=ambix_open(filename, AMBIX_READ, &ainfo);
+ if (x->x_ambix_t)
+ ambix_close(x->x_ambix_t);
+ x->x_ambix_t=ambix_open(filename, AMBIX_READ, &ainfo);
free(filename);
- if(ambix) {
- matrix=ambix_get_adaptormatrix(ambix);
+ if(x->x_ambix_t) {
+ matrix=ambix_get_adaptormatrix(x->x_ambix_t);
if(onsetframes) {
- ambix_seek(ambix, onsetframes, SEEK_SET);
+ ambix_seek(x->x_ambix_t, onsetframes, SEEK_SET);
}
}
@@ -279,7 +281,7 @@ static void *ambix_read_child_main(void *zz) {
pthread_mutex_lock(&x->x_mutex);
- if (NULL==ambix) {
+ if (NULL==x->x_ambix_t) {
x->x_fileerror = errno;
x->x_eof = 1;
goto lost;
@@ -358,7 +360,7 @@ static void *ambix_read_child_main(void *zz) {
ambibuf = (float32_t*)calloc(localfifosize*ambichannels, sizeof(float32_t));
xtrabuf = (float32_t*)calloc(localfifosize*xtrachannels, sizeof(float32_t));
}
- sysrtn = ambix_readf_float32(ambix, ambibuf, xtrabuf, wantframes);
+ sysrtn = ambix_readf_float32(x->x_ambix_t, ambibuf, xtrabuf, wantframes);
if(sysrtn>0) {
merge_samples(ambibuf, ambichannels, want_ambichannels,
xtrabuf, xtrachannels, want_xtrachannels,
@@ -389,30 +391,30 @@ static void *ambix_read_child_main(void *zz) {
x->x_requestcode = REQUEST_NOTHING;
/* fell out of read loop: close file if necessary,
set EOF and signal once more */
- if(ambix) {
+ if(x->x_ambix_t) {
pthread_mutex_unlock(&x->x_mutex);
- ambix_close(ambix);
- ambix=NULL;
+ ambix_close(x->x_ambix_t);
+ x->x_ambix_t=NULL;
pthread_mutex_lock(&x->x_mutex);
}
pthread_cond_signal(&x->x_answercondition);
} else if (x->x_requestcode == REQUEST_CLOSE) {
- if(ambix) {
+ if(x->x_ambix_t) {
pthread_mutex_unlock(&x->x_mutex);
- ambix_close(ambix);
- ambix=NULL;
+ ambix_close(x->x_ambix_t);
+ x->x_ambix_t=NULL;
pthread_mutex_lock(&x->x_mutex);
}
if (x->x_requestcode == REQUEST_CLOSE)
x->x_requestcode = REQUEST_NOTHING;
pthread_cond_signal(&x->x_answercondition);
} else if (x->x_requestcode == REQUEST_QUIT) {
- if(ambix) {
+ if(x->x_ambix_t) {
pthread_mutex_unlock(&x->x_mutex);
- ambix_close(ambix);
- ambix=NULL;
+ ambix_close(x->x_ambix_t);
+ x->x_ambix_t=NULL;
pthread_mutex_lock(&x->x_mutex);
}
x->x_requestcode = REQUEST_NOTHING;
@@ -554,6 +556,14 @@ static void ambix_read_tick(t_ambix_read *x) {
/* number of sample frames in file */
SETFLOAT(atoms+0, (t_float)(x->x_ambix.frames));
outlet_anything(x->x_infoout, gensym("frames"), 1, atoms);
+
+ /* number of markers in the file */
+ SETFLOAT(atoms+0, (t_float)(ambix_get_num_markers(x->x_ambix_t)));
+ outlet_anything(x->x_infoout, gensym("num_markers"), 1, atoms);
+
+ /* number of regions in the file */
+ SETFLOAT(atoms+0, (t_float)(ambix_get_num_regions(x->x_ambix_t)));
+ outlet_anything(x->x_infoout, gensym("num_regions"), 1, atoms);
}
@@ -614,8 +624,8 @@ static t_int *ambix_read_perform(t_int *w) {
/* check for EOF (and buffer is about to drain) */
if (x->x_eof &&
- x->x_fifohead > x->x_fifotail &&
- x->x_fifohead <= x->x_fifotail + wantframes-1
+ x->x_fifohead >= x->x_fifotail &&
+ x->x_fifohead < x->x_fifotail + wantframes-1
) {
int xfersize;
if (x->x_fileerror) {
@@ -785,6 +795,80 @@ static void ambix_read_free(t_ambix_read *x) {
ambix_matrix_deinit(&x->x_matrix);
}
+static void ambix_read_marker(t_ambix_read*x, t_float marker_id) {
+ if (!x->x_ambix_t)
+ return;
+ if ( ((int)marker_id >= 0) && ((int)marker_id < ambix_get_num_markers(x->x_ambix_t)) ) {
+ ambix_marker_t *marker;
+ marker = ambix_get_marker(x->x_ambix_t, (int)marker_id);
+ if (marker) {
+ t_atom atoms[3]; // id pos name
+ SETFLOAT(atoms+0, (t_float)(int)marker_id);
+ SETFLOAT(atoms+1, (t_float)marker->position);
+ SETSYMBOL(atoms+2, gensym(marker->name));
+ outlet_anything(x->x_infoout, gensym("marker"), 3, atoms);
+ }
+ } else {
+ pd_error(x, "ambix_read~: no marker with this id in file");
+ }
+}
+
+static void ambix_read_all_markers(t_ambix_read*x) {
+ int nummarkers, i;
+ if (!x->x_ambix_t)
+ return;
+ nummarkers = ambix_get_num_markers(x->x_ambix_t);
+ for (i=0; i<nummarkers; i++) {
+ ambix_read_marker(x, i);
+ }
+}
+
+static void ambix_read_region(t_ambix_read*x, t_float region_id) {
+ if (!x->x_ambix_t)
+ return;
+ if ( ((int)region_id >= 0) && ((int)region_id < ambix_get_num_regions(x->x_ambix_t)) ) {
+ ambix_region_t *region;
+ region = ambix_get_region(x->x_ambix_t, (int)region_id);
+ if (region) {
+ t_atom atoms[4]; // id start_pos end_pos name
+ SETFLOAT(atoms+0, (t_float)(int)region_id);
+ SETFLOAT(atoms+1, (t_float)region->start_position);
+ SETFLOAT(atoms+2, (t_float)region->end_position);
+ SETSYMBOL(atoms+3, gensym(region->name));
+ outlet_anything(x->x_infoout, gensym("region"), 4, atoms);
+ }
+ } else {
+ pd_error(x, "ambix_read~: no region with this id in file");
+ }
+}
+
+static void ambix_read_all_regions(t_ambix_read*x) {
+ int numregions, i;
+ if (!x->x_ambix_t)
+ return;
+ numregions = ambix_get_num_regions(x->x_ambix_t);
+ for (i=0; i<numregions; i++) {
+ ambix_read_region(x, i);
+ }
+}
+
+static void ambix_seek_pos(t_ambix_read*x, t_float position) {
+ if (!x->x_ambix_t) {
+ pd_error(x, "ambix_read~: seek not possible, requested with no prior 'open'");
+ return;
+ }
+ pthread_mutex_lock(&x->x_mutex);
+ if (x->x_state == STATE_STARTUP) {
+ int64_t ret = ambix_seek(x->x_ambix_t, (int64_t)position, SEEK_SET);
+ if (ret < 0)
+ pd_error(x, "ambix_read~: seek not possible");
+ pthread_mutex_unlock(&x->x_mutex);
+ } else {
+ pthread_mutex_unlock(&x->x_mutex);
+ pd_error(x, "ambix_read~: seek not possible, playback already started");
+ }
+}
+
AMBIX_EXPORT
void ambix_read_tilde_setup(void) {
ambix_read_class = class_new(gensym("ambix_read~"), (t_newmethod)ambix_read_new,
@@ -797,6 +881,11 @@ void ambix_read_tilde_setup(void) {
class_addmethod(ambix_read_class, (t_method)ambix_read_dsp, gensym("dsp"), A_NULL);
class_addmethod(ambix_read_class, (t_method)ambix_read_open, gensym("open"), A_SYMBOL, A_DEFFLOAT, A_NULL);
class_addmethod(ambix_read_class, (t_method)ambix_read_print, gensym("print"), A_NULL);
+ class_addmethod(ambix_read_class, (t_method)ambix_read_marker, gensym("get_marker"), A_DEFFLOAT, A_NULL);
+ class_addmethod(ambix_read_class, (t_method)ambix_read_all_markers, gensym("get_all_markers"), A_NULL);
+ class_addmethod(ambix_read_class, (t_method)ambix_read_region, gensym("get_region"), A_DEFFLOAT, A_NULL);
+ class_addmethod(ambix_read_class, (t_method)ambix_read_all_regions, gensym("get_all_regions"), A_NULL);
+ class_addmethod(ambix_read_class, (t_method)ambix_seek_pos, gensym("seek"), A_DEFFLOAT, A_NULL);
if(0)
MARK("[ambix_read~] setup done");
diff --git a/samples/pd/ambix_write~-help.pd b/samples/pd/ambix_write~-help.pd
index 78414bf..83fda33 100644
--- a/samples/pd/ambix_write~-help.pd
+++ b/samples/pd/ambix_write~-help.pd
@@ -1,6 +1,5 @@
-#N canvas 518 132 758 533 10;
+#N canvas 84 104 758 533 10;
#X msg 646 30 \; pd dsp 1;
-#X msg 74 161 open \$1;
#X msg 74 49 bang;
#X obj 74 69 savepanel;
#X text 356 432 <buffersize> is given in samples per channels (unlike
@@ -43,15 +42,16 @@ extra channels are requested) \, the ambisonics channels will always
be periphonic (3D) semi-normalized (SN3D) and ordered after their ACN.
;
#X obj 330 477 ambix_info;
-#X connect 1 0 22 0;
-#X connect 2 0 3 0;
-#X connect 3 0 1 0;
-#X connect 8 0 22 0;
-#X connect 9 0 22 0;
-#X connect 10 0 22 0;
-#X connect 16 0 22 2;
-#X connect 19 0 22 1;
-#X connect 20 0 22 3;
-#X connect 21 0 22 4;
-#X connect 27 0 22 0;
-#X connect 28 0 22 0;
+#X msg 74 161 open -bytes 3 \$1;
+#X connect 1 0 2 0;
+#X connect 2 0 33 0;
+#X connect 7 0 21 0;
+#X connect 8 0 21 0;
+#X connect 9 0 21 0;
+#X connect 15 0 21 2;
+#X connect 18 0 21 1;
+#X connect 19 0 21 3;
+#X connect 20 0 21 4;
+#X connect 26 0 21 0;
+#X connect 27 0 21 0;
+#X connect 33 0 21 0;
diff --git a/samples/pd/ambix_write~.c b/samples/pd/ambix_write~.c
index 72c64c1..0adbdbc 100644
--- a/samples/pd/ambix_write~.c
+++ b/samples/pd/ambix_write~.c
@@ -1,7 +1,8 @@
/* ambix_write~ - write AMBIsonics eXchange files in Pd -*- c -*-
Copyright © 1997-1999 Miller Puckette <msp at ucsd.edu>.
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2014 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2016, Matthias Kronlachner
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -190,6 +191,7 @@ typedef struct _ambix_write
/* parameters to communicate with subthread */
char *x_filename; /* file to open (string is permanently allocated) */
ambix_fileformat_t x_fileformat; /* extended or basic */
+ ambix_sampleformat_t x_sampleformat; /* 16, 24 or 32 bit */
uint32_t x_ambichannels; /* number of ambisonics channels in soundfile */
uint32_t x_extrachannels; /* number of extra channels in soundfile */
ambix_matrix_t*x_matrix;
@@ -243,6 +245,8 @@ static void *ambix_write_child_main(void *zz) {
int64_t onsetframes = x->x_onsetframes;
ambix_fileformat_t fileformat = x->x_fileformat;
+
+ ambix_sampleformat_t sampleformat = x->x_sampleformat;
uint32_t ambichannels = x->x_ambichannels;
uint32_t xtrachannels = x->x_extrachannels;
@@ -277,7 +281,7 @@ static void *ambix_write_child_main(void *zz) {
ainfo.extrachannels=xtrachannels;
ainfo.samplerate=samplerate;
-
+ ainfo.sampleformat=sampleformat;
/* if there's already a file open, close it. This
should never happen since ambix_write_open() calls stop if
needed and then waits until we're idle. */
@@ -470,8 +474,8 @@ static void *ambix_write_new(t_symbol*s, int argc, t_atom*argv) {
x->x_f = 0;
- x->x_ambichannels = 0;
- x->x_extrachannels = nchannels;
+ x->x_ambichannels = achannels;
+ x->x_extrachannels = xchannels;
x->x_matrix=NULL;
x->x_canvas = canvas_getcurrent();
@@ -580,6 +584,7 @@ static void ambix_write_open(t_ambix_write *x, t_symbol *s, int argc, t_atom *ar
x->x_filename = filesym->s_name;
x->x_fileformat = fileformat;
x->x_requestcode = REQUEST_OPEN;
+ x->x_sampleformat = sampleformat;
x->x_fifotail = 0;
x->x_fifohead = 0;
diff --git a/utils/ambix-deinterleave.c b/utils/ambix-deinterleave.c
index d1fde0d..b9b944c 100644
--- a/utils/ambix-deinterleave.c
+++ b/utils/ambix-deinterleave.c
@@ -1,6 +1,6 @@
/* ambix_deinterleave - create an ambix file -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2014 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
diff --git a/utils/ambix-dump.c b/utils/ambix-dump.c
index b20c06c..42227fb 100644
--- a/utils/ambix-dump.c
+++ b/utils/ambix-dump.c
@@ -1,6 +1,6 @@
/* ambix_dump - create an ambix file -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2014 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
diff --git a/utils/ambix-info.c b/utils/ambix-info.c
index 29e2d50..b9db912 100644
--- a/utils/ambix-info.c
+++ b/utils/ambix-info.c
@@ -33,6 +33,32 @@
void print_usage(const char*name);
void print_version(const char*name);
+void print_markers(ambix_t*ambix)
+{
+ uint32_t num_markers = ambix_get_num_markers(ambix);
+ if (num_markers) {
+ ambix_marker_t *marker = NULL;
+ uint32_t i;
+ for (i=0; i < num_markers; i++) {
+ marker = ambix_get_marker(ambix, i);
+ if (marker)
+ printf(" Marker %d: name: %s position: %f \n", i, marker->name, marker->position);
+ }
+ }
+}
+void print_regions(ambix_t*ambix)
+{
+ uint32_t num_regions = ambix_get_num_regions(ambix);
+ if (num_regions) {
+ ambix_region_t *region = NULL;
+ uint32_t i;
+ for (i=0; i < num_regions; i++) {
+ region = ambix_get_region(ambix, i);
+ printf(" Region %d: name: %s start_position: %f end_position: %f \n", i, region->name, region->start_position, region->end_position);
+ }
+ }
+}
+
void printinfo(const char*path) {
ambix_info_t info;
ambix_t*ambix;
@@ -59,6 +85,7 @@ void printinfo(const char*path) {
case(AMBIX_SAMPLEFORMAT_PCM24): printf("PCM24"); break;
case(AMBIX_SAMPLEFORMAT_PCM32): printf("PCM32"); break;
case(AMBIX_SAMPLEFORMAT_FLOAT32): printf("FLOAT32"); break;
+ case(AMBIX_SAMPLEFORMAT_FLOAT64): printf("FLOAT64"); break;
default: printf("**unknown**");
}
printf(")\n");
@@ -94,6 +121,11 @@ void printinfo(const char*path) {
}
printf("\n");
+ printf("Number of Markers\t: %d\n", ambix_get_num_markers(ambix));
+ print_markers(ambix);
+ printf("Number of Regions\t: %d\n", ambix_get_num_regions(ambix));
+ print_regions(ambix);
+
printf("Close file '%s': ", path);
if(AMBIX_ERR_SUCCESS!=ambix_close(ambix))
printf("failed\n");
diff --git a/utils/ambix-interleave.c b/utils/ambix-interleave.c
index 5714275..3007e32 100644
--- a/utils/ambix-interleave.c
+++ b/utils/ambix-interleave.c
@@ -1,6 +1,6 @@
/* ambix_interleave - create an ambix file -*- c -*-
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2016 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
@@ -46,6 +46,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
#ifdef _MSC_VER
# define strdup _strdup
@@ -66,6 +67,8 @@ typedef struct ai_t {
ambix_t*outhandle;
ambix_matrix_t*matrix;
+ ambix_matrixtype_t matrix_norm; /* normalisation matrix */
+ ambix_matrixtype_t matrix_rout; /* routing matrix */
uint32_t channels;
uint32_t blocksize;
@@ -74,6 +77,7 @@ typedef struct ai_t {
static void print_usage(const char*path);
static void print_version(const char*path);
static ai_t*ai_close(ai_t*ai);
+static int ai_exit = 0;
static ai_t*ai_matrix(ai_t*ai, const char*path) {
SF_INFO info;
@@ -88,7 +92,7 @@ static ai_t*ai_matrix(ai_t*ai, const char*path) {
file=sf_open(path, SFM_READ, &info);
if(!file) {
- fprintf(stderr, "ambix_interleave: matrix open failed '%s'\n", path);
+ fprintf(stderr, "ambix_interleave: tried to open matrix file '%s': ...failed\n", path);
return NULL;
}
rows=info.channels;
@@ -121,6 +125,47 @@ static ai_t*ai_matrix(ai_t*ai, const char*path) {
return result;
}
+static ai_t*ai_matrix_predefined(ai_t*ai, const char*format) {
+ /* just parse the format string, and set the output matrix type */
+#define MAX_MATRIX_NAME 10
+ size_t len=strnlen(format, MAX_MATRIX_NAME);
+ char*fmt=calloc(len+1, 1);
+ ai_t*result=ai;
+ size_t i;
+ /* make everything lower-case */
+ for(i=0; i<len; i++)
+ fmt[i]=tolower(format[i]);
+ fmt[len]=0;
+ /* FuMa */
+ if(!strncmp(fmt, "fuma", len)) {
+ ai->matrix_norm=AMBIX_MATRIX_FUMA;
+ ai->matrix_rout=AMBIX_MATRIX_FUMA;
+ goto cleanup;
+ }
+ /* N3D/SID */
+ if(!strncmp(fmt, "n3d|sid", len) || !strncmp(fmt, "sid|n3d", len)) {
+ ai->matrix_norm=AMBIX_MATRIX_N3D;
+ ai->matrix_rout=AMBIX_MATRIX_SID;
+ goto cleanup;
+ }
+ /* SID */
+ if(!strncmp(fmt, "sid", len) || !strncmp(fmt, "sn3d|sid", len) || !strncmp(fmt, "sid|sn3d", len)) {
+ ai->matrix_norm=AMBIX_MATRIX_IDENTITY;
+ ai->matrix_rout=AMBIX_MATRIX_SID;
+ goto cleanup;
+ }
+ /* N3D */
+ if(!strncmp(fmt, "n3d", len) || !strncmp(fmt, "sn3d|acn", len) || !strncmp(fmt, "acn|sn3d", len)) {
+ ai->matrix_norm=AMBIX_MATRIX_N3D;
+ ai->matrix_rout=AMBIX_MATRIX_IDENTITY;
+ goto cleanup;
+ }
+ result=0;
+ cleanup:
+ free(fmt);
+ return result;
+}
+
static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
ai_t*ai=(ai_t*)calloc(1, sizeof(ai_t));
uint32_t channels=0;
@@ -129,11 +174,13 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
while(argc) {
if(!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
print_usage(name);
- exit(0);
+ ai_exit=0;
+ return ai_close(ai);
}
if(!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version")) {
print_version(name);
- exit(0);
+ ai_exit=0;
+ return ai_close(ai);
}
if(!strcmp(argv[0], "-o") || !strcmp(argv[0], "--output")) {
if(argc>1) {
@@ -143,6 +190,7 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
continue;
}
fprintf(stderr, "no output file specified\n");
+ ai_exit=64;
return ai_close(ai);
}
if(!strcmp(argv[0], "-O") || !strcmp(argv[0], "--order")) {
@@ -154,6 +202,7 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
continue;
}
fprintf(stderr, "no ambisonics order specified\n");
+ ai_exit=64;
return ai_close(ai);
}
if(!strcmp(argv[0], "-b") || !strcmp(argv[0], "--blocksize")) {
@@ -164,12 +213,14 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
continue;
}
fprintf(stderr, "no blocksize specified\n");
+ ai_exit=64;
return ai_close(ai);
}
if(!strcmp(argv[0], "-X") || !strcmp(argv[0], "--matrix")) {
if(argc>1) {
- if(!ai_matrix(ai, argv[1])) {
+ if(!ai_matrix(ai, argv[1]) && !ai_matrix_predefined(ai, argv[1])) {
fprintf(stderr, "Couldn't read matrix '%s'\n", argv[1]);
+ ai_exit=66;
return ai_close(ai);
}
argv+=2;
@@ -177,6 +228,7 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
continue;
}
fprintf(stderr, "no matrix file specified\n");
+ ai_exit=64;
return ai_close(ai);
}
ai->infilenames=argv;
@@ -184,13 +236,22 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
break;
}
+ if(ai->matrix && (ai->matrix_norm || ai->matrix_rout)) {
+ /* both a matrix-file and matrix-specs were given; bail out! */
+ print_usage(argv[0]);
+ ai_exit=64;
+ return ai_close(ai);
+ }
+
if(!ai->infilenames) {
fprintf(stderr, "no input files specified\n");
+ ai_exit=66;
return ai_close(ai);
}
if(!ai->outfilename) {
fprintf(stderr, "no output filename specified\n");
+ ai_exit=73;
return ai_close(ai);
}
@@ -205,10 +266,11 @@ static ai_t*ai_cmdline(const char*name, int argc, char**argv) {
if((channels > 0) && ai->matrix) {
if(channels != ai->matrix->rows) {
fprintf(stderr, "ambix_interleave: order%02d needs %d channels, not %d\n", order, channels, ai->matrix->rows);
+ ai_exit=65;
return ai_close(ai);
}
}
-
+ ai_exit=0;
return ai;
}
@@ -249,6 +311,12 @@ static ai_t*ai_close(ai_t*ai) {
ai=NULL;
return NULL;
}
+static ambix_matrix_t*ai_calc_matrix(unsigned int rowcols, ambix_matrixtype_t typ) {
+ ambix_matrix_t*mtx=ambix_matrix_init(rowcols, rowcols, NULL);
+ ambix_matrix_t*mtx2=mtx?ambix_matrix_fill(mtx, typ):NULL;
+ if(mtx2!=mtx)ambix_matrix_destroy(mtx); mtx=NULL;
+ return mtx2;
+}
static ai_t*ai_open_input(ai_t*ai) {
uint32_t i;
@@ -258,7 +326,6 @@ static ai_t*ai_open_input(ai_t*ai) {
ai->inhandles=(SNDFILE**)calloc(ai->numIns, sizeof(SNDFILE*));
ai->ininfo =(SF_INFO*)calloc(ai->numIns, sizeof(SF_INFO));
}
-
for(i=0; i<ai->numIns; i++) {
SNDFILE*inhandle=ai->inhandles[i];
SF_INFO*info=&ai->ininfo[i];
@@ -271,7 +338,7 @@ static ai_t*ai_open_input(ai_t*ai) {
ai->info.samplerate=info->samplerate;
if(ai->info.sampleformat==AMBIX_SAMPLEFORMAT_NONE) {
int format=info->format;
- if((format & SF_FORMAT_FLOAT) || (format & SF_FORMAT_DOUBLE))
+ if((format & SF_FORMAT_FLOAT))
ai->info.sampleformat=AMBIX_SAMPLEFORMAT_FLOAT32;
else if((format & SF_FORMAT_PCM_S8) || (format & SF_FORMAT_PCM_16))
ai->info.sampleformat=AMBIX_SAMPLEFORMAT_PCM16;
@@ -279,13 +346,54 @@ static ai_t*ai_open_input(ai_t*ai) {
ai->info.sampleformat=AMBIX_SAMPLEFORMAT_PCM24;
else if((format & SF_FORMAT_PCM_32))
ai->info.sampleformat=AMBIX_SAMPLEFORMAT_PCM32;
+ else if((format & SF_FORMAT_DOUBLE))
+ ai->info.sampleformat=AMBIX_SAMPLEFORMAT_FLOAT64;
else
ai->info.sampleformat=AMBIX_SAMPLEFORMAT_PCM24;
}
channels+=info->channels;
ai->inhandles[i]=inhandle;
+ /* check if the input is a single .AMB file, */
+ if(1 == ai->numIns
+ && inhandle
+ && (sf_command(inhandle, SFC_WAVEX_GET_AMBISONIC, NULL, 0) == SF_AMBISONIC_B_FORMAT)) {
+ /* it is, so we decode it as ambisonics */
+
+ if(ai->matrix || ai->matrix_rout || ai->matrix_norm) {
+ /* but not if the user already set an adaptor matrix */
+ fprintf(stderr, "Cannot set adaptor-matrix when interleaving from AMB file.\n");
+ ai_exit=65;
+ return ai_close(ai);
+ }
+ ai->matrix = ai_calc_matrix(info->channels, AMBIX_MATRIX_FUMA);
+ }
+ }
+ if (ai->matrix_rout || ai->matrix_norm) {
+ /* predefined matrix, but we need to calc the size based on the channels */
+
+ if(ai->matrix)ambix_matrix_destroy(ai->matrix); ai->matrix=NULL;
+ if((ai->matrix_rout == ai->matrix_norm) && (ai->matrix_norm == AMBIX_MATRIX_FUMA)) {
+ ai->matrix=ai_calc_matrix(channels, AMBIX_MATRIX_FUMA);
+ if(!ai->matrix) {
+ fprintf(stderr, "Unable to set Furse-Malham matrix with %d channels\n", channels);
+ ai_exit=65;
+ return ai_close(ai);
+ }
+ } else {
+ ambix_matrix_t*route=ai_calc_matrix(channels, ai->matrix_rout);
+ ambix_matrix_t*norm =ai_calc_matrix(channels, ai->matrix_norm);
+ if(route && norm) {
+ ai->matrix = ambix_matrix_multiply(route, norm, NULL);
+ }
+ if(route)ambix_matrix_destroy(route); route=NULL;
+ if(norm )ambix_matrix_destroy(norm ); norm =NULL;
+ if(!ai->matrix) {
+ fprintf(stderr, "Unable to set normalisation/routing matrix with %d channels\n", channels);
+ ai_exit=65;
+ return ai_close(ai);
+ }
+ }
}
-
/* check whether input channels form a valid full set */
if(ai->matrix) {
if(channels<ai->matrix->cols) {
@@ -355,11 +463,20 @@ static ai_t*ai_open_output(ai_t*ai) {
return ai;
}
+/* deinterleave an *interleaved* source of <frames>*<channels> data in dest */
+static void deinterleaver(float*dest, const float*source, uint64_t frames, uint32_t channels) {
+ uint32_t channel;
+ for(channel=0; channel<channels; channel++) {
+ uint64_t frame;
+ for(frame=0; frame<frames; frame++) {
+ *dest++ = source[frame*channels+channel];
+ }
+ }
+}
+/* interleave a *non-interleaved* source of <frames>*<channels> data in dest */
static void interleaver(float*dest, const float*source, uint64_t frames, uint32_t channels) {
uint64_t frame;
-
-
for(frame=0; frame<frames; frame++) {
uint64_t channel;
for(channel=0; channel<channels; channel++) {
@@ -372,7 +489,8 @@ static void interleaver(float*dest, const float*source, uint64_t frames, uint32_
static ai_t*ai_copy_block(ai_t*ai,
float*ambidata,
float*extradata,
- float*interleavedata,
+ float*deinterleavedata,
+ float*sourcedata,
uint64_t frames) {
uint32_t i;
uint64_t channels=0;
@@ -381,20 +499,30 @@ static ai_t*ai_copy_block(ai_t*ai,
for(i=0; i<ai->numIns; i++) {
uint64_t offset=channels*frames;
SNDFILE*in=ai->inhandles[i];
+ uint32_t inchannels=ai->ininfo[i].channels;
if(in) {
+ uint64_t readframes=0;
//printf("reading %d frames from[%d] at %p+%d\n", (int)frames, (int)i, interleavedata, (int)offset);
- if(frames!=sf_readf_float(in, interleavedata+offset, frames)) {
+ if(sourcedata && inchannels>1) {
+ readframes=sf_readf_float(in, sourcedata, frames);
+ if(readframes)
+ deinterleaver(deinterleavedata+offset, sourcedata, frames, inchannels);
+ } else {
+ readframes=sf_readf_float(in, deinterleavedata+offset, frames);
+ }
+
+ if(frames!=readframes) {
return ai_close(ai);
}
- channels+=ai->ininfo[i].channels;
+ channels+=inchannels;
}
}
if(ambidata)
- interleaver(ambidata, interleavedata, frames, ai->info.ambichannels);
+ interleaver(ambidata, deinterleavedata, frames, ai->info.ambichannels);
if(extradata)
- interleaver(extradata, interleavedata+frames*ai->info.ambichannels, frames, ai->info.extrachannels);
+ interleaver(extradata, deinterleavedata+frames*ai->info.ambichannels, frames, ai->info.extrachannels);
//printf("writing %d frames to %p & %p\n", (int)frames, ambidata, extradata);
@@ -408,7 +536,8 @@ static ai_t*ai_copy_block(ai_t*ai,
static ai_t*ai_copy(ai_t*ai) {
uint64_t blocksize=0, blocks=0;
uint64_t frames=0, channels=0;
- float32_t*ambidata=NULL,*extradata=NULL,*interleavebuffer=NULL;
+ float32_t*ambidata=NULL,*extradata=NULL,*interleavebuffer=NULL,*source=NULL;
+ uint64_t i, maxchannels=0;
if(!ai)return ai;
blocksize=ai->blocksize;
if(blocksize<1)
@@ -416,27 +545,35 @@ static ai_t*ai_copy(ai_t*ai) {
frames=ai->info.frames;
channels=(ai->info.ambichannels+ai->info.extrachannels);
+ for(i=0; i<ai->numIns; i++) {
+ uint64_t c=ai->ininfo[i].channels;
+ if(c>maxchannels)maxchannels=c;
+ }
+
if(ai->info.ambichannels>0)
- ambidata =(float32_t*)malloc(sizeof(float32_t)*ai->info.ambichannels *blocksize);
+ ambidata =malloc(sizeof(*ambidata )*ai->info.ambichannels *blocksize);
if(ai->info.extrachannels>0)
- extradata=(float32_t*)malloc(sizeof(float32_t)*ai->info.extrachannels*blocksize);
+ extradata=malloc(sizeof(*extradata)*ai->info.extrachannels*blocksize);
+ if(maxchannels>1)
+ source =malloc(sizeof(*source )*maxchannels *blocksize);
interleavebuffer=(float32_t*)malloc(sizeof(float32_t)*channels*blocksize);
while(frames>blocksize) {
blocks++;
- if(!ai_copy_block(ai, ambidata, extradata, interleavebuffer, blocksize)) {
- return ai_close(ai);
- }
+ ai=ai_copy_block(ai, ambidata, extradata, interleavebuffer, source, blocksize);
+ if(!ai) break;
frames-=blocksize;
}
- if(!ai_copy_block(ai, ambidata, extradata, interleavebuffer, frames))
- return ai_close(ai);
+ if(ai)
+ ai=ai_copy_block(ai, ambidata, extradata, interleavebuffer, source, frames);
free(ambidata);
free(extradata);
free(interleavebuffer);
+ free(source);
+
return ai;
}
@@ -459,7 +596,7 @@ int main(int argc, char**argv) {
ai_t*ai=ai_cmdline(argv[0], argc-1, argv+1);
if(!ai) {
print_usage(argv[0]);//"ambix_interleave");
- return 1;
+ return ai_exit;
}
return ambix_interleave(ai);
@@ -474,7 +611,8 @@ void print_usage(const char*name) {
printf(" -h, --help print this help\n");
printf(" -o, --output output filename\n");
printf(" -O, --order force ambisonics order (default: autodetect)\n");
- printf(" -X, --matrix specify adaptor matrix file\n");
+ printf(" -X, --matrix specify adaptor matrix file or a predefined matrix\n");
+ printf(" ('FuMa', 'n3d|sid', 'n3d' or 'sid')\n");
printf(" -b, --blocksize blocksize for copying (default: %d)\n", DEFAULT_BLOCKSIZE);
printf("\n");
@@ -487,8 +625,9 @@ void print_usage(const char*name) {
"\nIf you specify the 'order', then all extranous channels will be stored as 'extra' channels."
"\n"
"\nYou can also write extended ambix files, by specifying an adaptor matrix"
- "\n(a soundfile where the channels are read as rows and the frames as columns),"
- "\nin which case the columns of the matrix define the number of (reduced) ambisonics channels read from the input"
+ "\n(either a soundfile, where the channels are read as rows and the frames as columns,"
+ "\nor by specifying one of the standard matrices), in which case the columns of the"
+ "\nmatrix define the number of (reduced) ambisonics channels read from the input"
"\nand the rows of the matrix must form a full 3d ambisonics set."
"\nInput channels exceeding the number of matrix columns are stored as 'extra' channels."
"\n"
diff --git a/utils/ambix-jplay.c b/utils/ambix-jplay.c
index 8aed9ad..41c0bae 100644
--- a/utils/ambix-jplay.c
+++ b/utils/ambix-jplay.c
@@ -1,7 +1,7 @@
/* ambix-jplay.c - play back an ambix file via jack -*- c -*-
Copyright © 2003-2010 Rohan Drape <rd at slavepianos.org>
- Copyright © 2012 IOhannes m zmölnig <zmoelnig at iem.at>.
+ Copyright © 2012-2014 IOhannes m zmölnig <zmoelnig at iem.at>.
Institute of Electronic Music and Acoustics (IEM),
University of Music and Dramatic Arts, Graz
--
libambix packaging
More information about the pkg-multimedia-commits
mailing list