pax_global_header00006660000000000000000000000064130007702420014505gustar00rootroot0000000000000052 comment=9785e37ec7e9a04077d2c5e2985d2331a8bd97df ambix-0.1.1/000077500000000000000000000000001300077024200126045ustar00rootroot00000000000000ambix-0.1.1/.deploy-documentation.sh000077500000000000000000000033011300077024200173610ustar00rootroot00000000000000#!/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@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}" ambix-0.1.1/.travis.yml000066400000000000000000000041131300077024200147140ustar00rootroot00000000000000language: 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@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 VERBOSE=1 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) ambix-0.1.1/AUTHORS000066400000000000000000000002101300077024200136450ustar00rootroot00000000000000 © 2012, Institute of Electronic Music and Acoustics © 2012, ivana © 2012-2016, IOhannes m zmölnig © 2016, Matthias Kronlachner ambix-0.1.1/BUGS000066400000000000000000000000671300077024200132720ustar00rootroot00000000000000ambix-interleave: fails to re-interleave ambix files ambix-0.1.1/CHANGELOG000066400000000000000000001154451300077024200140300ustar00rootroot00000000000000libambix (0.1.1) unstable; urgency=medium [ IOhannes m zmölnig ] * debugging printout in full precision * updated pinv testdata * raise threshold for pinv-test * scale the differences to the fixedpoint max * b2e_identity4x4_float: allow to set the eps * tests/b2e_eye4_float32: allow to set the eps * use double internally for test-data generation * use float64_t internally if no speed-loss is to be expected * tests/common_b2e: group ambix file operations * epsilon for tests/b2e_eye4_f32_f64 * epsilon for tests/b2e_eye4_f32_i32 * adjusted epsilon for b2e_rand4x7_*_pcm16 * use VERBOSE envvar to display the test-suite.log on failure * added coverity-override for CID:153347 * early exit if no strings are being added * early check for valid data (to avoid dereference before NULL-check) * made CAF-markers C-compatible * helper-script to get authors and copyright per file * added CHANGELOG and NEWS -- IOhannes m zmölnig Sun, 16 Oct 2016 23:21:31 +0200 libambix (0.1) unstable; urgency=medium [ IOhannes m zmölnig ] * fixed typos in header * return standard exit-codes * fixed double free if ai_copy_block() failed * allow dynamic matrices * helper-functions to calculate predefined matrices * prevent both matrix-file and matrix-specs at the same time * overload '-X' flag to sepcify adaptor matrix * updated help-printout * re-formatted README (as markdown) * initial Travis-CI config * install build-dependencies for sndfile * go back to project build-dir after building libsndfile * verbose build of libsndfile * fixed check for AMBIX_MATRIX_FUMA * removed superfluous NULL-pointer check * free data on early exit * free temporary fmt buffer * run the test-suite * build everything verbosely * remove libtool libs for libsndfile * debug: check whether /usr/local/lib is in LD_LIBRARY_PATH * debugging via ldd: which libsndfile is used? * set LD_LIBRARY_PATH before running 'make check' * started contributing guide [ Matthias Kronlachner ] * pd read external avoid loop on end of file * pd write external support selection of sampleformat * add support for read/write float64 (double) * libsndfile backend support float64 (double) * null backend support float64 * coreaudio backend float64 support * add float64 matrix multiplication * add pseudo-inverse matrix operation * utils add float64 support [ IOhannes m zmölnig ] * ensure 'foreign' mode for automake * [libambix/tests] include data.h into dist tarball * [libambix/tests] include data/file1.caf into dist tarball * pseudo-build test-data * run `make distcheck` as part of the travis-ci build * need to set the LD_LIBRARY_PATH for distcheck as well * C<=C99 does not allow variable-declarations inside loop-preamble * 'make distcheck' includes 'make check' * copyright-update, trailing whitespace, moved comment * fixed memleaks when calculating the pseudo-inverse fails * fixed memleak when calculating the inverse fails * Fixed typo resulting in FTBFS * Update README.md * more contibuting * don't overwrite the to-be-inverted matrix * nicer printout * zero-padding, doc * testing ambix_matrix_pinv() * free temporary matrix after use. * free eye-matrix after use * skip unimplemented tests * proper NULL-initialization of pointers * print addresses when printing matrices * STOPTEST macro to indicate successfull run of subtest * use STARTTEST/STOPTEST * mtxinverse_test takes 'const' matrices * dynamically transpose data rather than storing transposed data statically * some constness tests for matrix operations * compiler warnings about unimplemented tests * remember to do even more constness tests * added matrix-constness test to testsuite * [doxygen] subgroups * use ascii - rather than unicode – * removed empty lines * fixed comments * easier to read return of -abs() * test-implementation (float32 only) for mergeadaptor_matrix * declarations of the mergeadaptor_matrix() functions * easier to read "return -abs(err)" * call _ambix_mergeAdaptormatrix() if ambix->use_matrix is set when writing * setting the adaptor-matrix in WRITE+BASIC mode switches to BASIC2EXTENDED * fixed typo * easier to read "return -abs(err)" * [doxygen] (sub)sections for cmdline utilities * return INVALID_MATRIX if matrix cannot be inverted * use realinfo.fileformat for setting adaptormatrix in WRITE mode * (fake) return success in the *_if() helpers * print_if() helper that doesn't exit * print matrix if it is uninvertible * test invertibility of standard matrices * basic test for basic2extended writing * first basic2extended test * make ambix_matrix_transpose() and ambix_matrix_invert() as private by prefixing '_' * added _ambix_matrix_transpose() to private header * alternative implementation for matrix inversion * build the alternative matrix-inversion * function prototypes for matrix inversion in private.h * [matrix] use gauss-jordan inversion from matrix-invert.c * [matrix] remove local implementation of gauss-jordan inversion * use cholesky's algorithm to (pseudo) invert matrices * note that cholesky's inversion gives us the pseudo-inverse for free * renamed 'simple' tests to 'basic' * renamed ambix_none.c to common_none.c * saner frequency calculation * use a normal frequency * STARTTEST/STOPTEST now take format-strings and require \n * start/stop for b2e test * b2e: use identity matrix for first test * run b2e test * less verbose * basic2extended testing a number of square matrices * avoid passing of duplicate info to b2e test * use new API for b2e tests * don't test EXTENDED ambi readback * be more specific about writing EXTENDED files as BASIC * allow to open a basic2extended file for writing * need to pass the ambichannels-on-disk to ambix_open() * description of which FuMa matrix is being tested * free mtx after use * free pinv-matrix after use * lower frequency for test-signal * cleanup for early exit * another basic2extended test with a [4x9] random-matrix * make sure to reserve enough memory in the adaptorbuffer * merge-adaptormatrix: cols=full set; rows=reduced set * supporting BASIC2EXTENDED writing * destroy temp matrix after use * run tests in functions to isolate them * removed "goto cleanup" * compare against target ambichannels * use '%g' to pretty-print floats * re-use index variables * simplify addings new TESTS to Makefile.am * split basic2extended tests into separate files * allocate enough memory to hold both raw and adaptored ambi-channels * whitespace * allow to run valgrind for unit-tests * disabled serial-tests so check-valgrind works * fixed memleak in const-matrix tests * remove AX_VALGRIND_DFLT * allow coverity-scan for this branch * ambix_mergeadaptormatrix for all types * basic2extended test with 4x7 matrix * removed unneeded includes * [tests] lower thresholds for diffs * [tests] print used epsilon on failure * [tests] basic2extended tests with extrachannels * added float64 tests * [tests] added basic2extended tests for PCM formats * revert coverity-scan builds on all branches * added copyright info for cholesky decomposition * forgot closing comment * support for using AMB-files as input to ambix-interleave * fixed UUID-printout * renamed 'interleavedata' to the more correct 'interleavedata' * function to DEinterleave data * don't cast the result of malloc() * cleanup heap-allocated memory on early exit * provide a working-buffer for de-interleaving mulichannel input data * use temporary variable for number of channels per source * use temporary variable to check the success of sf_readf() * de-interleave multichannel input data * whitespace * don't build the gh-pages branch with travis-ci * documentation on BASIC2EXTENDED writing * simple doxygen apidoc deploy-script for travis/gh-pages * deploy doxygen * fixed typo in travis.yml * only deploy doxygen if not a PR and on master * getting rid of 'realpath' * print the do-doxygen variable * use C-style comments * TRAVIS_PULLREQUEST is when there's no PR * link to API documentation * [travis] hardcoding the repository * [travis] print errors when early exiting doxygen-deploy * [travis] B-D on doxygen * [travis] drop DOXYGEN_DEPLOY variable * [travis] drop unneeded blacklist for gh-pages branch * [doxygen] don't embed TIMESTAMP into html * use C++-style comments for missing code * [doxygen] free() the info junk * [doxygen] cosmetic fixes * [ooxygen] rephrased the basic2extended explanation * [doxygen] fix URL to mathjax * [doxygen] one-line project description * [doxygen] use for external links * [doxygen] started FAQ * [doxygen] exclude a few section from documentation * private versions of _ambix_matrix_multiply() and _ambix_matrix_pinv() * deprecate ambix_matrix_pinv() and ambix_matrix_multiply() * updated copyright * updated copyright-dates * added '--enable-debug' flag to configure * re-ordered flags: preprocessor, compiler, linker * raise visibility for DEBUG builds * added LDFLAGS to coverage builds (and use configure --enable-debug) * more generic testsuite-tests * print line-number when accumulating diffs * some generic tests for matrix-diff * added generic test for data utils * tricking higher coverage * disabled unused code * more matrix tests * disabling more unused code * ignore intermedia files from coverage-analysis * private tests * renamed deploy-doxygen to deploy-documentation * [travis-ci] use addons.apt for installing packages * deploy coverage directory as well... * [travis-ci] create a coverage report * run gcc+coverage and clang+coverity * deploy commits the entire output-directory (and is more verbose) * Use codecov.io as an external code-coverage test service * collapsed duplicate code in ambix_set_adaptormatrix * Call codecov.io after coverage.sh * added codecov.io badge to README.md * fix hyphenation of up-to-date [ Matthias Kronlachner ] * add marker and region functions to api * add markers and regions to ambix_t_struct * add implementation for marker and regions * add marker and region debug printout to utilities * add unit test for reading/writing markers and regions [ IOhannes m zmölnig ] * make doxyfile settable * fixed typo * mention output and *input* of audio-data * mention float64 asd possible format * single-line fail_if() * run a simpl2extended-test with chunksize=0 * cast functions to make values representable in low-resolution formats * make data_* generator functions accept a format-argument * mroe towards type-agnostic tests * adapted to new type-agnostic API * adapted to new type-agnostic API * easier debugging by using helper-vars * include common_b2e.h * adapt to new API (and use a header for function declarations) * alignment, printout... * first test to pass fmt * enabled int32 and int16 builds for specific test (b2e-eye4x4) * split format-tests * [travis-ci] display test-suite logs in case of failure * type-variable readf/writef wrappers * use vartype filereader/writer * consistent function-names for data_* foo * put data_size() and data_calloc() into common-header * use vartype data for b2e tests * consinstent indentation * common helper-functions getpid and unlink * use new helper-functions to create unique filenames * fun to generate uniqueish filename * better uniquefilename generator * use ambixtest_rmfile() instead of unlink() * dynamic outfilename * added a counter to allow for multiple files in the same process * FILENAME macros * use FILENAME macro * use FILENAME_FILE macro for output files * unique-filenames are now generated in the unittestfile itself * indentation * fixed indentation * fixed left-over code that causes FTFBS * normalized indentation * install ca-certificates to (hopefully) support coverity's new certificate * ignore .gcno files * test for ambix_get_sndfile() * build get_sndfile test * yet another workaround for travis-ci's outdated ca-certificates * fixed typo * disable unused code via preprocessor * renamed tests/matrix to tests/matrixtests * allow mtx_pinv() tests without reference result * try to invert MATRIX_ONE and MATRIX_ZERO * early exit if matrix_diff() has NaNs (rather than failure) * fail if mtx-inversions succeeds and no reference result is present. * untabify [ Matthias Kronlachner ] * add missing documentation to marker api functions * add private functions for handling chunks and reading/writing marker/region/strings data * add read/write any chunk to sndfile implementation * add implementation of reading/writing marker/region/strings chunk * remove debug outputs * check datasize before reading to avoid crash in case of invalid chunks * remove code duplication for byteswapping * remove warning of passing incompatible pointer types * cast to avoid warnings [ IOhannes m zmölnig ] * fixed-all-the-things [ Matthias Kronlachner ] * fixed return code * add read/write markers when opening file * marker chunk fix unnecessary allocations * add empty string in marker/region to unittest * pd read output number of markers/regions * pd-read external marker region read/seek support * remove printf from marker unittest * utils info print marker/region info [ IOhannes m zmölnig ] * [doc] note on unit-tests and CI * Fixed memleaks in unit-test * Fixed memory leaks in new marker_region_chunk code * refactored ambix_write_chunk() * [tests] link markers_region with common.c * [tests] create "unique" filename for markers_region test * [tests] remove test datafile once we are done * C<99 needs variable declarations at beginning of block * exclude .git* files from export * exclude .git* files from export * bumped version to 0.1 -- IOhannes m zmölnig Sun, 5 Oct 2016 22:50:17 +0200 libambix (0.0.1) unstable; urgency=medium [ iem user ] * cleaned up include paths [ iem user ] * forgot ambix.h * adjusted to custom libsndfile * startup script for custom libsndfile * load some more libraries * some more tests * ax testfiles [ IOhannes m zmölnig ] * moved external to pd/ folder * almost empty header files * UTF-8ified * doxygen documentation * dummy base file * start of autotools * doxygen config * use 'unsigned long' rather than 'size_t' * added ambix_err_t * dummy implementation * define AMBIX_INTERNAL when building the library * more documentation * return codes are ambix_err_t * updated gitignore * implemented ambix_get_sndfile * added sampleformat enum * check for libsndfile * start to read files * renamed AMBIX_EXTERN to AMBIX_API * use AMBIX_API * samplerate as double * documentation * typedefs for number types of given width * check for stdint.h * private header * reading matrix * added some fields to ambix_t * might work (or now) * protect file-inclusion with ifdef * no need to check for unistd.h and stdint.h * added matrix type * UUID-chunk handling is now in separate file * put matrix functionality in separate file * removed functions now found in separate files * build newly added files * _ambix_checkuuid() returns uint32_t * use new ambixmatrix_t type * moved sndfile code into separate file * added utility functions * use utility functions * test utilities * reorganized code: (private) sources live in src/ * fixed leftovers from function-renames * fixed double free on ambix_close() * set ambixinfo structure after reading * print some information * 32bit byte-swapper helper * ambix_matrix_fill_swapped() to fill matrix with byte-swapped data * check whether we need to byte-swap and do accordingly * reduced includes * UTF8ified * fixed typo * moved typedefs into separate header file * AMBI_EXPORT on gcc: visibility("default") * use visibility=hidden by default * use camelCase for function names * remove trailing whitespace * added some more errors * functions for getting/setting the matrix * fixed typo when assigning samplerate to ambixinfo * reset ambixinfo before setting it and returning to host * print reconstruction matrix * return reconstruction matrix (if feasible) * return proper error codes * MARK() define for easier debugging * use matrix from args * return AMBIX_ERR_SUCCESS rather than 0 * added ambix_matrix_copy() * implemented matrix multiplication * renamed getReconstructionMatrix() to getAdaptorMatrix() * dummy implementations for reading audio * documentation * initial adaptorbuffer handling * it's "adaptor" not "adapator" * initialize adaptor buffer on open * function-rename ambix_getReconstructionMatrix() -> ambix_getAdaptorMatrix() * adaptorbuffer resize now takes a sizeof() argument * ambix_matrix_create() and ambix_matrix_destroy() * adaptor code * implement _ambix_readf_ for libsndfile * deinitialize adaptorbuffer on ambix_close() * simple read implementation * shortened and improved description of ambix_readf_* * API for writing ambix files * backend implementation for writing audio to CAF * renamed _ambix_adaptor to _ambix_splitAdaptor * implement mergeAdapator * fixed possible segfault * implement data writing * accessor functions for UUID by version * implemented ambix_matrix_to_uuid1 * comment about quality of UUID * renamed setPremultiplyMatrix() to setAdaptorMatrix() * added filemode for read&write * store openmode in ambix_t structure * store byteswap info in ambix_t struct * ambix_write_header() * write_header() implementation * check format before writing header * fixed forgotten */ * documentation * write_uuidchunk * setting adaptormatrix for AMBIX_SIMPLE * use matrix2 rather than finalmatrix * shadow ambixinfo to allow easy conversion * ambix_matrix_eye() * clear 2nd matrix on ambix_close() * AMBIX_SIMPLE->AMBIX_EXTENDED conversion * use variables to enhance readability * added ambix_test a simple ambix file writer * private data is now only in backend * first draft of _ambix_write_uuidchunk * (dummy) checks before reading/writing * typo prevented full copy of ambixinfo * check whether properties are correct for writing * _ambix_print_info() helper * handle AMBIX_READ flag * initialize everything to 0 * print_sfinfo() helper * initialize everything to 0 * force otherchannels to 0 when opening ambix simple * added FIXXME that ambix_open() shouldn't fail so often * ambix_info now takes a list of files * write simple and extended files * use C-style comments rather than C++-style * uncomment the 'extern "C"' clause * moved format-detection logic out of sndfile.c * moved variables to form better groups * check whether reading/writing has started * return negative error in ambix_(read|write)f_* * made it compile... * added unsigned int type to number32_t union * _ambix_swap4array() * simpler implementation (and easier to optimize) * only free matrix if it is self-allocated * full test writing ambix extended * try to get properly aligned memory * freeing chunk_info on close() * trying to get properly align memory * print utilities * is_CAF is only boolean * don't forget to swap rows/cols * write something into matrix * what utilities to expect * moved matrix and utility declaration in separate headers * start (not much yet) * starting ambix_interleave * seems to work a bit... * fixed docs so doxygen stops complaining * better wording * use upper-case at beginning of sentence * re-organized code * protect against double inclusion * checks for libraries * specify Makefile's at beginning of configure.ac * include config.h if possible * write defines to config.h * tests for some sndfile specifics * typedefs for (u)int16 * sndfile.h should only be included in the backend specific implementation * need stdio.h for fprintf() * added pkg-config support for autotools * use pkg-config to check for sndfile * use SNDFILE_(CFLAGS|LIBS) for building ambix_interleave * read blocksize from cmdline * ambix_open overwrites ambixinfo, so use a copy * use blocksize from cmdline (and fix copying code) * print info on channels and frames after opening input files * added --help and --version options * added ambix_deinterleave * return SUCCESS on success * matrix multiplication of data-chunks * unit tests * include stdint.h on linux * include unit-tests * renamed 'success' to 'pass' to 'pass' * added fail_if() and friends * a real test: matrices * fixed some issues caught by unittests * ignore some autotools stuff * added some common functions * migrating functions to common.c * some more functions: comparing anonymous data * test for writing AMBIX_NONE files * print data and fix data_sine() * fixed data_sine() * finalized * tests for ambix simple * add eps to _diff() functions * split tests into functions * more data, better eps * added STARTTEST macro * check for isNan * use other matrix values to avoid roundign errors * autoprefix * new data generator: ramp * test for large data multiplication with eye * fixing matrix multiplications * at least deinterleaving simple files now works * test for ambix_extended * fixed extra-names * calloc(membercount, membersize) * changed matrix_fill to accept additional byteswap parameter * adapted to new matrix_fill function * made it work more sanely * implemented matrix reading * removed byteswap business from public API * no more byteswap in ambix API * apply function renames * renamed ambixfileformat to fileformat * renamed 'otherchannels' to 'extrachannels' * adapted to field renames * adapted to no transpose/no byteswap ambix API * error messages and matrix reading * removed ambix_matrix_fill_transposed() from public API * count samples that are outside eps * test for chunked writing * apply interleaver * less verbose * added data_transpose() * fixed datamul test * simplified code * seems to work... * cleaned up code * removed trailing whitespace * ISO-8859-15 to UTF-8 * renamed ambixinfo_t to ambix_info_t and likewise ambixmatrix_t * renamed CamelCase names to lower_case names * added license * moved COPYING to root * distribute doxygen file * better wording * generic install instruction * added autogen.sh * removed functions that are now in utils.h * renamed ambix_isFullSet to ambix_is_fullset * allow compilation on libsndfile without get_chunk() * added support for SFC_UUID * added test for sf_set_chunk() * fixed UUID reading with HAVE_UUID_INFO * unlink (delete) files after tests * switch to iterator based chunk reading * check for iterator based chunk access in sndfile * renamed ambix_ to ambix- * what's next? * fixed memleaks in tests * automake doesn't like hyphens in variables * added NULL backend * added ENABLED/DISABLED automake-conditionals * enable silent rules * added forgotten files * let configure handle the soname version * updated homepage field * renamed matrix_fill functions * adapted to function rename * adapted to function rename * remove trailing '====' when printing tests * renamed private member variables * added short readme * clarified docs * first half-implementation of FuMa->ambix converter * allow .amb files to be read * moved doxygen config into doc/ folder * use tex to set formulas * its libambix not libGcrypt * added main documentation in libambix.h * usage documentation (reading) * documentation fixups * removed ambix_write_header() * ambix_write_header() has been removed * ambix_write_header() has been removed * removed executable flag from data files * removed start-script only valid for a special computer * getting rid of old code * added check for OS * more documentation * stub for Pd-external * configure the Pd-part * added some more M4-macros * added convenience links and RTE_FLAGS * made it compile * starting to implement ambix_read~ * rename CHECK_RTE to IEM_CHECK_RTE * more in pd * fixed splitAdaptormatrix implementations * ambix_writef_*() takes pointer to const data * use (const) pointers where appropriate * non-threaded and working prototype * link against libambix * added ambix-dump, as simple utility that dumps ambix-files to the stdout * shortened lines in comments to 80chars * formatting * ambix_writef() now take pointers to const sources * iso2utf conversion * use v5(SHA1) UUIDs * added notes on format bugs * renamed "SIMPLE" to "BASIC" * enumerate some common conversion matrices * doxygen files now reside in doc/ * added pd to SUBDIRS * make _matrix_(diag|router) available internally * move _matrix_sid2acn into separate source file * move FuMa code into separate file * added docs about .amb format * started to port jack.play to ambix-jplay * fixed boilerplate description * enhanced utils/README * added copyright boilerplate to ambix-jplay * use ambix-jplay throughout * use full pathname in usage() * indentation * common files for jack-clients * slowly moving towards ambix-jplay * when requesting EXTENDED as BASIC, return the number of decoded ambichannels * small jcommon library * include jcommon library into build system * got some sound * code cleanup * properly setting memory to zero * when splitting the interleaved data, we need to take care of the _real_ channel layout * properly split out the extrachannels * don't fail if libsamplerate cannot be found * include config.h if there * include jack.record as ambix-jrecord * don't override HAVE_SAMPLERATE * run even without libsamplerate * AC_DEFINE(HAVE_*) for pkg-config * starting to make it work * renamed 'jack_client_unique_store' to 'jack_client_unique' * group jack calls together * added 'jack_client_unique' to libjcommon * added '_jack_port_register' to jcommon * moved functions to jcommon * compiles, now make it work * disabled unneeded cmdline flags * fixed copyright dates for rohan * changed 'jack.record' to 'ambix-jrecord' * build ambix-jrecord * trying to read matrixfile * AVN numbering starts at zero * provide client-unique function for (const char*) * recording something * provide default filename to ease debugging * basic recording works! * set adaptor matrix * remove debug printout for matrices * better description * matix_permutate * better matrix_print * ambix-matrix check * return NULL if FuMa is invalid * hopefully good implementation of FuMa matrices * removed unneeded code * only calculate weight+order matrix once during life-cycle * trying to reduce stack-size and simplify code * 0order FuMa-matrix * simplified code a bit * 1st attempt to create ambix2fuma mapping * check ambix2fuma matrices * creating AMBIX2FUMA matrices * fixed ambix2fuma conversion * run some tests on matrix fillers * add "name" argument to STARTTEST * more checks for matrix fillers * prototype for '_matrix_ambix2fuma' * MATRIX_SID implementation * starting to implement MATRIX_N3D * N3D/SN3D and SID/ACN * use fabs() rather than abs() for float32_t * print small values with %g * raise eps to 1e-6 * proper labelling for the matrices tests * free memory * prevent memleaks * fully initialize (S)N3D weight vectors * updated TODO * fixed memleaks * added inversion check for norm/order * changed bitmask fields for AMBIX_READ/AMBIX_WRITE * implementation of ambix_seek() * allow seeking * implemented ambix_seek * more TODO * use PACKAGE_VERSION for version display * remove unneccessary includes * added '-v' flag * print some more matrices * --version information ambix-j(record|play) * added synopsis for jtools * consistent help/version information * don't install devtools * note on install target * fixed description of ambix_seek() * AMBIX_SIMPLE -> AMBIX_BASIC * install libraries into rte_ * no more pkglib_, we use rte_ now * enable build of Pd externals * fixed CFLAGS/LIBADD for libjcommon.la * include for printf() * build-system issues have been sorted out * clarified README * ignore lots of by-products * fixed typos * more cross-references * added first draft for [ambix_write~] * allow to set matrix * use post() rather than printf() * added BUGS file * added note about [writesf~] license * changed 'Libgcrypt' to 'libambix' in boilerplate * mention MSP in ambix_read~ * don't fail if no matrix is present * code cleanup * starting to re-implement ambix_read~ with threads * we have sound but it is jerky * remove whitespaces * only seek if needed * playback works * search canvas-paths for file * send matrix when in EXTENDED mode * disable MARK() * fail if we cannot allocate a deinterleavebuffer * explain a bit about the ambix-deinterleave bug * fixed bug when deinterlacing extra-only files * nicer error messages * ambix-deinterleave bug has been fixed * run AM_PROG_CC_C_O for per-target flags * use AM_CPPFLAGS rather than INCLUDES * remove testing target * only copy the matrix if opening was successfull * output ambixinfo * it seems like we should lock the shared data in the tick callback * clear buffer (to avoid playing old samples) * linebreaks to increase readability * hopefully got the EOF check right * don't start to send samples if we still need to send out matrix/ambixinfo * build [ambix_info] * updated help-patches * install Pd-stuff into @rtedir@/ambix * generate ambix-meta.pd * fix file-handle leak * output full filename * use calloc() instead of malloc() * fix memleak * removed pd/old/ directory * use "private_data" instead of "private" member * cast results of malloc() and friends to correct types * functions always have to declare what they will return * declarations of some used functions * in C++ s and s are not the same * include when needed * C++ is more strict regarding implicit casts * trailing whitespaces * ambix_write_matrix() does not return anything * include "jcommon/observe-signal.h" when needed * rindex() returns (const char*) when given a (const char*) * don't include search in generated docs * coalesce all headers into ambix.h * moved main docs into .incl file (and hide it in generated files) * output HTML into apiref/ directory * build doxygen documentation * check for doxygen * only build docs if doxygen is present * libambix.h is now called libambix.incl * libambix.doxy lives in srcdir * add Pd-patches to distribution * adding pkg-config files * version-info is set to 0:0:0 * removed unneeded code * spell it "AMBIsonics eXchange" * ISO-8859 to UTF-8 conversion * only use stdint.h replacements for MSVC * don't fail if a pkg-module cannot be found * dummy VS208 project * made debug project work * explicit type-casts to reduce warnings in MSVC * MSVC doesn't know about "inline", only "__inline" * trying to make reducer_v work with MSVC * use rows_v[] to check whether the setting is valid * fixed "Release" config * more type-fixes to keep MSVC happy * visualstudio property pages * use property pages * project for ambix-info * dummy projects for utils * updated projects * removed unneeded variables * made it compile with MSVC * moved HAVE_SNDFILE_H from ambix.vsprops to libsndfile.vsprops * made it compile without wawrnings on MSVC * MSVC properties for Pd * added project for [ambix_info] * fixed typos in tmpvar names * dummy projects for Pd objects * on w32, define MSW * added pthread propertypage * add more pd-objects to solution * added hacks to ease compilation with MSVC/MinGW * added winhacks to w32-builds * add pthreads to read~/write~ externals * make [ambix_read~] compile on MSVC * our libsndfile has all the chunk-stuff * make buildlog-files project specific * build with winhacks * more msvc fixes for strncpy() and the like... * provide a strndup implementation * use winhacks * strndup() is needed both on msvc and mingw * enhance target-specific flags with AM_FLAGS * fix crasher bug with signed/unsigned * indentation * snprintf() takes a const format-string * getting rid of warnings * dummy use of variables * remove lines that don't do anything * fixed typo '==' is not the same as '=' * use parenthesis to clarify what is going on * decrement frames to write by the actual number of frames written * removed obsolete doxygen settings * no need to check uint32>=0 * memsetting entire chunk to 0 * Couthandles) * make sure ai->outinfo has been allocated * evaluate result of ambix_matrix_copy() * proper detection of SFM_RDRW * check whether ambix_readf() returns negative framecount * (un)locking mutex in ctor * (un)locking mutex in ctor * fixed error printout * protecting x_state with mutex * ouch, need to unlock() the mutex after use... * protex x_state with mutex * no need to call ai_close() if ai_dump_block() failed (again) * simplified error-handling in ambix-dump * text alignment -- IOhannes m zmölnig Sun, 14 Apr 2014 12:21:57 +0200 ambix-0.1.1/CONTRIBUTING.md000066400000000000000000000073271300077024200150460ustar00rootroot00000000000000Contributing 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. ambix-0.1.1/COPYING000066400000000000000000000636421300077024200136520ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library 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. This library 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 library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ambix-0.1.1/INSTALL000066400000000000000000000366001300077024200136420ustar00rootroot00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ambix-0.1.1/Makefile.am000066400000000000000000000002061300077024200146360ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 SUBDIRS=libambix \ replacement \ utils \ doc SUBDIRS+=samples SUBDIRS+=build ambix-0.1.1/NEWS000066400000000000000000000013051300077024200133020ustar00rootroot00000000000000libambix (0.1.1) unstable; urgency=medium * Fixed coverity-scan issues CID: 153342,153344,153345,153346,153347 * Adjusted test-suite tresholds To cater for different precisions on various CPU-types -- IOhannes m zmölnig Sun, 16 Oct 2016 23:21:51 +0200 libambix (0.1) unstable; urgency=medium * Support for float64 * Support for markers in CAF-files * Stable matrix inversion * Many bug fixes,... * travis-ci, coverity & codecov integration -- IOhannes m zmölnig Sun, 5 Oct 2016 22:50:17 +0200 libambix (0.0.1) unstable; urgency=medium * Initial release. -- IOhannes m zmölnig Sun, 14 Apr 2014 12:21:57 +0200 ambix-0.1.1/README.md000066400000000000000000000065131300077024200140700ustar00rootroot00000000000000libambix - 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 | ![Travis-CI](https://api.travis-ci.org/umlaeute/pd-iemnet.svg) | | Static Code Analysis | ![Coverity Scan](https://scan.coverity.com/projects/1736/badge.svg) | | Test Coverage | [![codecov](https://codecov.io/gh/iem-projects/ambix/branch/master/graph/badge.svg)](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 ambix-0.1.1/TODO000066400000000000000000000006561300077024200133030ustar00rootroot00000000000000FILE-FORMAT =========== ??? DEPENDENCIES ============ (optionally) getting rid of libsndfile - create our own minimal CAF-reader/writer - on OSX/iOS, use CoreAudio e.g. http://www.modejong.com/iOS/ExtAudioFileDemo.tar.bz2 helper-library ============== library for matrix operations related to libambix - find a good name for it - analysis of existing matrices - (basic matrix operations and construction is now in libambix) ambix-0.1.1/autogen.sh000077500000000000000000000000331300077024200146010ustar00rootroot00000000000000#!/bin/sh autoreconf -fiv ambix-0.1.1/build/000077500000000000000000000000001300077024200137035ustar00rootroot00000000000000ambix-0.1.1/build/Makefile.am000066400000000000000000000000231300077024200157320ustar00rootroot00000000000000SUBDIRS=w32-vs2008 ambix-0.1.1/build/create_makefile.sh000077500000000000000000000007461300077024200173510ustar00rootroot00000000000000#!/bin/sh usage_print() { echo "usage: $0 " echo " will generate /Makefile.am by adding all files in" echo " to the EXTRA_DIST target" } usage() { usage_print 1>&2 exit 1 } TARGETDIR=$1 if [ -d "${TARGETDIR}" ]; then : else usage fi listfiles() { git ls-files | grep -v Makefile.am | sort -u } doit() { echo -n "EXTRA_DIST=" listfiles | while read line; do echo " \\" echo -n " ${line}" done } cd ${TARGETDIR} doit > Makefile.am ambix-0.1.1/build/osx-xcode3/000077500000000000000000000000001300077024200156775ustar00rootroot00000000000000ambix-0.1.1/build/osx-xcode3/AmbiX-Info.plist000066400000000000000000000011741300077024200206500ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier at.iem.ambisonics.${PRODUCT_NAME:identifier} CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType FMWK CFBundleSignature ???? CFBundleVersion 1.0 ambix-0.1.1/build/osx-xcode3/ambix.xcodeproj/000077500000000000000000000000001300077024200207735ustar00rootroot00000000000000ambix-0.1.1/build/osx-xcode3/ambix.xcodeproj/project.pbxproj000066400000000000000000001127331300077024200240560ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 45; objects = { /* Begin PBXBuildFile section */ 3A0372D8158A28950093733E /* ambix_8h.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372AE158A28950093733E /* ambix_8h.html */; }; 3A0372D9158A28950093733E /* ambix_8h_source.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372AF158A28950093733E /* ambix_8h_source.html */; }; 3A0372DA158A28950093733E /* annotated.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B0158A28950093733E /* annotated.html */; }; 3A0372DB158A28950093733E /* bc_s.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B1158A28950093733E /* bc_s.png */; }; 3A0372DC158A28950093733E /* classes.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B2158A28950093733E /* classes.html */; }; 3A0372DD158A28950093733E /* closed.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B3158A28950093733E /* closed.png */; }; 3A0372DE158A28950093733E /* doxygen.css in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B4158A28950093733E /* doxygen.css */; }; 3A0372DF158A28950093733E /* doxygen.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B5158A28950093733E /* doxygen.png */; }; 3A0372E0158A28950093733E /* exportdefs_8h.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B6158A28950093733E /* exportdefs_8h.html */; }; 3A0372E1158A28950093733E /* exportdefs_8h_source.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B7158A28950093733E /* exportdefs_8h_source.html */; }; 3A0372E2158A28950093733E /* files.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B8158A28950093733E /* files.html */; }; 3A0372E3158A28950093733E /* format.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372B9158A28950093733E /* format.html */; }; 3A0372E4158A28950093733E /* functions.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372BA158A28950093733E /* functions.html */; }; 3A0372E5158A28950093733E /* functions_vars.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372BB158A28950093733E /* functions_vars.html */; }; 3A0372E6158A28950093733E /* globals.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372BC158A28950093733E /* globals.html */; }; 3A0372E7158A28950093733E /* globals_defs.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372BD158A28950093733E /* globals_defs.html */; }; 3A0372E8158A28950093733E /* globals_enum.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372BE158A28950093733E /* globals_enum.html */; }; 3A0372E9158A28950093733E /* globals_eval.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372BF158A28950093733E /* globals_eval.html */; }; 3A0372EA158A28950093733E /* globals_func.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C0158A28950093733E /* globals_func.html */; }; 3A0372EB158A28950093733E /* globals_type.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C1158A28950093733E /* globals_type.html */; }; 3A0372EC158A28950093733E /* group__ambix__matrix__multiply__data.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C2158A28950093733E /* group__ambix__matrix__multiply__data.html */; }; 3A0372ED158A28950093733E /* group__ambix__readf.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C3158A28950093733E /* group__ambix__readf.html */; }; 3A0372EE158A28950093733E /* group__ambix__writef.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C4158A28950093733E /* group__ambix__writef.html */; }; 3A0372EF158A28950093733E /* index.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C5158A28950093733E /* index.html */; }; 3A0372F0158A28950093733E /* jquery.js in Sources */ = {isa = PBXBuildFile; fileRef = 3A0372C6158A28950093733E /* jquery.js */; }; 3A0372F1158A28950093733E /* modules.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C7158A28950093733E /* modules.html */; }; 3A0372F2158A28950093733E /* nav_f.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C8158A28950093733E /* nav_f.png */; }; 3A0372F3158A28950093733E /* nav_h.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372C9158A28950093733E /* nav_h.png */; }; 3A0372F4158A28950093733E /* open.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372CA158A28950093733E /* open.png */; }; 3A0372F5158A28950093733E /* pages.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372CB158A28950093733E /* pages.html */; }; 3A0372F6158A28950093733E /* structambix__info__t-members.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372CC158A28950093733E /* structambix__info__t-members.html */; }; 3A0372F7158A28950093733E /* structambix__info__t.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372CD158A28950093733E /* structambix__info__t.html */; }; 3A0372F8158A28950093733E /* structambix__matrix__t-members.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372CE158A28950093733E /* structambix__matrix__t-members.html */; }; 3A0372F9158A28950093733E /* structambix__matrix__t.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372CF158A28950093733E /* structambix__matrix__t.html */; }; 3A0372FA158A28950093733E /* tab_a.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D0158A28950093733E /* tab_a.png */; }; 3A0372FB158A28950093733E /* tab_b.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D1158A28950093733E /* tab_b.png */; }; 3A0372FC158A28950093733E /* tab_h.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D2158A28950093733E /* tab_h.png */; }; 3A0372FD158A28950093733E /* tab_s.png in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D3158A28950093733E /* tab_s.png */; }; 3A0372FE158A28950093733E /* tabs.css in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D4158A28950093733E /* tabs.css */; }; 3A0372FF158A28950093733E /* unionnumber32__t-members.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D5158A28950093733E /* unionnumber32__t-members.html */; }; 3A037300158A28950093733E /* unionnumber32__t.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D6158A28950093733E /* unionnumber32__t.html */; }; 3A037301158A28950093733E /* usage.html in Resources */ = {isa = PBXBuildFile; fileRef = 3A0372D7158A28950093733E /* usage.html */; }; 3A45EDB11587797F006FE6D6 /* uuid_chunk.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDA71587797F006FE6D6 /* uuid_chunk.c */; }; 3A45EDB21587797F006FE6D6 /* adaptor.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDA81587797F006FE6D6 /* adaptor.c */; }; 3A45EDB31587797F006FE6D6 /* adaptor_fuma.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDA91587797F006FE6D6 /* adaptor_fuma.c */; }; 3A45EDB41587797F006FE6D6 /* libambix.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAA1587797F006FE6D6 /* libambix.c */; }; 3A45EDB51587797F006FE6D6 /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAB1587797F006FE6D6 /* matrix.c */; }; 3A45EDB61587797F006FE6D6 /* private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A45EDAC1587797F006FE6D6 /* private.h */; }; 3A45EDB81587797F006FE6D6 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAE1587797F006FE6D6 /* utils.c */; }; 3A45EDB91587797F006FE6D6 /* adaptor_acn.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAF1587797F006FE6D6 /* adaptor_acn.c */; }; 3A45EDBC158779CF006FE6D6 /* ambix.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A45EDBA158779CF006FE6D6 /* ambix.h */; }; 3A45EDBD158779CF006FE6D6 /* exportdefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A45EDBB158779CF006FE6D6 /* exportdefs.h */; }; 3A45EDE915877EA7006FE6D6 /* sndfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDE815877EA7006FE6D6 /* sndfile.c */; }; 3A45EDEB15877F6C006FE6D6 /* libsndfile.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A45EDEA15877F6C006FE6D6 /* libsndfile.1.dylib */; }; 3A45EE8015879729006FE6D6 /* private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A45EDAC1587797F006FE6D6 /* private.h */; }; 3A45EE8215879732006FE6D6 /* ambix.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A45EDBA158779CF006FE6D6 /* ambix.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A45EE8315879732006FE6D6 /* exportdefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A45EDBB158779CF006FE6D6 /* exportdefs.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3A45EF1315887F85006FE6D6 /* libsndfile.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A45EDEA15877F6C006FE6D6 /* libsndfile.1.dylib */; }; 3A45EF1715887FA2006FE6D6 /* libsndfile.1.dylib in Resources */ = {isa = PBXBuildFile; fileRef = 3A45EDEA15877F6C006FE6D6 /* libsndfile.1.dylib */; }; 3A45EF4F15888A13006FE6D6 /* uuid_chunk.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDA71587797F006FE6D6 /* uuid_chunk.c */; }; 3A45EF5015888A13006FE6D6 /* adaptor.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDA81587797F006FE6D6 /* adaptor.c */; }; 3A45EF5115888A13006FE6D6 /* adaptor_fuma.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDA91587797F006FE6D6 /* adaptor_fuma.c */; }; 3A45EF5215888A13006FE6D6 /* libambix.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAA1587797F006FE6D6 /* libambix.c */; }; 3A45EF5315888A13006FE6D6 /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAB1587797F006FE6D6 /* matrix.c */; }; 3A45EF5415888A13006FE6D6 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAE1587797F006FE6D6 /* utils.c */; }; 3A45EF5515888A13006FE6D6 /* adaptor_acn.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDAF1587797F006FE6D6 /* adaptor_acn.c */; }; 3A45EF5615888A13006FE6D6 /* sndfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 3A45EDE815877EA7006FE6D6 /* sndfile.c */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 3A0372AC158A25930093733E /* Copy Documentation */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; comments = "doxygen documentation"; dstPath = Documentation; dstSubfolderSpec = 7; files = ( ); name = "Copy Documentation"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 3A0372AE158A28950093733E /* ambix_8h.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ambix_8h.html; sourceTree = ""; }; 3A0372AF158A28950093733E /* ambix_8h_source.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ambix_8h_source.html; sourceTree = ""; }; 3A0372B0158A28950093733E /* annotated.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = annotated.html; sourceTree = ""; }; 3A0372B1158A28950093733E /* bc_s.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bc_s.png; sourceTree = ""; }; 3A0372B2158A28950093733E /* classes.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = classes.html; sourceTree = ""; }; 3A0372B3158A28950093733E /* closed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = closed.png; sourceTree = ""; }; 3A0372B4158A28950093733E /* doxygen.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = doxygen.css; sourceTree = ""; }; 3A0372B5158A28950093733E /* doxygen.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = doxygen.png; sourceTree = ""; }; 3A0372B6158A28950093733E /* exportdefs_8h.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = exportdefs_8h.html; sourceTree = ""; }; 3A0372B7158A28950093733E /* exportdefs_8h_source.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = exportdefs_8h_source.html; sourceTree = ""; }; 3A0372B8158A28950093733E /* files.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = files.html; sourceTree = ""; }; 3A0372B9158A28950093733E /* format.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = format.html; sourceTree = ""; }; 3A0372BA158A28950093733E /* functions.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = functions.html; sourceTree = ""; }; 3A0372BB158A28950093733E /* functions_vars.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = functions_vars.html; sourceTree = ""; }; 3A0372BC158A28950093733E /* globals.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = globals.html; sourceTree = ""; }; 3A0372BD158A28950093733E /* globals_defs.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = globals_defs.html; sourceTree = ""; }; 3A0372BE158A28950093733E /* globals_enum.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = globals_enum.html; sourceTree = ""; }; 3A0372BF158A28950093733E /* globals_eval.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = globals_eval.html; sourceTree = ""; }; 3A0372C0158A28950093733E /* globals_func.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = globals_func.html; sourceTree = ""; }; 3A0372C1158A28950093733E /* globals_type.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = globals_type.html; sourceTree = ""; }; 3A0372C2158A28950093733E /* group__ambix__matrix__multiply__data.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = group__ambix__matrix__multiply__data.html; sourceTree = ""; }; 3A0372C3158A28950093733E /* group__ambix__readf.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = group__ambix__readf.html; sourceTree = ""; }; 3A0372C4158A28950093733E /* group__ambix__writef.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = group__ambix__writef.html; sourceTree = ""; }; 3A0372C5158A28950093733E /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = ""; }; 3A0372C6158A28950093733E /* jquery.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jquery.js; sourceTree = ""; }; 3A0372C7158A28950093733E /* modules.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = modules.html; sourceTree = ""; }; 3A0372C8158A28950093733E /* nav_f.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nav_f.png; sourceTree = ""; }; 3A0372C9158A28950093733E /* nav_h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nav_h.png; sourceTree = ""; }; 3A0372CA158A28950093733E /* open.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = open.png; sourceTree = ""; }; 3A0372CB158A28950093733E /* pages.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = pages.html; sourceTree = ""; }; 3A0372CC158A28950093733E /* structambix__info__t-members.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "structambix__info__t-members.html"; sourceTree = ""; }; 3A0372CD158A28950093733E /* structambix__info__t.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = structambix__info__t.html; sourceTree = ""; }; 3A0372CE158A28950093733E /* structambix__matrix__t-members.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "structambix__matrix__t-members.html"; sourceTree = ""; }; 3A0372CF158A28950093733E /* structambix__matrix__t.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = structambix__matrix__t.html; sourceTree = ""; }; 3A0372D0158A28950093733E /* tab_a.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_a.png; sourceTree = ""; }; 3A0372D1158A28950093733E /* tab_b.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_b.png; sourceTree = ""; }; 3A0372D2158A28950093733E /* tab_h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_h.png; sourceTree = ""; }; 3A0372D3158A28950093733E /* tab_s.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_s.png; sourceTree = ""; }; 3A0372D4158A28950093733E /* tabs.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = tabs.css; sourceTree = ""; }; 3A0372D5158A28950093733E /* unionnumber32__t-members.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "unionnumber32__t-members.html"; sourceTree = ""; }; 3A0372D6158A28950093733E /* unionnumber32__t.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = unionnumber32__t.html; sourceTree = ""; }; 3A0372D7158A28950093733E /* usage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = usage.html; sourceTree = ""; }; 3A45ED9F15877872006FE6D6 /* libambix.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libambix.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 3A45EDA71587797F006FE6D6 /* uuid_chunk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = uuid_chunk.c; path = ../../libambix/src/uuid_chunk.c; sourceTree = SOURCE_ROOT; }; 3A45EDA81587797F006FE6D6 /* adaptor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = adaptor.c; path = ../../libambix/src/adaptor.c; sourceTree = SOURCE_ROOT; }; 3A45EDA91587797F006FE6D6 /* adaptor_fuma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = adaptor_fuma.c; path = ../../libambix/src/adaptor_fuma.c; sourceTree = SOURCE_ROOT; }; 3A45EDAA1587797F006FE6D6 /* libambix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = libambix.c; path = ../../libambix/src/libambix.c; sourceTree = SOURCE_ROOT; }; 3A45EDAB1587797F006FE6D6 /* matrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = matrix.c; path = ../../libambix/src/matrix.c; sourceTree = SOURCE_ROOT; }; 3A45EDAC1587797F006FE6D6 /* private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = private.h; path = ../../libambix/src/private.h; sourceTree = SOURCE_ROOT; }; 3A45EDAE1587797F006FE6D6 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = utils.c; path = ../../libambix/src/utils.c; sourceTree = SOURCE_ROOT; }; 3A45EDAF1587797F006FE6D6 /* adaptor_acn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = adaptor_acn.c; path = ../../libambix/src/adaptor_acn.c; sourceTree = SOURCE_ROOT; }; 3A45EDBA158779CF006FE6D6 /* ambix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ambix.h; path = ../../libambix/ambix/ambix.h; sourceTree = SOURCE_ROOT; }; 3A45EDBB158779CF006FE6D6 /* exportdefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = exportdefs.h; path = ../../libambix/ambix/exportdefs.h; sourceTree = SOURCE_ROOT; }; 3A45EDE815877EA7006FE6D6 /* sndfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = sndfile.c; path = ../../libambix/src/sndfile.c; sourceTree = SOURCE_ROOT; }; 3A45EDEA15877F6C006FE6D6 /* libsndfile.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsndfile.1.dylib; path = usr/local/lib/libsndfile.1.dylib; sourceTree = SDKROOT; }; 3A45EE6815879685006FE6D6 /* ambix.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ambix.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3A45EE6915879685006FE6D6 /* AmbiX-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AmbiX-Info.plist"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 3A45ED9D15877872006FE6D6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 3A45EDEB15877F6C006FE6D6 /* libsndfile.1.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 3A45EE6615879685006FE6D6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 3A45EF1315887F85006FE6D6 /* libsndfile.1.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 08FB7794FE84155DC02AAC07 /* testlib */ = { isa = PBXGroup; children = ( 3A0372AD158A28950093733E /* apiref */, 08FB7795FE84155DC02AAC07 /* Source */, 1AB674ADFE9D54B511CA2CBB /* Products */, 3A45EDEA15877F6C006FE6D6 /* libsndfile.1.dylib */, 3A45EE6915879685006FE6D6 /* AmbiX-Info.plist */, ); name = testlib; sourceTree = ""; }; 08FB7795FE84155DC02AAC07 /* Source */ = { isa = PBXGroup; children = ( 3A45EEAC15879C55006FE6D6 /* ambix */, 3A45EDE815877EA7006FE6D6 /* sndfile.c */, 3A45EDA71587797F006FE6D6 /* uuid_chunk.c */, 3A45EDA81587797F006FE6D6 /* adaptor.c */, 3A45EDA91587797F006FE6D6 /* adaptor_fuma.c */, 3A45EDAA1587797F006FE6D6 /* libambix.c */, 3A45EDAB1587797F006FE6D6 /* matrix.c */, 3A45EDAC1587797F006FE6D6 /* private.h */, 3A45EDAE1587797F006FE6D6 /* utils.c */, 3A45EDAF1587797F006FE6D6 /* adaptor_acn.c */, ); name = Source; sourceTree = ""; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( 3A45ED9F15877872006FE6D6 /* libambix.dylib */, 3A45EE6815879685006FE6D6 /* ambix.framework */, ); name = Products; sourceTree = ""; }; 3A0372AD158A28950093733E /* apiref */ = { isa = PBXGroup; children = ( 3A0372AE158A28950093733E /* ambix_8h.html */, 3A0372AF158A28950093733E /* ambix_8h_source.html */, 3A0372B0158A28950093733E /* annotated.html */, 3A0372B1158A28950093733E /* bc_s.png */, 3A0372B2158A28950093733E /* classes.html */, 3A0372B3158A28950093733E /* closed.png */, 3A0372B4158A28950093733E /* doxygen.css */, 3A0372B5158A28950093733E /* doxygen.png */, 3A0372B6158A28950093733E /* exportdefs_8h.html */, 3A0372B7158A28950093733E /* exportdefs_8h_source.html */, 3A0372B8158A28950093733E /* files.html */, 3A0372B9158A28950093733E /* format.html */, 3A0372BA158A28950093733E /* functions.html */, 3A0372BB158A28950093733E /* functions_vars.html */, 3A0372BC158A28950093733E /* globals.html */, 3A0372BD158A28950093733E /* globals_defs.html */, 3A0372BE158A28950093733E /* globals_enum.html */, 3A0372BF158A28950093733E /* globals_eval.html */, 3A0372C0158A28950093733E /* globals_func.html */, 3A0372C1158A28950093733E /* globals_type.html */, 3A0372C2158A28950093733E /* group__ambix__matrix__multiply__data.html */, 3A0372C3158A28950093733E /* group__ambix__readf.html */, 3A0372C4158A28950093733E /* group__ambix__writef.html */, 3A0372C5158A28950093733E /* index.html */, 3A0372C6158A28950093733E /* jquery.js */, 3A0372C7158A28950093733E /* modules.html */, 3A0372C8158A28950093733E /* nav_f.png */, 3A0372C9158A28950093733E /* nav_h.png */, 3A0372CA158A28950093733E /* open.png */, 3A0372CB158A28950093733E /* pages.html */, 3A0372CC158A28950093733E /* structambix__info__t-members.html */, 3A0372CD158A28950093733E /* structambix__info__t.html */, 3A0372CE158A28950093733E /* structambix__matrix__t-members.html */, 3A0372CF158A28950093733E /* structambix__matrix__t.html */, 3A0372D0158A28950093733E /* tab_a.png */, 3A0372D1158A28950093733E /* tab_b.png */, 3A0372D2158A28950093733E /* tab_h.png */, 3A0372D3158A28950093733E /* tab_s.png */, 3A0372D4158A28950093733E /* tabs.css */, 3A0372D5158A28950093733E /* unionnumber32__t-members.html */, 3A0372D6158A28950093733E /* unionnumber32__t.html */, 3A0372D7158A28950093733E /* usage.html */, ); name = apiref; path = ../../doc/apiref; sourceTree = SOURCE_ROOT; }; 3A45EEAC15879C55006FE6D6 /* ambix */ = { isa = PBXGroup; children = ( 3A45EDBA158779CF006FE6D6 /* ambix.h */, 3A45EDBB158779CF006FE6D6 /* exportdefs.h */, ); name = ambix; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 3A45ED9B15877872006FE6D6 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 3A45EDB61587797F006FE6D6 /* private.h in Headers */, 3A45EDBC158779CF006FE6D6 /* ambix.h in Headers */, 3A45EDBD158779CF006FE6D6 /* exportdefs.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 3A45EE6315879685006FE6D6 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 3A45EE8315879732006FE6D6 /* exportdefs.h in Headers */, 3A45EE8215879732006FE6D6 /* ambix.h in Headers */, 3A45EE8015879729006FE6D6 /* private.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 3A45ED9E15877872006FE6D6 /* libambix */ = { isa = PBXNativeTarget; buildConfigurationList = 3A45EDA215877893006FE6D6 /* Build configuration list for PBXNativeTarget "libambix" */; buildPhases = ( 3A45ED9B15877872006FE6D6 /* Headers */, 3A45ED9C15877872006FE6D6 /* Sources */, 3A45ED9D15877872006FE6D6 /* Frameworks */, ); buildRules = ( ); comments = "prefix set to \"\" to avoid \"liblibambix\""; dependencies = ( ); name = libambix; productName = libambix; productReference = 3A45ED9F15877872006FE6D6 /* libambix.dylib */; productType = "com.apple.product-type.library.dynamic"; }; 3A45EE6715879685006FE6D6 /* ambix */ = { isa = PBXNativeTarget; buildConfigurationList = 3A45EE6C15879688006FE6D6 /* Build configuration list for PBXNativeTarget "ambix" */; buildPhases = ( 3A45EE6315879685006FE6D6 /* Headers */, 3A45EE6415879685006FE6D6 /* Resources */, 3A45EE6515879685006FE6D6 /* Sources */, 3A45EE6615879685006FE6D6 /* Frameworks */, 3A0372AC158A25930093733E /* Copy Documentation */, ); buildRules = ( ); comments = "embedding libsndfile:\n\n- make sure libsndfile.1.dylib ends up in /Resources/\n- change the rpath of \"ambix\" to @loader_path/Resources/libsndfile.1.dylib\ne.g., with \n $ install_name_tool -change /usr/local/lib/libsndfile.1.dylib @loader_path/Resources/libsndfile.1.dylib ambix\n\n\nalternatively, copy libsndfile via a new \"copy files\" target to destination \"executables\", so it will end up in /Version/Current/"; dependencies = ( ); name = ambix; productName = AmbiX; productReference = 3A45EE6815879685006FE6D6 /* ambix.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "ambix" */; compatibilityVersion = "Xcode 3.1"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* testlib */; projectDirPath = ""; projectRoot = ""; targets = ( 3A45ED9E15877872006FE6D6 /* libambix */, 3A45EE6715879685006FE6D6 /* ambix */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 3A45EE6415879685006FE6D6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 3A45EF1715887FA2006FE6D6 /* libsndfile.1.dylib in Resources */, 3A0372D8158A28950093733E /* ambix_8h.html in Resources */, 3A0372D9158A28950093733E /* ambix_8h_source.html in Resources */, 3A0372DA158A28950093733E /* annotated.html in Resources */, 3A0372DB158A28950093733E /* bc_s.png in Resources */, 3A0372DC158A28950093733E /* classes.html in Resources */, 3A0372DD158A28950093733E /* closed.png in Resources */, 3A0372DE158A28950093733E /* doxygen.css in Resources */, 3A0372DF158A28950093733E /* doxygen.png in Resources */, 3A0372E0158A28950093733E /* exportdefs_8h.html in Resources */, 3A0372E1158A28950093733E /* exportdefs_8h_source.html in Resources */, 3A0372E2158A28950093733E /* files.html in Resources */, 3A0372E3158A28950093733E /* format.html in Resources */, 3A0372E4158A28950093733E /* functions.html in Resources */, 3A0372E5158A28950093733E /* functions_vars.html in Resources */, 3A0372E6158A28950093733E /* globals.html in Resources */, 3A0372E7158A28950093733E /* globals_defs.html in Resources */, 3A0372E8158A28950093733E /* globals_enum.html in Resources */, 3A0372E9158A28950093733E /* globals_eval.html in Resources */, 3A0372EA158A28950093733E /* globals_func.html in Resources */, 3A0372EB158A28950093733E /* globals_type.html in Resources */, 3A0372EC158A28950093733E /* group__ambix__matrix__multiply__data.html in Resources */, 3A0372ED158A28950093733E /* group__ambix__readf.html in Resources */, 3A0372EE158A28950093733E /* group__ambix__writef.html in Resources */, 3A0372EF158A28950093733E /* index.html in Resources */, 3A0372F1158A28950093733E /* modules.html in Resources */, 3A0372F2158A28950093733E /* nav_f.png in Resources */, 3A0372F3158A28950093733E /* nav_h.png in Resources */, 3A0372F4158A28950093733E /* open.png in Resources */, 3A0372F5158A28950093733E /* pages.html in Resources */, 3A0372F6158A28950093733E /* structambix__info__t-members.html in Resources */, 3A0372F7158A28950093733E /* structambix__info__t.html in Resources */, 3A0372F8158A28950093733E /* structambix__matrix__t-members.html in Resources */, 3A0372F9158A28950093733E /* structambix__matrix__t.html in Resources */, 3A0372FA158A28950093733E /* tab_a.png in Resources */, 3A0372FB158A28950093733E /* tab_b.png in Resources */, 3A0372FC158A28950093733E /* tab_h.png in Resources */, 3A0372FD158A28950093733E /* tab_s.png in Resources */, 3A0372FE158A28950093733E /* tabs.css in Resources */, 3A0372FF158A28950093733E /* unionnumber32__t-members.html in Resources */, 3A037300158A28950093733E /* unionnumber32__t.html in Resources */, 3A037301158A28950093733E /* usage.html in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 3A45ED9C15877872006FE6D6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 3A45EDB11587797F006FE6D6 /* uuid_chunk.c in Sources */, 3A45EDB21587797F006FE6D6 /* adaptor.c in Sources */, 3A45EDB31587797F006FE6D6 /* adaptor_fuma.c in Sources */, 3A45EDB41587797F006FE6D6 /* libambix.c in Sources */, 3A45EDB51587797F006FE6D6 /* matrix.c in Sources */, 3A45EDB81587797F006FE6D6 /* utils.c in Sources */, 3A45EDB91587797F006FE6D6 /* adaptor_acn.c in Sources */, 3A45EDE915877EA7006FE6D6 /* sndfile.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 3A45EE6515879685006FE6D6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 3A45EF4F15888A13006FE6D6 /* uuid_chunk.c in Sources */, 3A45EF5015888A13006FE6D6 /* adaptor.c in Sources */, 3A45EF5115888A13006FE6D6 /* adaptor_fuma.c in Sources */, 3A45EF5215888A13006FE6D6 /* libambix.c in Sources */, 3A45EF5315888A13006FE6D6 /* matrix.c in Sources */, 3A45EF5415888A13006FE6D6 /* utils.c in Sources */, 3A45EF5515888A13006FE6D6 /* adaptor_acn.c in Sources */, 3A45EF5615888A13006FE6D6 /* sndfile.c in Sources */, 3A0372F0158A28950093733E /* jquery.js in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 1DEB914F08733D8E0010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_OPTIMIZATION_LEVEL = 0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; PREBINDING = NO; SDKROOT = macosx10.5; }; name = Debug; }; 1DEB915008733D8E0010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; PREBINDING = NO; SDKROOT = macosx10.5; }; name = Release; }; 3A45EDA015877875006FE6D6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = NO; EXECUTABLE_PREFIX = ""; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( AMBIX_INTERNAL, HAVE_STDLIB_H, HAVE_STRING_H, HAVE_SNDFILE_H, HAVE_SF_CHUNK_INFO, HAVE_SF_SET_CHUNK, HAVE_SF_GET_CHUNK_ITERATOR, ); HEADER_SEARCH_PATHS = ( ../../libambix, /usr/local/include, ); INSTALL_PATH = "@loader_path"; ONLY_ACTIVE_ARCH = NO; PREBINDING = NO; PRODUCT_NAME = libambix; }; name = Debug; }; 3A45EDA115877875006FE6D6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; EXECUTABLE_PREFIX = ""; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; GCC_PREPROCESSOR_DEFINITIONS = ( AMBIX_INTERNAL, HAVE_STDLIB_H, HAVE_STRING_H, HAVE_SNDFILE_H, HAVE_SF_CHUNK_INFO, HAVE_SF_SET_CHUNK, HAVE_SF_GET_CHUNK_ITERATOR, ); HEADER_SEARCH_PATHS = ( ../../libambix, /usr/local/include, ); INSTALL_PATH = "@loader_path"; ONLY_ACTIVE_ARCH = NO; PREBINDING = NO; PRODUCT_NAME = libambix; ZERO_LINK = NO; }; name = Release; }; 3A45EE6A15879688006FE6D6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 0.0.1; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( AMBIX_INTERNAL, HAVE_STDLIB_H, HAVE_STRING_H, HAVE_SNDFILE_H, HAVE_SF_CHUNK_INFO, HAVE_SF_GET_CHUNK_ITERATOR, HAVE_SF_SET_CHUNK, ); GCC_SYMBOLS_PRIVATE_EXTERN = YES; HEADER_SEARCH_PATHS = ( /usr/local/include, ../../libambix, ); INFOPLIST_FILE = "AmbiX-Info.plist"; INSTALL_PATH = "@rpath"; OTHER_LDFLAGS = ""; PREBINDING = NO; PRODUCT_NAME = ambix; }; name = Debug; }; 3A45EE6B15879688006FE6D6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 0.0.1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; GCC_PREPROCESSOR_DEFINITIONS = ( AMBIX_INTERNAL, HAVE_STDLIB_H, HAVE_STRING_H, HAVE_SNDFILE_H, HAVE_SF_CHUNK_INFO, HAVE_SF_GET_CHUNK_ITERATOR, HAVE_SF_SET_CHUNK, ); GCC_SYMBOLS_PRIVATE_EXTERN = YES; HEADER_SEARCH_PATHS = ( /usr/local/include, ../../libambix, ); INFOPLIST_FILE = "AmbiX-Info.plist"; INSTALL_PATH = "@rpath"; OTHER_LDFLAGS = ""; PREBINDING = NO; PRODUCT_NAME = ambix; ZERO_LINK = NO; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "ambix" */ = { isa = XCConfigurationList; buildConfigurations = ( 1DEB914F08733D8E0010E9CD /* Debug */, 1DEB915008733D8E0010E9CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 3A45EDA215877893006FE6D6 /* Build configuration list for PBXNativeTarget "libambix" */ = { isa = XCConfigurationList; buildConfigurations = ( 3A45EDA015877875006FE6D6 /* Debug */, 3A45EDA115877875006FE6D6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 3A45EE6C15879688006FE6D6 /* Build configuration list for PBXNativeTarget "ambix" */ = { isa = XCConfigurationList; buildConfigurations = ( 3A45EE6A15879688006FE6D6 /* Debug */, 3A45EE6B15879688006FE6D6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; } ambix-0.1.1/build/utils/000077500000000000000000000000001300077024200150435ustar00rootroot00000000000000ambix-0.1.1/build/utils/git-copyright.py000077500000000000000000000102371300077024200202140ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # git-copyright: extract copyright-information from git # # # Copyright © 2016, IOhannes m zmölnig, forum::für::umläute, institute of electronic music and acoustics (iem) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # . # This program 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 # Affero General Public License for more details. # . # You should have received a copy of the GNU Affero General Public # License along with this program. If not, see # . from __future__ import print_function import git import sys verbose = 0 def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) author_aliases={ "zmoelnig": "IOhannes m zmölnig", "IOhannes m zmoelnig": "zmoelnig", "iem user": "Institute of Electronic Music and Acoustics", "CUBEmixer": "Institute of Electronic Music and Acoustics", } def commits2authordates(path): g = git.cmd.Git(path) #g.log('--name-only', '--pretty="%% %ad %an"') ## collect all commits #g.log('--pretty="%h %ad %an"', '--date=short').split("\n") commits=g.log('--pretty=%h').split("\n") filedict=dict() copydict=dict() for c in commits: if verbose: eprint("processing %s" % (c)) author=g.show('--pretty="%an"', '-s', c).strip('"') date=g.show('--pretty="%ad"', '-s', '--date=short', c).strip('"') files=g.show('--pretty=', '--name-only', c).split("\n") while author in author_aliases: author=author_aliases[author] for f in files: f=f.strip('"') if not f in filedict: filedict[f]=dict() if not author in filedict[f]: filedict[f][author]=[] filedict[f][author]+=[date] if not author in copydict: copydict[author]=[] copydict[author]+=[date] return (filedict, copydict) def copyright4files(filedict): for f in sorted(filedict): thisfile=filedict[f] authors=list(thisfile.keys()) authors.sort() copyright=[] for a in authors: dates=thisfile[a] dates.sort() year0=dates[0].split("-")[0] year1=dates[-1].split("-")[0] if year0 == year1: if year0 == "2012":break copyright+=["%s, %s" % (year0, a)] else: copyright+=["%s-%s, %s" % (year0,year1, a)] if copyright: print("%s" % (f)) copyright.sort() for c in copyright: print(" © %s" % (c)) def copyright4repo(copydict): if copydict: authors=list(copydict.keys()) authors.sort() copyright=[] for a in authors: dates=copydict[a] dates.sort() year0=dates[0].split("-")[0] year1=dates[-1].split("-")[0] if year0 == year1: # if year0 == "2012":break copyright+=["%s, %s" % (year0, a)] else: copyright+=["%s-%s, %s" % (year0,year1, a)] if copyright: copyright.sort() for c in copyright: print(" © %s" % (c)) def main(): import argparse global verbose parser = argparse.ArgumentParser(description='Extract copyright information from archive.') parser.add_argument('--verbose', '-v', action='store_true', help='raise verbosity') parser.add_argument('--per-file', action='store_true', help='show per-file copyright information (rather than per-project)') args = parser.parse_args() verbose = args.verbose c4f, c4r = commits2authordates(".") if args.per_file: copyright4files(c4f) else: copyright4repo(c4r) if __name__ == '__main__': main() ambix-0.1.1/build/w32-vs2008/000077500000000000000000000000001300077024200152565ustar00rootroot00000000000000ambix-0.1.1/build/w32-vs2008/Makefile.am000066400000000000000000000005411300077024200173120ustar00rootroot00000000000000EXTRA_DIST= \ ambix-deinterleave.vcproj \ ambix-dump.vcproj \ ambix_info.vcproj \ ambix-info.vcproj \ ambix-interleave.vcproj \ ambix-matrix.vcproj \ ambix_read~.vcproj \ ambix_readX~.vcproj \ ambix.sln \ ambix-test.vcproj \ ambix.vsprops \ ambix_write~.vcproj \ libambix.vcproj \ libambix.vsprops \ libsndfile.vsprops \ puredata.vspropsambix-0.1.1/build/w32-vs2008/ambix-deinterleave.vcproj000066400000000000000000000071421300077024200222540ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix-dump.vcproj000066400000000000000000000070501300077024200205500ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix-info.vcproj000066400000000000000000000070041300077024200205350ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix-interleave.vcproj000066400000000000000000000071361300077024200217460ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix-matrix.vcproj000066400000000000000000000070541300077024200211130ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix-test.vcproj000066400000000000000000000070501300077024200205620ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix.sln000066400000000000000000000155471300077024200171100ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libambix", "libambix.vcproj", "{26716438-5563-43B5-8D7E-D8B8ADBC4630}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix-info", "ambix-info.vcproj", "{D61D2BAE-0ED9-48D8-9C5B-EB8FEA6D7457}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix-interleave", "ambix-interleave.vcproj", "{BD1F767A-12B0-4EF6-9867-575B3B615E31}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix-test", "ambix-test.vcproj", "{443E3B23-86A2-48AB-A6E2-CC116B24EB57}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix-matrix", "ambix-matrix.vcproj", "{08361B4D-AF20-4CBE-8E88-D2E6037337DE}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix-dump", "ambix-dump.vcproj", "{06652754-6A83-4512-A720-70F79563443D}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix-deinterleave", "ambix-deinterleave.vcproj", "{253E153B-7F27-4A2E-9955-F1AD48C68E1C}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix_info", "ambix_info.vcproj", "{E6210FAD-6764-48A8-A357-DAD63B7A44E0}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix_read~", "ambix_read~.vcproj", "{0932801D-7075-486D-BB4F-FEBC2AA15FFC}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix_readX~", "ambix_readX~.vcproj", "{95B89D46-7697-48C4-B45C-8B01BE1E64ED}" ProjectSection(ProjectDependencies) = postProject {0932801D-7075-486D-BB4F-FEBC2AA15FFC} = {0932801D-7075-486D-BB4F-FEBC2AA15FFC} {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ambix_write~", "ambix_write~.vcproj", "{D4C88792-CB12-44A8-B9A5-8795C154BC6A}" ProjectSection(ProjectDependencies) = postProject {26716438-5563-43B5-8D7E-D8B8ADBC4630} = {26716438-5563-43B5-8D7E-D8B8ADBC4630} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {26716438-5563-43B5-8D7E-D8B8ADBC4630}.Debug|Win32.ActiveCfg = Debug|Win32 {26716438-5563-43B5-8D7E-D8B8ADBC4630}.Debug|Win32.Build.0 = Debug|Win32 {26716438-5563-43B5-8D7E-D8B8ADBC4630}.Release|Win32.ActiveCfg = Release|Win32 {26716438-5563-43B5-8D7E-D8B8ADBC4630}.Release|Win32.Build.0 = Release|Win32 {D61D2BAE-0ED9-48D8-9C5B-EB8FEA6D7457}.Debug|Win32.ActiveCfg = Debug|Win32 {D61D2BAE-0ED9-48D8-9C5B-EB8FEA6D7457}.Debug|Win32.Build.0 = Debug|Win32 {D61D2BAE-0ED9-48D8-9C5B-EB8FEA6D7457}.Release|Win32.ActiveCfg = Release|Win32 {D61D2BAE-0ED9-48D8-9C5B-EB8FEA6D7457}.Release|Win32.Build.0 = Release|Win32 {BD1F767A-12B0-4EF6-9867-575B3B615E31}.Debug|Win32.ActiveCfg = Debug|Win32 {BD1F767A-12B0-4EF6-9867-575B3B615E31}.Debug|Win32.Build.0 = Debug|Win32 {BD1F767A-12B0-4EF6-9867-575B3B615E31}.Release|Win32.ActiveCfg = Release|Win32 {BD1F767A-12B0-4EF6-9867-575B3B615E31}.Release|Win32.Build.0 = Release|Win32 {443E3B23-86A2-48AB-A6E2-CC116B24EB57}.Debug|Win32.ActiveCfg = Debug|Win32 {443E3B23-86A2-48AB-A6E2-CC116B24EB57}.Debug|Win32.Build.0 = Debug|Win32 {443E3B23-86A2-48AB-A6E2-CC116B24EB57}.Release|Win32.ActiveCfg = Release|Win32 {443E3B23-86A2-48AB-A6E2-CC116B24EB57}.Release|Win32.Build.0 = Release|Win32 {08361B4D-AF20-4CBE-8E88-D2E6037337DE}.Debug|Win32.ActiveCfg = Debug|Win32 {08361B4D-AF20-4CBE-8E88-D2E6037337DE}.Debug|Win32.Build.0 = Debug|Win32 {08361B4D-AF20-4CBE-8E88-D2E6037337DE}.Release|Win32.ActiveCfg = Release|Win32 {08361B4D-AF20-4CBE-8E88-D2E6037337DE}.Release|Win32.Build.0 = Release|Win32 {06652754-6A83-4512-A720-70F79563443D}.Debug|Win32.ActiveCfg = Debug|Win32 {06652754-6A83-4512-A720-70F79563443D}.Debug|Win32.Build.0 = Debug|Win32 {06652754-6A83-4512-A720-70F79563443D}.Release|Win32.ActiveCfg = Release|Win32 {06652754-6A83-4512-A720-70F79563443D}.Release|Win32.Build.0 = Release|Win32 {253E153B-7F27-4A2E-9955-F1AD48C68E1C}.Debug|Win32.ActiveCfg = Debug|Win32 {253E153B-7F27-4A2E-9955-F1AD48C68E1C}.Debug|Win32.Build.0 = Debug|Win32 {253E153B-7F27-4A2E-9955-F1AD48C68E1C}.Release|Win32.ActiveCfg = Release|Win32 {253E153B-7F27-4A2E-9955-F1AD48C68E1C}.Release|Win32.Build.0 = Release|Win32 {E6210FAD-6764-48A8-A357-DAD63B7A44E0}.Debug|Win32.ActiveCfg = Debug|Win32 {E6210FAD-6764-48A8-A357-DAD63B7A44E0}.Debug|Win32.Build.0 = Debug|Win32 {E6210FAD-6764-48A8-A357-DAD63B7A44E0}.Release|Win32.ActiveCfg = Release|Win32 {E6210FAD-6764-48A8-A357-DAD63B7A44E0}.Release|Win32.Build.0 = Release|Win32 {0932801D-7075-486D-BB4F-FEBC2AA15FFC}.Debug|Win32.ActiveCfg = Debug|Win32 {0932801D-7075-486D-BB4F-FEBC2AA15FFC}.Debug|Win32.Build.0 = Debug|Win32 {0932801D-7075-486D-BB4F-FEBC2AA15FFC}.Release|Win32.ActiveCfg = Release|Win32 {0932801D-7075-486D-BB4F-FEBC2AA15FFC}.Release|Win32.Build.0 = Release|Win32 {95B89D46-7697-48C4-B45C-8B01BE1E64ED}.Debug|Win32.ActiveCfg = Debug|Win32 {95B89D46-7697-48C4-B45C-8B01BE1E64ED}.Debug|Win32.Build.0 = Debug|Win32 {95B89D46-7697-48C4-B45C-8B01BE1E64ED}.Release|Win32.ActiveCfg = Release|Win32 {95B89D46-7697-48C4-B45C-8B01BE1E64ED}.Release|Win32.Build.0 = Release|Win32 {D4C88792-CB12-44A8-B9A5-8795C154BC6A}.Debug|Win32.ActiveCfg = Debug|Win32 {D4C88792-CB12-44A8-B9A5-8795C154BC6A}.Debug|Win32.Build.0 = Debug|Win32 {D4C88792-CB12-44A8-B9A5-8795C154BC6A}.Release|Win32.ActiveCfg = Release|Win32 {D4C88792-CB12-44A8-B9A5-8795C154BC6A}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ambix-0.1.1/build/w32-vs2008/ambix.vsprops000066400000000000000000000013161300077024200200150ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix_info.vcproj000066400000000000000000000071311300077024200206200ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix_readX~.vcproj000066400000000000000000000074621300077024200211350ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix_read~.vcproj000066400000000000000000000074601300077024200210030ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/ambix_write~.vcproj000066400000000000000000000074631300077024200212250ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/libambix.vcproj000066400000000000000000000114221300077024200202720ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/libambix.vsprops000066400000000000000000000004761300077024200205120ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/libsndfile.vsprops000066400000000000000000000007631300077024200210350ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/pthread.vsprops000066400000000000000000000007631300077024200203510ustar00rootroot00000000000000 ambix-0.1.1/build/w32-vs2008/puredata.vsprops000066400000000000000000000007241300077024200205240ustar00rootroot00000000000000 ambix-0.1.1/configure.ac000066400000000000000000000127761300077024200151070ustar00rootroot00000000000000AC_INIT([ambix],[0.1.1],[zmoelnig@iem.at], [libambix],[http://ambisonics.iem.at/xchange/format]) AM_INIT_AUTOMAKE([foreign]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AM_PROG_LIBTOOL 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 libambix/tests/data/Makefile]) AC_CONFIG_FILES([libambix/libambix.pc]) AC_CONFIG_FILES([utils/Makefile utils/jcommon/Makefile]) AC_CONFIG_FILES([doc/Makefile]) AC_CONFIG_FILES([replacement/Makefile]) AC_CONFIG_FILES([samples/Makefile]) AC_CONFIG_FILES([samples/pd/Makefile samples/pd/ambix-meta.pd]) AC_CONFIG_FILES([build/Makefile build/w32-vs2008/Makefile]) IEM_OPERATING_SYSTEM AC_PROG_INSTALL AC_LANG_C AC_PROG_CC AC_PROG_MAKE_SET AM_PROG_CC_C_O m4_ifdef([AC_PROG_OBJC], [AC_PROG_OBJC]) #------------------------------------------------------------------------------------ # Rules for library version information: # # 1. Start with version information of `0:0:0' for each libtool library. # 2. Update the version information only immediately before a public release of # your software. More frequent updates are unnecessary, and only guarantee # that the current interface number gets larger faster. # 3. If the library source code has changed at all since the last update, then # increment revision (`c:r:a' becomes `c:r+1:a'). # 4. If any interfaces have been added, removed, or changed since the last update, # increment current, and set revision to 0. # 5. If any interfaces have been added since the last public release, then increment # age. # 6. If any interfaces have been removed since the last public release, then set age # to 0. CLEAN_VERSION=`echo $PACKAGE_VERSION | $SED "s/p.*//"` VERSION_MINOR=`echo $CLEAN_VERSION | $SED "s/.*\.//"` SHARED_VERSION_INFO="0:$VERSION_MINOR:0" AC_SUBST(SHARED_VERSION_INFO) have_pd="no" IEM_CHECK_RTE AM_CONDITIONAL(HAVE_PUREDATA, [test "x$have_pd" = "xyes"]) 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]) ## checks for libsndfile AC_ARG_WITH([sndfile], [AS_HELP_STRING([--with-sndfile], [use libsndfile as backend for reading ambix-files])], [], [with_sndfile=yes]) have_sndfile="no" AS_IF([test "x$with_sndfile" != xno], [ tmp_sndfile_CFLAGS="$CFLAGS" tmp_sndfile_LIBS="$LIBS" PKG_CHECK_MODULES([SNDFILE], [sndfile], [have_sndfile="yes"], [have_sndfile="no"]) if test "x$have_sndfile" = "xyes"; then CFLAGS="$CFLAGS $SNDFILE_CFLAGS" LIBS="$LIBS $SNDFILE_LIBS" AC_CHECK_HEADERS(sndfile.h) AC_SEARCH_LIBS([sf_set_chunk], [sndfile], [AC_DEFINE([HAVE_SF_SET_CHUNK], [1], [Define to 1 if libsndfile can set custom chunks using sf_set_chunk()])]) AC_SEARCH_LIBS([sf_get_chunk_iterator], [sndfile], [AC_DEFINE([HAVE_SF_GET_CHUNK_ITERATOR], [1], [Define to 1 if libsndfile can get custom chunks via an iterator])]) AC_CHECK_TYPES([SF_CHUNK_INFO], [], [], [[#include ]]) dnl a custom version of libsndfile used sf_command to write UUID-chunks AC_CHECK_TYPES([SF_UUID_INFO], [], [], [[#include ]]) fi CFLAGS="$tmp_sndfile_CFLAGS" LIBS="$tmp_sndfile_LIBS" ]) AM_CONDITIONAL(HAVE_SNDFILE, [test "x$have_sndfile" = "xyes"]) ## checks for CoreAudio frameworks AC_ARG_WITH([CoreAudio], [AS_HELP_STRING([--with-CoreAudio], [use CoreAudio as backend for reading ambix-files])], [], [with_CoreAudio=check]) have_audiotoolbox="no" AS_IF([test "x$with_CoreAudio" != xno], [ IEM_CHECK_FRAMEWORK([Foundation], IEM_CHECK_FRAMEWORK([AudioToolbox], [have_audiotoolbox="yes"]) ) ] ) AM_CONDITIONAL([HAVE_FRAMEWORK_AUDIOTOOLBOX], [test "x$have_audiotoolbox" = "xyes"]) ## checks for jack AC_ARG_WITH([jack], [AS_HELP_STRING([--with-jack], [use JACK for playback/recording of live sound])], [], [with_jack=yes]) have_jack="no" AS_IF([test "x$with_jack" != xno], [ tmp_jack_CFLAGS="$CFLAGS" tmp_jack_LIBS="$LIBS" PKG_CHECK_MODULES([JACK], [jack], [have_jack="yes"], [have_jack="no"]) CFLAGS="$tmp_jack_CFLAGS" LIBS="$tmp_jack_LIBS" ]) AM_CONDITIONAL(HAVE_JACK, [test "x$have_jack" = "xyes"]) ## checks for samplerate AC_ARG_WITH([samplerate], [AS_HELP_STRING([--with-samplerate], [use libsamplerate for samplerate-conversion])], [], [with_samplerate=yes]) have_samplerate="no" AS_IF([test "x$with_samplerate" != xno], [ tmp_samplerate_CFLAGS="$CFLAGS" tmp_samplerate_LIBS="$LIBS" PKG_CHECK_MODULES([SAMPLERATE], [samplerate], [have_samplerate="yes"], [have_samplerate="no"]) CFLAGS="$tmp_samplerate_CFLAGS" LIBS="$tmp_samplerate_LIBS" ]) AM_CONDITIONAL(HAVE_SAMPLERATE, [test "x$have_samplerate" = "xyes"]) AC_CHECK_PROGS([DOXYGEN], [doxygen], [true]) AM_CONDITIONAL(HAVE_DOXYGEN, [test "x${DOXYGEN}" != "xtrue"]) AC_SUBST(DOXYGEN) 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 ambix-0.1.1/coverage.sh000077500000000000000000000015621300077024200147420ustar00rootroot00000000000000#!/bin/sh INFOFILE="libambix.info" OUTDIR=coverage/ MAKE=make ${MAKE} clean # Reconfigure with gcov support CFLAGS="-g -O0 --coverage" CXXFLAGS="-g -O0 --coverage" LDFLAGS="--coverage" \ ./configure --enable-debug --disable-silent-rules || exit 1 # Generate gcov output ${MAKE} || exit 1 # Generate html report lcov --base-directory . --directory . --zerocounters -q || exit 1 ${MAKE} check || exit 1 lcov --base-directory libambix/src --directory libambix/src -c -o ${INFOFILE} || exit 1 lcov --base-directory libambix/tests --directory libambix/tests -c -o tests_${INFOFILE} || exit 1 # remove output for external libraries lcov --remove ${INFOFILE} "/usr*" -o ${INFOFILE} || exit 1 lcov --remove tests_${INFOFILE} "/usr*" -o tests_${INFOFILE} || exit 1 rm -rf "${OUTDIR}" genhtml -o "${OUTDIR}" -t "libambix test coverage" --num-spaces 4 ${INFOFILE} tests_${INFOFILE} ambix-0.1.1/doc/000077500000000000000000000000001300077024200133515ustar00rootroot00000000000000ambix-0.1.1/doc/Makefile.am000066400000000000000000000004211300077024200154020ustar00rootroot00000000000000EXTRA_DIST=libambix.doxy \ libambix.incl html_DATA= if HAVE_DOXYGEN html_DATA+=apiref/* endif DOXYFILE=$(srcdir)/libambix.doxy apiref/*: all-local all-local: $(DOXYGEN) $(DOXYFILE) clean-local: -rm -rf apiref uninstall-local: -rm -rf "$(DESTDIR)$(docdir)/apiref" ambix-0.1.1/doc/libambix.doxy000066400000000000000000002224141300077024200160520ustar00rootroot00000000000000# Doxyfile 1.7.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = "libambix" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # 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 = "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 # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = . # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = ../libambix . # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../libambix/ambix libambix.incl # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = apiref # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # 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 = 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 # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. #USE_MATHJAX = NO USE_MATHJAX = YES # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. 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. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES ambix-0.1.1/doc/libambix.incl000066400000000000000000000531741300077024200160210ustar00rootroot00000000000000/* libambix.incl - Documentation for AMBIsonics eXchange Library -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ /** * @mainpage AMBIX - the AMBIsonics eXchange library * * @section intro_sec Introduction * * libambix is a library that allows you to read and write AMBIX-files. * It is strongly modelled after libsndfile, which it uses as a backend * * * @section usage_sec Usage * * libambix provides a (hopefully easy to use) C-interface. Basically you open a * file using ambix_open(), read audio data using @ref ambix_readf or write * audio data using @ref ambix_writef and call ambix_close() once you are done. * * For a more detailed documentation, see the @link usage Usage page. @endlink * * @section format_sec Format * * For a shortish specification of the ambix format see the @link format Format * page. @endlink */ /** * @page usage Usage * * @section read_usage Reading ambix files * * When opening a file for read, the ambix_info_t struct should be set to 0. On * successful open, all fields are filled by the library. If the open fails, * the state of the ambix_info_t fields is undefined. * * The only exception to this is, if you want to force the ambix file to be read * as either "BASIC" or "EXTENDED", e.g. because you don't want to care about * adaptor matrices or because you do. In this case you must set the fileformat * field the requested format. * * * * @subsection readbasic_usage Reading BASIC ambix files * * You can read any ambix file as "BASIC" by setting the 'fileformat' member of * the ambix_info_t struct to @ref AMBIX_BASIC prior to opening the file. * This will automatically do any conversion needed, by pre-multiplying the raw * ambisonics data with an embedded adaptor matrix. * * Real "BASIC" files lack extra audio channels. * However, when opening a file that is not a "BASIC" ambix file (e.g. an * "EXTENDED" ambix file) as a "BASIC" one, by forcing the 'fileformat' member * to '@ref AMBIX_BASIC', extra channels might be readable. * * @code ambix_t*ambix = NULL; ambix_info_t*info = calloc(1, sizeof(ambix_info_t)); ambix->fileformat = AMBIX_BASIC; ambix = ambix_open("ambixfile.caf", AMBIX_READ, info); if(ambix) { uint64_t frames = info->frames; uint64_t blocksize = 1024; float32_t*ambidata = calloc(info->ambichannels * blocksize, sizeof(float32_t)); float32_t*extradata = calloc(info->extrachannels * blocksize, sizeof(float32_t)); while(frames>blocksize) { uint64_t blocks = ambix_readf_float32(ambix, ambidata, extradata, blocksize); // process blocks frames of interleaved ambidata and interleaved extradata // ... frames-=blocks; } ambix_readf_float32(ambix, ambidata, extradata, frames); // process last block of interleaved ambidata and interleaved extradata // ... ambix_close(ambix); free(ambidata); free(extradata); } free(info); * @endcode * * * * @subsection readextended_usage Reading EXTENDED ambix files * * You can read an ambix file as "EXTENDED" by setting the 'fileformat' member * of the ambix_info_t struct to @ref AMBIX_EXTENDED prior to opening the file. You * will then have to retrieve the adaptor matrix from the file, in order to be * able to reconstruct the full ambisonics set. You can also analyze the matrix * to make educated guesses about the original channel layout. * * @code ambix_t*ambix = NULL; ambix_info_t*info = calloc(1, sizeof(ambix_info_t)); /* 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); if(ambix) { uint64_t frames = info->frames; uint64_t blocksize = 1024; float32_t*ambidata = calloc(info->ambichannels * blocksize, sizeof(float32_t)); float32_t*extradata = calloc(info->extrachannels * blocksize, sizeof(float32_t)); const ambix_matrix_t*adaptormatrix=ambix_get_adaptormatrix(ambix); while(frames>blocksize) { uint64_t blocks = ambix_readf_float32(ambix, ambidata, extradata, blocksize); // process blocks frames of interleaved ambidata and interleaved extradata, // using the adaptormatrix // ... frames-=blocks; } ambix_readf_float32(ambix, ambidata, extradata, frames); // process last block of interleaved ambidata and interleaved extradata // using the adaptormatrix // ... ambix_close(ambix); free(ambidata); free(extradata); } free(info); * @endcode * * * @subsection readunknown_usage Reading any ambix files * * 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 = ambix_open("ambixfile.caf", AMBIX_READ, info); if(ambix) { switch(ambix->fileformat) { case(AMBIX_BASIC): printf("this file is ambix basic\n"); break; case(AMBIX_EXTENDED): printf("this file is ambix extended\n"); break; case(AMBIX_NONE): printf("this file is not an ambix file\n"); break; default: printf("this file is of unknown format...\n"); } ambix_close(ambix); } free(info); * @endcode * * * @section write_usage Writing ambix files * * To write data to an ambix file, you have to open it with the @ref AMBIX_WRITE * flag. You also need to specify some global properties of the output data, * namely the samplerate and the sampleformat, as well as the number of * ambisonics channels and the number of extra channels that are physically * stored on the disk. * * @subsection writebasic_usage Writing BASIC ambix files * * You can write "BASIC" ambix files by setting the 'fileformat' member of the * 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 (see also @ref writebasic2extended_usage). * A full set of ambisonics must always satisfy the formula * @f$channels=(order_{ambi}+1)^2@f$. * * You cannot write extra audio channels into a "BASIC" ambix file. * * @code ambix_t*ambix = NULL; ambix_info_t*info = calloc(1, sizeof(ambix_info_t)); /* need to specify samplerate and sampleformat */ ambix->samplerate = 44100; 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 = ambix_open("ambixfile.caf", AMBIX_WRITE, info); if(ambix) { uint64_t frames = info->frames; uint64_t blocksize = 1024; uint64_t block; float32_t*ambidata = calloc(info->ambichannels * blocksize, sizeof(float32_t)); while(haveData) { // acquire blocksize samples of a full set of 3rd order ambisonics data (16 channels) // into ambidata (interleaved) // ... block = ambix_writef_float32(ambix, ambidata, NULL, blocksize); } ambix_close(ambix); free(ambidata); } free(info); * @endcode * * @subsection writeextended_usage Writing EXTENDED ambix files * * You can write "EXTENDED" ambix files by setting the 'fileformat' member of * the ambix_info_t struct to @ref AMBIX_EXTENDED prior to opening the file. * * You MUST set an adaptormatrix (to convert the reduced set to a full * ambisonics set) using ambix_set_adaptormatrix(). It 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. * * @code ambix_t*ambix = NULL; ambix_info_t*info = calloc(1, sizeof(ambix_info_t)); /* need to specify samplerate and sampleformat */ ambix->samplerate = 44100; 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 = ambix_open("ambixfile.caf", AMBIX_WRITE, info); if(ambix) { uint64_t frames = info->frames; uint64_t blocksize = 1024; uint64_t block; float32_t*ambidata = calloc(info->ambichannels * blocksize, sizeof(float32_t)); float32_t*extradata = calloc(info->extrachannels * blocksize, sizeof(float32_t)); /* 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) // ... ambix_set_adapatormatrix(ambix, &adaptormatrix); ambix_write_header(ambix); while(haveData) { // acquire blocksize samples of a full set of reduced ambisonics data (8 channels) // into ambidata (interleaved), and a some (1) extra channels // ... block = ambix_writef_float32(ambix, ambidata, extradata, blocksize); } ambix_close(ambix); ambix_matrix_deinit(&adaptormatrix); 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 * */ /** * @page format The ambix format * * The ambisonics channel layout for ambix-files is @link format_norm SN3D@endlink/@link format_acn ACN @endlink (3D, seminormalized, Ambisonic Channel Numbers), * henceforth called "standard layout". * * Files in @ref AMBIX_BASIC format always store the data in the standard layout. * Files in @ref AMBIX_EXTENDED format can store the data in any layout they prefer, * but have to provide an adapator matrix @f$M@f$ that can be used to convert the * channels layout stored within the file to the standard layout, according to * the formula @f$\vec{b}_{standardlayout}=M_{adaptor}*\vec{b}_{filelayout}@f$. * * E.g. if the channels are stored in the traditional @em B-format (3D), * the following adaptor matrix has to be used: * * @f$M_{B\rightarrow ambix}=\begin{pmatrix}\sqrt{2}&0&0&0\\0&0&0&-1\\0&1&0&0\\0&0&-1&0\end{pmatrix}@f$ * * @section format_bugfix Bug-fixes for the format-specification * * The original format proposal * 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. * * @subsection format_bugfix_UUID UUID-chunk * * The original format proposal defined a UUID @b 49454d2e-4154-2f41-4d42-49582f584d4c, * which is equivalent to the literal "IEM.AT/AMBIX/XML" (the UUID is an ASCII-representation of this string). * Unfortunately this does not take into account, that while UUIDs can be @e random, * certain bits are reserved (e.g. indicating the UUID variant). * The originally suggested UUID is - according to it's reserved bits - a v2 variant (DCE Security), * though in reality it is not. This makes name clashes probable and counteracts the idea of using UUIDs. * This UUID should therefore be deprecated. * * Therefore, it is suggested to use URL based UUID of the v5 variant (SHA-1 based), with the URLs following the scheme * http://ambisonics.iem.at/xchange/format/1.0 , * where the last element of the URL denotes the ambix specification version the given chunk adheres to. * This allows for easy and consistent adding of new UUIDs, if the format ever needs to be extended. * * The URL http://ambisonics.iem.at/xchange/format/1.0 translates to the UUID @b 1ad318c3-00e5-5576-be2d-0dca2460bc89. * * For compatibility reasons, libambix will be able to read both the original (deprecated) and the new UUID. * However, it will only write the new UUID to newly created ambix files. * * @subsection format_bugfix_sampletypes Valid sample types * * The original format proposal enumerates the valid sample (audio data) types, as int16, int24, int32 and float32. * This seems to be an unnecessary restriction on the CAF-format. * All sample types valid in CAF-files should be valid in ambix files as well. * * @subsection format_bugfix_rowcols Type of rows & columns in the adaptor matrix * * The original format proposal shows the adaptor matrix as a linear array of float32 values, with the first element * being the number of rows in the matrix and the second element being the number of columns. The remaining values form the * actual matrix data in the order a[0,0], a[0,1]...a[L,C]. * Since both rows and columns can only be positive integer values, this has been changed, so the first two values are of the type int32. * * @subsection format_bugfix_extrachannels Extra (non-ambisonics) channels * * The original format proposal speaks only of full ambisonics sets (in the case of the "BASIC" format, all audio channels * in the CAF-file must form exactly a full ambisonics set; in the case of the "EXTENDED" format, all audio channels in the * CAF-file multiplied by the adaptor matrix must form a full ambisonics set). * When implementing libambix, this was interpreted to allow room for "extra" (non-ambisonics) channels in the "EXTENDED" format: * If a file holds (C+X) audio channels (with both C and X being positive integers), * the first C channels are converted into a full ambisonics set by multiplying it with the [L*C] adaptor matrix. * The remaining X channels are provided "as-is", and can be used to store extra data (like click-tracks,...) * * @section format_glossary Format Glossary * @subsection format_norm Normalisation * * There are a number of different ways how to @em normalize the Ambisonics channels * (that is: how they are weighted relative to each other). * The default layout assumes Schmidt semi-normalized spherical harmonics. * * @subsection format_acn Ambisonics Channel Number * The channel ordering is standardized using the following formula * (with @f$l@f$ being the @em degree and @f$m@f$ being the @em order of the spherical harmonic). * * @f$ACN = l * ( l + 1 ) + m@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 library for reading and writing ambisonics exchange 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 * */ ambix-0.1.1/libambix/000077500000000000000000000000001300077024200143735ustar00rootroot00000000000000ambix-0.1.1/libambix/Makefile.am000066400000000000000000000003201300077024200164220ustar00rootroot00000000000000SUBDIRS=src #run tests at the end SUBDIRS+=tests EXTRA_DIST=libambix.pc.in pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libambix.pc nobase_include_HEADERS = \ ambix/exportdefs.h \ ambix/ambix.h ambix-0.1.1/libambix/ambix/000077500000000000000000000000001300077024200154735ustar00rootroot00000000000000ambix-0.1.1/libambix/ambix/ambix.h000066400000000000000000000644501300077024200167550ustar00rootroot00000000000000/* ambix/ambix.h - AMBIsonics eXchange Library Interface -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ /** * @file ambix/ambix.h * @brief AMBIsonics eXchange Library Interface * @details This file is part of libambix * @author IOhannes m zmölnig * @date 2012 * @copyright LGPL-2.1 */ #ifndef AMBIX_AMBIX_H #define AMBIX_AMBIX_H #include "exportdefs.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /** 32bit floating point number */ typedef float float32_t; /** 64bit floating point number */ typedef double float64_t; #ifdef _MSC_VER /** 16bit signed integer */ typedef signed short int16_t; /** 16bit unsigned integer */ typedef unsigned short uint16_t; /** 32bit signed integer */ typedef signed int int32_t; /** 32bit unsigned integer */ typedef unsigned int uint32_t; /** 64bit signed integer */ typedef signed long int64_t; /** 64bit unsigned integer */ typedef unsigned long uint64_t; #else # include #endif /** a 32bit number (either float or int), useful for endianness operations */ typedef union { /** 32bit floating point */ float32_t f; /** 32bit signed integer */ int32_t i; /** 32bit unsigned integer */ uint32_t u; } number32_t; /** opaque handle to an ambix file */ typedef struct ambix_t_struct ambix_t; /** error codes returned by functions */ typedef enum { /** an unknown error */ AMBIX_ERR_UNKNOWN=-1, /** no error encountered */ AMBIX_ERR_SUCCESS= 0, /** an invalid ambix handle was passed to the function */ AMBIX_ERR_INVALID_HANDLE, /** the file in question is invalid (e.g. doesn't contain audio) */ AMBIX_ERR_INVALID_FILE, /** matrix dimension mismatch */ AMBIX_ERR_INVALID_DIMENSION, /** the ambix handle is in a format that does not allow the function (e.g. * setting a premultiply matrix for a format other than AMBIX_BASIC) */ AMBIX_ERR_INVALID_FORMAT, /** you specified an invalid matrix */ AMBIX_ERR_INVALID_MATRIX, } ambix_err_t; /** error codes returned by functions */ typedef enum { /** open file for reading */ AMBIX_READ = (1 << 4), /** open file for writing */ AMBIX_WRITE = (1 << 5), /** open file for reading&writing */ AMBIX_RDRW = (AMBIX_READ|AMBIX_WRITE) } ambix_filemode_t; /** ambix file types */ typedef enum { /** file is not an ambix file (or unknown) */ AMBIX_NONE = 0, /** basic ambix file (w/ pre-multiplication matrix) */ AMBIX_BASIC = 1, /** extended ambix file (w pre-multiplication matrix ) */ AMBIX_EXTENDED = 2 } ambix_fileformat_t; /** ambix sample formats */ typedef enum { /** unknown (or illegal) sample formats */ AMBIX_SAMPLEFORMAT_NONE=0, /** signed 16 bit integer */ AMBIX_SAMPLEFORMAT_PCM16, /** signed 24 bit integer */ AMBIX_SAMPLEFORMAT_PCM24, /** signed 32 bit integer */ AMBIX_SAMPLEFORMAT_PCM32, /** 32 bit floating point */ AMBIX_SAMPLEFORMAT_FLOAT32, /** 64 bit floating point */ AMBIX_SAMPLEFORMAT_FLOAT64, } ambix_sampleformat_t; /** ambix matrix types */ typedef enum { /** invalid matrix format */ AMBIX_MATRIX_INVALID = -1, /** a matrix filled with zeros */ AMBIX_MATRIX_ZERO = 0, /** a matrix filled with ones */ AMBIX_MATRIX_ONE = 1, /** an identity matrix (diagonal is 1, rest is 0) */ AMBIX_MATRIX_IDENTITY, /** 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 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) */ AMBIX_MATRIX_AMBIX = 0x8000, /** conversion matrix N3D -> SN3D */ AMBIX_MATRIX_N3D = 1 | AMBIX_MATRIX_AMBIX, /** conversion matrix SID -> ACN */ AMBIX_MATRIX_SID = 2 | AMBIX_MATRIX_AMBIX, /** conversion matrix Furse-Malham -> ambix */ AMBIX_MATRIX_FUMA = 3 | AMBIX_MATRIX_AMBIX, /** back conversion matrix ambix -> ambix */ AMBIX_MATRIX_TO_AMBIX = 0x4000 | AMBIX_MATRIX_AMBIX, /** conversion matrix SN3D -> N3D */ AMBIX_MATRIX_TO_N3D = AMBIX_MATRIX_TO_AMBIX | AMBIX_MATRIX_N3D, /** 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, } ambix_matrixtype_t; /** a 2-dimensional floating point matrix */ typedef struct ambix_matrix_t { /** number of rows */ uint32_t rows; /** number of columns */ uint32_t cols; /** matrix data (as vector (length: rows) of row-vectors (length: cols)) */ float32_t **data; } ambix_matrix_t; /** this is for passing data about the opened ambix file between the host * application and the library */ typedef struct ambix_info_t { /** number of frames in the file */ uint64_t frames; /** samplerate in Hz */ double samplerate; /** sample type of the ambix file */ ambix_sampleformat_t sampleformat; /** 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 * @remark think of a better name, like 'uncodedchannels' */ uint32_t extrachannels; /** number of (raw) ambisonics channels present in the file. * * 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 * * Opens a soundfile for reading/writing * * @param path filename of the file to open * * @param mode whether to open the file for reading and/or writing (@ref AMBIX_READ, * @ref AMBIX_WRITE, @ref AMBIX_RDRW) * * @param ambixinfo pointer to a valid ambix_info_t structure * * @remark when opening a file for reading, the structure should be initialized * to zero before calling ambix_open(): the fields will be set by the library; * if you set the ambixinfo.ambixformat field to something else than @ref AMBIX_NONE, * the library will present the data as if the was written in this format (e.g. * if you set ambixinfo.ambixformat to @ref AMBIX_BASIC but the file really is * @ref AMBIX_EXTENDED, the library will automatically pre-multiply the * reconstruction matrix to give you the full ambisonics set. * * @remark when opening a file for writing, the caller must set the fields; if * ambixinfo.ambixformat is @ref AMBIX_NONE, than ambixinfo.ambichannels must be 0, * else ambixinfo.ambichannels must be >0; if ambixinfo.ambixformat is * @ref AMBIX_BASIC, then ambixinfo.ambichannels must be @f$(order_{ambi}+1)^2@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) ; /** @brief Close an ambix handle * * Closes an ambix handle and cleans up all memory allocations associated with * it. * * @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) ; /** @brief Reposition the file pointer * * Reposition the file read (and/or write) pointer to a new offset. * Consecutive calls to @ref ambix_readf (resp. @ref ambix_writef) will read * (resp. write) from the new position. * * @param ambix The handle to an ambix file * @param frames frame offset from the position given in whence * @param whence location from where to seek; if whence is set to SEEK_SET, * SEEK_CUR, or SEEK_END, the offset is relative to the start of the file, * the current position indicator, or end-of-file, respectively. * * @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 from the ambix file * @defgroup ambix_readf ambix_readf() * * Reads samples from an ambix file, possibly expanding a reduced channel set to * a full ambisonics set (when reading an 'ambix extended' file as 'ambix * basic') * * @param ambix The handle to an ambix file * * @param ambidata pointer to user allocated array to retrieve ambisonics * channels into; must be large enough to hold at least * (frames*ambix->info.ambichannels) samples, OR if you are reading the file as * 'ambix basic' and you successfully added an adaptor matrix using * ambix_set_adaptormatrix() the array must be large enough to hold at least * (frames * adaptormatrix.rows) samples. * * @param otherdata pointer to user allocated array to retrieve non-ambisonics * channels into must be large enough to hold at least * (frames*ambix->info.otherchannels) samples. * * @param frames number of sample frames you want to read * * @return the number of sample frames successfully read * * @ingroup ambix */ /** @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 (as single precision floating point 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 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, * possibly expanding a reduced channel set to a full ambisonics set (when * writing an 'ambix extended' file as 'ambix basic'). * * Data will be stored on harddisk in the format specified when opening the file * for writing which need not be float32, in which case the data is * automatically converted by the library to the appropriate format. * * @param ambix The handle to an ambix file. * * @param ambidata pointer to user allocated array to retrieve ambisonics * channels from; must be large enough to hold (frames*ambix->info.ambichannels) * samples. * * @param otherdata pointer to user allocated array to retrieve non-ambisonics * channels into must be large enough to hold (frames*ambix->info.otherchannels) * samples. * * @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 */ 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 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 * to reconstruct a full 3d ambisonics set from the channels stored in ambix * file. In the ambix @ref AMBIX_BASIC format no adaptor matrix is present, the file * always contains the full set. * * @remark the adaptor matrix can only be obtained for a ambix extended file; if * you have opened an ambix extended file as "ambix basic", the adaptor will be * done by the library; in this case, you will not be able to fetch the adaptor * matrix. * * @remark if you have opened an ambix basic file as ambix extended, this will * return a unity matrix. * * @param ambix The handle to an ambix file * * @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) ; /** @brief Set a matrix to be pre-multiplied * * Adds an (additional) adaptor matrix to the processing. Depending on the mode * 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 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 * AMBIX_EXTENDED' file, this tells the library to store the matrix as the * adaptor matrix within the file. * * @param ambix The handle to an ambix file * * @param matrix a matrix that will be pre-multiplied to the * reconstruction-matrix; can be freed after this call. * * @return an errorcode indicating success * * @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) ; /* * @section api_matrix matrix utility functions */ /** @brief Create a matrix * * Allocates a new (empty) matrix object. * 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) ; /** @brief Destroy a matrix * * Frees all resources allocated for the matrix object. * 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) ; /** @brief Initialize a matrix * * Allocates memory for matrix-data of given dimensions * * @param rows number of rows in the newly initialized matrix * * @param cols number of columns in the newly initialized matrix * * @param mtx pointer to a matrix object; if NULL a new matrix object will be * created, else the given matrix object will be re-initialized. * * @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) ; /** @brief De-initialize a matrix * * 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) ; /** @brief Fill a matrix according to specs * * Fill a properly initialized matrix according to type. You can use this to * generate standard matrices (e.g. using AMBIX_MATRIX_ONE will set all elements * of the matrix to 1.0). Since this call will not change the matrix layout * (e.g. the dimension), it is the responsibility of the caller to ensure that * the matrix has a proper layout for the requested type (e.g. it is an error to * fill a Furse-Malham matrix into a matrix that holds more than 3rd order * ambisonics). * * @param matrix initialized matrix object to fill * * @param type data specification * * @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) ; /** @brief Fill a matrix with values * * Fill data into a properly initialized matrix * * @param mtx initialized matrix object to copy data into * * @param data pointer to at least (mtx->rows*mtx->cols) values; data is ordered * row-by-row with no padding (A[0,0], A[0,1], .., A[0,cols-1], A[1, 0], .. * 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) ; /** @brief Copy a matrix to another matrix * * Copy a matrix, possibly resizing or creating the destination * * @param src the source matrix to copy the data from * * @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 * 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(). * * @ingroup ambix_matrix */ 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. * * @param dest a pointer to hold the output data; it must be large enough to * hold at least rows*frames samples (allocated by the user). * * @param mtx the matrix to multiply source with. * * @param source a pointer to an array that holds cols*frames samples (allocated * by the user). * * @param frames number of frames in source * * @return an error code indicating success * * @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 */ AMBIX_API ambix_err_t ambix_matrix_multiply_int32(int32_t *dest, const ambix_matrix_t *mtx, const int32_t *source, int64_t frames) ; /** @brief Multiply a matrix with (16 bit signed integer) data * * @ingroup ambix_matrix_multiply_data */ 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) ; /** @brief Calculate the order of a full 3d ambisonics set for a given number of * channels. * * @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) ; /** @brief Checks whether the channel can form a full 3d ambisonics set. * * @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) ; #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* AMBIX_AMBIX_H */ ambix-0.1.1/libambix/ambix/exportdefs.h000066400000000000000000000044721300077024200200360ustar00rootroot00000000000000/* ambix/exportdefs.h - defines for dll import/export -*- c -*- Copyright © 2012 IOhannes m zmölnig 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 . */ /** * @file ambix/exportdefs.h * @brief export definitions for various compilers * @details This file is part of libambix * @author IOhannes m zmölnig * @date 2012 * @copyright LGPL-2.1 */ #ifndef AMBIX_EXPORTDEFS_H #define AMBIX_EXPORTDEFS_H #if defined _MSC_VER /* MSVC always uses dllimport/dllexport */ # define DLL_EXPORT #endif /* _MSC_VER */ #ifdef DLL_EXPORT /* Windows requires explicit import and exporting of functions and classes. * While this is a pain to do sometimes, in large software development * projects, it is very useful. */ # define AMBIX_EXPORT __declspec(dllexport) # define AMBIX_IMPORT __declspec(dllimport) # define AMBIX_DEPRECATED __declspec(deprecated) #elif defined __GNUC__ # define AMBIX_EXPORT __attribute__ ((visibility("default"))) # define AMBIX_IMPORT # define AMBIX_DEPRECATED __attribute__ ((deprecated)) #else /* unknown compiler */ # warning set up compiler specific defines /** mark symbols to be exported from libambix */ # define AMBIX_EXPORT /** mark symbols to be imported from libambix */ # define AMBIX_IMPORT /** mark symbols to be deprecated */ # define AMBIX_DEPRECATED #endif #ifdef AMBIX_INTERNAL /** mark symbols to be useable outside the library */ # define AMBIX_API AMBIX_EXPORT #else /** mark symbols to be useable outside the library */ # define AMBIX_API AMBIX_IMPORT #endif #endif /* AMBIX_EXPORTDEFS_H */ ambix-0.1.1/libambix/libambix.pc.in000066400000000000000000000004301300077024200171100ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: sndfile Description: A library for reading and writing AMBIsonics eXchange files Requires: Version: @VERSION@ Libs: -L${libdir} -lambix Libs.private: @SNDFILE_LIBS@ Cflags: -I${includedir} ambix-0.1.1/libambix/src/000077500000000000000000000000001300077024200151625ustar00rootroot00000000000000ambix-0.1.1/libambix/src/Makefile.am000066400000000000000000000057641300077024200172320ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign AM_CPPFLAGS = -I$(top_srcdir)/libambix lib_LTLIBRARIES = libambix.la #------------------------------------------------------------------------------------ # Rules for library version information: # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # # 1. Start with version information of `0:0:0' for each libtool library. # 2. Update the version information only immediately before a public release of # your software. More frequent updates are unnecessary, and only guarantee # that the current interface number gets larger faster. # 3. If the library source code has changed at all since the last update, then # increment revision (`c:r:a' becomes `c:r+1:a'). # 4. If any interfaces have been added, removed, or changed since the last # update, increment current, and set revision to 0. # 5. If any interfaces have been added since the last public release, then # increment age. # 6. If any interfaces have been removed since the last public release, then # set age to 0. # # The following explanation may help to understand the above rules a bit better: # consider that there are three possible kinds of reactions from users of your # library to changes in a shared library: # # 1. Programs using the previous version may use the new version as drop-in # replacement, and programs using the new version can also work with the # previous one. In other words, no recompiling nor relinking is needed. In # this case, bump revision only, don't touch current nor age. # 2. Programs using the previous version may use the new version as drop-in # replacement, but programs using the new version may use APIs not present in # the previous one. In other words, a program linking against the new version # may fail with “unresolved symbols” if linking against the old version at # runtime: set revision to 0, bump current and age. # 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_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) libambix_la_SOURCES = libambix.c \ adaptor.c \ adaptor_acn.c \ adaptor_fuma.c \ matrix.c matrix_invert.c \ utils.c \ uuid_chunk.c \ marker_region_chunk.c \ private.h if HAVE_SNDFILE libambix_la_SOURCES += sndfile.c libambix_la_CFLAGS += @SNDFILE_CFLAGS@ libambix_la_LIBADD += @SNDFILE_LIBS@ else !HAVE_SNDFILE if HAVE_FRAMEWORK_AUDIOTOOLBOX libambix_la_SOURCES += coreaudio.m libambix_la_LIBADD += @IEM_FRAMEWORK_AUDIOTOOLBOX@ @IEM_FRAMEWORK_FOUNDATION@ else !HAVE_FRAMEWORK_AUDIOTOOLBOX libambix_la_SOURCES += null.c endif !HAVE_FRAMEWORK_AUDIOTOOLBOX endif !HAVE_SNDFILE ambix-0.1.1/libambix/src/adaptor.c000066400000000000000000000206471300077024200167710ustar00rootroot00000000000000/* adaptor.c - extracting ambisonics data from data using adaptor matrices -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "private.h" #ifdef HAVE_STDLIB_H # include #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 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) return AMBIX_ERR_UNKNOWN; if(size > ambix->adaptorbuffersize) { /* re-allocate memory! */ void*newbuf=realloc(ambix->adaptorbuffer, size); if(newbuf) { ambix->adaptorbuffer=newbuf; ambix->adaptorbuffersize=size; } else { free(ambix->adaptorbuffer); ambix->adaptorbuffer=NULL; ambix->adaptorbuffersize=0; return AMBIX_ERR_UNKNOWN; } } return AMBIX_ERR_SUCCESS; } ambix_err_t _ambix_adaptorbuffer_destroy(ambix_t*ambix) { if(ambix->adaptorbuffer) free(ambix->adaptorbuffer); ambix->adaptorbuffer=NULL; ambix->adaptorbuffersize=0; return AMBIX_ERR_SUCCESS; } #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) { \ int64_t frame; \ for(frame=0; framedata; \ const uint32_t fullambichannels=matrix->rows; \ const uint32_t rawambichannels=matrix->cols; \ int64_t f; \ for(f=0; fdata; \ const uint32_t fullambichannels=matrix->cols; \ const uint32_t ambixchannels=matrix->rows; \ int64_t f; \ for(f=0; fambix and store in destination */ \ uint32_t outchan, inchan; \ const type##_t*src = ambi_data+fullambichannels*f; \ for(outchan=0; outchan. 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 . */ #include "private.h" int _matrix_sid2acn(float32_t*data, uint32_t count) { float32_t*datap=data; int32_t order=ambix_channels2order(count); int32_t o; if(order<0)return 0; for(o=0; o<=order; o++) { uint32_t offset=o>0?ambix_order2channels(o-1):0; int32_t maxindex=ambix_order2channels(o)-offset; int32_t index; for(index=1; index=0; index-=2) { *datap++=(float32_t)(index+offset); } } return 1; } ambix-0.1.1/libambix/src/adaptor_fuma.c000066400000000000000000000215331300077024200177740ustar00rootroot00000000000000/* adaptor_fuma.c - adaptors to/from FUrse-MAlham sets -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . 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://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 */ #include "private.h" #include #include static ambix_matrix_t* fuma2ambix_weightorder(void) { const float32_t sqrt2 = (float32_t)(sqrt(2.)); // 1.414 const float32_t sqrt3_4 = (float32_t)(sqrt(3.)/2.); // 0.86603 const float32_t sqrt5_8 = (float32_t)(sqrt(5./2.)/2.); // 0.79057 const float32_t sqrt32_45= (float32_t)(4.*sqrt(2./5.)/3.);// 0.84327 const float32_t sqrt5_9 = (float32_t)(sqrt(5.)/3.); // 0.74536 static float32_t order[]={ 0, 2, 3, 1, 8, 6, 4, 5, 7, 15, 13, 11, 9, 10, 12, 14, }; float32_t weights[]={ sqrt2, -1, 1, -1, sqrt3_4, -sqrt3_4, 1, -sqrt3_4, sqrt3_4, -sqrt5_8, sqrt5_9, -sqrt32_45, 1, -sqrt32_45, sqrt5_9, -sqrt5_8, }; ambix_matrix_t*result_m=NULL; ambix_matrix_t*weight_m=NULL; ambix_matrix_t*order_m =NULL; 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); ambix_matrix_destroy(weight_m);weight_m=NULL; ambix_matrix_destroy(order_m); order_m=NULL; return result_m; } static ambix_matrix_t* ambix2fuma_weightorder(void) { const float32_t sqrt1_2 = (float32_t)(1./sqrt(2.)); // 0.707 const float32_t sqrt4_3 = (float32_t)(2./sqrt(3.)); // 1.1547 const float32_t sqrt8_5 = (float32_t)(2.*sqrt(2./5.)); // 1.2649 const float32_t sqrt45_32= (float32_t)(3.*sqrt(5./2.)/4.);// 1.1856 const float32_t sqrt9_5 = (float32_t)(3./sqrt(5.)); // 1.3416 static float32_t order[]={ 0, 2, 3, 1, 8, 6, 4, 5, 7, 15, 13, 11, 9, 10, 12, 14, }; float32_t weights[]={ sqrt1_2, -1, 1, -1, sqrt4_3, -sqrt4_3, 1, -sqrt4_3, sqrt4_3, -sqrt8_5, sqrt9_5, -sqrt45_32, 1, -sqrt45_32, sqrt9_5, -sqrt8_5, }; ambix_matrix_t*result_m=NULL; ambix_matrix_t*weight_m=NULL; ambix_matrix_t*order_m =NULL; 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); ambix_matrix_destroy(weight_m);weight_m=NULL; ambix_matrix_destroy(order_m); order_m=NULL; return result_m; } static ambix_matrix_t* _matrix_multiply3(ambix_matrix_t*mtx1, ambix_matrix_t*mtx2, ambix_matrix_t*mtx3, ambix_matrix_t*result) { ambix_matrix_t*tmp=NULL; tmp=_ambix_matrix_multiply(mtx1, mtx2, tmp); result=_ambix_matrix_multiply(tmp, mtx3, result); ambix_matrix_destroy(tmp); return result; } ambix_matrix_t* _matrix_ambix2fuma(uint32_t cols) { #if 1 float32_t reducer_v[17][16]={ {0}, /* NULL */ {0}, // W {0}, /* NULL */ {0, 1, 2}, // WXY {0, 1, 2, 3}, // WXYZ {0, 1, 2, 7, 8}, // WXYUV {0, 1, 2, 3, 7, 8}, // WXYZUV {0, 1, 2, 7, 8, 14, 15}, // WXYUVPQ {0, 1, 2, 3, 7, 8, 14, 15}, // WXYZUVPQ {0, 1, 2, 3, 4, 5, 6, 7, 8}, // WXYZRSTUV {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* NULL */ {0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15}, // WXYZRSTUVPQ {0}, /* NULL */ {0}, /* NULL */ {0}, /* NULL */ {0}, /* NULL */ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // WXYZRSTUVKLMNOPQ }; #else float32_t * reducer_v[]={ NULL, (float32_t[]) {0}, // W NULL, (float32_t[]) {0, 1, 2}, // WXY (float32_t[]) {0, 1, 2, 3}, // WXYZ (float32_t[]) {0, 1, 2, 7, 8}, // WXYUV (float32_t[]) {0, 1, 2, 3, 7, 8}, // WXYZUV (float32_t[]) {0, 1, 2, 7, 8, 14, 15}, // WXYUVPQ (float32_t[]) {0, 1, 2, 3, 7, 8, 14, 15}, // WXYZUVPQ (float32_t[]) {0, 1, 2, 3, 4, 5, 6, 7, 8}, // WXYZRSTUV NULL, (float32_t[]) {0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15}, // WXYZRSTUVPQ NULL, NULL, NULL, NULL, (float32_t[]) {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // WXYZRSTUVKLMNOPQ }; #endif static const uint32_t rows_v[]={ 0, 1, // W 0, 4, // WXY 4, // WXYZ 9, // WXYUV 9, // WXYZUV 16,// WXYUVPQ 16,// WXYZUVPQ 9, // WXYZRSTUV 0, 16,// WXYZRSTUVPQ 0, 0, 0, 0, 16,// WXYZRSTUVKLMNOPQ }; if(cols > 16) return NULL; if(rows_v[cols]) { ambix_matrix_t*weightorder_m=NULL; ambix_matrix_t*expand_m=NULL; ambix_matrix_t*reduce_m=NULL; ambix_matrix_t*final_m=NULL; expand_m=ambix_matrix_init(16, rows_v[cols], expand_m); expand_m=ambix_matrix_fill(expand_m, AMBIX_MATRIX_IDENTITY); if(NULL==weightorder_m) weightorder_m=ambix2fuma_weightorder(); reduce_m=ambix_matrix_init(cols, 16, reduce_m); if(_matrix_permutate(reduce_m, reducer_v[cols], 0)) { final_m=_matrix_multiply3(reduce_m, weightorder_m, expand_m, final_m); } ambix_matrix_destroy(expand_m); expand_m=NULL; ambix_matrix_destroy(reduce_m); reduce_m=NULL; ambix_matrix_destroy(weightorder_m); weightorder_m=NULL; return final_m; } return NULL; } ambix_matrix_t* _matrix_fuma2ambix(uint32_t rows) { #if 1 float32_t reducer_v[17][16]={ {0}, /* NULL */ {0}, // W {0}, /* NULL */ {0, 1, 2}, // WXY {0, 1, 2, 3}, // WXYZ {0, 1, 2, 7, 8}, // WXYUV {0, 1, 2, 3, 7, 8}, // WXYZUV {0, 1, 2, 7, 8, 14, 15}, // WXYUVPQ {0, 1, 2, 3, 7, 8, 14, 15}, // WXYZUVPQ {0, 1, 2, 3, 4, 5, 6, 7, 8}, // WXYZRSTUV {0}, /* NULL */ {0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15}, // WXYZRSTUVPQ {0}, /* NULL */ {0}, /* NULL */ {0}, /* NULL */ {0}, /* NULL */ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // WXYZRSTUVKLMNOPQ }; #else float32_t*reducer_v[]={ NULL, (float32_t[]) {0}, // W NULL, (float32_t[]) {0, 1, 2}, // WXY (float32_t[]) {0, 1, 2, 3}, // WXYZ (float32_t[]) {0, 1, 2, 7, 8}, // WXYUV (float32_t[]) {0, 1, 2, 3, 7, 8}, // WXYZUV (float32_t[]) {0, 1, 2, 7, 8, 14, 15}, // WXYUVPQ (float32_t[]) {0, 1, 2, 3, 7, 8, 14, 15}, // WXYZUVPQ (float32_t[]) {0, 1, 2, 3, 4, 5, 6, 7, 8}, // WXYZRSTUV NULL, (float32_t[]) {0, 1, 2, 3, 4, 5, 6, 7, 8, 14, 15}, // WXYZRSTUVPQ NULL, NULL, NULL, NULL, (float32_t[]) {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, // WXYZRSTUVKLMNOPQ }; #endif static const uint32_t cols_v[]={ 0, 1, // W 0, 4, // WXY 4, // WXYZ 9, // WXYUV 9, // WXYZUV 16,// WXYUVPQ 16,// WXYZUVPQ 9, // WXYZRSTUV 0, 16,// WXYZRSTUVPQ 0, 0, 0, 0, 16,// WXYZRSTUVKLMNOPQ }; if(rows > 16) return NULL; if(cols_v[rows]) { ambix_matrix_t*weightorder_m=NULL; ambix_matrix_t*expand_m=NULL; ambix_matrix_t*reduce_m=NULL; ambix_matrix_t*final_m=NULL; expand_m=ambix_matrix_init(cols_v[rows], 16, expand_m); expand_m=ambix_matrix_fill(expand_m, AMBIX_MATRIX_IDENTITY); if(NULL==weightorder_m) weightorder_m=fuma2ambix_weightorder(); reduce_m=ambix_matrix_init(16, rows, reduce_m); if(_matrix_permutate(reduce_m, reducer_v[rows], 1)) { final_m=_matrix_multiply3(expand_m, weightorder_m, reduce_m, final_m); } ambix_matrix_destroy(expand_m); expand_m=NULL; ambix_matrix_destroy(reduce_m); reduce_m=NULL; ambix_matrix_destroy(weightorder_m); weightorder_m=NULL; return final_m; } return NULL; } ambix-0.1.1/libambix/src/coreaudio.m000066400000000000000000000524141300077024200173200ustar00rootroot00000000000000/* coreaudio.c - CoreAudio backend support -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #include "private.h" #import #import @interface AmbixData : NSObject { @public AudioFileID file; @public ExtAudioFileRef xfile; @public ambix_sampleformat_t sampleformat; } @end typedef struct ambixcoreaudio_private_struct { NSAutoreleasePool * pool; AmbixData*data; } ambixcoreaudio_private_t; static inline AmbixData*PRIVATE(ambix_t*ax) { ambixcoreaudio_private_t*priv=(ambixcoreaudio_private_t*)(ax->private_data); return priv->data; } @implementation AmbixData @end static void print_error(OSStatus err) { union { char s[5]; OSStatus err; } u; u.err=err; u.s[4]=0; printf("ERR: %x='%s'\n", err, u.s); } static void print_caf_formatID(UInt32 format) { union { char s[4]; UInt32 format; } u; u.format=format; printf("'%c%c%c%c'\n", u.s[0], u.s[1], u.s[2], u.s[3]); } #define str(x) #x #define xstr(x) str(x) #define PRINTFLAG(y) do {if (flags&y) {printf("" xstr(y)"|"); flags^=y;}}while(0) static void print_caf_flags(UInt32 flags) { PRINTFLAG(kAudioFormatFlagIsBigEndian); PRINTFLAG(kAudioFormatFlagIsPacked); PRINTFLAG(kAudioFormatFlagIsAlignedHigh); PRINTFLAG(kAudioFormatFlagIsNonInterleaved); PRINTFLAG(kAudioFormatFlagIsNonMixable); PRINTFLAG(kAudioFormatFlagsAreAllClear); PRINTFLAG(kAudioFormatFlagIsFloat); PRINTFLAG(kAudioFormatFlagIsSignedInteger); printf("%d\n", flags); } static void print_caformat(const AudioStreamBasicDescription*format) { printf(" SampleRate=%f\n", (float)format->mSampleRate); printf(" FormatID="); print_caf_formatID(format->mFormatID); printf(" FormatFlags="); print_caf_flags(format->mFormatFlags); printf(" BytesPerPacket=%lu\n", (unsigned long)format->mBytesPerPacket); printf(" FramesPerPacket=%lu\n", (unsigned long)format->mFramesPerPacket); printf(" BytesPerFrame=%lu\n", (unsigned long)format->mBytesPerFrame); printf(" ChannelsPerFrame=%lu\n", (unsigned long)format->mChannelsPerFrame); printf(" BitsPerChannel=%lu\n", (unsigned long)format->mBitsPerChannel); printf(" Reserved=%lu\n", (unsigned long)format->mReserved); } UInt32 coreaudio_doGetFlags ( UInt32 inValidBitsPerChannel, UInt32 inTotalBitsPerChannel, bool inIsFloat, bool inIsBigEndian, bool inIsNonInterleaved ) { return (inIsFloat ? kAudioFormatFlagIsFloat : kAudioFormatFlagIsSignedInteger) | (inIsBigEndian ? ((UInt32)kAudioFormatFlagIsBigEndian) : 0) | ((!inIsFloat && (inValidBitsPerChannel == inTotalBitsPerChannel)) ? kAudioFormatFlagIsPacked : kAudioFormatFlagIsAlignedHigh) | (inIsNonInterleaved ? ((UInt32)kAudioFormatFlagIsNonInterleaved) : 0); } UInt32 coreaudio_getFlags (UInt32 samplebits, bool isFloat, bool isBigEndian) { return coreaudio_doGetFlags(samplebits, samplebits, isFloat, isBigEndian, false); } static int _coreaudio_isNativeEndian(const ExtAudioFileRef cainfo) { AudioStreamBasicDescription f; UInt32 datasize=sizeof(f); memset(&f, 0, sizeof(f)); if(noErr == ExtAudioFileGetProperty(cainfo, kExtAudioFileProperty_FileDataFormat, &datasize, &f)) { return ((f.mFormatID == kAudioFormatLinearPCM) && ((f.mFormatFlags & kLinearPCMFormatFlagIsBigEndian) == kAudioFormatFlagsNativeEndian)); } return 0; } static int _coreaudio_isCAF(const AudioFileID*file) { /* trying to read format (is it caf?) */ UInt32 myformat=0; UInt32 formatSize=sizeof(myformat); OSStatus err=AudioFileGetProperty (*file, kAudioFilePropertyFileFormat, &formatSize, &myformat ); return (kAudioFileCAFType==myformat); } static int read_uuidchunk(ambix_t*ax) { /* read UUID */ UInt32 index=0; OSStatus err = noErr; char*data=NULL; for(index=0; ; index++) { UInt32 size=0; UInt32 datasize=0; uint32_t chunkver=0; if(data) free(data); data=NULL; err = AudioFileGetUserDataSize (PRIVATE(ax)->file, 'uuid', index, &size); if(noErr!=err) break; if(0==size) continue; datasize=size; data=calloc(datasize, sizeof(char)); if(!data)continue; err = AudioFileGetUserData (PRIVATE(ax)->file, 'uuid', index, &datasize, data); if(noErr!=err) break; if(datasize<16) continue; chunkver=_ambix_checkUUID(data); switch(chunkver) { case(1): if(_ambix_uuid1_to_matrix(data+16, datasize-16, &ax->matrix, ax->byteswap)) { if(data) free(data) ; data=NULL; return AMBIX_ERR_SUCCESS; } break; default: break; } } if(data) free(data); data=NULL; return AMBIX_ERR_UNKNOWN; } static ambix_sampleformat_t coreaudio_getSampleformat(AudioStreamBasicDescription*format) { int isFloat=(format->mFormatFlags & kLinearPCMFormatFlagIsFloat); int isInt =(format->mFormatFlags & kLinearPCMFormatFlagIsSignedInteger); int samplesize=format->mBitsPerChannel; if(format->mFormatFlags & kLinearPCMFormatFlagIsFloat) { if(32==samplesize)return AMBIX_SAMPLEFORMAT_FLOAT32; } else if (format->mFormatFlags & kLinearPCMFormatFlagIsSignedInteger) { switch(samplesize) { case 16: return AMBIX_SAMPLEFORMAT_PCM16; case 24: return AMBIX_SAMPLEFORMAT_PCM24; case 32: return AMBIX_SAMPLEFORMAT_PCM32; default: break; } } return AMBIX_SAMPLEFORMAT_NONE; } static ambix_sampleformat_t coreaudio_setSampleformat(ambix_sampleformat_t sampleformat, AudioStreamBasicDescription*format, bool nativeEndian) { bool bigEndian=true; if(nativeEndian) bigEndian=( kAudioFormatFlagIsBigEndian == kAudioFormatFlagsNativeEndian); switch(sampleformat) { case(AMBIX_SAMPLEFORMAT_PCM16): format->mBitsPerChannel = 16; format->mFormatID=kAudioFormatLinearPCM; format->mFramesPerPacket=1; format->mBytesPerFrame=(format->mBitsPerChannel/8)*format->mChannelsPerFrame; format->mBytesPerPacket=format->mBytesPerFrame; format->mFormatFlags = coreaudio_getFlags (format->mBitsPerChannel, false, bigEndian); return sampleformat; case(AMBIX_SAMPLEFORMAT_PCM24): format->mBitsPerChannel = 24; format->mFormatID=kAudioFormatLinearPCM; format->mFramesPerPacket=1; format->mBytesPerFrame=(format->mBitsPerChannel/8)*format->mChannelsPerFrame; format->mBytesPerPacket=format->mBytesPerFrame; format->mFormatFlags = coreaudio_getFlags (format->mBitsPerChannel, false, bigEndian); return sampleformat; case(AMBIX_SAMPLEFORMAT_PCM32): format->mBitsPerChannel = 32; format->mFormatID=kAudioFormatLinearPCM; format->mFramesPerPacket=1; format->mBytesPerFrame=(format->mBitsPerChannel/8)*format->mChannelsPerFrame; format->mBytesPerPacket=format->mBytesPerFrame; format->mFormatFlags = coreaudio_getFlags (format->mBitsPerChannel, false, bigEndian); return sampleformat; case(AMBIX_SAMPLEFORMAT_FLOAT32): format->mBitsPerChannel = 32; format->mFormatID=kAudioFormatLinearPCM; format->mFramesPerPacket=1; format->mBytesPerFrame=(format->mBitsPerChannel/8)*format->mChannelsPerFrame; format->mBytesPerPacket=format->mBytesPerFrame; format->mFormatFlags = coreaudio_getFlags (format->mBitsPerChannel, true, bigEndian); return sampleformat; } return AMBIX_SAMPLEFORMAT_NONE; } static ambix_sampleformat_t coreaudio_setClientFormat(ambix_t*axinfo, ambix_sampleformat_t sampleformat) { OSStatus err = noErr; AudioStreamBasicDescription format; UInt32 formatsize=sizeof(format); if(sampleformat == PRIVATE(axinfo)->sampleformat) return sampleformat; err = ExtAudioFileGetProperty(PRIVATE(axinfo)->xfile, kExtAudioFileProperty_FileDataFormat, &formatsize, &format); if(noErr != err) return AMBIX_SAMPLEFORMAT_NONE; sampleformat = coreaudio_setSampleformat(sampleformat, &format, true); if(AMBIX_SAMPLEFORMAT_NONE == sampleformat) return AMBIX_SAMPLEFORMAT_NONE; err = ExtAudioFileSetProperty(PRIVATE(axinfo)->xfile, kExtAudioFileProperty_ClientDataFormat, sizeof(format), &format); if(noErr != err) return AMBIX_SAMPLEFORMAT_NONE; PRIVATE(axinfo)->sampleformat = sampleformat; return sampleformat; } static void ambix2coreaudio_info(const ambix_info_t*axinfo, AudioStreamBasicDescription*format, bool nativeEndian) { UInt32 channels=(UInt32)(axinfo->ambichannels+axinfo->extrachannels); memset(format, 0, sizeof(*format)); format->mChannelsPerFrame=channels; format->mSampleRate=(Float64)axinfo->samplerate; coreaudio_setSampleformat(axinfo->sampleformat, format, nativeEndian); } static ambix_err_t coreaudio2ambix_info(const ExtAudioFileRef cainfo, ambix_info_t*axinfo) { AudioStreamBasicDescription format; UInt32 datasize=0; SInt64 frames; datasize=sizeof(SInt64); if(noErr == ExtAudioFileGetProperty(cainfo, kExtAudioFileProperty_FileLengthFrames, &datasize, &frames)) { axinfo->frames=(uint64_t)frames; } datasize=sizeof(format); memset(&format, 0, sizeof(format)); if(noErr == ExtAudioFileGetProperty(cainfo, kExtAudioFileProperty_FileDataFormat, &datasize, &format)) { ambix_sampleformat_t sampleformat=coreaudio_getSampleformat(&format); if(AMBIX_SAMPLEFORMAT_NONE==sampleformat) return AMBIX_ERR_INVALID_FORMAT; axinfo->sampleformat = sampleformat; axinfo->samplerate = (double)format.mSampleRate; axinfo->extrachannels = format.mChannelsPerFrame; } return AMBIX_ERR_SUCCESS; } ambix_err_t _ambix_open_read(ambix_t*ambix, const char *path, const ambix_info_t*ambixinfo) { OSStatus err = noErr; ambixcoreaudio_private_t*priv=0; ambix->private_data=calloc(1, sizeof(ambixcoreaudio_private_t)); if(!ambix->private_data)return AMBIX_ERR_UNKNOWN; priv=(ambixcoreaudio_private_t*)ambix->private_data; priv->pool = [[NSAutoreleasePool alloc] init]; priv->data = [[AmbixData alloc] init]; if(!(priv->pool) || !(priv->data)) { _ambix_close(ambix); return AMBIX_ERR_UNKNOWN; } PRIVATE(ambix)->file=NULL; PRIVATE(ambix)->xfile=NULL; NSURL *inURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:path]]; err = AudioFileOpenURL((CFURLRef)inURL, 0x01, /* kAudioFileReadPermission, */ 0, &(PRIVATE(ambix)->file)); if(noErr!=err) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } err = ExtAudioFileWrapAudioFileID ( (PRIVATE(ambix)->file), false, &(PRIVATE(ambix)->xfile)); if(noErr!=err) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } if(NULL==(PRIVATE(ambix)->xfile)) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } memset(&ambix->realinfo, 0, sizeof(*ambixinfo)); if(AMBIX_ERR_SUCCESS!=coreaudio2ambix_info(PRIVATE(ambix)->xfile, &ambix->realinfo)) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } ambix->byteswap = !_coreaudio_isNativeEndian(PRIVATE(ambix)->xfile); ambix->channels = ambix->realinfo.extrachannels; /* FIXXXME: realinfo is a bad vehicle */ int caf=_coreaudio_isCAF(&PRIVATE(ambix)->file); int is_ambix=0; if(caf) { is_ambix=1; if(AMBIX_ERR_SUCCESS == read_uuidchunk(ambix)) { ambix->format=AMBIX_EXTENDED; } else { ambix->format=AMBIX_BASIC; } } else { ambix->format=AMBIX_NONE; } ambix->is_AMBIX=is_ambix; return AMBIX_ERR_SUCCESS; } ambix_err_t _ambix_open_write(ambix_t*ambix, const char *path, const ambix_info_t*ambixinfo) { int is_ambix=0; OSStatus err = noErr; ambixcoreaudio_private_t*priv=0; AudioStreamBasicDescription format; ambix2coreaudio_info(ambixinfo, &format, false); ambix->private_data=calloc(1, sizeof(ambixcoreaudio_private_t)); if(!ambix->private_data)return AMBIX_ERR_UNKNOWN; priv=(ambixcoreaudio_private_t*)ambix->private_data; priv->pool = [[NSAutoreleasePool alloc] init]; priv->data = [[AmbixData alloc] init]; if(!(priv->pool) || !(priv->data)) { _ambix_close(ambix); return AMBIX_ERR_UNKNOWN; } PRIVATE(ambix)->file=NULL; PRIVATE(ambix)->xfile=NULL; PRIVATE(ambix)->sampleformat=ambixinfo->sampleformat; if(ambixinfo->ambichannels>0) is_ambix=1; NSURL *inURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:path]]; err = AudioFileCreateWithURL((CFURLRef)inURL, kAudioFileCAFType, &format, kAudioFileFlags_EraseFile, /* FIXME?: 0 */ &(PRIVATE(ambix)->file)); if(noErr!=err) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } err = ExtAudioFileWrapAudioFileID ( (PRIVATE(ambix)->file), true, &(PRIVATE(ambix)->xfile)); if(noErr!=err) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } if(NULL==(PRIVATE(ambix)->xfile)) { _ambix_close(ambix); return AMBIX_ERR_INVALID_FILE; } ambix->is_AMBIX=is_ambix; ambix->byteswap = !_coreaudio_isNativeEndian(PRIVATE(ambix)->xfile); ambix->channels = format.mChannelsPerFrame; return AMBIX_ERR_SUCCESS; } ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo) { //printf("AMBIX: CoreAudio support\n"); if((mode & AMBIX_READ) & (mode & AMBIX_WRITE)) return AMBIX_ERR_INVALID_FILE; else if (mode & AMBIX_WRITE) return _ambix_open_write(ambix, path, ambixinfo); else if (mode & AMBIX_READ) return _ambix_open_read(ambix, path, ambixinfo); return AMBIX_ERR_INVALID_FILE; } ambix_err_t _ambix_close (ambix_t*ambix) { if(ambix&&ambix->private_data) { ambix_err_t err=AMBIX_ERR_SUCCESS; ambixcoreaudio_private_t*priv=(ambixcoreaudio_private_t*)ambix->private_data; /* FIRST close the file itself */ if(PRIVATE(ambix)) { if(PRIVATE(ambix)->xfile) ExtAudioFileDispose(PRIVATE(ambix)->xfile); PRIVATE(ambix)->xfile=NULL; if(PRIVATE(ambix)->file) AudioFileClose(PRIVATE(ambix)->file); PRIVATE(ambix)->file=NULL; [priv->data release]; } else { err=AMBIX_ERR_INVALID_FILE; } priv->data=NULL; /* SECOND release the autorelease pool... */ if(priv->pool) { [priv->pool release]; } else { err=AMBIX_ERR_INVALID_FILE; } priv->pool=NULL; /* LAST free the private data */ free(ambix->private_data); ambix->private_data=NULL; return err; } return AMBIX_ERR_INVALID_FILE; } int64_t coreaudio_readf(ambix_t*ambix, void*data, int64_t frames, ambix_sampleformat_t sampleformat, UInt32 bytespersample) { if(AMBIX_SAMPLEFORMAT_NONE == coreaudio_setClientFormat(ambix, sampleformat)) return -1; UInt32 readframes=(UInt32)frames; UInt32 channels = ambix->channels; AudioBufferList fillBufList; fillBufList.mNumberBuffers = 1; fillBufList.mBuffers[0].mNumberChannels = channels; fillBufList.mBuffers[0].mDataByteSize = frames * bytespersample * channels; fillBufList.mBuffers[0].mData = data; OSStatus err = ExtAudioFileRead (PRIVATE(ambix)->xfile, &readframes, &fillBufList); if(noErr != err)return -1; return (int64_t)readframes; } int64_t _ambix_readf_int16 (ambix_t*ambix, int16_t*data, int64_t frames) { return coreaudio_readf(ambix, data, frames, AMBIX_SAMPLEFORMAT_PCM16, 2); } int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames) { return coreaudio_readf(ambix, data, frames, AMBIX_SAMPLEFORMAT_PCM32, 4); } 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); //printf("realinfo:\n");_ambix_print_info(&ambix->realinfo); if(AMBIX_SAMPLEFORMAT_NONE == coreaudio_setClientFormat(ambix, sampleformat)) return -1; UInt32 writeframes=(UInt32)frames; UInt32 channels = ambix->channels; OSStatus err = noErr; AudioBufferList fillBufList; fillBufList.mNumberBuffers = 1; fillBufList.mBuffers[0].mNumberChannels = channels; fillBufList.mBuffers[0].mDataByteSize = frames * bytespersample * channels; fillBufList.mBuffers[0].mData = (void*)data; //printf("ambix_write: %d/%d channels\n", (int)ambix->info.ambichannels, (int)ambix->info.extrachannels); //printf("writing %d frames of %d channels (%d) in %p\n", (int)frames, (int)channels, (int)(fillBufList.mBuffers[0].mDataByteSize), data); err=ExtAudioFileWrite (PRIVATE(ambix)->xfile, writeframes, &fillBufList); if(noErr != err)return -1; return (int64_t)writeframes; } int64_t _ambix_writef_int16 (ambix_t*ambix, const int16_t*data, int64_t frames) { return coreaudio_writef(ambix, data, frames, AMBIX_SAMPLEFORMAT_PCM16, 2); } int64_t _ambix_writef_int32 (ambix_t*ambix, const int32_t*data, int64_t frames) { return coreaudio_writef(ambix, data, frames, AMBIX_SAMPLEFORMAT_PCM32, 4); } int64_t _ambix_writef_float32 (ambix_t*ambix, const float32_t*data, int64_t frames) { //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, 'uuid', index, datasize, data); if(noErr!=err) return AMBIX_ERR_UNKNOWN; return AMBIX_ERR_SUCCESS; } ambix_err_t _ambix_write_uuidchunk(ambix_t*ax, const void*data, int64_t datasize) { /* find a free slot and write UUID */ UInt32 index=0; OSStatus err = noErr; char*readdata=NULL; for(index=0; ; index++) { UInt32 size=0; UInt32 readdatasize=0; uint32_t chunkver=0; if(readdata) free(readdata); readdata=NULL; err = AudioFileGetUserDataSize ( PRIVATE(ax)->file, 'uuid', index, &size); if(noErr!=err) { if(readdata) free(readdata) ; readdata=NULL; /* there is no uuid-chunk[index], so we use it: */ return _ambix_write_uuidchunk_at(ax, index, data, datasize); } if(0==size) continue; readdatasize=size; data=calloc(readdatasize, sizeof(char)); if(!data)continue; err = AudioFileGetUserData ( PRIVATE(ax)->file, 'uuid', index, &readdatasize, readdata); if(noErr!=err) break; if(readdatasize<16) continue; chunkver=_ambix_checkUUID(readdata); switch(chunkver) { case(1): /* there is a valid ambix uuid-chunk[index], so we overwrite it: */ if(readdata) free(readdata) ; readdata=NULL; return _ambix_write_uuidchunk_at(ax, index, data, datasize); default: /* there is a uuid-chunk[index] but it's not ambix, so skip it */ break; } } if(readdata) free(readdata); data=NULL; return AMBIX_ERR_UNKNOWN; } static int64_t _ambix_tell(ambix_t*ambix) { SInt64 pos=0; OSStatus err = ExtAudioFileTell (PRIVATE(ambix)->xfile, &pos); if(noErr==err) return pos; else return -1; } int64_t _ambix_seek (ambix_t* ambix, int64_t frames, int whence) { OSStatus err=noErr; SInt64 inFrameOffset; int64_t offset=0; switch(whence) { case SEEK_SET: offset=0; break; case SEEK_END: offset=ambix->realinfo.frames; break; case SEEK_CUR: offset=_ambix_tell(ambix); break; default: return -1; } if(offset<0) return -1; inFrameOffset=frames+offset; err=ExtAudioFileSeek ( PRIVATE(ambix)->xfile, inFrameOffset); return _ambix_tell(ambix); } ambix-0.1.1/libambix/src/libambix.c000066400000000000000000000441101300077024200171150ustar00rootroot00000000000000/* libambix.c - AMBIsonics eXchange Library -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "private.h" #ifdef HAVE_STDLIB_H #include #endif /* HAVE_STDLIB_H */ #ifdef HAVE_STRING_H # include #endif /* HAVE_STRING_H */ /* forward declarations */ ambix_err_t _ambix_write_header (ambix_t*ambix); static ambix_err_t _check_write_ambixinfo(ambix_info_t*info) { /* FIXXME: rather than failing, we could force the values to be correct */ switch(info->fileformat) { case AMBIX_NONE: if(info->ambichannels>0) return AMBIX_ERR_INVALID_FORMAT; break; case AMBIX_BASIC: if(info->extrachannels>0) return AMBIX_ERR_INVALID_FORMAT; if(!ambix_is_fullset(info->ambichannels)) return AMBIX_ERR_INVALID_FORMAT; break; default: break; } return AMBIX_ERR_SUCCESS; } static void _ambix_info_set(ambix_t*ambix , ambix_fileformat_t format , int32_t otherchannels , int32_t ambichannels , int32_t fullambichannels ) { switch(format) { case AMBIX_NONE: ambichannels=fullambichannels=0; break; case AMBIX_BASIC: otherchannels=0; break; default: break; } ambix->realinfo.fileformat=format; ambix->realinfo.ambichannels=ambichannels; ambix->realinfo.extrachannels=otherchannels; 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=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 */ return NULL; } if(AMBIX_WRITE & mode) { err=_check_write_ambixinfo(ambixinfo); 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=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(ambixinfo->fileformat) { case(AMBIX_NONE): _ambix_info_set(ambix, AMBIX_NONE, channels, 0, 0); break; case(AMBIX_BASIC): _ambix_info_set(ambix, AMBIX_BASIC, 0, channels, channels); break; case(AMBIX_EXTENDED): /* the number of full channels is not clear yet! * the user MUST call set_adaptormatrix() first */ _ambix_info_set(ambix, AMBIX_EXTENDED, otherchannels, ambichannels, 0); break; } } else { if(ambix->format>AMBIX_BASIC) { /* check whether channels are (N+1)^2 * if so, we have a simple-ambix file, else it is just an ordinary caf */ if(ambix->matrix.cols <= channels && /* reduced set must be fully present */ ambix_is_fullset(ambix->matrix.rows)) { /* expanded set must be a full set */ /* it's a simple AMBIX! */ _ambix_info_set(ambix, AMBIX_EXTENDED, channels-ambix->matrix.cols, ambix->matrix.cols, ambix->matrix.rows); } else { /* ouch! matrix is not valid! */ _ambix_info_set(ambix, AMBIX_NONE, channels, 0, 0); } } else { /* no uuid chunk found, it's probably a BASIC ambix file */ /* check whether channels are (N+1)^2 * if so, we have a simple-ambix file, else it is just an ordinary caf */ if(ambix_is_fullset(channels)) { /* expanded set must be a full set */ /* it's a simple AMBIX! */ _ambix_info_set(ambix, AMBIX_BASIC, 0, channels, channels); } else { /* it's an ordinary CAF file */ _ambix_info_set(ambix, AMBIX_NONE, channels, 0, 0); } } } /* retrieve markers/regions/strings*/ _ambix_read_markersregions(ambix); } else { /* it's not a CAF file.... */ _ambix_info_set(ambix, AMBIX_NONE, channels, 0, 0); } haveformat=ambix->realinfo.fileformat; 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; ambix->use_matrix=1; ambix->info.ambichannels=ambix->matrix.rows; } else if(AMBIX_EXTENDED==wantformat && AMBIX_BASIC==haveformat) { ambix_matrix_init(ambix->realinfo.ambichannels, ambix->realinfo.ambichannels, &ambix->matrix); ambix_matrix_fill(&ambix->matrix, AMBIX_MATRIX_IDENTITY); ambix->info.fileformat=AMBIX_EXTENDED; ambix->use_matrix=0; } memcpy(ambixinfo, &ambix->info, sizeof(ambix->info)); if(_ambix_adaptorbuffer_resize(ambix, DEFAULT_ADAPTORBUFFER_SIZE, sizeof(float32_t)) == AMBIX_ERR_SUCCESS) return ambix; } ambix_close(ambix); return NULL; } ambix_err_t ambix_close (ambix_t*ambix) { ambix_err_t res=AMBIX_ERR_SUCCESS; if(NULL==ambix) { return AMBIX_ERR_INVALID_HANDLE; } if((ambix->filemode & AMBIX_WRITE) && ambix->pendingHeaders) { _ambix_write_header(ambix); } res=_ambix_close(ambix); _ambix_adaptorbuffer_destroy(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; } 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) { #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) { 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) { 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); if(mtx != &ambix->matrix2) return AMBIX_ERR_UNKNOWN; ambix->use_matrix=2; return AMBIX_ERR_SUCCESS; } else { if(matrix->cols != ambix->realinfo.ambichannels) { return AMBIX_ERR_INVALID_DIMENSION; } mtx=ambix_matrix_copy(matrix, &ambix->matrix2); if(mtx) { ambix->use_matrix=2; } else { return AMBIX_ERR_UNKNOWN; } } } 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; } return AMBIX_ERR_UNKNOWN; } ambix_err_t _ambix_write_header (ambix_t*ambix) { void*data=NULL; if(ambix->filemode & AMBIX_WRITE) { 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); uint64_t usedlen=1+datalen/sizeof(float32_t); if(datalen<1) return AMBIX_ERR_UNKNOWN; data=calloc(usedlen, sizeof(float32_t)); if(_ambix_matrix_to_uuid1(&ambix->matrix, data, ambix->byteswap)!=datalen) goto cleanup; /* and write it to file */ res=_ambix_write_uuidchunk(ambix, data, datalen); if(data) free(data); if(AMBIX_ERR_SUCCESS==res) 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; } } else return AMBIX_ERR_INVALID_FILE; cleanup: if(data) free(data); return AMBIX_ERR_UNKNOWN; } static ambix_err_t _ambix_check_write(ambix_t*ambix, const void*ambidata, const void*otherdata, int64_t frames) { /* TODO: add some checks whether writing is feasible * e.g. format=extended but no (or wrong) matrix present */ 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) return res; } ambix->startedWriting=1; return AMBIX_ERR_SUCCESS; } static ambix_err_t _ambix_check_read(ambix_t*ambix, const void*ambidata, const void*otherdata, int64_t frames) { /* 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) \ 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) { return (err>0)?-err:err;} \ err=_ambix_adaptorbuffer_resize(ambix, frames, sizeof(type##_t)); \ 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) { \ case 1: \ _ambix_splitAdaptormatrix_##type(adaptorbuffer, ambix->realinfo.ambichannels+ambix->realinfo.extrachannels, &ambix->matrix , ambidata, otherdata, realframes); \ break; \ case 2: \ _ambix_splitAdaptormatrix_##type(adaptorbuffer, ambix->realinfo.ambichannels+ambix->realinfo.extrachannels, &ambix->matrix2 , ambidata, otherdata, realframes); \ break; \ default: \ _ambix_splitAdaptor_##type (adaptorbuffer, ambix->realinfo.ambichannels+ambix->realinfo.extrachannels, ambix->realinfo.ambichannels, ambidata, otherdata, realframes); \ }; \ return realframes; \ } #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) { return (err>0)?-err:err;} \ err=_ambix_adaptorbuffer_resize(ambix, frames, sizeof(type##_t)); \ if(AMBIX_ERR_SUCCESS != err) { return (err>0)?-err:err;} \ adaptorbuffer=(type##_t*)ambix->adaptorbuffer; \ 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); ambix-0.1.1/libambix/src/marker_region_chunk.c000066400000000000000000000473601300077024200213540ustar00rootroot00000000000000/* marker_region_chunk.c - read/write marker and region chunk -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz Copyright © 2016 Matthias Kronlachner 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 . */ #include "private.h" #ifdef HAVE_STRING_H # include #endif /* HAVE_STRING_H */ #ifdef HAVE_STDLIB_H # include #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 */ #define AMBIX_MAKE_MARKER(a, b, c, d) ((uint32_t) ((((uint32_t) (a)) << 24) | ((b) << 16) | ((c) << 8) | (d))) typedef enum { kCAFMarkerType_Generic = 0, kCAFMarkerType_ProgramStart = AMBIX_MAKE_MARKER('p', 'b', 'e', 'g'), kCAFMarkerType_ProgramEnd = AMBIX_MAKE_MARKER('p', 'e', 'n', 'd'), kCAFMarkerType_TrackStart = AMBIX_MAKE_MARKER('t', 'b', 'e', 'g'), kCAFMarkerType_TrackEnd = AMBIX_MAKE_MARKER('t', 'e', 'n', 'd'), kCAFMarkerType_Index = AMBIX_MAKE_MARKER('i', 'n', 'd', 'x'), kCAFMarkerType_RegionStart = AMBIX_MAKE_MARKER('r', 'b', 'e', 'g'), kCAFMarkerType_RegionEnd = AMBIX_MAKE_MARKER('r', 'e', 'n', 'd'), kCAFMarkerType_RegionSyncPoint = AMBIX_MAKE_MARKER('r', 's', 'y', 'c'), kCAFMarkerType_SelectionStart = AMBIX_MAKE_MARKER('s', 'b', 'e', 'g'), kCAFMarkerType_SelectionEnd = AMBIX_MAKE_MARKER('s', 'e', 'n', 'd'), kCAFMarkerType_EditSourceBegin = AMBIX_MAKE_MARKER('c', 'b', 'e', 'g'), kCAFMarkerType_EditSourceEnd = AMBIX_MAKE_MARKER('c', 'e', 'n', 'd'), kCAFMarkerType_EditDestinationBegin = AMBIX_MAKE_MARKER('d', 'b', 'e', 'g'), kCAFMarkerType_EditDestinationEnd = AMBIX_MAKE_MARKER('d', 'e', 'n', 'd'), kCAFMarkerType_SustainLoopStart = AMBIX_MAKE_MARKER('s', 'l', 'b', 'g'), kCAFMarkerType_SustainLoopEnd = AMBIX_MAKE_MARKER('s', 'l', 'e', 'n'), kCAFMarkerType_ReleaseLoopStart = AMBIX_MAKE_MARKER('r', 'l', 'b', 'g'), kCAFMarkerType_ReleaseLoopEnd = AMBIX_MAKE_MARKER('r', 'l', 'e', 'n'), } kCAFMarkerType; // uint32_t /* individual marker struct */ typedef struct { kCAFMarkerType 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; inum_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_data) continue; 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))) { 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= 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++; } } 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_data) continue; 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))) { free(marker_data); break; } bytePtr = (unsigned char*)marker_data; bytePtr += 2*sizeof(uint32_t); for (i=0; imNumberMarkers; 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); } } 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_data) continue; 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)) { free(region_data); break; } bytePtr = (unsigned char*)region_data; data_read += 2*sizeof(uint32_t); // SIZEOF_CAFRegionChunk for (i=0; imNumberRegions; 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; jmNumberMarkers; 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); } } free(region_data); } } while(0); /* free allocated strings data */ if (mystrings.string_ids) free(mystrings.string_ids); for (i=0; imStringID = 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; uint32_t num_strings = ambix->num_markers+ambix->num_regions; void *strings_data = NULL; void *marker_data = NULL; void *region_data = NULL; uint32_t datasize_strings = 0; uint32_t datasize_markers = 0; uint32_t datasize_regions = 0; unsigned char* byte_ptr_strings = NULL; unsigned char* byte_ptr_stringid = NULL; int64_t byteoffset_strings = 0; CAFStrings *strings_chunk = NULL; /* reserve space for strings */ if (!num_strings) { return AMBIX_ERR_SUCCESS; } 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; inum_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 */ if (ambix->num_regions > 0) { // a region consists of 2 markers (start,end) and region chunk CAFRegionChunk* region_chunk = NULL; unsigned char* byte_ptr_regions = NULL; datasize_regions = 2*sizeof(uint32_t) + ambix->num_regions*(SIZEOF_CAFRegion + 2*sizeof(CAFMarker)); region_data = calloc(1, datasize_regions); region_chunk = (CAFRegionChunk*)region_data; 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; inum_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; } ambix-0.1.1/libambix/src/matrix.c000066400000000000000000000345461300077024200166460ustar00rootroot00000000000000/* matrix.c - Matrix handling -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "private.h" #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #include ambix_matrix_t* ambix_matrix_create(void) { return ambix_matrix_init(0, 0, NULL); } void ambix_matrix_destroy(ambix_matrix_t*mtx) { ambix_matrix_deinit(mtx); free(mtx); mtx=NULL; } void ambix_matrix_deinit(ambix_matrix_t*mtx) { uint32_t r; if(mtx->data) { for(r=0; rrows; r++) { if(mtx->data[r]) free(mtx->data[r]); mtx->data[r]=NULL; } } free(mtx->data); mtx->data=NULL; mtx->rows=0; mtx->cols=0; } ambix_matrix_t* ambix_matrix_init(uint32_t rows, uint32_t cols, ambix_matrix_t*orgmtx) { ambix_matrix_t*mtx=orgmtx; uint32_t r; if(!mtx) { mtx=(ambix_matrix_t*)calloc(1, sizeof(ambix_matrix_t)); if(!mtx) return NULL; mtx->data=NULL; } ambix_matrix_deinit(mtx); mtx->rows=rows; mtx->cols=cols; if(rows>0 && cols > 0) { mtx->data=(float32_t**)calloc(rows, sizeof(float32_t*)); for(r=0; rdata[r]=(float32_t*)calloc(cols, sizeof(float32_t)); } } return mtx; } ambix_matrix_t* _ambix_matrix_transpose(const ambix_matrix_t*matrix, ambix_matrix_t*xirtam) { uint32_t rows, cols, r, c; float32_t**mtx, **xtm; if(!xirtam) xirtam=ambix_matrix_init(matrix->cols, matrix->rows, NULL); rows=matrix->rows; cols=matrix->cols; mtx=matrix->data; xtm=xirtam->data; for(r=0; rdata; uint32_t rows=mtx->rows; uint32_t cols=mtx->cols; uint32_t r; const float*data=(const float*)ndata; for(r=0; rdata; uint32_t rows=mtx->rows; uint32_t cols=mtx->cols; uint32_t r; for(r=0; rcols, mtx->rows, NULL); if(!xtm) return AMBIX_ERR_UNKNOWN; if(byteswap) err=_ambix_matrix_fill_data_byteswapped(xtm, (const number32_t*)data); else err=ambix_matrix_fill_data(xtm, data); if(AMBIX_ERR_SUCCESS==err) { ambix_matrix_t*resu=_ambix_matrix_transpose(mtx, xtm); if(!resu) err=AMBIX_ERR_UNKNOWN; } ambix_matrix_destroy(xtm); return err; } #endif ambix_matrix_t* ambix_matrix_copy(const ambix_matrix_t*src, ambix_matrix_t*dest) { if(!src) return NULL; if(!dest) dest=(ambix_matrix_t*)calloc(1, sizeof(ambix_matrix_t)); if((dest->rows != src->rows) || (dest->cols != src->cols)) ambix_matrix_init(src->rows, src->cols, dest); do { uint32_t r, c; float32_t**s=src->data; float32_t**d=dest->data; for(r=0; rrows; r++) { for(c=0; ccols; c++) { d[r][c]=s[r][c]; } } } while(0); return dest; } ambix_matrix_t* _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; if(!left || !right) return NULL; if(left->cols != right->rows) return NULL; if(!dest) dest=(ambix_matrix_t*)calloc(1, sizeof(ambix_matrix_t)); if((dest->rows != left->rows) || (dest->cols != right->cols)) ambix_matrix_init(left->rows, right->cols, dest); rows=dest->rows; cols=dest->cols; common=left->cols; ldat=left->data; rdat=right->data; ddat=dest->data; for(r=0; rrows; int32_t cols=matrix->cols; int32_t r, c; float32_t**mtx=matrix->data; ambix_matrix_t*result=NULL; switch(typ) { default: return NULL; case (AMBIX_MATRIX_ZERO): for(r=0; r ACN/SN3D */ result=_matrix_fuma2ambix(cols); if(!result) return NULL; matrix=ambix_matrix_copy(result, matrix); break; case (AMBIX_MATRIX_TO_FUMA): /* Furse Malham -> ACN/SN3D */ result=_matrix_ambix2fuma(rows); if(!result) return NULL; matrix=ambix_matrix_copy(result, matrix); break; case (AMBIX_MATRIX_SID): /* SID -> ACN */ { float32_t*ordering=(float32_t*)malloc(rows*sizeof(float32_t)); if(!ordering) return NULL; if(!_matrix_sid2acn(ordering, rows)) { free(ordering); return NULL; } matrix=_matrix_router(matrix, ordering, rows, 0); free(ordering); } break; case (AMBIX_MATRIX_TO_SID): /* ACN -> SID */ { float32_t*ordering=(float32_t*)malloc(rows*sizeof(float32_t)); if(!_matrix_sid2acn(ordering, rows)) { free(ordering); return NULL; } matrix=_matrix_router(matrix, ordering, rows, 1); free(ordering); } break; case (AMBIX_MATRIX_N3D): /* N3D -> SN3D */ { float32_t*weights=NULL, *w_=NULL; int32_t counter=0; int32_t o=0, order=ambix_channels2order(rows); if(order<0) return NULL; weights=(float32_t*)malloc(rows*sizeof(float32_t)); w_=weights; for(o=0; o<=order; o++) { const float32_t w=(float32_t)(1./sqrt(2.*o+1.)); int32_t i; for(i=0; i<(2*o+1); i++) { *w_++=w; counter++; } } matrix=_matrix_diag(matrix, weights, rows); free(weights); } break; case (AMBIX_MATRIX_TO_N3D): /* SN3D -> N3D */ { float32_t*weights=NULL, *w_=NULL; int32_t counter=0; int32_t o, order=ambix_channels2order(rows); if(order<0) return NULL; weights=(float32_t*)malloc(rows*sizeof(float32_t)); w_=weights; for(o=0; o<=order; o++) { const float32_t w=(float32_t)(sqrt(2.*o+1.)); int32_t i; for(i=0; i<(2*o+1); i++) { *w_++=w; counter++; } } matrix=_matrix_diag(matrix, weights, rows); free(weights); } break; } if(result) ambix_matrix_destroy(result); return matrix; } 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 rowrows > 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); } } while (0); if(At) ambix_matrix_destroy(At); if(temp) ambix_matrix_destroy(temp); if(temp2)ambix_matrix_destroy(temp2); } return result; } #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; framedata; \ const uint32_t outchannels=matrix->rows; \ const uint32_t inchannels=matrix->cols; \ int64_t frame; \ for(frame=0; framedata[i][i]=diag[i]; return matrix; } ambix_matrix_t*_matrix_router(ambix_matrix_t*orgmatrix, const float32_t*route, uint32_t count, int swap) { uint32_t i; ambix_matrix_t*matrix=NULL; for(i=0; icount) return NULL; } matrix=ambix_matrix_init(count, count, orgmatrix); for(i=0; idata[o][i]=1.; else matrix->data[i][o]=1.; } return matrix; } ambix_matrix_t*_matrix_permutate(ambix_matrix_t*matrix, const float32_t*route, int swap) { uint32_t i; uint32_t count =swap?matrix->cols:matrix->rows; uint32_t maxroute=swap?matrix->rows:matrix->cols; for(i=0; imaxroute) return NULL; } for(i=0; i=-0.1) { uint32_t o=(uint32_t)route[i]; if(swap) matrix->data[o][i]=1.; else matrix->data[i][o]=1.; } } 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); } ambix-0.1.1/libambix/src/matrix_invert.c000066400000000000000000000161041300077024200202230ustar00rootroot00000000000000/* matrix_invert.c - utilities for matrix inversion -*- c -*- Copyright © 2016 IOhannes m zmölnig . 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 . */ #include "private.h" #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #include /** * 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-eps && diagel= 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 * \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 * \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; } ambix-0.1.1/libambix/src/null.c000066400000000000000000000043011300077024200162760ustar00rootroot00000000000000/* null.c - dummy backend support -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #include "private.h" 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) { return AMBIX_ERR_INVALID_FILE; } struct SNDFILE_tag*_ambix_get_sndfile (ambix_t*ambix) { return 0; } int64_t _ambix_readf_int16 (ambix_t*ambix, int16_t*data, int64_t frames) { return -1; } int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames) { return -1; } 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; } int64_t _ambix_writef_int32 (ambix_t*ambix, const int32_t*data, int64_t frames) { return -1; } 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; } int64_t _ambix_seek (ambix_t* ambix, int64_t frames, int whence) { return -1; } ambix-0.1.1/libambix/src/private.h000066400000000000000000000604001300077024200170050ustar00rootroot00000000000000/* private.h - AMBIsonics eXchange Library Private Interface -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ /** * @file private.h * @brief AMBIsonics eXchange Library Private Interface * @details This file is part of libambix * @author IOhannes m zmölnig * @date 2012 * @copyright LGPL-2.1 * @internal */ #ifndef AMBIX_PRIVATE_H #define AMBIX_PRIVATE_H #ifndef AMBIX_INTERNAL # error private.h must only be used from within libambix #endif #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #ifdef _MSC_VER # define inline __inline #endif #include /** this is for passing data about the opened ambix file between the host application and the library */ struct ambix_t_struct { /** private data by the actual backend */ void*private_data; /** whether the file is a valid AMBIX file (CAF) */ int is_AMBIX; /** whether the file has an UUID-chunk, and which AMBIX version it describs */ ambix_fileformat_t format; /** read/write mode */ ambix_filemode_t filemode; /** whether the file is byteswapped in relation to host */ int byteswap; /** full number of channels in the file */ int32_t channels; /** ambisonics info chunk as presented to the outside world */ ambix_info_t info; /** ambisonics info chunk as read from disk */ ambix_info_t realinfo; /** reconstruction matrix */ ambix_matrix_t matrix; /** final reconstruction matrix (potentially includes another adaptor matrix) */ ambix_matrix_t matrix2; /** whether to use the matrix(1), the finalmatrix(2), or no matrix when decoding */ int use_matrix; /** buffer for adaptor signals */ void*adaptorbuffer; /** size of the adaptor buffer (in bytes) */ uint64_t adaptorbuffersize; /** default adaptorbuffer size in frames */ #define DEFAULT_ADAPTORBUFFER_SIZE 64 /** 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 */ int startedWriting; /** whether we have pending headers to write */ int pendingHeaders; }; /** @brief Do open an ambix file * * this is implemented by the various backends (currently only libsndfile) * * @param ambix a pointer to an allocated ambix structure, that get's filled by this call * @param path filename of the file to open * @param mode open read/write * @param ambixinfo struct to a valid ambixinfo structure * @return errorcode indicating success */ ambix_err_t _ambix_open (ambix_t*ambix, const char *path, const ambix_filemode_t mode, const ambix_info_t*ambixinfo); /** @brief Do close an ambix file * * this is implemented by the various backends (currently only libsndfile) * * @param ambix a pointer to a valid ambix structure (has to be freed outside) * @return errorcode indicating success */ ambix_err_t _ambix_close (ambix_t*ambix); /** @brief seek in ambix-file * @param ambix The handle to an ambix file * @param frames frame offset from the position given in whence * @param whence location from where to seek; (see lseek) * @return the offset in (multichannel) frames from the start of the audio data or -1 if an error occurred */ int64_t _ambix_seek (ambix_t* ambix, int64_t frames, int whence); /** @brief Do get an libsndfile handle * * this is implemented by the various backends (currently only libsndfile) * * @param ambix a pointer to a valid ambix structure * @return an SNDFILE handle or NULL if not possible */ struct SNDFILE_tag*_ambix_get_sndfile (ambix_t*ambix); /** @brief read 32bit float data from file * @param ambix a pointer to a valid ambix structure * @param data pointer to an float32_t array that can hold at least frames*channels values * @param frames number of sample frames to read * @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 */ int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames); /** @see _ambix_readf_float32 * @remark this operates on 16bit integer data */ int64_t _ambix_readf_int16 (ambix_t*ambix, int16_t*data, int64_t frames); /** @brief write 32bit float data to file * @param ambix a pointer to a valid ambix structure * @param data pointer to an float32_t array that holds frames*channels values * @param frames number of sample frames to write * @return number of sample frames successfully written */ 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); /** @see _ambix_writef_float32 * @remark this operates on 16bit integer data */ int64_t _ambix_writef_int16 (ambix_t*ambix, const int16_t*data, int64_t frames); /** @brief Get UUID for ambix * @param ambix version * @return a pointer to the UUID for the given version or NULL * @remark currently only one UUID is defined for the ambix format (version 1) * future versions of the standard might add additional UUIDs */ const char* _ambix_getUUID(uint32_t version); /** @brief Check data for ambix UUID * @param data Array holding the UUID * @return ambix-version this UUID is associated with, or 0 on failure * @remark currently only one UUID is defined for the ambix format (version 1) * future versions of the standard might add additional UUIDs */ uint32_t _ambix_checkUUID(const char UUID[16]); /** @brief extract matrix from ambix UUID-chunk (v1) * @param data Array holding the payload data (excluding the UUID itself) * @param datasize size of data * @param mtx pointer to a matrix object that should be filled (if NULL, this function will allocate a matrix object for you) * @param byteswap TRUE if data has to be byteswapped (e.g. when reading BIG_ENDIAN data on LITTLE_ENDIAN machines) * @return a pointer to the filled matrix or NULL on failure * @remark only use data from a uuid-chunk for which _ambix_parseuuid() that returned '1' */ ambix_matrix_t*_ambix_uuid1_to_matrix(const void*data, uint64_t datasize, ambix_matrix_t*mtx, int byteswap); /** @brief generate UUID-chunk (v1) from matrix * @param matrix data to store in chunk * @param data pointer to memory to store the UUID-chunk in (or NULL) * @param byteswap TRUE if data has to be byteswapped (e.g. when reading BIG_ENDIAN data on LITTLE_ENDIAN machines) * @return datasize needed for the UUID-chunk * @remark you should call this two times: first with data=NULL, which will return the datasize you need to allocate; * then you allocate enough data (datasize bytes) and call the function again */ uint64_t _ambix_matrix_to_uuid1(const ambix_matrix_t*matrix, void*data, int byteswap); /** @brief write UUID chunk to file * @param ambix valid ambix handle * @param data pointer to memory holding the UUID-chunk * @param datasize size of data * @return error code indicating success * @remark you should only call this once, after opening the file and before writing sample frames to it */ 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 * * Fill data into a properly initialized matrix * * @param mtx initialized matrix object to copy data into * @param data pointer to at least (mtx->rows*mtx->cols) values; data is ordered row-by-row with no padding (A[0,0], A[0,1], .., A[0,cols-1], A[1, 0], .. A[rows-1, cols-1]) * @return an error code indicating success */ 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 * @return byte-swapped data */ 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 * * makes sure that the internal adaptorbuffer of ambix can hold at least * frames*(ambichannels+otherchannels) samples of size typesize * * @param ambix valid ambix handle * @param frames number of frames target buffer must be able to hold * @param typesize sizeof(sampletype) * @return error code indicating success */ ambix_err_t _ambix_adaptorbuffer_resize(ambix_t*ambix, uint64_t frames, uint16_t typesize); /** @brief free an adaptor buffer * @param ambix valid ambix handle * @return error code indicating success */ ambix_err_t _ambix_adaptorbuffer_destroy(ambix_t*ambix); /** @brief extract ambisonics and non-ambisonics channels from interleaved (32bit floating point) data * * extract the first ambichannels channels from the source into dest_ambi * the remaining source channels are written into dest_other * it is an error if ambichannels>sourcechannels (resulting in a negative number of non-ambisonics channels) * * @param source the interleaved samplebuffer to read from * @param sourcechannels the number of channels in the source * @param dest_ambi the ambisonics channels (interleaved) * @param ambichannels the number of ambisonics channels to extract * @param dest_other the non-ambisonics channels (interleaved) * @param frames number of frames to extract * @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 */ ambix_err_t _ambix_splitAdaptor_int32(const int32_t*source, uint32_t sourcechannels, uint32_t ambichannels, int32_t*dest_ambi, int32_t*dest_other, int64_t frames); /** @brief extract ambisonics and non-ambisonics channels from interleaved (16bit signed integer) data * @see _ambix_splitAdapator_float32 */ ambix_err_t _ambix_splitAdaptor_int16(const int16_t*source, uint32_t sourcechannels, uint32_t ambichannels, int16_t*dest_ambi, int16_t*dest_other, int64_t frames); /** @brief extract ambisonics and non-ambisonics channels from interleaved data using matrix operations * * extract matrix.rows ambisonics channels into dest_ambi by multiplying the matrix with matrix.cols source channels * the remaining source channels are written into dest_other * it is an error if matrix.cols>sourcechannels (resulting in a negative number of non-ambisonics channels) * * @param source the interleaved samplebuffer to read from * @param sourcechannels the number of channels in the source * @param dest_ambi the ambisonics channels (interleaved) * @param dest_other the non-ambisonics channels (interleaved) * @param frames number of frames to extract * @return error code indicating success */ 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); /** @brief merge two separate interleaved (32bit floating point) audio data blocks into one * * append ambisonics and non-ambisonics channels into one big interleaved chunk * * @param source1 the first interleaved samplebuffer to read from * @param source1channels the number of channels in source1 * @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*(source1channels+source2channels) samples * @param frames number of frames to extract * @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 */ ambix_err_t _ambix_mergeAdaptor_int32(const int32_t*source1, uint32_t source1channels, const int32_t*source2, uint32_t source2channels, int32_t*destination, int64_t frames); /** @brief merge two separate interleaved (16bit signed integer) audio data blocks into one * @see _ambix_mergeAdapator_float32 */ 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 */ void _ambix_print_info(const ambix_info_t*info); #define MARK() printf("%s:%d[%s]\n", __FILE__, __LINE__, __FUNCTION__) /** @brief create a diagonal matrix from a vector * @param orgmatrix pointer to the matrix object that will hold the result or NULL * @param diag array of count floats that will form the diagonal vector * @param count number of elements in diag * @return pointer to the resulting diagonal matrix, or NULL in case something went wrong */ ambix_matrix_t*_matrix_diag(ambix_matrix_t*orgmatrix, const float32_t*diag, uint32_t count); /** @brief create a permutation matrix * @param orgmatrix pointer to the matrix object that will hold the result or NULL * @param route permutation vector (if(route[1]==4)then{row#1 of output matrix will be [0 0 0 0 1 0 ...]} * @param count number of elements in route * @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 */ ambix_matrix_t*_matrix_router(ambix_matrix_t*orgmatrix, const float32_t*route, uint32_t count, int transpose); /** @brief create a permutation matrix * @param matrix pointer to a properly initialized matrix object that will hold the result * @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 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 */ ambix_matrix_t*_matrix_permutate(ambix_matrix_t*matrix, const float32_t*permutate, int swap); /** @brief calculate the permutation vector to convert from SID to ACN * @param data caller-allocated array of count elements that will hold the result * @param count number of elements in data * @result 1 on success, 0 if something went wrong (in which case the content of data is undefined */ int _matrix_sid2acn(float32_t*data, uint32_t count); /** @brief calculate the adaptor matrix to convert from FuMa to standard matrices * @param channels number of Furse-Malham channels that need to be converted to standard set (3, 4, 5, 6, 7, 8, 9, 11, 16) * @result an adaptor matrix (or NULL in case of failure); it's the responsibility of the caller to free the matrix * @see http://members.tripod.com/martin_leese/Ambisonic/B-Format_file_format.html */ ambix_matrix_t*_matrix_fuma2ambix(unsigned int channels); ambix_matrix_t*_matrix_ambix2fuma(unsigned int channels); #endif /* AMBIX_PRIVATE_H */ ambix-0.1.1/libambix/src/sndfile.c000066400000000000000000000371711300077024200167630ustar00rootroot00000000000000/* sndfile.c - libsndfile support -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . 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 . SF_UUID_ code is: Copyright © 2012 Christian Nachbar , Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz */ #include "private.h" #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ #ifdef HAVE_STRING_H # include #endif /* HAVE_STRING_H */ #ifdef HAVE_SNDFILE_H # include #endif /* HAVE_SNDFILE_H */ #ifdef _MSC_VER # define snprintf _snprintf #endif /* _MSC_VER */ //#define DEBUG_SFINFO typedef struct ambixsndfile_private_t { /** handle to the libsndfile object */ SNDFILE*sf_file; /** libsndfile info as returned by sf_open() */ SF_INFO sf_info; #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; static inline ambixsndfile_private_t*PRIVATE(ambix_t*ax) { return ((ambixsndfile_private_t*)(ax->private_data)); } static ambix_sampleformat_t sndfile2ambix_sampleformat(int sformat) { switch(sformat) { case(SF_FORMAT_PCM_16): return AMBIX_SAMPLEFORMAT_PCM16 ; 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; } static int ambix2sndfile_sampleformat(ambix_sampleformat_t asformat) { switch(asformat) { case(AMBIX_SAMPLEFORMAT_PCM16): return SF_FORMAT_PCM_16; 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)); printf(" samplerate\t: %d\n", info->samplerate); printf(" channels\t: %d\n", info->channels); printf(" format\t: %d\n", info->format); 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) { sfinfo->frames=axinfo->frames; sfinfo->samplerate=(int)axinfo->samplerate; sfinfo->channels=axinfo->ambichannels+axinfo->extrachannels; sfinfo->format=SF_FORMAT_CAF | ambix2sndfile_sampleformat(axinfo->sampleformat); sfinfo->sections=0; sfinfo->seekable=0; } static void sndfile2ambix_info(const SF_INFO*sfinfo, ambix_info_t*axinfo) { axinfo->frames=(uint64_t)sfinfo->frames; axinfo->samplerate=(double)(sfinfo->samplerate); axinfo->extrachannels=sfinfo->channels; axinfo->sampleformat=sndfile2ambix_sampleformat(sfinfo->format & SF_FORMAT_SUBMASK); } 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 ; 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 ; for(iterator = sf_get_chunk_iterator (file, &chunk_info); NULL!=iterator; iterator=sf_next_chunk_iterator (iterator)) { if(chunk_info.data) free(chunk_info.data); chunk_info.data=NULL; err = sf_get_chunk_size (iterator, &chunk_info) ; if(err != SF_ERR_NO_ERROR) { continue; } if(chunk_info.datalen<16) { continue; } chunk_info.data = malloc (chunk_info.datalen) ; if(!chunk_info.data) { return AMBIX_ERR_UNKNOWN; } err = sf_get_chunk_data (iterator, &chunk_info) ; if(err != SF_ERR_NO_ERROR) { continue; } 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)) { free(chunk_info.data); return AMBIX_ERR_SUCCESS; } } else continue; } if(chunk_info.data) free(chunk_info.data) ; 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; } } #endif return AMBIX_ERR_UNKNOWN; } 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; ambix->private_data=calloc(1, sizeof(ambixsndfile_private_t)); ambix2sndfile_info(ambixinfo, &PRIVATE(ambix)->sf_info); if((mode & AMBIX_READ) && (mode & AMBIX_WRITE)) sfmode= SFM_RDWR; else if (mode & AMBIX_WRITE) sfmode= SFM_WRITE; else if (mode & AMBIX_READ) sfmode= SFM_READ; PRIVATE(ambix)->sf_file=sf_open(path, sfmode, &PRIVATE(ambix)->sf_info) ; if(!PRIVATE(ambix)->sf_file) return AMBIX_ERR_INVALID_FILE; memset(&ambix->realinfo, 0, sizeof(*ambixinfo)); sndfile2ambix_info(&PRIVATE(ambix)->sf_info, &ambix->realinfo); ambix->byteswap=(sf_command(PRIVATE(ambix)->sf_file, SFC_RAW_DATA_NEEDS_ENDSWAP, NULL, 0) == SF_TRUE); ambix->channels = PRIVATE(ambix)->sf_info.channels; caf=((SF_FORMAT_CAF == (SF_FORMAT_TYPEMASK & PRIVATE(ambix)->sf_info.format)) != 0); if(caf) { is_ambix=1; if(read_uuidchunk(ambix) == AMBIX_ERR_SUCCESS) { ambix->format=AMBIX_EXTENDED; } else { ambix->format=AMBIX_BASIC; } } else { // check whether this is an .amb file or the like... if(0) { } else if(sf_command(PRIVATE(ambix)->sf_file, SFC_WAVEX_GET_AMBISONIC, NULL, 0) == SF_AMBISONIC_B_FORMAT) { /* The four B-format signals are interleaved for each sample frame in the order W,X,Y,Z. If the extended six-channel B-Format is used, the U and V signals will occupy the fifth and sixth slots: W,X,Y,Z,U,V. If horizontal-only B-format is to be represented, a three or five-channel file will suffice, with signals interleaved as W,X,Y (First Order), or W,X,Y,U,V (Second-order). However, four and -six-channel files are also acceptable, with the Z channel empty. Higher-order configurations are possible in theory, but are not addressed here. A decoder program should either 'degrade gracefully', or reject formats it cannot handle. For all B-format configurations, the dwChannelMask field should be set to zero. Though strictly speaking an optional chunk, it is recommended that the PEAK chunk be used for all B-Format files. Apart from its general utility, it has the special virtue for B-format in that applications can determine from the peak value for the Z channel whether the file is indeed full periphonic B-format (with height information), or 'Horizontal-only' (Z channel present but empty). */ switch(ambix->channels) { case 3: /* h = 1st order 2-D */ ambix_matrix_init(ambix_order2channels(1), ambix->channels, &ambix->matrix); break; case 4: /* f = 1st order 3-D */ ambix_matrix_init(ambix_order2channels(1), ambix->channels, &ambix->matrix); break; case 5: /* hh = 2nd order 2-D */ ambix_matrix_init(ambix_order2channels(2), ambix->channels, &ambix->matrix); break; case 6: /* fh = 2nd order 2-D + 1st order 3-D (formerly called 2.5 order) */ ambix_matrix_init(ambix_order2channels(2), ambix->channels, &ambix->matrix); break; case 7: /* hhh = 3rd order 2-D */ ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix); break; case 8: /* fhh = 3rd order 2-D + 1st order 3-D */ ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix); break; case 9: /* ff = 2nd order 3-D */ ambix_matrix_init(ambix_order2channels(2), ambix->channels, &ambix->matrix); break; case 11: /* ffh = 3rd order 2-D + 2nd order 3-D */ ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix); break; case 16: /* fff = 3rd order 3-D */ ambix_matrix_init(ambix_order2channels(3), ambix->channels, &ambix->matrix); break; } if(NULL != ambix_matrix_fill(&ambix->matrix, AMBIX_MATRIX_FUMA)) { is_ambix=1; ambix->format=AMBIX_EXTENDED; } else { is_ambix=0; ambix->format=AMBIX_NONE; } } else { is_ambix=0; ambix->format=AMBIX_NONE; } } ambix->is_AMBIX=is_ambix; #ifdef DEBUG_SFINFO print_sfinfo( &PRIVATE(ambix)->sf_info); #endif return AMBIX_ERR_SUCCESS; } 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; #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;isf_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)); return AMBIX_ERR_SUCCESS; } int64_t _ambix_seek (ambix_t* ambix, int64_t frames, int bias) { int whence=0; if(bias & AMBIX_RDRW) { whence |= SFM_RDWR; } else { whence |= (bias & AMBIX_READ )?SFM_READ:0; whence |= (bias & AMBIX_WRITE)?SFM_WRITE:0; } whence |= (bias & SEEK_SET); whence |= (bias & SEEK_CUR); whence |= (bias & SEEK_END); if(PRIVATE(ambix)->sf_file) return (int64_t)sf_seek(PRIVATE(ambix)->sf_file, (sf_count_t)frames, whence); return -1; } 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) { return (int64_t)sf_readf_short(PRIVATE(ambix)->sf_file, (short*)data, frames) ; } int64_t _ambix_readf_int32 (ambix_t*ambix, int32_t*data, int64_t frames) { return (int64_t)sf_readf_int(PRIVATE(ambix)->sf_file, (int*)data, 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) ; } int64_t _ambix_writef_int32 (ambix_t*ambix, const int32_t*data, int64_t frames) { return (int64_t)sf_writef_int(PRIVATE(ambix)->sf_file, (int*)data, 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 ; 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 ; 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) ; 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; } #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. 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 . */ #include "private.h" #include #include uint32_t ambix_order2channels(uint32_t order) { /* L=(N+1)^2 */ return (order+1)*(order+1); } int32_t ambix_channels2order(uint32_t channels) { /* L=(N+1)^2 */ int32_t order1=(int32_t)sqrt((double)channels); if(order1*order1==channels) { /* expanded set must be a full set */ return order1-1; } return -1; } int ambix_is_fullset(uint32_t channels) { return (ambix_order2channels(ambix_channels2order(channels))==channels); } void _ambix_print_info(const ambix_info_t*info) { printf("AMBIX_INFO %p\n", info); if(!info)return; printf(" frames\t: %d\n", (int)(info->frames)); printf(" samplerate\t: %f\n", info->samplerate); printf(" sampleformat\t: %d\n", info->sampleformat); printf(" fileformat\t: %d\n", info->fileformat); printf(" ambichannels\t: %d\n", info->ambichannels); printf(" otherchannels\t: %d\n", info->extrachannels); } void _ambix_print_matrix(const ambix_matrix_t*mtx) { printf("matrix %p", mtx); if(mtx) { float32_t**data=mtx->data; uint32_t r, c; printf(" [%dx%d] = %p\n", mtx->rows, mtx->cols, mtx->data); for(r=0; rrows; r++) { for(c=0; ccols; c++) { printf("%08f ", data[r][c]); } printf("\n"); } } printf("\n"); } 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; printf(" private\t: %p\n", ambix->private_data); printf(" is_AMBIX\t: %d\n", ambix->is_AMBIX); printf(" format\t: %d\n", ambix->format); printf(" filemode\t: %d\n", ambix->filemode); printf(" byteswap\t: %d\n", ambix->byteswap); printf(" channels\t: %d\n", ambix->channels); printf(" info\t:\n"); _ambix_print_info(&ambix->info); printf(" realinfo\t:\n"); _ambix_print_info(&ambix->realinfo); printf(" matrix\t:\n"); _ambix_print_matrix(&ambix->matrix); printf(" matrix2\t:\n"); _ambix_print_matrix(&ambix->matrix2); printf(" use_matrix\t: %d\n", ambix->use_matrix); 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); } void _ambix_swap4array(uint32_t*data, uint64_t datasize) { uint64_t i; for(i=0; i. 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 . */ #include "private.h" #ifdef HAVE_STRING_H # include #endif /* HAVE_STRING_H */ #ifdef HAVE_STDLIB_H # include #endif /* HAVE_STDLIB_H */ /* on UUIDs: * ideally, we would use UUIDs based on an URI that indicates the format-version * e.g. URI="http://ambisonics.iem.at/xchange/format/1.0" * this can be converted to an UUID(v5), using a small perl-script like * @code #!/usr/bin/perl use UUID::Tiny; my $v5_url_UUIDs = create_UUID_as_string(UUID_V5, UUID_NS_URL, $ARGV[0]); print "$v5_url_UUIDs\n"; * @endcode * * this gives us: * http://ambisonics.iem.at/xchange/format/1.0 1ad318c3-00e5-5576-be2d-0dca2460bc89 * http://ambisonics.iem.at/xchange/format/2.0 7c449194-05e1-58e4-9463-d0f8f2a1ed0f * http://ambisonics.iem.at/xchange/format/3.0 50c26359-d96d-5a67-bc19-db124f7606d0 */ #include #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; printf("-"); _ambix_printUUID4(data);data+=2; printf("-"); _ambix_printUUID4(data);data+=2; printf("-"); _ambix_printUUID4(data);data+=2; printf("-"); _ambix_printUUID4(data);data+=2; _ambix_printUUID4(data);data+=2; _ambix_printUUID4(data);data+=2; } #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" */ static const char _ambix_uuid_v1[]={0x1a, 0xd3, 0x18, 0xc3, 0x00, 0xe5, 0x55, 0x76, 0xbe, 0x2d, 0x0d, 0xca, 0x24, 0x60, 0xbc, 0x89}; const char* _ambix_getUUID(uint32_t version) { switch(version) { default: break; case 1: return _ambix_uuid_v1; } return NULL; } uint32_t _ambix_checkUUID(const char data[16]) { if(!memcmp(data, _ambix_uuid_v1, 16)) return 1; /* compat mode: old AMBIXv1 UUID */ if(!memcmp(data, _ambix_uuid_v1_, 16)) return 1; return 0; } ambix_matrix_t* _ambix_uuid1_to_matrix(const void*vdata, uint64_t datasize, ambix_matrix_t*orgmtx, int swap) { const char*cdata=(const char*)vdata; ambix_matrix_t*mtx=orgmtx; uint32_t rows; uint32_t cols; uint64_t size; uint32_t index; if(datasize<(sizeof(rows)+sizeof(cols))) return NULL; index = 0; memcpy(&rows, cdata+index, sizeof(uint32_t)); index += sizeof(uint32_t); memcpy(&cols, cdata+index, sizeof(uint32_t)); index += sizeof(uint32_t); if(swap) { rows=swap4(rows); cols=swap4(cols); } size=(uint64_t)rows*cols; if(rows<1 || cols<1 || size < 1) goto cleanup; if(size*sizeof(float32_t) > datasize) { goto cleanup; } if(!mtx) { mtx=(ambix_matrix_t*)calloc(1, sizeof(ambix_matrix_t)); if(!mtx) goto cleanup; } if(!ambix_matrix_init(rows, cols, mtx)) goto cleanup; if(swap) { if(_ambix_matrix_fill_data_byteswapped(mtx, (number32_t*)(cdata+index)) != AMBIX_ERR_SUCCESS) goto cleanup; } else { if(ambix_matrix_fill_data(mtx, (float32_t*)(cdata+index)) != AMBIX_ERR_SUCCESS) goto cleanup; } return mtx; cleanup: if(mtx && mtx!=orgmtx) { ambix_matrix_deinit(mtx); free(mtx); mtx=NULL; } return NULL; } uint64_t _ambix_matrix_to_uuid1(const ambix_matrix_t*matrix, void*vdata, int swap) { char*cdata=(char*)vdata; const char*uuid=_ambix_getUUID(1); uint64_t index=0; uint64_t datasize=0; uint32_t rows=matrix->rows; uint32_t cols=matrix->cols; float32_t**mtx=matrix->data; if(!uuid) return 0; datasize+=16; /* reserved for the UUID */ datasize+=sizeof(uint32_t); /* rows */ datasize+=sizeof(uint32_t); /* cols */ datasize+=(uint64_t)rows*(uint64_t)cols*sizeof(float32_t); /* data */ if(vdata) { uint32_t*uidata=(uint32_t*)vdata; uint64_t r; uint32_t*swapdata; uint64_t elements=(uint64_t)rows*(uint64_t)cols; memcpy(cdata, uuid, 16); index+=16; //swapdata=cdata+index; swapdata=uidata+(index / sizeof(uint32_t)); memcpy(cdata+index, &rows, sizeof(uint32_t)); index+=sizeof(uint32_t); memcpy(cdata+index, &cols, sizeof(uint32_t)); index+=sizeof(uint32_t); for(r=0; rframes != 44100, __LINE__, "Frames are not correct"); fail_if (info->samplerate != 44100, __LINE__, "Samplerate is not correct"); fail_if (info->sampleformat != AMBIX_SAMPLEFORMAT_FLOAT32, __LINE__, "Sampleformat is not correct"); fail_if (info->fileformat != AMBIX_BASIC, __LINE__, "Fileformat is not correct"); fail_if (info->ambichannels != 9, __LINE__, "Ambichannels are not correct"); fail_if (info->extrachannels != 0, __LINE__, "Non-ambichannels are not correct"); fail_if (NULL!=ambix_get_adaptormatrix(ambix), __LINE__, "Error, there is reconstruction matrix"); ambix_close (ambix); free(info); return 0; } ambix-0.1.1/libambix/tests/ambix_readf_int16.c000066400000000000000000000001221300077024200211560ustar00rootroot00000000000000#include "common.h" int main () { /* FIXXME: no test yet */ return skip(); } ambix-0.1.1/libambix/tests/ambix_seek.c000066400000000000000000000007251300077024200200140ustar00rootroot00000000000000#include "common.h" #include "data.h" int main() { int result=0; ambix_t *ambix = NULL; ambix_info_t *info= calloc(1, sizeof(ambix_info_t)); ambix=ambix_open(AMBIXTEST_FILE1, AMBIX_READ, info); skip_if(NULL==ambix, __LINE__, "ambix_open(%s, AMBIX_READ, info)", AMBIXTEST_FILE1); result= ambix_seek (ambix, 100, SEEK_CUR); fail_if (result!=100, __LINE__, "File failed to seek correct data"); ambix_close(ambix); free(info); return 0; } ambix-0.1.1/libambix/tests/ambix_seek_read.c000066400000000000000000000015471300077024200210120ustar00rootroot00000000000000#include "common.h" #include "data.h" int main() { ambix_t *ambix = NULL; ambix_info_t *info= calloc(1, sizeof(ambix_info_t)); int32_t ambidata[100]; int32_t *otherdata= 0; int result=0; int cmp=0; ambix=ambix_open(AMBIXTEST_FILE1, AMBIX_READ, info); //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. //UNCOMMENT WHEN FIXED /*cmp= ambix_readf_int32(ambix, *ambidata, otherdata, 100); printf("rezultat readf-a je %d\n", cmp); result= ambix_seek (ambix, 100, SEEK_CUR); if (cmp!=result) { printf ("Greska u potrazi\n"); } else fail_if (result!=100, __LINE__, "File failed to seek correct data");*/ ambix_close(ambix); free(info); /* FIXXXME: this test is not working yet */ return skip(); } ambix-0.1.1/libambix/tests/ambix_writef_int16.c000066400000000000000000000014301300077024200214000ustar00rootroot00000000000000#include "common.h" #include "data.h" int main () { ambix_t *ambix = NULL; ambix_info_t *info= calloc(1, sizeof(ambix_info_t)); int16_t *ambidata= 0; int16_t *otherdata=0; int16_t frames= 10; ambix=ambix_open(AMBIXTEST_FILE1, AMBIX_READ, info); int16_t result=0; /* ambix_writef_int16 (ambix_t *ambix, const int16_t *ambidata, const int16_t *otherdata, int64_t frames) Write (16bit signed integer) samples to the ambix file. Returns: the number of sample frames successfully written */ // UNCOMMENT WHEN FIXED /*result=ambix_writef_int16 (ambix,ambidata,otherdata,frames); fail_if (frames!=result, __LINE__, "Files were not written successfully"); */ ambix_close(ambix); free(info); /* FIXXME: no test yet */ return skip(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_3extra_float32.c000066400000000000000000000012471300077024200245610ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_3extra_float64.c000066400000000000000000000012471300077024200245660ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_3extra_pcm16.c000066400000000000000000000012451300077024200242330ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_3extra_pcm32.c000066400000000000000000000012451300077024200242310ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_float32.c000066400000000000000000000012471300077024200232730ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_float64.c000066400000000000000000000012471300077024200233000ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_pcm16.c000066400000000000000000000012451300077024200227450ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_FUMA4x4_pcm32.c000066400000000000000000000012451300077024200227430ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_3extra_float32.c000066400000000000000000000012471300077024200244150ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_3extra_float64.c000066400000000000000000000012471300077024200244220ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_3extra_pcm16.c000066400000000000000000000012451300077024200240670ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_3extra_pcm32.c000066400000000000000000000012451300077024200240650ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_float32.c000066400000000000000000000012471300077024200231270ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_float64.c000066400000000000000000000012471300077024200231340ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_pcm16.c000066400000000000000000000012451300077024200226010ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_N3D4x4_pcm32.c000066400000000000000000000012451300077024200225770ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_3extra_float32.c000066400000000000000000000012441300077024200244450ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_3extra_float64.c000066400000000000000000000012441300077024200244520ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_3extra_pcm16.c000066400000000000000000000012451300077024200241220ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_3extra_pcm32.c000066400000000000000000000012451300077024200241200ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_float32.c000066400000000000000000000012441300077024200231570ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_float64.c000066400000000000000000000012441300077024200231640ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_pcm16.c000066400000000000000000000012451300077024200226340ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_SID4x4_pcm32.c000066400000000000000000000012451300077024200226320ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_3extra_float32.c000066400000000000000000000012441300077024200256570ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_3extra_float64.c000066400000000000000000000012441300077024200256640ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_3extra_pcm16.c000066400000000000000000000012451300077024200253340ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_3extra_pcm32.c000066400000000000000000000012451300077024200253320ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_float32.c000066400000000000000000000016251300077024200243740ustar00rootroot00000000000000#include "common_basic2extended.h" #ifndef FMT # define FMT FLOAT32 #endif #ifndef EPS # define EPS 0 #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, EPS, FMT); err+=test_defaultmatrix("IDENTITY0000:" STRINGIFY(FMT), 4, 4, AMBIX_MATRIX_IDENTITY, 0, 0, EPS, FMT); return pass(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_float32__f64.c000066400000000000000000000001251300077024200252040ustar00rootroot00000000000000#define FMT FLOAT64 #define EPS 2e-8 #include "basic2extended_identity4x4_float32.c" ambix-0.1.1/libambix/tests/basic2extended_identity4x4_float32__i16.c000066400000000000000000000001021300077024200251770ustar00rootroot00000000000000#define FMT INT16 #include "basic2extended_identity4x4_float32.c" ambix-0.1.1/libambix/tests/basic2extended_identity4x4_float32__i32.c000066400000000000000000000001241300077024200252010ustar00rootroot00000000000000#define FMT INT32 #define EPS 1e-8 #include "basic2extended_identity4x4_float32.c" ambix-0.1.1/libambix/tests/basic2extended_identity4x4_float64.c000066400000000000000000000012441300077024200243760ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_pcm16.c000066400000000000000000000012451300077024200240460ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_identity4x4_pcm32.c000066400000000000000000000012451300077024200240440ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_3extra_float32.c000066400000000000000000000017201300077024200247540ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_3extra_float64.c000066400000000000000000000017201300077024200247610ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_3extra_pcm16.c000066400000000000000000000017161300077024200244350ustar00rootroot00000000000000#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, 8e-5); return pass(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_3extra_pcm32.c000066400000000000000000000017161300077024200244330ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_float32.c000066400000000000000000000017201300077024200234660ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_float64.c000066400000000000000000000017201300077024200234730ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_pcm16.c000066400000000000000000000017161300077024200231470ustar00rootroot00000000000000#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, 8e-5); return pass(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x7_pcm32.c000066400000000000000000000017161300077024200231450ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_3extra_float32.c000066400000000000000000000020501300077024200247530ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_3extra_float64.c000066400000000000000000000020501300077024200247600ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_3extra_pcm16.c000066400000000000000000000020461300077024200244340ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_3extra_pcm32.c000066400000000000000000000020461300077024200244320ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_float32.c000066400000000000000000000020501300077024200234650ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_float64.c000066400000000000000000000020501300077024200234720ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_pcm16.c000066400000000000000000000020461300077024200231460ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic2extended_rand4x9_pcm32.c000066400000000000000000000020461300077024200231440ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic_float32.c000066400000000000000000000003511300077024200203130ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic_float64.c000066400000000000000000000003511300077024200203200ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic_pcm16.c000066400000000000000000000003541300077024200177720ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/basic_pcm32.c000066400000000000000000000003471300077024200177720ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/common.c000066400000000000000000000236421300077024200172000ustar00rootroot00000000000000/* common test functionality Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #ifdef HAVE_UNISTD_H # include #endif #include #include #ifdef DBL_DECIMAL_DIG #define OP_DBL_Digs (DBL_DECIMAL_DIG) #else #ifdef DECIMAL_DIG #define OP_DBL_Digs (DECIMAL_DIG) #else #define OP_DBL_Digs (DBL_DIG + 3) #endif #endif 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[%p] ", mtx); printf(" [%dx%d]@%p\n[\n", mtx->rows, mtx->cols, mtx->data); if(mtx->data) { uint32_t c, r; for(r=0; rrows; r++) { for(c=0; ccols; c++) printf(" %.*e", OP_DBL_Digs - 1, mtx->data[r][c]); printf("\n"); } } printf("]\n"); } #define MAX_OVER 10 float32_t matrix_diff(uint32_t line, const ambix_matrix_t*A, const ambix_matrix_t*B, float32_t eps) { uint32_t r, c; float32_t sum=0.; float32_t maxdiff=-1.f; uint64_t overcount=0; float32_t**a=NULL; float32_t**b=NULL; fail_if((NULL==A), line, "left-hand matrix of matrixdiff is NULL"); fail_if((NULL==B), line, "right-hand matrix of matrixdiff is NULL"); fail_if(((A->rows!=B->rows) || (A->cols!=B->cols)), line, "matrixdiff matrices do not match [%dx%d]!=[%dx%d]", A->rows, A->cols, B->rows, B->cols); a=A->data; b=B->data; for(r=0; rrows; r++) for(c=0; ccols; c++) { float32_t v=a[r][c]-b[r][c]; float32_t vabs=(v<0)?-v:v; if(isnan(v))return v; if(vabs>maxdiff) maxdiff=vabs; sum+=vabs; if(vabs>eps) { overcount++; if(overcountMAX_OVER) 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, 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 %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(overcountMAX_OVER) printf("[%d] accumulated error %f over %d/%d frames (eps=%g)\n", line, sum, (int)overcount, (int)frames, eps); return maxdiff; } void data_print(ambixtest_presentationformat_t fmt, const void*data, uint64_t frames) { uint64_t i; char out[16]; for(i=0; i. 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 . */ #ifndef TESTS_COMMON_H #define TESTS_COMMON_H #include #ifdef HAVE_CONFIG_H # include "config.h" #endif #include 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 #include #define MARK() printf("%s:%d[%s]\n", __FILE__, __LINE__, __FUNCTION__) static inline int pass_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 pass(); } ; return test; } /* pass_if */ static inline int skip_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 skip(); } ; return test; } /* skip_if */ static inline int fail_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 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(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); 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 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 */ ambix-0.1.1/libambix/tests/common_basic.c000066400000000000000000000076451300077024200203460ustar00rootroot00000000000000/* simple - test ambix simple Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include void check_create_simple(const char*path, ambix_sampleformat_t format, float32_t eps) { ambix_info_t info, rinfo, winfo; ambix_t*ambix=NULL; float32_t*orgdata,*data,*resultdata; uint32_t frames=441000; uint32_t channels=4; float32_t periods=4724; int64_t err64; float32_t diff=0.; uint32_t gotframes; printf("test using '%s' [%d]\n", path, (int)format); resultdata=(float32_t*)calloc(channels*frames, sizeof(float32_t)); data=(float32_t*)calloc(channels*frames, sizeof(float32_t)); memset(&winfo, 0, sizeof(winfo)); memset(&info, 0, sizeof(info)); info.fileformat=AMBIX_BASIC; info.ambichannels=channels; info.extrachannels=0; info.samplerate=44100; info.sampleformat=format; memcpy(&rinfo, &info, sizeof(info)); ambix=ambix_open(path, AMBIX_WRITE, &rinfo); fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path); orgdata=data_sine(FLOAT32, frames, channels, periods); //data_print(FLOAT32, orgdata, 100); memcpy(data, orgdata, frames*channels*sizeof(float32_t)); fail_if((NULL==data), __LINE__, "couldn't create data %dx%d sine @ %f", (int)frames, (int)channels, (float)periods); 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__, 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); ambix=NULL; ambix=ambix_open(path, AMBIX_READ, &rinfo); fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for reading", path); fail_if((info.fileformat!=rinfo.fileformat), __LINE__, "fileformat mismatch %d!=%d", (int)info.fileformat, (int)rinfo.fileformat); fail_if((info.samplerate!=rinfo.samplerate), __LINE__, "samplerate mismatch %g!=%g", (float)info.samplerate, (float)rinfo.samplerate); fail_if((info.sampleformat!=rinfo.sampleformat), __LINE__, "sampleformat mismatch %d!=%d", (int)info.sampleformat, (int)rinfo.sampleformat); fail_if((info.ambichannels!=rinfo.ambichannels), __LINE__, "ambichannels mismatch %d!=%d", (int)info.ambichannels, (int)rinfo.ambichannels); fail_if((info.extrachannels!=rinfo.extrachannels), __LINE__, "extrachannels mismatch %d!=%d", (int)info.extrachannels, (int)rinfo.extrachannels); gotframes=0; do { err64=ambix_readf_float32(ambix, resultdata+(gotframes*channels), NULL, (frames-gotframes)); fail_if((err64<0), __LINE__, "reading frames failed after %d/%d frames", (int)gotframes, (int)frames); gotframes+=err64; } while(err64>0 && gotframeseps), __LINE__, "data diff %f > %f", diff, eps); fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix); ambix=NULL; free(data); free(resultdata); free(orgdata); ambixtest_rmfile(path); } ambix-0.1.1/libambix/tests/common_basic2extended.c000066400000000000000000000222621300077024200221410ustar00rootroot00000000000000/* common_simple2exetended - common function for writing extended files as simple files Copyright © 2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include 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; 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)); ambix=ambix_open(path, AMBIX_WRITE, &winfo); if(fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path))return 1; 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; frameeps), __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 && gotframeseps), __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 && gotframeseps), __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; } ambix-0.1.1/libambix/tests/common_basic2extended.h000066400000000000000000000025401300077024200221430ustar00rootroot00000000000000/* tests/common_basic2extended.h - AMBIsonics eXchange Library test utilities -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #ifndef TESTS_COMMON_BASIC2EXTENDED_H #define TESTS_COMMON_BASIC2EXTENDED_H #include "common.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); #endif /* TESTS_COMMON_BASIC2EXTENDED_H */ ambix-0.1.1/libambix/tests/common_extended.c000066400000000000000000000152061300077024200210550ustar00rootroot00000000000000/* extended - test ambix extended Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include void check_create_extended(const char*path, ambix_sampleformat_t format, uint32_t chunksize, float32_t eps) { ambix_info_t info, rinfo, winfo; ambix_t*ambix=NULL; float32_t*orgambidata,*ambidata,*resultambidata; float32_t*orgotherdata,*otherdata,*resultotherdata; uint32_t framesize=441000; uint32_t ambichannels=4; uint32_t extrachannels=2; float32_t periods=20000; ambix_matrix_t eye={0,0,NULL}; const ambix_matrix_t*eye2=NULL; int64_t err64, gotframes; float32_t diff=0.; STARTTEST("\n"); printf("test using '%s' [%d] with chunks of %d and eps=%f\n", path, (int)format, (int)chunksize, eps); resultambidata=(float32_t*)calloc(ambichannels*framesize, sizeof(float32_t)); ambidata=(float32_t*)calloc(ambichannels*framesize, sizeof(float32_t)); resultotherdata=(float32_t*)calloc(extrachannels*framesize, sizeof(float32_t)); otherdata=(float32_t*)calloc(extrachannels*framesize, sizeof(float32_t)); ambix_matrix_init(ambichannels, ambichannels, &eye); ambix_matrix_fill(&eye, AMBIX_MATRIX_IDENTITY); memset(&winfo, 0, sizeof(winfo)); memset(&info, 0, sizeof(info)); info.fileformat=AMBIX_EXTENDED; info.ambichannels=ambichannels; info.extrachannels=extrachannels; info.samplerate=44100; info.sampleformat=format; memcpy(&rinfo, &info, sizeof(info)); ambix=ambix_open(path, AMBIX_WRITE, &rinfo); fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path); 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); memcpy(ambidata, orgambidata, framesize*ambichannels*sizeof(float32_t)); memcpy(otherdata, orgotherdata, framesize*extrachannels*sizeof(float32_t)); fail_if((AMBIX_ERR_SUCCESS!=ambix_set_adaptormatrix(ambix, &eye)), __LINE__, "failed setting adaptor matrix"); if(chunksize>0) { uint32_t subframe=chunksize; uint32_t chunks = framesize/chunksize; uint32_t framesleft=framesize; uint32_t frame; printf("writing %d chunks of %d frames\n", (int)chunks, (int)chunksize); for(frame=0; frameeps), __LINE__, "ambidata diff %f > %f", diff, 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); ambix=NULL; /* read data back */ ambix=ambix_open(path, AMBIX_READ, &rinfo); fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for reading", path); fail_if((info.fileformat!=rinfo.fileformat), __LINE__, "fileformat mismatch %d!=%d", (int)info.fileformat, (int)rinfo.fileformat); fail_if((info.samplerate!=rinfo.samplerate), __LINE__, "samplerate mismatch %g!=%g", (float)info.samplerate, (float)rinfo.samplerate); fail_if((info.sampleformat!=rinfo.sampleformat), __LINE__, "sampleformat mismatch %d!=%d", (int)info.sampleformat, (int)rinfo.sampleformat); fail_if((info.ambichannels!=rinfo.ambichannels), __LINE__, "ambichannels mismatch %d!=%d", (int)info.ambichannels, (int)rinfo.ambichannels); fail_if((info.extrachannels!=rinfo.extrachannels), __LINE__, "extrachannels mismatch %d!=%d", (int)info.extrachannels, (int)rinfo.extrachannels); eye2=ambix_get_adaptormatrix(ambix); fail_if((NULL==eye2), __LINE__, "failed reading adaptor matrix"); diff=matrix_diff(__LINE__, &eye, eye2, eps); fail_if((diff>eps), __LINE__, "adaptormatrix diff %f > %f", diff, eps); gotframes=0; do { //err64=ambix_readf_float32(ambix, resultambidata, resultotherdata, framesize); err64=ambix_readf_float32(ambix, resultambidata +(gotframes*ambichannels ), resultotherdata+(gotframes*extrachannels), (framesize-gotframes)); fail_if((err64<0), __LINE__, "reading frames failed after %d/%d frames", (int)gotframes, (int)framesize); gotframes+=err64; } while(err64>0 && gotframeseps), __LINE__, "ambidata diff %f > %f", diff, 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); ambix=NULL; free(resultambidata); free(ambidata); free(resultotherdata); free(otherdata); free(orgambidata); free(orgotherdata); ambix_matrix_deinit(&eye); ambixtest_rmfile(path); } ambix-0.1.1/libambix/tests/common_none.c000066400000000000000000000075261300077024200202220ustar00rootroot00000000000000/* none - test ambix none Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include void check_create_none(const char*path, ambix_sampleformat_t format) { ambix_info_t info, rinfo, winfo; ambix_t*ambix=NULL; float32_t*orgdata,*data,*resultdata; uint32_t frames=44100; uint32_t channels=6; float32_t periods=10; int64_t err64, gotframes; float32_t diff=0., eps=1e-30; resultdata=(float32_t*)calloc(channels*frames, sizeof(float32_t)); data=(float32_t*)calloc(channels*frames, sizeof(float32_t)); memset(&winfo, 0, sizeof(winfo)); memset(&info, 0, sizeof(info)); info.fileformat=AMBIX_NONE; info.ambichannels=0; info.extrachannels=channels; info.samplerate=44100; info.sampleformat=format; memcpy(&rinfo, &info, sizeof(info)); ambix=ambix_open(path, AMBIX_WRITE, &rinfo); fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for writing", path); orgdata=data_sine(FLOAT32, frames, channels, periods); //data_print(FLOAT32, orgdata, 100); memcpy(data, orgdata, frames*channels*sizeof(float32_t)); fail_if((NULL==data), __LINE__, "couldn't create data %dx%d sine @ %f", (int)frames, (int)channels, (float)periods); 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__, 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); ambix=NULL; ambix=ambix_open(path, AMBIX_READ, &rinfo); fail_if((NULL==ambix), __LINE__, "couldn't create ambix file '%s' for reading", path); fail_if((info.fileformat!=rinfo.fileformat), __LINE__, "fileformat mismatch %d!=%d", (int)info.fileformat, (int)rinfo.fileformat); fail_if((info.samplerate!=rinfo.samplerate), __LINE__, "samplerate mismatch %g!=%g", (float)info.samplerate, (float)rinfo.samplerate); fail_if((info.sampleformat!=rinfo.sampleformat), __LINE__, "sampleformat mismatch %d!=%d", (int)info.sampleformat, (int)rinfo.sampleformat); fail_if((info.ambichannels!=rinfo.ambichannels), __LINE__, "ambichannels mismatch %d!=%d", (int)info.ambichannels, (int)rinfo.ambichannels); fail_if((info.extrachannels!=rinfo.extrachannels), __LINE__, "extrachannels mismatch %d!=%d", (int)info.extrachannels, (int)rinfo.extrachannels); gotframes=0; do { err64=ambix_readf_float32(ambix, NULL, resultdata+(gotframes*channels), (frames-gotframes)); fail_if((err64<0), __LINE__, "reading frames failed after %d/%d frames", (int)gotframes, (int)frames); gotframes+=err64; } while(err64>0 && gotframeseps), __LINE__, "data diff %f > %f", diff, eps); fail_if((AMBIX_ERR_SUCCESS!=ambix_close(ambix)), __LINE__, "closing ambix file %p", ambix); ambix=NULL; free(resultdata); free(data); free(orgdata); ambixtest_rmfile(path); } ambix-0.1.1/libambix/tests/const_matrix.c000066400000000000000000000246651300077024200204300ustar00rootroot00000000000000/* const_matrix - test constness in matrix operations Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include 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%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%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; rdata[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; rdata[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%g)", errf, eps); } /* cleanup */ ambix_matrix_destroy(mtx); ambix_matrix_destroy(result); free(org_vectors); for(r=0; r%f)", errf, eps); errf=matrix_diff(line, B, B0, eps); fail_if(!(errf%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%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 ambix-0.1.1/libambix/tests/data.h000066400000000000000000000021701300077024200166170ustar00rootroot00000000000000/* tests/data.h - AMBIsonics eXchange Library test data -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #ifndef TESTS_DATA_H #define TESTS_DATA_H /* file1.caf * AMBIX_BASIC, 3rd order (9 channels) * 44100 samples, all zero */ #define AMBIXTEST_FILE1 "data/file1.caf" #endif /* TESTS_DATA_H */ ambix-0.1.1/libambix/tests/data/000077500000000000000000000000001300077024200164465ustar00rootroot00000000000000ambix-0.1.1/libambix/tests/data/Makefile.am000066400000000000000000000002241300077024200205000ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign EXTRA_DIST = file1.caf.org noinst_DATA=$(EXTRA_DIST:%.org=%) % :: %.org cp $< $@ clean-local: rm -rf $(noinst_DATA) ambix-0.1.1/libambix/tests/data/file1.caf.org000066400000000000000000060446201300077024200207230ustar00rootroot00000000000000caffdesc @刀lpcm$ peakpfree4data9ambix-0.1.1/libambix/tests/data/foo.pd000066400000000000000000000021331300077024200175550ustar00rootroot00000000000000#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; ambix-0.1.1/libambix/tests/data/foo.wav000066400000000000000000060350401300077024200177600ustar00rootroot00000000000000RIFF:WAVEfmt  D9$ factDPEAKP>pPdata9ambix-0.1.1/libambix/tests/datatest.c000066400000000000000000000070471300077024200175220ustar00rootroot00000000000000/* data - test generic data functionality Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include 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 diff0.f, __LINE__, "diffing mtx with itself returned %g (>%g)", errf, 0.f); /* compare equal data */ STARTTEST("equal\n"); for(i=0; i0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f); /* compare data where all values differ, but eps, __LINE__, "diffing mtx with mtx+eps/2 returned %g (>%g)", errf, size, eps); for(i=0; ieps, __LINE__, "diffing mtx with mtx-eps/2 returned %g (>%g)", errf, size, eps); /* compare data where many values differ with eps */ STARTTEST("mosteps\n"); for(i=0; i(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; ieps 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(); } ambix-0.1.1/libambix/tests/debug_utils.c000066400000000000000000000013211300077024200202040ustar00rootroot00000000000000#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(); } ambix-0.1.1/libambix/tests/extended_float32_0.c000066400000000000000000000004551300077024200212560ustar00rootroot00000000000000#include "common.h" #include #include 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_FLOAT32, 0, 1e-7); return pass(); } ambix-0.1.1/libambix/tests/extended_float32_1024.c000066400000000000000000000004601300077024200215010ustar00rootroot00000000000000#include "common.h" #include #include 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_FLOAT32, 1024, 1e-7); return pass(); } ambix-0.1.1/libambix/tests/extended_float64_0.c000066400000000000000000000004551300077024200212630ustar00rootroot00000000000000#include "common.h" #include #include 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(); } ambix-0.1.1/libambix/tests/extended_float64_1024.c000066400000000000000000000004601300077024200215060ustar00rootroot00000000000000#include "common.h" #include #include 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(); } ambix-0.1.1/libambix/tests/extended_pcm16_0.c000066400000000000000000000004651300077024200207330ustar00rootroot00000000000000#include "common.h" #include #include 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_PCM16, 1024, 1./20000.); return pass(); } ambix-0.1.1/libambix/tests/extended_pcm16_1024.c000066400000000000000000000004651300077024200211620ustar00rootroot00000000000000#include "common.h" #include #include 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_PCM16, 1024, 1./20000.); return pass(); } ambix-0.1.1/libambix/tests/extended_pcm32_0.c000066400000000000000000000004551300077024200207300ustar00rootroot00000000000000#include "common.h" #include #include 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_PCM32, 0, 1e-5); return pass(); } ambix-0.1.1/libambix/tests/extended_pcm32_1024.c000066400000000000000000000004601300077024200211530ustar00rootroot00000000000000#include "common.h" #include #include 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_PCM32, 1024, 1e-5); return pass(); } ambix-0.1.1/libambix/tests/fail.c000066400000000000000000000001111300077024200166050ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return fail(); } ambix-0.1.1/libambix/tests/fail_if0.c000066400000000000000000000001601300077024200173470ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return fail_if(0, __LINE__, "should %s fail", "NOT"); } ambix-0.1.1/libambix/tests/fail_if1.c000066400000000000000000000001631300077024200173530ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return fail_if(1, __LINE__, "should %s fail", "indeed"); } ambix-0.1.1/libambix/tests/markers_regions.c000066400000000000000000000101711300077024200210730ustar00rootroot00000000000000#include "common.h" #include "data.h" #include 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(); } ambix-0.1.1/libambix/tests/matrices.c000066400000000000000000000205431300077024200175140ustar00rootroot00000000000000/* matrices - test preset matrices Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include float32_t matrix_check_diff(const char*name, ambix_matrix_t*mtx1,ambix_matrix_t*mtx2) { uint32_t col, row; float32_t errf=0.; fail_if((mtx1->cols != mtx2->cols), __LINE__, "matrix columns (%s) do not match %d!=%d", name, mtx1->cols, mtx2->cols); fail_if((mtx1->rows != mtx2->rows), __LINE__, "matrix rows (%s) do not match %d!=%d", name, mtx1->rows, mtx2->rows); for(col=0; colcols; col++) { for(row=0; rowrows; row++) { errf+=fabs(mtx1->data[row][col] - mtx2->data[row][col]); } } return errf; } ambix_matrix_t*inverse_matrices(ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) { ambix_matrixtype_t pyt = (ambix_matrixtype_t)(AMBIX_MATRIX_TO_AMBIX | typ); ambix_matrix_t*mtx=ambix_matrix_init(rows, cols, NULL); ambix_matrix_t*xtm=ambix_matrix_init(cols, rows, NULL); ambix_matrix_t*a2f=NULL; ambix_matrix_t*f2a=NULL; skip_if(NULL==mtx, __LINE__, "couldn't create mtx-matrix"); skip_if(NULL==xtm, __LINE__, "couldn't create xtm-matrix"); a2f=ambix_matrix_fill(mtx, typ); f2a=ambix_matrix_fill(xtm, pyt); skip_if(NULL==a2f, __LINE__, "couldn't create a2f-matrix"); skip_if(NULL==f2a, __LINE__, "couldn't create f2a-matrix"); // ambix_matrix_t*result=ambix_matrix_multiply(a2f, f2a, NULL); ambix_matrix_t*result=ambix_matrix_multiply(f2a, a2f, NULL); if(a2f!=mtx) ambix_matrix_destroy(a2f); ambix_matrix_destroy(mtx); if(f2a!=xtm) ambix_matrix_destroy(f2a); ambix_matrix_destroy(xtm); return result; } void check_inversion(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) { ambix_matrix_t*eye=NULL; ambix_matrix_t*result=NULL; float32_t errf; float32_t eps=1e-6; STARTTEST("%s\n", name); result=inverse_matrices(typ, rows, cols); eye=ambix_matrix_init(result->rows, result->cols, eye); skip_if(NULL==eye, __LINE__, "couldn't create eye-matrix"); eye=ambix_matrix_fill(eye, AMBIX_MATRIX_IDENTITY); skip_if(NULL==eye, __LINE__, "couldn't fill eye-matrix"); errf=matrix_check_diff(name, result, eye); if(!(errfrows, result->cols, zeros); skip_if(NULL==zeros, __LINE__, "couldn't create zeros-matrix"); zeros=ambix_matrix_fill(zeros, AMBIX_MATRIX_ZERO); skip_if(NULL==zeros, __LINE__, "couldn't fill zeros-matrix"); errf=matrix_check_diff(name, result, zeros); if(AMBIX_MATRIX_ZERO==typ) { fail_if(!(errf%f)", errf, eps); } else { fail_if((errfsn3d [ 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); check_inversion("FuMa[ 4, 4]", AMBIX_MATRIX_FUMA, 4, 4); check_inversion("FuMa[ 9, 5]", AMBIX_MATRIX_FUMA, 9, 5); check_inversion("FuMa[ 9, 6]", AMBIX_MATRIX_FUMA, 9, 6); check_inversion("FuMa[ 9, 9]", AMBIX_MATRIX_FUMA, 9, 9); check_inversion("FuMa[16, 7]", AMBIX_MATRIX_FUMA, 16, 7); 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); snprintf(name, 63, "n3d2snd3d[%d, %d]", chan, chan); check_matrix(name, AMBIX_MATRIX_N3D, chan, chan); snprintf(name, 63, "sn3d2n3d[%d, %d]", chan, chan); check_matrix(name, AMBIX_MATRIX_TO_N3D, chan, chan); snprintf(name, 63, "n3d[%d, %d]", chan, chan); check_inversion(name, AMBIX_MATRIX_N3D, 1, 1); snprintf(name, 63, "sid2acn[%d, %d]", chan, chan); check_matrix(name, AMBIX_MATRIX_SID, chan, chan); snprintf(name, 63, "acn2sid[%d, %d]", chan, chan); check_matrix(name, AMBIX_MATRIX_TO_SID, chan, chan); snprintf(name, 63, "sid[%d, %d]", chan, chan); check_inversion(name, AMBIX_MATRIX_SID, 1, 1); } STOPTEST("\n"); return pass(); } ambix-0.1.1/libambix/tests/matrixtests.c000066400000000000000000000504401300077024200202730ustar00rootroot00000000000000/* matrix - test matrix functionality Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include static float32_t leftdata_4_3[]= { 1.89999997615814208984e-01, 5.99999986588954925537e-02, 1.40000000596046447754e-01, 5.00000007450580596924e-02, 7.99999982118606567383e-02, 4.39999997615814208984e-01, 2.50000000000000000000e-01, 8.99999976158142089844e-01, 7.69999980926513671875e-01, 8.29999983310699462891e-01, 5.09999990463256835938e-01, 5.79999983310699462891e-01, }; static float32_t leftdata_4_4[]= { 7.13118553161621093750e-01, 1.05479925870895385742e-01, 1.88202366232872009277e-01, 1.49696469306945800781e-01, 9.03538286685943603516e-01, 9.58506166934967041016e-02, 1.49015650153160095215e-01, 6.73076272010803222656e-01, 7.11025714874267578125e-01, 4.27885711193084716797e-01, 5.05072295665740966797e-01, 2.34252512454986572266e-01, 1.91707342863082885742e-01, 3.83728086948394775391e-01, 3.97484041750431060791e-02, 5.89549958705902099609e-01, }; 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 */ 3.20059925317764282227e-01, -6.16572856903076171875e-01, -7.58203923702239990234e-01, 1.39707016944885253906e+00, -4.75395143032073974609e-01, -2.11239647865295410156e+00, 1.44310879707336425781e+00, -1.98593139648437500000e-01, 3.49719613790512084961e-01, 2.68386173248291015625e+00, -1.50602340698242187500e-01, -1.96372553706169128418e-01, }; static float32_t resultpinv_4_4[] = { /* (leftdata[4,4])^-1 */ 3.26068806648254394531e+00, -7.50604689121246337891e-01, -1.02798342704772949219e+00, 4.37466591596603393555e-01, 4.47858381271362304688e+00, -3.52734327316284179688e+00, -8.83177340030670166016e-01, 3.24082684516906738281e+00, -6.75182533264160156250e+00, 2.95947027206420898438e+00, 3.87480235099792480469e+00, -3.20398116111755371094e+00, -3.52011203765869140625e+00, 2.34043407440185546875e+00, 6.47875070571899414062e-01, -3.39426249265670776367e-01, }; 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->colsrows)?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%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%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%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%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 diff0.f, __LINE__, "diffing mtx with itself returned %g (>%g)", errf, 0.f); /* compare equal matrices */ STARTTEST("equal\n"); for(i=0; i0.f, __LINE__, "diffing mtx with copy returned %g (>%g)", errf, 0.f); /* compare matrices where all values differ, but eps, __LINE__, "diffing mtx with mtx+eps/2 returned %g (>%g)", errf, eps); for(i=0; ieps, __LINE__, "diffing mtx with mtx-eps/2 returned %g (>%g)", errf, eps); /* compare matrices where many values differ with eps */ STARTTEST("mosteps\n"); for(i=0; i(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; ieps 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(3e-5); return pass(); } ambix-0.1.1/libambix/tests/none_float32.c000066400000000000000000000022151300077024200201720ustar00rootroot00000000000000/* none_float32 - test ambix none (FLOAT32) Copyright © 2012 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include void check_create_none(const char*path, ambix_sampleformat_t format); int main(int argc, char**argv) { check_create_none(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT32); return pass(); } ambix-0.1.1/libambix/tests/none_float64.c000066400000000000000000000022221300077024200201750ustar00rootroot00000000000000/* none_float32 - test ambix none (FLOAT64) Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ #include "common.h" #include #include void check_create_none(const char*path, ambix_sampleformat_t format); int main(int argc, char**argv) { check_create_none(FILENAME_FILE, AMBIX_SAMPLEFORMAT_FLOAT64); return pass(); } ambix-0.1.1/libambix/tests/pass.c000066400000000000000000000017311300077024200166510ustar00rootroot00000000000000/* pass - simple test that always passes Copyright © 2012 IOhannes m zmölnig . 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 . */ #include "common.h" int main(int argc, char**argv) { return pass(); } ambix-0.1.1/libambix/tests/pass_if0.c000066400000000000000000000001601300077024200174020ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return pass_if(0, __LINE__, "should %s pass", "NOT"); } ambix-0.1.1/libambix/tests/pass_if1.c000066400000000000000000000001631300077024200174060ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return pass_if(1, __LINE__, "should %s pass", "indeed"); } ambix-0.1.1/libambix/tests/runtest.sh000077500000000000000000000010451300077024200176000ustar00rootroot00000000000000#!/bin/sh APP=$1 _TESTTYPE=$2 TESTTYPE=${TESTTYPE:-$_TESTTYPE} ################################## VALGRIND="libtool --mode=execute valgrind --error-exitcode=1 -q" if which valgrind > /dev/null then MEMGRIND="${VALGRIND} --leak-check=full" DRDGRIND="${VALGRIND} --tool=drd" HELGRIND="${VALGRIND} --tool=helgrind" else MEMGRIND= DRDGRIND= HELGRIND= fi get_runtest() { case "$1" in mem*|MEM*) echo ${MEMGRIND} ;; DRD|drd) echo ${DRDGRIND} ;; HEL*|hel*) echo ${HELGRIND} ;; *) ;; esac } $(get_runtest $TESTTYPE) ${APP} ambix-0.1.1/libambix/tests/skip.c000066400000000000000000000001111300077024200166400ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return skip(); } ambix-0.1.1/libambix/tests/skip_if0.c000066400000000000000000000001601300077024200174020ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return skip_if(0, __LINE__, "should %s skip", "NOT"); } ambix-0.1.1/libambix/tests/skip_if1.c000066400000000000000000000001631300077024200174060ustar00rootroot00000000000000#include "common.h" int main(int argc, char**argv) { return skip_if(1, __LINE__, "should %s skip", "indeed"); } ambix-0.1.1/m4/000077500000000000000000000000001300077024200131245ustar00rootroot00000000000000ambix-0.1.1/m4/ax_pthread.m4000066400000000000000000000261041300077024200155100ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREADS. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) AC_MSG_RESULT($ax_pthread_ok) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; *-darwin*) acx_pthread_flags="-pthread $acx_pthread_flags" ;; esac if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include static void routine(void* a) {a=0;} static void* start_routine(void* a) {return a;}], [pthread_t th; pthread_attr_t attr; pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_create(&th,0,start_routine,0); pthread_cleanup_pop(0); ], [ax_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($ax_pthread_ok) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_TRY_LINK([#include ], [int attr=$attr; return attr;], [attr_name=$attr; break]) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREADS,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl AX_PTHREAD ambix-0.1.1/m4/iem_check_framework.m4000066400000000000000000000023101300077024200173460ustar00rootroot00000000000000dnl Copyright (C) 2005-2012 IOhannes m zmölnig dnl This file is free software; IOhannes m zmölnig dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # IEM_CHECK_FRAMEWORK(FRAMEWORK, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) # # AC_DEFUN([IEM_CHECK_FRAMEWORK], [ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) AC_SUBST(IEM_FRAMEWORK_[]NAME[]) AC_MSG_CHECKING([for "$1"-framework]) iem_check_ldflags_org="${LDFLAGS}" LDFLAGS="-framework [$1] ${LDFLAGS}" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [iem_check_ldflags_success="yes"],[iem_check_ldflags_success="no"]) if test "x$iem_check_ldflags_success" = "xyes"; then AC_MSG_RESULT([yes]) AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), [1], [framework $1]) AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_IEM_FRAMEWORK_$1), [1], [framework $1]) IEM_FRAMEWORK_[]NAME[]="-framework [$1]" [$2] else AC_MSG_RESULT([no]) LDFLAGS="$iem_check_ldflags_org" [$3] fi AM_CONDITIONAL(HAVE_FRAMEWORK_[]NAME, [test "x$iem_check_ldflags_success" = "xyes"]) undefine([NAME]) ])# IEM_CHECK_FRAMEWORK ambix-0.1.1/m4/iem_operatingsystem.m4000066400000000000000000000016731300077024200174640ustar00rootroot00000000000000dnl try to figure out the target operating system and set some AM-macros accordingly dnl dnl Copyright (C) 2011 IOhannes m zmölnig AC_DEFUN([IEM_OPERATING_SYSTEM], [ AC_CANONICAL_HOST LINUX=no ANDROID=no MACOSX=no IPHONEOS=no BSD=no WINDOWS=no MINGW=no CYGWIN=no HURD=no IRIX=no case $host_os in *linux*) LINUX=yes ;; *darwin*) MACOSX=yes ;; GNU/kFreeBSD) BSD=yes ;; *mingw*) WINDOWS=yes MINGW=yes ;; *cygwin*) WINDOWS=yes CYGWIN=yes ;; GNU) HURD=yes ;; esac AM_CONDITIONAL(LINUX, test x$LINUX = xyes) AM_CONDITIONAL(ANDROID, test x$ANDROID = xyes) AM_CONDITIONAL(MACOSX, test x$MACOSX = xyes) AM_CONDITIONAL(IPHONEOS, test x$IPHONEOS = xyes) AM_CONDITIONAL(BSD, test x$BSD = xyes) AM_CONDITIONAL(WINDOWS, test x$WINDOWS = xyes) AM_CONDITIONAL(CYGWIN, test x$MINGW = xyes) AM_CONDITIONAL(MINGW, test x$MINGW = xyes) AM_CONDITIONAL(HURD, test x$HURD = xyes) AM_CONDITIONAL(IRIX, test x$IRIX = xyes) ]) dnl IEM_OPERATING_SYSTEM ambix-0.1.1/m4/iem_relativerpath.m4000066400000000000000000000015731300077024200171000ustar00rootroot00000000000000dnl Copyright (C) 2011 IOhannes m zmölnig dnl This file is free software; IOhannes m zmölnig dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. ## useage: add the @RELATIVERPATH_FLAGS@ to the LDFLAGS of your external ## TODO: add other platforms ## on OSX we have to add "-install_name @loader_path/$NAME" when linking the _library_ ## on W32 this should no be needed at all (but is it?) AC_DEFUN([IEM_RELATIVERPATH], [ originrpath_org_CFLAGS=$CFLAGS IEM_CHECK_CFLAGS([-Wl,-enable-new-dtags -Wl,-rpath,"\$ORIGIN"], [have_originrpath="yes"], [have_originrpath="no"]) CFLAGS=$originrpath_org_CFLAGS RELATIVERPATH_FLAGS="" if test "x$have_originrpath" = "xyes"; then RELATIVERPATH_FLAGS="-Wl,-enable-new-dtags -Wl,-rpath,\"\\\$\$ORIGIN\"" fi AC_SUBST([RELATIVERPATH_FLAGS]) ])# IEM_RELATIVERPATH ambix-0.1.1/m4/iem_rte.m4000066400000000000000000000100571300077024200150150ustar00rootroot00000000000000dnl Copyright (C) 2005-2012 IOhannes m zmölnig dnl This file is free software; IOhannes m zmölnig dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. # CHECK_RTE() # # checks for RTE (currently: Pd) # if so, they are added to the LDFLAGS, CFLAGS and whatelse AC_DEFUN([IEM_CHECK_RTE], [ IEM_OPERATING_SYSTEM AC_ARG_WITH([rte], AS_HELP_STRING([--with-rte=],[use the given RTE (e.g. 'pd') or none])) AC_ARG_WITH([pd], AS_HELP_STRING([--with-pd=],[where to find pd-binary (./bin/pd.exe) and pd-sources])) ### this should only be set if Pd has been found # the extension AC_ARG_WITH([extension], AS_HELP_STRING([--with-extension=],[enforce a certain file-extension (e.g. pd_linux)])) AC_ARG_WITH([rtedir], [AS_HELP_STRING([--rtedir=DIR], [externals (plugin) dir for RTE (default ${exec_prefix}/lib/pd/extra)])], [rtedir=$withval], [rtedir=['${exec_prefix}/lib/pd/extra']]) test "x${with_rte}" = "x" && with_rte="yes" ## this really should run some autodetection test "x${with_rte}" = "xyes" && with_rte="pd" if test "x${with_rte}" = "xpd"; then tmp_rte_orgcppflags="$CPPFLAGS" tmp_rte_orgcflags="$CFLAGS" tmp_rte_orgcxxflags="$CXXFLAGS" tmp_rte_orgldflags="$LDFLAGS" tmp_rte_orglibs="$LIBS" tmp_rte_cflags="-DPD" tmp_rte_libs="" RTE="Pure Data" ## some default paths if test "x${with_pd}" = "x"; then case $host_os in *darwin*) if test -d "/Applications/Pd-extended.app/Contents/Resources"; then with_pd="/Applications/Pd-extended.app/Contents/Resources"; fi if test -d "/Applications/Pd.app/Contents/Resources"; then with_pd="/Applications/Pd.app/Contents/Resources"; fi ;; *mingw* | *cygwin*) if test -d "${PROGRAMFILES}/Pd-extended"; then with_pd="${PROGRAMFILES}/Pd-extended"; fi if test -d "${PROGRAMFILES}/pd"; then with_pd="${PROGRAMFILES}/pd"; fi ;; esac fi if test -d "$with_pd" ; then if test -d "${with_pd}/src" ; then tmp_rte_cflags="${tmp_rte_cflags}${tmp_rte_cflags:+ }-I${with_pd}/src" elif test -d "${with_pd}/include/pd" ; then tmp_rte_cflags="${tmp_rte_cflags}${tmp_rte_cflags:+ }-I${with_pd}/include/pd" elif test -d "${with_pd}/include" ; then tmp_rte_cflags="${tmp_rte_cflags}${tmp_rte_cflags:+ }-I${with_pd}/include" else tmp_rte_cflags="${tmp_rte_cflags}${tmp_rte_cflags:+ }-I${with_pd}" fi if test -d "${with_pd}/bin" ; then tmp_rte_libs="${tmp_rte_libs}${tmp_rte_libs:+ }-L${with_pd}/bin" else tmp_rte_libs="${tmp_rte_libs}${tmp_rte_libs:+ }-L${with_pd}" fi CPPFLAGS="$CPPFLAGS ${tmp_rte_cflags}" CFLAGS="$CFLAGS ${tmp_rte_cflags}" CXXFLAGS="$CXXFLAGS ${tmp_rte_cflags}" LIBS="$LIBS ${tmp_rte_libs}" fi AC_CHECK_LIB([:pd.dll], [nullfn], [have_pddll="yes"], [have_pddll="no"]) if test "x$have_pddll" = "xyes"; then tmp_rte_libs="${tmp_rte_libs}${tmp_rte_libs:+ }-Xlinker -l:pd.dll" else AC_CHECK_LIB([pd], [nullfn], [tmp_rte_libs="${tmp_rte_libs}${tmp_rte_libs:+ }-lpd"]) fi AC_CHECK_HEADERS([m_pd.h], [have_pd="yes"], [have_pd="no"]) dnl LATER check why this doesn't use the --with-pd includes dnl for now it will basically disable anything that needs s_stuff.h if it cannot be found in /usr[/local]/include AC_CHECK_HEADERS([s_stuff.h], [], [], [#ifdef HAVE_M_PD_H # define PD # include "m_pd.h" #endif ]) if test "x$with_extension" != "x"; then tmp_rte_extension=$with_extension else case x$host_os in x*darwin*) tmp_rte_extension=pd_darwin ;; x*mingw* | x*cygwin*) tmp_rte_extension=dll ;; x) dnl just assuming that it is still linux (e.g. x86_64) tmp_rte_extension="pd_linux" ;; *) tmp_rte_extension=pd_`echo $host_os | sed -e '/.*/s/-.*//' -e 's/\[.].*//'` ;; esac fi RTE_EXTENSION=$tmp_rte_extension RTE_CFLAGS="$tmp_rte_cflags" RTE_LIBS="$tmp_rte_libs" AC_SUBST(RTE_EXTENSION) AC_SUBST(RTE_CFLAGS) AC_SUBST(RTE_LIBS) AC_SUBST(RTE) AC_SUBST([rtedir], ['${exec_prefix}/lib/pd/extra'])dnl CPPFLAGS="$tmp_rte_orgcppflags" CFLAGS="$tmp_rte_orgcflags" CXXFLAGS="$tmp_rte_orgcxxflags" LDFLAGS="$tmp_rte_orgldflags" LIBS="$tmp_rte_orglibs" fi ]) # CHECK_RTE ambix-0.1.1/m4/pkg.m4000066400000000000000000000131121300077024200141450ustar00rootroot00000000000000# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_DEFINE(HAVE_$1[], [1], [Define to 1 if you have $1]) AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES ambix-0.1.1/release.sh000077500000000000000000000045511300077024200145700ustar00rootroot00000000000000#!/bin/sh #################################### # prepare package for release # DONE: get current version from configure.ac # DONE: ChangeLog generator using git-dch # DONE: update configure.ac # TODO: automatically update AUTHORS # TODO: automatically prepare NEWS (from ChangeLog) # TODO: automatically launch editors for ChangeLog/NEWS/AUTHORS # TODO: automatically tag (if all went well) CHANGELOG=CHANGELOG NEWS=NEWS AUTHORS=AUTHORS error() { echo "$@" 1>&2 } fatal() { error "$@" exit 1 } usage() { fatal "usage: $0 [] " 1>&2 } getoldversion () { dpkg-parsechangelog --count 1 -l${CHANGELOG} | egrep "^Version:" | head -1 | cut -f2 -d' ' } getmoduleversion() { grep "^AC_INIT" configure.ac | sed -e 's|[^,]*,||' \ -e 's|,.*||' \ -e 's|[][]||g' } getgitbranch() { git rev-parse --abbrev-ref HEAD } if [ -d "debian/" ]; then fatal "debian/ directory exists" fi if [ "$(getgitbranch)" != "master" ]; then fatal "current branch '$(getgitbranch)' is not 'master'" fi if [ "x$2" = "x" ]; then ## guess current version NEWVERSION=$1 OLDVERSION=$(getoldversion) else OLDVERSION=$1 NEWVERSION=$2 fi if [ "x${NEWVERSION}" = "x" ]; then NEWVERSION=$(getmoduleversion) fi if git tag -l v${OLDVERSION} | grep . >/dev/null then : else fatal "it seems like there is no tag 'v${OLDVERSION}'" fi if [ "x${OLDVERSION}" = "x" ]; then usage fi echo "updating from ${OLDVERSION}" if [ "x${NEWVERSION}" = "x" ]; then usage fi if dpkg --compare-versions ${OLDVERSION} ge ${NEWVERSION} then fatal "version mismatch: ${NEWVERSION} is not newer than ${OLDVERSION}" fi echo "updating to ${NEWVERSION}" OK=false mkdir debian touch debian/control cp ${CHANGELOG} debian/changelog gbp dch -R --since "v${OLDVERSION}" -N "${NEWVERSION}" && cat debian/changelog > ${CHANGELOG} && OK=true dch --news ${NEWS} || OK=false rm -rf debian if [ "x${OK}" = "xtrue" ]; then sed -e "s|^\(AC_INIT[^,]*\),[[][^,]*[]],\(.*\)|\1,[${NEWVERSION}],\2|" -i configure.ac fi if [ "x${OK}" = "xtrue" ]; then echo "all went well" echo "" echo "- please check your ${CHANGELOG}" echo "- please check&edit your ${NEWS}" echo "- please check&edit your ${AUTHORS}" echo "- and don't forget to git-tag the new version as v${NEWVERSION}" echo " git tag v${NEWVERSION} -m \"released v${NEWVERSION}\"" else fatal "ouch, something went wrong..." fi ambix-0.1.1/replacement/000077500000000000000000000000001300077024200151035ustar00rootroot00000000000000ambix-0.1.1/replacement/Makefile.am000066400000000000000000000000331300077024200171330ustar00rootroot00000000000000noinst_HEADERS = strndup.h ambix-0.1.1/replacement/strndup.h000066400000000000000000000027051300077024200167570ustar00rootroot00000000000000/* strndup.h - AMBIsonics eXchange strndup() replacement implementation -*- c -*- Copyright © 2012 IOhannes m zmölnig . Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz Copyright © 2005 Free Software Foundation, Inc. Written by Kaveh R. Ghazi . 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 . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifndef HAVE_STRNDUP # include # include static char * strndup (const char *s, size_t n) { char *result = NULL; size_t len = strlen (s); if (n < len) len = n; result = (char *) malloc (len + 1); if (!result) return 0; result[len] = '\0'; return (char *) memcpy (result, s, len); } #endif /* HAVE_STRNDUP */ ambix-0.1.1/samples/000077500000000000000000000000001300077024200142505ustar00rootroot00000000000000ambix-0.1.1/samples/Makefile.am000066400000000000000000000001271300077024200163040ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign SUBDIRS= if HAVE_PUREDATA SUBDIRS+=pd endif HAVE_PUREDATA ambix-0.1.1/samples/pd/000077500000000000000000000000001300077024200146535ustar00rootroot00000000000000ambix-0.1.1/samples/pd/Makefile.am000066400000000000000000000042331300077024200167110ustar00rootroot00000000000000AUTOMAKE_OPTIONS = foreign rteambixdir = @rtedir@/ambix rteambix_LTLIBRARIES= dist_rteambix_DATA= AM_CFLAGS = AM_LDFLAGS= -module -avoid-version -shared -shrext .@RTE_EXTENSION@ if WINDOWS AM_LDFLAGS+= -no-undefined endif AM_CPPFLAGS = -I$(top_srcdir)/libambix -I$(top_srcdir) # RTE AM_CFLAGS += @RTE_CFLAGS@ AM_LDFLAGS+= @RTE_LIBS@ AM_LDFLAGS+=$(top_builddir)/libambix/src/libambix.la ambix_read__la_CFLAGS = $(AM_CFLAGS) @PTHREAD_CFLAGS@ ambix_read__la_LDFLAGS = $(AM_LDFLAGS) @PTHREAD_LIBS@ ambix_readX__la_CFLAGS = $(AM_CFLAGS) @PTHREAD_CFLAGS@ ambix_readX__la_LDFLAGS = $(AM_LDFLAGS) @PTHREAD_LIBS@ ambix_write__la_CFLAGS = $(AM_CFLAGS) @PTHREAD_CFLAGS@ ambix_write__la_LDFLAGS = $(AM_LDFLAGS) @PTHREAD_LIBS@ rteambix_LTLIBRARIES+= \ ambix_info.la \ ambix_read~.la \ ambix_readX~.la \ ambix_write~.la dist_rteambix_DATA+= \ ambix_read~-help.pd \ ambix_readX~-help.pd \ ambix_write~-help.pd \ ambix_info-help.pd \ ambix-meta.pd ambix_info_la_SOURCES = ambix_info.c ambix_read__la_SOURCES = ambix_read~.c ambix_readX__la_SOURCES = ambix_read~.c ambix_write__la_SOURCES = ambix_write~.c noinst_HEADERS = winhacks.h if WINDOWS ambix_info_la_SOURCES += winhacks.c ambix_read__la_SOURCES += winhacks.c ambix_readX__la_SOURCES += winhacks.c ambix_write__la_SOURCES += winhacks.c endif WINDOWS # convenience symlinks .PHONY: convenience-link clean-convenience-link convenience-link: $(rteambix_LTLIBRARIES) @for lib in $^; do \ for soname in `echo | $(EGREP) "^dlname=" $$lib | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do \ echo "$$soname: creating convenience link from $(abs_builddir)/.libs to $(builddir)"; \ rm -f $$soname ; \ test -e $(abs_builddir)/.libs/$$soname && \ $(LN_S) $(abs_builddir)/.libs/$$soname $$soname || true; \ done; \ done clean-convenience-link: @for lib in $(rteambix_LTLIBRARIES); do \ for soname in `echo | $(EGREP) "^dlname=" $$lib | $(SED) -e "s|^dlname='\(.*\)'|\1|"`; do \ echo "$$soname: cleaning convenience links"; \ test -L $$soname && rm -f $$soname || true; \ done; done all-local:: convenience-link clean-local:: clean-convenience-link ambix-0.1.1/samples/pd/ambix-meta.pd.in000066400000000000000000000004631300077024200176340ustar00rootroot00000000000000#N canvas 118 49 745 103 10; #N canvas 500 278 380 146 META 0; #X text 10 50 AUTHOR IOhannes m zmölnig; #X text 10 10 NAME ambix; #X text 10 30 VERSION @VERSION@; #X text 10 70 LICENSE LGPL-2.1; #X text 10 90 DESCRIPTION objects for reading/writing of AMBIsonics eXchange files; #X restore 313 37 pd META; ambix-0.1.1/samples/pd/ambix_info-help.pd000066400000000000000000000036171300077024200202500ustar00rootroot00000000000000#N canvas 171 231 707 524 10; #X obj 103 91 ambix_info; #X obj 103 141 print info; #X msg 103 70 open \$1; #X obj 103 28 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 -1; #X obj 103 111 t a a; #X obj 103 49 openpanel; #X obj 371 261 t a; #X symbolatom 236 156 0 0 0 3 fileformat - -; #X symbolatom 321 156 0 0 0 3 sampleformat - -; #X floatatom 236 291 0 0 0 3 ambichannels - -; #X floatatom 313 291 0 0 0 3 extrachannels - -; #X obj 425 321 t a; #X obj 236 336 route matrix; #N canvas 4 49 450 300 matrix 0; #X obj 71 43 inlet; #X obj 71 63 list prepend matrix; #X obj 71 83 list trim; #X obj 71 133 t a; #X text 100 132 ready for use with [iemmatrix]; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 2 0 3 0; #X restore 236 368 pd matrix; #X obj 305 370 print ???; #X obj 236 196 route frames samplerate; #X obj 407 181 t a a; #X obj 420 196 route frames samplerate; #X obj 420 216 /; #X floatatom 313 211 0 0 0 3 samplerate - -; #X floatatom 236 211 0 0 0 3 frames - -; #X floatatom 420 231 0 0 0 3 duration[sec] - -; #X obj 236 126 route fileformat sampleformat; #X obj 236 276 route ambichannels extrachannels; #X obj 236 141 symbol; #X obj 321 141 symbol; #X text 266 12 [ambix_info]; #X text 266 30 get information about an AMBIsonics eXchange file; #X obj 145 477 ambix_read~; #X obj 235 477 ambix_readX~; #X obj 330 477 ambix_info; #X text 48 477 see also:; #X connect 0 0 4 0; #X connect 2 0 0 0; #X connect 3 0 5 0; #X connect 4 0 1 0; #X connect 4 1 22 0; #X connect 5 0 2 0; #X connect 6 0 23 0; #X connect 11 0 12 0; #X connect 12 0 13 0; #X connect 12 1 14 0; #X connect 15 0 20 0; #X connect 15 1 19 0; #X connect 15 2 6 0; #X connect 16 0 15 0; #X connect 16 1 17 0; #X connect 17 0 18 0; #X connect 17 1 18 1; #X connect 18 0 21 0; #X connect 22 0 24 0; #X connect 22 1 25 0; #X connect 22 2 16 0; #X connect 23 0 9 0; #X connect 23 1 10 0; #X connect 23 2 11 0; #X connect 24 0 7 0; #X connect 25 0 8 0; ambix-0.1.1/samples/pd/ambix_info.c000066400000000000000000000137761300077024200171500ustar00rootroot00000000000000/* ambix_info - get information on AMBIsonics eXchange files into Pd -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #if 0 # define MARK printf("%s[%d]:%s\t", __FILE__, __LINE__, __FUNCTION__), printf #else static void noop(const char*format, ...) {} # define MARK noop #endif #include #include #include #include #include #include #include "winhacks.h" /************************* ambix_info object ******************************/ /* [ambix_info~] uses the Posix threads package; for the moment we're Linux only although this should be portable to the other platforms. Each instance of ambix_info~ owns a "child" thread for doing the unix (MSW?) file reading. The parent thread signals the child each time: (1) a file wants opening or closing; (2) we've eaten another 1/16 of the shared buffer (so that the child thread should check if it's time to read some more.) The child signals the parent whenever a read has completed. Signalling is done by setting "conditions" and putting data in mutex-controlled common areas. */ static t_class *ambix_info_class; typedef struct _ambix_info { t_object x_obj; t_canvas *x_canvas; t_outlet*x_outlet; } t_ambix_info; /* tries to expand the given filename to it's full glory) */ t_symbol*get_filename(t_canvas*canvas, t_symbol*s) { int fd=0; char buf[MAXPDSTRING]; char result[MAXPDSTRING]; char*bufptr; if(!s || !s->s_name || !*s->s_name) { return NULL; } if ((fd=canvas_open(canvas, s->s_name, "", buf, &bufptr, MAXPDSTRING, 1))>=0){ sys_close(fd); snprintf(result, MAXPDSTRING-1, "%s/%s", buf, bufptr); result[MAXPDSTRING-1]=0; return gensym(result); } else if(canvas) { canvas_makefilename(canvas, s->s_name, result, MAXPDSTRING); return gensym(result); } return s; } /******** the object proper runs in the calling (parent) thread ****/ static void *ambix_info_new(void) { t_ambix_info*x = (t_ambix_info *)pd_new(ambix_info_class); x->x_outlet = outlet_new(&x->x_obj, &s_bang); x->x_canvas = canvas_getcurrent(); return (x); } static void ambix_info_open(t_ambix_info *x, t_symbol*s) { t_atom atoms[1]; ambix_info_t ainfo; ambix_t*ambix=NULL; const ambix_matrix_t*matrix=NULL; t_symbol*filesym=get_filename(x->x_canvas, s); char*filename=(filesym!=NULL)?filesym->s_name:NULL; memset(&ainfo, 0, sizeof(ainfo)); ambix=ambix_open(filename, AMBIX_READ, &ainfo); if(!ambix) { error("[ambix_info]: unable to open '%s'", filename); return; } /* filename */ SETSYMBOL(atoms+0, filesym); outlet_anything(x->x_outlet, gensym("filename"), 1, atoms); /* ambix fileformat */ switch(ainfo.fileformat) { case AMBIX_NONE: SETSYMBOL(atoms+0, gensym("NONE")); break; case AMBIX_BASIC: SETSYMBOL(atoms+0, gensym("BASIC")); break; case AMBIX_EXTENDED: SETSYMBOL(atoms+0, gensym("EXTENDED")); break; default: SETSYMBOL(atoms+0, gensym("unknown")); break; } outlet_anything(x->x_outlet, gensym("fileformat"), 1, atoms); /* number of ambisonics channels */ SETFLOAT(atoms+0, (t_float)(ainfo.ambichannels)); outlet_anything(x->x_outlet, gensym("ambichannels"), 1, atoms); /* number of non-ambisonics channels */ SETFLOAT(atoms+0, (t_float)(ainfo.extrachannels)); outlet_anything(x->x_outlet, gensym("extrachannels"), 1, atoms); /* ambix sampleformat */ switch(ainfo.sampleformat) { case AMBIX_SAMPLEFORMAT_NONE: SETSYMBOL(atoms+0, gensym("NONE")); break; case AMBIX_SAMPLEFORMAT_PCM16: SETSYMBOL(atoms+0, gensym("PCM16")); break; case AMBIX_SAMPLEFORMAT_PCM24: SETSYMBOL(atoms+0, gensym("PCM24")); break; case AMBIX_SAMPLEFORMAT_PCM32: SETSYMBOL(atoms+0, gensym("PCM32")); break; case AMBIX_SAMPLEFORMAT_FLOAT32: SETSYMBOL(atoms+0, gensym("FLOAT32")); break; default: SETSYMBOL(atoms+0, gensym("unknown")); break; } outlet_anything(x->x_outlet, gensym("sampleformat"), 1, atoms); /* samplerate of file */ SETFLOAT(atoms+0, (t_float)(ainfo.samplerate)); outlet_anything(x->x_outlet, gensym("samplerate"), 1, atoms); /* number of sample frames in file */ SETFLOAT(atoms+0, (t_float)(ainfo.frames)); outlet_anything(x->x_outlet, gensym("frames"), 1, atoms); matrix=ambix_get_adaptormatrix(ambix); if(matrix) { int size=matrix->rows*matrix->cols; if(size) { uint32_t r, c, index; t_atom*ap=(t_atom*)getbytes(sizeof(t_atom)*(size+2)); SETFLOAT(ap+0, matrix->rows); SETFLOAT(ap+1, matrix->cols); index=2; for(r=0; rrows; r++) { for(c=0; ccols; c++) { SETFLOAT(ap+index, matrix->data[r][c]); index++; } } outlet_anything(x->x_outlet, gensym("matrix"), size+2, ap); freebytes(ap, sizeof(t_atom)*(size+2)); } } ambix_close(ambix); } static void ambix_info_free(t_ambix_info *x) { /* request QUIT and wait for acknowledge */ outlet_free(x->x_outlet); } AMBIX_EXPORT void ambix_info_setup(void) { ambix_info_class = class_new(gensym("ambix_info"), (t_newmethod)ambix_info_new, (t_method)ambix_info_free, sizeof(t_ambix_info), 0, A_GIMME, A_NULL); class_addmethod(ambix_info_class, (t_method)ambix_info_open, gensym("open"), A_SYMBOL, A_NULL); if(0) { MARK("setup"); } } ambix-0.1.1/samples/pd/ambix_readX~-help.pd000066400000000000000000000106641300077024200205560ustar00rootroot00000000000000#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 95 185 1; #X obj 495 429 /; #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 - -, f 5; #X obj 299 388 env~; #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; #X obj 74 69 openpanel; #X obj 145 549 readsf~; #X text 215 81 You must "open" the ambix file in advance \, to allow the buffer to be filled up \, and the send "1" to start playback.; #X text 215 107 Sending "0" stops playback.; #X text 215 129 Some information on the file is sent to the last outlet of the object \, e.g. the number of frames (samples per channel) \, the number of ambisonics- and nonambisonics- channels found in the file and the samplerate; #X obj 495 486 route resamplerate; #X obj 630 471 t a; #X floatatom 495 503 0 0 0 0 - - -; #X text 491 518 samplerate (after evtl. re-sampling); #X text 286 296 is given in samples per channels (unlike [readsf~] where you specify it in bytes per channel); #X text 43 525 see also:; #X text 220 280 arguments: <#ambioutlet~s:4> <#extraoutlet~s:0> ; #X text 200 18 [ambix_readX~] read an AMBIsonics eXchange file (EXTENDED ; #X text 215 47 The [ambix_readX~] reads an ambix soundfile into it's signal outputs \, much like [readsf~] for normal soundfiles.; #X obj 74 277 ambix_readX~ 4 2; #X obj 45 468 print matrix; #X obj 45 313 t a a; #X text 220 186 The ambisonics channels will be presented AS-IS. In order to obtain a full standard set of ambisonics channels (SN3D \, ACN) \, you will need to multiply the channels with the adaptor matrix 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 - -, f 5; #X obj 112 406 env~; #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 - -, f 5; #X obj 192 406 env~; #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; #X connect 4 0 5 0; #X connect 6 0 7 0; #X connect 6 1 2 0; #X connect 7 0 4 0; #X connect 7 1 4 1; #X connect 7 2 22 0; #X connect 8 0 9 0; #X connect 10 0 11 0; #X connect 12 0 30 0; #X connect 14 0 30 0; #X connect 15 0 16 0; #X connect 16 0 14 0; #X connect 21 0 23 0; #X connect 22 0 21 0; #X connect 30 0 32 0; #X connect 30 1 43 1; #X connect 30 2 43 2; #X connect 30 3 43 3; #X connect 30 4 43 4; #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; #X connect 37 0 38 0; #X connect 39 0 40 0; #X connect 41 0 42 0; #X connect 43 0 35 0; #X connect 43 1 37 0; #X connect 43 2 39 0; #X connect 43 3 41 0; #X connect 47 0 30 0; ambix-0.1.1/samples/pd/ambix_read~-help.pd000066400000000000000000000101351300077024200204170ustar00rootroot00000000000000#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 94 153 1; #X obj 74 298 env~; #X floatatom 74 318 5 0 0 3 ACN0 - -, f 5; #X obj 495 399 /; #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 - -, f 5; #X obj 149 330 env~; #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 - -, f 5; #X obj 74 238 ambix_read~ 4 2; #X obj 264 358 env~; #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 - -, f 5; #X msg 99 175 0; #X msg 646 30 \; pd dsp 1; #X msg 74 122 open \$1; #X msg 74 49 bang; #X obj 74 69 openpanel; #X obj 145 499 readsf~; #X text 200 18 [ambix_read~] read an AMBIsonics eXchange file (SIMPLE mode); #X text 215 47 The [ambix_read~] reads an ambix soundfile into it's signal outputs \, much like [readsf~] for normal soundfiles.; #X text 215 81 You must "open" the ambix file in advance \, to allow the buffer to be filled up \, and the send "1" to start playback.; #X text 215 107 Sending "0" stops playback.; #X text 215 129 Some information on the file is sent to the last outlet of the object \, e.g. the number of frames (samples per channel) \, the number of ambisonics- and nonambisonics- channels found in the file and the samplerate; #X obj 495 456 route resamplerate; #X obj 630 441 t a; #X floatatom 495 471 0 0 0 0 - - -; #X text 491 486 samplerate (after evtl. re-sampling); #X text 286 266 is given in samples per channels (unlike [readsf~] where you specify it in bytes per channel); #X text 43 475 see also:; #X obj 145 477 ambix_readX~; #X text 215 186 The ambisonics channels will always be periphonic (3D) semi-normalized (SN3D) and ordered after their ACN.; #X text 225 213 If you work with a Furse-Malham decoder \, you will need to transform the output data.; #X text 215 243 arguments: <#ambioutlet~s:4> <#extraoutlet~s:0> ; #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; #X connect 4 0 5 0; #X connect 6 0 7 0; #X connect 8 0 9 0; #X connect 8 1 2 0; #X connect 9 0 6 0; #X connect 9 1 6 1; #X connect 9 2 33 0; #X connect 10 0 11 0; #X connect 12 0 13 0; #X connect 14 0 15 0; #X connect 16 0 4 0; #X connect 16 1 10 0; #X connect 16 2 12 0; #X connect 16 3 14 0; #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; #X connect 23 0 16 0; #X connect 24 0 25 0; #X connect 25 0 23 0; #X connect 32 0 34 0; #X connect 33 0 32 0; #X connect 43 0 16 0; ambix-0.1.1/samples/pd/ambix_read~.c000066400000000000000000000706711300077024200173230ustar00rootroot00000000000000/* ambix_read~ - read AMBIsonics eXchange files in Pd -*- c -*- Copyright © 1997-1999, Miller Puckette . Copyright © 2012-2014, IOhannes m zmölnig . Copyright © 2016, Matthias Kronlachner 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 . [ambix_read~] is based on Pd's [ambix_read~], which is released under a 3-clause BSD-License ("Standard Improved BSD License") */ #if 0 # define MARK printf("%s[%d]:%s\t", __FILE__, __LINE__, __FUNCTION__), printf #else static void noop(const char*format, ...) {} # define MARK noop #endif #ifndef _WIN32 # include # include #endif #include #ifdef _WIN32 # include #endif #include #include #include #include #include #include #include "winhacks.h" #define MAXSFCHANS 64 #define DEFAULTVECSIZE 128 #define READFRAMES 16384 #define WRITFRAMES 16384 #define DEFBUFPERCHAN 65536 #define MINBUFSIZE (4 * READFRAMES) #define MAXBUFSIZE 4194304 #define REQUEST_NOTHING 0 #define REQUEST_OPEN 1 #define REQUEST_CLOSE 2 #define REQUEST_QUIT 3 #define REQUEST_BUSY 4 #define STATE_IDLE 0 #define STATE_STARTUP 1 #define STATE_STREAM 2 /* merge to buffers of interleaved samples into a single interleaved buffer * buf1 holds chan1 samples per frame, buf2 holds chan2 samples per frame * the dest buffer holds (want1+want2) samples per frame * if chanchan ZERO samples are filled in */ static void merge_samples(float32_t*buf1, uint32_t chan1, uint32_t want1, float32_t*buf2, uint32_t chan2, uint32_t want2, t_sample*dest, uint32_t destsize, uint32_t offset, uint32_t frames) { uint32_t left1=(want1>chan1)?want1-chan1:0; uint32_t left2=(want2>chan2)?want2-chan2:0; uint32_t use1=(chan1s_name || !*s->s_name) { return NULL; } if ((fd=canvas_open(canvas, s->s_name, "", buf, &bufptr, MAXPDSTRING, 1))>=0){ sys_close(fd); snprintf(result, MAXPDSTRING-1, "%s/%s", buf, bufptr); result[MAXPDSTRING-1]=0; return gensym(result); } else if(canvas) { canvas_makefilename(canvas, s->s_name, result, MAXPDSTRING); return gensym(result); } return s; } /************************* ambix_read object ******************************/ /* [ambix_read~] uses the Posix threads package; for the moment we're Linux only although this should be portable to the other platforms. Each instance of ambix_read~ owns a "child" thread for doing the unix (MSW?) file reading. The parent thread signals the child each time: (1) a file wants opening or closing; (2) we've eaten another 1/16 of the shared buffer (so that the child thread should check if it's time to read some more.) The child signals the parent whenever a read has completed. Signalling is done by setting "conditions" and putting data in mutex-controlled common areas. */ static t_class *ambix_read_class; typedef struct _infoflags { int f_eof; /* EOF notification */ int f_matrix; /* send matrix */ int f_ambix; /* send ambix_info */ } t_infoflags; typedef struct _ambix_read { t_object x_obj; t_canvas *x_canvas; t_sample *x_buf; /* soundfile buffer */ int x_bufsize; /* buffer size in bytes */ int x_bufframes; /* buffer size in frames */ int x_noutlets; /* number of audio outlets */ t_sample *(x_outvec[MAXSFCHANS]); /* audio vectors */ t_clock *x_clock; /* to call back on EOF */ t_outlet *x_infoout; /* bang-on-done outlet */ t_outlet *x_matrixout; /* bang-on-done outlet */ t_infoflags x_infoflags; /* what to do in the callback */ uint32_t x_ambichannels; /* ambichannels of the object (const) */ uint32_t x_xtrachannels; /* xtrachannels of the object (const) */ ambix_fileformat_t x_fileformat; /* readmode of the object (const) */ int x_vecsize; /* vector size for transfers */ int x_state; /* opened, running, or idle */ int x_requestcode; /* pending request from parent to I/O thread */ t_float x_insamplerate; /* sample rate of input signal if known */ /* parameters to communicate with subthread */ char *x_filename; /* file to open (string is permanently allocated) */ int x_fileerror; /* slot for "errno" return */ t_float x_samplerate; /* sample rate of soundfile */ long x_onsetframes; /* number of sample frames to skip */ 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 */ int x_fifotail; /* index of next byte the ugen will read */ int x_eof; /* true if fifohead has stopped changing */ int x_sigcountdown; /* counter for signalling child for more data */ int x_sigperiod; /* number of ticks per signal */ pthread_mutex_t x_mutex; pthread_cond_t x_requestcondition; pthread_cond_t x_answercondition; pthread_t x_childthread; } t_ambix_read; /************** the child thread which performs file I/O ***********/ static void *ambix_read_child_main(void *zz) { t_ambix_read *x = (t_ambix_read*)zz; 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; pthread_mutex_lock(&x->x_mutex); while (1) { int fifohead; t_sample *buf=NULL; if (x->x_requestcode == REQUEST_NOTHING) { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); } else if (x->x_requestcode == REQUEST_OPEN) { ambix_info_t ainfo; int64_t sysrtn; int wantframes; const ambix_matrix_t*matrix=NULL; /* copy file stuff out of the data structure so we can relinquish the mutex while we're in open_soundfile(). */ long onsetframes = x->x_onsetframes; int localfifosize = x->x_fifosize; uint32_t ambichannels=0, xtrachannels=0; /* get this from ainfo */ float32_t*ambibuf = NULL; float32_t*xtrabuf = NULL; char *filename = strndup(x->x_filename, MAXPDSTRING); // char *dirname = canvas_getdir(x->x_canvas)->s_name; /* alter the request code so that an ensuing "open" will get noticed. */ x->x_requestcode = REQUEST_BUSY; x->x_fileerror = 0; /* open the soundfile with the mutex unlocked */ pthread_mutex_unlock(&x->x_mutex); memset(&ainfo, 0, sizeof(ainfo)); ainfo.fileformat=want_fileformat; if (x->x_ambix_t) ambix_close(x->x_ambix_t); x->x_ambix_t=ambix_open(filename, AMBIX_READ, &ainfo); free(filename); if(x->x_ambix_t) { matrix=ambix_get_adaptormatrix(x->x_ambix_t); if(onsetframes) { ambix_seek(x->x_ambix_t, onsetframes, SEEK_SET); } } ambichannels=ainfo.ambichannels; xtrachannels=ainfo.extrachannels; ambibuf = (float32_t*)calloc(localfifosize*ambichannels, sizeof(float32_t)); xtrabuf = (float32_t*)calloc(localfifosize*xtrachannels, sizeof(float32_t)); pthread_mutex_lock(&x->x_mutex); if (NULL==x->x_ambix_t) { x->x_fileerror = errno; x->x_eof = 1; goto lost; } /* check if another request has been made; if so, field it */ if (x->x_requestcode != REQUEST_BUSY) goto lost; /* copy back into the instance structure. */ if(matrix) { ambix_matrix_copy(matrix, &x->x_matrix); x->x_infoflags.f_matrix=1; } memcpy(&x->x_ambix, &ainfo, sizeof(ainfo)); x->x_infoflags.f_ambix=1; /* clear the FIFO */ memset(x->x_buf, 0, x->x_bufsize); x->x_fifohead = 0; /* set fifosize from bufsize. fifosize must be a multiple of the number of bytes eaten for each DSP tick. We pessimistically assume MAXVECSIZE samples per tick since that could change. There could be a problem here if the vector size increases while a soundfile is being played... */ x->x_fifosize = x->x_bufframes-(x->x_bufframes%x->x_vecsize); /* arrange for the "request" condition to be signalled 16 times per buffer */ x->x_sigcountdown = x->x_sigperiod = (x->x_fifosize / (16 * x->x_vecsize)); /* in a loop, wait for the fifo to get hungry and feed it */ while (x->x_requestcode == REQUEST_BUSY) { int fifosize = x->x_fifosize; int bufframes = 0; if (x->x_eof) break; if (x->x_fifohead >= x->x_fifotail) { /* if the head is >= the tail, we can immediately read to the end of the fifo. Unless, that is, we would read all the way to the end of the buffer and the "tail" is zero; this would fill the buffer completely which isn't allowed because you can't tell a completely full buffer from an empty one. */ if (x->x_fifotail || (fifosize - x->x_fifohead > READFRAMES)) { wantframes = fifosize - x->x_fifohead; if (wantframes > READFRAMES) wantframes = READFRAMES; } else { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); continue; } } else { /* otherwise check if there are at least READFRAMES bytes to read. If not, wait and loop back. */ wantframes = x->x_fifotail - x->x_fifohead - 1; if (wantframes < READFRAMES) { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); continue; } else wantframes = READFRAMES; } buf = x->x_buf; fifohead = x->x_fifohead; bufframes = x->x_bufframes; pthread_mutex_unlock(&x->x_mutex); if(localfifosizex_ambix_t, ambibuf, xtrabuf, wantframes); if(sysrtn>0) { merge_samples(ambibuf, ambichannels, want_ambichannels, xtrabuf, xtrachannels, want_xtrachannels, buf, bufframes, fifohead, sysrtn); } pthread_mutex_lock(&x->x_mutex); if (x->x_requestcode != REQUEST_BUSY) break; if (sysrtn < 0) { x->x_fileerror = errno; break; } else if (sysrtn == 0) { x->x_eof = 1; break; } else { x->x_fifohead += sysrtn; if (x->x_fifohead == fifosize) x->x_fifohead = 0; } /* signal parent in case it's waiting for data */ pthread_cond_signal(&x->x_answercondition); } lost: free(ambibuf); free(xtrabuf); if (x->x_requestcode == REQUEST_BUSY) x->x_requestcode = REQUEST_NOTHING; /* fell out of read loop: close file if necessary, set EOF and signal once more */ if(x->x_ambix_t) { pthread_mutex_unlock(&x->x_mutex); 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(x->x_ambix_t) { pthread_mutex_unlock(&x->x_mutex); 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(x->x_ambix_t) { pthread_mutex_unlock(&x->x_mutex); ambix_close(x->x_ambix_t); x->x_ambix_t=NULL; pthread_mutex_lock(&x->x_mutex); } x->x_requestcode = REQUEST_NOTHING; pthread_cond_signal(&x->x_answercondition); break; } else { } } pthread_mutex_unlock(&x->x_mutex); return (0); } /******** the object proper runs in the calling (parent) thread ****/ static void ambix_read_tick(t_ambix_read *x); static void *ambix_read_new(t_symbol*s, int argc, t_atom*argv) { int achannels=0, xchannels=0, bufframes=-1, bufsize=0; t_ambix_read *x; int nchannels, i; t_sample *buf=NULL; int have_x=0, limiting=0; switch(argc) { case 0: achannels=4; break; case 1: achannels=atom_getint(argv+0); break; case 2: achannels=atom_getint(argv+0); xchannels=atom_getint(argv+1); have_x=1; break; case 3: achannels=atom_getint(argv+0); xchannels=atom_getint(argv+1); have_x=1; bufframes=atom_getint(argv+2); break; default: error("usage: [%s~ ]", s->s_name); return NULL; } if(achannels+xchannels>MAXSFCHANS) { /* ouch, user requested too much! */ if(achannels>MAXSFCHANS) { achannels=MAXSFCHANS; xchannels=0; } else { xchannels=MAXSFCHANS-achannels; } limiting=1; } nchannels=achannels+xchannels; if(limiting) { /* FIXXME: warning on channel limiting */ } if(have_x) { /* FIXXME: remove 'have_x' variable */ } if (bufframes <= 0) bufframes = DEFBUFPERCHAN; else if (bufframes < MINBUFSIZE) bufframes = MINBUFSIZE; else if (bufframes > MAXBUFSIZE) bufframes = MAXBUFSIZE; bufsize=bufframes*nchannels; buf = (t_sample*)getbytes(bufsize*sizeof(t_sample)); if (!buf) return (0); x = (t_ambix_read *)pd_new(ambix_read_class); x->x_fileformat=(gensym("ambix_read~")==s)?AMBIX_BASIC:AMBIX_EXTENDED; memset(&x->x_matrix, 0, sizeof(x->x_matrix)); if(AMBIX_EXTENDED==x->x_fileformat) x->x_matrixout = outlet_new(&x->x_obj, 0); else x->x_matrixout = NULL; for (i = 0; i < nchannels; i++) outlet_new(&x->x_obj, gensym("signal")); x->x_noutlets = nchannels; x->x_infoout = outlet_new(&x->x_obj, &s_bang); x->x_ambichannels = achannels; x->x_xtrachannels = xchannels; x->x_canvas = canvas_getcurrent(); pthread_mutex_init(&x->x_mutex, 0); pthread_cond_init(&x->x_requestcondition, 0); pthread_cond_init(&x->x_answercondition, 0); pthread_mutex_lock(&x->x_mutex); x->x_vecsize = DEFAULTVECSIZE; x->x_state = STATE_IDLE; x->x_clock = clock_new(x, (t_method)ambix_read_tick); x->x_buf = buf; x->x_bufsize = bufsize; x->x_bufframes = bufframes; x->x_fifosize = x->x_fifohead = x->x_fifotail = x->x_requestcode = 0; pthread_mutex_unlock(&x->x_mutex); pthread_create(&x->x_childthread, 0, ambix_read_child_main, x); return (x); } static void ambix_read_tick(t_ambix_read *x) { pthread_mutex_lock(&x->x_mutex); if(x->x_infoflags.f_eof) outlet_bang(x->x_infoout); if(x->x_infoflags.f_ambix) { t_atom atoms[1]; /* number of ambisonics channels */ SETFLOAT(atoms+0, (t_float)(x->x_ambix.ambichannels)); outlet_anything(x->x_infoout, gensym("ambichannels"), 1, atoms); /* number of non-ambisonics channels */ SETFLOAT(atoms+0, (t_float)(x->x_ambix.extrachannels)); outlet_anything(x->x_infoout, gensym("extrachannels"), 1, atoms); /* playback samplerate (might be different if we did resampling) */ SETFLOAT(atoms+0, (t_float)(x->x_ambix.samplerate)); outlet_anything(x->x_infoout, gensym("resamplerate"), 1, atoms); /* samplerate of file */ SETFLOAT(atoms+0, (t_float)(x->x_ambix.samplerate)); outlet_anything(x->x_infoout, gensym("samplerate"), 1, atoms); /* 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); } if(x->x_infoflags.f_matrix && x->x_matrixout) { int size=x->x_matrix.rows*x->x_matrix.cols; if(size) { uint32_t r, c, index; t_atom*ap=(t_atom*)getbytes(sizeof(t_atom)*(size+2)); SETFLOAT(ap+0, x->x_matrix.rows); SETFLOAT(ap+1, x->x_matrix.cols); index=2; for(r=0; rx_matrix.rows; r++) { for(c=0; cx_matrix.cols; c++) { SETFLOAT(ap+index, x->x_matrix.data[r][c]); index++; } } outlet_anything(x->x_matrixout, gensym("matrix"), size+2, ap); freebytes(ap, sizeof(t_atom)*(size+2)); } } memset(&x->x_infoflags, 0, sizeof(x->x_infoflags)); pthread_mutex_unlock(&x->x_mutex); } static t_int *ambix_read_perform(t_int *w) { t_ambix_read *x = (t_ambix_read *)(w[1]); int vecsize = x->x_vecsize, noutlets = x->x_noutlets, i, j; t_sample *fp; int skip=0; if(x->x_infoflags.f_matrix || x->x_infoflags.f_ambix ) { clock_delay(x->x_clock, 0); skip=1; } if (!skip && x->x_state == STATE_STREAM) { int wantframes; pthread_mutex_lock(&x->x_mutex); wantframes = vecsize; while ( !x->x_eof && x->x_fifohead >= x->x_fifotail && x->x_fifohead < x->x_fifotail + wantframes-1 ) { pthread_cond_signal(&x->x_requestcondition); pthread_cond_wait(&x->x_answercondition, &x->x_mutex); /* resync local variables -- bug fix thanks to Shahrokh */ vecsize = x->x_vecsize; wantframes = vecsize; } /* 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 ) { int xfersize; if (x->x_fileerror) { pd_error(x, "dsp: %s: %s", x->x_filename, (x->x_fileerror == EIO ? "unknown or bad header format" : strerror(x->x_fileerror))); } x->x_infoflags.f_eof=1; clock_delay(x->x_clock, 0); x->x_state = STATE_IDLE; /* if there's a partial buffer left, copy it out. */ xfersize = (x->x_fifohead - x->x_fifotail + 1); if (xfersize) { deinterleave_samples(x->x_buf+(x->x_fifotail*noutlets), noutlets, x->x_outvec, xfersize); vecsize -= xfersize; } /* then zero out the (rest of the) output */ for (i = 0; i < noutlets; i++) for (j = vecsize, fp = x->x_outvec[i] + xfersize; j--; ) *fp++ = 0; pthread_cond_signal(&x->x_requestcondition); pthread_mutex_unlock(&x->x_mutex); return (w+2); } deinterleave_samples(x->x_buf+(x->x_fifotail*noutlets), noutlets, x->x_outvec, vecsize); x->x_fifotail += wantframes; if (x->x_fifotail >= x->x_fifosize) { x->x_fifotail = 0; } if ((--x->x_sigcountdown) <= 0) { pthread_cond_signal(&x->x_requestcondition); x->x_sigcountdown = x->x_sigperiod; } pthread_mutex_unlock(&x->x_mutex); } else { for (i = 0; i < noutlets; i++) for (j = vecsize, fp = x->x_outvec[i]; j--; ) *fp++ = 0; } return (w+2); } static void ambix_read_start(t_ambix_read *x) { /* start making output. If we're in the "startup" state change to the "running" state. */ pthread_mutex_lock(&x->x_mutex); if (x->x_state == STATE_STARTUP) { x->x_state = STATE_STREAM; pthread_mutex_unlock(&x->x_mutex); } else { pthread_mutex_unlock(&x->x_mutex); pd_error(x, "ambix_read~: start requested with no prior 'open'"); } } static void ambix_read_stop(t_ambix_read *x) { /* LATER rethink whether you need the mutex just to set a variable? */ pthread_mutex_lock(&x->x_mutex); x->x_state = STATE_IDLE; x->x_requestcode = REQUEST_CLOSE; pthread_cond_signal(&x->x_requestcondition); pthread_mutex_unlock(&x->x_mutex); } static void ambix_read_float(t_ambix_read *x, t_floatarg f) { if (f != 0) ambix_read_start(x); else ambix_read_stop(x); } /* open method. Called as: open filename [skipframes] (if headersize is zero, header is taken to be automatically detected; thus, use the special "-1" to mean a truly headerless file.) */ static void ambix_read_open(t_ambix_read*x, t_symbol*s, t_float onsetframes) { t_symbol*filesym=get_filename(x->x_canvas, s); if (!filesym) return; pthread_mutex_lock(&x->x_mutex); x->x_requestcode = REQUEST_OPEN; x->x_filename = filesym->s_name; x->x_fifotail = 0; x->x_fifohead = 0; x->x_onsetframes = (onsetframes > 0 ? onsetframes : 0); x->x_eof = 0; x->x_fileerror = 0; x->x_state = STATE_STARTUP; pthread_cond_signal(&x->x_requestcondition); pthread_mutex_unlock(&x->x_mutex); } static void ambix_read_dsp(t_ambix_read *x, t_signal **sp) { int i, noutlets = x->x_noutlets; pthread_mutex_lock(&x->x_mutex); x->x_vecsize = sp[0]->s_n; x->x_sigperiod = (x->x_fifosize / (16 * x->x_vecsize)); for (i = 0; i < noutlets; i++) x->x_outvec[i] = sp[i]->s_vec; pthread_mutex_unlock(&x->x_mutex); dsp_add(ambix_read_perform, 1, x); } static void ambix_read_print(t_ambix_read *x) { post("state %d", x->x_state); post("fifo head %d", x->x_fifohead); post("fifo tail %d", x->x_fifotail); post("fifo size %d", x->x_fifosize); post("eof %d", x->x_eof); #if 0 if(1) { int c, f=0; int frames=x->x_fifosize; int channels=x->x_noutlets; float32_t*buf=x->x_buf; for(f=0; fx_fifosize; f++) { startpost("frame[%d]:", f); for(c=0; cx_mutex); x->x_requestcode = REQUEST_QUIT; pthread_cond_signal(&x->x_requestcondition); while (x->x_requestcode != REQUEST_NOTHING) { pthread_cond_signal(&x->x_requestcondition); pthread_cond_wait(&x->x_answercondition, &x->x_mutex); } pthread_mutex_unlock(&x->x_mutex); if (pthread_join(x->x_childthread, &threadrtn)) error("ambix_read_free: join failed"); pthread_cond_destroy(&x->x_requestcondition); pthread_cond_destroy(&x->x_answercondition); pthread_mutex_destroy(&x->x_mutex); freebytes(x->x_buf, x->x_bufsize); clock_free(x->x_clock); outlet_free(x->x_infoout); if(x->x_matrixout) outlet_free(x->x_matrixout); 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; ix_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; ix_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, (t_method)ambix_read_free, sizeof(t_ambix_read), 0, A_GIMME, A_NULL); class_addcreator((t_newmethod)ambix_read_new, gensym("ambix_readX~"), A_GIMME, 0); class_addfloat(ambix_read_class, (t_method)ambix_read_float); class_addmethod(ambix_read_class, (t_method)ambix_read_start, gensym("start"), A_NULL); class_addmethod(ambix_read_class, (t_method)ambix_read_stop, gensym("stop"), A_NULL); 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"); } AMBIX_EXPORT void ambix_readX_tilde_setup(void) { ambix_read_tilde_setup(); } ambix-0.1.1/samples/pd/ambix_write~-help.pd000066400000000000000000000040331300077024200206360ustar00rootroot00000000000000#N canvas 84 104 758 533 10; #X msg 646 30 \; pd dsp 1; #X msg 74 49 bang; #X obj 74 69 savepanel; #X text 356 432 is given in samples per channels (unlike [readsf~] where you specify it in bytes per channel); #X text 43 475 see also:; #X text 311 412 arguments: <#ambioutlet~s:4> <#extraoutlet~s:0> ; #X text 207 18 [ambix_write~] write an AMBIsonics eXchange file; #X msg 111 186 start; #X msg 111 215 stop; #X obj 166 308 osc~ 440; #X obj 145 477 ambix_read~; #X obj 235 477 ambix_readX~; #X obj 145 499 writesf~; #X text 233 308 ACN0; #X text 243 328 ACN1; #X obj 188 349 osc~ 220; #X text 253 348 ACN2; #X text 263 368 ACN3; #X obj 178 329 osc~ 110; #X obj 198 369 osc~ 330; #X obj 184 396 noise~; #X obj 74 418 ambix_write~ 4 1; #X text 240 396 extra0; #X text 216 47 The [ambix_write~] writes audio signals into an ambix soundfile \, much like [writesf~] for normal soundfiles.; #X text 217 78 [ambix_write~] creates a subthread whose task is to write audio streams to disk. You need not provide any disk access time between "open" and "start" \, but between "stop" and the next "open" you must give the object time to flush all the output to disk.; #X text 217 204 You can also write EXTENDED ambix files \, by specifying an adaptor-matrix _before_ sending the "open" message.; #X msg 113 252 matrix 4 4 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1; #X msg 116 273 matrix; #X text 167 273 specify NONE-matrix (switch to BASIC mode); #X text 434 257 (switches to EXTENDED mode); #X text 416 246 specify [4x4] identity matrix; #X text 214 149 When writing BASIC ambix files (the default \, if no 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 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; ambix-0.1.1/samples/pd/ambix_write~.c000066400000000000000000000544761300077024200175470ustar00rootroot00000000000000/* ambix_write~ - write AMBIsonics eXchange files in Pd -*- c -*- Copyright © 1997-1999 Miller Puckette . Copyright © 2012-2014 IOhannes m zmölnig . Copyright © 2016, Matthias Kronlachner 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 . [ambix_write~] is based on Pd's [writesf~], which is released under a 3-clause BSD-License ("Standard Improved BSD License") */ #ifndef _WIN32 # include # include #endif #include #ifdef _WIN32 # include #endif #include #include #include #include #include #include #include "winhacks.h" #define MAXSFCHANS 64 #define DEFAULTVECSIZE 128 #define READFRAMES 16384 #define WRITFRAMES 16384 #define DEFBUFPERCHAN 65536 #define MINBUFSIZE (4 * READFRAMES) #define MAXBUFSIZE 4194304 #define REQUEST_NOTHING 0 #define REQUEST_OPEN 1 #define REQUEST_CLOSE 2 #define REQUEST_QUIT 3 #define REQUEST_BUSY 4 #define STATE_IDLE 0 #define STATE_STARTUP 1 #define STATE_STREAM 2 /******************** soundfile access routines **********************/ static int ambixwrite_argparse(void *obj, int *p_argc, t_atom **p_argv, t_symbol **p_filesym, ambix_fileformat_t *p_fileformat, ambix_sampleformat_t *p_sampleformat, t_float *p_rate) { int argc = *p_argc; t_atom *argv = *p_argv; ambix_fileformat_t fileformat=AMBIX_EXTENDED; ambix_sampleformat_t sampleformat=AMBIX_SAMPLEFORMAT_PCM24; t_symbol *filesym; t_float rate = -1; while (argc > 0 && argv->a_type == A_SYMBOL && *argv->a_w.w_symbol->s_name == '-') { char *flag = argv->a_w.w_symbol->s_name + 1; if(0) { #if 0 } else if (!strcmp(flag, "nframes")) { if (argc < 2 || argv[1].a_type != A_FLOAT || ((nframes = argv[1].a_w.w_float) < 0)) goto usage; argc -= 2; argv += 2; #endif } else if (!strcmp(flag, "bytes")) { if (argc < 2 || argv[1].a_type != A_FLOAT) goto usage; switch(atom_getint(argv+1)) { case 2: sampleformat=AMBIX_SAMPLEFORMAT_PCM16; break; case 3: sampleformat=AMBIX_SAMPLEFORMAT_PCM24; break; case 4: sampleformat=AMBIX_SAMPLEFORMAT_FLOAT32; break; default: goto usage; } argc -= 2; argv += 2; } else if (!strcmp(flag, "r") || !strcmp(flag, "rate")) { if (argc < 2 || argv[1].a_type != A_FLOAT || ((rate = argv[1].a_w.w_float) <= 0)) goto usage; argc -= 2; argv += 2; } else goto usage; } if (!argc || argv->a_type != A_SYMBOL) goto usage; filesym = argv->a_w.w_symbol; argc--; argv++; *p_argc = argc; *p_argv = argv; if(p_filesym) *p_filesym = filesym; if(p_fileformat) *p_fileformat = fileformat; if(p_sampleformat) *p_sampleformat = sampleformat; if(p_rate) *p_rate = rate; return (0); usage: return (-1); } /* takes sample-blocks (per channel) and interleaves them */ /* to be used in perform() to get Pd-channels into the fifo */ static void interleave_samples(t_sample**invecs, uint32_t channels, t_sample*outbuf, uint32_t frames) { uint32_t f, c; for(f=0; fx_mutex); while (1) { if (x->x_requestcode == REQUEST_NOTHING) { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); } else if (x->x_requestcode == REQUEST_OPEN) { int sysrtn, writeframes; ambix_info_t ainfo; /* copy file stuff out of the data structure so we can relinquish the mutex while we're in open_soundfile(). */ 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; int localfifosize = x->x_fifosize; float32_t*ambibuf = NULL; float32_t*xtrabuf = NULL; double samplerate = x->x_samplerate; ambix_matrix_t*matrix=NULL; char *filename = strndup(x->x_filename, MAXPDSTRING); if(x->x_matrix) matrix=ambix_matrix_copy(x->x_matrix, matrix); /* alter the request code so that an ensuing "open" will get noticed. */ x->x_requestcode = REQUEST_BUSY; x->x_fileerror = 0; /* open the soundfile with the mutex unlocked */ pthread_mutex_unlock(&x->x_mutex); memset(&ainfo, 0, sizeof(ainfo)); ainfo.fileformat=fileformat; ainfo.ambichannels=ambichannels; 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. */ if (ambix) ambix_close(ambix); ambix=ambix_open(filename, AMBIX_WRITE, &ainfo); free(filename); if(matrix) { if(ambix) ambix_set_adaptormatrix(ambix, matrix); ambix_matrix_destroy(matrix); matrix=NULL; } if(ambix && onsetframes) { ambix_seek(ambix, onsetframes, SEEK_SET); } if(ambix) { ambibuf = (float32_t*)calloc(localfifosize*ambichannels, sizeof(float32_t)); xtrabuf = (float32_t*)calloc(localfifosize*xtrachannels, sizeof(float32_t)); } pthread_mutex_lock(&x->x_mutex); if(NULL==ambix) { x->x_eof = 1; x->x_fileerror = errno; x->x_requestcode = REQUEST_NOTHING; continue; } /* check if another request has been made; if so, field it */ if (x->x_requestcode != REQUEST_BUSY) continue; x->x_fifotail = 0; /* in a loop, wait for the fifo to have data and write it to disk */ while (x->x_requestcode == REQUEST_BUSY || (x->x_requestcode == REQUEST_CLOSE && x->x_fifohead != x->x_fifotail)) { int fifosize = x->x_fifosize, fifotail; t_sample*buf = x->x_buf; /* if the head is < the tail, we can immediately write from tail to end of fifo to disk; otherwise we hold off writing until there are at least WRITESIZE bytes in the buffer */ if (x->x_fifohead < x->x_fifotail || x->x_fifohead >= x->x_fifotail + WRITFRAMES || (x->x_requestcode == REQUEST_CLOSE && x->x_fifohead != x->x_fifotail)) { writeframes = (x->x_fifohead < x->x_fifotail ? fifosize : x->x_fifohead) - x->x_fifotail; if (writeframes > READFRAMES) writeframes = READFRAMES; } else { pthread_cond_signal(&x->x_answercondition); pthread_cond_wait(&x->x_requestcondition, &x->x_mutex); continue; } fifotail = x->x_fifotail; pthread_mutex_unlock(&x->x_mutex); if(localfifosizex_mutex); if (x->x_requestcode != REQUEST_BUSY && x->x_requestcode != REQUEST_CLOSE) break; if (sysrtn < writeframes) { x->x_fileerror = errno; break; } else { x->x_fifotail += sysrtn; if (x->x_fifotail == fifosize) x->x_fifotail = 0; } /* signal parent in case it's waiting for data */ pthread_cond_signal(&x->x_answercondition); } free(ambibuf);free(xtrabuf); } else if (x->x_requestcode == REQUEST_CLOSE || x->x_requestcode == REQUEST_QUIT) { int quit = (x->x_requestcode == REQUEST_QUIT); if (ambix) { pthread_mutex_unlock(&x->x_mutex); ambix_close(ambix); ambix=NULL; pthread_mutex_lock(&x->x_mutex); } x->x_requestcode = REQUEST_NOTHING; pthread_cond_signal(&x->x_answercondition); if (quit) break; } else { } } pthread_mutex_unlock(&x->x_mutex); return (0); } /******** the object proper runs in the calling (parent) thread ****/ //static void *ambix_write_new(t_floatarg fnchannels, t_floatarg fbufsize) { static void *ambix_write_new(t_symbol*s, int argc, t_atom*argv) { int achannels=0, xchannels=0, bufframes=-1, bufsize=0; int have_x=0, limiting=0; t_ambix_write *x; int nchannels, i; t_sample*buf; switch(argc) { case 0: achannels=4; break; case 1: achannels=atom_getint(argv+0); break; case 2: achannels=atom_getint(argv+0); xchannels=atom_getint(argv+1); have_x=1; break; case 3: achannels=atom_getint(argv+0); xchannels=atom_getint(argv+1); have_x=1; bufframes =atom_getint(argv+2); break; default: error("usage: [ambix_write~ ]"); return NULL; } if(achannels+xchannels>MAXSFCHANS) { /* ouch, user requested too much! */ if(achannels>MAXSFCHANS) { achannels=MAXSFCHANS; xchannels=0; } else { xchannels=MAXSFCHANS-achannels; } limiting=1; } nchannels=achannels+xchannels; if (bufframes <= 0) bufframes = DEFBUFPERCHAN; else if (bufframes < MINBUFSIZE) bufframes = MINBUFSIZE; else if (bufframes > MAXBUFSIZE) bufframes = MAXBUFSIZE; bufsize=bufframes*nchannels; buf = (t_sample*)getbytes(bufsize*sizeof(t_sample)); if (!buf) return (0); x = (t_ambix_write *)pd_new(ambix_write_class); if(limiting) { pd_error(x, "limiting to %d ambisonics channels and %d extra channels", achannels, xchannels); if(have_x) { /* FIXXME: remove 'have_x' variable */ } } for (i = 1; i < nchannels; i++) inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); x->x_f = 0; x->x_ambichannels = achannels; x->x_extrachannels = xchannels; x->x_matrix=NULL; x->x_canvas = canvas_getcurrent(); pthread_mutex_init(&x->x_mutex, 0); pthread_cond_init(&x->x_requestcondition, 0); pthread_cond_init(&x->x_answercondition, 0); pthread_mutex_lock(&x->x_mutex); x->x_vecsize = DEFAULTVECSIZE; x->x_insamplerate = x->x_samplerate = 0; x->x_state = STATE_IDLE; x->x_buf = buf; x->x_bufsize = bufsize; x->x_bufframes = bufframes; x->x_fifosize = x->x_fifohead = x->x_fifotail = x->x_requestcode = 0; pthread_mutex_unlock(&x->x_mutex); pthread_create(&x->x_childthread, 0, ambix_write_child_main, x); return (x); } static t_int *ambix_write_perform(t_int *w) { t_ambix_write *x = (t_ambix_write *)(w[1]); uint32_t achannels = x->x_ambichannels, xchannels=x->x_extrachannels; int vecsize = x->x_vecsize; uint32_t channels=achannels+xchannels; if (x->x_state == STATE_STREAM) { pthread_mutex_lock(&x->x_mutex); while (x->x_fifotail > x->x_fifohead && x->x_fifotail < x->x_fifohead + vecsize + 1) { pthread_cond_signal(&x->x_requestcondition); pthread_cond_wait(&x->x_answercondition, &x->x_mutex); } interleave_samples(x->x_invec, channels, x->x_buf+(x->x_fifohead*channels), vecsize); x->x_fifohead += vecsize; if (x->x_fifohead >= x->x_fifosize) x->x_fifohead = 0; if ((--x->x_sigcountdown) <= 0) { pthread_cond_signal(&x->x_requestcondition); x->x_sigcountdown = x->x_sigperiod; } pthread_mutex_unlock(&x->x_mutex); } return (w+2); } static void ambix_write_start(t_ambix_write *x) { /* start making output. If we're in the "startup" state change to the "running" state. */ pthread_mutex_lock(&x->x_mutex); if (x->x_state == STATE_STARTUP) { x->x_state = STATE_STREAM; pthread_mutex_unlock(&x->x_mutex); } else { pthread_mutex_unlock(&x->x_mutex); pd_error(x, "ambix_write: start requested with no prior 'open'"); } } static void ambix_write_stop(t_ambix_write *x) { /* LATER rethink whether you need the mutex just to set a Svariable? */ pthread_mutex_lock(&x->x_mutex); x->x_state = STATE_IDLE; x->x_requestcode = REQUEST_CLOSE; pthread_cond_signal(&x->x_requestcondition); pthread_mutex_unlock(&x->x_mutex); } /* open method. Called as: open [args] filename with args as in ambixwrite_argparse(). */ static void ambix_write_open(t_ambix_write *x, t_symbol *s, int argc, t_atom *argv) { t_symbol *filesym; t_float samplerate; ambix_fileformat_t fileformat; ambix_sampleformat_t sampleformat; if (x->x_state != STATE_IDLE) { ambix_write_stop(x); } if (ambixwrite_argparse(x, &argc, &argv, &filesym, &fileformat, &sampleformat, &samplerate)) { pd_error(x, "ambix_write~: usage: open [-bytes [234]] [-rate ####] filename"); return; } if (argc) pd_error(x, "extra argument(s) to ambix_write~: ignored"); pthread_mutex_lock(&x->x_mutex); while (x->x_requestcode != REQUEST_NOTHING) { pthread_cond_signal(&x->x_requestcondition); pthread_cond_wait(&x->x_answercondition, &x->x_mutex); } //x->x_bytespersample = bytespersamp; 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; x->x_eof = 0; x->x_fileerror = 0; x->x_state = STATE_STARTUP; if(0){} #if 0 else if (samplerate > 0) x->x_samplerate = samplerate; #endif else if (x->x_insamplerate > 0) x->x_samplerate = x->x_insamplerate; else x->x_samplerate = sys_getsr(); /* set fifosize from bufsize. fifosize must be a multiple of the number of bytes eaten for each DSP tick. */ x->x_fifosize = x->x_bufframes-(x->x_bufframes%x->x_vecsize); /* arrange for the "request" condition to be signalled 16 times per buffer */ x->x_sigcountdown = x->x_sigperiod = (x->x_fifosize / (16 * x->x_vecsize)); pthread_cond_signal(&x->x_requestcondition); pthread_mutex_unlock(&x->x_mutex); } static void ambix_write_dsp(t_ambix_write *x, t_signal **sp) { int i, ninlets = x->x_ambichannels+x->x_extrachannels; pthread_mutex_lock(&x->x_mutex); x->x_vecsize = sp[0]->s_n; x->x_fifosize = x->x_bufframes-(x->x_bufframes%x->x_vecsize); x->x_sigperiod = (x->x_fifosize / (16 * x->x_vecsize)); for (i = 0; i < ninlets; i++) x->x_invec[i] = sp[i]->s_vec; x->x_insamplerate = sp[0]->s_sr; pthread_mutex_unlock(&x->x_mutex); dsp_add(ambix_write_perform, 1, x); } static void ambix_write_print(t_ambix_write *x) { post("state %d", x->x_state); post("fifo head %d", x->x_fifohead); post("fifo tail %d", x->x_fifotail); post("fifo size %d", x->x_fifosize); post("eof %d", x->x_eof); } static void ambix_write_free(t_ambix_write *x) { /* request QUIT and wait for acknowledge */ void *threadrtn; pthread_mutex_lock(&x->x_mutex); x->x_requestcode = REQUEST_QUIT; /* post("stopping ambix_write thread..."); */ pthread_cond_signal(&x->x_requestcondition); while (x->x_requestcode != REQUEST_NOTHING) { /* post("signalling..."); */ pthread_cond_signal(&x->x_requestcondition); pthread_cond_wait(&x->x_answercondition, &x->x_mutex); } pthread_mutex_unlock(&x->x_mutex); if (pthread_join(x->x_childthread, &threadrtn)) error("ambix_write_free: join failed"); /* post("... done."); */ pthread_cond_destroy(&x->x_requestcondition); pthread_cond_destroy(&x->x_answercondition); pthread_mutex_destroy(&x->x_mutex); freebytes(x->x_buf, x->x_bufsize); if(x->x_matrix) ambix_matrix_destroy(x->x_matrix); x->x_matrix=NULL; } static void printmatrix(const ambix_matrix_t*mtx) { if(mtx) { float32_t**data=mtx->data; uint32_t r, c; post(" [%dx%d] = %p", mtx->rows, mtx->cols, mtx->data); for(r=0; rrows; r++) { for(c=0; ccols; c++) { startpost("%08f ", data[r][c]); } endpost(); } } endpost(); } static void ambix_write_matrix(t_ambix_write *x, t_symbol*s, int argc, t_atom*argv) { int rows, cols; float32_t*data=NULL; int count; if(x->x_matrix) ambix_matrix_destroy(x->x_matrix); x->x_matrix=NULL; if(argc>=2) { rows=atom_getint(argv+0); cols=atom_getint(argv+1); argc-=2; argv+=2; } else { pd_error(x, "invalid matrix message"); return; } if(argc!=rows*cols) { pd_error(x, "invalid matrix"); return; } data=(float32_t*)malloc(rows*cols*sizeof(float32_t)); for(count=0; countx_matrix=ambix_matrix_init(rows, cols, x->x_matrix); if(AMBIX_ERR_SUCCESS!=ambix_matrix_fill_data(x->x_matrix, data)) { pd_error(x, "invalid matrix data [%dx%d]=%p", rows, cols, data); if(x->x_matrix) ambix_matrix_destroy(x->x_matrix); x->x_matrix=NULL; } free(data); if(x->x_matrix) printmatrix(x->x_matrix); } AMBIX_EXPORT void ambix_write_tilde_setup(void) { ambix_write_class = class_new(gensym("ambix_write~"), (t_newmethod)ambix_write_new, (t_method)ambix_write_free, sizeof(t_ambix_write), 0, A_GIMME, A_NULL); class_addmethod(ambix_write_class, (t_method)ambix_write_start, gensym("start"), A_NULL); class_addmethod(ambix_write_class, (t_method)ambix_write_stop, gensym("stop"), A_NULL); class_addmethod(ambix_write_class, (t_method)ambix_write_matrix, gensym("matrix"), A_GIMME, A_NULL); class_addmethod(ambix_write_class, (t_method)ambix_write_dsp, gensym("dsp"), A_NULL); class_addmethod(ambix_write_class, (t_method)ambix_write_open, gensym("open"), A_GIMME, A_NULL); class_addmethod(ambix_write_class, (t_method)ambix_write_print, gensym("print"), A_NULL); CLASS_MAINSIGNALIN(ambix_write_class, t_ambix_write, x_f); } ambix-0.1.1/samples/pd/winhacks.c000066400000000000000000000022001300077024200166200ustar00rootroot00000000000000/* winhacks.h - AMBIsonics eXchange hacks for w32 compilation -*- c -*- Copyright © 2012 IOhannes m zmölnig . Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz Copyright © 2005 Free Software Foundation, Inc. Written by Kaveh R. Ghazi . 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 . */ #ifdef __MINGW32__ int _get_output_format( void ) { return 1; } #endif /* __MINGW32__ */ ambix-0.1.1/samples/pd/winhacks.h000066400000000000000000000022321300077024200166320ustar00rootroot00000000000000/* winhacks.h - AMBIsonics eXchange hacks for w32 compilation -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #ifndef WINHACKS_H #define WINHACKS_H #ifdef __MINGW32__ int _get_output_format( void ); #endif /* mingw */ #include "replacement/strndup.h" #ifdef _MSC_VER # define snprintf _snprintf #endif /* MSVC */ #endif /* WINHACKS_H */ ambix-0.1.1/utils/000077500000000000000000000000001300077024200137445ustar00rootroot00000000000000ambix-0.1.1/utils/Makefile.am000066400000000000000000000026431300077024200160050ustar00rootroot00000000000000SUBDIRS = bin_PROGRAMS = \ ambix-info noinst_PROGRAMS = \ ambix-dump \ ambix-matrix \ ambix-test if HAVE_SNDFILE bin_PROGRAMS += \ ambix-interleave \ ambix-deinterleave if HAVE_JACK SUBDIRS += jcommon bin_PROGRAMS += \ ambix-jplay \ ambix-jrecord endif HAVE_JACK endif HAVE_SNDFILE AM_CPPFLAGS = -I$(top_srcdir)/libambix -I$(top_srcdir) LDADD = $(top_builddir)/libambix/src/libambix.la ambix_info_SOURCES = ambix-info.c ambix_interleave_SOURCES = ambix-interleave.c ambix_interleave_CFLAGS = @SNDFILE_CFLAGS@ ambix_interleave_LDADD = $(top_builddir)/libambix/src/libambix.la @SNDFILE_LIBS@ ambix_deinterleave_SOURCES = ambix-deinterleave.c ambix_deinterleave_CFLAGS = @SNDFILE_CFLAGS@ ambix_deinterleave_LDADD = $(top_builddir)/libambix/src/libambix.la @SNDFILE_LIBS@ ambix_test_SOURCES = ambix-test.c ambix_dump_SOURCES = ambix-dump.c ambix_matrix_SOURCES = ambix-matrix.c ambix_jplay_CFLAGS = @JACK_CFLAGS@ @SAMPLERATE_CFLAGS@ @PTHREAD_CFLAGS@ ambix_jplay_LDADD = $(top_builddir)/libambix/src/libambix.la \ $(builddir)/jcommon/libjcommon.la \ @JACK_LIBS@ @SAMPLERATE_LIBS@ @PTHREAD_LIBS@ ambix_jplay_SOURCES = ambix-jplay.c ambix_jrecord_CFLAGS = @JACK_CFLAGS@ @SAMPLERATE_CFLAGS@ @PTHREAD_CFLAGS@ @SNDFILE_CFLAGS@ ambix_jrecord_LDADD = $(top_builddir)/libambix/src/libambix.la \ $(builddir)/jcommon/libjcommon.la \ @JACK_LIBS@ @SAMPLERATE_LIBS@ @PTHREAD_LIBS@ @SNDFILE_LIBS@ ambix_jrecord_SOURCES = ambix-jrecord.c ambix-0.1.1/utils/README.txt000066400000000000000000000037331300077024200154500ustar00rootroot00000000000000ambix-utils: collection of utilities to deal with ambix files ambix-info: get info about an ambix file ambix-interleave -o [-O ] [-X ] [ ...] merge several (multi-channel) audio files into a single ambix file; infile1 becomes W-channel, infile2 becomes X-channel,... by default this will write an 'ambix simple' file (only full sets are accepted) eventually files are written as 'ambix extended' file with adaptor matrix set to unity if 'order' is specified, all inchannels not needed for the full set are written as 'extrachannels' 'matrixfile' is a soundfile/octavefile that is interpreted as matrix: each channel is a row, sampleframes are columns if 'matrix' is specified it must construct a full-set (it must satisfy rows=(O+1)^2) if 'matrix' is specified, all inchannels not needed to reconstruct to a full set are 'extrachannels' if both 'order' and 'matrix' are specified they must match ambix-deinterleave split an ambix file into ambi/non-ambi data split an ambi file into separate channels (decoded) if the 'infile' is called 'data.caf', the output files are called 'data_ambisonics_00.caf' and 'data_extra_00.caf', where the number for ambisonics channels is the ACN (ambisonics channel number (starting from 0)) and the numbers for extra channels start at 0 ambix-jplay playback an ambix file via jack jack channels are called "ambisonics_%02d" and "extra_%02d" reduced sets are always expanded to full sets Disclaimer: this is a port of jack.play from jack-tools Copyright (c) 2003-2010, Rohan Drape Copyright (c) 2012, IOhannes m zmölnig, IEM Licensed under the GPL-2 (or later) ambix-jrec [-O ] [-X ] [-x <#extrachannels>] record an ambix file via jack (for options see ambix-interleave) Disclaimer: this is a port of jack.rec from jack-tools Copyright (c) 2003-2010, Rohan Drape Copyright (c) 2012, IOhannes m zmölnig, IEM Licensed under the GPL-2 (or later) ambix-0.1.1/utils/ambix-deinterleave.c000066400000000000000000000352671300077024200176720ustar00rootroot00000000000000/* ambix_deinterleave - create an ambix file -*- c -*- Copyright © 2012-2014 IOhannes m zmölnig . 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 . */ /** * @brief ambix_deinterleave - merge several (multi-channel) audio files into a single ambix file * * ambix_deinterleave -o [-O ] [-X ] [ ...] * merge several (multi-channel) audio files into a single ambix file; * infile1 becomes W-channel, infile2 becomes X-channel,... * by default this will write an 'ambix basic' file (only full sets are accepted) * eventually files are written as 'ambix extended' file with adaptor matrix set to unity * if 'order' is specified, all inchannels not needed for the full set are written as 'extrachannels' * 'matrixfile' is a soundfile/octavefile that is interpreted as matrix: each channel is a row, sampleframes are columns * if 'matrix' is specified it must construct a full-set (it must satisfy rows=(O+1)^2) * if 'matrix' is specified, all inchannels not needed to reconstruct to a full set are 'extrachannels' * if both 'order' and 'matrix' are specified they must match */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "ambix/ambix.h" #include "sndfile.h" #include #include #include #ifdef _MSC_VER # define strdup _strdup # define snprintf _snprintf #endif #define MARK() printf("%s:%d[%s]\n", __FILE__, __LINE__, __FUNCTION__) typedef struct ai_t { ambix_info_t info; char*infilename; ambix_t*inhandle; char*prefix,*suffix; SNDFILE**outhandles; SF_INFO *outinfo; uint32_t numOuts; ambix_matrix_t matrix; uint32_t blocksize; #define DEFAULT_BLOCKSIZE 1024 #define MAX_FILENAMESIZE 1024 } ai_t; static void print_usage(const char*path); static void print_version(const char*path); static ai_t*ai_close(ai_t*ai); #define DEFAULT_SUFFIX ".wav" static char*ai_prefix(const char*filename) { char*result=NULL; const char*last=strrchr(filename, '.'); if(last) { int length=last-filename; result=(char*)calloc(sizeof(char), strlen(filename)); strncpy(result, filename, length); result[length]='-'; result[length+1]='\0'; return result; } result=strdup("outfile-"); 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 blocksize=0; while(argc) { if(!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) { print_usage(name); exit(0); } if(!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version")) { print_version(name); exit(0); } if(!strcmp(argv[0], "-p") || !strcmp(argv[0], "--prefix")) { if(argc>1) { //printf("prefix: '%s'\n", argv[1]); ai->prefix=strdup(argv[1]); argv+=2; argc-=2; continue; } return ai_close(ai); } if(!strcmp(argv[0], "-s") || !strcmp(argv[0], "--suffix")) { if(argc>1) { ai->suffix=strdup(argv[1]); argv+=2; argc-=2; continue; } return ai_close(ai); } if(!strcmp(argv[0], "-b") || !strcmp(argv[0], "--blocksize")) { if(argc>1) { blocksize=atoi(argv[1]); argv+=2; argc-=2; continue; } return ai_close(ai); } if(argc) { ai->infilename=strdup(argv[0]); } break; } if(!ai->infilename) return ai_close(ai); if(!ai->prefix) ai->prefix=ai_prefix(ai->infilename); if(!ai->suffix) ai->suffix=strdup(DEFAULT_SUFFIX); if(blocksize>0) ai->blocksize=blocksize; else ai->blocksize=DEFAULT_BLOCKSIZE; return ai; } static ai_t*ai_close(ai_t*ai) { uint32_t i; if(!ai)return NULL; // printf("closing %d outhandles %p\n", ai->numOuts, ai->outhandles); if(ai->outhandles) { for(i=0; inumOuts; i++) { SNDFILE*outhandle=ai->outhandles[i]; if(outhandle) { int err=sf_close(outhandle); if(err!=0) { ; // printf("closing outhandle[%d] returned %d\n", i, err); } } ai->outhandles[i]=NULL; } free(ai->outhandles); } ai->outhandles=NULL; if(ai->outinfo) free(ai->outinfo); ai->outinfo=NULL; if(ai->inhandle) { ambix_close(ai->inhandle); } ai->inhandle=NULL; if(ai->prefix) free(ai->prefix); ai->prefix=NULL; if(ai->suffix) free(ai->suffix); ai->suffix=NULL; if(ai->infilename) free(ai->infilename); ai->infilename=NULL; ambix_matrix_deinit (&ai->matrix); free(ai); return NULL; } static ai_t*ai_open_input(ai_t*ai) { const ambix_matrix_t*matrix=NULL; if(!ai)return ai; if(!ai->inhandle) { ai->info.fileformat=AMBIX_EXTENDED; ai->inhandle=ambix_open(ai->infilename, AMBIX_READ, &ai->info); } if(!ai->inhandle) { return ai_close(ai); } if((ai->info.ambichannels < 1) && (ai->info.extrachannels < 1)) { return ai_close(ai); } if(ai->info.ambichannels>0) { matrix=ambix_get_adaptormatrix(ai->inhandle); if(!matrix) { return ai_close(ai); } ambix_matrix_copy(matrix, &ai->matrix); } else { ambix_matrix_deinit(&ai->matrix); } return ai; } static ai_t*ai_open_output(ai_t*ai) { SF_INFO info; int format=0; int32_t chan, channel, ambichannels, extrachannels; if(!ai)return ai; ambichannels=ai->matrix.rows; extrachannels=ai->info.extrachannels; if(!ai->outhandles) { ai->numOuts=ambichannels+extrachannels; ai->outhandles=(SNDFILE**)calloc(ai->numOuts, sizeof(SNDFILE*)); ai->outinfo =(SF_INFO*)calloc(ai->numOuts, sizeof(SF_INFO)); } if(!ai->outhandles) { return ai_close(ai); } if(!ai->outinfo) { return ai_close(ai); } switch(ai->info.sampleformat) { case(AMBIX_SAMPLEFORMAT_PCM16) : format |= SF_FORMAT_PCM_16; break; case(AMBIX_SAMPLEFORMAT_PCM24) : format |= SF_FORMAT_PCM_24; break; case(AMBIX_SAMPLEFORMAT_PCM32) : format |= SF_FORMAT_PCM_32; break; default: case(AMBIX_SAMPLEFORMAT_FLOAT32): format |= SF_FORMAT_FLOAT ; break; } info.format = format | SF_FORMAT_WAV; info.frames = ai->info.frames; info.samplerate = (int)(ai->info.samplerate); info.channels = 1; if(!sf_format_check(&info)) { printf("output format invalid!\n"); printf(" format = 0x%x\n", info.format); printf(" rate = %d\n", info.samplerate); printf(" channels = %d\n", info.channels); } channel=0; // printf("creating outfiles for %d/%d\n", ambichannels, extrachannels); for(chan=0; chanprefix, chan, ai->suffix); filename[MAX_FILENAMESIZE-1]=0; // printf("ambifile%d=%s\n", chan, filename); memcpy(&ai->outinfo[channel], &info, sizeof(info)); ai->outhandles[channel]=sf_open(filename, SFM_WRITE, &ai->outinfo[channel]); // printf("created outhandle[%d] %p\n", channel, ai->outhandles[channel]); if(!ai->outhandles[channel]) { return ai_close(ai); } channel++; } for(chan=0; chanprefix, chan, ai->suffix); filename[MAX_FILENAMESIZE-1]=0; //printf("extrafile%d=%s\n", chan, filename); memcpy(&ai->outinfo[channel], &info, sizeof(info)); ai->outhandles[channel]=sf_open(filename, SFM_WRITE, &ai->outinfo[channel]); if(!ai->outhandles[channel]) { return ai_close(ai); } channel++; } return ai; } static void deinterleaver(float*dest, const float*source, uint64_t frames, uint32_t channels) { uint64_t frame; for(frame=0; framematrix; rows=matrix->rows; cols=matrix->cols; ambichannels=ai->info.ambichannels; extrachannels=ai->info.extrachannels; fullambichannels=rows; if(cols!=ambichannels) { printf("columns do not match ambichannels %d!=%d\n", cols, ambichannels); } /* read the raw data */ framed=ambix_readf_float32(ai->inhandle, rawdata, extradata, frames); if(frames!=framed) { printf("failed reading %d frames (got %d)\n", (int)frames, (int)framed); return ai_close(ai); } /* decode the ambisonics data */ // printf("reading ambidata %p & %p\n", rawdata, cookeddata); channel=0; if(rawdata && cookeddata) { if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(cookeddata, matrix, rawdata, frames)) { printf("failed decoding\n"); return ai_close(ai); } /* deinterleave the buffer */ deinterleaver(deinterleavebuffer, cookeddata, frames, fullambichannels); /* store the ambisonics data */ for(c=0; couthandles[channel], deinterleavebuffer+c*frames, frames); if(frames!=framed) { printf("failed writing %d ambiframes to %d (got %d)\n", (int)frames, (int)channel, (int)framed); return ai_close(ai); } channel++; } } /* store the extra data */ // printf("reading extradata %p\n", extradata); if(extradata) { deinterleaver(deinterleavebuffer, extradata, frames, extrachannels); for(c=0; couthandles[channel], deinterleavebuffer+c*frames, frames); if(frames!=framed) { printf("failed writing %d extraframes to %d (got %d)\n", (int)frames, (int)channel, (int)framed); return ai_close(ai); } channel++; } } //printf("reading done\n"); return ai; } static ai_t*ai_copy(ai_t*ai) { uint64_t blocksize=0, blocks=0; uint64_t frames=0; float32_t*rawdata=NULL, *cookeddata=NULL, *extradata=NULL,*deinterleavebuf=NULL; uint64_t size=0; if(!ai)return ai; blocksize=ai->blocksize; if(blocksize<1) blocksize=DEFAULT_BLOCKSIZE; frames=ai->info.frames; if(ai->info.ambichannels) { const ambix_matrix_t*matrix=&ai->matrix; if(!matrix) { printf("no adaptor matrix found...\n"); return ai_close(ai); } size=(ai->info.ambichannels)*blocksize; rawdata=(float32_t*)malloc(sizeof(float32_t)*size); cookeddata=(float32_t*)malloc(sizeof(float32_t)*(matrix->rows)*blocksize); if((matrix->rows)*blocksize > size) size=(matrix->rows)*blocksize; } if(ai->info.extrachannels) { extradata=(float32_t*)malloc(sizeof(float32_t)*(ai->info.extrachannels)*blocksize); if((ai->info.extrachannels)*blocksize > size) size=(ai->info.extrachannels)*blocksize; } deinterleavebuf=(float32_t*)malloc(sizeof(float32_t)*size); if(NULL==deinterleavebuf) { free(rawdata); free(cookeddata); free(extradata); return ai_close(ai); } while(frames>blocksize) { blocks++; if(!ai_copy_block(ai, rawdata, cookeddata, extradata, deinterleavebuf, blocksize)) { return ai_close(ai); } frames-=blocksize; } if(!ai_copy_block(ai, rawdata, cookeddata, extradata, deinterleavebuf, frames)) { return ai_close(ai); } free(rawdata); free(cookeddata); free(extradata); free(deinterleavebuf); // printf("reading really done %p\n", ai); return ai; } static int ambix_deinterleave(ai_t*ai) { ai_t*result=ai_open_input(ai); // if(result)printf("success @ %d!\n", __LINE__); result=ai_open_output(result); //if(result)printf("success @ %d!\n", __LINE__); result=ai_copy(result); //if(result)printf("success @ %d!\n", __LINE__); if(result) { printf("Deinterleaving '%s' to %d files (%s*%s)\n", ai->infilename, ai->numOuts, ai->prefix, ai->suffix); ai_close(result); } //if(result)printf("success @ %d!\n", __LINE__); // printf("deinterleave done %p\n", result); return (result!=NULL); } int main(int argc, char**argv) { ai_t*ai=ai_cmdline(argv[0], argc-1, argv+1); if(!ai) { print_usage(argv[0]);//"ambix_deinterleave"); return 1; } return ambix_deinterleave(ai); } void print_usage(const char*name) { printf("\n"); printf("Usage: %s [options] infile\n", name); printf("Split an ambix file into several mono files\n"); printf("\n"); printf("Options:\n"); printf(" -h, --help print this help\n"); printf(" -v, --version print version info\n"); printf(" -p, --prefix output prefix\n"); printf("\n"); printf( "\nThis splits an ambix file into several mono files, naming them according to type:" "\nIf infile is 'FieldRecording.caf', this will extract audio data into" "\n'FieldRecording-ambi000.caf', 'FieldRecording-ambi001.caf', ..., 'FieldRecording-extra000.caf', ..." "\n" ); printf("\n"); #ifdef PACKAGE_BUGREPORT printf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL printf("Home page: %s\n", PACKAGE_URL); #endif } void print_version(const char*name) { #ifdef PACKAGE_VERSION printf("%s %s\n", name, PACKAGE_VERSION); #endif printf("\n"); printf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); printf("\n"); printf("License LGPLv2.1: GNU Lesser GPL version 2.1 or later \n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf("Written by IOhannes m zmoelnig \n"); } ambix-0.1.1/utils/ambix-dump.c000066400000000000000000000253271300077024200161640ustar00rootroot00000000000000/* ambix_dump - create an ambix file -*- c -*- Copyright © 2012-2014 IOhannes m zmölnig . 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 . */ /** * @brief ambix_dump - merge several (multi-channel) audio files into a single ambix file * * ambix_dump -o [-O ] [-X ] [ ...] * merge several (multi-channel) audio files into a single ambix file; * infile1 becomes W-channel, infile2 becomes X-channel,... * by default this will write an 'ambix basic' file (only full sets are accepted) * eventually files are written as 'ambix extended' file with adaptor matrix set to unity * if 'order' is specified, all inchannels not needed for the full set are written as 'extrachannels' * 'matrixfile' is a soundfile/octavefile that is interpreted as matrix: each channel is a row, sampleframes are columns * if 'matrix' is specified it must construct a full-set (it must satisfy rows=(O+1)^2) * if 'matrix' is specified, all inchannels not needed to reconstruct to a full set are 'extrachannels' * if both 'order' and 'matrix' are specified they must match */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "ambix/ambix.h" #include #include #include #include "replacement/strndup.h" #define MARK() printf("%s:%d[%s]\n", __FILE__, __LINE__, __FUNCTION__) typedef struct ai_t { ambix_t*ambix; ambix_info_t info; char*filename; const ambix_matrix_t*matrix; ambix_fileformat_t format; int dumpRaw; int dumpCooked; int dumpXtra; uint32_t blocksize; #define DEFAULT_BLOCKSIZE 1024 #define MAX_FILENAMESIZE 1024 } 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 ai_t*ai_cmdline(const char*name, int argc, char**argv) { ai_t*ai=(ai_t*)calloc(1, sizeof(ai_t)); uint32_t blocksize=0; int dumpRaw=0, dumpCooked=0, dumpXtra=0; ambix_fileformat_t format=0; while(argc) { if(!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) { print_usage(name); exit(0); } if(!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version")) { print_version(name); exit(0); } if(!strcmp(argv[0], "-r") || !strcmp(argv[0], "--raw")) { dumpRaw=1; argv++; argc--; continue; } if(!strcmp(argv[0], "-a") || !strcmp(argv[0], "--ambisonics")) { dumpCooked=1; argv++; argc--; continue; } if(!strcmp(argv[0], "-x") || !strcmp(argv[0], "--extra")) { dumpXtra=1; argv++; argc--; continue; } if(!strcmp(argv[0], "-B") || !strcmp(argv[0], "--basic")) { format=AMBIX_BASIC; argv++; argc--; continue; } if(!strcmp(argv[0], "-X") || !strcmp(argv[0], "--extended")) { format=AMBIX_EXTENDED; argv++; argc--; continue; } if(!strcmp(argv[0], "-b") || !strcmp(argv[0], "--blocksize")) { if(argc>1) { blocksize=atoi(argv[1]); argv+=2; argc-=2; continue; } return ai_close(ai); } if(argc) { ai->filename=strndup(argv[0], 1024); } break; } if(!ai->filename) { return ai_close(ai); } if(blocksize>0) ai->blocksize=blocksize; else ai->blocksize=DEFAULT_BLOCKSIZE; if(!dumpRaw && !dumpCooked && !dumpXtra) { dumpCooked=1; } if(format>0) ai->format = format; else ai->format = AMBIX_EXTENDED; if(format == AMBIX_BASIC) dumpRaw=dumpRaw || dumpCooked; ai->dumpRaw=dumpRaw; ai->dumpCooked=dumpCooked; ai->dumpXtra=dumpXtra; return ai; } static ai_t*ai_close(ai_t*ai) { if(!ai)return NULL; // printf("closing %d outhandles %p\n", ai->numOuts, ai->outhandles); if(ai->ambix) { ambix_close(ai->ambix); } free(ai->filename); ai->filename=NULL; ai->ambix=NULL; free(ai); ai=NULL; return ai; } static ai_t*ai_open_input(ai_t*ai) { if(!ai)return ai; if(!ai->ambix) { ai->info.fileformat=ai->format; ai->ambix=ambix_open(ai->filename, AMBIX_READ, &ai->info); } if(!ai->ambix) { return ai_close(ai); } if((ai->info.ambichannels < 1) && (ai->info.extrachannels < 1)) { return ai_close(ai); } ai->matrix=ambix_get_adaptormatrix(ai->ambix); return ai; } static void printf_block(const char*prefix, float*data, uint32_t channels, uint32_t frames) { printf("%s:*[%dx%d]@%p\n", prefix, frames, channels, data); if(data) { uint32_t c, f; for(f=0; finfo.ambichannels; extrachannels=ai->info.extrachannels; matrix=ai->matrix; if(matrix) { uint32_t rows=matrix->rows; uint32_t cols=matrix->cols; fullambichannels=rows; if(cols!=ambichannels) { printf("columns do not match ambichannels %d!=%d\n", cols, ambichannels); } } else { fullambichannels=ambichannels; } /* read the raw data */ if(frames!=ambix_readf_float32(ai->ambix, rawdata, extradata, frames)) { return ai_close(ai); } if(ai->dumpRaw) { printf_block("RAW", rawdata, ambichannels, frames); } /* decode the ambisonics data */ // printf("reading ambidata %p & %p\n", rawdata, cookeddata); if(rawdata && cookeddata && matrix) { if(AMBIX_ERR_SUCCESS!=ambix_matrix_multiply_float32(cookeddata, matrix, rawdata, frames)) { printf("failed decoding\n"); return ai_close(ai); } } if(ai->dumpCooked) { printf_block("AMB", cookeddata, fullambichannels, frames); } /* dump the extra data */ // printf("reading extradata %p\n", extradata); if(ai->dumpXtra) { printf_block("XTR", extradata, extrachannels, frames); } //printf("reading done\n"); return ai; } static ai_t*ai_dodump(ai_t*ai) { uint64_t blocksize=0, blocks=0; uint64_t frames=0; float32_t*rawdata=NULL, *cookeddata=NULL, *extradata=NULL,*dumpbuf=NULL; uint64_t size=0; if(!ai)return ai; blocksize=ai->blocksize; if(blocksize<1) blocksize=DEFAULT_BLOCKSIZE; frames=ai->info.frames; if(ai->info.ambichannels) { const ambix_matrix_t*matrix=ai->matrix; if(!matrix) { printf("no adaptor matrix founde...\n"); // return ai_close(ai); } size=(ai->info.ambichannels)*blocksize; rawdata=(float32_t*)malloc(sizeof(float32_t)*size); if(matrix) { cookeddata=(float32_t*)malloc(sizeof(float32_t)*(matrix->rows)*blocksize); if((matrix->rows)*blocksize > size) size=(matrix->rows)*blocksize; } } if(ai->info.extrachannels) { extradata=(float32_t*)malloc(sizeof(float32_t)*(ai->info.extrachannels)*blocksize); if((ai->info.extrachannels)*blocksize > size) size=(ai->info.extrachannels)*blocksize; } dumpbuf=(float32_t*)malloc(sizeof(float32_t)*size); while(frames>blocksize) { blocks++; if(!ai_dump_block(ai, rawdata, cookeddata, extradata, dumpbuf, blocksize)) { ai=NULL; break; } frames-=blocksize; } if(ai && !ai_dump_block(ai, rawdata, cookeddata, extradata, dumpbuf, frames)) { ai=NULL; } free(rawdata); free(cookeddata); free(extradata); free(dumpbuf); // printf("reading really done %p\n", ai); return ai; } static int ambix_dump(ai_t*ai) { ai_t*result=ai_open_input(ai); // if(result)printf("success @ %d!\n", __LINE__); result=ai_dodump(result); //if(result)printf("success @ %d!\n", __LINE__); if(result) ai_close(result); //if(result)printf("success @ %d!\n", __LINE__); // printf("dump done %p\n", result); return (result!=NULL); } int main(int argc, char**argv) { ai_t*ai=ai_cmdline(argv[0], argc-1, argv+1); if(!ai) { print_usage(argv[0]);//"ambix_dump"); return 1; } return ambix_dump(ai); } void print_usage(const char*name) { printf("\n"); printf("Usage: %s [options] infile\n", name); printf("Print sample values of an ambix file to the stdout\n"); printf("\n"); printf("Options:\n"); printf(" -h, --help print this help\n"); printf(" -V, --version print version info\n"); printf(" -r, --raw dump raw ambisonics data\n"); printf(" -a, --ambisonics dump cooked ambisonics data\n"); printf(" -x, --extra dump additional audio data\n"); printf(" -B, --basic open as AMBIX_BASIC\n"); printf(" -X, --extended open as AMBIX_EXTENDED\n"); printf("\n"); printf( "\nDumps the contents of an ambix file to the stderr in human readable form:" "\neach frame is output in a separate line, with the channels separated by space" "\n" ); printf("\n"); #ifdef PACKAGE_BUGREPORT printf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL printf("Home page: %s\n", PACKAGE_URL); #endif } void print_version(const char*name) { #ifdef PACKAGE_VERSION printf("%s %s\n", name, PACKAGE_VERSION); #endif printf("\n"); printf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); printf("\n"); printf("License LGPLv2.1: GNU Lesser GPL version 2.1 or later \n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf("Written by IOhannes m zmoelnig \n"); } ambix-0.1.1/utils/ambix-info.c000066400000000000000000000126111300077024200161420ustar00rootroot00000000000000/* ambix_info - display info about an ambix file -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "ambix/ambix.h" #include #include #include 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; const ambix_matrix_t*matrix; memset(&info, 0, sizeof(info)); printf("Open file '%s': ", path); ambix=ambix_open(path, AMBIX_READ, &info); if(!ambix) { printf("failed\n"); return; } else printf("OK\n"); printf("Frames\t: %d\n", (int)(info.frames)); printf("Samplerate\t: %f\n", info.samplerate); printf("Sampleformat\t: %d (", info.sampleformat); switch(info.sampleformat) { case(AMBIX_SAMPLEFORMAT_NONE): printf("NONE"); break; case(AMBIX_SAMPLEFORMAT_PCM16): printf("PCM16"); break; 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"); printf("ambiXformat\t: %d (", info.fileformat); switch(info.fileformat) { case(AMBIX_NONE): printf("NONE"); break; case(AMBIX_BASIC): printf("BASIC"); break; case(AMBIX_EXTENDED): printf("EXTENDED"); break; default: printf("**unknown** 0x%04X", info.fileformat); } printf(")\n"); printf("Ambisonics channels\t: %d\n", info.ambichannels); printf("Non-Ambisonics channels\t: %d\n", info.extrachannels); matrix=ambix_get_adaptormatrix(ambix); printf("Reconstruction matrix\t: "); if(!matrix) { printf("**none**"); } else { uint32_t r, c; printf("[%dx%d]\n", matrix->rows, matrix->cols); for(r=0; rrows; r++) { printf("\t"); for(c=0; ccols; c++) { printf("%.6f ", matrix->data[r][c]); } printf("\n"); } } 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"); else printf("OK\n"); } int main(int argc, char**argv) { if(argc>1) { int i; if((!strcmp(argv[1], "-V")) || (!strcmp(argv[1], "--version"))) print_version(argv[0]); if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) print_usage(argv[0]); for(i=1; i\n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf("Written by IOhannes m zmoelnig \n"); exit(1); } ambix-0.1.1/utils/ambix-interleave.c000066400000000000000000000501611300077024200173470ustar00rootroot00000000000000/* ambix_interleave - create an ambix file -*- c -*- Copyright © 2012-2016 IOhannes m zmölnig . 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 . */ /** * @brief ambix_interleave - merge several (multi-channel) audio files into a single ambix file * * ambix_interleave -o [-O ] [-X ] [ ...] * merge several (multi-channel) audio files into a single ambix file; * infile1 becomes W-channel, infile2 becomes X-channel,... * by default this will write an 'ambix basic' file (only full sets are accepted) * eventually files are written as 'ambix extended' file with adaptor matrix set to unity * if 'order' is specified, all inchannels not needed for the full set are written as 'extrachannels' * 'matrixfile' is a soundfile/octavefile that is interpreted as matrix: each channel is a row, sampleframes are columns * if 'matrix' is specified it must construct a full-set (it must satisfy rows=(O+1)^2) * if 'matrix' is specified, all inchannels not needed to reconstruct to a full set are 'extrachannels' * if both 'order' and 'matrix' are specified they must match */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "sndfile.h" #include "ambix/ambix.h" #include #include #include #include #ifdef _MSC_VER # define strdup _strdup #endif #define MARK() printf("%s:%d[%s]\n", __FILE__, __LINE__, __FUNCTION__) typedef struct ai_t { ambix_info_t info; char**infilenames; SNDFILE**inhandles; SF_INFO *ininfo; uint32_t numIns; char*outfilename; 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; #define DEFAULT_BLOCKSIZE 1024 } 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; SNDFILE*file=NULL; uint32_t rows, cols; float*data=NULL; ai_t*result=NULL; ambix_matrix_t*mtx=NULL; uint32_t frames; memset(&info, 0, sizeof(info)); file=sf_open(path, SFM_READ, &info); if(!file) { fprintf(stderr, "ambix_interleave: tried to open matrix file '%s': ...failed\n", path); return NULL; } rows=info.channels; cols=(uint32_t)info.frames; data=(float*)malloc(rows*cols*sizeof(float)); frames=(uint32_t)sf_readf_float(file, data, cols); if(cols!=frames) { fprintf(stderr, "ambix_interleave: matrix reading %d frames returned %d\n", frames, cols); goto cleanup; } mtx=ambix_matrix_init(cols, rows, NULL); if(mtx && (AMBIX_ERR_SUCCESS==ambix_matrix_fill_data(mtx, data))) { uint32_t r, c; ai->matrix=ambix_matrix_init(rows, cols, NULL); for(r=0; rmatrix->data[r][c]=mtx->data[c][r]; } result=ai; // fprintf(stderr, "ambix_interleave: matrices not yet supported\n"); cleanup: if(mtx) ambix_matrix_destroy(mtx); sf_close(file); free(data); 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; imatrix_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; uint32_t order=0; uint32_t blocksize=0; while(argc) { if(!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) { print_usage(name); ai_exit=0; return ai_close(ai); } if(!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version")) { print_version(name); ai_exit=0; return ai_close(ai); } if(!strcmp(argv[0], "-o") || !strcmp(argv[0], "--output")) { if(argc>1) { ai->outfilename=strdup(argv[1]); argv+=2; argc-=2; continue; } fprintf(stderr, "no output file specified\n"); ai_exit=64; return ai_close(ai); } if(!strcmp(argv[0], "-O") || !strcmp(argv[0], "--order")) { if(argc>1) { order=atoi(argv[1]); channels=ambix_order2channels(order); argv+=2; argc-=2; continue; } fprintf(stderr, "no ambisonics order specified\n"); ai_exit=64; return ai_close(ai); } if(!strcmp(argv[0], "-b") || !strcmp(argv[0], "--blocksize")) { if(argc>1) { blocksize=atoi(argv[1]); argv+=2; argc-=2; 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]) && !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; argc-=2; continue; } fprintf(stderr, "no matrix file specified\n"); ai_exit=64; return ai_close(ai); } ai->infilenames=argv; ai->numIns=argc; 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); } if(channels>0) { ai->channels = channels; } if(blocksize>0) ai->blocksize=blocksize; else ai->blocksize=DEFAULT_BLOCKSIZE; 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; } static ai_t*ai_close(ai_t*ai) { uint32_t i; if(!ai)return NULL; if(ai->inhandles) { for(i=0; inumIns; i++) { SNDFILE*inhandle=ai->inhandles[i]; if(inhandle) { sf_close(inhandle); } ai->inhandles[i]=NULL; } free(ai->inhandles); } ai->inhandles=NULL; if(ai->ininfo) free(ai->ininfo); ai->ininfo=NULL; if(ai->outhandle) { ambix_close(ai->outhandle); } ai->outhandle=NULL; if(ai->outfilename) free(ai->outfilename); ai->outfilename=NULL; if(ai->matrix) { ambix_matrix_destroy(ai->matrix); } ai->matrix=NULL; free(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; uint32_t channels=0; if(!ai)return ai; if(!ai->inhandles) { ai->inhandles=(SNDFILE**)calloc(ai->numIns, sizeof(SNDFILE*)); ai->ininfo =(SF_INFO*)calloc(ai->numIns, sizeof(SF_INFO)); } for(i=0; inumIns; i++) { SNDFILE*inhandle=ai->inhandles[i]; SF_INFO*info=&ai->ininfo[i]; if(!inhandle) { inhandle=sf_open(ai->infilenames[i], SFM_READ, info); } if(ai->info.frames==0 || (ai->info.frames > (info->frames))) ai->info.frames=(uint64_t)info->frames; if(ai->info.samplerate<1.) ai->info.samplerate=info->samplerate; if(ai->info.sampleformat==AMBIX_SAMPLEFORMAT_NONE) { int format=info->format; 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; else if((format & SF_FORMAT_PCM_24)) 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(channelsmatrix->cols) { return ai_close(ai); } /* extended format */ ai->info.fileformat=AMBIX_EXTENDED; ai->info.ambichannels=ai->matrix->cols; ai->info.extrachannels=channels-ai->matrix->cols; } else if (ai->channels > 0) { if(ai->channels < channels) { ai->info.fileformat=AMBIX_EXTENDED; ai->info.ambichannels=(ai->channels); ai->info.extrachannels=channels-(ai->channels); ai->matrix=ambix_matrix_init(ai->channels, ai->channels, NULL); ai->matrix=ambix_matrix_fill (ai->matrix, AMBIX_MATRIX_IDENTITY); } else if (ai->channels == channels) { /* basic format */ ai->info.fileformat=AMBIX_BASIC; ai->info.ambichannels=channels; ai->info.extrachannels=0; } else { return ai_close(ai); } } else { if(!ambix_is_fullset(channels)) { return ai_close(ai); } /* basic format */ ai->info.fileformat=AMBIX_BASIC; ai->info.ambichannels=channels; ai->info.extrachannels=0; } printf("format: %s\n", (ai->info.fileformat==AMBIX_BASIC)?"basic":"extended"); printf("got %d input channels each %d frames\n", channels, (int)(ai->info.frames)); printf("ambichannels: %d\n", ai->info.ambichannels); printf("extrachannels: %d\n", ai->info.extrachannels); if(ai->matrix) printf("matrix: [%dx%d]\n", ai->matrix->rows, ai->matrix->cols); else printf("matrix: NONE\n"); if((ai->info.ambichannels < 1) && (ai->info.extrachannels < 1)) { fprintf(stderr, "no output channels defined\n"); return ai_close(ai); } return ai; } static ai_t*ai_open_output(ai_t*ai) { ambix_info_t info; if(!ai)return ai; memcpy(&info, &ai->info, sizeof(info)); ai->outhandle=ambix_open(ai->outfilename, AMBIX_WRITE, &info); if(AMBIX_EXTENDED==ai->info.fileformat) { ambix_err_t err=ambix_set_adaptormatrix(ai->outhandle, ai->matrix); if(err!=AMBIX_ERR_SUCCESS) { fprintf(stderr, "setting adapator matrix [%dx%d]=%d returned %d\n", ai->matrix->rows, ai->matrix->cols, ambix_is_fullset(ai->matrix->rows), err); return ai_close(ai); } } return ai; } /* deinterleave an *interleaved* source of * data in dest */ static void deinterleaver(float*dest, const float*source, uint64_t frames, uint32_t channels) { uint32_t channel; for(channel=0; channel* data in dest */ static void interleaver(float*dest, const float*source, uint64_t frames, uint32_t channels) { uint64_t frame; for(frame=0; framenumIns; 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(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+=inchannels; } } if(ambidata) interleaver(ambidata, deinterleavedata, frames, ai->info.ambichannels); if(extradata) interleaver(extradata, deinterleavedata+frames*ai->info.ambichannels, frames, ai->info.extrachannels); //printf("writing %d frames to %p & %p\n", (int)frames, ambidata, extradata); if(frames!=ambix_writef_float32(ai->outhandle, ambidata, extradata, frames)) { return ai_close(ai); } return 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,*source=NULL; uint64_t i, maxchannels=0; if(!ai)return ai; blocksize=ai->blocksize; if(blocksize<1) blocksize=DEFAULT_BLOCKSIZE; frames=ai->info.frames; channels=(ai->info.ambichannels+ai->info.extrachannels); for(i=0; inumIns; i++) { uint64_t c=ai->ininfo[i].channels; if(c>maxchannels)maxchannels=c; } if(ai->info.ambichannels>0) ambidata =malloc(sizeof(*ambidata )*ai->info.ambichannels *blocksize); if(ai->info.extrachannels>0) 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++; ai=ai_copy_block(ai, ambidata, extradata, interleavebuffer, source, blocksize); if(!ai) break; frames-=blocksize; } if(ai) ai=ai_copy_block(ai, ambidata, extradata, interleavebuffer, source, frames); free(ambidata); free(extradata); free(interleavebuffer); free(source); return ai; } static int ambix_interleave(ai_t*ai) { ai_t*result=ai_open_input(ai); // if(result)printf("success @ %d!\n", __LINE__); result=ai_open_output(result); //if(result)printf("success @ %d!\n", __LINE__); result=ai_copy(result); //if(result)printf("success @ %d!\n", __LINE__); if(result) ai_close(result); // result:=ai //if(result)printf("success @ %d!\n", __LINE__); return (result!=NULL); } 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 ai_exit; } return ambix_interleave(ai); } void print_usage(const char*name) { printf("\n"); printf("Usage: %s -o outfile [options] infile1...\n", name); printf("Merges several audio files into an ambix file\n"); printf("\n"); printf("Options:\n"); 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 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"); printf( "\nIn it's simplest form, you pass it a number of input files," "\nthe accumulated channels of which form a full 3d ambisonics set" "\n(channel #0 becomes the W-channel,...)." "\nThe ambisonics order is calculated from the number of channels using N=(O+1)^2." "\n" "\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(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" ); printf("\n"); #ifdef PACKAGE_BUGREPORT printf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL printf("Home page: %s\n", PACKAGE_URL); #endif } void print_version(const char*name) { #ifdef PACKAGE_VERSION printf("%s %s\n", name, PACKAGE_VERSION); #endif printf("\n"); printf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); printf("\n"); printf("License LGPLv2.1: GNU Lesser GPL version 2.1 or later \n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf("Written by IOhannes m zmoelnig \n"); } ambix-0.1.1/utils/ambix-jplay.c000066400000000000000000000416571300077024200163420ustar00rootroot00000000000000/* ambix-jplay.c - play back an ambix file via jack -*- c -*- Copyright © 2003-2010 Rohan Drape Copyright © 2012-2014 IOhannes m zmölnig . Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz This file is based on 'jack.play' from Rohan Drape's "jack-tools" collection you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ambix-jplay 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 General Public License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #ifdef HAVE_SAMPLERATE # include #endif /* HAVE_SAMPLERATE */ #include "jcommon/jack-ringbuffer.h" #include "jcommon/observe-signal.h" #include "jcommon/common.h" struct player_opt { int buffer_frames; int minimal_frames; int64_t seek_request; int transport_aware; int unique_name; double src_ratio; int rb_request_frames; int converter; char client_name[64]; }; static void interleave_data(float32_t*source1, uint32_t source1channels, float32_t*source2, uint32_t source2channels, float*destination, int64_t frames) { int64_t frame; for(frame=0; frameo.seek_request >= 0) { int64_t err = ambix_seek(d->sound_file, (int64_t)d->o.seek_request, SEEK_SET); if(err == -1) { eprintf("ambix-jplay: seek request failed, %ld\n", (long)d->o.seek_request); } d->o.seek_request = -1; } /* Wait for write space at the ring buffer. */ int nbytes = d->o.minimal_frames * sizeof(float) * d->channels; nbytes = jack_ringbuffer_wait_for_write(d->rb, nbytes, d->pipe[0]); /* Do not overflow the local buffer. */ if(nbytes > d->buffer_bytes) { // this happens whenever buffer_bytes is not power-of-two eprintf("ambix-jplay: impossible condition, write space (%d > %d).\n", (int)nbytes, (int)d->buffer_bytes); nbytes = d->buffer_bytes; } /* Read sound file data, which *must* be frame aligned. */ int nframes =(nbytes / sizeof(float))/ d->channels; int nsamples = nframes * d->channels; int64_t err = ambix_readf_float32(d->sound_file, d->a_buffer, d->e_buffer, nframes); if(err == 0) { if(d->o.transport_aware) { memset(d->a_buffer, 0, nframes * d->a_channels * sizeof(float32_t)); memset(d->e_buffer, 0, nframes * d->e_channels * sizeof(float32_t)); memset(d->d_buffer, 0, nsamples * sizeof(float)); err = nframes; } else { return NULL; } } interleave_data(d->a_buffer, d->a_channels, d->e_buffer, d->e_channels, d->d_buffer, err); /* Write data to ring buffer. */ jack_ringbuffer_write(d->rb, (char *)d->d_buffer, (size_t)(err*d->channels) * sizeof(float)); } return NULL; } int sync_handler(jack_transport_state_t state, jack_position_t *position, void *PTR) { struct player *d = (struct player*)PTR; d->o.seek_request = (int64_t)position->frame; return 1; } void signal_set(float **s, int n, int c, float z) { int j; for(j = 0; j < c; j++) { int i; for(i = 0; i < n; i++) { s[j][i] = z; } } } /* Write data from the ring buffer to the JACK output ports. If the disk thread is late, ie. the ring buffer is empty print a warning and zero the output ports. */ int signal_proc(jack_nframes_t nframes, void *PTR) { struct player *d = (struct player *)PTR; int nsamples = nframes * d->channels; int nbytes = nsamples * sizeof(float); /* Ensure the period size is workable. */ if(nbytes > d->buffer_bytes) { eprintf("ambix-jplay: period size exceeds limit (%d > %d)\n", nbytes, d->buffer_bytes); FAILURE; return 1; } /* Get port data buffers. */ int i,j; for(i = 0; i < d->channels; i++) { d->out[i] = (float *)jack_port_get_buffer(d->output_port[i], nframes); } /* Write silence if the transport is stopped. If stopped the disk thread will sleep and signals will be ignored, so check here also. */ if(d->o.transport_aware && !jack_transport_is_rolling(d->client)) { if(observe_end_of_process ()) { FAILURE; return 1; } else { signal_set(d->out, nframes, d->channels, 0.0); return 0; } } long err = 0; #ifdef HAVE_SAMPLERATE /* Get data from sample rate converter, this returns the number of frames acquired. */ err = src_callback_read (d->src, d->o.src_ratio, (long)nframes, d->j_buffer); if(err==0) { eprintf("ambix-jplay: sample rate converter failed: %s\n", src_strerror(src_error(d->src))); FAILURE; } #else err=jack_ringbuffer_read(d->rb, (char *)d->j_buffer, nbytes); err=err/((sizeof(float))*(d->channels)); #endif /* HAVE_SAMPLERATE */ /* Uninterleave available data to the output buffers. */ for(i = 0; i < err; i++) { for(j = 0; j < d->channels; j++) { d->out[j][i] = d->j_buffer[(i*d->channels)+j]; } } /* If any sample data is unavailable inform the user and zero the output buffers. The print statement is not correct, a this should set a flag and have another thread take appropriate action. */ if(err < nframes) { eprintf("ambix-jplay: disk thread late (%ld < %d)\n", err, nframes); for(i = err; i < nframes; i++) { for(j = 0; j < d->channels; j++) { d->out[j][i] = 0.0; } } } /* Indicate to the disk thread that the ring buffer has been read from. This is done by writing a single byte to a communication pipe. Once the disk thread gets so far ahead that the ring buffer is full it reads this communication channel to wait for space to become available. So long as PIPE_BUF is not a pathologically small value this write operation is atomic and will not block. The number of bytes that can accumulate in the pipe is a factor of the relative sizes of the ring buffer and the process callback, but should in no case be very large. */ char b = 1; xwrite(d->pipe[1], &b, 1); return 0; } void usage(const char*filename) { eprintf("Usage: %s [ options ] sound-file\n", filename); eprintf("Play back an ambix file via JACK\n"); eprintf("\n"); eprintf("Options:\n"); eprintf(" -b N : Ring buffer size in frames (default=4096).\n"); #ifdef HAVE_SAMPLERATE eprintf(" -c N : ID of conversion algorithm (default=2, SRC_SINC_FASTEST).\n"); #endif /* HAVE_SAMPLERATE */ eprintf(" -i N : Initial disk seek in frames (default=0).\n"); eprintf(" -m N : Minimal disk read size in frames (default=32).\n"); eprintf(" -q N : Frames to request from ring buffer (default=64).\n"); eprintf(" -r N : Resampling ratio multiplier (default=1.0).\n"); eprintf(" -t : Jack transport awareness.\n"); eprintf(" -V : Print version information.\n"); eprintf(" -h : Print this help.\n"); eprintf("\n"); #ifdef PACKAGE_BUGREPORT eprintf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL eprintf("Home page: %s\n", PACKAGE_URL); #endif FAILURE; } void version(const char*name) { #ifdef PACKAGE_VERSION eprintf("%s %s\n", name, PACKAGE_VERSION); #endif eprintf("\n"); eprintf("Copyright (C) 2003-2010 Rohan Drape\n"); eprintf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); eprintf("\n"); eprintf("License GPLv2: GNU GPL version 2 or later \n"); eprintf("This is free software: you are free to change and redistribute it.\n"); eprintf("There is NO WARRANTY, to the extent permitted by law.\n"); eprintf("\n"); eprintf("Written by IOhannes m zmoelnig , based on jack.play by Rohan Drape\n"); FAILURE; } /* Get data from ring buffer. Return number of frames read. This could check the read size first, but then would still need to check the actual result size, and therefore have two error cases. Since there is no alternative but to drop sample data in any case it does not matter much. */ long read_input_from_rb(void *PTR, float **buf) { struct player *d = (struct player*)PTR; int nsamples = d->channels * d->o.rb_request_frames; int nbytes = (size_t)nsamples * sizeof(float); int err = jack_ringbuffer_read(d->rb, (char *)d->k_buffer, nbytes); err /= d->channels * sizeof(float); *buf = d->k_buffer; /* SRC locks up if we return zero here, return a silent frame */ if(err==0) { eprintf("ambix-jplay: ringbuffer empty... zeroing data\n"); memset(d->k_buffer, 0, (size_t)nsamples * sizeof(float)); err = d->o.rb_request_frames; } return (long)err; } int jackplay(const char *file_name, struct player_opt o) { struct player d; d.o = o; observe_signals (); /* Open sound file. */ ambix_info_t ambixinfo; memset(&ambixinfo, 0, sizeof(ambixinfo)); ambixinfo.fileformat=AMBIX_BASIC; d.sound_file = ambix_open(file_name, AMBIX_READ, &ambixinfo); d.a_channels = ambixinfo.ambichannels; d.e_channels = ambixinfo.extrachannels; d.channels = d.a_channels + d.e_channels; /* Allocate channel based data. */ if(d.channels < 1) { eprintf("ambix-jplay: illegal number of channels in file: %d\n", d.channels); FAILURE; } d.out = (float**)xmalloc(d.channels * sizeof(float *)); d.output_port = (jack_port_t**)xmalloc(d.channels * sizeof(jack_port_t *)); /* Allocate buffers. */ d.buffer_samples = d.o.buffer_frames * d.channels; d.buffer_bytes = d.buffer_samples * sizeof(float); d.a_buffer = (float32_t*)xmalloc(d.o.buffer_frames * d.a_channels * sizeof(float32_t)); d.e_buffer = (float32_t*)xmalloc(d.o.buffer_frames * d.e_channels * sizeof(float32_t)); d.d_buffer = (float*)xmalloc(d.buffer_bytes); d.j_buffer = (float*)xmalloc(d.buffer_bytes); d.k_buffer = (float*)xmalloc(d.buffer_bytes); d.rb = jack_ringbuffer_create(d.buffer_bytes); #ifdef HAVE_SAMPLERATE /* Setup sample rate conversion. */ int err; d.src = src_callback_new (read_input_from_rb, d.o.converter, d.channels, &err, &d); if(!d.src) { eprintf("ambix-jplay: sample rate conversion setup failed: %s\n", src_strerror(err)); FAILURE; } #else # warning samplerate conversion #endif /* HAVE_SAMPLERATE */ /* Create communication pipe. */ xpipe(d.pipe); /* Become a client of the JACK server. */ if(d.o.unique_name) { d.client = jack_client_unique(d.o.client_name); } else { d.client = jack_client_open(d.o.client_name,JackNullOption,NULL); } if(!d.client) { eprintf("ambix-jplay: could not create jack client: %s", d.o.client_name); FAILURE; } /* Start disk thread, the priority number is a random guess.... */ jack_client_create_thread (d.client, &(d.disk_thread), 50, 1, disk_proc, &d); /* Set error, process and shutdown handlers. */ jack_set_error_function(jack_client_minimal_error_handler); jack_on_shutdown(d.client, jack_client_minimal_shutdown_handler, 0); if(d.o.transport_aware) { jack_set_sync_callback(d.client, sync_handler, &d); } jack_set_process_callback(d.client, signal_proc, &d); /* Inform the user of sample-rate mismatch. */ int osr = jack_get_sample_rate(d.client); int isr = ambixinfo.samplerate; if(osr != isr) { d.o.src_ratio *= (osr / isr); eprintf("ambix-jplay: resampling, sample rate of file != server, %d != %d\n", isr, osr); } /* Create output ports, connect if env variable set and activate client. */ // jack_port_make_standard(d.client, d.output_port, d.channels, true); do { int i=0, a, e; for(a=0; a argc - 1) { usage (argv[0]); } int i; for(i = optind; i < argc; i++) { printf("%s: %s\n", argv[0], argv[i]); jackplay(argv[i], o); } return EXIT_SUCCESS; } ambix-0.1.1/utils/ambix-jrecord.c000066400000000000000000000334201300077024200166400ustar00rootroot00000000000000/* ambix-jrecord.c - record and ambix file via jack -*- c -*- Copyright © 2003-2006 Rohan Drape Copyright © 2012 IOhannes m zmölnig . Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz This file is based on 'jack.record' from Rohan Drape's "jack-tools" collection you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ambix-jrecord 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 General Public License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #include #include #include "jcommon/jack-ringbuffer.h" #include "jcommon/observe-signal.h" #include "jcommon/common.h" struct recorder { int buffer_bytes; int buffer_samples; int buffer_frames; int minimal_frames; float timer_seconds; int timer_frames; int timer_counter; float sample_rate; float32_t *a_buffer, *e_buffer; float *d_buffer; float *j_buffer; float *u_buffer; ambix_fileformat_t file_format; ambix_sampleformat_t sample_format; ambix_t *sound_file; int channels; uint32_t a_channels, e_channels; jack_port_t **input_port; float **in; jack_ringbuffer_t *ring_buffer; pthread_t disk_thread; int pipe[2]; }; #include static ambix_matrix_t*matrix_read(const char*path, ambix_matrix_t*matrix) { SF_INFO info; uint32_t rows, cols; float*data=NULL; ambix_matrix_t*mtx=NULL, *result=NULL; uint32_t frames; memset(&info, 0, sizeof(info)); SNDFILE*file=sf_open(path, SFM_READ, &info); if(!file) { fprintf(stderr, "ambix_interleave: matrix open failed '%s'\n", path); return NULL; } rows=info.channels; cols=info.frames; data=(float*)malloc(rows*cols*sizeof(float)); frames=sf_readf_float(file, data, cols); if(cols!=frames) { fprintf(stderr, "ambix_interleave: matrix reading %d frames returned %d\n", frames, cols); goto cleanup; } mtx=ambix_matrix_init(cols, rows, NULL); if(mtx && (AMBIX_ERR_SUCCESS==ambix_matrix_fill_data(mtx, data))) { uint32_t r, c; matrix=ambix_matrix_init(rows, cols, matrix); for(r=0; rdata[r][c]=mtx->data[c][r]; } result=matrix; // fprintf(stderr, "ambix_interleave: matrices not yet supported\n"); cleanup: if(mtx) ambix_matrix_destroy(mtx); sf_close(file); free(data); return result; } void signal_interleave_to(float32_t *dst, const float32_t **src, uint32_t f, uint32_t c) { uint32_t i, k = 0; for(i = 0; i < f; i++) { uint32_t j; for(j = 0; j < c; j++) { dst[k++] = src[j][i]; } } } void interleave_split(float32_t*source, uint32_t sourcechannels, uint32_t dst1channels, float32_t*dst1, float32_t*dst2, int64_t frames) { int64_t frame; for(frame=0; framesound_file, d->a_buffer, d->e_buffer, nsamples); } void *disk_thread_procedure(void *PTR) { struct recorder *d = (struct recorder *) PTR; while(!observe_end_of_process()) { /* Wait for data at the ring buffer. */ int nbytes = d->minimal_frames * sizeof(float) * d->channels; nbytes = jack_ringbuffer_wait_for_read(d->ring_buffer, nbytes, d->pipe[0]); /* Drop excessive data to not overflow the local buffer. */ if(nbytes > d->buffer_bytes) { eprintf("ambix-jrecord: impossible condition, read space (%d > %d).\n", nbytes, d->buffer_bytes); nbytes = d->buffer_bytes; } /* Read data from the ring buffer. */ jack_ringbuffer_read(d->ring_buffer, (char *) d->d_buffer, nbytes); /* Do write operation. The sample count *must* be an integral number of frames. */ int nframes = (nbytes / sizeof(float))/ d->channels; interleave_split(d->d_buffer, d->channels, d->a_channels, d->a_buffer, d->e_buffer, nframes); write_to_disk(d, nframes); /* Handle timer */ d->timer_counter += nframes; if(d->timer_frames > 0 && d->timer_counter >= d->timer_frames) { return NULL; } } return NULL; } /* Write data from the JACK input ports to the ring buffer. If the disk thread is late, ie. the ring buffer is full, print an error and halt the client. */ int process(jack_nframes_t nframes, void *PTR) { struct recorder *d = (struct recorder *) PTR; int nsamples = nframes * d->channels; int nbytes = nsamples * sizeof(float); /* Get port data buffers. */ int i; for(i = 0; i < d->channels; i++) { d->in[i] = (float *) jack_port_get_buffer(d->input_port[i], nframes); } /* Check period size is workable. If the buffer is large, ie 4096 frames, this should never be of practical concern. */ if(nbytes >= d->buffer_bytes) { eprintf("ambix-jrecord: period size exceeds limit\n"); FAILURE; return 1; } /* Check that there is adequate space in the ringbuffer. */ int space = (int) jack_ringbuffer_write_space(d->ring_buffer); if(space < nbytes) { eprintf("ambix-jrecord: overflow error, %d > %d\n", nbytes, space); FAILURE; return 1; } /* Interleave input to buffer and copy into ringbuffer. */ signal_interleave_to(d->j_buffer, (const float **)d->in, nframes, d->channels); int err = jack_ringbuffer_write(d->ring_buffer, (char *) d->j_buffer, (size_t) nbytes); if(err != nbytes) { eprintf("ambix-jrecord: error writing to ringbuffer, %d != %d\n", err, nbytes); FAILURE; return 1; } /* Poke the disk thread to indicate data is on the ring buffer. */ char b = 1; xwrite(d->pipe[1], &b, 1); return 0; } void usage(const char*name) { eprintf("Usage: %s [ options ] sound-file\n", name); eprintf("Record an ambix file via JACK\n"); eprintf("\n"); eprintf("Options:\n"); eprintf(" -O N : ambisonics order (default=1).\n"); eprintf(" -X s : sound-file holding adaptor matrix matrix to reconstruct full ambisonics set (forces AMBIX_EXTENDED format).\n"); eprintf(" -x N : Number of non-ambisonics ('extra') channels (forces AMBIX_EXTENDED format).\n"); eprintf(" -b N : Ring buffer size in frames (default=4096).\n"); // LATER: allow user to specify the sample-format // eprintf(" -f N : File format (default=0x10006).\n"); eprintf(" -m N : Minimal disk read size in frames (default=32).\n"); eprintf(" -t N : Set a timer to record for N seconds (default=-1).\n"); eprintf(" -V : Print version information.\n"); eprintf(" -h : Print this help.\n"); eprintf("\n"); #ifdef PACKAGE_BUGREPORT eprintf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL eprintf("Home page: %s\n", PACKAGE_URL); #endif FAILURE; } void version(const char*name) { #ifdef PACKAGE_VERSION eprintf("%s %s\n", name, PACKAGE_VERSION); #endif eprintf("\n"); eprintf("Copyright (C) 2003-2010 Rohan Drape\n"); eprintf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); eprintf("\n"); eprintf("License GPLv2: GNU GPL version 2 or later \n"); eprintf("This is free software: you are free to change and redistribute it.\n"); eprintf("There is NO WARRANTY, to the extent permitted by law.\n"); eprintf("\n"); eprintf("Written by IOhannes m zmoelnig , based on jack.record by Rohan Drape\n"); FAILURE; } int main(int argc, char *argv[]) { const char*filename = "jtest.caf"; const char*myname=argv[0]; observe_signals (); struct recorder d; ambix_matrix_t*matrix=NULL; int32_t order = -1; d.buffer_frames = 4096; d.minimal_frames = 32; d.channels = 2; d.timer_seconds = -1.0; d.timer_counter = 0; d.sample_format = AMBIX_SAMPLEFORMAT_FLOAT32; d.file_format = AMBIX_BASIC; int c; while((c = getopt(argc, argv, "hVx:X:O:b:fhm:n:t:")) != -1) { switch(c) { case 'x': d.e_channels = (int) strtol(optarg, NULL, 0); d.file_format = AMBIX_EXTENDED; break; case 'X': matrix=matrix_read(optarg, matrix); if(!matrix) { eprintf("%s: couldn't read matrix-file '%s'\n", myname, optarg); FAILURE; } d.file_format = AMBIX_EXTENDED; break; case 'O': order = (uint32_t) strtol(optarg, NULL, 0); break; case 'b': d.buffer_frames = (int) strtol(optarg, NULL, 0); break; #if 0 case 'f': d.file_format = (int) strtol(optarg, NULL, 0); break; #endif case 'V': version (myname); break; case 'h': usage (myname); break; case 'm': d.minimal_frames = (int) strtol(optarg, NULL, 0); break; case 't': d.timer_seconds = (float) strtod(optarg, NULL); break; default: eprintf("%s: illegal option, %c\n", myname, c); usage (myname); break; } } if(optind == argc - 1) { filename=argv[optind]; } else { eprintf("opening default file '%s'\n", filename); //usage (myname); } /* Allocate channel based data. */ if(matrix) { if(order<0) { d.a_channels = matrix->cols; } else { if(ambix_order2channels(order) != matrix->rows) { eprintf("%s: ambisonics order:%d cannot use [%dx%d] adaptor matrix.\n", myname, order, matrix->rows, matrix->cols); FAILURE; } d.a_channels = matrix->cols; } } else { if(order<0) order=1; d.a_channels=ambix_order2channels(order); } switch(d.file_format) { case AMBIX_BASIC: //d.a_channels; d.e_channels=0; break; case AMBIX_EXTENDED: //d.a_channels; //d.e_channels; break; case AMBIX_NONE: default: d.a_channels=0; //d.e_channels; } d.channels = d.a_channels+d.e_channels; if(d.channels < 1) { eprintf("%s: illegal number of channels: %d\n", myname, d.channels); FAILURE; } d.in = (float**)xmalloc(d.channels * sizeof(float *)); d.input_port = (jack_port_t**)xmalloc(d.channels * sizeof(jack_port_t *)); /* Connect to JACK. */ jack_client_t *client = jack_client_unique_("ambix-jrecord"); jack_set_error_function(jack_client_minimal_error_handler); jack_on_shutdown(client, jack_client_minimal_shutdown_handler, 0); jack_set_process_callback(client, process, &d); d.sample_rate = jack_get_sample_rate(client); /* Setup timer. */ if(d.timer_seconds < 0.0) { d.timer_frames = -1; } else { d.timer_frames = d.timer_seconds * d.sample_rate; } /* Create sound file. */ ambix_info_t sfinfo; memset(&sfinfo, 0, sizeof(sfinfo)); sfinfo.samplerate = (int) d.sample_rate; sfinfo.frames = 0; sfinfo.fileformat = d.file_format; sfinfo.ambichannels = d.a_channels; sfinfo.extrachannels = d.e_channels; d.sound_file = ambix_open(filename, AMBIX_WRITE, &sfinfo); if(matrix) { ambix_err_t aerr = ambix_set_adaptormatrix(d.sound_file, matrix); if(AMBIX_ERR_SUCCESS != aerr) { eprintf("setting [%dx%d] matrix returned %d.\n", matrix->rows, matrix->cols, aerr); FAILURE; } } /* Allocate buffers. */ d.buffer_samples = d.buffer_frames * d.channels; d.buffer_bytes = d.buffer_samples * sizeof(float); d.a_buffer = (float32_t*)xmalloc(d.buffer_frames * d.a_channels * sizeof(float32_t)); d.e_buffer = (float32_t*)xmalloc(d.buffer_frames * d.e_channels * sizeof(float32_t)); d.d_buffer = (float*)xmalloc(d.buffer_bytes); d.j_buffer = (float*)xmalloc(d.buffer_bytes); d.u_buffer = (float*)xmalloc(d.buffer_bytes); d.ring_buffer = jack_ringbuffer_create(d.buffer_bytes); /* Create communication pipe. */ xpipe(d.pipe); /* Start disk thread. */ pthread_create (&(d.disk_thread), NULL, disk_thread_procedure, &d); /* Create input ports and activate client. */ #if 0 jack_port_make_standard(client, d.input_port, d.channels, false); jack_client_activate(client); #else do { int i=0, a, e; const char*format=(sfinfo.fileformat == AMBIX_BASIC)?"ACN_%d":"ambisonics_%d"; const int a_offset=(sfinfo.fileformat == AMBIX_BASIC)?0:1; for(a=0; a. 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 . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "ambix/ambix.h" #include #include #include void print_version(const char*name); void print_usage(const char*name); typedef struct { ambix_matrixtype_t typ; const char*name; } matrix_map_t; #if 0 static matrix_map_t matrixmap[] = { AMBIX_MATRIX_ZERO, "MATRIX_ZERO", AMBIX_MATRIX_ONE, "MATRIX_ONE", AMBIX_MATRIX_AMBIX, "MATRIX_AMBIX", AMBIX_MATRIX_N3D, "MATRIX_N3D", AMBIX_MATRIX_SID, "MATRIX_SID", AMBIX_MATRIX_FUMA, "MATRIX_FUMA", AMBIX_MATRIX_TO_AMBIX, "MATRIX_TO_AMBIX", AMBIX_MATRIX_TO_N3D, "MATRIX_TO_N3D", AMBIX_MATRIX_TO_SID, "MATRIX_TO_SID", AMBIX_MATRIX_TO_FUMA, "MATRIX_TO_FUMA", }; #endif static void printmatrix(const ambix_matrix_t*mtx) { printf("matrix %p", mtx); if(mtx) { float32_t**data=mtx->data; uint32_t r, c; printf(" [%dx%d] = %p\n", mtx->rows, mtx->cols, mtx->data); for(r=0; rrows; r++) { for(c=0; ccols; c++) { printf("%08f ", data[r][c]); } printf("\n"); } } printf("\n"); } static void print_matrix(const char*name, ambix_matrixtype_t typ, uint32_t rows, uint32_t cols) { ambix_matrix_t*mtx=ambix_matrix_init(rows, cols, NULL); if(mtx) { ambix_matrix_t*result=ambix_matrix_fill(mtx, typ); if(result) { printf("%s\t%d\n", name, (int)typ); printmatrix(result); if(result!=mtx) ambix_matrix_destroy(result); } else { printf("couldn't create matrix [%dx%d] of type %s[%d]\n", rows, cols, name, typ); } ambix_matrix_destroy(mtx); } } int main(int argc, char**argv) { if(argc>1) { if((!strcmp(argv[1], "-V")) || (!strcmp(argv[1], "--version"))) print_version(argv[0]); if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) print_usage(argv[0]); } print_matrix("FuMa []" , AMBIX_MATRIX_FUMA, 1, 1); print_matrix("FuMa [h]" , AMBIX_MATRIX_FUMA, 4, 3); print_matrix("FuMa [f]" , AMBIX_MATRIX_FUMA, 4, 4); print_matrix("FuMa [hh]" , AMBIX_MATRIX_FUMA, 9, 5); print_matrix("FuMa [fh]" , AMBIX_MATRIX_FUMA, 9, 6); print_matrix("FuMa [ff]" , AMBIX_MATRIX_FUMA, 9, 9); print_matrix("FuMa [hhh]", AMBIX_MATRIX_FUMA, 16, 7); print_matrix("FuMa [fhh]", AMBIX_MATRIX_FUMA, 16, 8); print_matrix("FuMa [ffh]", AMBIX_MATRIX_FUMA, 16, 11); print_matrix("FuMa [fff]", AMBIX_MATRIX_FUMA, 16, 16); print_matrix("MaFu []" , AMBIX_MATRIX_TO_FUMA, 1, 1); print_matrix("MaFu [h]" , AMBIX_MATRIX_TO_FUMA, 3, 4); print_matrix("MaFu [f]" , AMBIX_MATRIX_TO_FUMA, 4, 4); print_matrix("MaFu [hh]" , AMBIX_MATRIX_TO_FUMA, 5, 9); print_matrix("MaFu [fh]" , AMBIX_MATRIX_TO_FUMA, 6, 9); print_matrix("MaFu [ff]" , AMBIX_MATRIX_TO_FUMA, 9, 9); print_matrix("MaFu [hhh]", AMBIX_MATRIX_TO_FUMA, 7, 16); print_matrix("MaFu [fhh]", AMBIX_MATRIX_TO_FUMA, 8, 16); print_matrix("MaFu [ffh]", AMBIX_MATRIX_TO_FUMA, 11, 16); print_matrix("MaFu [fff]", AMBIX_MATRIX_TO_FUMA, 16, 16); print_matrix("zero [16]", AMBIX_MATRIX_ZERO, 16, 16); print_matrix("one [16]", AMBIX_MATRIX_ONE, 16, 16); print_matrix("identity [16]", AMBIX_MATRIX_IDENTITY, 16, 16); print_matrix("SID [16]", AMBIX_MATRIX_SID, 16, 16); print_matrix("->SID [16]", AMBIX_MATRIX_TO_SID, 16, 16); print_matrix("N3D [16]", AMBIX_MATRIX_N3D, 16, 16); print_matrix("->N3D [16]", AMBIX_MATRIX_TO_N3D, 16, 16); return 0; } void print_usage(const char*name) { printf("\n"); printf("Usage: %s\n", name); printf("Print some standard matrices when dealing with ambisonics\n"); printf("(this may be of limited use when not debugging libambix).\n"); printf("\n"); printf("Options:\n"); printf(" -h, --help Print this help\n"); printf(" -V, --version Version information\n"); printf("\n"); #ifdef PACKAGE_BUGREPORT printf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL printf("Home page: %s\n", PACKAGE_URL); #endif exit(1); } void print_version(const char*name) { #ifdef PACKAGE_VERSION printf("%s %s\n", name, PACKAGE_VERSION); #endif printf("\n"); printf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); printf("\n"); printf("License LGPLv2.1: GNU Lesser GPL version 2.1 or later \n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf("Written by IOhannes m zmoelnig \n"); exit(1); } ambix-0.1.1/utils/ambix-test.c000066400000000000000000000173641300077024200162000ustar00rootroot00000000000000/* ambix_test - test ambix -*- c -*- Copyright © 2012 IOhannes m zmölnig . 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 . */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ #include "ambix/ambix.h" #include #include #include void print_usage(const char*name); void print_version(const char*name); void createfile_basic(const char*path, uint32_t ambichannels, uint32_t extrachannels, uint64_t frames) { ambix_info_t info; ambix_t*ambix; extrachannels=0; memset(&info, 0, sizeof(info)); info.frames=frames; info.samplerate=44100; info.sampleformat=AMBIX_SAMPLEFORMAT_FLOAT32; info.fileformat=AMBIX_BASIC; info.ambichannels=ambichannels; info.extrachannels=extrachannels; printf("Open file '%s': ", path); ambix=ambix_open(path, AMBIX_WRITE, &info); if(!ambix) { printf("failed\n"); return; } else printf("OK\n"); printf("Frames\t: %d\n", (int)info.frames); printf("Samplerate\t: %f\n", info.samplerate); printf("Sampleformat\t: %d (", info.sampleformat); switch(info.sampleformat) { case(AMBIX_SAMPLEFORMAT_NONE): printf("NONE"); break; case(AMBIX_SAMPLEFORMAT_PCM16): printf("PCM16"); break; case(AMBIX_SAMPLEFORMAT_PCM24): printf("PCM24"); break; case(AMBIX_SAMPLEFORMAT_PCM32): printf("PCM32"); break; case(AMBIX_SAMPLEFORMAT_FLOAT32): printf("FLOAT32"); break; default: printf("**unknown**"); } printf(")\n"); printf("ambiXformat\t: %d (", info.fileformat); switch(info.fileformat) { case(AMBIX_NONE): printf("NONE"); break; case(AMBIX_BASIC): printf("BASIC"); break; case(AMBIX_EXTENDED): printf("EXTENDED"); break; default: printf("**unknown** 0x%04X", info.fileformat); } printf(")\n"); printf("Ambisonics channels\t: %d\n", info.ambichannels); printf("Non-Ambisonics channels\t: %d\n", info.extrachannels); /* now write some data... */ do { uint64_t res; float32_t*ambidata =(float32_t*)malloc(sizeof(float32_t)*64*ambichannels); float32_t*otherdata=(float32_t*)malloc(sizeof(float32_t)*64*extrachannels); while(frames>64) { res=ambix_writef_float32(ambix, ambidata, otherdata, 64); frames-=res; } if(frames>0) res=ambix_writef_float32(ambix, ambidata, otherdata, frames); free(ambidata);ambidata=NULL; free(otherdata);otherdata=NULL; } while(0); printf("Close file '%s': ", path); if(AMBIX_ERR_SUCCESS!=ambix_close(ambix)) printf("failed\n"); else printf("OK\n"); } void createfile_extended(const char*path, uint32_t ambichannels, uint32_t extrachannels, uint64_t frames) { ambix_info_t info; ambix_t*ambix; ambix_matrix_t adaptmatrix; ambix_err_t err; memset(&info, 0, sizeof(info)); info.frames=frames; info.samplerate=44100; info.sampleformat=AMBIX_SAMPLEFORMAT_FLOAT32; info.fileformat=AMBIX_EXTENDED; info.ambichannels=ambichannels; info.extrachannels=extrachannels; printf("Open file '%s': ", path); ambix=ambix_open(path, AMBIX_WRITE, &info); if(!ambix) { printf("failed\n"); return; } else printf("OK\n"); printf("Frames\t: %d\n", (int)info.frames); printf("Samplerate\t: %f\n", info.samplerate); printf("Sampleformat\t: %d (", info.sampleformat); switch(info.sampleformat) { case(AMBIX_SAMPLEFORMAT_NONE): printf("NONE"); break; case(AMBIX_SAMPLEFORMAT_PCM16): printf("PCM16"); break; case(AMBIX_SAMPLEFORMAT_PCM24): printf("PCM24"); break; case(AMBIX_SAMPLEFORMAT_PCM32): printf("PCM32"); break; case(AMBIX_SAMPLEFORMAT_FLOAT32): printf("FLOAT32"); break; default: printf("**unknown**"); } printf(")\n"); printf("ambiXformat\t: %d (", info.fileformat); switch(info.fileformat) { case(AMBIX_NONE): printf("NONE"); break; case(AMBIX_BASIC): printf("BASIC"); break; case(AMBIX_EXTENDED): printf("EXTENDED"); break; default: printf("**unknown** 0x%04X", info.fileformat); } printf(")\n"); printf("Ambisonics channels\t: %d\n", info.ambichannels); printf("Non-Ambisonics channels\t: %d\n", info.extrachannels); memset(&adaptmatrix, 0, sizeof(adaptmatrix)); ambix_matrix_init(25, ambichannels,&adaptmatrix); do { uint32_t r, c, rows=adaptmatrix.rows, cols=adaptmatrix.cols; float32_t**data=adaptmatrix.data; for(r=0; rblocksize) { res=ambix_writef_float32(ambix, ambidata, otherdata, blocksize); if(res!=blocksize) printf("write returned %d!=%d\n", (int)res, blocksize); frames-=blocksize; } if(frames>0) { res=ambix_writef_float32(ambix, ambidata, otherdata, frames); if(res!=frames) printf("write returned %d!=%d\n", (int)res, (int)frames); } free(ambidata);ambidata=NULL; free(otherdata);otherdata=NULL; } while(0); printf("Close file '%s': ", path); if(AMBIX_ERR_SUCCESS!=ambix_close(ambix)) printf("failed\n"); else printf("OK\n"); ambix_matrix_deinit(&adaptmatrix); } int main(int argc, char**argv) { if(argc>1) { if((!strcmp(argv[1], "-V")) || (!strcmp(argv[1], "--version"))) print_version(argv[0]); if((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) print_usage(argv[0]); createfile_basic(argv[1], 9, 3, 44100); if(argc>2) createfile_extended(argv[2], 9, 3, 44100); } else { print_usage(argv[0]); } return 0; } void print_usage(const char*name) { printf("\n"); printf("Usage: %s outfile_basic [outfile_extended]\n", name); printf("Create ambix test-files\n"); printf("(this may be of limited use when not debugging libambix).\n"); printf("\n"); printf("Options:\n"); printf(" -h, --help Print this help\n"); printf(" -V, --version Version information\n"); printf("\n"); #ifdef PACKAGE_BUGREPORT printf("Report bugs to: %s\n\n", PACKAGE_BUGREPORT); #endif #ifdef PACKAGE_URL printf("Home page: %s\n", PACKAGE_URL); #endif exit(1); } void print_version(const char*name) { #ifdef PACKAGE_VERSION printf("%s %s\n", name, PACKAGE_VERSION); #endif printf("\n"); printf("Copyright (C) 2012 Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts (KUG), Graz, Austria.\n"); printf("\n"); printf("License LGPLv2.1: GNU Lesser GPL version 2.1 or later \n"); printf("This is free software: you are free to change and redistribute it.\n"); printf("There is NO WARRANTY, to the extent permitted by law.\n"); printf("\n"); printf("Written by IOhannes m zmoelnig \n"); exit(1); } ambix-0.1.1/utils/jcommon/000077500000000000000000000000001300077024200154065ustar00rootroot00000000000000ambix-0.1.1/utils/jcommon/Makefile.am000066400000000000000000000006341300077024200174450ustar00rootroot00000000000000noinst_LTLIBRARIES = libjcommon.la libjcommon_la_CFLAGS = libjcommon_la_LIBADD = libjcommon_la_CFLAGS += \ @SAMPLERATE_CFLAGS@ @PTHREAD_CFLAGS@ \ @JACK_CFLAGS@ libjcommon_la_LIBADD += $(top_builddir)/libambix/src/libambix.la \ @SAMPLERATE_LIBS@ @PTHREAD_LIBS@ \ @JACK_LIBS@ libjcommon_la_SOURCES = \ common.c \ common.h \ jack-ringbuffer.c \ jack-ringbuffer.h \ observe-signal.c \ observe-signal.h ambix-0.1.1/utils/jcommon/common.c000066400000000000000000000037301300077024200170450ustar00rootroot00000000000000#ifdef HAVE_CONFIG_H # include "config.h" #endif #include "common.h" #include #include #include #include void *xmalloc(size_t size) { void *p = malloc(size); if(p == NULL) { fprintf(stderr, "malloc() failed: %ld\n", (long)size); FAILURE; } return p; } int xpipe(int filedes[2]) { int err = pipe(filedes); if(err) { perror("pipe() failed"); FAILURE; } return err; } ssize_t xwrite(int filedes, const void *buffer, size_t size) { ssize_t err = write(filedes, buffer, size); if(err == -1) { perror("write() failed"); FAILURE; } return err; } ssize_t xread(int filedes, void *buffer, size_t size) { ssize_t err = read(filedes, buffer, size); if(err == -1) { perror("read() failed"); FAILURE; } return err; } void jack_client_minimal_error_handler(const char *desc) { eprintf("jack error: %s\n", desc); } void jack_client_minimal_shutdown_handler(void *arg) { eprintf("jack shutdown\n"); FAILURE; } int jack_transport_is_rolling(jack_client_t *client) { jack_transport_state_t s = jack_transport_query(client , NULL); return s & JackTransportRolling; } jack_client_t *jack_client_unique(char *name) { int n = (int)getpid(); char uniq[64]; snprintf(uniq, 64, "%s-%d", name, n); strncpy(name,uniq,64); jack_client_t *client = jack_client_open(uniq,JackNullOption,NULL); if(! client) { eprintf("jack_client_open() failed: %s\n", uniq); FAILURE; } return client; } jack_client_t *jack_client_unique_(const char *name) { char uniq[64]; snprintf(uniq, 64, "%s", name); return jack_client_unique(uniq); } jack_port_t*_jack_port_register(jack_client_t *client, int direction, const char*format, int n) { char name[64]; jack_port_t*port; snprintf(name, 64, format, n); port = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, direction, 0); if(!port) { eprintf("jack_port_register() failed at %s\n", name); FAILURE; } return port; } ambix-0.1.1/utils/jcommon/common.h000066400000000000000000000036321300077024200170530ustar00rootroot00000000000000/* jcommon/common.h - common helper functions for jack-utils -*- c -*- Copyright © 2003-2001 Rohan Drape Copyright © 2012 IOhannes m zmölnig . Institute of Electronic Music and Acoustics (IEM), University of Music and Dramatic Arts, Graz This file is based on Rohan Drape's "jack-tools" collection you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ambix-jplay 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 General Public License along with this program; if not, see . */ #ifndef JCOMMON_COMMON_H #define JCOMMON_COMMON_H #ifdef HAVE_SYS_TYPES_H # include #endif /* HAVE_SYS_TYPES_H */ #include #ifndef FAILURE #define FAILURE exit(1) #endif #define eprintf(...) fprintf(stderr,__VA_ARGS__) void *xmalloc(size_t size); int xpipe(int filedes[2]); ssize_t xwrite(int filedes, const void *buffer, size_t size); ssize_t xread(int filedes, void *buffer, size_t size); void jack_client_minimal_error_handler(const char *desc); void jack_client_minimal_shutdown_handler(void *arg); int jack_transport_is_rolling(jack_client_t *client); jack_client_t *jack_client_unique_(const char*name); /* this simply create a unique client-name, withbout telling us... */ jack_client_t *jack_client_unique(char*name); /* this will change 'name' to the actual result */ jack_port_t*_jack_port_register(jack_client_t *client, int direction, const char*format, int n); #endif /* JCOMMON_COMMON_H */ ambix-0.1.1/utils/jcommon/jack-ringbuffer.c000066400000000000000000000032761300077024200206210ustar00rootroot00000000000000/* jack-ringbuffer.c - (c) rohan drape, 2005-2006 */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "jack-ringbuffer.h" #include "common.h" void jack_ringbuffer_print_debug(const jack_ringbuffer_t *r, const char *s) { eprintf("%s: read_ptr=%d,write_ptr=%d,size=%d,size_mask=%d\n", s, (int)r->read_ptr, (int)r->write_ptr, (int)r->size, (int)r->size_mask); } int jack_ringbuffer_wait_for_read(const jack_ringbuffer_t *r, int nbytes, int fd) { int space = (int) jack_ringbuffer_read_space(r); while(space < nbytes) { char b; if(read(fd, &b, 1)== -1) { eprintf("%s: error reading communication pipe\n", __func__); FAILURE; } space = (int) jack_ringbuffer_read_space(r); } return space; } int jack_ringbuffer_wait_for_write(jack_ringbuffer_t *r, int nbytes, int fd) { int space = (int)jack_ringbuffer_write_space(r); while(space < nbytes) { char b; if(read(fd, &b, 1)== -1) { fprintf (stderr, "%s: error reading communication pipe\n", __func__); FAILURE; } space = (int) jack_ringbuffer_write_space(r); } return space; } void jack_ringbuffer_read_exactly(jack_ringbuffer_t *r, char *buf, int n) { int err = jack_ringbuffer_read(r, buf, n); if(err != n) { eprintf("%s: error reading ring buffer (%d != %d)\n", __func__, err, n); FAILURE; } } void jack_ringbuffer_write_exactly(jack_ringbuffer_t *r, const char *buf, int n) { int err = jack_ringbuffer_write(r, buf, n); if(err != n) { eprintf("%s: error writing ring buffer (%d != %d)\n", __func__, err, n); FAILURE; } } ambix-0.1.1/utils/jcommon/jack-ringbuffer.h000066400000000000000000000010151300077024200206130ustar00rootroot00000000000000#ifndef JCOMMON_JACK_RINGBUFFER_H #define JCOMMON_JACK_RINGBUFFER_H #include #include void jack_ringbuffer_print_debug(const jack_ringbuffer_t *r, const char *s); int jack_ringbuffer_wait_for_read(const jack_ringbuffer_t *r, int nbytes, int fd); int jack_ringbuffer_wait_for_write(jack_ringbuffer_t *r, int nbytes, int fd); void jack_ringbuffer_read_exactly(jack_ringbuffer_t *r, char *buf, int n); void jack_ringbuffer_write_exactly(jack_ringbuffer_t *r, const char *buf, int n); #endif ambix-0.1.1/utils/jcommon/observe-signal.c000066400000000000000000000036211300077024200204740ustar00rootroot00000000000000/* observe-signal.c - (c) rohan drape, 2005-2006 */ #define _XOPEN_SOURCE 600 /* To use SA_RESTART and SA_RESETHAND */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "observe-signal.h" volatile unsigned int signal_received = 0; static void signal_management_handler(int s) { signal_received |= 1 << s; } static void *signal_management_thread(void *PTR) { pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); sigset_t blocked; sigprocmask(SIG_SETMASK, 0, &blocked); int s; sigwait(&blocked, &s); if(s != SIGSEGV) { sigprocmask(SIG_UNBLOCK, &blocked, 0); } signal_management_handler(s); return NULL; } int observe_signals(void) { sigset_t signals; signal_received = 0; sigemptyset(&signals); sigaddset(&signals, SIGHUP); sigaddset(&signals, SIGINT); sigaddset(&signals, SIGQUIT); sigaddset(&signals, SIGPIPE); sigaddset(&signals, SIGTERM); struct sigaction action; action.sa_handler = signal_management_handler; action.sa_mask = signals; action.sa_flags = SA_RESTART | SA_RESETHAND; int i; for(i = 1; i < 32; i++) { if(sigismember(&signals, i)) { if(sigaction(i, &action, 0)) { fprintf(stderr, "sigaction() failed: %d\n", i); return -1; } } } if(pthread_sigmask(SIG_SETMASK, &signals, 0)) { fprintf(stderr, "pthread_sigmask() failed: %s\n", strerror(errno)); return -1; } pthread_t signal_thread_id; if(pthread_create(&signal_thread_id, 0, signal_management_thread, 0)) { fprintf(stderr, "pthread_create() failed\n"); return -1; } pthread_detach(signal_thread_id); return 0; } bool observe_end_of_process(void) { return(signal_received & 1< int observe_signals(void); bool observe_end_of_process(void); #endif