[-] took out the trash
This commit is contained in:
parent
652d191b13
commit
5c53621598
116
.github/workflows/ci.yml
vendored
116
.github/workflows/ci.yml
vendored
@ -1,116 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{matrix.config.name}}
|
||||
runs-on: ${{matrix.config.os}}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: "Win32-Release",
|
||||
os: windows-latest,
|
||||
cmake_opts: "-A Win32 \
|
||||
-DALSOFT_BUILD_ROUTER=ON \
|
||||
-DALSOFT_REQUIRE_WINMM=ON \
|
||||
-DALSOFT_REQUIRE_DSOUND=ON \
|
||||
-DALSOFT_REQUIRE_WASAPI=ON",
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Win32-Debug",
|
||||
os: windows-latest,
|
||||
cmake_opts: "-A Win32 \
|
||||
-DALSOFT_BUILD_ROUTER=ON \
|
||||
-DALSOFT_REQUIRE_WINMM=ON \
|
||||
-DALSOFT_REQUIRE_DSOUND=ON \
|
||||
-DALSOFT_REQUIRE_WASAPI=ON",
|
||||
build_type: "Debug"
|
||||
}
|
||||
- {
|
||||
name: "Win64-Release",
|
||||
os: windows-latest,
|
||||
cmake_opts: "-A x64 \
|
||||
-DALSOFT_BUILD_ROUTER=ON \
|
||||
-DALSOFT_REQUIRE_WINMM=ON \
|
||||
-DALSOFT_REQUIRE_DSOUND=ON \
|
||||
-DALSOFT_REQUIRE_WASAPI=ON",
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Win64-Debug",
|
||||
os: windows-latest,
|
||||
cmake_opts: "-A x64 \
|
||||
-DALSOFT_BUILD_ROUTER=ON \
|
||||
-DALSOFT_REQUIRE_WINMM=ON \
|
||||
-DALSOFT_REQUIRE_DSOUND=ON \
|
||||
-DALSOFT_REQUIRE_WASAPI=ON",
|
||||
build_type: "Debug"
|
||||
}
|
||||
- {
|
||||
name: "macOS-Release",
|
||||
os: macos-latest,
|
||||
cmake_opts: "-DALSOFT_REQUIRE_COREAUDIO=ON",
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Linux-Release",
|
||||
os: ubuntu-latest,
|
||||
cmake_opts: "-DALSOFT_REQUIRE_RTKIT=ON \
|
||||
-DALSOFT_REQUIRE_ALSA=ON \
|
||||
-DALSOFT_REQUIRE_OSS=ON \
|
||||
-DALSOFT_REQUIRE_PORTAUDIO=ON \
|
||||
-DALSOFT_REQUIRE_PULSEAUDIO=ON \
|
||||
-DALSOFT_REQUIRE_JACK=ON \
|
||||
-DALSOFT_REQUIRE_PIPEWIRE=ON",
|
||||
deps_cmdline: "sudo apt update && sudo apt-get install -qq \
|
||||
libpulse-dev \
|
||||
portaudio19-dev \
|
||||
libasound2-dev \
|
||||
libjack-dev \
|
||||
libpipewire-0.3-dev \
|
||||
qtbase5-dev \
|
||||
libdbus-1-dev",
|
||||
build_type: "Release"
|
||||
}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: Install Dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ ! -z "${{matrix.config.deps_cmdline}}" ]]; then
|
||||
eval ${{matrix.config.deps_cmdline}}
|
||||
fi
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=${{matrix.config.build_type}} ${{matrix.config.cmake_opts}} .
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --build build --config ${{matrix.config.build_type}}
|
||||
|
||||
- name: Create Archive
|
||||
if: ${{ matrix.config.os == 'windows-latest' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cd build
|
||||
mkdir archive
|
||||
mkdir archive/router
|
||||
cp ${{matrix.config.build_type}}/soft_oal.dll archive
|
||||
cp ${{matrix.config.build_type}}/OpenAL32.dll archive/router
|
||||
|
||||
- name: Upload Archive
|
||||
# Upload package as an artifact of this workflow.
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
if: ${{ matrix.config.os == 'windows-latest' }}
|
||||
with:
|
||||
name: soft_oal-${{matrix.config.name}}
|
||||
path: build/archive
|
76
.github/workflows/makemhr.yml
vendored
76
.github/workflows/makemhr.yml
vendored
@ -1,76 +0,0 @@
|
||||
name: makemhr
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'utils/makemhr/**'
|
||||
- '.github/workflows/makemhr.yml'
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
Win64:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get current date
|
||||
run: echo "CurrentDate=$(date +'%Y-%m-%d')" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Get commit hash
|
||||
run: echo "CommitHash=$(git rev-parse --short=7 HEAD)" >> $env:GITHUB_ENV
|
||||
|
||||
- name: Clone libmysofa
|
||||
run: git clone --depth 1 --branch v1.3.1 https://github.com/hoene/libmysofa.git libmysofa
|
||||
|
||||
- name: Add MSBuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.1.3
|
||||
|
||||
- name: Restore libmysofa NuGet packages
|
||||
working-directory: ${{github.workspace}}/libmysofa
|
||||
run: nuget restore ${{github.workspace}}/libmysofa/windows/libmysofa.sln
|
||||
|
||||
- name: Build libmysofa
|
||||
working-directory: ${{github.workspace}}/libmysofa
|
||||
run: msbuild /m /p:Configuration=${{env.BUILD_TYPE}} ${{github.workspace}}/libmysofa/windows/libmysofa.sln
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -D "MYSOFA_LIBRARY=${{github.workspace}}/libmysofa/windows/bin/x64/Release/mysofa.lib" -D "MYSOFA_INCLUDE_DIR=${{github.workspace}}/libmysofa/src/hrtf" -D "ZLIB_LIBRARY=${{github.workspace}}/libmysofa/windows/third-party/zlib-1.2.11/lib/zlib.lib" -D "ZLIB_INCLUDE_DIR=${{github.workspace}}/libmysofa/windows/third-party/zlib-1.2.11/include"
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Make Artifacts folder
|
||||
run: |
|
||||
mkdir "Artifacts"
|
||||
mkdir "Release"
|
||||
|
||||
- name: Collect artifacts
|
||||
run: |
|
||||
copy "build/Release/makemhr.exe" "Artifacts/makemhr.exe"
|
||||
copy "libmysofa/windows/third-party/zlib-1.2.11/bin/zlib.dll" "Artifacts/zlib.dll"
|
||||
|
||||
- name: Upload makemhr artifact
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: makemhr
|
||||
path: "Artifacts/"
|
||||
|
||||
- name: Compress artifacts
|
||||
uses: papeloto/action-zip@v1
|
||||
with:
|
||||
files: Artifacts/
|
||||
dest: "Release/makemhr.zip"
|
||||
|
||||
- name: GitHub pre-release
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{secrets.GITHUB_TOKEN}}"
|
||||
automatic_release_tag: "makemhr"
|
||||
prerelease: true
|
||||
title: "[${{env.CurrentDate}}] makemhr-${{env.CommitHash}}"
|
||||
files: "Release/makemhr.zip"
|
125
.travis.yml
125
.travis.yml
@ -1,125 +0,0 @@
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: xenial
|
||||
- os: linux
|
||||
dist: trusty
|
||||
env:
|
||||
- BUILD_ANDROID=true
|
||||
- os: freebsd
|
||||
compiler: clang
|
||||
- os: osx
|
||||
- os: osx
|
||||
osx_image: xcode11
|
||||
env:
|
||||
- BUILD_IOS=true
|
||||
sudo: required
|
||||
install:
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" && -z "${BUILD_ANDROID}" ]]; then
|
||||
# Install pulseaudio, portaudio, ALSA, JACK dependencies for
|
||||
# corresponding backends.
|
||||
# Install Qt5 dependency for alsoft-config.
|
||||
sudo apt-get install -qq \
|
||||
libpulse-dev \
|
||||
portaudio19-dev \
|
||||
libasound2-dev \
|
||||
libjack-dev \
|
||||
qtbase5-dev \
|
||||
libdbus-1-dev
|
||||
fi
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
|
||||
curl -o ~/android-ndk.zip https://dl.google.com/android/repository/android-ndk-r21-linux-x86_64.zip
|
||||
unzip -q ~/android-ndk.zip -d ~ \
|
||||
'android-ndk-r21/build/cmake/*' \
|
||||
'android-ndk-r21/build/core/toolchains/arm-linux-androideabi-*/*' \
|
||||
'android-ndk-r21/platforms/android-16/arch-arm/*' \
|
||||
'android-ndk-r21/source.properties' \
|
||||
'android-ndk-r21/sources/android/support/include/*' \
|
||||
'android-ndk-r21/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/*' \
|
||||
'android-ndk-r21/sources/cxx-stl/llvm-libc++/include/*' \
|
||||
'android-ndk-r21/sysroot/*' \
|
||||
'android-ndk-r21/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/*' \
|
||||
'android-ndk-r21/toolchains/llvm/prebuilt/linux-x86_64/*'
|
||||
export OBOE_LOC=~/oboe
|
||||
git clone --depth 1 -b 1.3-stable https://github.com/google/oboe "$OBOE_LOC"
|
||||
fi
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "freebsd" ]]; then
|
||||
# Install Ninja as it's used downstream.
|
||||
# Install dependencies for all supported backends.
|
||||
# Install Qt5 dependency for alsoft-config.
|
||||
# Install ffmpeg for examples.
|
||||
sudo pkg install -y \
|
||||
alsa-lib \
|
||||
ffmpeg \
|
||||
jackit \
|
||||
libmysofa \
|
||||
ninja \
|
||||
portaudio \
|
||||
pulseaudio \
|
||||
qt5-buildtools \
|
||||
qt5-qmake \
|
||||
qt5-widgets \
|
||||
sdl2 \
|
||||
sndio \
|
||||
$NULL
|
||||
fi
|
||||
script:
|
||||
- cmake --version
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" && -z "${BUILD_ANDROID}" ]]; then
|
||||
cmake \
|
||||
-DALSOFT_REQUIRE_ALSA=ON \
|
||||
-DALSOFT_REQUIRE_OSS=ON \
|
||||
-DALSOFT_REQUIRE_PORTAUDIO=ON \
|
||||
-DALSOFT_REQUIRE_PULSEAUDIO=ON \
|
||||
-DALSOFT_REQUIRE_JACK=ON \
|
||||
-DALSOFT_EMBED_HRTF_DATA=YES \
|
||||
.
|
||||
fi
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
|
||||
cmake \
|
||||
-DANDROID_STL=c++_shared \
|
||||
-DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r21/build/cmake/android.toolchain.cmake \
|
||||
-DOBOE_SOURCE="$OBOE_LOC" \
|
||||
-DALSOFT_REQUIRE_OBOE=ON \
|
||||
-DALSOFT_REQUIRE_OPENSL=ON \
|
||||
-DALSOFT_EMBED_HRTF_DATA=YES \
|
||||
.
|
||||
fi
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "freebsd" ]]; then
|
||||
cmake -GNinja \
|
||||
-DALSOFT_REQUIRE_ALSA=ON \
|
||||
-DALSOFT_REQUIRE_JACK=ON \
|
||||
-DALSOFT_REQUIRE_OSS=ON \
|
||||
-DALSOFT_REQUIRE_PORTAUDIO=ON \
|
||||
-DALSOFT_REQUIRE_PULSEAUDIO=ON \
|
||||
-DALSOFT_REQUIRE_SDL2=ON \
|
||||
-DALSOFT_REQUIRE_SNDIO=ON \
|
||||
-DALSOFT_EMBED_HRTF_DATA=YES \
|
||||
.
|
||||
fi
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" && -z "${BUILD_IOS}" ]]; then
|
||||
cmake \
|
||||
-DALSOFT_REQUIRE_COREAUDIO=ON \
|
||||
-DALSOFT_EMBED_HRTF_DATA=YES \
|
||||
.
|
||||
fi
|
||||
- >
|
||||
if [[ "${TRAVIS_OS_NAME}" == "osx" && "${BUILD_IOS}" == "true" ]]; then
|
||||
cmake \
|
||||
-GXcode \
|
||||
-DCMAKE_SYSTEM_NAME=iOS \
|
||||
-DALSOFT_OSX_FRAMEWORK=ON \
|
||||
-DALSOFT_REQUIRE_COREAUDIO=ON \
|
||||
-DALSOFT_EMBED_HRTF_DATA=YES \
|
||||
"-DCMAKE_OSX_ARCHITECTURES=armv7;arm64" \
|
||||
.
|
||||
fi
|
||||
- cmake --build . --clean-first
|
1780
CMakeLists.txt
1780
CMakeLists.txt
File diff suppressed because it is too large
Load Diff
56
README.md
56
README.md
@ -1,67 +1,11 @@
|
||||
OpenAL Soft
|
||||
===========
|
||||
|
||||
`master` branch CI status : [![GitHub Actions Status](https://github.com/kcat/openal-soft/actions/workflows/ci.yml/badge.svg)](https://github.com/kcat/openal-soft/actions) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)
|
||||
|
||||
OpenAL Soft is an LGPL-licensed, cross-platform, software implementation of the OpenAL 3D audio API. It's forked from the open-sourced Windows version available originally from openal.org's SVN repository (now defunct).
|
||||
OpenAL provides capabilities for playing audio in a virtual 3D environment. Distance attenuation, doppler shift, and directional sound emitters are among the features handled by the API. More advanced effects, including air absorption, occlusion, and environmental reverb, are available through the EFX extension. It also facilitates streaming audio, multi-channel buffers, and audio capture.
|
||||
|
||||
More information is available on the [official website](http://openal-soft.org/).
|
||||
|
||||
Source Install
|
||||
-------------
|
||||
To install OpenAL Soft, use your favorite shell to go into the build/
|
||||
directory, and run:
|
||||
|
||||
```bash
|
||||
cmake ..
|
||||
```
|
||||
|
||||
Alternatively, you can use any available CMake front-end, like cmake-gui,
|
||||
ccmake, or your preferred IDE's CMake project parser.
|
||||
|
||||
Assuming configuration went well, you can then build it. The command
|
||||
`cmake --build .` will instruct CMake to build the project with the toolchain
|
||||
chosen during configuration (often GNU Make or NMake, although others are
|
||||
possible).
|
||||
|
||||
Please Note: Double check that the appropriate backends were detected. Often,
|
||||
complaints of no sound, crashing, and missing devices can be solved by making
|
||||
sure the correct backends are being used. CMake's output will identify which
|
||||
backends were enabled.
|
||||
|
||||
For most systems, you will likely want to make sure PipeWire, PulseAudio, and
|
||||
ALSA were detected (if your target system uses them). For Windows, make sure
|
||||
WASAPI was detected.
|
||||
|
||||
|
||||
Building openal-soft - Using vcpkg
|
||||
----------------------------------
|
||||
|
||||
You can download and install openal-soft using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install openal-soft
|
||||
|
||||
The openal-soft port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
Utilities
|
||||
---------
|
||||
The source package comes with an informational utility, openal-info, and is
|
||||
built by default. It prints out information provided by the ALC and AL sub-
|
||||
systems, including discovered devices, version information, and extensions.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
OpenAL Soft can be configured on a per-user and per-system basis. This allows
|
||||
users and sysadmins to control information provided to applications, as well
|
||||
as application-agnostic behavior of the library. See alsoftrc.sample for
|
||||
available settings.
|
||||
|
||||
|
||||
Acknowledgements
|
||||
|
@ -1,16 +0,0 @@
|
||||
# Cross-compiling for Android is handled by the NDK's own provided toolchain,
|
||||
# which as of this writing, should be in
|
||||
# ${ndk_root}/build/cmake/android.toolchain.cmake
|
||||
#
|
||||
# Certain older NDK versions may also need to explicitly pick the libc++
|
||||
# runtime. So for example:
|
||||
# cmake .. -DANDROID_STL=c++_shared \
|
||||
# -DCMAKE_TOOLCHAIN_FILE=${ndk_root}/build/cmake/android.toolchain.cmake
|
||||
#
|
||||
# Certain NDK versions may also need to use the lld linker to avoid errors
|
||||
# about missing liblog.so and libOpenSLES.so. That can be done by:
|
||||
# cmake .. -DANDROID_LD=lld \
|
||||
# -DCMAKE_TOOLCHAIN_FILE=${ndk_root}/build/cmake/android.toolchain.cmake
|
||||
#
|
||||
|
||||
MESSAGE(FATAL_ERROR "Use the toolchain provided by the Android NDK")
|
37
XCompile.txt
37
XCompile.txt
@ -1,37 +0,0 @@
|
||||
# Cross-compiling requires CMake 2.6 or newer. Example:
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-w64-mingw32
|
||||
# Where 'i686-w64-mingw32' is the host prefix for your cross-compiler. If you
|
||||
# already have a toolchain file setup, you may use that instead of this file.
|
||||
|
||||
# the name of the target operating system
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
SET(CMAKE_C_COMPILER "${HOST}-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "${HOST}-g++")
|
||||
SET(CMAKE_RC_COMPILER "${HOST}-windres")
|
||||
|
||||
# here is the target environment located
|
||||
SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}")
|
||||
|
||||
# here is where stuff gets installed to
|
||||
SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
|
||||
|
||||
# adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
# programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
# set env vars so that pkg-config will look in the appropriate directory for
|
||||
# .pc files (as there seems to be no way to force using ${HOST}-pkg-config)
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
|
||||
set(ENV{PKG_CONFIG_PATH} "")
|
||||
|
||||
# Qt4 tools
|
||||
SET(QT_QMAKE_EXECUTABLE ${HOST}-qmake)
|
||||
SET(QT_MOC_EXECUTABLE ${HOST}-moc)
|
||||
SET(QT_RCC_EXECUTABLE ${HOST}-rcc)
|
||||
SET(QT_UIC_EXECUTABLE ${HOST}-uic)
|
||||
SET(QT_LRELEASE_EXECUTABLE ${HOST}-lrelease)
|
666
alsoftrc.sample
666
alsoftrc.sample
@ -1,666 +0,0 @@
|
||||
# OpenAL config file.
|
||||
#
|
||||
# Option blocks may appear multiple times, and duplicated options will take the
|
||||
# last value specified. Environment variables may be specified within option
|
||||
# values, and are automatically substituted when the config file is loaded.
|
||||
# Environment variable names may only contain alpha-numeric characters (a-z,
|
||||
# A-Z, 0-9) and underscores (_), and are prefixed with $. For example,
|
||||
# specifying "$HOME/file.ext" would typically result in something like
|
||||
# "/home/user/file.ext". To specify an actual "$" character, use "$$".
|
||||
#
|
||||
# Device-specific values may be specified by including the device name in the
|
||||
# block name, with "general" replaced by the device name. That is, general
|
||||
# options for the device "Name of Device" would be in the [Name of Device]
|
||||
# block, while ALSA options would be in the [alsa/Name of Device] block.
|
||||
# Options marked as "(global)" are not influenced by the device.
|
||||
#
|
||||
# The system-wide settings can be put in /etc/xdg/alsoft.conf (as determined by
|
||||
# the XDG_CONFIG_DIRS env var list, /etc/xdg being the default if unset) and
|
||||
# user-specific override settings in $HOME/.config/alsoft.conf (as determined
|
||||
# by the XDG_CONFIG_HOME env var).
|
||||
#
|
||||
# For Windows, these settings should go into $AppData\alsoft.ini
|
||||
#
|
||||
# An additional configuration file (alsoft.ini on Windows, alsoft.conf on other
|
||||
# OSs) can be placed alongside the process executable for app-specific config
|
||||
# settings.
|
||||
#
|
||||
# Option and block names are case-senstive. The supplied values are only hints
|
||||
# and may not be honored (though generally it'll try to get as close as
|
||||
# possible). Note: options that are left unset may default to app- or system-
|
||||
# specified values. These are the current available settings:
|
||||
|
||||
##
|
||||
## General stuff
|
||||
##
|
||||
[general]
|
||||
|
||||
## disable-cpu-exts: (global)
|
||||
# Disables use of specialized methods that use specific CPU intrinsics.
|
||||
# Certain methods may utilize CPU extensions for improved performance, and
|
||||
# this option is useful for preventing some or all of those methods from being
|
||||
# used. The available extensions are: sse, sse2, sse3, sse4.1, and neon.
|
||||
# Specifying 'all' disables use of all such specialized methods.
|
||||
#disable-cpu-exts =
|
||||
|
||||
## drivers: (global)
|
||||
# Sets the backend driver list order, comma-seperated. Unknown backends and
|
||||
# duplicated names are ignored. Unlisted backends won't be considered for use
|
||||
# unless the list is ended with a comma (e.g. 'oss,' will try OSS first before
|
||||
# other backends, while 'oss' will try OSS only). Backends prepended with -
|
||||
# won't be considered for use (e.g. '-oss,' will try all available backends
|
||||
# except OSS). An empty list means to try all backends.
|
||||
#drivers =
|
||||
|
||||
## channels:
|
||||
# Sets the default output channel configuration. If left unspecified, one will
|
||||
# try to be detected from the system, with a fallback to stereo. The available
|
||||
# values are: mono, stereo, quad, surround51, surround61, surround71,
|
||||
# surround3d71, ambi1, ambi2, ambi3. Note that the ambi* configurations output
|
||||
# ambisonic channels of the given order (using ACN ordering and SN3D
|
||||
# normalization by default), which need to be decoded to play correctly on
|
||||
# speakers.
|
||||
#channels =
|
||||
|
||||
## sample-type:
|
||||
# Sets the default output sample type. Currently, all mixing is done with
|
||||
# 32-bit float and converted to the output sample type as needed. Available
|
||||
# values are:
|
||||
# int8 - signed 8-bit int
|
||||
# uint8 - unsigned 8-bit int
|
||||
# int16 - signed 16-bit int
|
||||
# uint16 - unsigned 16-bit int
|
||||
# int32 - signed 32-bit int
|
||||
# uint32 - unsigned 32-bit int
|
||||
# float32 - 32-bit float
|
||||
#sample-type = float32
|
||||
|
||||
## frequency:
|
||||
# Sets the default output frequency. If left unspecified it will try to detect
|
||||
# a default from the system, otherwise it will fallback to 48000.
|
||||
#frequency =
|
||||
|
||||
## period_size:
|
||||
# Sets the update period size, in sample frames. This is the number of frames
|
||||
# needed for each mixing update. Acceptable values range between 64 and 8192.
|
||||
# If left unspecified it will default to 1/50th of the frequency (20ms, or 882
|
||||
# for 44100, 960 for 48000, etc).
|
||||
#period_size =
|
||||
|
||||
## periods:
|
||||
# Sets the number of update periods. Higher values create a larger mix ahead,
|
||||
# which helps protect against skips when the CPU is under load, but increases
|
||||
# the delay between a sound getting mixed and being heard. Acceptable values
|
||||
# range between 2 and 16.
|
||||
#periods = 3
|
||||
|
||||
## stereo-mode:
|
||||
# Specifies if stereo output is treated as being headphones or speakers. With
|
||||
# headphones, HRTF or crossfeed filters may be used for better audio quality.
|
||||
# Valid settings are auto, speakers, and headphones.
|
||||
#stereo-mode = auto
|
||||
|
||||
## stereo-encoding:
|
||||
# Specifies the default encoding method for stereo output. Valid values are:
|
||||
# basic - Standard amplitude panning (aka pair-wise, stereo pair, etc) between
|
||||
# -30 and +30 degrees.
|
||||
# uhj - Creates a stereo-compatible two-channel UHJ mix, which encodes some
|
||||
# surround sound information into stereo output that can be decoded with
|
||||
# a surround sound receiver.
|
||||
# hrtf - Uses filters to provide better spatialization of sounds while using
|
||||
# stereo headphones.
|
||||
# If crossfeed filters are used, basic stereo mixing is used.
|
||||
#stereo-encoding = basic
|
||||
|
||||
## ambi-format:
|
||||
# Specifies the channel order and normalization for the "ambi*" set of channel
|
||||
# configurations. Valid settings are: fuma, acn+fuma, ambix (or acn+sn3d), or
|
||||
# acn+n3d
|
||||
#ambi-format = ambix
|
||||
|
||||
## hrtf:
|
||||
# Deprecated. Consider using stereo-encoding instead. Valid values are auto,
|
||||
# off, and on.
|
||||
#hrtf = auto
|
||||
|
||||
## hrtf-mode:
|
||||
# Specifies the rendering mode for HRTF processing. Setting the mode to full
|
||||
# (default) applies a unique HRIR filter to each source given its relative
|
||||
# location, providing the clearest directional response at the cost of the
|
||||
# highest CPU usage. Setting the mode to ambi1, ambi2, or ambi3 will instead
|
||||
# mix to a first-, second-, or third-order ambisonic buffer respectively, then
|
||||
# decode that buffer with HRTF filters. Ambi1 has the lowest CPU usage,
|
||||
# replacing the per-source HRIR filter for a simple 4-channel panning mix, but
|
||||
# retains full 3D placement at the cost of a more diffuse response. Ambi2 and
|
||||
# ambi3 increasingly improve the directional clarity, at the cost of more CPU
|
||||
# usage (still less than "full", given some number of active sources).
|
||||
#hrtf-mode = full
|
||||
|
||||
## hrtf-size:
|
||||
# Specifies the impulse response size, in samples, for the HRTF filter. Larger
|
||||
# values increase the filter quality, while smaller values reduce processing
|
||||
# cost. A value of 0 (default) uses the full filter size in the dataset, and
|
||||
# the default dataset has a filter size of 64 samples at 48khz.
|
||||
#hrtf-size = 0
|
||||
|
||||
## default-hrtf:
|
||||
# Specifies the default HRTF to use. When multiple HRTFs are available, this
|
||||
# determines the preferred one to use if none are specifically requested. Note
|
||||
# that this is the enumerated HRTF name, not necessarily the filename.
|
||||
#default-hrtf =
|
||||
|
||||
## hrtf-paths:
|
||||
# Specifies a comma-separated list of paths containing HRTF data sets. The
|
||||
# format of the files are described in docs/hrtf.txt. The files within the
|
||||
# directories must have the .mhr file extension to be recognized. By default,
|
||||
# OS-dependent data paths will be used. They will also be used if the list
|
||||
# ends with a comma. On Windows this is:
|
||||
# $AppData\openal\hrtf
|
||||
# And on other systems, it's (in order):
|
||||
# $XDG_DATA_HOME/openal/hrtf (defaults to $HOME/.local/share/openal/hrtf)
|
||||
# $XDG_DATA_DIRS/openal/hrtf (defaults to /usr/local/share/openal/hrtf and
|
||||
# /usr/share/openal/hrtf)
|
||||
#hrtf-paths =
|
||||
|
||||
## cf_level:
|
||||
# Sets the crossfeed level for stereo output. Valid values are:
|
||||
# 0 - No crossfeed
|
||||
# 1 - Low crossfeed
|
||||
# 2 - Middle crossfeed
|
||||
# 3 - High crossfeed (virtual speakers are closer to itself)
|
||||
# 4 - Low easy crossfeed
|
||||
# 5 - Middle easy crossfeed
|
||||
# 6 - High easy crossfeed
|
||||
# Users of headphones may want to try various settings. Has no effect on non-
|
||||
# stereo modes.
|
||||
#cf_level = 0
|
||||
|
||||
## resampler: (global)
|
||||
# Selects the default resampler used when mixing sources. Valid values are:
|
||||
# point - nearest sample, no interpolation
|
||||
# linear - extrapolates samples using a linear slope between samples
|
||||
# cubic - extrapolates samples using a Catmull-Rom spline
|
||||
# bsinc12 - extrapolates samples using a band-limited Sinc filter (varying
|
||||
# between 12 and 24 points, with anti-aliasing)
|
||||
# fast_bsinc12 - same as bsinc12, except without interpolation between down-
|
||||
# sampling scales
|
||||
# bsinc24 - extrapolates samples using a band-limited Sinc filter (varying
|
||||
# between 24 and 48 points, with anti-aliasing)
|
||||
# fast_bsinc24 - same as bsinc24, except without interpolation between down-
|
||||
# sampling scales
|
||||
#resampler = cubic
|
||||
|
||||
## rt-prio: (global)
|
||||
# Sets the real-time priority value for the mixing thread. Not all drivers may
|
||||
# use this (eg. PortAudio) as those APIs already control the priority of the
|
||||
# mixing thread. 0 and negative values will disable real-time priority. Note
|
||||
# that this may constitute a security risk since a real-time priority thread
|
||||
# can indefinitely block normal-priority threads if it fails to wait. Disable
|
||||
# this if it turns out to be a problem.
|
||||
#rt-prio = 1
|
||||
|
||||
## rt-time-limit: (global)
|
||||
# On non-Windows systems, allows reducing the process's RLIMIT_RTTIME resource
|
||||
# as necessary for acquiring real-time priority from RTKit.
|
||||
#rt-time-limit = true
|
||||
|
||||
## sources:
|
||||
# Sets the maximum number of allocatable sources. Lower values may help for
|
||||
# systems with apps that try to play more sounds than the CPU can handle.
|
||||
#sources = 256
|
||||
|
||||
## slots:
|
||||
# Sets the maximum number of Auxiliary Effect Slots an app can create. A slot
|
||||
# can use a non-negligible amount of CPU time if an effect is set on it even
|
||||
# if no sources are feeding it, so this may help when apps use more than the
|
||||
# system can handle.
|
||||
#slots = 64
|
||||
|
||||
## sends:
|
||||
# Limits the number of auxiliary sends allowed per source. Setting this higher
|
||||
# than the default has no effect.
|
||||
#sends = 6
|
||||
|
||||
## front-stablizer:
|
||||
# Applies filters to "stablize" front sound imaging. A psychoacoustic method
|
||||
# is used to generate a front-center channel signal from the front-left and
|
||||
# front-right channels, improving the front response by reducing the combing
|
||||
# artifacts and phase errors. Consequently, it will only work with channel
|
||||
# configurations that include front-left, front-right, and front-center.
|
||||
#front-stablizer = false
|
||||
|
||||
## output-limiter:
|
||||
# Applies a gain limiter on the final mixed output. This reduces the volume
|
||||
# when the output samples would otherwise clamp, avoiding excessive clipping
|
||||
# noise.
|
||||
#output-limiter = true
|
||||
|
||||
## dither:
|
||||
# Applies dithering on the final mix, for 8- and 16-bit output by default.
|
||||
# This replaces the distortion created by nearest-value quantization with low-
|
||||
# level whitenoise.
|
||||
#dither = true
|
||||
|
||||
## dither-depth:
|
||||
# Quantization bit-depth for dithered output. A value of 0 (or less) will
|
||||
# match the output sample depth. For int32, uint32, and float32 output, 0 will
|
||||
# disable dithering because they're at or beyond the rendered precision. The
|
||||
# maximum dither depth is 24.
|
||||
#dither-depth = 0
|
||||
|
||||
## volume-adjust:
|
||||
# A global volume adjustment for source output, expressed in decibels. The
|
||||
# value is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will
|
||||
# be a scale of 4x, etc. Similarly, -6 will be x1/2, and -12 is about x1/4. A
|
||||
# value of 0 means no change.
|
||||
#volume-adjust = 0
|
||||
|
||||
## excludefx: (global)
|
||||
# Sets which effects to exclude, preventing apps from using them. This can
|
||||
# help for apps that try to use effects which are too CPU intensive for the
|
||||
# system to handle. Available effects are: eaxreverb,reverb,autowah,chorus,
|
||||
# compressor,distortion,echo,equalizer,flanger,modulator,dedicated,pshifter,
|
||||
# fshifter,vmorpher.
|
||||
#excludefx =
|
||||
|
||||
## default-reverb: (global)
|
||||
# A reverb preset that applies by default to all sources on send 0
|
||||
# (applications that set their own slots on send 0 will override this).
|
||||
# Available presets include: None, Generic, PaddedCell, Room, Bathroom,
|
||||
# Livingroom, Stoneroom, Auditorium, ConcertHall, Cave, Arena, Hangar,
|
||||
# CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Mountains,
|
||||
# Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic.
|
||||
#default-reverb =
|
||||
|
||||
## trap-alc-error: (global)
|
||||
# Generates a SIGTRAP signal when an ALC device error is generated, on systems
|
||||
# that support it. This helps when debugging, while trying to find the cause
|
||||
# of a device error. On Windows, a breakpoint exception is generated.
|
||||
#trap-alc-error = false
|
||||
|
||||
## trap-al-error: (global)
|
||||
# Generates a SIGTRAP signal when an AL context error is generated, on systems
|
||||
# that support it. This helps when debugging, while trying to find the cause
|
||||
# of a context error. On Windows, a breakpoint exception is generated.
|
||||
#trap-al-error = false
|
||||
|
||||
##
|
||||
## Ambisonic decoder stuff
|
||||
##
|
||||
[decoder]
|
||||
|
||||
## hq-mode:
|
||||
# Enables a high-quality ambisonic decoder. This mode is capable of frequency-
|
||||
# dependent processing, creating a better reproduction of 3D sound rendering
|
||||
# over surround sound speakers.
|
||||
#hq-mode = true
|
||||
|
||||
## distance-comp:
|
||||
# Enables compensation for the speakers' relative distances to the listener.
|
||||
# This applies the necessary delays and attenuation to make the speakers
|
||||
# behave as though they are all equidistant, which is important for proper
|
||||
# playback of 3D sound rendering. Requires the proper distances to be
|
||||
# specified in the decoder configuration file.
|
||||
#distance-comp = true
|
||||
|
||||
## nfc:
|
||||
# Enables near-field control filters. This simulates and compensates for low-
|
||||
# frequency effects caused by the curvature of nearby sound-waves, which
|
||||
# creates a more realistic perception of sound distance with surround sound
|
||||
# output. Note that the effect may be stronger or weaker than intended if the
|
||||
# application doesn't use or specify an appropriate unit scale, or if
|
||||
# incorrect speaker distances are set. For HRTF output, hrtf-mode must be set
|
||||
# to one of the ambi* values for this to function.
|
||||
#nfc = false
|
||||
|
||||
## speaker-dist:
|
||||
# Specifies the speaker distance in meters, used by the near-field control
|
||||
# filters with surround sound output. For ambisonic output modes, this value
|
||||
# is the basis for the NFC-HOA Reference Delay parameter (calculated as
|
||||
# delay_seconds = speaker_dist/343.3). This value is not used when a decoder
|
||||
# configuration is set for the output mode (since they specify the per-speaker
|
||||
# distances, overriding this setting), or when the NFC filters are off. Valid
|
||||
# values range from 0.1 to 10.
|
||||
#speaker-dist = 1
|
||||
|
||||
## quad:
|
||||
# Decoder configuration file for Quadraphonic channel output. See
|
||||
# docs/ambdec.txt for a description of the file format.
|
||||
#quad =
|
||||
|
||||
## surround51:
|
||||
# Decoder configuration file for 5.1 Surround (Side and Rear) channel output.
|
||||
# See docs/ambdec.txt for a description of the file format.
|
||||
#surround51 =
|
||||
|
||||
## surround61:
|
||||
# Decoder configuration file for 6.1 Surround channel output. See
|
||||
# docs/ambdec.txt for a description of the file format.
|
||||
#surround61 =
|
||||
|
||||
## surround71:
|
||||
# Decoder configuration file for 7.1 Surround channel output. See
|
||||
# docs/ambdec.txt for a description of the file format.
|
||||
#surround71 =
|
||||
|
||||
## surround3d71:
|
||||
# Decoder configuration file for 3D7.1 Surround channel output. See
|
||||
# docs/ambdec.txt for a description of the file format. See also
|
||||
# docs/3D7.1.txt for information about 3D7.1.
|
||||
#surround3d71 =
|
||||
|
||||
##
|
||||
## UHJ and Super Stereo stuff
|
||||
##
|
||||
[uhj]
|
||||
|
||||
## decode-filter: (global)
|
||||
# Specifies the all-pass filter type for UHJ decoding and Super Stereo
|
||||
# processing. Valid values are:
|
||||
# iir - utilizes dual IIR filters, providing a wide pass-band with low CPU
|
||||
# use, but causes additional phase shifts on the signal.
|
||||
# fir256 - utilizes a 256-point FIR filter, providing more stable results but
|
||||
# exhibiting attenuation in the lower and higher frequency bands.
|
||||
# fir512 - utilizes a 512-point FIR filter, providing a wider pass-band than
|
||||
# fir256, at the cost of more CPU use.
|
||||
#decode-filter = iir
|
||||
|
||||
## encode-filter: (global)
|
||||
# Specifies the all-pass filter type for UHJ output encoding. Valid values are
|
||||
# the same as for decode-filter.
|
||||
#encode-filter = iir
|
||||
|
||||
##
|
||||
## Reverb effect stuff (includes EAX reverb)
|
||||
##
|
||||
[reverb]
|
||||
|
||||
## boost: (global)
|
||||
# A global amplification for reverb output, expressed in decibels. The value
|
||||
# is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a
|
||||
# scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A
|
||||
# value of 0 means no change.
|
||||
#boost = 0
|
||||
|
||||
##
|
||||
## PipeWire backend stuff
|
||||
##
|
||||
[pipewire]
|
||||
|
||||
## assume-audio: (global)
|
||||
# Causes the backend to succeed initialization even if PipeWire reports no
|
||||
# audio support. Currently, audio support is detected by the presence of audio
|
||||
# source or sink nodes, although this can cause false negatives in cases where
|
||||
# device availability during library initialization is spotty. Future versions
|
||||
# of PipeWire are expected to have a more robust method to test audio support,
|
||||
# but in the mean time this can be set to true to assume PipeWire has audio
|
||||
# support even when no nodes may be reported at initialization time.
|
||||
#assume-audio = false
|
||||
|
||||
## rt-mix:
|
||||
# Renders samples directly in the real-time processing callback. This allows
|
||||
# for lower latency and less overall CPU utilization, but can increase the
|
||||
# risk of underruns when increasing the amount of work the mixer needs to do.
|
||||
#rt-mix = true
|
||||
|
||||
##
|
||||
## PulseAudio backend stuff
|
||||
##
|
||||
[pulse]
|
||||
|
||||
## spawn-server: (global)
|
||||
# Attempts to autospawn a PulseAudio server whenever needed (initializing the
|
||||
# backend, enumerating devices, etc). Setting autospawn to false in Pulse's
|
||||
# client.conf will still prevent autospawning even if this is set to true.
|
||||
#spawn-server = false
|
||||
|
||||
## allow-moves: (global)
|
||||
# Allows PulseAudio to move active streams to different devices. Note that the
|
||||
# device specifier (seen by applications) will not be updated when this
|
||||
# occurs, and neither will the AL device configuration (sample rate, format,
|
||||
# etc).
|
||||
#allow-moves = true
|
||||
|
||||
## fix-rate:
|
||||
# Specifies whether to match the playback stream's sample rate to the device's
|
||||
# sample rate. Enabling this forces OpenAL Soft to mix sources and effects
|
||||
# directly to the actual output rate, avoiding a second resample pass by the
|
||||
# PulseAudio server.
|
||||
#fix-rate = false
|
||||
|
||||
## adjust-latency:
|
||||
# Attempts to adjust the overall latency of device playback. Note that this
|
||||
# may have adverse effects on the resulting internal buffer sizes and mixing
|
||||
# updates, leading to performance problems and drop-outs. However, if the
|
||||
# PulseAudio server is creating a lot of latency, enabling this may help make
|
||||
# it more manageable.
|
||||
#adjust-latency = false
|
||||
|
||||
##
|
||||
## ALSA backend stuff
|
||||
##
|
||||
[alsa]
|
||||
|
||||
## device: (global)
|
||||
# Sets the device name for the default playback device.
|
||||
#device = default
|
||||
|
||||
## device-prefix: (global)
|
||||
# Sets the prefix used by the discovered (non-default) playback devices. This
|
||||
# will be appended with "CARD=c,DEV=d", where c is the card id and d is the
|
||||
# device index for the requested device name.
|
||||
#device-prefix = plughw:
|
||||
|
||||
## device-prefix-*: (global)
|
||||
# Card- and device-specific prefixes may be used to override the device-prefix
|
||||
# option. The option may specify the card id (eg, device-prefix-NVidia), or
|
||||
# the card id and device index (eg, device-prefix-NVidia-0). The card id is
|
||||
# case-sensitive.
|
||||
#device-prefix- =
|
||||
|
||||
## custom-devices: (global)
|
||||
# Specifies a list of enumerated playback devices and the ALSA devices they
|
||||
# refer to. The list pattern is "Display Name=ALSA device;...". The display
|
||||
# names will be returned for device enumeration, and the ALSA device is the
|
||||
# device name to open for each enumerated device.
|
||||
#custom-devices =
|
||||
|
||||
## capture: (global)
|
||||
# Sets the device name for the default capture device.
|
||||
#capture = default
|
||||
|
||||
## capture-prefix: (global)
|
||||
# Sets the prefix used by the discovered (non-default) capture devices. This
|
||||
# will be appended with "CARD=c,DEV=d", where c is the card id and d is the
|
||||
# device number for the requested device name.
|
||||
#capture-prefix = plughw:
|
||||
|
||||
## capture-prefix-*: (global)
|
||||
# Card- and device-specific prefixes may be used to override the
|
||||
# capture-prefix option. The option may specify the card id (eg,
|
||||
# capture-prefix-NVidia), or the card id and device index (eg,
|
||||
# capture-prefix-NVidia-0). The card id is case-sensitive.
|
||||
#capture-prefix- =
|
||||
|
||||
## custom-captures: (global)
|
||||
# Specifies a list of enumerated capture devices and the ALSA devices they
|
||||
# refer to. The list pattern is "Display Name=ALSA device;...". The display
|
||||
# names will be returned for device enumeration, and the ALSA device is the
|
||||
# device name to open for each enumerated device.
|
||||
#custom-captures =
|
||||
|
||||
## mmap:
|
||||
# Sets whether to try using mmap mode (helps reduce latencies and CPU
|
||||
# consumption). If mmap isn't available, it will automatically fall back to
|
||||
# non-mmap mode. True, yes, on, and non-0 values will attempt to use mmap. 0
|
||||
# and anything else will force mmap off.
|
||||
#mmap = true
|
||||
|
||||
## allow-resampler:
|
||||
# Specifies whether to allow ALSA's built-in resampler. Enabling this will
|
||||
# allow the playback device to be set to a different sample rate than the
|
||||
# actual output, causing ALSA to apply its own resampling pass after OpenAL
|
||||
# Soft resamples and mixes the sources and effects for output.
|
||||
#allow-resampler = false
|
||||
|
||||
##
|
||||
## OSS backend stuff
|
||||
##
|
||||
[oss]
|
||||
|
||||
## device: (global)
|
||||
# Sets the device name for OSS output.
|
||||
#device = /dev/dsp
|
||||
|
||||
## capture: (global)
|
||||
# Sets the device name for OSS capture.
|
||||
#capture = /dev/dsp
|
||||
|
||||
##
|
||||
## Solaris backend stuff
|
||||
##
|
||||
[solaris]
|
||||
|
||||
## device: (global)
|
||||
# Sets the device name for Solaris output.
|
||||
#device = /dev/audio
|
||||
|
||||
##
|
||||
## QSA backend stuff
|
||||
##
|
||||
[qsa]
|
||||
|
||||
##
|
||||
## JACK backend stuff
|
||||
##
|
||||
[jack]
|
||||
|
||||
## spawn-server: (global)
|
||||
# Attempts to autospawn a JACK server when initializing.
|
||||
#spawn-server = false
|
||||
|
||||
## custom-devices: (global)
|
||||
# Specifies a list of enumerated devices and the ports they connect to. The
|
||||
# list pattern is "Display Name=ports regex;Display Name=ports regex;...". The
|
||||
# display names will be returned for device enumeration, and the ports regex
|
||||
# is the regular expression to identify the target ports on the server (as
|
||||
# given by the jack_get_ports function) for each enumerated device.
|
||||
#custom-devices =
|
||||
|
||||
## rt-mix:
|
||||
# Renders samples directly in the real-time processing callback. This allows
|
||||
# for lower latency and less overall CPU utilization, but can increase the
|
||||
# risk of underruns when increasing the amount of work the mixer needs to do.
|
||||
#rt-mix = true
|
||||
|
||||
## connect-ports:
|
||||
# Attempts to automatically connect the client ports to physical server ports.
|
||||
# Client ports that fail to connect will leave the remaining channels
|
||||
# unconnected and silent (the device format won't change to accommodate).
|
||||
#connect-ports = true
|
||||
|
||||
## buffer-size:
|
||||
# Sets the update buffer size, in samples, that the backend will keep buffered
|
||||
# to handle the server's real-time processing requests. This value must be a
|
||||
# power of 2, or else it will be rounded up to the next power of 2. If it is
|
||||
# less than JACK's buffer update size, it will be clamped. This option may
|
||||
# be useful in case the server's update size is too small and doesn't give the
|
||||
# mixer time to keep enough audio available for the processing requests.
|
||||
# Ignored when rt-mix is true.
|
||||
#buffer-size = 0
|
||||
|
||||
##
|
||||
## WASAPI backend stuff
|
||||
##
|
||||
[wasapi]
|
||||
|
||||
## allow-resampler:
|
||||
# Specifies whether to allow an extra resampler pass on the output. Enabling
|
||||
# this will allow the playback device to be set to a different sample rate
|
||||
# than the actual output can accept, causing the backend to apply its own
|
||||
# resampling pass after OpenAL Soft mixes the sources and processes effects
|
||||
# for output.
|
||||
#allow-resampler = true
|
||||
|
||||
##
|
||||
## DirectSound backend stuff
|
||||
##
|
||||
[dsound]
|
||||
|
||||
##
|
||||
## Windows Multimedia backend stuff
|
||||
##
|
||||
[winmm]
|
||||
|
||||
##
|
||||
## PortAudio backend stuff
|
||||
##
|
||||
[port]
|
||||
|
||||
## device: (global)
|
||||
# Sets the device index for output. Negative values will use the default as
|
||||
# given by PortAudio itself.
|
||||
#device = -1
|
||||
|
||||
## capture: (global)
|
||||
# Sets the device index for capture. Negative values will use the default as
|
||||
# given by PortAudio itself.
|
||||
#capture = -1
|
||||
|
||||
##
|
||||
## Wave File Writer stuff
|
||||
##
|
||||
[wave]
|
||||
|
||||
## file: (global)
|
||||
# Sets the filename of the wave file to write to. An empty name prevents the
|
||||
# backend from opening, even when explicitly requested.
|
||||
# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
|
||||
#file =
|
||||
|
||||
## bformat: (global)
|
||||
# Creates AMB format files using first-order ambisonics instead of a standard
|
||||
# single- or multi-channel .wav file.
|
||||
#bformat = false
|
||||
|
||||
##
|
||||
## EAX extensions stuff
|
||||
##
|
||||
[eax]
|
||||
|
||||
## enable: (global)
|
||||
# Sets whether to enable EAX extensions or not.
|
||||
#enable = true
|
||||
|
||||
##
|
||||
## Per-game compatibility options (these should only be set in per-game config
|
||||
## files, *NOT* system- or user-level!)
|
||||
##
|
||||
[game_compat]
|
||||
|
||||
## nfc-scale: (global)
|
||||
# A meters-per-unit distance scale applied to NFC filters. If a game doesn't
|
||||
# use real-world meters for in-game units, the filters may create a too-near
|
||||
# or too-distant effect. For instance, if the game uses 1 foot per unit, a
|
||||
# value of 0.3048 will correctly adjust the filters. Or if the game uses 1
|
||||
# kilometer per unit, a value of 1000 will correctly adjust the filters.
|
||||
#nfc-scale = 1
|
||||
|
||||
## enable-sub-data-ext: (global)
|
||||
# Enables the AL_SOFT_buffer_sub_data extension, disabling the
|
||||
# AL_EXT_SOURCE_RADIUS extension. These extensions are incompatible, so only
|
||||
# one can be available. The latter extension is more commonly used, but this
|
||||
# option can be enabled for older apps that want the former extension.
|
||||
#enable-sub-data-ext = false
|
||||
|
||||
## reverse-x: (global)
|
||||
# Reverses the local X (left-right) position of 3D sound sources.
|
||||
#reverse-x = false
|
||||
|
||||
## reverse-y: (global)
|
||||
# Reverses the local Y (up-down) position of 3D sound sources.
|
||||
#reverse-y = false
|
||||
|
||||
## reverse-z: (global)
|
||||
# Reverses the local Z (front-back) position of 3D sound sources.
|
||||
#reverse-z = false
|
21
appveyor.yml
21
appveyor.yml
@ -1,21 +0,0 @@
|
||||
version: 1.23.0.{build}
|
||||
|
||||
environment:
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
GEN: "Visual Studio 15 2017"
|
||||
matrix:
|
||||
- ARCH: Win32
|
||||
CFG: Release
|
||||
- ARCH: x64
|
||||
CFG: Release
|
||||
|
||||
after_build:
|
||||
- 7z a ..\soft_oal.zip "%APPVEYOR_BUILD_FOLDER%\build\%CFG%\soft_oal.dll" "%APPVEYOR_BUILD_FOLDER%\README.md" "%APPVEYOR_BUILD_FOLDER%\COPYING"
|
||||
|
||||
artifacts:
|
||||
- path: soft_oal.zip
|
||||
|
||||
build_script:
|
||||
- cd build
|
||||
- cmake -G "%GEN%" -A %ARCH% -DALSOFT_BUILD_ROUTER=ON -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_WASAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES ..
|
||||
- cmake --build . --config %CFG% --clean-first
|
@ -1,73 +0,0 @@
|
||||
# - Find alsa
|
||||
# Find the alsa libraries (asound)
|
||||
#
|
||||
# This module defines the following variables:
|
||||
# ALSA_FOUND - True if ALSA_INCLUDE_DIR & ALSA_LIBRARY are found
|
||||
# ALSA_LIBRARIES - Set when ALSA_LIBRARY is found
|
||||
# ALSA_INCLUDE_DIRS - Set when ALSA_INCLUDE_DIR is found
|
||||
#
|
||||
# ALSA_INCLUDE_DIR - where to find asoundlib.h, etc.
|
||||
# ALSA_LIBRARY - the asound library
|
||||
# ALSA_VERSION_STRING - the version of alsa found (since CMake 2.8.8)
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2009-2011 Kitware, Inc.
|
||||
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# * The names of Kitware, Inc., the Insight Consortium, or the names of
|
||||
# any consortium members, or of any contributors, may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
find_path(ALSA_INCLUDE_DIR NAMES alsa/asoundlib.h
|
||||
DOC "The ALSA (asound) include directory"
|
||||
)
|
||||
|
||||
find_library(ALSA_LIBRARY NAMES asound
|
||||
DOC "The ALSA (asound) library"
|
||||
)
|
||||
|
||||
if(ALSA_INCLUDE_DIR AND EXISTS "${ALSA_INCLUDE_DIR}/alsa/version.h")
|
||||
file(STRINGS "${ALSA_INCLUDE_DIR}/alsa/version.h" alsa_version_str REGEX "^#define[\t ]+SND_LIB_VERSION_STR[\t ]+\".*\"")
|
||||
|
||||
string(REGEX REPLACE "^.*SND_LIB_VERSION_STR[\t ]+\"([^\"]*)\".*$" "\\1" ALSA_VERSION_STRING "${alsa_version_str}")
|
||||
unset(alsa_version_str)
|
||||
endif()
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set ALSA_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ALSA
|
||||
REQUIRED_VARS ALSA_LIBRARY ALSA_INCLUDE_DIR
|
||||
VERSION_VAR ALSA_VERSION_STRING)
|
||||
|
||||
if(ALSA_FOUND)
|
||||
set( ALSA_LIBRARIES ${ALSA_LIBRARY} )
|
||||
set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY)
|
@ -1,21 +0,0 @@
|
||||
# - Find AudioIO includes and libraries
|
||||
#
|
||||
# AUDIOIO_FOUND - True if AUDIOIO_INCLUDE_DIR is found
|
||||
# AUDIOIO_INCLUDE_DIRS - Set when AUDIOIO_INCLUDE_DIR is found
|
||||
#
|
||||
# AUDIOIO_INCLUDE_DIR - where to find sys/audioio.h, etc.
|
||||
#
|
||||
|
||||
find_path(AUDIOIO_INCLUDE_DIR
|
||||
NAMES sys/audioio.h
|
||||
DOC "The AudioIO include directory"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(AudioIO REQUIRED_VARS AUDIOIO_INCLUDE_DIR)
|
||||
|
||||
if(AUDIOIO_FOUND)
|
||||
set(AUDIOIO_INCLUDE_DIRS ${AUDIOIO_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(AUDIOIO_INCLUDE_DIR)
|
@ -1,157 +0,0 @@
|
||||
# vim: ts=2 sw=2
|
||||
# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)
|
||||
#
|
||||
# Once done this will define
|
||||
# FFMPEG_FOUND - System has the all required components.
|
||||
# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
|
||||
# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components.
|
||||
# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components.
|
||||
#
|
||||
# For each of the components it will additionaly set.
|
||||
# - AVCODEC
|
||||
# - AVDEVICE
|
||||
# - AVFORMAT
|
||||
# - AVUTIL
|
||||
# - POSTPROC
|
||||
# - SWSCALE
|
||||
# - SWRESAMPLE
|
||||
# the following variables will be defined
|
||||
# <component>_FOUND - System has <component>
|
||||
# <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers
|
||||
# <component>_LIBRARIES - Link these to use <component>
|
||||
# <component>_DEFINITIONS - Compiler switches required for using <component>
|
||||
# <component>_VERSION - The components version
|
||||
#
|
||||
# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org>
|
||||
# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org>
|
||||
# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if(NOT FFmpeg_FIND_COMPONENTS)
|
||||
set(FFmpeg_FIND_COMPONENTS AVFORMAT AVCODEC AVUTIL)
|
||||
endif()
|
||||
|
||||
#
|
||||
### Macro: set_component_found
|
||||
#
|
||||
# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.
|
||||
#
|
||||
macro(set_component_found _component)
|
||||
if(${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
|
||||
# message(STATUS " - ${_component} found.")
|
||||
set(${_component}_FOUND TRUE)
|
||||
else()
|
||||
# message(STATUS " - ${_component} not found.")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
#
|
||||
### Macro: find_component
|
||||
#
|
||||
# Checks for the given component by invoking pkgconfig and then looking up the libraries and
|
||||
# include directories.
|
||||
#
|
||||
macro(find_component _component _pkgconfig _library _header)
|
||||
if(NOT WIN32)
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
find_package(PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(PC_${_component} ${_pkgconfig})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_path(${_component}_INCLUDE_DIRS ${_header}
|
||||
HINTS
|
||||
${FFMPEGSDK_INC}
|
||||
${PC_LIB${_component}_INCLUDEDIR}
|
||||
${PC_LIB${_component}_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES
|
||||
ffmpeg
|
||||
)
|
||||
|
||||
find_library(${_component}_LIBRARIES NAMES ${_library}
|
||||
HINTS
|
||||
${FFMPEGSDK_LIB}
|
||||
${PC_LIB${_component}_LIBDIR}
|
||||
${PC_LIB${_component}_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number." FORCE)
|
||||
set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS." FORCE)
|
||||
|
||||
set_component_found(${_component})
|
||||
|
||||
mark_as_advanced(
|
||||
${_component}_INCLUDE_DIRS
|
||||
${_component}_LIBRARIES
|
||||
${_component}_DEFINITIONS
|
||||
${_component}_VERSION)
|
||||
endmacro()
|
||||
|
||||
|
||||
set(FFMPEGSDK $ENV{FFMPEG_HOME})
|
||||
if(FFMPEGSDK)
|
||||
set(FFMPEGSDK_INC "${FFMPEGSDK}/include")
|
||||
set(FFMPEGSDK_LIB "${FFMPEGSDK}/lib")
|
||||
endif()
|
||||
|
||||
# Check for all possible components.
|
||||
find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h)
|
||||
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
|
||||
find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h)
|
||||
find_component(AVUTIL libavutil avutil libavutil/avutil.h)
|
||||
find_component(SWSCALE libswscale swscale libswscale/swscale.h)
|
||||
find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
|
||||
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
|
||||
|
||||
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
|
||||
foreach(_component ${FFmpeg_FIND_COMPONENTS})
|
||||
if(${_component}_FOUND)
|
||||
# message(STATUS "Required component ${_component} present.")
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES})
|
||||
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
|
||||
list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
|
||||
else()
|
||||
# message(STATUS "Required component ${_component} missing.")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Add libz if it exists (needed for static ffmpeg builds)
|
||||
find_library(_FFmpeg_HAVE_LIBZ NAMES z)
|
||||
if(_FFmpeg_HAVE_LIBZ)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${_FFmpeg_HAVE_LIBZ})
|
||||
endif()
|
||||
|
||||
# Build the include path and library list with duplicates removed.
|
||||
if(FFMPEG_INCLUDE_DIRS)
|
||||
list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
if(FFMPEG_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES FFMPEG_LIBRARIES)
|
||||
endif()
|
||||
|
||||
# cache the vars.
|
||||
set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE)
|
||||
set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE)
|
||||
|
||||
mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS)
|
||||
|
||||
# Now set the noncached _FOUND vars for the components.
|
||||
foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWRESAMPLE SWSCALE)
|
||||
set_component_found(${_component})
|
||||
endforeach ()
|
||||
|
||||
# Compile the list of required vars
|
||||
set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
|
||||
foreach(_component ${FFmpeg_FIND_COMPONENTS})
|
||||
list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)
|
||||
endforeach()
|
||||
|
||||
# Give a nice error message if some of the required vars are missing.
|
||||
find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})
|
@ -1,60 +0,0 @@
|
||||
# - Find JACK
|
||||
# Find the JACK libraries
|
||||
#
|
||||
# This module defines the following variables:
|
||||
# JACK_FOUND - True if JACK_INCLUDE_DIR & JACK_LIBRARY are found
|
||||
# JACK_INCLUDE_DIRS - where to find jack.h, etc.
|
||||
# JACK_LIBRARIES - the jack library
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2009-2011 Kitware, Inc.
|
||||
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# * The names of Kitware, Inc., the Insight Consortium, or the names of
|
||||
# any consortium members, or of any contributors, may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
find_path(JACK_INCLUDE_DIR NAMES jack/jack.h
|
||||
DOC "The JACK include directory"
|
||||
)
|
||||
|
||||
find_library(JACK_LIBRARY NAMES jack
|
||||
DOC "The JACK library"
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set JACK_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(JACK REQUIRED_VARS JACK_LIBRARY JACK_INCLUDE_DIR)
|
||||
|
||||
if(JACK_FOUND)
|
||||
set(JACK_LIBRARIES ${JACK_LIBRARY})
|
||||
set(JACK_INCLUDE_DIRS ${JACK_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(JACK_INCLUDE_DIR JACK_LIBRARY)
|
@ -1,81 +0,0 @@
|
||||
# - Find MySOFA
|
||||
# Find the MySOFA libraries
|
||||
#
|
||||
# This module defines the following variables:
|
||||
# MYSOFA_FOUND - True if MYSOFA_INCLUDE_DIR & MYSOFA_LIBRARY are found
|
||||
# MYSOFA_INCLUDE_DIRS - where to find mysofa.h, etc.
|
||||
# MYSOFA_LIBRARIES - the MySOFA library
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2009-2011 Kitware, Inc.
|
||||
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# * The names of Kitware, Inc., the Insight Consortium, or the names of
|
||||
# any consortium members, or of any contributors, may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
find_package(ZLIB)
|
||||
|
||||
find_path(MYSOFA_INCLUDE_DIR NAMES mysofa.h
|
||||
DOC "The MySOFA include directory"
|
||||
)
|
||||
|
||||
find_library(MYSOFA_LIBRARY NAMES mysofa
|
||||
DOC "The MySOFA library"
|
||||
)
|
||||
|
||||
find_library(MYSOFA_M_LIBRARY NAMES m
|
||||
DOC "The math library for MySOFA"
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set MYSOFA_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MySOFA REQUIRED_VARS MYSOFA_LIBRARY MYSOFA_INCLUDE_DIR ZLIB_FOUND)
|
||||
|
||||
if(MYSOFA_FOUND)
|
||||
set(MYSOFA_INCLUDE_DIRS ${MYSOFA_INCLUDE_DIR})
|
||||
set(MYSOFA_LIBRARIES ${MYSOFA_LIBRARY})
|
||||
set(MYSOFA_LIBRARIES ${MYSOFA_LIBRARIES} ZLIB::ZLIB)
|
||||
if(MYSOFA_M_LIBRARY)
|
||||
set(MYSOFA_LIBRARIES ${MYSOFA_LIBRARIES} ${MYSOFA_M_LIBRARY})
|
||||
endif()
|
||||
|
||||
add_library(MySOFA::MySOFA UNKNOWN IMPORTED)
|
||||
set_property(TARGET MySOFA::MySOFA PROPERTY
|
||||
IMPORTED_LOCATION ${MYSOFA_LIBRARY})
|
||||
set_target_properties(MySOFA::MySOFA PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${MYSOFA_INCLUDE_DIRS}
|
||||
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
|
||||
if(MYSOFA_M_LIBRARY)
|
||||
set_property(TARGET MySOFA::MySOFA APPEND PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${MYSOFA_M_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(MYSOFA_INCLUDE_DIR MYSOFA_LIBRARY)
|
@ -1,33 +0,0 @@
|
||||
# - Find OSS includes
|
||||
#
|
||||
# OSS_FOUND - True if OSS_INCLUDE_DIR is found
|
||||
# OSS_INCLUDE_DIRS - Set when OSS_INCLUDE_DIR is found
|
||||
# OSS_LIBRARIES - Set when OSS_LIBRARY is found
|
||||
#
|
||||
# OSS_INCLUDE_DIR - where to find sys/soundcard.h, etc.
|
||||
# OSS_LIBRARY - where to find libossaudio (optional).
|
||||
#
|
||||
|
||||
find_path(OSS_INCLUDE_DIR
|
||||
NAMES sys/soundcard.h
|
||||
DOC "The OSS include directory"
|
||||
)
|
||||
|
||||
find_library(OSS_LIBRARY
|
||||
NAMES ossaudio
|
||||
DOC "Optional OSS library"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OSS REQUIRED_VARS OSS_INCLUDE_DIR)
|
||||
|
||||
if(OSS_FOUND)
|
||||
set(OSS_INCLUDE_DIRS ${OSS_INCLUDE_DIR})
|
||||
if(OSS_LIBRARY)
|
||||
set(OSS_LIBRARIES ${OSS_LIBRARY})
|
||||
else()
|
||||
unset(OSS_LIBRARIES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(OSS_INCLUDE_DIR OSS_LIBRARY)
|
@ -1,31 +0,0 @@
|
||||
# - Find Oboe
|
||||
# Find the Oboe library
|
||||
#
|
||||
# This module defines the following variable:
|
||||
# OBOE_FOUND - True if Oboe was found
|
||||
#
|
||||
# This module defines the following target:
|
||||
# oboe::oboe - Import target for linking Oboe to a project
|
||||
#
|
||||
|
||||
find_path(OBOE_INCLUDE_DIR NAMES oboe/Oboe.h
|
||||
DOC "The Oboe include directory"
|
||||
)
|
||||
|
||||
find_library(OBOE_LIBRARY NAMES oboe
|
||||
DOC "The Oboe library"
|
||||
)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set OBOE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Oboe REQUIRED_VARS OBOE_LIBRARY OBOE_INCLUDE_DIR)
|
||||
|
||||
if(OBOE_FOUND)
|
||||
add_library(oboe::oboe UNKNOWN IMPORTED)
|
||||
set_target_properties(oboe::oboe PROPERTIES
|
||||
IMPORTED_LOCATION ${OBOE_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${OBOE_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(OBOE_INCLUDE_DIR OBOE_LIBRARY)
|
@ -1,63 +0,0 @@
|
||||
# - Find OpenSL
|
||||
# Find the OpenSL libraries
|
||||
#
|
||||
# This module defines the following variables and targets:
|
||||
# OPENSL_FOUND - True if OPENSL was found
|
||||
# OpenSL::OpenSLES - The OpenSLES target
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2009-2011 Kitware, Inc.
|
||||
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# * The names of Kitware, Inc., the Insight Consortium, or the names of
|
||||
# any consortium members, or of any contributors, may not be used to
|
||||
# endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
find_path(OPENSL_INCLUDE_DIR NAMES SLES/OpenSLES.h
|
||||
DOC "The OpenSL include directory")
|
||||
find_path(OPENSL_ANDROID_INCLUDE_DIR NAMES SLES/OpenSLES_Android.h
|
||||
DOC "The OpenSL Android include directory")
|
||||
|
||||
find_library(OPENSL_LIBRARY NAMES OpenSLES
|
||||
DOC "The OpenSL library")
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set OPENSL_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OpenSL REQUIRED_VARS OPENSL_LIBRARY OPENSL_INCLUDE_DIR
|
||||
OPENSL_ANDROID_INCLUDE_DIR)
|
||||
|
||||
if(OPENSL_FOUND)
|
||||
add_library(OpenSL::OpenSLES UNKNOWN IMPORTED)
|
||||
set_target_properties(OpenSL::OpenSLES PROPERTIES
|
||||
IMPORTED_LOCATION ${OPENSL_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${OPENSL_INCLUDE_DIR}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${OPENSL_ANDROID_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(OPENSL_INCLUDE_DIR OPENSL_ANDROID_INCLUDE_DIR OPENSL_LIBRARY)
|
@ -1,32 +0,0 @@
|
||||
# - Find PortAudio includes and libraries
|
||||
#
|
||||
# PORTAUDIO_FOUND - True if PORTAUDIO_INCLUDE_DIR & PORTAUDIO_LIBRARY
|
||||
# are found
|
||||
# PORTAUDIO_LIBRARIES - Set when PORTAUDIO_LIBRARY is found
|
||||
# PORTAUDIO_INCLUDE_DIRS - Set when PORTAUDIO_INCLUDE_DIR is found
|
||||
#
|
||||
# PORTAUDIO_INCLUDE_DIR - where to find portaudio.h, etc.
|
||||
# PORTAUDIO_LIBRARY - the portaudio library
|
||||
#
|
||||
|
||||
find_path(PORTAUDIO_INCLUDE_DIR
|
||||
NAMES portaudio.h
|
||||
DOC "The PortAudio include directory"
|
||||
)
|
||||
|
||||
find_library(PORTAUDIO_LIBRARY
|
||||
NAMES portaudio
|
||||
DOC "The PortAudio library"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(PortAudio
|
||||
REQUIRED_VARS PORTAUDIO_LIBRARY PORTAUDIO_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if(PORTAUDIO_FOUND)
|
||||
set(PORTAUDIO_LIBRARIES ${PORTAUDIO_LIBRARY})
|
||||
set(PORTAUDIO_INCLUDE_DIRS ${PORTAUDIO_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(PORTAUDIO_INCLUDE_DIR PORTAUDIO_LIBRARY)
|
@ -1,34 +0,0 @@
|
||||
# - Find PulseAudio includes and libraries
|
||||
#
|
||||
# PULSEAUDIO_FOUND - True if PULSEAUDIO_INCLUDE_DIR &
|
||||
# PULSEAUDIO_LIBRARY are found
|
||||
#
|
||||
# PULSEAUDIO_INCLUDE_DIR - where to find pulse/pulseaudio.h, etc.
|
||||
# PULSEAUDIO_LIBRARY - the pulse library
|
||||
# PULSEAUDIO_VERSION_STRING - the version of PulseAudio found
|
||||
#
|
||||
|
||||
find_path(PULSEAUDIO_INCLUDE_DIR
|
||||
NAMES pulse/pulseaudio.h
|
||||
DOC "The PulseAudio include directory"
|
||||
)
|
||||
|
||||
find_library(PULSEAUDIO_LIBRARY
|
||||
NAMES pulse
|
||||
DOC "The PulseAudio library"
|
||||
)
|
||||
|
||||
if(PULSEAUDIO_INCLUDE_DIR AND EXISTS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h")
|
||||
file(STRINGS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h" pulse_version_str
|
||||
REGEX "^#define[\t ]+pa_get_headers_version\\(\\)[\t ]+\\(\".*\"\\)")
|
||||
|
||||
string(REGEX REPLACE "^.*pa_get_headers_version\\(\\)[\t ]+\\(\"([^\"]*)\"\\).*$" "\\1"
|
||||
PULSEAUDIO_VERSION_STRING "${pulse_version_str}")
|
||||
unset(pulse_version_str)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(PulseAudio
|
||||
REQUIRED_VARS PULSEAUDIO_LIBRARY PULSEAUDIO_INCLUDE_DIR
|
||||
VERSION_VAR PULSEAUDIO_VERSION_STRING
|
||||
)
|
@ -1,25 +0,0 @@
|
||||
# - Try to find SndFile
|
||||
# Once done this will define
|
||||
#
|
||||
# SNDFILE_FOUND - system has SndFile
|
||||
# SndFile::SndFile - the SndFile target
|
||||
#
|
||||
|
||||
find_path(SNDFILE_INCLUDE_DIR NAMES sndfile.h)
|
||||
|
||||
find_library(SNDFILE_LIBRARY NAMES sndfile sndfile-1)
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set SNDFILE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
|
||||
|
||||
if(SNDFILE_FOUND)
|
||||
add_library(SndFile::SndFile UNKNOWN IMPORTED)
|
||||
set_target_properties(SndFile::SndFile PROPERTIES
|
||||
IMPORTED_LOCATION ${SNDFILE_LIBRARY}
|
||||
INTERFACE_INCLUDE_DIRECTORIES ${SNDFILE_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# show the SNDFILE_INCLUDE_DIR and SNDFILE_LIBRARY variables only in the advanced view
|
||||
mark_as_advanced(SNDFILE_INCLUDE_DIR SNDFILE_LIBRARY)
|
@ -1,32 +0,0 @@
|
||||
# - Find SoundIO (sndio) includes and libraries
|
||||
#
|
||||
# SOUNDIO_FOUND - True if SOUNDIO_INCLUDE_DIR & SOUNDIO_LIBRARY are
|
||||
# found
|
||||
# SOUNDIO_LIBRARIES - Set when SOUNDIO_LIBRARY is found
|
||||
# SOUNDIO_INCLUDE_DIRS - Set when SOUNDIO_INCLUDE_DIR is found
|
||||
#
|
||||
# SOUNDIO_INCLUDE_DIR - where to find sndio.h, etc.
|
||||
# SOUNDIO_LIBRARY - the sndio library
|
||||
#
|
||||
|
||||
find_path(SOUNDIO_INCLUDE_DIR
|
||||
NAMES sndio.h
|
||||
DOC "The SoundIO include directory"
|
||||
)
|
||||
|
||||
find_library(SOUNDIO_LIBRARY
|
||||
NAMES sndio
|
||||
DOC "The SoundIO library"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SoundIO
|
||||
REQUIRED_VARS SOUNDIO_LIBRARY SOUNDIO_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if(SOUNDIO_FOUND)
|
||||
set(SOUNDIO_LIBRARIES ${SOUNDIO_LIBRARY})
|
||||
set(SOUNDIO_INCLUDE_DIRS ${SOUNDIO_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(SOUNDIO_INCLUDE_DIR SOUNDIO_LIBRARY)
|
@ -1,12 +0,0 @@
|
||||
# Read the input file into 'indata', converting each byte to a pair of hex
|
||||
# characters
|
||||
file(READ "${INPUT_FILE}" indata HEX)
|
||||
|
||||
# For each pair of characters, indent them and prepend the 0x prefix, and
|
||||
# append a comma separateor.
|
||||
# TODO: Prettify this. Should group a number of bytes per line instead of one
|
||||
# per line.
|
||||
string(REGEX REPLACE "(..)" " 0x\\1,\n" output "${indata}")
|
||||
|
||||
# Write the list of hex chars to the output file
|
||||
file(WRITE "${OUTPUT_FILE}" "${output}")
|
@ -75,7 +75,10 @@ AmbDecConf::~AmbDecConf() = default;
|
||||
|
||||
al::optional<std::string> AmbDecConf::load(const char *fname) noexcept
|
||||
{
|
||||
al::ifstream f{fname};
|
||||
AuString str = fname;
|
||||
AuFS::NormalizePath(str, str);
|
||||
al::ifstream f{ str };
|
||||
|
||||
if(!f.is_open())
|
||||
return std::string("Failed to open file \"")+fname+"\"";
|
||||
|
||||
|
@ -1323,7 +1323,11 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate)
|
||||
else
|
||||
{
|
||||
TRACE("Loading %s...\n", fname.c_str());
|
||||
auto fstr = std::make_unique<al::ifstream>(fname.c_str(), std::ios::binary);
|
||||
|
||||
AuString str = fname.c_str();
|
||||
AuFS::NormalizePath(str, str);
|
||||
|
||||
auto fstr = std::make_unique<al::ifstream>(str, std::ios::binary);
|
||||
if(!fstr->is_open())
|
||||
{
|
||||
ERR("Could not open %s\n", fname.c_str());
|
||||
|
12
openal.pc.in
12
openal.pc.in
@ -1,12 +0,0 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: OpenAL
|
||||
Description: OpenAL is a cross-platform 3D audio API
|
||||
Requires: @PKG_CONFIG_REQUIRES@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -l@LIBNAME@ @PKG_CONFIG_LIBS@
|
||||
Libs.private:@PKG_CONFIG_PRIVATE_LIBS@
|
||||
Cflags: -I${includedir} -I${includedir}/AL @PKG_CONFIG_CFLAGS@
|
@ -1,90 +0,0 @@
|
||||
#pragma code_page(65001)
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "version.h"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION ALSOFT_VERSION_NUM
|
||||
PRODUCTVERSION ALSOFT_VERSION_NUM
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", ""
|
||||
VALUE "FileDescription", "Main implementation library"
|
||||
VALUE "FileVersion", ALSOFT_VERSION
|
||||
VALUE "InternalName", "OpenAL32.dll"
|
||||
VALUE "LegalCopyright", "GNU LGPL - Version 2, June 1991"
|
||||
VALUE "OriginalFilename", "OpenAL32.dll"
|
||||
VALUE "ProductName", "OpenAL Soft"
|
||||
VALUE "ProductVersion", ALSOFT_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
@ -1,15 +0,0 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by openal32.rc, router.rc, soft_oal.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
@ -1,90 +0,0 @@
|
||||
#pragma code_page(65001)
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "version.h"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION ALSOFT_VERSION_NUM
|
||||
PRODUCTVERSION ALSOFT_VERSION_NUM
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", ""
|
||||
VALUE "FileDescription", "Router library"
|
||||
VALUE "FileVersion", ALSOFT_VERSION
|
||||
VALUE "InternalName", "OpenAL32.dll"
|
||||
VALUE "LegalCopyright", "GNU LGPL - Version 2, June 1991"
|
||||
VALUE "OriginalFilename", "OpenAL32.dll"
|
||||
VALUE "ProductName", "OpenAL Soft"
|
||||
VALUE "ProductVersion", ALSOFT_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
@ -1,90 +0,0 @@
|
||||
#pragma code_page(65001)
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "version.h"
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION ALSOFT_VERSION_NUM
|
||||
PRODUCTVERSION ALSOFT_VERSION_NUM
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", ""
|
||||
VALUE "FileDescription", "Main implementation library"
|
||||
VALUE "FileVersion", ALSOFT_VERSION
|
||||
VALUE "InternalName", "soft_oal.dll"
|
||||
VALUE "LegalCopyright", "GNU LGPL - Version 2, June 1991"
|
||||
VALUE "OriginalFilename", "soft_oal.dll"
|
||||
VALUE "ProductName", "OpenAL Soft"
|
||||
VALUE "ProductVersion", ALSOFT_VERSION
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
171
router/al.cpp
171
router/al.cpp
@ -1,171 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "router.h"
|
||||
|
||||
|
||||
std::atomic<DriverIface*> CurrentCtxDriver{nullptr};
|
||||
|
||||
#define DECL_THUNK1(R,n,T1) AL_API R AL_APIENTRY n(T1 a) \
|
||||
{ \
|
||||
DriverIface *iface = GetThreadDriver(); \
|
||||
if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
|
||||
return iface->n(a); \
|
||||
}
|
||||
#define DECL_THUNK2(R,n,T1,T2) AL_API R AL_APIENTRY n(T1 a, T2 b) \
|
||||
{ \
|
||||
DriverIface *iface = GetThreadDriver(); \
|
||||
if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
|
||||
return iface->n(a, b); \
|
||||
}
|
||||
#define DECL_THUNK3(R,n,T1,T2,T3) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c) \
|
||||
{ \
|
||||
DriverIface *iface = GetThreadDriver(); \
|
||||
if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
|
||||
return iface->n(a, b, c); \
|
||||
}
|
||||
#define DECL_THUNK4(R,n,T1,T2,T3,T4) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c, T4 d) \
|
||||
{ \
|
||||
DriverIface *iface = GetThreadDriver(); \
|
||||
if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
|
||||
return iface->n(a, b, c, d); \
|
||||
}
|
||||
#define DECL_THUNK5(R,n,T1,T2,T3,T4,T5) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c, T4 d, T5 e) \
|
||||
{ \
|
||||
DriverIface *iface = GetThreadDriver(); \
|
||||
if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
|
||||
return iface->n(a, b, c, d, e); \
|
||||
}
|
||||
|
||||
|
||||
/* Ugly hack for some apps calling alGetError without a current context, and
|
||||
* expecting it to be AL_NO_ERROR.
|
||||
*/
|
||||
AL_API ALenum AL_APIENTRY alGetError(void)
|
||||
{
|
||||
DriverIface *iface = GetThreadDriver();
|
||||
if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire);
|
||||
return iface ? iface->alGetError() : AL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
DECL_THUNK1(void, alDopplerFactor, ALfloat)
|
||||
DECL_THUNK1(void, alDopplerVelocity, ALfloat)
|
||||
DECL_THUNK1(void, alSpeedOfSound, ALfloat)
|
||||
DECL_THUNK1(void, alDistanceModel, ALenum)
|
||||
|
||||
DECL_THUNK1(void, alEnable, ALenum)
|
||||
DECL_THUNK1(void, alDisable, ALenum)
|
||||
DECL_THUNK1(ALboolean, alIsEnabled, ALenum)
|
||||
|
||||
DECL_THUNK1(const ALchar*, alGetString, ALenum)
|
||||
DECL_THUNK2(void, alGetBooleanv, ALenum, ALboolean*)
|
||||
DECL_THUNK2(void, alGetIntegerv, ALenum, ALint*)
|
||||
DECL_THUNK2(void, alGetFloatv, ALenum, ALfloat*)
|
||||
DECL_THUNK2(void, alGetDoublev, ALenum, ALdouble*)
|
||||
DECL_THUNK1(ALboolean, alGetBoolean, ALenum)
|
||||
DECL_THUNK1(ALint, alGetInteger, ALenum)
|
||||
DECL_THUNK1(ALfloat, alGetFloat, ALenum)
|
||||
DECL_THUNK1(ALdouble, alGetDouble, ALenum)
|
||||
|
||||
DECL_THUNK1(ALboolean, alIsExtensionPresent, const ALchar*)
|
||||
DECL_THUNK1(void*, alGetProcAddress, const ALchar*)
|
||||
DECL_THUNK1(ALenum, alGetEnumValue, const ALchar*)
|
||||
|
||||
DECL_THUNK2(void, alListenerf, ALenum, ALfloat)
|
||||
DECL_THUNK4(void, alListener3f, ALenum, ALfloat, ALfloat, ALfloat)
|
||||
DECL_THUNK2(void, alListenerfv, ALenum, const ALfloat*)
|
||||
DECL_THUNK2(void, alListeneri, ALenum, ALint)
|
||||
DECL_THUNK4(void, alListener3i, ALenum, ALint, ALint, ALint)
|
||||
DECL_THUNK2(void, alListeneriv, ALenum, const ALint*)
|
||||
DECL_THUNK2(void, alGetListenerf, ALenum, ALfloat*)
|
||||
DECL_THUNK4(void, alGetListener3f, ALenum, ALfloat*, ALfloat*, ALfloat*)
|
||||
DECL_THUNK2(void, alGetListenerfv, ALenum, ALfloat*)
|
||||
DECL_THUNK2(void, alGetListeneri, ALenum, ALint*)
|
||||
DECL_THUNK4(void, alGetListener3i, ALenum, ALint*, ALint*, ALint*)
|
||||
DECL_THUNK2(void, alGetListeneriv, ALenum, ALint*)
|
||||
|
||||
DECL_THUNK2(void, alGenSources, ALsizei, ALuint*)
|
||||
DECL_THUNK2(void, alDeleteSources, ALsizei, const ALuint*)
|
||||
DECL_THUNK1(ALboolean, alIsSource, ALuint)
|
||||
DECL_THUNK3(void, alSourcef, ALuint, ALenum, ALfloat)
|
||||
DECL_THUNK5(void, alSource3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat)
|
||||
DECL_THUNK3(void, alSourcefv, ALuint, ALenum, const ALfloat*)
|
||||
DECL_THUNK3(void, alSourcei, ALuint, ALenum, ALint)
|
||||
DECL_THUNK5(void, alSource3i, ALuint, ALenum, ALint, ALint, ALint)
|
||||
DECL_THUNK3(void, alSourceiv, ALuint, ALenum, const ALint*)
|
||||
DECL_THUNK3(void, alGetSourcef, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK5(void, alGetSource3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*)
|
||||
DECL_THUNK3(void, alGetSourcefv, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetSourcei, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK5(void, alGetSource3i, ALuint, ALenum, ALint*, ALint*, ALint*)
|
||||
DECL_THUNK3(void, alGetSourceiv, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK2(void, alSourcePlayv, ALsizei, const ALuint*)
|
||||
DECL_THUNK2(void, alSourceStopv, ALsizei, const ALuint*)
|
||||
DECL_THUNK2(void, alSourceRewindv, ALsizei, const ALuint*)
|
||||
DECL_THUNK2(void, alSourcePausev, ALsizei, const ALuint*)
|
||||
DECL_THUNK1(void, alSourcePlay, ALuint)
|
||||
DECL_THUNK1(void, alSourceStop, ALuint)
|
||||
DECL_THUNK1(void, alSourceRewind, ALuint)
|
||||
DECL_THUNK1(void, alSourcePause, ALuint)
|
||||
DECL_THUNK3(void, alSourceQueueBuffers, ALuint, ALsizei, const ALuint*)
|
||||
DECL_THUNK3(void, alSourceUnqueueBuffers, ALuint, ALsizei, ALuint*)
|
||||
|
||||
DECL_THUNK2(void, alGenBuffers, ALsizei, ALuint*)
|
||||
DECL_THUNK2(void, alDeleteBuffers, ALsizei, const ALuint*)
|
||||
DECL_THUNK1(ALboolean, alIsBuffer, ALuint)
|
||||
DECL_THUNK3(void, alBufferf, ALuint, ALenum, ALfloat)
|
||||
DECL_THUNK5(void, alBuffer3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat)
|
||||
DECL_THUNK3(void, alBufferfv, ALuint, ALenum, const ALfloat*)
|
||||
DECL_THUNK3(void, alBufferi, ALuint, ALenum, ALint)
|
||||
DECL_THUNK5(void, alBuffer3i, ALuint, ALenum, ALint, ALint, ALint)
|
||||
DECL_THUNK3(void, alBufferiv, ALuint, ALenum, const ALint*)
|
||||
DECL_THUNK3(void, alGetBufferf, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK5(void, alGetBuffer3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*)
|
||||
DECL_THUNK3(void, alGetBufferfv, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetBufferi, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK5(void, alGetBuffer3i, ALuint, ALenum, ALint*, ALint*, ALint*)
|
||||
DECL_THUNK3(void, alGetBufferiv, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK5(void, alBufferData, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei)
|
||||
|
||||
/* EFX 1.0. Required here to be exported from libOpenAL32.dll.a/OpenAL32.lib
|
||||
* with the router enabled.
|
||||
*/
|
||||
DECL_THUNK2(void, alGenFilters, ALsizei, ALuint*)
|
||||
DECL_THUNK2(void, alDeleteFilters, ALsizei, const ALuint*)
|
||||
DECL_THUNK1(ALboolean, alIsFilter, ALuint)
|
||||
DECL_THUNK3(void, alFilterf, ALuint, ALenum, ALfloat)
|
||||
DECL_THUNK3(void, alFilterfv, ALuint, ALenum, const ALfloat*)
|
||||
DECL_THUNK3(void, alFilteri, ALuint, ALenum, ALint)
|
||||
DECL_THUNK3(void, alFilteriv, ALuint, ALenum, const ALint*)
|
||||
DECL_THUNK3(void, alGetFilterf, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetFilterfv, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetFilteri, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK3(void, alGetFilteriv, ALuint, ALenum, ALint*)
|
||||
|
||||
DECL_THUNK2(void, alGenEffects, ALsizei, ALuint*)
|
||||
DECL_THUNK2(void, alDeleteEffects, ALsizei, const ALuint*)
|
||||
DECL_THUNK1(ALboolean, alIsEffect, ALuint)
|
||||
DECL_THUNK3(void, alEffectf, ALuint, ALenum, ALfloat)
|
||||
DECL_THUNK3(void, alEffectfv, ALuint, ALenum, const ALfloat*)
|
||||
DECL_THUNK3(void, alEffecti, ALuint, ALenum, ALint)
|
||||
DECL_THUNK3(void, alEffectiv, ALuint, ALenum, const ALint*)
|
||||
DECL_THUNK3(void, alGetEffectf, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetEffectfv, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetEffecti, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK3(void, alGetEffectiv, ALuint, ALenum, ALint*)
|
||||
|
||||
DECL_THUNK2(void, alGenAuxiliaryEffectSlots, ALsizei, ALuint*)
|
||||
DECL_THUNK2(void, alDeleteAuxiliaryEffectSlots, ALsizei, const ALuint*)
|
||||
DECL_THUNK1(ALboolean, alIsAuxiliaryEffectSlot, ALuint)
|
||||
DECL_THUNK3(void, alAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat)
|
||||
DECL_THUNK3(void, alAuxiliaryEffectSlotfv, ALuint, ALenum, const ALfloat*)
|
||||
DECL_THUNK3(void, alAuxiliaryEffectSloti, ALuint, ALenum, ALint)
|
||||
DECL_THUNK3(void, alAuxiliaryEffectSlotiv, ALuint, ALenum, const ALint*)
|
||||
DECL_THUNK3(void, alGetAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetAuxiliaryEffectSlotfv, ALuint, ALenum, ALfloat*)
|
||||
DECL_THUNK3(void, alGetAuxiliaryEffectSloti, ALuint, ALenum, ALint*)
|
||||
DECL_THUNK3(void, alGetAuxiliaryEffectSlotiv, ALuint, ALenum, ALint*)
|
1017
router/alc.cpp
1017
router/alc.cpp
File diff suppressed because it is too large
Load Diff
@ -1,457 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "router.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "AL/alc.h"
|
||||
#include "AL/al.h"
|
||||
|
||||
#include "almalloc.h"
|
||||
#include "strutils.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
|
||||
std::vector<DriverIfacePtr> DriverList;
|
||||
|
||||
thread_local DriverIface *ThreadCtxDriver;
|
||||
|
||||
enum LogLevel LogLevel = LogLevel_Error;
|
||||
FILE *LogFile;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
DriverIface *GetThreadDriver() noexcept { return ThreadCtxDriver; }
|
||||
void SetThreadDriver(DriverIface *driver) noexcept { ThreadCtxDriver = driver; }
|
||||
#endif
|
||||
|
||||
static void LoadDriverList(void);
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain(HINSTANCE, DWORD reason, void*)
|
||||
{
|
||||
switch(reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
LogFile = stderr;
|
||||
if(auto logfname = al::getenv("ALROUTER_LOGFILE"))
|
||||
{
|
||||
FILE *f = fopen(logfname->c_str(), "w");
|
||||
if(f == nullptr)
|
||||
ERR("Could not open log file: %s\n", logfname->c_str());
|
||||
else
|
||||
LogFile = f;
|
||||
}
|
||||
if(auto loglev = al::getenv("ALROUTER_LOGLEVEL"))
|
||||
{
|
||||
char *end = nullptr;
|
||||
long l = strtol(loglev->c_str(), &end, 0);
|
||||
if(!end || *end != '\0')
|
||||
ERR("Invalid log level value: %s\n", loglev->c_str());
|
||||
else if(l < LogLevel_None || l > LogLevel_Trace)
|
||||
ERR("Log level out of range: %s\n", loglev->c_str());
|
||||
else
|
||||
LogLevel = static_cast<enum LogLevel>(l);
|
||||
}
|
||||
TRACE("Initializing router v0.1-%s %s\n", ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
|
||||
LoadDriverList();
|
||||
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
DriverList.clear();
|
||||
|
||||
if(LogFile && LogFile != stderr)
|
||||
fclose(LogFile);
|
||||
LogFile = nullptr;
|
||||
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void AddModule(HMODULE module, const WCHAR *name)
|
||||
{
|
||||
for(auto &drv : DriverList)
|
||||
{
|
||||
if(drv->Module == module)
|
||||
{
|
||||
TRACE("Skipping already-loaded module %p\n", decltype(std::declval<void*>()){module});
|
||||
FreeLibrary(module);
|
||||
return;
|
||||
}
|
||||
if(drv->Name == name)
|
||||
{
|
||||
TRACE("Skipping similarly-named module %ls\n", name);
|
||||
FreeLibrary(module);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DriverList.emplace_back(std::make_unique<DriverIface>(name, module));
|
||||
DriverIface &newdrv = *DriverList.back();
|
||||
|
||||
/* Load required functions. */
|
||||
int err = 0;
|
||||
#define LOAD_PROC(x) do { \
|
||||
newdrv.x = reinterpret_cast<decltype(newdrv.x)>(reinterpret_cast<void*>( \
|
||||
GetProcAddress(module, #x))); \
|
||||
if(!newdrv.x) \
|
||||
{ \
|
||||
ERR("Failed to find entry point for %s in %ls\n", #x, name); \
|
||||
err = 1; \
|
||||
} \
|
||||
} while(0)
|
||||
LOAD_PROC(alcCreateContext);
|
||||
LOAD_PROC(alcMakeContextCurrent);
|
||||
LOAD_PROC(alcProcessContext);
|
||||
LOAD_PROC(alcSuspendContext);
|
||||
LOAD_PROC(alcDestroyContext);
|
||||
LOAD_PROC(alcGetCurrentContext);
|
||||
LOAD_PROC(alcGetContextsDevice);
|
||||
LOAD_PROC(alcOpenDevice);
|
||||
LOAD_PROC(alcCloseDevice);
|
||||
LOAD_PROC(alcGetError);
|
||||
LOAD_PROC(alcIsExtensionPresent);
|
||||
LOAD_PROC(alcGetProcAddress);
|
||||
LOAD_PROC(alcGetEnumValue);
|
||||
LOAD_PROC(alcGetString);
|
||||
LOAD_PROC(alcGetIntegerv);
|
||||
LOAD_PROC(alcCaptureOpenDevice);
|
||||
LOAD_PROC(alcCaptureCloseDevice);
|
||||
LOAD_PROC(alcCaptureStart);
|
||||
LOAD_PROC(alcCaptureStop);
|
||||
LOAD_PROC(alcCaptureSamples);
|
||||
|
||||
LOAD_PROC(alEnable);
|
||||
LOAD_PROC(alDisable);
|
||||
LOAD_PROC(alIsEnabled);
|
||||
LOAD_PROC(alGetString);
|
||||
LOAD_PROC(alGetBooleanv);
|
||||
LOAD_PROC(alGetIntegerv);
|
||||
LOAD_PROC(alGetFloatv);
|
||||
LOAD_PROC(alGetDoublev);
|
||||
LOAD_PROC(alGetBoolean);
|
||||
LOAD_PROC(alGetInteger);
|
||||
LOAD_PROC(alGetFloat);
|
||||
LOAD_PROC(alGetDouble);
|
||||
LOAD_PROC(alGetError);
|
||||
LOAD_PROC(alIsExtensionPresent);
|
||||
LOAD_PROC(alGetProcAddress);
|
||||
LOAD_PROC(alGetEnumValue);
|
||||
LOAD_PROC(alListenerf);
|
||||
LOAD_PROC(alListener3f);
|
||||
LOAD_PROC(alListenerfv);
|
||||
LOAD_PROC(alListeneri);
|
||||
LOAD_PROC(alListener3i);
|
||||
LOAD_PROC(alListeneriv);
|
||||
LOAD_PROC(alGetListenerf);
|
||||
LOAD_PROC(alGetListener3f);
|
||||
LOAD_PROC(alGetListenerfv);
|
||||
LOAD_PROC(alGetListeneri);
|
||||
LOAD_PROC(alGetListener3i);
|
||||
LOAD_PROC(alGetListeneriv);
|
||||
LOAD_PROC(alGenSources);
|
||||
LOAD_PROC(alDeleteSources);
|
||||
LOAD_PROC(alIsSource);
|
||||
LOAD_PROC(alSourcef);
|
||||
LOAD_PROC(alSource3f);
|
||||
LOAD_PROC(alSourcefv);
|
||||
LOAD_PROC(alSourcei);
|
||||
LOAD_PROC(alSource3i);
|
||||
LOAD_PROC(alSourceiv);
|
||||
LOAD_PROC(alGetSourcef);
|
||||
LOAD_PROC(alGetSource3f);
|
||||
LOAD_PROC(alGetSourcefv);
|
||||
LOAD_PROC(alGetSourcei);
|
||||
LOAD_PROC(alGetSource3i);
|
||||
LOAD_PROC(alGetSourceiv);
|
||||
LOAD_PROC(alSourcePlayv);
|
||||
LOAD_PROC(alSourceStopv);
|
||||
LOAD_PROC(alSourceRewindv);
|
||||
LOAD_PROC(alSourcePausev);
|
||||
LOAD_PROC(alSourcePlay);
|
||||
LOAD_PROC(alSourceStop);
|
||||
LOAD_PROC(alSourceRewind);
|
||||
LOAD_PROC(alSourcePause);
|
||||
LOAD_PROC(alSourceQueueBuffers);
|
||||
LOAD_PROC(alSourceUnqueueBuffers);
|
||||
LOAD_PROC(alGenBuffers);
|
||||
LOAD_PROC(alDeleteBuffers);
|
||||
LOAD_PROC(alIsBuffer);
|
||||
LOAD_PROC(alBufferData);
|
||||
LOAD_PROC(alDopplerFactor);
|
||||
LOAD_PROC(alDopplerVelocity);
|
||||
LOAD_PROC(alSpeedOfSound);
|
||||
LOAD_PROC(alDistanceModel);
|
||||
if(!err)
|
||||
{
|
||||
ALCint alc_ver[2] = { 0, 0 };
|
||||
newdrv.alcGetIntegerv(nullptr, ALC_MAJOR_VERSION, 1, &alc_ver[0]);
|
||||
newdrv.alcGetIntegerv(nullptr, ALC_MINOR_VERSION, 1, &alc_ver[1]);
|
||||
if(newdrv.alcGetError(nullptr) == ALC_NO_ERROR)
|
||||
newdrv.ALCVer = MAKE_ALC_VER(alc_ver[0], alc_ver[1]);
|
||||
else
|
||||
{
|
||||
WARN("Failed to query ALC version for %ls, assuming 1.0\n", name);
|
||||
newdrv.ALCVer = MAKE_ALC_VER(1, 0);
|
||||
}
|
||||
|
||||
#undef LOAD_PROC
|
||||
#define LOAD_PROC(x) do { \
|
||||
newdrv.x = reinterpret_cast<decltype(newdrv.x)>(reinterpret_cast<void*>( \
|
||||
GetProcAddress(module, #x))); \
|
||||
if(!newdrv.x) \
|
||||
{ \
|
||||
WARN("Failed to find optional entry point for %s in %ls\n", #x, name); \
|
||||
} \
|
||||
} while(0)
|
||||
LOAD_PROC(alBufferf);
|
||||
LOAD_PROC(alBuffer3f);
|
||||
LOAD_PROC(alBufferfv);
|
||||
LOAD_PROC(alBufferi);
|
||||
LOAD_PROC(alBuffer3i);
|
||||
LOAD_PROC(alBufferiv);
|
||||
LOAD_PROC(alGetBufferf);
|
||||
LOAD_PROC(alGetBuffer3f);
|
||||
LOAD_PROC(alGetBufferfv);
|
||||
LOAD_PROC(alGetBufferi);
|
||||
LOAD_PROC(alGetBuffer3i);
|
||||
LOAD_PROC(alGetBufferiv);
|
||||
|
||||
#undef LOAD_PROC
|
||||
#define LOAD_PROC(x) do { \
|
||||
newdrv.x = reinterpret_cast<decltype(newdrv.x)>( \
|
||||
newdrv.alcGetProcAddress(nullptr, #x)); \
|
||||
if(!newdrv.x) \
|
||||
{ \
|
||||
ERR("Failed to find entry point for %s in %ls\n", #x, name); \
|
||||
err = 1; \
|
||||
} \
|
||||
} while(0)
|
||||
if(newdrv.alcIsExtensionPresent(nullptr, "ALC_EXT_thread_local_context"))
|
||||
{
|
||||
LOAD_PROC(alcSetThreadContext);
|
||||
LOAD_PROC(alcGetThreadContext);
|
||||
}
|
||||
}
|
||||
|
||||
if(err)
|
||||
{
|
||||
DriverList.pop_back();
|
||||
return;
|
||||
}
|
||||
TRACE("Loaded module %p, %ls, ALC %d.%d\n", decltype(std::declval<void*>()){module}, name,
|
||||
newdrv.ALCVer>>8, newdrv.ALCVer&255);
|
||||
#undef LOAD_PROC
|
||||
}
|
||||
|
||||
static void SearchDrivers(WCHAR *path)
|
||||
{
|
||||
WIN32_FIND_DATAW fdata;
|
||||
|
||||
TRACE("Searching for drivers in %ls...\n", path);
|
||||
std::wstring srchPath = path;
|
||||
srchPath += L"\\*oal.dll";
|
||||
|
||||
HANDLE srchHdl = FindFirstFileW(srchPath.c_str(), &fdata);
|
||||
if(srchHdl != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
do {
|
||||
HMODULE mod;
|
||||
|
||||
srchPath = path;
|
||||
srchPath += L"\\";
|
||||
srchPath += fdata.cFileName;
|
||||
TRACE("Found %ls\n", srchPath.c_str());
|
||||
|
||||
mod = LoadLibraryW(srchPath.c_str());
|
||||
if(!mod)
|
||||
WARN("Could not load %ls\n", srchPath.c_str());
|
||||
else
|
||||
AddModule(mod, fdata.cFileName);
|
||||
} while(FindNextFileW(srchHdl, &fdata));
|
||||
FindClose(srchHdl);
|
||||
}
|
||||
}
|
||||
|
||||
static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
|
||||
{
|
||||
WCHAR *res = nullptr;
|
||||
while(str && *str != '\0')
|
||||
{
|
||||
if(*str == ch)
|
||||
res = str;
|
||||
++str;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int GetLoadedModuleDirectory(const WCHAR *name, WCHAR *moddir, DWORD length)
|
||||
{
|
||||
HMODULE module = nullptr;
|
||||
WCHAR *sep0, *sep1;
|
||||
|
||||
if(name)
|
||||
{
|
||||
module = GetModuleHandleW(name);
|
||||
if(!module) return 0;
|
||||
}
|
||||
|
||||
if(GetModuleFileNameW(module, moddir, length) == 0)
|
||||
return 0;
|
||||
|
||||
sep0 = strrchrW(moddir, '/');
|
||||
if(sep0) sep1 = strrchrW(sep0+1, '\\');
|
||||
else sep1 = strrchrW(moddir, '\\');
|
||||
|
||||
if(sep1) *sep1 = '\0';
|
||||
else if(sep0) *sep0 = '\0';
|
||||
else *moddir = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LoadDriverList(void)
|
||||
{
|
||||
WCHAR dll_path[MAX_PATH+1] = L"";
|
||||
WCHAR cwd_path[MAX_PATH+1] = L"";
|
||||
WCHAR proc_path[MAX_PATH+1] = L"";
|
||||
WCHAR sys_path[MAX_PATH+1] = L"";
|
||||
int len;
|
||||
|
||||
if(GetLoadedModuleDirectory(L"OpenAL32.dll", dll_path, MAX_PATH))
|
||||
TRACE("Got DLL path %ls\n", dll_path);
|
||||
|
||||
GetCurrentDirectoryW(MAX_PATH, cwd_path);
|
||||
len = lstrlenW(cwd_path);
|
||||
if(len > 0 && (cwd_path[len-1] == '\\' || cwd_path[len-1] == '/'))
|
||||
cwd_path[len-1] = '\0';
|
||||
TRACE("Got current working directory %ls\n", cwd_path);
|
||||
|
||||
if(GetLoadedModuleDirectory(nullptr, proc_path, MAX_PATH))
|
||||
TRACE("Got proc path %ls\n", proc_path);
|
||||
|
||||
GetSystemDirectoryW(sys_path, MAX_PATH);
|
||||
len = lstrlenW(sys_path);
|
||||
if(len > 0 && (sys_path[len-1] == '\\' || sys_path[len-1] == '/'))
|
||||
sys_path[len-1] = '\0';
|
||||
TRACE("Got system path %ls\n", sys_path);
|
||||
|
||||
/* Don't search the DLL's path if it is the same as the current working
|
||||
* directory, app's path, or system path (don't want to do duplicate
|
||||
* searches, or increase the priority of the app or system path).
|
||||
*/
|
||||
if(dll_path[0] &&
|
||||
(!cwd_path[0] || wcscmp(dll_path, cwd_path) != 0) &&
|
||||
(!proc_path[0] || wcscmp(dll_path, proc_path) != 0) &&
|
||||
(!sys_path[0] || wcscmp(dll_path, sys_path) != 0))
|
||||
SearchDrivers(dll_path);
|
||||
if(cwd_path[0] &&
|
||||
(!proc_path[0] || wcscmp(cwd_path, proc_path) != 0) &&
|
||||
(!sys_path[0] || wcscmp(cwd_path, sys_path) != 0))
|
||||
SearchDrivers(cwd_path);
|
||||
if(proc_path[0] && (!sys_path[0] || wcscmp(proc_path, sys_path) != 0))
|
||||
SearchDrivers(proc_path);
|
||||
if(sys_path[0])
|
||||
SearchDrivers(sys_path);
|
||||
}
|
||||
|
||||
|
||||
PtrIntMap::~PtrIntMap()
|
||||
{
|
||||
std::lock_guard<std::mutex> maplock{mLock};
|
||||
al_free(mKeys);
|
||||
mKeys = nullptr;
|
||||
mValues = nullptr;
|
||||
mSize = 0;
|
||||
mCapacity = 0;
|
||||
}
|
||||
|
||||
ALenum PtrIntMap::insert(void *key, int value)
|
||||
{
|
||||
std::lock_guard<std::mutex> maplock{mLock};
|
||||
auto iter = std::lower_bound(mKeys, mKeys+mSize, key);
|
||||
auto pos = static_cast<ALsizei>(std::distance(mKeys, iter));
|
||||
|
||||
if(pos == mSize || mKeys[pos] != key)
|
||||
{
|
||||
if(mSize == mCapacity)
|
||||
{
|
||||
void **newkeys{nullptr};
|
||||
ALsizei newcap{mCapacity ? (mCapacity<<1) : 4};
|
||||
if(newcap > mCapacity)
|
||||
newkeys = static_cast<void**>(
|
||||
al_calloc(16, (sizeof(mKeys[0])+sizeof(mValues[0]))*newcap)
|
||||
);
|
||||
if(!newkeys)
|
||||
return AL_OUT_OF_MEMORY;
|
||||
auto newvalues = reinterpret_cast<int*>(&newkeys[newcap]);
|
||||
|
||||
if(mKeys)
|
||||
{
|
||||
std::copy_n(mKeys, mSize, newkeys);
|
||||
std::copy_n(mValues, mSize, newvalues);
|
||||
}
|
||||
al_free(mKeys);
|
||||
mKeys = newkeys;
|
||||
mValues = newvalues;
|
||||
mCapacity = newcap;
|
||||
}
|
||||
|
||||
if(pos < mSize)
|
||||
{
|
||||
std::copy_backward(mKeys+pos, mKeys+mSize, mKeys+mSize+1);
|
||||
std::copy_backward(mValues+pos, mValues+mSize, mValues+mSize+1);
|
||||
}
|
||||
mSize++;
|
||||
}
|
||||
mKeys[pos] = key;
|
||||
mValues[pos] = value;
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
int PtrIntMap::removeByKey(void *key)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
std::lock_guard<std::mutex> maplock{mLock};
|
||||
auto iter = std::lower_bound(mKeys, mKeys+mSize, key);
|
||||
auto pos = static_cast<ALsizei>(std::distance(mKeys, iter));
|
||||
if(pos < mSize && mKeys[pos] == key)
|
||||
{
|
||||
ret = mValues[pos];
|
||||
if(pos+1 < mSize)
|
||||
{
|
||||
std::copy(mKeys+pos+1, mKeys+mSize, mKeys+pos);
|
||||
std::copy(mValues+pos+1, mValues+mSize, mValues+pos);
|
||||
}
|
||||
mSize--;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int PtrIntMap::lookupByKey(void *key)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
std::lock_guard<std::mutex> maplock{mLock};
|
||||
auto iter = std::lower_bound(mKeys, mKeys+mSize, key);
|
||||
auto pos = static_cast<ALsizei>(std::distance(mKeys, iter));
|
||||
if(pos < mSize && mKeys[pos] == key)
|
||||
ret = mValues[pos];
|
||||
|
||||
return ret;
|
||||
}
|
243
router/router.h
243
router/router.h
@ -1,243 +0,0 @@
|
||||
#ifndef ROUTER_ROUTER_H
|
||||
#define ROUTER_ROUTER_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "AL/alc.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
|
||||
#define MAKE_ALC_VER(major, minor) (((major)<<8) | (minor))
|
||||
|
||||
struct DriverIface {
|
||||
std::wstring Name;
|
||||
HMODULE Module{nullptr};
|
||||
int ALCVer{0};
|
||||
std::once_flag InitOnceCtx{};
|
||||
|
||||
LPALCCREATECONTEXT alcCreateContext{nullptr};
|
||||
LPALCMAKECONTEXTCURRENT alcMakeContextCurrent{nullptr};
|
||||
LPALCPROCESSCONTEXT alcProcessContext{nullptr};
|
||||
LPALCSUSPENDCONTEXT alcSuspendContext{nullptr};
|
||||
LPALCDESTROYCONTEXT alcDestroyContext{nullptr};
|
||||
LPALCGETCURRENTCONTEXT alcGetCurrentContext{nullptr};
|
||||
LPALCGETCONTEXTSDEVICE alcGetContextsDevice{nullptr};
|
||||
LPALCOPENDEVICE alcOpenDevice{nullptr};
|
||||
LPALCCLOSEDEVICE alcCloseDevice{nullptr};
|
||||
LPALCGETERROR alcGetError{nullptr};
|
||||
LPALCISEXTENSIONPRESENT alcIsExtensionPresent{nullptr};
|
||||
LPALCGETPROCADDRESS alcGetProcAddress{nullptr};
|
||||
LPALCGETENUMVALUE alcGetEnumValue{nullptr};
|
||||
LPALCGETSTRING alcGetString{nullptr};
|
||||
LPALCGETINTEGERV alcGetIntegerv{nullptr};
|
||||
LPALCCAPTUREOPENDEVICE alcCaptureOpenDevice{nullptr};
|
||||
LPALCCAPTURECLOSEDEVICE alcCaptureCloseDevice{nullptr};
|
||||
LPALCCAPTURESTART alcCaptureStart{nullptr};
|
||||
LPALCCAPTURESTOP alcCaptureStop{nullptr};
|
||||
LPALCCAPTURESAMPLES alcCaptureSamples{nullptr};
|
||||
|
||||
PFNALCSETTHREADCONTEXTPROC alcSetThreadContext{nullptr};
|
||||
PFNALCGETTHREADCONTEXTPROC alcGetThreadContext{nullptr};
|
||||
|
||||
LPALENABLE alEnable{nullptr};
|
||||
LPALDISABLE alDisable{nullptr};
|
||||
LPALISENABLED alIsEnabled{nullptr};
|
||||
LPALGETSTRING alGetString{nullptr};
|
||||
LPALGETBOOLEANV alGetBooleanv{nullptr};
|
||||
LPALGETINTEGERV alGetIntegerv{nullptr};
|
||||
LPALGETFLOATV alGetFloatv{nullptr};
|
||||
LPALGETDOUBLEV alGetDoublev{nullptr};
|
||||
LPALGETBOOLEAN alGetBoolean{nullptr};
|
||||
LPALGETINTEGER alGetInteger{nullptr};
|
||||
LPALGETFLOAT alGetFloat{nullptr};
|
||||
LPALGETDOUBLE alGetDouble{nullptr};
|
||||
LPALGETERROR alGetError{nullptr};
|
||||
LPALISEXTENSIONPRESENT alIsExtensionPresent{nullptr};
|
||||
LPALGETPROCADDRESS alGetProcAddress{nullptr};
|
||||
LPALGETENUMVALUE alGetEnumValue{nullptr};
|
||||
LPALLISTENERF alListenerf{nullptr};
|
||||
LPALLISTENER3F alListener3f{nullptr};
|
||||
LPALLISTENERFV alListenerfv{nullptr};
|
||||
LPALLISTENERI alListeneri{nullptr};
|
||||
LPALLISTENER3I alListener3i{nullptr};
|
||||
LPALLISTENERIV alListeneriv{nullptr};
|
||||
LPALGETLISTENERF alGetListenerf{nullptr};
|
||||
LPALGETLISTENER3F alGetListener3f{nullptr};
|
||||
LPALGETLISTENERFV alGetListenerfv{nullptr};
|
||||
LPALGETLISTENERI alGetListeneri{nullptr};
|
||||
LPALGETLISTENER3I alGetListener3i{nullptr};
|
||||
LPALGETLISTENERIV alGetListeneriv{nullptr};
|
||||
LPALGENSOURCES alGenSources{nullptr};
|
||||
LPALDELETESOURCES alDeleteSources{nullptr};
|
||||
LPALISSOURCE alIsSource{nullptr};
|
||||
LPALSOURCEF alSourcef{nullptr};
|
||||
LPALSOURCE3F alSource3f{nullptr};
|
||||
LPALSOURCEFV alSourcefv{nullptr};
|
||||
LPALSOURCEI alSourcei{nullptr};
|
||||
LPALSOURCE3I alSource3i{nullptr};
|
||||
LPALSOURCEIV alSourceiv{nullptr};
|
||||
LPALGETSOURCEF alGetSourcef{nullptr};
|
||||
LPALGETSOURCE3F alGetSource3f{nullptr};
|
||||
LPALGETSOURCEFV alGetSourcefv{nullptr};
|
||||
LPALGETSOURCEI alGetSourcei{nullptr};
|
||||
LPALGETSOURCE3I alGetSource3i{nullptr};
|
||||
LPALGETSOURCEIV alGetSourceiv{nullptr};
|
||||
LPALSOURCEPLAYV alSourcePlayv{nullptr};
|
||||
LPALSOURCESTOPV alSourceStopv{nullptr};
|
||||
LPALSOURCEREWINDV alSourceRewindv{nullptr};
|
||||
LPALSOURCEPAUSEV alSourcePausev{nullptr};
|
||||
LPALSOURCEPLAY alSourcePlay{nullptr};
|
||||
LPALSOURCESTOP alSourceStop{nullptr};
|
||||
LPALSOURCEREWIND alSourceRewind{nullptr};
|
||||
LPALSOURCEPAUSE alSourcePause{nullptr};
|
||||
LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers{nullptr};
|
||||
LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers{nullptr};
|
||||
LPALGENBUFFERS alGenBuffers{nullptr};
|
||||
LPALDELETEBUFFERS alDeleteBuffers{nullptr};
|
||||
LPALISBUFFER alIsBuffer{nullptr};
|
||||
LPALBUFFERF alBufferf{nullptr};
|
||||
LPALBUFFER3F alBuffer3f{nullptr};
|
||||
LPALBUFFERFV alBufferfv{nullptr};
|
||||
LPALBUFFERI alBufferi{nullptr};
|
||||
LPALBUFFER3I alBuffer3i{nullptr};
|
||||
LPALBUFFERIV alBufferiv{nullptr};
|
||||
LPALGETBUFFERF alGetBufferf{nullptr};
|
||||
LPALGETBUFFER3F alGetBuffer3f{nullptr};
|
||||
LPALGETBUFFERFV alGetBufferfv{nullptr};
|
||||
LPALGETBUFFERI alGetBufferi{nullptr};
|
||||
LPALGETBUFFER3I alGetBuffer3i{nullptr};
|
||||
LPALGETBUFFERIV alGetBufferiv{nullptr};
|
||||
LPALBUFFERDATA alBufferData{nullptr};
|
||||
LPALDOPPLERFACTOR alDopplerFactor{nullptr};
|
||||
LPALDOPPLERVELOCITY alDopplerVelocity{nullptr};
|
||||
LPALSPEEDOFSOUND alSpeedOfSound{nullptr};
|
||||
LPALDISTANCEMODEL alDistanceModel{nullptr};
|
||||
|
||||
/* Functions to load after first context creation. */
|
||||
LPALGENFILTERS alGenFilters{nullptr};
|
||||
LPALDELETEFILTERS alDeleteFilters{nullptr};
|
||||
LPALISFILTER alIsFilter{nullptr};
|
||||
LPALFILTERF alFilterf{nullptr};
|
||||
LPALFILTERFV alFilterfv{nullptr};
|
||||
LPALFILTERI alFilteri{nullptr};
|
||||
LPALFILTERIV alFilteriv{nullptr};
|
||||
LPALGETFILTERF alGetFilterf{nullptr};
|
||||
LPALGETFILTERFV alGetFilterfv{nullptr};
|
||||
LPALGETFILTERI alGetFilteri{nullptr};
|
||||
LPALGETFILTERIV alGetFilteriv{nullptr};
|
||||
LPALGENEFFECTS alGenEffects{nullptr};
|
||||
LPALDELETEEFFECTS alDeleteEffects{nullptr};
|
||||
LPALISEFFECT alIsEffect{nullptr};
|
||||
LPALEFFECTF alEffectf{nullptr};
|
||||
LPALEFFECTFV alEffectfv{nullptr};
|
||||
LPALEFFECTI alEffecti{nullptr};
|
||||
LPALEFFECTIV alEffectiv{nullptr};
|
||||
LPALGETEFFECTF alGetEffectf{nullptr};
|
||||
LPALGETEFFECTFV alGetEffectfv{nullptr};
|
||||
LPALGETEFFECTI alGetEffecti{nullptr};
|
||||
LPALGETEFFECTIV alGetEffectiv{nullptr};
|
||||
LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots{nullptr};
|
||||
LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots{nullptr};
|
||||
LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot{nullptr};
|
||||
LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf{nullptr};
|
||||
LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv{nullptr};
|
||||
LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti{nullptr};
|
||||
LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv{nullptr};
|
||||
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf{nullptr};
|
||||
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv{nullptr};
|
||||
LPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti{nullptr};
|
||||
LPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv{nullptr};
|
||||
|
||||
template<typename T>
|
||||
DriverIface(T&& name, HMODULE mod)
|
||||
: Name(std::forward<T>(name)), Module(mod)
|
||||
{ }
|
||||
~DriverIface()
|
||||
{
|
||||
if(Module)
|
||||
FreeLibrary(Module);
|
||||
Module = nullptr;
|
||||
}
|
||||
};
|
||||
using DriverIfacePtr = std::unique_ptr<DriverIface>;
|
||||
|
||||
extern std::vector<DriverIfacePtr> DriverList;
|
||||
|
||||
extern thread_local DriverIface *ThreadCtxDriver;
|
||||
extern std::atomic<DriverIface*> CurrentCtxDriver;
|
||||
|
||||
/* HACK: MinGW generates bad code when accessing an extern thread_local object.
|
||||
* Add a wrapper function for it that only accesses it where it's defined.
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
DriverIface *GetThreadDriver() noexcept;
|
||||
void SetThreadDriver(DriverIface *driver) noexcept;
|
||||
#else
|
||||
inline DriverIface *GetThreadDriver() noexcept { return ThreadCtxDriver; }
|
||||
inline void SetThreadDriver(DriverIface *driver) noexcept { ThreadCtxDriver = driver; }
|
||||
#endif
|
||||
|
||||
|
||||
class PtrIntMap {
|
||||
void **mKeys{nullptr};
|
||||
/* Shares memory with keys. */
|
||||
int *mValues{nullptr};
|
||||
|
||||
ALsizei mSize{0};
|
||||
ALsizei mCapacity{0};
|
||||
std::mutex mLock;
|
||||
|
||||
public:
|
||||
PtrIntMap() = default;
|
||||
~PtrIntMap();
|
||||
|
||||
ALenum insert(void *key, int value);
|
||||
int removeByKey(void *key);
|
||||
int lookupByKey(void *key);
|
||||
};
|
||||
|
||||
|
||||
enum LogLevel {
|
||||
LogLevel_None = 0,
|
||||
LogLevel_Error = 1,
|
||||
LogLevel_Warn = 2,
|
||||
LogLevel_Trace = 3,
|
||||
};
|
||||
extern enum LogLevel LogLevel;
|
||||
extern FILE *LogFile;
|
||||
|
||||
#define TRACE(...) do { \
|
||||
if(LogLevel >= LogLevel_Trace) \
|
||||
{ \
|
||||
fprintf(LogFile, "AL Router (II): " __VA_ARGS__); \
|
||||
fflush(LogFile); \
|
||||
} \
|
||||
} while(0)
|
||||
#define WARN(...) do { \
|
||||
if(LogLevel >= LogLevel_Warn) \
|
||||
{ \
|
||||
fprintf(LogFile, "AL Router (WW): " __VA_ARGS__); \
|
||||
fflush(LogFile); \
|
||||
} \
|
||||
} while(0)
|
||||
#define ERR(...) do { \
|
||||
if(LogLevel >= LogLevel_Error) \
|
||||
{ \
|
||||
fprintf(LogFile, "AL Router (EE): " __VA_ARGS__); \
|
||||
fflush(LogFile); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#endif /* ROUTER_ROUTER_H */
|
3958
utils/CIAIR.def
3958
utils/CIAIR.def
File diff suppressed because it is too large
Load Diff
@ -1,425 +0,0 @@
|
||||
# This is a makemhr HRIR definition file. It is used to define the layout and
|
||||
# source data to be processed into an OpenAL Soft compatible HRTF.
|
||||
#
|
||||
# This definition is used to transform the left and right ear HRIRs of any
|
||||
# raw data set from the IRCAM/AKG Listen HRTF database.
|
||||
#
|
||||
# The data sets are available free of charge from:
|
||||
#
|
||||
# http://recherche.ircam.fr/equipes/salles/listen/index.html
|
||||
#
|
||||
# Contact for the Listen HRTF Database:
|
||||
#
|
||||
# Olivier Warusfel <olivier.warusfel@ircam.fr>,
|
||||
# Room Acoustics Team, IRCAM
|
||||
# 1, place Igor Stravinsky
|
||||
# 75004 PARIS, France
|
||||
|
||||
rate = 44100
|
||||
|
||||
# The IRCAM sets are stereo because they provide both ear HRIRs.
|
||||
type = stereo
|
||||
|
||||
# The raw sets have up to 8192 samples, but 2048 seems large enough.
|
||||
points = 2048
|
||||
|
||||
# No head radius was provided. Just use the average radius of 9 cm.
|
||||
radius = 0.09
|
||||
|
||||
# The IRCAM sets are single-field (like most others) with a distance between
|
||||
# the source and the listener of 1.95 meters.
|
||||
distance = 1.95
|
||||
|
||||
# This set isn't as dense as the MIT set.
|
||||
azimuths = 1, 6, 12, 24, 24, 24, 24, 24, 24, 24, 12, 6, 1
|
||||
|
||||
# The IRCAM source azimuth is counter-clockwise, so it needs to be flipped.
|
||||
# Left and right ear HRIRs (from the respective WAVE channels) are used to
|
||||
# create a stereo HRTF.
|
||||
|
||||
# Replace all occurrences of IRC_#### for the desired subject (1005 was used
|
||||
# in this demonstration).
|
||||
[ 3, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P315.wav" right
|
||||
[ 3, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P315.wav" right
|
||||
[ 3, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P315.wav" right
|
||||
[ 3, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P315.wav" right
|
||||
[ 3, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P315.wav" right
|
||||
[ 3, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P315.wav" right
|
||||
[ 3, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P315.wav" right
|
||||
[ 3, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P315.wav" right
|
||||
[ 3, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P315.wav" right
|
||||
[ 3, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P315.wav" right
|
||||
[ 3, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P315.wav" right
|
||||
[ 3, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P315.wav" right
|
||||
[ 3, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P315.wav" right
|
||||
[ 3, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P315.wav" right
|
||||
[ 3, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P315.wav" right
|
||||
[ 3, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P315.wav" right
|
||||
[ 3, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P315.wav" right
|
||||
[ 3, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P315.wav" right
|
||||
[ 3, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P315.wav" right
|
||||
[ 3, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P315.wav" right
|
||||
[ 3, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P315.wav" right
|
||||
[ 3, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P315.wav" right
|
||||
[ 3, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P315.wav" right
|
||||
[ 3, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P315.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P315.wav" right
|
||||
|
||||
[ 4, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P330.wav" right
|
||||
[ 4, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P330.wav" right
|
||||
[ 4, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P330.wav" right
|
||||
[ 4, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P330.wav" right
|
||||
[ 4, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P330.wav" right
|
||||
[ 4, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P330.wav" right
|
||||
[ 4, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P330.wav" right
|
||||
[ 4, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P330.wav" right
|
||||
[ 4, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P330.wav" right
|
||||
[ 4, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P330.wav" right
|
||||
[ 4, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P330.wav" right
|
||||
[ 4, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P330.wav" right
|
||||
[ 4, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P330.wav" right
|
||||
[ 4, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P330.wav" right
|
||||
[ 4, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P330.wav" right
|
||||
[ 4, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P330.wav" right
|
||||
[ 4, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P330.wav" right
|
||||
[ 4, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P330.wav" right
|
||||
[ 4, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P330.wav" right
|
||||
[ 4, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P330.wav" right
|
||||
[ 4, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P330.wav" right
|
||||
[ 4, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P330.wav" right
|
||||
[ 4, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P330.wav" right
|
||||
[ 4, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P330.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P330.wav" right
|
||||
|
||||
[ 5, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P345.wav" right
|
||||
[ 5, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P345.wav" right
|
||||
[ 5, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P345.wav" right
|
||||
[ 5, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P345.wav" right
|
||||
[ 5, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P345.wav" right
|
||||
[ 5, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P345.wav" right
|
||||
[ 5, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P345.wav" right
|
||||
[ 5, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P345.wav" right
|
||||
[ 5, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P345.wav" right
|
||||
[ 5, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P345.wav" right
|
||||
[ 5, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P345.wav" right
|
||||
[ 5, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P345.wav" right
|
||||
[ 5, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P345.wav" right
|
||||
[ 5, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P345.wav" right
|
||||
[ 5, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P345.wav" right
|
||||
[ 5, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P345.wav" right
|
||||
[ 5, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P345.wav" right
|
||||
[ 5, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P345.wav" right
|
||||
[ 5, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P345.wav" right
|
||||
[ 5, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P345.wav" right
|
||||
[ 5, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P345.wav" right
|
||||
[ 5, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P345.wav" right
|
||||
[ 5, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P345.wav" right
|
||||
[ 5, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P345.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P345.wav" right
|
||||
|
||||
[ 6, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P000.wav" right
|
||||
[ 6, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P000.wav" right
|
||||
[ 6, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P000.wav" right
|
||||
[ 6, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P000.wav" right
|
||||
[ 6, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P000.wav" right
|
||||
[ 6, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P000.wav" right
|
||||
[ 6, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P000.wav" right
|
||||
[ 6, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P000.wav" right
|
||||
[ 6, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P000.wav" right
|
||||
[ 6, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P000.wav" right
|
||||
[ 6, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P000.wav" right
|
||||
[ 6, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P000.wav" right
|
||||
[ 6, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P000.wav" right
|
||||
[ 6, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P000.wav" right
|
||||
[ 6, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P000.wav" right
|
||||
[ 6, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P000.wav" right
|
||||
[ 6, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P000.wav" right
|
||||
[ 6, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P000.wav" right
|
||||
[ 6, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P000.wav" right
|
||||
[ 6, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P000.wav" right
|
||||
[ 6, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P000.wav" right
|
||||
[ 6, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P000.wav" right
|
||||
[ 6, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P000.wav" right
|
||||
[ 6, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P000.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P000.wav" right
|
||||
|
||||
[ 7, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P015.wav" right
|
||||
[ 7, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P015.wav" right
|
||||
[ 7, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P015.wav" right
|
||||
[ 7, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P015.wav" right
|
||||
[ 7, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P015.wav" right
|
||||
[ 7, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P015.wav" right
|
||||
[ 7, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P015.wav" right
|
||||
[ 7, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P015.wav" right
|
||||
[ 7, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P015.wav" right
|
||||
[ 7, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P015.wav" right
|
||||
[ 7, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P015.wav" right
|
||||
[ 7, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P015.wav" right
|
||||
[ 7, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P015.wav" right
|
||||
[ 7, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P015.wav" right
|
||||
[ 7, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P015.wav" right
|
||||
[ 7, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P015.wav" right
|
||||
[ 7, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P015.wav" right
|
||||
[ 7, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P015.wav" right
|
||||
[ 7, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P015.wav" right
|
||||
[ 7, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P015.wav" right
|
||||
[ 7, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P015.wav" right
|
||||
[ 7, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P015.wav" right
|
||||
[ 7, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P015.wav" right
|
||||
[ 7, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P015.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P015.wav" right
|
||||
|
||||
[ 8, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P030.wav" right
|
||||
[ 8, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P030.wav" right
|
||||
[ 8, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P030.wav" right
|
||||
[ 8, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P030.wav" right
|
||||
[ 8, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P030.wav" right
|
||||
[ 8, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P030.wav" right
|
||||
[ 8, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P030.wav" right
|
||||
[ 8, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P030.wav" right
|
||||
[ 8, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P030.wav" right
|
||||
[ 8, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P030.wav" right
|
||||
[ 8, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P030.wav" right
|
||||
[ 8, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P030.wav" right
|
||||
[ 8, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P030.wav" right
|
||||
[ 8, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P030.wav" right
|
||||
[ 8, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P030.wav" right
|
||||
[ 8, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P030.wav" right
|
||||
[ 8, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P030.wav" right
|
||||
[ 8, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P030.wav" right
|
||||
[ 8, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P030.wav" right
|
||||
[ 8, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P030.wav" right
|
||||
[ 8, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P030.wav" right
|
||||
[ 8, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P030.wav" right
|
||||
[ 8, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P030.wav" right
|
||||
[ 8, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P030.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P030.wav" right
|
||||
|
||||
[ 9, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P045.wav" right
|
||||
[ 9, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T345_P045.wav" right
|
||||
[ 9, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P045.wav" right
|
||||
[ 9, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T315_P045.wav" right
|
||||
[ 9, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P045.wav" right
|
||||
[ 9, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T285_P045.wav" right
|
||||
[ 9, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P045.wav" right
|
||||
[ 9, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T255_P045.wav" right
|
||||
[ 9, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P045.wav" right
|
||||
[ 9, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T225_P045.wav" right
|
||||
[ 9, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P045.wav" right
|
||||
[ 9, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T195_P045.wav" right
|
||||
[ 9, 12 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P045.wav" right
|
||||
[ 9, 13 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T165_P045.wav" right
|
||||
[ 9, 14 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P045.wav" right
|
||||
[ 9, 15 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T135_P045.wav" right
|
||||
[ 9, 16 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P045.wav" right
|
||||
[ 9, 17 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T105_P045.wav" right
|
||||
[ 9, 18 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P045.wav" right
|
||||
[ 9, 19 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T075_P045.wav" right
|
||||
[ 9, 20 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P045.wav" right
|
||||
[ 9, 21 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T045_P045.wav" right
|
||||
[ 9, 22 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P045.wav" right
|
||||
[ 9, 23 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P045.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T015_P045.wav" right
|
||||
|
||||
[ 10, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P060.wav" right
|
||||
[ 10, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T330_P060.wav" right
|
||||
[ 10, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P060.wav" right
|
||||
[ 10, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T270_P060.wav" right
|
||||
[ 10, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P060.wav" right
|
||||
[ 10, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T210_P060.wav" right
|
||||
[ 10, 6 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P060.wav" right
|
||||
[ 10, 7 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T150_P060.wav" right
|
||||
[ 10, 8 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P060.wav" right
|
||||
[ 10, 9 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T090_P060.wav" right
|
||||
[ 10, 10 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P060.wav" right
|
||||
[ 10, 11 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P060.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T030_P060.wav" right
|
||||
|
||||
[ 11, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P075.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P075.wav" right
|
||||
[ 11, 1 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P075.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T300_P075.wav" right
|
||||
[ 11, 2 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P075.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T240_P075.wav" right
|
||||
[ 11, 3 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P075.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T180_P075.wav" right
|
||||
[ 11, 4 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P075.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T120_P075.wav" right
|
||||
[ 11, 5 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P075.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T060_P075.wav" right
|
||||
|
||||
[ 12, 0 ] = wave (0) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P090.wav" left
|
||||
+ wave (1) : "./IRC/RAW/WAV/IRC_1005_R/IRC_1005_R_R0195_T000_P090.wav" right
|
||||
|
@ -1,844 +0,0 @@
|
||||
# This is a makemhr HRIR definition file. It is used to define the layout and
|
||||
# source data to be processed into an OpenAL Soft compatible HRTF.
|
||||
#
|
||||
# This definition is used to transform the left ear HRIRs from the full set
|
||||
# of KEMAR HRIRs provided by Bill Gardner <billg@media.mit.edu> and Keith
|
||||
# Martin <kdm@media.mit.edu> of MIT Media Laboratory.
|
||||
#
|
||||
# The data (full.zip) is available from:
|
||||
#
|
||||
# http://sound.media.mit.edu/resources/KEMAR.html
|
||||
#
|
||||
# It is copyrighted 1994 by MIT Media Laboratory, and provided free of charge
|
||||
# with no restrictions on use so long as the authors (above) are cited.
|
||||
#
|
||||
# This definition is used to generate the default HRTF table used by OpenAL
|
||||
# Soft.
|
||||
|
||||
# The following are the data set metrics. They must always be specified at
|
||||
# the start of a definition file, but their order is not important.
|
||||
|
||||
# Sampling rate of the HRIR data (in hertz).
|
||||
rate = 44100
|
||||
|
||||
# The channel type of incoming HRIR data (mono or stereo). Mono channel
|
||||
# inputs will result in mirroring to provide the right ear HRIRs. If not
|
||||
# specified, this defaults to mono.
|
||||
type = mono
|
||||
|
||||
# The number of points to use from the HRIR data. This should be a
|
||||
# sufficiently large value (to encompass the entire impulse response). It
|
||||
# cannot be smaller than the truncation size (default is 32) specified on the
|
||||
# command line.
|
||||
points = 512
|
||||
|
||||
# The radius of the listener's head (measured ear-to-ear in meters). The
|
||||
# makemhr utility uses this value to rescale measured propagation delays when
|
||||
# a custom head radius is specified on the command line. It is also used as
|
||||
# the default radius when the spherical model is used to calculate an
|
||||
# approximate set of delays. This should match the data set as close as
|
||||
# possible for accurate rescaling when using the measured delays (the
|
||||
# default). At the moment, radius rescaling does not adjust HRIR coupling.
|
||||
radius = 0.09
|
||||
|
||||
# A list of the distances between the source and the listener (in meters) for
|
||||
# each field. These must start at or above the head radius and proceed in
|
||||
# ascending order. Since the MIT set is single-field, there is only one
|
||||
# distance.
|
||||
distance = 1.4
|
||||
|
||||
# A list of the number of azimuths measured for each elevation per field.
|
||||
# Elevations are separated by commas (,) while fields are separated by
|
||||
# semicolons (;). There must be at least 5 elevations covering 180 degrees
|
||||
# degrees of elevation for the data set to be viable. The poles (first and
|
||||
# last elevation) must be singular (an azimuth count of 1).
|
||||
azimuths = 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1
|
||||
|
||||
# Following the metrics is the list of source HRIRs for each field,
|
||||
# elevation, and azimuth triplet. They don't have to be specified in order,
|
||||
# but the final composition must not be sparse. They can however begin above
|
||||
# a number of elevations (as typical for HRIR measurements).
|
||||
#
|
||||
# The field index is used to determine the distance coordinate (for mult-
|
||||
# field HRTFs) while the elevation and azimuth indices are used to determine
|
||||
# the resulting polar coordinates following OpenAL Soft's convention (-90
|
||||
# degree elevation increasing counter-clockwise from the bottom; 0 degree
|
||||
# azimuth increasing clockwise from the front).
|
||||
#
|
||||
# More than one HRIR can be used per source. This allows the composition of
|
||||
# averaged magnitude responses or the specification of stereo HRTFs. Target
|
||||
# ears must (and can only be) specified for each source when the type metric
|
||||
# is set to 'stereo'.
|
||||
#
|
||||
# Source specification is of the form (~BNF):
|
||||
#
|
||||
# source = ( sf_index | mf_index ) source_ref [ '+' source_ref ]*
|
||||
#
|
||||
# sf_index = '[' ev_index ',' az_index ']' '='
|
||||
# mf_index = '[' fd_index ',' ev_index ',' az_index ']' '='
|
||||
# source_ref = mono_ref | stereo_ref
|
||||
#
|
||||
# fd_index = unsigned_integer
|
||||
# ev_index = unsigned_integer
|
||||
# az_index = unsigned_integer
|
||||
# mono_ref = ref_spec ':' filename
|
||||
# stereo_ref = ref_spec ':' filename ear
|
||||
#
|
||||
# ref_spec = ( wave_fmt '(' wave_parms ')' [ '@' start_sample ] ) |
|
||||
# ( bin_fmt '(' bini_parms ')' [ '@' start_byte ] ) |
|
||||
# ( bin_fmt '(' binf_parms ')' [ '@' start_byte ] ) |
|
||||
# ( ascii_fmt '(' asci_parms ')' [ '@' start_element ] ) |
|
||||
# ( ascii_fmt '(' ascf_parms ')' [ '@' start_element ] )
|
||||
# filename = double_quoted_string
|
||||
# ear = 'left' | 'right'
|
||||
#
|
||||
# wave_fmt = 'wave'
|
||||
# wave_parms = channel
|
||||
# bin_fmt = 'bin_le' | 'bin_be'
|
||||
# bini_parms = 'int' ',' byte_size [ ',' bin_sig_bits ] [ ';' skip_bytes ]
|
||||
# binf_parms = 'fp' ',' byte_size [ ';' skip_bytes ]
|
||||
# ascii_fmt = 'ascii'
|
||||
# asci_parms = 'int' ',' sig_bits [ ';' skip_elements ]
|
||||
# ascf_parms = 'fp' [ ';' skip_elements ]
|
||||
# start_sample = unsigned_integer
|
||||
# start_byte = unsigned_integer
|
||||
# start_element = unsigned_integer
|
||||
#
|
||||
# channel = unsigned_integer
|
||||
# byte_size = unsigned_integer
|
||||
# bin_sig_bits = signed_integer
|
||||
# skip_bytes = unsigned_integer
|
||||
# sig_bits = unsigned_integer
|
||||
# skip_elements = unsigned_integer
|
||||
#
|
||||
# For bin_sig_bits, positive values mean the significant bits start at the
|
||||
# MSB (padding toward the LSB) while negative values mean they start at the
|
||||
# LSB.
|
||||
|
||||
# Even though the MIT set is provided as stereo .wav files, each channel is
|
||||
# for a different sized KEMAR ear. Since it is not a stereo data set, no ear
|
||||
# is specified. The smaller KEMAR ear (in the left channel: 0) is used.
|
||||
[ 5, 0 ] = wave (0) : "./MITfull/elev-40/L-40e000a.wav"
|
||||
[ 5, 1 ] = wave (0) : "./MITfull/elev-40/L-40e006a.wav"
|
||||
[ 5, 2 ] = wave (0) : "./MITfull/elev-40/L-40e013a.wav"
|
||||
[ 5, 3 ] = wave (0) : "./MITfull/elev-40/L-40e019a.wav"
|
||||
[ 5, 4 ] = wave (0) : "./MITfull/elev-40/L-40e026a.wav"
|
||||
[ 5, 5 ] = wave (0) : "./MITfull/elev-40/L-40e032a.wav"
|
||||
[ 5, 6 ] = wave (0) : "./MITfull/elev-40/L-40e039a.wav"
|
||||
[ 5, 7 ] = wave (0) : "./MITfull/elev-40/L-40e045a.wav"
|
||||
[ 5, 8 ] = wave (0) : "./MITfull/elev-40/L-40e051a.wav"
|
||||
[ 5, 9 ] = wave (0) : "./MITfull/elev-40/L-40e058a.wav"
|
||||
[ 5, 10 ] = wave (0) : "./MITfull/elev-40/L-40e064a.wav"
|
||||
[ 5, 11 ] = wave (0) : "./MITfull/elev-40/L-40e071a.wav"
|
||||
[ 5, 12 ] = wave (0) : "./MITfull/elev-40/L-40e077a.wav"
|
||||
[ 5, 13 ] = wave (0) : "./MITfull/elev-40/L-40e084a.wav"
|
||||
[ 5, 14 ] = wave (0) : "./MITfull/elev-40/L-40e090a.wav"
|
||||
[ 5, 15 ] = wave (0) : "./MITfull/elev-40/L-40e096a.wav"
|
||||
[ 5, 16 ] = wave (0) : "./MITfull/elev-40/L-40e103a.wav"
|
||||
[ 5, 17 ] = wave (0) : "./MITfull/elev-40/L-40e109a.wav"
|
||||
[ 5, 18 ] = wave (0) : "./MITfull/elev-40/L-40e116a.wav"
|
||||
[ 5, 19 ] = wave (0) : "./MITfull/elev-40/L-40e122a.wav"
|
||||
[ 5, 20 ] = wave (0) : "./MITfull/elev-40/L-40e129a.wav"
|
||||
[ 5, 21 ] = wave (0) : "./MITfull/elev-40/L-40e135a.wav"
|
||||
[ 5, 22 ] = wave (0) : "./MITfull/elev-40/L-40e141a.wav"
|
||||
[ 5, 23 ] = wave (0) : "./MITfull/elev-40/L-40e148a.wav"
|
||||
[ 5, 24 ] = wave (0) : "./MITfull/elev-40/L-40e154a.wav"
|
||||
[ 5, 25 ] = wave (0) : "./MITfull/elev-40/L-40e161a.wav"
|
||||
[ 5, 26 ] = wave (0) : "./MITfull/elev-40/L-40e167a.wav"
|
||||
[ 5, 27 ] = wave (0) : "./MITfull/elev-40/L-40e174a.wav"
|
||||
[ 5, 28 ] = wave (0) : "./MITfull/elev-40/L-40e180a.wav"
|
||||
[ 5, 29 ] = wave (0) : "./MITfull/elev-40/L-40e186a.wav"
|
||||
[ 5, 30 ] = wave (0) : "./MITfull/elev-40/L-40e193a.wav"
|
||||
[ 5, 31 ] = wave (0) : "./MITfull/elev-40/L-40e199a.wav"
|
||||
[ 5, 32 ] = wave (0) : "./MITfull/elev-40/L-40e206a.wav"
|
||||
[ 5, 33 ] = wave (0) : "./MITfull/elev-40/L-40e212a.wav"
|
||||
[ 5, 34 ] = wave (0) : "./MITfull/elev-40/L-40e219a.wav"
|
||||
[ 5, 35 ] = wave (0) : "./MITfull/elev-40/L-40e225a.wav"
|
||||
[ 5, 36 ] = wave (0) : "./MITfull/elev-40/L-40e231a.wav"
|
||||
[ 5, 37 ] = wave (0) : "./MITfull/elev-40/L-40e238a.wav"
|
||||
[ 5, 38 ] = wave (0) : "./MITfull/elev-40/L-40e244a.wav"
|
||||
[ 5, 39 ] = wave (0) : "./MITfull/elev-40/L-40e251a.wav"
|
||||
[ 5, 40 ] = wave (0) : "./MITfull/elev-40/L-40e257a.wav"
|
||||
[ 5, 41 ] = wave (0) : "./MITfull/elev-40/L-40e264a.wav"
|
||||
[ 5, 42 ] = wave (0) : "./MITfull/elev-40/L-40e270a.wav"
|
||||
[ 5, 43 ] = wave (0) : "./MITfull/elev-40/L-40e276a.wav"
|
||||
[ 5, 44 ] = wave (0) : "./MITfull/elev-40/L-40e283a.wav"
|
||||
[ 5, 45 ] = wave (0) : "./MITfull/elev-40/L-40e289a.wav"
|
||||
[ 5, 46 ] = wave (0) : "./MITfull/elev-40/L-40e296a.wav"
|
||||
[ 5, 47 ] = wave (0) : "./MITfull/elev-40/L-40e302a.wav"
|
||||
[ 5, 48 ] = wave (0) : "./MITfull/elev-40/L-40e309a.wav"
|
||||
[ 5, 49 ] = wave (0) : "./MITfull/elev-40/L-40e315a.wav"
|
||||
[ 5, 50 ] = wave (0) : "./MITfull/elev-40/L-40e321a.wav"
|
||||
[ 5, 51 ] = wave (0) : "./MITfull/elev-40/L-40e328a.wav"
|
||||
[ 5, 52 ] = wave (0) : "./MITfull/elev-40/L-40e334a.wav"
|
||||
[ 5, 53 ] = wave (0) : "./MITfull/elev-40/L-40e341a.wav"
|
||||
[ 5, 54 ] = wave (0) : "./MITfull/elev-40/L-40e347a.wav"
|
||||
[ 5, 55 ] = wave (0) : "./MITfull/elev-40/L-40e354a.wav"
|
||||
|
||||
[ 6, 0 ] = wave (0) : "./MITfull/elev-30/L-30e000a.wav"
|
||||
[ 6, 1 ] = wave (0) : "./MITfull/elev-30/L-30e006a.wav"
|
||||
[ 6, 2 ] = wave (0) : "./MITfull/elev-30/L-30e012a.wav"
|
||||
[ 6, 3 ] = wave (0) : "./MITfull/elev-30/L-30e018a.wav"
|
||||
[ 6, 4 ] = wave (0) : "./MITfull/elev-30/L-30e024a.wav"
|
||||
[ 6, 5 ] = wave (0) : "./MITfull/elev-30/L-30e030a.wav"
|
||||
[ 6, 6 ] = wave (0) : "./MITfull/elev-30/L-30e036a.wav"
|
||||
[ 6, 7 ] = wave (0) : "./MITfull/elev-30/L-30e042a.wav"
|
||||
[ 6, 8 ] = wave (0) : "./MITfull/elev-30/L-30e048a.wav"
|
||||
[ 6, 9 ] = wave (0) : "./MITfull/elev-30/L-30e054a.wav"
|
||||
[ 6, 10 ] = wave (0) : "./MITfull/elev-30/L-30e060a.wav"
|
||||
[ 6, 11 ] = wave (0) : "./MITfull/elev-30/L-30e066a.wav"
|
||||
[ 6, 12 ] = wave (0) : "./MITfull/elev-30/L-30e072a.wav"
|
||||
[ 6, 13 ] = wave (0) : "./MITfull/elev-30/L-30e078a.wav"
|
||||
[ 6, 14 ] = wave (0) : "./MITfull/elev-30/L-30e084a.wav"
|
||||
[ 6, 15 ] = wave (0) : "./MITfull/elev-30/L-30e090a.wav"
|
||||
[ 6, 16 ] = wave (0) : "./MITfull/elev-30/L-30e096a.wav"
|
||||
[ 6, 17 ] = wave (0) : "./MITfull/elev-30/L-30e102a.wav"
|
||||
[ 6, 18 ] = wave (0) : "./MITfull/elev-30/L-30e108a.wav"
|
||||
[ 6, 19 ] = wave (0) : "./MITfull/elev-30/L-30e114a.wav"
|
||||
[ 6, 20 ] = wave (0) : "./MITfull/elev-30/L-30e120a.wav"
|
||||
[ 6, 21 ] = wave (0) : "./MITfull/elev-30/L-30e126a.wav"
|
||||
[ 6, 22 ] = wave (0) : "./MITfull/elev-30/L-30e132a.wav"
|
||||
[ 6, 23 ] = wave (0) : "./MITfull/elev-30/L-30e138a.wav"
|
||||
[ 6, 24 ] = wave (0) : "./MITfull/elev-30/L-30e144a.wav"
|
||||
[ 6, 25 ] = wave (0) : "./MITfull/elev-30/L-30e150a.wav"
|
||||
[ 6, 26 ] = wave (0) : "./MITfull/elev-30/L-30e156a.wav"
|
||||
[ 6, 27 ] = wave (0) : "./MITfull/elev-30/L-30e162a.wav"
|
||||
[ 6, 28 ] = wave (0) : "./MITfull/elev-30/L-30e168a.wav"
|
||||
[ 6, 29 ] = wave (0) : "./MITfull/elev-30/L-30e174a.wav"
|
||||
[ 6, 30 ] = wave (0) : "./MITfull/elev-30/L-30e180a.wav"
|
||||
[ 6, 31 ] = wave (0) : "./MITfull/elev-30/L-30e186a.wav"
|
||||
[ 6, 32 ] = wave (0) : "./MITfull/elev-30/L-30e192a.wav"
|
||||
[ 6, 33 ] = wave (0) : "./MITfull/elev-30/L-30e198a.wav"
|
||||
[ 6, 34 ] = wave (0) : "./MITfull/elev-30/L-30e204a.wav"
|
||||
[ 6, 35 ] = wave (0) : "./MITfull/elev-30/L-30e210a.wav"
|
||||
[ 6, 36 ] = wave (0) : "./MITfull/elev-30/L-30e216a.wav"
|
||||
[ 6, 37 ] = wave (0) : "./MITfull/elev-30/L-30e222a.wav"
|
||||
[ 6, 38 ] = wave (0) : "./MITfull/elev-30/L-30e228a.wav"
|
||||
[ 6, 39 ] = wave (0) : "./MITfull/elev-30/L-30e234a.wav"
|
||||
[ 6, 40 ] = wave (0) : "./MITfull/elev-30/L-30e240a.wav"
|
||||
[ 6, 41 ] = wave (0) : "./MITfull/elev-30/L-30e246a.wav"
|
||||
[ 6, 42 ] = wave (0) : "./MITfull/elev-30/L-30e252a.wav"
|
||||
[ 6, 43 ] = wave (0) : "./MITfull/elev-30/L-30e258a.wav"
|
||||
[ 6, 44 ] = wave (0) : "./MITfull/elev-30/L-30e264a.wav"
|
||||
[ 6, 45 ] = wave (0) : "./MITfull/elev-30/L-30e270a.wav"
|
||||
[ 6, 46 ] = wave (0) : "./MITfull/elev-30/L-30e276a.wav"
|
||||
[ 6, 47 ] = wave (0) : "./MITfull/elev-30/L-30e282a.wav"
|
||||
[ 6, 48 ] = wave (0) : "./MITfull/elev-30/L-30e288a.wav"
|
||||
[ 6, 49 ] = wave (0) : "./MITfull/elev-30/L-30e294a.wav"
|
||||
[ 6, 50 ] = wave (0) : "./MITfull/elev-30/L-30e300a.wav"
|
||||
[ 6, 51 ] = wave (0) : "./MITfull/elev-30/L-30e306a.wav"
|
||||
[ 6, 52 ] = wave (0) : "./MITfull/elev-30/L-30e312a.wav"
|
||||
[ 6, 53 ] = wave (0) : "./MITfull/elev-30/L-30e318a.wav"
|
||||
[ 6, 54 ] = wave (0) : "./MITfull/elev-30/L-30e324a.wav"
|
||||
[ 6, 55 ] = wave (0) : "./MITfull/elev-30/L-30e330a.wav"
|
||||
[ 6, 56 ] = wave (0) : "./MITfull/elev-30/L-30e336a.wav"
|
||||
[ 6, 57 ] = wave (0) : "./MITfull/elev-30/L-30e342a.wav"
|
||||
[ 6, 58 ] = wave (0) : "./MITfull/elev-30/L-30e348a.wav"
|
||||
[ 6, 59 ] = wave (0) : "./MITfull/elev-30/L-30e354a.wav"
|
||||
|
||||
[ 7, 0 ] = wave (0) : "./MITfull/elev-20/L-20e000a.wav"
|
||||
[ 7, 1 ] = wave (0) : "./MITfull/elev-20/L-20e005a.wav"
|
||||
[ 7, 2 ] = wave (0) : "./MITfull/elev-20/L-20e010a.wav"
|
||||
[ 7, 3 ] = wave (0) : "./MITfull/elev-20/L-20e015a.wav"
|
||||
[ 7, 4 ] = wave (0) : "./MITfull/elev-20/L-20e020a.wav"
|
||||
[ 7, 5 ] = wave (0) : "./MITfull/elev-20/L-20e025a.wav"
|
||||
[ 7, 6 ] = wave (0) : "./MITfull/elev-20/L-20e030a.wav"
|
||||
[ 7, 7 ] = wave (0) : "./MITfull/elev-20/L-20e035a.wav"
|
||||
[ 7, 8 ] = wave (0) : "./MITfull/elev-20/L-20e040a.wav"
|
||||
[ 7, 9 ] = wave (0) : "./MITfull/elev-20/L-20e045a.wav"
|
||||
[ 7, 10 ] = wave (0) : "./MITfull/elev-20/L-20e050a.wav"
|
||||
[ 7, 11 ] = wave (0) : "./MITfull/elev-20/L-20e055a.wav"
|
||||
[ 7, 12 ] = wave (0) : "./MITfull/elev-20/L-20e060a.wav"
|
||||
[ 7, 13 ] = wave (0) : "./MITfull/elev-20/L-20e065a.wav"
|
||||
[ 7, 14 ] = wave (0) : "./MITfull/elev-20/L-20e070a.wav"
|
||||
[ 7, 15 ] = wave (0) : "./MITfull/elev-20/L-20e075a.wav"
|
||||
[ 7, 16 ] = wave (0) : "./MITfull/elev-20/L-20e080a.wav"
|
||||
[ 7, 17 ] = wave (0) : "./MITfull/elev-20/L-20e085a.wav"
|
||||
[ 7, 18 ] = wave (0) : "./MITfull/elev-20/L-20e090a.wav"
|
||||
[ 7, 19 ] = wave (0) : "./MITfull/elev-20/L-20e095a.wav"
|
||||
[ 7, 20 ] = wave (0) : "./MITfull/elev-20/L-20e100a.wav"
|
||||
[ 7, 21 ] = wave (0) : "./MITfull/elev-20/L-20e105a.wav"
|
||||
[ 7, 22 ] = wave (0) : "./MITfull/elev-20/L-20e110a.wav"
|
||||
[ 7, 23 ] = wave (0) : "./MITfull/elev-20/L-20e115a.wav"
|
||||
[ 7, 24 ] = wave (0) : "./MITfull/elev-20/L-20e120a.wav"
|
||||
[ 7, 25 ] = wave (0) : "./MITfull/elev-20/L-20e125a.wav"
|
||||
[ 7, 26 ] = wave (0) : "./MITfull/elev-20/L-20e130a.wav"
|
||||
[ 7, 27 ] = wave (0) : "./MITfull/elev-20/L-20e135a.wav"
|
||||
[ 7, 28 ] = wave (0) : "./MITfull/elev-20/L-20e140a.wav"
|
||||
[ 7, 29 ] = wave (0) : "./MITfull/elev-20/L-20e145a.wav"
|
||||
[ 7, 30 ] = wave (0) : "./MITfull/elev-20/L-20e150a.wav"
|
||||
[ 7, 31 ] = wave (0) : "./MITfull/elev-20/L-20e155a.wav"
|
||||
[ 7, 32 ] = wave (0) : "./MITfull/elev-20/L-20e160a.wav"
|
||||
[ 7, 33 ] = wave (0) : "./MITfull/elev-20/L-20e165a.wav"
|
||||
[ 7, 34 ] = wave (0) : "./MITfull/elev-20/L-20e170a.wav"
|
||||
[ 7, 35 ] = wave (0) : "./MITfull/elev-20/L-20e175a.wav"
|
||||
[ 7, 36 ] = wave (0) : "./MITfull/elev-20/L-20e180a.wav"
|
||||
[ 7, 37 ] = wave (0) : "./MITfull/elev-20/L-20e185a.wav"
|
||||
[ 7, 38 ] = wave (0) : "./MITfull/elev-20/L-20e190a.wav"
|
||||
[ 7, 39 ] = wave (0) : "./MITfull/elev-20/L-20e195a.wav"
|
||||
[ 7, 40 ] = wave (0) : "./MITfull/elev-20/L-20e200a.wav"
|
||||
[ 7, 41 ] = wave (0) : "./MITfull/elev-20/L-20e205a.wav"
|
||||
[ 7, 42 ] = wave (0) : "./MITfull/elev-20/L-20e210a.wav"
|
||||
[ 7, 43 ] = wave (0) : "./MITfull/elev-20/L-20e215a.wav"
|
||||
[ 7, 44 ] = wave (0) : "./MITfull/elev-20/L-20e220a.wav"
|
||||
[ 7, 45 ] = wave (0) : "./MITfull/elev-20/L-20e225a.wav"
|
||||
[ 7, 46 ] = wave (0) : "./MITfull/elev-20/L-20e230a.wav"
|
||||
[ 7, 47 ] = wave (0) : "./MITfull/elev-20/L-20e235a.wav"
|
||||
[ 7, 48 ] = wave (0) : "./MITfull/elev-20/L-20e240a.wav"
|
||||
[ 7, 49 ] = wave (0) : "./MITfull/elev-20/L-20e245a.wav"
|
||||
[ 7, 50 ] = wave (0) : "./MITfull/elev-20/L-20e250a.wav"
|
||||
[ 7, 51 ] = wave (0) : "./MITfull/elev-20/L-20e255a.wav"
|
||||
[ 7, 52 ] = wave (0) : "./MITfull/elev-20/L-20e260a.wav"
|
||||
[ 7, 53 ] = wave (0) : "./MITfull/elev-20/L-20e265a.wav"
|
||||
[ 7, 54 ] = wave (0) : "./MITfull/elev-20/L-20e270a.wav"
|
||||
[ 7, 55 ] = wave (0) : "./MITfull/elev-20/L-20e275a.wav"
|
||||
[ 7, 56 ] = wave (0) : "./MITfull/elev-20/L-20e280a.wav"
|
||||
[ 7, 57 ] = wave (0) : "./MITfull/elev-20/L-20e285a.wav"
|
||||
[ 7, 58 ] = wave (0) : "./MITfull/elev-20/L-20e290a.wav"
|
||||
[ 7, 59 ] = wave (0) : "./MITfull/elev-20/L-20e295a.wav"
|
||||
[ 7, 60 ] = wave (0) : "./MITfull/elev-20/L-20e300a.wav"
|
||||
[ 7, 61 ] = wave (0) : "./MITfull/elev-20/L-20e305a.wav"
|
||||
[ 7, 62 ] = wave (0) : "./MITfull/elev-20/L-20e310a.wav"
|
||||
[ 7, 63 ] = wave (0) : "./MITfull/elev-20/L-20e315a.wav"
|
||||
[ 7, 64 ] = wave (0) : "./MITfull/elev-20/L-20e320a.wav"
|
||||
[ 7, 65 ] = wave (0) : "./MITfull/elev-20/L-20e325a.wav"
|
||||
[ 7, 66 ] = wave (0) : "./MITfull/elev-20/L-20e330a.wav"
|
||||
[ 7, 67 ] = wave (0) : "./MITfull/elev-20/L-20e335a.wav"
|
||||
[ 7, 68 ] = wave (0) : "./MITfull/elev-20/L-20e340a.wav"
|
||||
[ 7, 69 ] = wave (0) : "./MITfull/elev-20/L-20e345a.wav"
|
||||
[ 7, 70 ] = wave (0) : "./MITfull/elev-20/L-20e350a.wav"
|
||||
[ 7, 71 ] = wave (0) : "./MITfull/elev-20/L-20e355a.wav"
|
||||
|
||||
[ 8, 0 ] = wave (0) : "./MITfull/elev-10/L-10e000a.wav"
|
||||
[ 8, 1 ] = wave (0) : "./MITfull/elev-10/L-10e005a.wav"
|
||||
[ 8, 2 ] = wave (0) : "./MITfull/elev-10/L-10e010a.wav"
|
||||
[ 8, 3 ] = wave (0) : "./MITfull/elev-10/L-10e015a.wav"
|
||||
[ 8, 4 ] = wave (0) : "./MITfull/elev-10/L-10e020a.wav"
|
||||
[ 8, 5 ] = wave (0) : "./MITfull/elev-10/L-10e025a.wav"
|
||||
[ 8, 6 ] = wave (0) : "./MITfull/elev-10/L-10e030a.wav"
|
||||
[ 8, 7 ] = wave (0) : "./MITfull/elev-10/L-10e035a.wav"
|
||||
[ 8, 8 ] = wave (0) : "./MITfull/elev-10/L-10e040a.wav"
|
||||
[ 8, 9 ] = wave (0) : "./MITfull/elev-10/L-10e045a.wav"
|
||||
[ 8, 10 ] = wave (0) : "./MITfull/elev-10/L-10e050a.wav"
|
||||
[ 8, 11 ] = wave (0) : "./MITfull/elev-10/L-10e055a.wav"
|
||||
[ 8, 12 ] = wave (0) : "./MITfull/elev-10/L-10e060a.wav"
|
||||
[ 8, 13 ] = wave (0) : "./MITfull/elev-10/L-10e065a.wav"
|
||||
[ 8, 14 ] = wave (0) : "./MITfull/elev-10/L-10e070a.wav"
|
||||
[ 8, 15 ] = wave (0) : "./MITfull/elev-10/L-10e075a.wav"
|
||||
[ 8, 16 ] = wave (0) : "./MITfull/elev-10/L-10e080a.wav"
|
||||
[ 8, 17 ] = wave (0) : "./MITfull/elev-10/L-10e085a.wav"
|
||||
[ 8, 18 ] = wave (0) : "./MITfull/elev-10/L-10e090a.wav"
|
||||
[ 8, 19 ] = wave (0) : "./MITfull/elev-10/L-10e095a.wav"
|
||||
[ 8, 20 ] = wave (0) : "./MITfull/elev-10/L-10e100a.wav"
|
||||
[ 8, 21 ] = wave (0) : "./MITfull/elev-10/L-10e105a.wav"
|
||||
[ 8, 22 ] = wave (0) : "./MITfull/elev-10/L-10e110a.wav"
|
||||
[ 8, 23 ] = wave (0) : "./MITfull/elev-10/L-10e115a.wav"
|
||||
[ 8, 24 ] = wave (0) : "./MITfull/elev-10/L-10e120a.wav"
|
||||
[ 8, 25 ] = wave (0) : "./MITfull/elev-10/L-10e125a.wav"
|
||||
[ 8, 26 ] = wave (0) : "./MITfull/elev-10/L-10e130a.wav"
|
||||
[ 8, 27 ] = wave (0) : "./MITfull/elev-10/L-10e135a.wav"
|
||||
[ 8, 28 ] = wave (0) : "./MITfull/elev-10/L-10e140a.wav"
|
||||
[ 8, 29 ] = wave (0) : "./MITfull/elev-10/L-10e145a.wav"
|
||||
[ 8, 30 ] = wave (0) : "./MITfull/elev-10/L-10e150a.wav"
|
||||
[ 8, 31 ] = wave (0) : "./MITfull/elev-10/L-10e155a.wav"
|
||||
[ 8, 32 ] = wave (0) : "./MITfull/elev-10/L-10e160a.wav"
|
||||
[ 8, 33 ] = wave (0) : "./MITfull/elev-10/L-10e165a.wav"
|
||||
[ 8, 34 ] = wave (0) : "./MITfull/elev-10/L-10e170a.wav"
|
||||
[ 8, 35 ] = wave (0) : "./MITfull/elev-10/L-10e175a.wav"
|
||||
[ 8, 36 ] = wave (0) : "./MITfull/elev-10/L-10e180a.wav"
|
||||
[ 8, 37 ] = wave (0) : "./MITfull/elev-10/L-10e185a.wav"
|
||||
[ 8, 38 ] = wave (0) : "./MITfull/elev-10/L-10e190a.wav"
|
||||
[ 8, 39 ] = wave (0) : "./MITfull/elev-10/L-10e195a.wav"
|
||||
[ 8, 40 ] = wave (0) : "./MITfull/elev-10/L-10e200a.wav"
|
||||
[ 8, 41 ] = wave (0) : "./MITfull/elev-10/L-10e205a.wav"
|
||||
[ 8, 42 ] = wave (0) : "./MITfull/elev-10/L-10e210a.wav"
|
||||
[ 8, 43 ] = wave (0) : "./MITfull/elev-10/L-10e215a.wav"
|
||||
[ 8, 44 ] = wave (0) : "./MITfull/elev-10/L-10e220a.wav"
|
||||
[ 8, 45 ] = wave (0) : "./MITfull/elev-10/L-10e225a.wav"
|
||||
[ 8, 46 ] = wave (0) : "./MITfull/elev-10/L-10e230a.wav"
|
||||
[ 8, 47 ] = wave (0) : "./MITfull/elev-10/L-10e235a.wav"
|
||||
[ 8, 48 ] = wave (0) : "./MITfull/elev-10/L-10e240a.wav"
|
||||
[ 8, 49 ] = wave (0) : "./MITfull/elev-10/L-10e245a.wav"
|
||||
[ 8, 50 ] = wave (0) : "./MITfull/elev-10/L-10e250a.wav"
|
||||
[ 8, 51 ] = wave (0) : "./MITfull/elev-10/L-10e255a.wav"
|
||||
[ 8, 52 ] = wave (0) : "./MITfull/elev-10/L-10e260a.wav"
|
||||
[ 8, 53 ] = wave (0) : "./MITfull/elev-10/L-10e265a.wav"
|
||||
[ 8, 54 ] = wave (0) : "./MITfull/elev-10/L-10e270a.wav"
|
||||
[ 8, 55 ] = wave (0) : "./MITfull/elev-10/L-10e275a.wav"
|
||||
[ 8, 56 ] = wave (0) : "./MITfull/elev-10/L-10e280a.wav"
|
||||
[ 8, 57 ] = wave (0) : "./MITfull/elev-10/L-10e285a.wav"
|
||||
[ 8, 58 ] = wave (0) : "./MITfull/elev-10/L-10e290a.wav"
|
||||
[ 8, 59 ] = wave (0) : "./MITfull/elev-10/L-10e295a.wav"
|
||||
[ 8, 60 ] = wave (0) : "./MITfull/elev-10/L-10e300a.wav"
|
||||
[ 8, 61 ] = wave (0) : "./MITfull/elev-10/L-10e305a.wav"
|
||||
[ 8, 62 ] = wave (0) : "./MITfull/elev-10/L-10e310a.wav"
|
||||
[ 8, 63 ] = wave (0) : "./MITfull/elev-10/L-10e315a.wav"
|
||||
[ 8, 64 ] = wave (0) : "./MITfull/elev-10/L-10e320a.wav"
|
||||
[ 8, 65 ] = wave (0) : "./MITfull/elev-10/L-10e325a.wav"
|
||||
[ 8, 66 ] = wave (0) : "./MITfull/elev-10/L-10e330a.wav"
|
||||
[ 8, 67 ] = wave (0) : "./MITfull/elev-10/L-10e335a.wav"
|
||||
[ 8, 68 ] = wave (0) : "./MITfull/elev-10/L-10e340a.wav"
|
||||
[ 8, 69 ] = wave (0) : "./MITfull/elev-10/L-10e345a.wav"
|
||||
[ 8, 70 ] = wave (0) : "./MITfull/elev-10/L-10e350a.wav"
|
||||
[ 8, 71 ] = wave (0) : "./MITfull/elev-10/L-10e355a.wav"
|
||||
|
||||
[ 9, 0 ] = wave (0) : "./MITfull/elev0/L0e000a.wav"
|
||||
[ 9, 1 ] = wave (0) : "./MITfull/elev0/L0e005a.wav"
|
||||
[ 9, 2 ] = wave (0) : "./MITfull/elev0/L0e010a.wav"
|
||||
[ 9, 3 ] = wave (0) : "./MITfull/elev0/L0e015a.wav"
|
||||
[ 9, 4 ] = wave (0) : "./MITfull/elev0/L0e020a.wav"
|
||||
[ 9, 5 ] = wave (0) : "./MITfull/elev0/L0e025a.wav"
|
||||
[ 9, 6 ] = wave (0) : "./MITfull/elev0/L0e030a.wav"
|
||||
[ 9, 7 ] = wave (0) : "./MITfull/elev0/L0e035a.wav"
|
||||
[ 9, 8 ] = wave (0) : "./MITfull/elev0/L0e040a.wav"
|
||||
[ 9, 9 ] = wave (0) : "./MITfull/elev0/L0e045a.wav"
|
||||
[ 9, 10 ] = wave (0) : "./MITfull/elev0/L0e050a.wav"
|
||||
[ 9, 11 ] = wave (0) : "./MITfull/elev0/L0e055a.wav"
|
||||
[ 9, 12 ] = wave (0) : "./MITfull/elev0/L0e060a.wav"
|
||||
[ 9, 13 ] = wave (0) : "./MITfull/elev0/L0e065a.wav"
|
||||
[ 9, 14 ] = wave (0) : "./MITfull/elev0/L0e070a.wav"
|
||||
[ 9, 15 ] = wave (0) : "./MITfull/elev0/L0e075a.wav"
|
||||
[ 9, 16 ] = wave (0) : "./MITfull/elev0/L0e080a.wav"
|
||||
[ 9, 17 ] = wave (0) : "./MITfull/elev0/L0e085a.wav"
|
||||
[ 9, 18 ] = wave (0) : "./MITfull/elev0/L0e090a.wav"
|
||||
[ 9, 19 ] = wave (0) : "./MITfull/elev0/L0e095a.wav"
|
||||
[ 9, 20 ] = wave (0) : "./MITfull/elev0/L0e100a.wav"
|
||||
[ 9, 21 ] = wave (0) : "./MITfull/elev0/L0e105a.wav"
|
||||
[ 9, 22 ] = wave (0) : "./MITfull/elev0/L0e110a.wav"
|
||||
[ 9, 23 ] = wave (0) : "./MITfull/elev0/L0e115a.wav"
|
||||
[ 9, 24 ] = wave (0) : "./MITfull/elev0/L0e120a.wav"
|
||||
[ 9, 25 ] = wave (0) : "./MITfull/elev0/L0e125a.wav"
|
||||
[ 9, 26 ] = wave (0) : "./MITfull/elev0/L0e130a.wav"
|
||||
[ 9, 27 ] = wave (0) : "./MITfull/elev0/L0e135a.wav"
|
||||
[ 9, 28 ] = wave (0) : "./MITfull/elev0/L0e140a.wav"
|
||||
[ 9, 29 ] = wave (0) : "./MITfull/elev0/L0e145a.wav"
|
||||
[ 9, 30 ] = wave (0) : "./MITfull/elev0/L0e150a.wav"
|
||||
[ 9, 31 ] = wave (0) : "./MITfull/elev0/L0e155a.wav"
|
||||
[ 9, 32 ] = wave (0) : "./MITfull/elev0/L0e160a.wav"
|
||||
[ 9, 33 ] = wave (0) : "./MITfull/elev0/L0e165a.wav"
|
||||
[ 9, 34 ] = wave (0) : "./MITfull/elev0/L0e170a.wav"
|
||||
[ 9, 35 ] = wave (0) : "./MITfull/elev0/L0e175a.wav"
|
||||
[ 9, 36 ] = wave (0) : "./MITfull/elev0/L0e180a.wav"
|
||||
[ 9, 37 ] = wave (0) : "./MITfull/elev0/L0e185a.wav"
|
||||
[ 9, 38 ] = wave (0) : "./MITfull/elev0/L0e190a.wav"
|
||||
[ 9, 39 ] = wave (0) : "./MITfull/elev0/L0e195a.wav"
|
||||
[ 9, 40 ] = wave (0) : "./MITfull/elev0/L0e200a.wav"
|
||||
[ 9, 41 ] = wave (0) : "./MITfull/elev0/L0e205a.wav"
|
||||
[ 9, 42 ] = wave (0) : "./MITfull/elev0/L0e210a.wav"
|
||||
[ 9, 43 ] = wave (0) : "./MITfull/elev0/L0e215a.wav"
|
||||
[ 9, 44 ] = wave (0) : "./MITfull/elev0/L0e220a.wav"
|
||||
[ 9, 45 ] = wave (0) : "./MITfull/elev0/L0e225a.wav"
|
||||
[ 9, 46 ] = wave (0) : "./MITfull/elev0/L0e230a.wav"
|
||||
[ 9, 47 ] = wave (0) : "./MITfull/elev0/L0e235a.wav"
|
||||
[ 9, 48 ] = wave (0) : "./MITfull/elev0/L0e240a.wav"
|
||||
[ 9, 49 ] = wave (0) : "./MITfull/elev0/L0e245a.wav"
|
||||
[ 9, 50 ] = wave (0) : "./MITfull/elev0/L0e250a.wav"
|
||||
[ 9, 51 ] = wave (0) : "./MITfull/elev0/L0e255a.wav"
|
||||
[ 9, 52 ] = wave (0) : "./MITfull/elev0/L0e260a.wav"
|
||||
[ 9, 53 ] = wave (0) : "./MITfull/elev0/L0e265a.wav"
|
||||
[ 9, 54 ] = wave (0) : "./MITfull/elev0/L0e270a.wav"
|
||||
[ 9, 55 ] = wave (0) : "./MITfull/elev0/L0e275a.wav"
|
||||
[ 9, 56 ] = wave (0) : "./MITfull/elev0/L0e280a.wav"
|
||||
[ 9, 57 ] = wave (0) : "./MITfull/elev0/L0e285a.wav"
|
||||
[ 9, 58 ] = wave (0) : "./MITfull/elev0/L0e290a.wav"
|
||||
[ 9, 59 ] = wave (0) : "./MITfull/elev0/L0e295a.wav"
|
||||
[ 9, 60 ] = wave (0) : "./MITfull/elev0/L0e300a.wav"
|
||||
[ 9, 61 ] = wave (0) : "./MITfull/elev0/L0e305a.wav"
|
||||
[ 9, 62 ] = wave (0) : "./MITfull/elev0/L0e310a.wav"
|
||||
[ 9, 63 ] = wave (0) : "./MITfull/elev0/L0e315a.wav"
|
||||
[ 9, 64 ] = wave (0) : "./MITfull/elev0/L0e320a.wav"
|
||||
[ 9, 65 ] = wave (0) : "./MITfull/elev0/L0e325a.wav"
|
||||
[ 9, 66 ] = wave (0) : "./MITfull/elev0/L0e330a.wav"
|
||||
[ 9, 67 ] = wave (0) : "./MITfull/elev0/L0e335a.wav"
|
||||
[ 9, 68 ] = wave (0) : "./MITfull/elev0/L0e340a.wav"
|
||||
[ 9, 69 ] = wave (0) : "./MITfull/elev0/L0e345a.wav"
|
||||
[ 9, 70 ] = wave (0) : "./MITfull/elev0/L0e350a.wav"
|
||||
[ 9, 71 ] = wave (0) : "./MITfull/elev0/L0e355a.wav"
|
||||
|
||||
[ 10, 0 ] = wave (0) : "./MITfull/elev10/L10e000a.wav"
|
||||
[ 10, 1 ] = wave (0) : "./MITfull/elev10/L10e005a.wav"
|
||||
[ 10, 2 ] = wave (0) : "./MITfull/elev10/L10e010a.wav"
|
||||
[ 10, 3 ] = wave (0) : "./MITfull/elev10/L10e015a.wav"
|
||||
[ 10, 4 ] = wave (0) : "./MITfull/elev10/L10e020a.wav"
|
||||
[ 10, 5 ] = wave (0) : "./MITfull/elev10/L10e025a.wav"
|
||||
[ 10, 6 ] = wave (0) : "./MITfull/elev10/L10e030a.wav"
|
||||
[ 10, 7 ] = wave (0) : "./MITfull/elev10/L10e035a.wav"
|
||||
[ 10, 8 ] = wave (0) : "./MITfull/elev10/L10e040a.wav"
|
||||
[ 10, 9 ] = wave (0) : "./MITfull/elev10/L10e045a.wav"
|
||||
[ 10, 10 ] = wave (0) : "./MITfull/elev10/L10e050a.wav"
|
||||
[ 10, 11 ] = wave (0) : "./MITfull/elev10/L10e055a.wav"
|
||||
[ 10, 12 ] = wave (0) : "./MITfull/elev10/L10e060a.wav"
|
||||
[ 10, 13 ] = wave (0) : "./MITfull/elev10/L10e065a.wav"
|
||||
[ 10, 14 ] = wave (0) : "./MITfull/elev10/L10e070a.wav"
|
||||
[ 10, 15 ] = wave (0) : "./MITfull/elev10/L10e075a.wav"
|
||||
[ 10, 16 ] = wave (0) : "./MITfull/elev10/L10e080a.wav"
|
||||
[ 10, 17 ] = wave (0) : "./MITfull/elev10/L10e085a.wav"
|
||||
[ 10, 18 ] = wave (0) : "./MITfull/elev10/L10e090a.wav"
|
||||
[ 10, 19 ] = wave (0) : "./MITfull/elev10/L10e095a.wav"
|
||||
[ 10, 20 ] = wave (0) : "./MITfull/elev10/L10e100a.wav"
|
||||
[ 10, 21 ] = wave (0) : "./MITfull/elev10/L10e105a.wav"
|
||||
[ 10, 22 ] = wave (0) : "./MITfull/elev10/L10e110a.wav"
|
||||
[ 10, 23 ] = wave (0) : "./MITfull/elev10/L10e115a.wav"
|
||||
[ 10, 24 ] = wave (0) : "./MITfull/elev10/L10e120a.wav"
|
||||
[ 10, 25 ] = wave (0) : "./MITfull/elev10/L10e125a.wav"
|
||||
[ 10, 26 ] = wave (0) : "./MITfull/elev10/L10e130a.wav"
|
||||
[ 10, 27 ] = wave (0) : "./MITfull/elev10/L10e135a.wav"
|
||||
[ 10, 28 ] = wave (0) : "./MITfull/elev10/L10e140a.wav"
|
||||
[ 10, 29 ] = wave (0) : "./MITfull/elev10/L10e145a.wav"
|
||||
[ 10, 30 ] = wave (0) : "./MITfull/elev10/L10e150a.wav"
|
||||
[ 10, 31 ] = wave (0) : "./MITfull/elev10/L10e155a.wav"
|
||||
[ 10, 32 ] = wave (0) : "./MITfull/elev10/L10e160a.wav"
|
||||
[ 10, 33 ] = wave (0) : "./MITfull/elev10/L10e165a.wav"
|
||||
[ 10, 34 ] = wave (0) : "./MITfull/elev10/L10e170a.wav"
|
||||
[ 10, 35 ] = wave (0) : "./MITfull/elev10/L10e175a.wav"
|
||||
[ 10, 36 ] = wave (0) : "./MITfull/elev10/L10e180a.wav"
|
||||
[ 10, 37 ] = wave (0) : "./MITfull/elev10/L10e185a.wav"
|
||||
[ 10, 38 ] = wave (0) : "./MITfull/elev10/L10e190a.wav"
|
||||
[ 10, 39 ] = wave (0) : "./MITfull/elev10/L10e195a.wav"
|
||||
[ 10, 40 ] = wave (0) : "./MITfull/elev10/L10e200a.wav"
|
||||
[ 10, 41 ] = wave (0) : "./MITfull/elev10/L10e205a.wav"
|
||||
[ 10, 42 ] = wave (0) : "./MITfull/elev10/L10e210a.wav"
|
||||
[ 10, 43 ] = wave (0) : "./MITfull/elev10/L10e215a.wav"
|
||||
[ 10, 44 ] = wave (0) : "./MITfull/elev10/L10e220a.wav"
|
||||
[ 10, 45 ] = wave (0) : "./MITfull/elev10/L10e225a.wav"
|
||||
[ 10, 46 ] = wave (0) : "./MITfull/elev10/L10e230a.wav"
|
||||
[ 10, 47 ] = wave (0) : "./MITfull/elev10/L10e235a.wav"
|
||||
[ 10, 48 ] = wave (0) : "./MITfull/elev10/L10e240a.wav"
|
||||
[ 10, 49 ] = wave (0) : "./MITfull/elev10/L10e245a.wav"
|
||||
[ 10, 50 ] = wave (0) : "./MITfull/elev10/L10e250a.wav"
|
||||
[ 10, 51 ] = wave (0) : "./MITfull/elev10/L10e255a.wav"
|
||||
[ 10, 52 ] = wave (0) : "./MITfull/elev10/L10e260a.wav"
|
||||
[ 10, 53 ] = wave (0) : "./MITfull/elev10/L10e265a.wav"
|
||||
[ 10, 54 ] = wave (0) : "./MITfull/elev10/L10e270a.wav"
|
||||
[ 10, 55 ] = wave (0) : "./MITfull/elev10/L10e275a.wav"
|
||||
[ 10, 56 ] = wave (0) : "./MITfull/elev10/L10e280a.wav"
|
||||
[ 10, 57 ] = wave (0) : "./MITfull/elev10/L10e285a.wav"
|
||||
[ 10, 58 ] = wave (0) : "./MITfull/elev10/L10e290a.wav"
|
||||
[ 10, 59 ] = wave (0) : "./MITfull/elev10/L10e295a.wav"
|
||||
[ 10, 60 ] = wave (0) : "./MITfull/elev10/L10e300a.wav"
|
||||
[ 10, 61 ] = wave (0) : "./MITfull/elev10/L10e305a.wav"
|
||||
[ 10, 62 ] = wave (0) : "./MITfull/elev10/L10e310a.wav"
|
||||
[ 10, 63 ] = wave (0) : "./MITfull/elev10/L10e315a.wav"
|
||||
[ 10, 64 ] = wave (0) : "./MITfull/elev10/L10e320a.wav"
|
||||
[ 10, 65 ] = wave (0) : "./MITfull/elev10/L10e325a.wav"
|
||||
[ 10, 66 ] = wave (0) : "./MITfull/elev10/L10e330a.wav"
|
||||
[ 10, 67 ] = wave (0) : "./MITfull/elev10/L10e335a.wav"
|
||||
[ 10, 68 ] = wave (0) : "./MITfull/elev10/L10e340a.wav"
|
||||
[ 10, 69 ] = wave (0) : "./MITfull/elev10/L10e345a.wav"
|
||||
[ 10, 70 ] = wave (0) : "./MITfull/elev10/L10e350a.wav"
|
||||
[ 10, 71 ] = wave (0) : "./MITfull/elev10/L10e355a.wav"
|
||||
|
||||
[ 11, 0 ] = wave (0) : "./MITfull/elev20/L20e000a.wav"
|
||||
[ 11, 1 ] = wave (0) : "./MITfull/elev20/L20e005a.wav"
|
||||
[ 11, 2 ] = wave (0) : "./MITfull/elev20/L20e010a.wav"
|
||||
[ 11, 3 ] = wave (0) : "./MITfull/elev20/L20e015a.wav"
|
||||
[ 11, 4 ] = wave (0) : "./MITfull/elev20/L20e020a.wav"
|
||||
[ 11, 5 ] = wave (0) : "./MITfull/elev20/L20e025a.wav"
|
||||
[ 11, 6 ] = wave (0) : "./MITfull/elev20/L20e030a.wav"
|
||||
[ 11, 7 ] = wave (0) : "./MITfull/elev20/L20e035a.wav"
|
||||
[ 11, 8 ] = wave (0) : "./MITfull/elev20/L20e040a.wav"
|
||||
[ 11, 9 ] = wave (0) : "./MITfull/elev20/L20e045a.wav"
|
||||
[ 11, 10 ] = wave (0) : "./MITfull/elev20/L20e050a.wav"
|
||||
[ 11, 11 ] = wave (0) : "./MITfull/elev20/L20e055a.wav"
|
||||
[ 11, 12 ] = wave (0) : "./MITfull/elev20/L20e060a.wav"
|
||||
[ 11, 13 ] = wave (0) : "./MITfull/elev20/L20e065a.wav"
|
||||
[ 11, 14 ] = wave (0) : "./MITfull/elev20/L20e070a.wav"
|
||||
[ 11, 15 ] = wave (0) : "./MITfull/elev20/L20e075a.wav"
|
||||
[ 11, 16 ] = wave (0) : "./MITfull/elev20/L20e080a.wav"
|
||||
[ 11, 17 ] = wave (0) : "./MITfull/elev20/L20e085a.wav"
|
||||
[ 11, 18 ] = wave (0) : "./MITfull/elev20/L20e090a.wav"
|
||||
[ 11, 19 ] = wave (0) : "./MITfull/elev20/L20e095a.wav"
|
||||
[ 11, 20 ] = wave (0) : "./MITfull/elev20/L20e100a.wav"
|
||||
[ 11, 21 ] = wave (0) : "./MITfull/elev20/L20e105a.wav"
|
||||
[ 11, 22 ] = wave (0) : "./MITfull/elev20/L20e110a.wav"
|
||||
[ 11, 23 ] = wave (0) : "./MITfull/elev20/L20e115a.wav"
|
||||
[ 11, 24 ] = wave (0) : "./MITfull/elev20/L20e120a.wav"
|
||||
[ 11, 25 ] = wave (0) : "./MITfull/elev20/L20e125a.wav"
|
||||
[ 11, 26 ] = wave (0) : "./MITfull/elev20/L20e130a.wav"
|
||||
[ 11, 27 ] = wave (0) : "./MITfull/elev20/L20e135a.wav"
|
||||
[ 11, 28 ] = wave (0) : "./MITfull/elev20/L20e140a.wav"
|
||||
[ 11, 29 ] = wave (0) : "./MITfull/elev20/L20e145a.wav"
|
||||
[ 11, 30 ] = wave (0) : "./MITfull/elev20/L20e150a.wav"
|
||||
[ 11, 31 ] = wave (0) : "./MITfull/elev20/L20e155a.wav"
|
||||
[ 11, 32 ] = wave (0) : "./MITfull/elev20/L20e160a.wav"
|
||||
[ 11, 33 ] = wave (0) : "./MITfull/elev20/L20e165a.wav"
|
||||
[ 11, 34 ] = wave (0) : "./MITfull/elev20/L20e170a.wav"
|
||||
[ 11, 35 ] = wave (0) : "./MITfull/elev20/L20e175a.wav"
|
||||
[ 11, 36 ] = wave (0) : "./MITfull/elev20/L20e180a.wav"
|
||||
[ 11, 37 ] = wave (0) : "./MITfull/elev20/L20e185a.wav"
|
||||
[ 11, 38 ] = wave (0) : "./MITfull/elev20/L20e190a.wav"
|
||||
[ 11, 39 ] = wave (0) : "./MITfull/elev20/L20e195a.wav"
|
||||
[ 11, 40 ] = wave (0) : "./MITfull/elev20/L20e200a.wav"
|
||||
[ 11, 41 ] = wave (0) : "./MITfull/elev20/L20e205a.wav"
|
||||
[ 11, 42 ] = wave (0) : "./MITfull/elev20/L20e210a.wav"
|
||||
[ 11, 43 ] = wave (0) : "./MITfull/elev20/L20e215a.wav"
|
||||
[ 11, 44 ] = wave (0) : "./MITfull/elev20/L20e220a.wav"
|
||||
[ 11, 45 ] = wave (0) : "./MITfull/elev20/L20e225a.wav"
|
||||
[ 11, 46 ] = wave (0) : "./MITfull/elev20/L20e230a.wav"
|
||||
[ 11, 47 ] = wave (0) : "./MITfull/elev20/L20e235a.wav"
|
||||
[ 11, 48 ] = wave (0) : "./MITfull/elev20/L20e240a.wav"
|
||||
[ 11, 49 ] = wave (0) : "./MITfull/elev20/L20e245a.wav"
|
||||
[ 11, 50 ] = wave (0) : "./MITfull/elev20/L20e250a.wav"
|
||||
[ 11, 51 ] = wave (0) : "./MITfull/elev20/L20e255a.wav"
|
||||
[ 11, 52 ] = wave (0) : "./MITfull/elev20/L20e260a.wav"
|
||||
[ 11, 53 ] = wave (0) : "./MITfull/elev20/L20e265a.wav"
|
||||
[ 11, 54 ] = wave (0) : "./MITfull/elev20/L20e270a.wav"
|
||||
[ 11, 55 ] = wave (0) : "./MITfull/elev20/L20e275a.wav"
|
||||
[ 11, 56 ] = wave (0) : "./MITfull/elev20/L20e280a.wav"
|
||||
[ 11, 57 ] = wave (0) : "./MITfull/elev20/L20e285a.wav"
|
||||
[ 11, 58 ] = wave (0) : "./MITfull/elev20/L20e290a.wav"
|
||||
[ 11, 59 ] = wave (0) : "./MITfull/elev20/L20e295a.wav"
|
||||
[ 11, 60 ] = wave (0) : "./MITfull/elev20/L20e300a.wav"
|
||||
[ 11, 61 ] = wave (0) : "./MITfull/elev20/L20e305a.wav"
|
||||
[ 11, 62 ] = wave (0) : "./MITfull/elev20/L20e310a.wav"
|
||||
[ 11, 63 ] = wave (0) : "./MITfull/elev20/L20e315a.wav"
|
||||
[ 11, 64 ] = wave (0) : "./MITfull/elev20/L20e320a.wav"
|
||||
[ 11, 65 ] = wave (0) : "./MITfull/elev20/L20e325a.wav"
|
||||
[ 11, 66 ] = wave (0) : "./MITfull/elev20/L20e330a.wav"
|
||||
[ 11, 67 ] = wave (0) : "./MITfull/elev20/L20e335a.wav"
|
||||
[ 11, 68 ] = wave (0) : "./MITfull/elev20/L20e340a.wav"
|
||||
[ 11, 69 ] = wave (0) : "./MITfull/elev20/L20e345a.wav"
|
||||
[ 11, 70 ] = wave (0) : "./MITfull/elev20/L20e350a.wav"
|
||||
[ 11, 71 ] = wave (0) : "./MITfull/elev20/L20e355a.wav"
|
||||
|
||||
[ 12, 0 ] = wave (0) : "./MITfull/elev30/L30e000a.wav"
|
||||
[ 12, 1 ] = wave (0) : "./MITfull/elev30/L30e006a.wav"
|
||||
[ 12, 2 ] = wave (0) : "./MITfull/elev30/L30e012a.wav"
|
||||
[ 12, 3 ] = wave (0) : "./MITfull/elev30/L30e018a.wav"
|
||||
[ 12, 4 ] = wave (0) : "./MITfull/elev30/L30e024a.wav"
|
||||
[ 12, 5 ] = wave (0) : "./MITfull/elev30/L30e030a.wav"
|
||||
[ 12, 6 ] = wave (0) : "./MITfull/elev30/L30e036a.wav"
|
||||
[ 12, 7 ] = wave (0) : "./MITfull/elev30/L30e042a.wav"
|
||||
[ 12, 8 ] = wave (0) : "./MITfull/elev30/L30e048a.wav"
|
||||
[ 12, 9 ] = wave (0) : "./MITfull/elev30/L30e054a.wav"
|
||||
[ 12, 10 ] = wave (0) : "./MITfull/elev30/L30e060a.wav"
|
||||
[ 12, 11 ] = wave (0) : "./MITfull/elev30/L30e066a.wav"
|
||||
[ 12, 12 ] = wave (0) : "./MITfull/elev30/L30e072a.wav"
|
||||
[ 12, 13 ] = wave (0) : "./MITfull/elev30/L30e078a.wav"
|
||||
[ 12, 14 ] = wave (0) : "./MITfull/elev30/L30e084a.wav"
|
||||
[ 12, 15 ] = wave (0) : "./MITfull/elev30/L30e090a.wav"
|
||||
[ 12, 16 ] = wave (0) : "./MITfull/elev30/L30e096a.wav"
|
||||
[ 12, 17 ] = wave (0) : "./MITfull/elev30/L30e102a.wav"
|
||||
[ 12, 18 ] = wave (0) : "./MITfull/elev30/L30e108a.wav"
|
||||
[ 12, 19 ] = wave (0) : "./MITfull/elev30/L30e114a.wav"
|
||||
[ 12, 20 ] = wave (0) : "./MITfull/elev30/L30e120a.wav"
|
||||
[ 12, 21 ] = wave (0) : "./MITfull/elev30/L30e126a.wav"
|
||||
[ 12, 22 ] = wave (0) : "./MITfull/elev30/L30e132a.wav"
|
||||
[ 12, 23 ] = wave (0) : "./MITfull/elev30/L30e138a.wav"
|
||||
[ 12, 24 ] = wave (0) : "./MITfull/elev30/L30e144a.wav"
|
||||
[ 12, 25 ] = wave (0) : "./MITfull/elev30/L30e150a.wav"
|
||||
[ 12, 26 ] = wave (0) : "./MITfull/elev30/L30e156a.wav"
|
||||
[ 12, 27 ] = wave (0) : "./MITfull/elev30/L30e162a.wav"
|
||||
[ 12, 28 ] = wave (0) : "./MITfull/elev30/L30e168a.wav"
|
||||
[ 12, 29 ] = wave (0) : "./MITfull/elev30/L30e174a.wav"
|
||||
[ 12, 30 ] = wave (0) : "./MITfull/elev30/L30e180a.wav"
|
||||
[ 12, 31 ] = wave (0) : "./MITfull/elev30/L30e186a.wav"
|
||||
[ 12, 32 ] = wave (0) : "./MITfull/elev30/L30e192a.wav"
|
||||
[ 12, 33 ] = wave (0) : "./MITfull/elev30/L30e198a.wav"
|
||||
[ 12, 34 ] = wave (0) : "./MITfull/elev30/L30e204a.wav"
|
||||
[ 12, 35 ] = wave (0) : "./MITfull/elev30/L30e210a.wav"
|
||||
[ 12, 36 ] = wave (0) : "./MITfull/elev30/L30e216a.wav"
|
||||
[ 12, 37 ] = wave (0) : "./MITfull/elev30/L30e222a.wav"
|
||||
[ 12, 38 ] = wave (0) : "./MITfull/elev30/L30e228a.wav"
|
||||
[ 12, 39 ] = wave (0) : "./MITfull/elev30/L30e234a.wav"
|
||||
[ 12, 40 ] = wave (0) : "./MITfull/elev30/L30e240a.wav"
|
||||
[ 12, 41 ] = wave (0) : "./MITfull/elev30/L30e246a.wav"
|
||||
[ 12, 42 ] = wave (0) : "./MITfull/elev30/L30e252a.wav"
|
||||
[ 12, 43 ] = wave (0) : "./MITfull/elev30/L30e258a.wav"
|
||||
[ 12, 44 ] = wave (0) : "./MITfull/elev30/L30e264a.wav"
|
||||
[ 12, 45 ] = wave (0) : "./MITfull/elev30/L30e270a.wav"
|
||||
[ 12, 46 ] = wave (0) : "./MITfull/elev30/L30e276a.wav"
|
||||
[ 12, 47 ] = wave (0) : "./MITfull/elev30/L30e282a.wav"
|
||||
[ 12, 48 ] = wave (0) : "./MITfull/elev30/L30e288a.wav"
|
||||
[ 12, 49 ] = wave (0) : "./MITfull/elev30/L30e294a.wav"
|
||||
[ 12, 50 ] = wave (0) : "./MITfull/elev30/L30e300a.wav"
|
||||
[ 12, 51 ] = wave (0) : "./MITfull/elev30/L30e306a.wav"
|
||||
[ 12, 52 ] = wave (0) : "./MITfull/elev30/L30e312a.wav"
|
||||
[ 12, 53 ] = wave (0) : "./MITfull/elev30/L30e318a.wav"
|
||||
[ 12, 54 ] = wave (0) : "./MITfull/elev30/L30e324a.wav"
|
||||
[ 12, 55 ] = wave (0) : "./MITfull/elev30/L30e330a.wav"
|
||||
[ 12, 56 ] = wave (0) : "./MITfull/elev30/L30e336a.wav"
|
||||
[ 12, 57 ] = wave (0) : "./MITfull/elev30/L30e342a.wav"
|
||||
[ 12, 58 ] = wave (0) : "./MITfull/elev30/L30e348a.wav"
|
||||
[ 12, 59 ] = wave (0) : "./MITfull/elev30/L30e354a.wav"
|
||||
|
||||
[ 13, 0 ] = wave (0) : "./MITfull/elev40/L40e000a.wav"
|
||||
[ 13, 1 ] = wave (0) : "./MITfull/elev40/L40e006a.wav"
|
||||
[ 13, 2 ] = wave (0) : "./MITfull/elev40/L40e013a.wav"
|
||||
[ 13, 3 ] = wave (0) : "./MITfull/elev40/L40e019a.wav"
|
||||
[ 13, 4 ] = wave (0) : "./MITfull/elev40/L40e026a.wav"
|
||||
[ 13, 5 ] = wave (0) : "./MITfull/elev40/L40e032a.wav"
|
||||
[ 13, 6 ] = wave (0) : "./MITfull/elev40/L40e039a.wav"
|
||||
[ 13, 7 ] = wave (0) : "./MITfull/elev40/L40e045a.wav"
|
||||
[ 13, 8 ] = wave (0) : "./MITfull/elev40/L40e051a.wav"
|
||||
[ 13, 9 ] = wave (0) : "./MITfull/elev40/L40e058a.wav"
|
||||
[ 13, 10 ] = wave (0) : "./MITfull/elev40/L40e064a.wav"
|
||||
[ 13, 11 ] = wave (0) : "./MITfull/elev40/L40e071a.wav"
|
||||
[ 13, 12 ] = wave (0) : "./MITfull/elev40/L40e077a.wav"
|
||||
[ 13, 13 ] = wave (0) : "./MITfull/elev40/L40e084a.wav"
|
||||
[ 13, 14 ] = wave (0) : "./MITfull/elev40/L40e090a.wav"
|
||||
[ 13, 15 ] = wave (0) : "./MITfull/elev40/L40e096a.wav"
|
||||
[ 13, 16 ] = wave (0) : "./MITfull/elev40/L40e103a.wav"
|
||||
[ 13, 17 ] = wave (0) : "./MITfull/elev40/L40e109a.wav"
|
||||
[ 13, 18 ] = wave (0) : "./MITfull/elev40/L40e116a.wav"
|
||||
[ 13, 19 ] = wave (0) : "./MITfull/elev40/L40e122a.wav"
|
||||
[ 13, 20 ] = wave (0) : "./MITfull/elev40/L40e129a.wav"
|
||||
[ 13, 21 ] = wave (0) : "./MITfull/elev40/L40e135a.wav"
|
||||
[ 13, 22 ] = wave (0) : "./MITfull/elev40/L40e141a.wav"
|
||||
[ 13, 23 ] = wave (0) : "./MITfull/elev40/L40e148a.wav"
|
||||
[ 13, 24 ] = wave (0) : "./MITfull/elev40/L40e154a.wav"
|
||||
[ 13, 25 ] = wave (0) : "./MITfull/elev40/L40e161a.wav"
|
||||
[ 13, 26 ] = wave (0) : "./MITfull/elev40/L40e167a.wav"
|
||||
[ 13, 27 ] = wave (0) : "./MITfull/elev40/L40e174a.wav"
|
||||
[ 13, 28 ] = wave (0) : "./MITfull/elev40/L40e180a.wav"
|
||||
[ 13, 29 ] = wave (0) : "./MITfull/elev40/L40e186a.wav"
|
||||
[ 13, 30 ] = wave (0) : "./MITfull/elev40/L40e193a.wav"
|
||||
[ 13, 31 ] = wave (0) : "./MITfull/elev40/L40e199a.wav"
|
||||
[ 13, 32 ] = wave (0) : "./MITfull/elev40/L40e206a.wav"
|
||||
[ 13, 33 ] = wave (0) : "./MITfull/elev40/L40e212a.wav"
|
||||
[ 13, 34 ] = wave (0) : "./MITfull/elev40/L40e219a.wav"
|
||||
[ 13, 35 ] = wave (0) : "./MITfull/elev40/L40e225a.wav"
|
||||
[ 13, 36 ] = wave (0) : "./MITfull/elev40/L40e231a.wav"
|
||||
[ 13, 37 ] = wave (0) : "./MITfull/elev40/L40e238a.wav"
|
||||
[ 13, 38 ] = wave (0) : "./MITfull/elev40/L40e244a.wav"
|
||||
[ 13, 39 ] = wave (0) : "./MITfull/elev40/L40e251a.wav"
|
||||
[ 13, 40 ] = wave (0) : "./MITfull/elev40/L40e257a.wav"
|
||||
[ 13, 41 ] = wave (0) : "./MITfull/elev40/L40e264a.wav"
|
||||
[ 13, 42 ] = wave (0) : "./MITfull/elev40/L40e270a.wav"
|
||||
[ 13, 43 ] = wave (0) : "./MITfull/elev40/L40e276a.wav"
|
||||
[ 13, 44 ] = wave (0) : "./MITfull/elev40/L40e283a.wav"
|
||||
[ 13, 45 ] = wave (0) : "./MITfull/elev40/L40e289a.wav"
|
||||
[ 13, 46 ] = wave (0) : "./MITfull/elev40/L40e296a.wav"
|
||||
[ 13, 47 ] = wave (0) : "./MITfull/elev40/L40e302a.wav"
|
||||
[ 13, 48 ] = wave (0) : "./MITfull/elev40/L40e309a.wav"
|
||||
[ 13, 49 ] = wave (0) : "./MITfull/elev40/L40e315a.wav"
|
||||
[ 13, 50 ] = wave (0) : "./MITfull/elev40/L40e321a.wav"
|
||||
[ 13, 51 ] = wave (0) : "./MITfull/elev40/L40e328a.wav"
|
||||
[ 13, 52 ] = wave (0) : "./MITfull/elev40/L40e334a.wav"
|
||||
[ 13, 53 ] = wave (0) : "./MITfull/elev40/L40e341a.wav"
|
||||
[ 13, 54 ] = wave (0) : "./MITfull/elev40/L40e347a.wav"
|
||||
[ 13, 55 ] = wave (0) : "./MITfull/elev40/L40e354a.wav"
|
||||
|
||||
[ 14, 0 ] = wave (0) : "./MITfull/elev50/L50e000a.wav"
|
||||
[ 14, 1 ] = wave (0) : "./MITfull/elev50/L50e008a.wav"
|
||||
[ 14, 2 ] = wave (0) : "./MITfull/elev50/L50e016a.wav"
|
||||
[ 14, 3 ] = wave (0) : "./MITfull/elev50/L50e024a.wav"
|
||||
[ 14, 4 ] = wave (0) : "./MITfull/elev50/L50e032a.wav"
|
||||
[ 14, 5 ] = wave (0) : "./MITfull/elev50/L50e040a.wav"
|
||||
[ 14, 6 ] = wave (0) : "./MITfull/elev50/L50e048a.wav"
|
||||
[ 14, 7 ] = wave (0) : "./MITfull/elev50/L50e056a.wav"
|
||||
[ 14, 8 ] = wave (0) : "./MITfull/elev50/L50e064a.wav"
|
||||
[ 14, 9 ] = wave (0) : "./MITfull/elev50/L50e072a.wav"
|
||||
[ 14, 10 ] = wave (0) : "./MITfull/elev50/L50e080a.wav"
|
||||
[ 14, 11 ] = wave (0) : "./MITfull/elev50/L50e088a.wav"
|
||||
[ 14, 12 ] = wave (0) : "./MITfull/elev50/L50e096a.wav"
|
||||
[ 14, 13 ] = wave (0) : "./MITfull/elev50/L50e104a.wav"
|
||||
[ 14, 14 ] = wave (0) : "./MITfull/elev50/L50e112a.wav"
|
||||
[ 14, 15 ] = wave (0) : "./MITfull/elev50/L50e120a.wav"
|
||||
[ 14, 16 ] = wave (0) : "./MITfull/elev50/L50e128a.wav"
|
||||
[ 14, 17 ] = wave (0) : "./MITfull/elev50/L50e136a.wav"
|
||||
[ 14, 18 ] = wave (0) : "./MITfull/elev50/L50e144a.wav"
|
||||
[ 14, 19 ] = wave (0) : "./MITfull/elev50/L50e152a.wav"
|
||||
[ 14, 20 ] = wave (0) : "./MITfull/elev50/L50e160a.wav"
|
||||
[ 14, 21 ] = wave (0) : "./MITfull/elev50/L50e168a.wav"
|
||||
[ 14, 22 ] = wave (0) : "./MITfull/elev50/L50e176a.wav"
|
||||
[ 14, 23 ] = wave (0) : "./MITfull/elev50/L50e184a.wav"
|
||||
[ 14, 24 ] = wave (0) : "./MITfull/elev50/L50e192a.wav"
|
||||
[ 14, 25 ] = wave (0) : "./MITfull/elev50/L50e200a.wav"
|
||||
[ 14, 26 ] = wave (0) : "./MITfull/elev50/L50e208a.wav"
|
||||
[ 14, 27 ] = wave (0) : "./MITfull/elev50/L50e216a.wav"
|
||||
[ 14, 28 ] = wave (0) : "./MITfull/elev50/L50e224a.wav"
|
||||
[ 14, 29 ] = wave (0) : "./MITfull/elev50/L50e232a.wav"
|
||||
[ 14, 30 ] = wave (0) : "./MITfull/elev50/L50e240a.wav"
|
||||
[ 14, 31 ] = wave (0) : "./MITfull/elev50/L50e248a.wav"
|
||||
[ 14, 32 ] = wave (0) : "./MITfull/elev50/L50e256a.wav"
|
||||
[ 14, 33 ] = wave (0) : "./MITfull/elev50/L50e264a.wav"
|
||||
[ 14, 34 ] = wave (0) : "./MITfull/elev50/L50e272a.wav"
|
||||
[ 14, 35 ] = wave (0) : "./MITfull/elev50/L50e280a.wav"
|
||||
[ 14, 36 ] = wave (0) : "./MITfull/elev50/L50e288a.wav"
|
||||
[ 14, 37 ] = wave (0) : "./MITfull/elev50/L50e296a.wav"
|
||||
[ 14, 38 ] = wave (0) : "./MITfull/elev50/L50e304a.wav"
|
||||
[ 14, 39 ] = wave (0) : "./MITfull/elev50/L50e312a.wav"
|
||||
[ 14, 40 ] = wave (0) : "./MITfull/elev50/L50e320a.wav"
|
||||
[ 14, 41 ] = wave (0) : "./MITfull/elev50/L50e328a.wav"
|
||||
[ 14, 42 ] = wave (0) : "./MITfull/elev50/L50e336a.wav"
|
||||
[ 14, 43 ] = wave (0) : "./MITfull/elev50/L50e344a.wav"
|
||||
[ 14, 44 ] = wave (0) : "./MITfull/elev50/L50e352a.wav"
|
||||
|
||||
[ 15, 0 ] = wave (0) : "./MITfull/elev60/L60e000a.wav"
|
||||
[ 15, 1 ] = wave (0) : "./MITfull/elev60/L60e010a.wav"
|
||||
[ 15, 2 ] = wave (0) : "./MITfull/elev60/L60e020a.wav"
|
||||
[ 15, 3 ] = wave (0) : "./MITfull/elev60/L60e030a.wav"
|
||||
[ 15, 4 ] = wave (0) : "./MITfull/elev60/L60e040a.wav"
|
||||
[ 15, 5 ] = wave (0) : "./MITfull/elev60/L60e050a.wav"
|
||||
[ 15, 6 ] = wave (0) : "./MITfull/elev60/L60e060a.wav"
|
||||
[ 15, 7 ] = wave (0) : "./MITfull/elev60/L60e070a.wav"
|
||||
[ 15, 8 ] = wave (0) : "./MITfull/elev60/L60e080a.wav"
|
||||
[ 15, 9 ] = wave (0) : "./MITfull/elev60/L60e090a.wav"
|
||||
[ 15, 10 ] = wave (0) : "./MITfull/elev60/L60e100a.wav"
|
||||
[ 15, 11 ] = wave (0) : "./MITfull/elev60/L60e110a.wav"
|
||||
[ 15, 12 ] = wave (0) : "./MITfull/elev60/L60e120a.wav"
|
||||
[ 15, 13 ] = wave (0) : "./MITfull/elev60/L60e130a.wav"
|
||||
[ 15, 14 ] = wave (0) : "./MITfull/elev60/L60e140a.wav"
|
||||
[ 15, 15 ] = wave (0) : "./MITfull/elev60/L60e150a.wav"
|
||||
[ 15, 16 ] = wave (0) : "./MITfull/elev60/L60e160a.wav"
|
||||
[ 15, 17 ] = wave (0) : "./MITfull/elev60/L60e170a.wav"
|
||||
[ 15, 18 ] = wave (0) : "./MITfull/elev60/L60e180a.wav"
|
||||
[ 15, 19 ] = wave (0) : "./MITfull/elev60/L60e190a.wav"
|
||||
[ 15, 20 ] = wave (0) : "./MITfull/elev60/L60e200a.wav"
|
||||
[ 15, 21 ] = wave (0) : "./MITfull/elev60/L60e210a.wav"
|
||||
[ 15, 22 ] = wave (0) : "./MITfull/elev60/L60e220a.wav"
|
||||
[ 15, 23 ] = wave (0) : "./MITfull/elev60/L60e230a.wav"
|
||||
[ 15, 24 ] = wave (0) : "./MITfull/elev60/L60e240a.wav"
|
||||
[ 15, 25 ] = wave (0) : "./MITfull/elev60/L60e250a.wav"
|
||||
[ 15, 26 ] = wave (0) : "./MITfull/elev60/L60e260a.wav"
|
||||
[ 15, 27 ] = wave (0) : "./MITfull/elev60/L60e270a.wav"
|
||||
[ 15, 28 ] = wave (0) : "./MITfull/elev60/L60e280a.wav"
|
||||
[ 15, 29 ] = wave (0) : "./MITfull/elev60/L60e290a.wav"
|
||||
[ 15, 30 ] = wave (0) : "./MITfull/elev60/L60e300a.wav"
|
||||
[ 15, 31 ] = wave (0) : "./MITfull/elev60/L60e310a.wav"
|
||||
[ 15, 32 ] = wave (0) : "./MITfull/elev60/L60e320a.wav"
|
||||
[ 15, 33 ] = wave (0) : "./MITfull/elev60/L60e330a.wav"
|
||||
[ 15, 34 ] = wave (0) : "./MITfull/elev60/L60e340a.wav"
|
||||
[ 15, 35 ] = wave (0) : "./MITfull/elev60/L60e350a.wav"
|
||||
|
||||
[ 16, 0 ] = wave (0) : "./MITfull/elev70/L70e000a.wav"
|
||||
[ 16, 1 ] = wave (0) : "./MITfull/elev70/L70e015a.wav"
|
||||
[ 16, 2 ] = wave (0) : "./MITfull/elev70/L70e030a.wav"
|
||||
[ 16, 3 ] = wave (0) : "./MITfull/elev70/L70e045a.wav"
|
||||
[ 16, 4 ] = wave (0) : "./MITfull/elev70/L70e060a.wav"
|
||||
[ 16, 5 ] = wave (0) : "./MITfull/elev70/L70e075a.wav"
|
||||
[ 16, 6 ] = wave (0) : "./MITfull/elev70/L70e090a.wav"
|
||||
[ 16, 7 ] = wave (0) : "./MITfull/elev70/L70e105a.wav"
|
||||
[ 16, 8 ] = wave (0) : "./MITfull/elev70/L70e120a.wav"
|
||||
[ 16, 9 ] = wave (0) : "./MITfull/elev70/L70e135a.wav"
|
||||
[ 16, 10 ] = wave (0) : "./MITfull/elev70/L70e150a.wav"
|
||||
[ 16, 11 ] = wave (0) : "./MITfull/elev70/L70e165a.wav"
|
||||
[ 16, 12 ] = wave (0) : "./MITfull/elev70/L70e180a.wav"
|
||||
[ 16, 13 ] = wave (0) : "./MITfull/elev70/L70e195a.wav"
|
||||
[ 16, 14 ] = wave (0) : "./MITfull/elev70/L70e210a.wav"
|
||||
[ 16, 15 ] = wave (0) : "./MITfull/elev70/L70e225a.wav"
|
||||
[ 16, 16 ] = wave (0) : "./MITfull/elev70/L70e240a.wav"
|
||||
[ 16, 17 ] = wave (0) : "./MITfull/elev70/L70e255a.wav"
|
||||
[ 16, 18 ] = wave (0) : "./MITfull/elev70/L70e270a.wav"
|
||||
[ 16, 19 ] = wave (0) : "./MITfull/elev70/L70e285a.wav"
|
||||
[ 16, 20 ] = wave (0) : "./MITfull/elev70/L70e300a.wav"
|
||||
[ 16, 21 ] = wave (0) : "./MITfull/elev70/L70e315a.wav"
|
||||
[ 16, 22 ] = wave (0) : "./MITfull/elev70/L70e330a.wav"
|
||||
[ 16, 23 ] = wave (0) : "./MITfull/elev70/L70e345a.wav"
|
||||
|
||||
[ 17, 0 ] = wave (0) : "./MITfull/elev80/L80e000a.wav"
|
||||
[ 17, 1 ] = wave (0) : "./MITfull/elev80/L80e030a.wav"
|
||||
[ 17, 2 ] = wave (0) : "./MITfull/elev80/L80e060a.wav"
|
||||
[ 17, 3 ] = wave (0) : "./MITfull/elev80/L80e090a.wav"
|
||||
[ 17, 4 ] = wave (0) : "./MITfull/elev80/L80e120a.wav"
|
||||
[ 17, 5 ] = wave (0) : "./MITfull/elev80/L80e150a.wav"
|
||||
[ 17, 6 ] = wave (0) : "./MITfull/elev80/L80e180a.wav"
|
||||
[ 17, 7 ] = wave (0) : "./MITfull/elev80/L80e210a.wav"
|
||||
[ 17, 8 ] = wave (0) : "./MITfull/elev80/L80e240a.wav"
|
||||
[ 17, 9 ] = wave (0) : "./MITfull/elev80/L80e270a.wav"
|
||||
[ 17, 10 ] = wave (0) : "./MITfull/elev80/L80e300a.wav"
|
||||
[ 17, 11 ] = wave (0) : "./MITfull/elev80/L80e330a.wav"
|
||||
|
||||
[ 18, 0 ] = wave (0) : "./MITfull/elev90/L90e000a.wav"
|
||||
|
@ -1,51 +0,0 @@
|
||||
# This is a makemhr HRIR definition file. It is used to define the layout and
|
||||
# source data to be processed into an OpenAL Soft compatible HRTF.
|
||||
#
|
||||
# This definition is used to transform the SOFA packaged KEMAR HRIRs
|
||||
# originally provided by Bill Gardner <billg@media.mit.edu> and Keith Martin
|
||||
# <kdm@media.mit.edu> of MIT Media Laboratory.
|
||||
#
|
||||
# The SOFA conversion is available from:
|
||||
#
|
||||
# http://sofacoustics.org/data/database/mit/
|
||||
#
|
||||
# The original data is available from:
|
||||
#
|
||||
# http://sound.media.mit.edu/resources/KEMAR.html
|
||||
#
|
||||
# It is copyrighted 1994 by MIT Media Laboratory, and provided free of charge
|
||||
# with no restrictions on use so long as the authors (above) are cited.
|
||||
|
||||
# Sampling rate of the HRIR data (in hertz).
|
||||
rate = 44100
|
||||
|
||||
# The SOFA file is stereo, but the original data was mono. Channels are just
|
||||
# mirrored by azimuth; so save some memory by allowing OpenAL Soft to mirror
|
||||
# them at run time.
|
||||
type = mono
|
||||
|
||||
points = 512
|
||||
|
||||
radius = 0.09
|
||||
|
||||
# The MIT set has only one field with a distance of 1.4m.
|
||||
distance = 1.4
|
||||
|
||||
# The MIT set varies the number of azimuths for each elevation to maintain
|
||||
# an average distance between them.
|
||||
azimuths = 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1
|
||||
|
||||
# Normally the dataset would be composed manually by listing all necessary
|
||||
# 'sofa' sources with the appropriate radius, elevation, azimuth (counter-
|
||||
# clockwise for SOFA files) and receiver arguments:
|
||||
#
|
||||
# [ 5, 0 ] = sofa (1.4, -40.0, 0.0 : 0) : "./mit_kemar_normal_pinna.sofa"
|
||||
# [ 5, 1 ] = sofa (1.4, -40.0, 353.6 : 0) : "./mit_kemar_normal_pinna.sofa"
|
||||
# [ 5, 2 ] = sofa (1.4, -40.0, 347.1 : 0) : "./mit_kemar_normal_pinna.sofa"
|
||||
# [ 5, 3 ] = sofa (1.4, -40.0, 340.7 : 0) : "./mit_kemar_normal_pinna.sofa"
|
||||
# ...
|
||||
#
|
||||
# If HRIR composition isn't necessary, it's easier to just use the following:
|
||||
|
||||
[ * ] = sofa : "./mit_kemar_normal_pinna.sofa" mono
|
||||
|
@ -1,48 +0,0 @@
|
||||
# This is a makemhr HRIR definition file. It is used to define the layout and
|
||||
# source data to be processed into an OpenAL Soft compatible HRTF.
|
||||
#
|
||||
# This definition is used to transform the near-field KEMAR HRIRs provided by
|
||||
# Bosun Xie <phbsxie@scut.edu.cn> of the South China University of
|
||||
# Technology, Guangzhou, China; and converted from SCUT to SOFA format by
|
||||
# Piotr Majdak <piotr@majdak.com> of the Acoustics Research Institute,
|
||||
# Austrian Academy of Sciences.
|
||||
#
|
||||
# A copy of the data (SCUT_KEMAR_radius_all.sofa) is available from:
|
||||
#
|
||||
# http://sofacoustics.org/data/database/scut/SCUT_KEMAR_radius_all.sofa
|
||||
#
|
||||
# It is provided under the Creative Commons CC 3.0 BY-SA-NC license:
|
||||
#
|
||||
# https://creativecommons.org/licenses/by-nc-sa/3.0/
|
||||
|
||||
rate = 44100
|
||||
|
||||
# While the SOFA file is stereo, doubling the size of the data set will cause
|
||||
# the utility to exhaust its address space if compiled 32-bit. Since the
|
||||
# dummy head is symmetric, the same results (ignoring variations caused by
|
||||
# measurement error) can be obtained using mono channel processing.
|
||||
type = mono
|
||||
|
||||
points = 512
|
||||
|
||||
radius = 0.09
|
||||
|
||||
# This data set has 10 fields ranging from 0.2m to 1m. The layout was
|
||||
# obtained using the sofa-info utility.
|
||||
distance = 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0
|
||||
|
||||
azimuths = 1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1;
|
||||
1, 24, 36, 72, 72, 72, 72, 72, 72, 72, 36, 24, 1
|
||||
|
||||
# Given the above compatible layout, we can automatically process the entire
|
||||
# data set.
|
||||
[ * ] = sofa : "./SCUT_KEMAR_radius_all.sofa" mono
|
||||
|
@ -1,32 +0,0 @@
|
||||
project(alsoft-config)
|
||||
|
||||
if(Qt5Widgets_FOUND)
|
||||
qt5_wrap_ui(UIS mainwindow.ui)
|
||||
|
||||
qt5_wrap_cpp(MOCS mainwindow.h)
|
||||
|
||||
add_executable(alsoft-config
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
verstr.cpp
|
||||
verstr.h
|
||||
${UIS} ${RSCS} ${TRS} ${MOCS})
|
||||
target_link_libraries(alsoft-config Qt5::Widgets)
|
||||
target_include_directories(alsoft-config PRIVATE "${alsoft-config_BINARY_DIR}"
|
||||
"${OpenAL_BINARY_DIR}")
|
||||
set_target_properties(alsoft-config PROPERTIES ${DEFAULT_TARGET_PROPS}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${OpenAL_BINARY_DIR})
|
||||
if(TARGET build_version)
|
||||
add_dependencies(alsoft-config build_version)
|
||||
endif()
|
||||
|
||||
message(STATUS "Building configuration program")
|
||||
|
||||
if(ALSOFT_INSTALL_UTILS)
|
||||
install(TARGETS alsoft-config
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
endif()
|
@ -1,11 +0,0 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,86 +0,0 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QListWidget>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
private slots:
|
||||
void cancelCloseAction();
|
||||
|
||||
void saveCurrentConfig();
|
||||
|
||||
void saveConfigAsFile();
|
||||
void loadConfigFromFile();
|
||||
|
||||
void showAboutPage();
|
||||
|
||||
void enableApplyButton();
|
||||
|
||||
void updateResamplerLabel(int num);
|
||||
|
||||
void updatePeriodSizeEdit(int size);
|
||||
void updatePeriodSizeSlider();
|
||||
void updatePeriodCountEdit(int size);
|
||||
void updatePeriodCountSlider();
|
||||
|
||||
void selectQuadDecoderFile();
|
||||
void select51DecoderFile();
|
||||
void select61DecoderFile();
|
||||
void select71DecoderFile();
|
||||
void select3D71DecoderFile();
|
||||
|
||||
void updateJackBufferSizeEdit(int size);
|
||||
void updateJackBufferSizeSlider();
|
||||
|
||||
void updateHrtfModeLabel(int num);
|
||||
void addHrtfFile();
|
||||
void removeHrtfFile();
|
||||
|
||||
void updateHrtfRemoveButton();
|
||||
|
||||
void showEnabledBackendMenu(QPoint pt);
|
||||
void showDisabledBackendMenu(QPoint pt);
|
||||
|
||||
void selectOSSPlayback();
|
||||
void selectOSSCapture();
|
||||
|
||||
void selectSolarisPlayback();
|
||||
|
||||
void selectWaveOutput();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
QValidator *mPeriodSizeValidator;
|
||||
QValidator *mPeriodCountValidator;
|
||||
QValidator *mSourceCountValidator;
|
||||
QValidator *mEffectSlotValidator;
|
||||
QValidator *mSourceSendValidator;
|
||||
QValidator *mSampleRateValidator;
|
||||
QValidator *mJackBufferValidator;
|
||||
|
||||
bool mNeedsSave;
|
||||
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
void selectDecoderFile(QLineEdit *line, const char *name);
|
||||
|
||||
QStringList collectHrtfs();
|
||||
|
||||
void loadConfig(const QString &fname);
|
||||
void saveConfig(const QString &fname) const;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +0,0 @@
|
||||
|
||||
#include "verstr.h"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
|
||||
QString GetVersionString()
|
||||
{
|
||||
return QStringLiteral(ALSOFT_VERSION "-" ALSOFT_GIT_COMMIT_HASH " (" ALSOFT_GIT_BRANCH " branch).");
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef VERSTR_H
|
||||
#define VERSTR_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
QString GetVersionString();
|
||||
|
||||
#endif /* VERSTR_H */
|
137
utils/getopt.c
137
utils/getopt.c
@ -1,137 +0,0 @@
|
||||
/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "getopt.h"
|
||||
|
||||
int opterr = 1, /* if error message should be printed */
|
||||
optind = 1, /* index into parent argv vector */
|
||||
optopt, /* character checked for validity */
|
||||
optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG (int)':'
|
||||
#define EMSG ""
|
||||
|
||||
/*
|
||||
* Get program name in Windows
|
||||
*/
|
||||
const char * _getprogname(void);
|
||||
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt(int nargc, char * const nargv[], const char *ostr)
|
||||
{
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
char *oli; /* option letter list index */
|
||||
|
||||
if (optreset || *place == 0) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
place = nargv[optind];
|
||||
if (optind >= nargc || *place++ != '-') {
|
||||
/* Argument is absent or is not an option */
|
||||
place = EMSG;
|
||||
return (-1);
|
||||
}
|
||||
optopt = *place++;
|
||||
if (optopt == '-' && *place == 0) {
|
||||
/* "--" => end of options */
|
||||
++optind;
|
||||
place = EMSG;
|
||||
return (-1);
|
||||
}
|
||||
if (optopt == 0) {
|
||||
/* Solitary '-', treat as a '-' option
|
||||
if the program (eg su) is looking for it. */
|
||||
place = EMSG;
|
||||
if (strchr(ostr, '-') == NULL)
|
||||
return (-1);
|
||||
optopt = '-';
|
||||
}
|
||||
} else
|
||||
optopt = *place++;
|
||||
|
||||
/* See if option letter is one the caller wanted... */
|
||||
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
|
||||
if (*place == 0)
|
||||
++optind;
|
||||
if (opterr && *ostr != ':')
|
||||
(void)fprintf(stderr,
|
||||
"%s: illegal option -- %c\n", _getprogname(),
|
||||
optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
|
||||
/* Does this option need an argument? */
|
||||
if (oli[1] != ':') {
|
||||
/* don't need argument */
|
||||
optarg = NULL;
|
||||
if (*place == 0)
|
||||
++optind;
|
||||
} else {
|
||||
/* Option-argument is either the rest of this argument or the
|
||||
entire next argument. */
|
||||
if (*place)
|
||||
optarg = place;
|
||||
else if (nargc > ++optind)
|
||||
optarg = nargv[optind];
|
||||
else {
|
||||
/* option-argument absent */
|
||||
place = EMSG;
|
||||
if (*ostr == ':')
|
||||
return (BADARG);
|
||||
if (opterr)
|
||||
(void)fprintf(stderr,
|
||||
"%s: option requires an argument -- %c\n",
|
||||
_getprogname(), optopt);
|
||||
return (BADCH);
|
||||
}
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
return (optopt); /* return option letter */
|
||||
}
|
||||
|
||||
const char * _getprogname() {
|
||||
char *pgmptr = NULL;
|
||||
_get_pgmptr(&pgmptr);
|
||||
return strrchr(pgmptr,'\\')+1;
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
#ifndef GETOPT_H
|
||||
#define GETOPT_H
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt, optreset;
|
||||
|
||||
int getopt(int nargc, char * const nargv[], const char *ostr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
#endif /* !GETOPT_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
||||
#ifndef LOADDEF_H
|
||||
#define LOADDEF_H
|
||||
|
||||
#include <istream>
|
||||
|
||||
#include "makemhr.h"
|
||||
|
||||
|
||||
bool LoadDefInput(std::istream &istream, const char *startbytes, std::streamsize startbytecount,
|
||||
const char *filename, const uint fftSize, const uint truncSize, const uint outRate,
|
||||
const ChannelModeT chanMode, HrirDataT *hData);
|
||||
|
||||
#endif /* LOADDEF_H */
|
@ -1,603 +0,0 @@
|
||||
/*
|
||||
* HRTF utility for producing and demonstrating the process of creating an
|
||||
* OpenAL Soft compatible HRIR data set.
|
||||
*
|
||||
* Copyright (C) 2018-2019 Christopher Fitzgerald
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Or visit: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#include "loadsofa.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "aloptional.h"
|
||||
#include "alspan.h"
|
||||
#include "makemhr.h"
|
||||
#include "polyphase_resampler.h"
|
||||
#include "sofa-support.h"
|
||||
|
||||
#include "mysofa.h"
|
||||
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
/* Attempts to produce a compatible layout. Most data sets tend to be
|
||||
* uniform and have the same major axis as used by OpenAL Soft's HRTF model.
|
||||
* This will remove outliers and produce a maximally dense layout when
|
||||
* possible. Those sets that contain purely random measurements or use
|
||||
* different major axes will fail.
|
||||
*/
|
||||
static bool PrepareLayout(const uint m, const float *xyzs, HrirDataT *hData)
|
||||
{
|
||||
fprintf(stdout, "Detecting compatible layout...\n");
|
||||
|
||||
auto fds = GetCompatibleLayout(m, xyzs);
|
||||
if(fds.size() > MAX_FD_COUNT)
|
||||
{
|
||||
fprintf(stdout, "Incompatible layout (inumerable radii).\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
double distances[MAX_FD_COUNT]{};
|
||||
uint evCounts[MAX_FD_COUNT]{};
|
||||
auto azCounts = std::vector<std::array<uint,MAX_EV_COUNT>>(MAX_FD_COUNT);
|
||||
for(auto &azs : azCounts) azs.fill(0u);
|
||||
|
||||
uint fi{0u}, ir_total{0u};
|
||||
for(const auto &field : fds)
|
||||
{
|
||||
distances[fi] = field.mDistance;
|
||||
evCounts[fi] = field.mEvCount;
|
||||
|
||||
for(uint ei{0u};ei < field.mEvStart;ei++)
|
||||
azCounts[fi][ei] = field.mAzCounts[field.mEvCount-ei-1];
|
||||
for(uint ei{field.mEvStart};ei < field.mEvCount;ei++)
|
||||
{
|
||||
azCounts[fi][ei] = field.mAzCounts[ei];
|
||||
ir_total += field.mAzCounts[ei];
|
||||
}
|
||||
|
||||
++fi;
|
||||
}
|
||||
fprintf(stdout, "Using %u of %u IRs.\n", ir_total, m);
|
||||
const auto azs = al::as_span(azCounts).first<MAX_FD_COUNT>();
|
||||
return PrepareHrirData({distances, fi}, evCounts, azs, hData);
|
||||
}
|
||||
|
||||
|
||||
float GetSampleRate(MYSOFA_HRTF *sofaHrtf)
|
||||
{
|
||||
const char *srate_dim{nullptr};
|
||||
const char *srate_units{nullptr};
|
||||
MYSOFA_ARRAY *srate_array{&sofaHrtf->DataSamplingRate};
|
||||
MYSOFA_ATTRIBUTE *srate_attrs{srate_array->attributes};
|
||||
while(srate_attrs)
|
||||
{
|
||||
if(std::string{"DIMENSION_LIST"} == srate_attrs->name)
|
||||
{
|
||||
if(srate_dim)
|
||||
{
|
||||
fprintf(stderr, "Duplicate SampleRate.DIMENSION_LIST\n");
|
||||
return 0.0f;
|
||||
}
|
||||
srate_dim = srate_attrs->value;
|
||||
}
|
||||
else if(std::string{"Units"} == srate_attrs->name)
|
||||
{
|
||||
if(srate_units)
|
||||
{
|
||||
fprintf(stderr, "Duplicate SampleRate.Units\n");
|
||||
return 0.0f;
|
||||
}
|
||||
srate_units = srate_attrs->value;
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Unexpected sample rate attribute: %s = %s\n", srate_attrs->name,
|
||||
srate_attrs->value);
|
||||
srate_attrs = srate_attrs->next;
|
||||
}
|
||||
if(!srate_dim)
|
||||
{
|
||||
fprintf(stderr, "Missing sample rate dimensions\n");
|
||||
return 0.0f;
|
||||
}
|
||||
if(srate_dim != std::string{"I"})
|
||||
{
|
||||
fprintf(stderr, "Unsupported sample rate dimensions: %s\n", srate_dim);
|
||||
return 0.0f;
|
||||
}
|
||||
if(!srate_units)
|
||||
{
|
||||
fprintf(stderr, "Missing sample rate unit type\n");
|
||||
return 0.0f;
|
||||
}
|
||||
if(srate_units != std::string{"hertz"})
|
||||
{
|
||||
fprintf(stderr, "Unsupported sample rate unit type: %s\n", srate_units);
|
||||
return 0.0f;
|
||||
}
|
||||
/* I dimensions guarantees 1 element, so just extract it. */
|
||||
if(srate_array->values[0] < MIN_RATE || srate_array->values[0] > MAX_RATE)
|
||||
{
|
||||
fprintf(stderr, "Sample rate out of range: %f (expected %u to %u)", srate_array->values[0],
|
||||
MIN_RATE, MAX_RATE);
|
||||
return 0.0f;
|
||||
}
|
||||
return srate_array->values[0];
|
||||
}
|
||||
|
||||
enum class DelayType : uint8_t {
|
||||
None,
|
||||
I_R, /* [1][Channels] */
|
||||
M_R, /* [HRIRs][Channels] */
|
||||
Invalid,
|
||||
};
|
||||
DelayType PrepareDelay(MYSOFA_HRTF *sofaHrtf)
|
||||
{
|
||||
const char *delay_dim{nullptr};
|
||||
MYSOFA_ARRAY *delay_array{&sofaHrtf->DataDelay};
|
||||
MYSOFA_ATTRIBUTE *delay_attrs{delay_array->attributes};
|
||||
while(delay_attrs)
|
||||
{
|
||||
if(std::string{"DIMENSION_LIST"} == delay_attrs->name)
|
||||
{
|
||||
if(delay_dim)
|
||||
{
|
||||
fprintf(stderr, "Duplicate Delay.DIMENSION_LIST\n");
|
||||
return DelayType::Invalid;
|
||||
}
|
||||
delay_dim = delay_attrs->value;
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Unexpected delay attribute: %s = %s\n", delay_attrs->name,
|
||||
delay_attrs->value ? delay_attrs->value : "<null>");
|
||||
delay_attrs = delay_attrs->next;
|
||||
}
|
||||
if(!delay_dim)
|
||||
{
|
||||
fprintf(stderr, "Missing delay dimensions\n");
|
||||
return DelayType::None;
|
||||
}
|
||||
if(delay_dim == std::string{"I,R"})
|
||||
return DelayType::I_R;
|
||||
else if(delay_dim == std::string{"M,R"})
|
||||
return DelayType::M_R;
|
||||
|
||||
fprintf(stderr, "Unsupported delay dimensions: %s\n", delay_dim);
|
||||
return DelayType::Invalid;
|
||||
}
|
||||
|
||||
bool CheckIrData(MYSOFA_HRTF *sofaHrtf)
|
||||
{
|
||||
const char *ir_dim{nullptr};
|
||||
MYSOFA_ARRAY *ir_array{&sofaHrtf->DataIR};
|
||||
MYSOFA_ATTRIBUTE *ir_attrs{ir_array->attributes};
|
||||
while(ir_attrs)
|
||||
{
|
||||
if(std::string{"DIMENSION_LIST"} == ir_attrs->name)
|
||||
{
|
||||
if(ir_dim)
|
||||
{
|
||||
fprintf(stderr, "Duplicate IR.DIMENSION_LIST\n");
|
||||
return false;
|
||||
}
|
||||
ir_dim = ir_attrs->value;
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Unexpected IR attribute: %s = %s\n", ir_attrs->name,
|
||||
ir_attrs->value ? ir_attrs->value : "<null>");
|
||||
ir_attrs = ir_attrs->next;
|
||||
}
|
||||
if(!ir_dim)
|
||||
{
|
||||
fprintf(stderr, "Missing IR dimensions\n");
|
||||
return false;
|
||||
}
|
||||
if(ir_dim != std::string{"M,R,N"})
|
||||
{
|
||||
fprintf(stderr, "Unsupported IR dimensions: %s\n", ir_dim);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate the onset time of a HRIR. */
|
||||
static constexpr int OnsetRateMultiple{10};
|
||||
static double CalcHrirOnset(PPhaseResampler &rs, const uint rate, const uint n,
|
||||
al::span<double> upsampled, const double *hrir)
|
||||
{
|
||||
rs.process(n, hrir, static_cast<uint>(upsampled.size()), upsampled.data());
|
||||
|
||||
auto abs_lt = [](const double &lhs, const double &rhs) -> bool
|
||||
{ return std::abs(lhs) < std::abs(rhs); };
|
||||
auto iter = std::max_element(upsampled.cbegin(), upsampled.cend(), abs_lt);
|
||||
return static_cast<double>(std::distance(upsampled.cbegin(), iter)) /
|
||||
(double{OnsetRateMultiple}*rate);
|
||||
}
|
||||
|
||||
/* Calculate the magnitude response of a HRIR. */
|
||||
static void CalcHrirMagnitude(const uint points, const uint n, al::span<complex_d> h, double *hrir)
|
||||
{
|
||||
auto iter = std::copy_n(hrir, points, h.begin());
|
||||
std::fill(iter, h.end(), complex_d{0.0, 0.0});
|
||||
|
||||
FftForward(n, h.data());
|
||||
MagnitudeResponse(n, h.data(), hrir);
|
||||
}
|
||||
|
||||
static bool LoadResponses(MYSOFA_HRTF *sofaHrtf, HrirDataT *hData, const DelayType delayType,
|
||||
const uint outRate)
|
||||
{
|
||||
std::atomic<uint> loaded_count{0u};
|
||||
|
||||
auto load_proc = [sofaHrtf,hData,delayType,outRate,&loaded_count]() -> bool
|
||||
{
|
||||
const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
|
||||
hData->mHrirsBase.resize(channels * hData->mIrCount * hData->mIrSize, 0.0);
|
||||
double *hrirs = hData->mHrirsBase.data();
|
||||
|
||||
std::unique_ptr<double[]> restmp;
|
||||
al::optional<PPhaseResampler> resampler;
|
||||
if(outRate && outRate != hData->mIrRate)
|
||||
{
|
||||
resampler.emplace().init(hData->mIrRate, outRate);
|
||||
restmp = std::make_unique<double[]>(sofaHrtf->N);
|
||||
}
|
||||
|
||||
for(uint si{0u};si < sofaHrtf->M;++si)
|
||||
{
|
||||
loaded_count.fetch_add(1u);
|
||||
|
||||
float aer[3]{
|
||||
sofaHrtf->SourcePosition.values[3*si],
|
||||
sofaHrtf->SourcePosition.values[3*si + 1],
|
||||
sofaHrtf->SourcePosition.values[3*si + 2]
|
||||
};
|
||||
mysofa_c2s(aer);
|
||||
|
||||
if(std::abs(aer[1]) >= 89.999f)
|
||||
aer[0] = 0.0f;
|
||||
else
|
||||
aer[0] = std::fmod(360.0f - aer[0], 360.0f);
|
||||
|
||||
auto field = std::find_if(hData->mFds.cbegin(), hData->mFds.cend(),
|
||||
[&aer](const HrirFdT &fld) -> bool
|
||||
{ return (std::abs(aer[2] - fld.mDistance) < 0.001); });
|
||||
if(field == hData->mFds.cend())
|
||||
continue;
|
||||
|
||||
const double evscale{180.0 / static_cast<double>(field->mEvs.size()-1)};
|
||||
double ef{(90.0 + aer[1]) / evscale};
|
||||
auto ei = static_cast<uint>(std::round(ef));
|
||||
ef = (ef - ei) * evscale;
|
||||
if(std::abs(ef) >= 0.1) continue;
|
||||
|
||||
const double azscale{360.0 / static_cast<double>(field->mEvs[ei].mAzs.size())};
|
||||
double af{aer[0] / azscale};
|
||||
auto ai = static_cast<uint>(std::round(af));
|
||||
af = (af-ai) * azscale;
|
||||
ai %= static_cast<uint>(field->mEvs[ei].mAzs.size());
|
||||
if(std::abs(af) >= 0.1) continue;
|
||||
|
||||
HrirAzT *azd = &field->mEvs[ei].mAzs[ai];
|
||||
if(azd->mIrs[0] != nullptr)
|
||||
{
|
||||
fprintf(stderr, "\nMultiple measurements near [ a=%f, e=%f, r=%f ].\n",
|
||||
aer[0], aer[1], aer[2]);
|
||||
return false;
|
||||
}
|
||||
|
||||
for(uint ti{0u};ti < channels;++ti)
|
||||
{
|
||||
azd->mIrs[ti] = &hrirs[hData->mIrSize * (hData->mIrCount*ti + azd->mIndex)];
|
||||
if(!resampler)
|
||||
std::copy_n(&sofaHrtf->DataIR.values[(si*sofaHrtf->R + ti)*sofaHrtf->N],
|
||||
sofaHrtf->N, azd->mIrs[ti]);
|
||||
else
|
||||
{
|
||||
std::copy_n(&sofaHrtf->DataIR.values[(si*sofaHrtf->R + ti)*sofaHrtf->N],
|
||||
sofaHrtf->N, restmp.get());
|
||||
resampler->process(sofaHrtf->N, restmp.get(), hData->mIrSize, azd->mIrs[ti]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Include any per-channel or per-HRIR delays. */
|
||||
if(delayType == DelayType::I_R)
|
||||
{
|
||||
const float *delayValues{sofaHrtf->DataDelay.values};
|
||||
for(uint ti{0u};ti < channels;++ti)
|
||||
azd->mDelays[ti] = delayValues[ti] / static_cast<float>(hData->mIrRate);
|
||||
}
|
||||
else if(delayType == DelayType::M_R)
|
||||
{
|
||||
const float *delayValues{sofaHrtf->DataDelay.values};
|
||||
for(uint ti{0u};ti < channels;++ti)
|
||||
azd->mDelays[ti] = delayValues[si*sofaHrtf->R + ti] /
|
||||
static_cast<float>(hData->mIrRate);
|
||||
}
|
||||
}
|
||||
|
||||
if(outRate && outRate != hData->mIrRate)
|
||||
{
|
||||
const double scale{static_cast<double>(outRate) / hData->mIrRate};
|
||||
hData->mIrRate = outRate;
|
||||
hData->mIrPoints = std::min(static_cast<uint>(std::ceil(hData->mIrPoints*scale)),
|
||||
hData->mIrSize);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
std::future_status load_status{};
|
||||
auto load_future = std::async(std::launch::async, load_proc);
|
||||
do {
|
||||
load_status = load_future.wait_for(std::chrono::milliseconds{50});
|
||||
printf("\rLoading HRIRs... %u of %u", loaded_count.load(), sofaHrtf->M);
|
||||
fflush(stdout);
|
||||
} while(load_status != std::future_status::ready);
|
||||
fputc('\n', stdout);
|
||||
return load_future.get();
|
||||
}
|
||||
|
||||
|
||||
/* Calculates the frequency magnitudes of the HRIR set. Work is delegated to
|
||||
* this struct, which runs asynchronously on one or more threads (sharing the
|
||||
* same calculator object).
|
||||
*/
|
||||
struct MagCalculator {
|
||||
const uint mFftSize{};
|
||||
const uint mIrPoints{};
|
||||
std::vector<double*> mIrs{};
|
||||
std::atomic<size_t> mCurrent{};
|
||||
std::atomic<size_t> mDone{};
|
||||
|
||||
void Worker()
|
||||
{
|
||||
auto htemp = std::vector<complex_d>(mFftSize);
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* Load the current index to process. */
|
||||
size_t idx{mCurrent.load()};
|
||||
do {
|
||||
/* If the index is at the end, we're done. */
|
||||
if(idx >= mIrs.size())
|
||||
return;
|
||||
/* Otherwise, increment the current index atomically so other
|
||||
* threads know to go to the next one. If this call fails, the
|
||||
* current index was just changed by another thread and the new
|
||||
* value is loaded into idx, which we'll recheck.
|
||||
*/
|
||||
} while(!mCurrent.compare_exchange_weak(idx, idx+1, std::memory_order_relaxed));
|
||||
|
||||
CalcHrirMagnitude(mIrPoints, mFftSize, htemp, mIrs[idx]);
|
||||
|
||||
/* Increment the number of IRs done. */
|
||||
mDone.fetch_add(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool LoadSofaFile(const char *filename, const uint numThreads, const uint fftSize,
|
||||
const uint truncSize, const uint outRate, const ChannelModeT chanMode, HrirDataT *hData)
|
||||
{
|
||||
int err;
|
||||
MySofaHrtfPtr sofaHrtf{mysofa_load(filename, &err)};
|
||||
if(!sofaHrtf)
|
||||
{
|
||||
fprintf(stdout, "Error: Could not load %s: %s\n", filename, SofaErrorStr(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NOTE: Some valid SOFA files are failing this check. */
|
||||
err = mysofa_check(sofaHrtf.get());
|
||||
if(err != MYSOFA_OK)
|
||||
fprintf(stderr, "Warning: Supposedly malformed source file '%s' (%s).\n", filename,
|
||||
SofaErrorStr(err));
|
||||
|
||||
mysofa_tocartesian(sofaHrtf.get());
|
||||
|
||||
/* Make sure emitter and receiver counts are sane. */
|
||||
if(sofaHrtf->E != 1)
|
||||
{
|
||||
fprintf(stderr, "%u emitters not supported\n", sofaHrtf->E);
|
||||
return false;
|
||||
}
|
||||
if(sofaHrtf->R > 2 || sofaHrtf->R < 1)
|
||||
{
|
||||
fprintf(stderr, "%u receivers not supported\n", sofaHrtf->R);
|
||||
return false;
|
||||
}
|
||||
/* Assume R=2 is a stereo measurement, and R=1 is mono left-ear-only. */
|
||||
if(sofaHrtf->R == 2 && chanMode == CM_AllowStereo)
|
||||
hData->mChannelType = CT_STEREO;
|
||||
else
|
||||
hData->mChannelType = CT_MONO;
|
||||
|
||||
/* Check and set the FFT and IR size. */
|
||||
if(sofaHrtf->N > fftSize)
|
||||
{
|
||||
fprintf(stderr, "Sample points exceeds the FFT size.\n");
|
||||
return false;
|
||||
}
|
||||
if(sofaHrtf->N < truncSize)
|
||||
{
|
||||
fprintf(stderr, "Sample points is below the truncation size.\n");
|
||||
return false;
|
||||
}
|
||||
hData->mIrPoints = sofaHrtf->N;
|
||||
hData->mFftSize = fftSize;
|
||||
hData->mIrSize = std::max(1u + (fftSize/2u), sofaHrtf->N);
|
||||
|
||||
/* Assume a default head radius of 9cm. */
|
||||
hData->mRadius = 0.09;
|
||||
|
||||
hData->mIrRate = static_cast<uint>(GetSampleRate(sofaHrtf.get()) + 0.5f);
|
||||
if(!hData->mIrRate)
|
||||
return false;
|
||||
|
||||
DelayType delayType = PrepareDelay(sofaHrtf.get());
|
||||
if(delayType == DelayType::Invalid)
|
||||
return false;
|
||||
|
||||
if(!CheckIrData(sofaHrtf.get()))
|
||||
return false;
|
||||
if(!PrepareLayout(sofaHrtf->M, sofaHrtf->SourcePosition.values, hData))
|
||||
return false;
|
||||
if(!LoadResponses(sofaHrtf.get(), hData, delayType, outRate))
|
||||
return false;
|
||||
sofaHrtf = nullptr;
|
||||
|
||||
for(uint fi{0u};fi < hData->mFds.size();fi++)
|
||||
{
|
||||
uint ei{0u};
|
||||
for(;ei < hData->mFds[fi].mEvs.size();ei++)
|
||||
{
|
||||
uint ai{0u};
|
||||
for(;ai < hData->mFds[fi].mEvs[ei].mAzs.size();ai++)
|
||||
{
|
||||
HrirAzT &azd = hData->mFds[fi].mEvs[ei].mAzs[ai];
|
||||
if(azd.mIrs[0] != nullptr) break;
|
||||
}
|
||||
if(ai < hData->mFds[fi].mEvs[ei].mAzs.size())
|
||||
break;
|
||||
}
|
||||
if(ei >= hData->mFds[fi].mEvs.size())
|
||||
{
|
||||
fprintf(stderr, "Missing source references [ %d, *, * ].\n", fi);
|
||||
return false;
|
||||
}
|
||||
hData->mFds[fi].mEvStart = ei;
|
||||
for(;ei < hData->mFds[fi].mEvs.size();ei++)
|
||||
{
|
||||
for(uint ai{0u};ai < hData->mFds[fi].mEvs[ei].mAzs.size();ai++)
|
||||
{
|
||||
HrirAzT &azd = hData->mFds[fi].mEvs[ei].mAzs[ai];
|
||||
if(azd.mIrs[0] == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Missing source reference [ %d, %d, %d ].\n", fi, ei, ai);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t hrir_total{0};
|
||||
const uint channels{(hData->mChannelType == CT_STEREO) ? 2u : 1u};
|
||||
double *hrirs = hData->mHrirsBase.data();
|
||||
for(uint fi{0u};fi < hData->mFds.size();fi++)
|
||||
{
|
||||
for(uint ei{0u};ei < hData->mFds[fi].mEvStart;ei++)
|
||||
{
|
||||
for(uint ai{0u};ai < hData->mFds[fi].mEvs[ei].mAzs.size();ai++)
|
||||
{
|
||||
HrirAzT &azd = hData->mFds[fi].mEvs[ei].mAzs[ai];
|
||||
for(uint ti{0u};ti < channels;ti++)
|
||||
azd.mIrs[ti] = &hrirs[hData->mIrSize * (hData->mIrCount*ti + azd.mIndex)];
|
||||
}
|
||||
}
|
||||
|
||||
for(uint ei{hData->mFds[fi].mEvStart};ei < hData->mFds[fi].mEvs.size();ei++)
|
||||
hrir_total += hData->mFds[fi].mEvs[ei].mAzs.size() * channels;
|
||||
}
|
||||
|
||||
std::atomic<size_t> hrir_done{0};
|
||||
auto onset_proc = [hData,channels,&hrir_done]() -> bool
|
||||
{
|
||||
/* Temporary buffer used to calculate the IR's onset. */
|
||||
auto upsampled = std::vector<double>(OnsetRateMultiple * hData->mIrPoints);
|
||||
/* This resampler is used to help detect the response onset. */
|
||||
PPhaseResampler rs;
|
||||
rs.init(hData->mIrRate, OnsetRateMultiple*hData->mIrRate);
|
||||
|
||||
for(auto &field : hData->mFds)
|
||||
{
|
||||
for(auto &elev : field.mEvs.subspan(field.mEvStart))
|
||||
{
|
||||
for(auto &azd : elev.mAzs)
|
||||
{
|
||||
for(uint ti{0};ti < channels;ti++)
|
||||
{
|
||||
hrir_done.fetch_add(1u, std::memory_order_acq_rel);
|
||||
azd.mDelays[ti] += CalcHrirOnset(rs, hData->mIrRate, hData->mIrPoints,
|
||||
upsampled, azd.mIrs[ti]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
std::future_status load_status{};
|
||||
auto load_future = std::async(std::launch::async, onset_proc);
|
||||
do {
|
||||
load_status = load_future.wait_for(std::chrono::milliseconds{50});
|
||||
printf("\rCalculating HRIR onsets... %zu of %zu", hrir_done.load(), hrir_total);
|
||||
fflush(stdout);
|
||||
} while(load_status != std::future_status::ready);
|
||||
fputc('\n', stdout);
|
||||
if(!load_future.get())
|
||||
return false;
|
||||
|
||||
MagCalculator calculator{hData->mFftSize, hData->mIrPoints};
|
||||
for(auto &field : hData->mFds)
|
||||
{
|
||||
for(auto &elev : field.mEvs.subspan(field.mEvStart))
|
||||
{
|
||||
for(auto &azd : elev.mAzs)
|
||||
{
|
||||
for(uint ti{0};ti < channels;ti++)
|
||||
calculator.mIrs.push_back(azd.mIrs[ti]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::thread> thrds;
|
||||
thrds.reserve(numThreads);
|
||||
for(size_t i{0};i < numThreads;++i)
|
||||
thrds.emplace_back(std::mem_fn(&MagCalculator::Worker), &calculator);
|
||||
size_t count;
|
||||
do {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{50});
|
||||
count = calculator.mDone.load();
|
||||
|
||||
printf("\rCalculating HRIR magnitudes... %zu of %zu", count, calculator.mIrs.size());
|
||||
fflush(stdout);
|
||||
} while(count != calculator.mIrs.size());
|
||||
fputc('\n', stdout);
|
||||
|
||||
for(auto &thrd : thrds)
|
||||
{
|
||||
if(thrd.joinable())
|
||||
thrd.join();
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#ifndef LOADSOFA_H
|
||||
#define LOADSOFA_H
|
||||
|
||||
#include "makemhr.h"
|
||||
|
||||
|
||||
bool LoadSofaFile(const char *filename, const uint numThreads, const uint fftSize,
|
||||
const uint truncSize, const uint outRate, const ChannelModeT chanMode, HrirDataT *hData);
|
||||
|
||||
#endif /* LOADSOFA_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,131 +0,0 @@
|
||||
#ifndef MAKEMHR_H
|
||||
#define MAKEMHR_H
|
||||
|
||||
#include <vector>
|
||||
#include <complex>
|
||||
|
||||
#include "alcomplex.h"
|
||||
#include "polyphase_resampler.h"
|
||||
|
||||
|
||||
// The maximum path length used when processing filenames.
|
||||
#define MAX_PATH_LEN (256)
|
||||
|
||||
// The limit to the number of 'distances' listed in the data set definition.
|
||||
// Must be less than 256
|
||||
#define MAX_FD_COUNT (16)
|
||||
|
||||
// The limits to the number of 'elevations' listed in the data set definition.
|
||||
// Must be less than 256.
|
||||
#define MIN_EV_COUNT (5)
|
||||
#define MAX_EV_COUNT (181)
|
||||
|
||||
// The limits for each of the 'azimuths' listed in the data set definition.
|
||||
// Must be less than 256.
|
||||
#define MIN_AZ_COUNT (1)
|
||||
#define MAX_AZ_COUNT (255)
|
||||
|
||||
// The limits for the 'distance' from source to listener for each field in
|
||||
// the definition file.
|
||||
#define MIN_DISTANCE (0.05)
|
||||
#define MAX_DISTANCE (2.50)
|
||||
|
||||
// The limits for the sample 'rate' metric in the data set definition and for
|
||||
// resampling.
|
||||
#define MIN_RATE (32000)
|
||||
#define MAX_RATE (96000)
|
||||
|
||||
// The limits for the HRIR 'points' metric in the data set definition.
|
||||
#define MIN_POINTS (16)
|
||||
#define MAX_POINTS (8192)
|
||||
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
/* Complex double type. */
|
||||
using complex_d = std::complex<double>;
|
||||
|
||||
|
||||
enum ChannelModeT : bool {
|
||||
CM_AllowStereo = false,
|
||||
CM_ForceMono = true
|
||||
};
|
||||
|
||||
// Sample and channel type enum values.
|
||||
enum SampleTypeT {
|
||||
ST_S16 = 0,
|
||||
ST_S24 = 1
|
||||
};
|
||||
|
||||
// Certain iterations rely on these integer enum values.
|
||||
enum ChannelTypeT {
|
||||
CT_NONE = -1,
|
||||
CT_MONO = 0,
|
||||
CT_STEREO = 1
|
||||
};
|
||||
|
||||
// Structured HRIR storage for stereo azimuth pairs, elevations, and fields.
|
||||
struct HrirAzT {
|
||||
double mAzimuth{0.0};
|
||||
uint mIndex{0u};
|
||||
double mDelays[2]{0.0, 0.0};
|
||||
double *mIrs[2]{nullptr, nullptr};
|
||||
};
|
||||
|
||||
struct HrirEvT {
|
||||
double mElevation{0.0};
|
||||
al::span<HrirAzT> mAzs;
|
||||
};
|
||||
|
||||
struct HrirFdT {
|
||||
double mDistance{0.0};
|
||||
uint mEvStart{0u};
|
||||
al::span<HrirEvT> mEvs;
|
||||
};
|
||||
|
||||
// The HRIR metrics and data set used when loading, processing, and storing
|
||||
// the resulting HRTF.
|
||||
struct HrirDataT {
|
||||
uint mIrRate{0u};
|
||||
SampleTypeT mSampleType{ST_S24};
|
||||
ChannelTypeT mChannelType{CT_NONE};
|
||||
uint mIrPoints{0u};
|
||||
uint mFftSize{0u};
|
||||
uint mIrSize{0u};
|
||||
double mRadius{0.0};
|
||||
uint mIrCount{0u};
|
||||
|
||||
std::vector<double> mHrirsBase;
|
||||
std::vector<HrirEvT> mEvsBase;
|
||||
std::vector<HrirAzT> mAzsBase;
|
||||
|
||||
std::vector<HrirFdT> mFds;
|
||||
|
||||
/* GCC warns when it tries to inline this. */
|
||||
~HrirDataT();
|
||||
};
|
||||
|
||||
|
||||
bool PrepareHrirData(const al::span<const double> distances,
|
||||
const al::span<const uint,MAX_FD_COUNT> evCounts,
|
||||
const al::span<const std::array<uint,MAX_EV_COUNT>,MAX_FD_COUNT> azCounts, HrirDataT *hData);
|
||||
void MagnitudeResponse(const uint n, const complex_d *in, double *out);
|
||||
|
||||
// Performs a forward FFT.
|
||||
inline void FftForward(const uint n, complex_d *inout)
|
||||
{ forward_fft(al::as_span(inout, n)); }
|
||||
|
||||
// Performs an inverse FFT.
|
||||
inline void FftInverse(const uint n, complex_d *inout)
|
||||
{
|
||||
inverse_fft(al::as_span(inout, n));
|
||||
double f{1.0 / n};
|
||||
for(uint i{0};i < n;i++)
|
||||
inout[i] *= f;
|
||||
}
|
||||
|
||||
// Performs linear interpolation.
|
||||
inline double Lerp(const double a, const double b, const double f)
|
||||
{ return a + f * (b - a); }
|
||||
|
||||
#endif /* MAKEMHR_H */
|
@ -1,444 +0,0 @@
|
||||
/*
|
||||
* OpenAL Info Utility
|
||||
*
|
||||
* Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "AL/alc.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#include "win_main_utf8.h"
|
||||
|
||||
/* C doesn't allow casting between function and non-function pointer types, so
|
||||
* with C99 we need to use a union to reinterpret the pointer type. Pre-C99
|
||||
* still needs to use a normal cast and live with the warning (C++ is fine with
|
||||
* a regular reinterpret_cast).
|
||||
*/
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define FUNCTION_CAST(T, ptr) (union{void *p; T f;}){ptr}.f
|
||||
#else
|
||||
#define FUNCTION_CAST(T, ptr) (T)(ptr)
|
||||
#endif
|
||||
|
||||
#define MAX_WIDTH 80
|
||||
|
||||
static void printList(const char *list, char separator)
|
||||
{
|
||||
size_t col = MAX_WIDTH, len;
|
||||
const char *indent = " ";
|
||||
const char *next;
|
||||
|
||||
if(!list || *list == '\0')
|
||||
{
|
||||
fprintf(stdout, "\n%s!!! none !!!\n", indent);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
next = strchr(list, separator);
|
||||
if(next)
|
||||
{
|
||||
len = (size_t)(next-list);
|
||||
do {
|
||||
next++;
|
||||
} while(*next == separator);
|
||||
}
|
||||
else
|
||||
len = strlen(list);
|
||||
|
||||
if(len + col + 2 >= MAX_WIDTH)
|
||||
{
|
||||
fprintf(stdout, "\n%s", indent);
|
||||
col = strlen(indent);
|
||||
}
|
||||
else
|
||||
{
|
||||
fputc(' ', stdout);
|
||||
col++;
|
||||
}
|
||||
|
||||
len = fwrite(list, 1, len, stdout);
|
||||
col += len;
|
||||
|
||||
if(!next || *next == '\0')
|
||||
break;
|
||||
fputc(',', stdout);
|
||||
col++;
|
||||
|
||||
list = next;
|
||||
} while(1);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
static void printDeviceList(const char *list)
|
||||
{
|
||||
if(!list || *list == '\0')
|
||||
printf(" !!! none !!!\n");
|
||||
else do {
|
||||
printf(" %s\n", list);
|
||||
list += strlen(list) + 1;
|
||||
} while(*list != '\0');
|
||||
}
|
||||
|
||||
|
||||
static ALenum checkALErrors(int linenum)
|
||||
{
|
||||
ALenum err = alGetError();
|
||||
if(err != AL_NO_ERROR)
|
||||
printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err), err, linenum);
|
||||
return err;
|
||||
}
|
||||
#define checkALErrors() checkALErrors(__LINE__)
|
||||
|
||||
static ALCenum checkALCErrors(ALCdevice *device, int linenum)
|
||||
{
|
||||
ALCenum err = alcGetError(device);
|
||||
if(err != ALC_NO_ERROR)
|
||||
printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device, err), err, linenum);
|
||||
return err;
|
||||
}
|
||||
#define checkALCErrors(x) checkALCErrors((x),__LINE__)
|
||||
|
||||
|
||||
static void printALCInfo(ALCdevice *device)
|
||||
{
|
||||
ALCint major, minor;
|
||||
|
||||
if(device)
|
||||
{
|
||||
const ALCchar *devname = NULL;
|
||||
printf("\n");
|
||||
if(alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||
devname = alcGetString(device, ALC_ALL_DEVICES_SPECIFIER);
|
||||
if(checkALCErrors(device) != ALC_NO_ERROR || !devname)
|
||||
devname = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
printf("** Info for device \"%s\" **\n", devname);
|
||||
}
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
|
||||
if(checkALCErrors(device) == ALC_NO_ERROR)
|
||||
printf("ALC version: %d.%d\n", major, minor);
|
||||
if(device)
|
||||
{
|
||||
printf("ALC extensions:");
|
||||
printList(alcGetString(device, ALC_EXTENSIONS), ' ');
|
||||
checkALCErrors(device);
|
||||
}
|
||||
}
|
||||
|
||||
static void printHRTFInfo(ALCdevice *device)
|
||||
{
|
||||
LPALCGETSTRINGISOFT alcGetStringiSOFT;
|
||||
ALCint num_hrtfs;
|
||||
|
||||
if(alcIsExtensionPresent(device, "ALC_SOFT_HRTF") == ALC_FALSE)
|
||||
{
|
||||
printf("HRTF extension not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
alcGetStringiSOFT = FUNCTION_CAST(LPALCGETSTRINGISOFT,
|
||||
alcGetProcAddress(device, "alcGetStringiSOFT"));
|
||||
|
||||
alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtfs);
|
||||
if(!num_hrtfs)
|
||||
printf("No HRTFs found\n");
|
||||
else
|
||||
{
|
||||
ALCint i;
|
||||
printf("Available HRTFs:\n");
|
||||
for(i = 0;i < num_hrtfs;++i)
|
||||
{
|
||||
const ALCchar *name = alcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i);
|
||||
printf(" %s\n", name);
|
||||
}
|
||||
}
|
||||
checkALCErrors(device);
|
||||
}
|
||||
|
||||
static void printModeInfo(ALCdevice *device)
|
||||
{
|
||||
ALCint srate = 0;
|
||||
|
||||
if(alcIsExtensionPresent(device, "ALC_SOFT_output_mode"))
|
||||
{
|
||||
const char *modename = "(error)";
|
||||
ALCenum mode = 0;
|
||||
|
||||
alcGetIntegerv(device, ALC_OUTPUT_MODE_SOFT, 1, &mode);
|
||||
checkALCErrors(device);
|
||||
switch(mode)
|
||||
{
|
||||
case ALC_ANY_SOFT: modename = "Unknown / unspecified"; break;
|
||||
case ALC_MONO_SOFT: modename = "Mono"; break;
|
||||
case ALC_STEREO_SOFT: modename = "Stereo (unspecified encoding)"; break;
|
||||
case ALC_STEREO_BASIC_SOFT: modename = "Stereo (basic)"; break;
|
||||
case ALC_STEREO_UHJ_SOFT: modename = "Stereo (UHJ)"; break;
|
||||
case ALC_STEREO_HRTF_SOFT: modename = "Stereo (HRTF)"; break;
|
||||
case ALC_QUAD_SOFT: modename = "Quadraphonic"; break;
|
||||
case ALC_SURROUND_5_1_SOFT: modename = "5.1 Surround"; break;
|
||||
case ALC_SURROUND_6_1_SOFT: modename = "6.1 Surround"; break;
|
||||
case ALC_SURROUND_7_1_SOFT: modename = "7.1 Surround"; break;
|
||||
}
|
||||
printf("Device output mode: %s\n", modename);
|
||||
}
|
||||
else
|
||||
printf("Output mode extension not available\n");
|
||||
|
||||
alcGetIntegerv(device, ALC_FREQUENCY, 1, &srate);
|
||||
if(checkALCErrors(device) == ALC_NO_ERROR)
|
||||
printf("Device sample rate: %dhz\n", srate);
|
||||
}
|
||||
|
||||
static void printALInfo(void)
|
||||
{
|
||||
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
|
||||
printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
|
||||
printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
|
||||
printf("OpenAL extensions:");
|
||||
printList(alGetString(AL_EXTENSIONS), ' ');
|
||||
checkALErrors();
|
||||
}
|
||||
|
||||
static void printResamplerInfo(void)
|
||||
{
|
||||
LPALGETSTRINGISOFT alGetStringiSOFT;
|
||||
ALint num_resamplers;
|
||||
ALint def_resampler;
|
||||
|
||||
if(!alIsExtensionPresent("AL_SOFT_source_resampler"))
|
||||
{
|
||||
printf("Resampler info not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
alGetStringiSOFT = FUNCTION_CAST(LPALGETSTRINGISOFT, alGetProcAddress("alGetStringiSOFT"));
|
||||
|
||||
num_resamplers = alGetInteger(AL_NUM_RESAMPLERS_SOFT);
|
||||
def_resampler = alGetInteger(AL_DEFAULT_RESAMPLER_SOFT);
|
||||
|
||||
if(!num_resamplers)
|
||||
printf("!!! No resamplers found !!!\n");
|
||||
else
|
||||
{
|
||||
ALint i;
|
||||
printf("Available resamplers:\n");
|
||||
for(i = 0;i < num_resamplers;++i)
|
||||
{
|
||||
const ALchar *name = alGetStringiSOFT(AL_RESAMPLER_NAME_SOFT, i);
|
||||
printf(" %s%s\n", name, (i==def_resampler)?" *":"");
|
||||
}
|
||||
}
|
||||
checkALErrors();
|
||||
}
|
||||
|
||||
static void printEFXInfo(ALCdevice *device)
|
||||
{
|
||||
static LPALGENFILTERS palGenFilters;
|
||||
static LPALDELETEFILTERS palDeleteFilters;
|
||||
static LPALFILTERI palFilteri;
|
||||
static LPALGENEFFECTS palGenEffects;
|
||||
static LPALDELETEEFFECTS palDeleteEffects;
|
||||
static LPALEFFECTI palEffecti;
|
||||
|
||||
static const ALint filters[] = {
|
||||
AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS,
|
||||
AL_FILTER_NULL
|
||||
};
|
||||
char filterNames[] = "Low-pass,High-pass,Band-pass,";
|
||||
static const ALint effects[] = {
|
||||
AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS,
|
||||
AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER,
|
||||
AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER,
|
||||
AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR,
|
||||
AL_EFFECT_AUTOWAH, AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER,
|
||||
AL_EFFECT_NULL
|
||||
};
|
||||
static const ALint dedeffects[] = {
|
||||
AL_EFFECT_DEDICATED_DIALOGUE, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT,
|
||||
AL_EFFECT_NULL
|
||||
};
|
||||
char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
|
||||
"Frequency Shifter,Vocal Morpher,Pitch Shifter,Ring Modulator,Autowah,"
|
||||
"Compressor,Equalizer,Dedicated Dialog,Dedicated LFE,";
|
||||
ALCint major, minor, sends;
|
||||
ALuint object;
|
||||
char *current;
|
||||
int i;
|
||||
|
||||
if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE)
|
||||
{
|
||||
printf("EFX not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
palGenFilters = FUNCTION_CAST(LPALGENFILTERS, alGetProcAddress("alGenFilters"));
|
||||
palDeleteFilters = FUNCTION_CAST(LPALDELETEFILTERS, alGetProcAddress("alDeleteFilters"));
|
||||
palFilteri = FUNCTION_CAST(LPALFILTERI, alGetProcAddress("alFilteri"));
|
||||
palGenEffects = FUNCTION_CAST(LPALGENEFFECTS, alGetProcAddress("alGenEffects"));
|
||||
palDeleteEffects = FUNCTION_CAST(LPALDELETEEFFECTS, alGetProcAddress("alDeleteEffects"));
|
||||
palEffecti = FUNCTION_CAST(LPALEFFECTI, alGetProcAddress("alEffecti"));
|
||||
|
||||
alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major);
|
||||
alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor);
|
||||
if(checkALCErrors(device) == ALC_NO_ERROR)
|
||||
printf("EFX version: %d.%d\n", major, minor);
|
||||
alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends);
|
||||
if(checkALCErrors(device) == ALC_NO_ERROR)
|
||||
printf("Max auxiliary sends: %d\n", sends);
|
||||
|
||||
palGenFilters(1, &object);
|
||||
checkALErrors();
|
||||
|
||||
current = filterNames;
|
||||
for(i = 0;filters[i] != AL_FILTER_NULL;i++)
|
||||
{
|
||||
char *next = strchr(current, ',');
|
||||
assert(next != NULL);
|
||||
|
||||
palFilteri(object, AL_FILTER_TYPE, filters[i]);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
memmove(current, next+1, strlen(next));
|
||||
else
|
||||
current = next+1;
|
||||
}
|
||||
printf("Supported filters:");
|
||||
printList(filterNames, ',');
|
||||
|
||||
palDeleteFilters(1, &object);
|
||||
palGenEffects(1, &object);
|
||||
checkALErrors();
|
||||
|
||||
current = effectNames;
|
||||
for(i = 0;effects[i] != AL_EFFECT_NULL;i++)
|
||||
{
|
||||
char *next = strchr(current, ',');
|
||||
assert(next != NULL);
|
||||
|
||||
palEffecti(object, AL_EFFECT_TYPE, effects[i]);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
memmove(current, next+1, strlen(next));
|
||||
else
|
||||
current = next+1;
|
||||
}
|
||||
if(alcIsExtensionPresent(device, "ALC_EXT_DEDICATED"))
|
||||
{
|
||||
for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++)
|
||||
{
|
||||
char *next = strchr(current, ',');
|
||||
assert(next != NULL);
|
||||
|
||||
palEffecti(object, AL_EFFECT_TYPE, dedeffects[i]);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
memmove(current, next+1, strlen(next));
|
||||
else
|
||||
current = next+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++)
|
||||
{
|
||||
char *next = strchr(current, ',');
|
||||
assert(next != NULL);
|
||||
memmove(current, next+1, strlen(next));
|
||||
}
|
||||
}
|
||||
printf("Supported effects:");
|
||||
printList(effectNames, ',');
|
||||
|
||||
palDeleteEffects(1, &object);
|
||||
checkALErrors();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* OpenAL Soft gives UTF-8 strings, so set the console to expect that. */
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
|
||||
if(argc > 1 && (strcmp(argv[1], "--help") == 0 ||
|
||||
strcmp(argv[1], "-h") == 0))
|
||||
{
|
||||
printf("Usage: %s [playback device]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Available playback devices:\n");
|
||||
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||
printDeviceList(alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER));
|
||||
else
|
||||
printDeviceList(alcGetString(NULL, ALC_DEVICE_SPECIFIER));
|
||||
printf("Available capture devices:\n");
|
||||
printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER));
|
||||
|
||||
if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
|
||||
printf("Default playback device: %s\n",
|
||||
alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER));
|
||||
else
|
||||
printf("Default playback device: %s\n",
|
||||
alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
|
||||
printf("Default capture device: %s\n",
|
||||
alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
|
||||
|
||||
printALCInfo(NULL);
|
||||
|
||||
device = alcOpenDevice((argc>1) ? argv[1] : NULL);
|
||||
if(!device)
|
||||
{
|
||||
printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device"));
|
||||
return 1;
|
||||
}
|
||||
printALCInfo(device);
|
||||
printHRTFInfo(device);
|
||||
|
||||
context = alcCreateContext(device, NULL);
|
||||
if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
|
||||
{
|
||||
if(context)
|
||||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
printf("\n!!! Failed to set a context !!!\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printModeInfo(device);
|
||||
printALInfo();
|
||||
printResamplerInfo();
|
||||
printEFXInfo(device);
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
alcCloseDevice(device);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* SOFA info utility for inspecting SOFA file metrics and determining HRTF
|
||||
* utility compatible layouts.
|
||||
*
|
||||
* Copyright (C) 2018-2019 Christopher Fitzgerald
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Or visit: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "sofa-support.h"
|
||||
|
||||
#include "mysofa.h"
|
||||
|
||||
#include "win_main_utf8.h"
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
static void PrintSofaAttributes(const char *prefix, struct MYSOFA_ATTRIBUTE *attribute)
|
||||
{
|
||||
while(attribute)
|
||||
{
|
||||
fprintf(stdout, "%s.%s: %s\n", prefix, attribute->name, attribute->value);
|
||||
attribute = attribute->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintSofaArray(const char *prefix, struct MYSOFA_ARRAY *array)
|
||||
{
|
||||
PrintSofaAttributes(prefix, array->attributes);
|
||||
for(uint i{0u};i < array->elements;i++)
|
||||
fprintf(stdout, "%s[%u]: %.6f\n", prefix, i, array->values[i]);
|
||||
}
|
||||
|
||||
/* Attempts to produce a compatible layout. Most data sets tend to be
|
||||
* uniform and have the same major axis as used by OpenAL Soft's HRTF model.
|
||||
* This will remove outliers and produce a maximally dense layout when
|
||||
* possible. Those sets that contain purely random measurements or use
|
||||
* different major axes will fail.
|
||||
*/
|
||||
static void PrintCompatibleLayout(const uint m, const float *xyzs)
|
||||
{
|
||||
fputc('\n', stdout);
|
||||
|
||||
auto fds = GetCompatibleLayout(m, xyzs);
|
||||
if(fds.empty())
|
||||
{
|
||||
fprintf(stdout, "No compatible field layouts in SOFA file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint used_elems{0};
|
||||
for(size_t fi{0u};fi < fds.size();++fi)
|
||||
{
|
||||
for(uint ei{fds[fi].mEvStart};ei < fds[fi].mEvCount;++ei)
|
||||
used_elems += fds[fi].mAzCounts[ei];
|
||||
}
|
||||
|
||||
fprintf(stdout, "Compatible Layout (%u of %u measurements):\n\ndistance = %.3f", used_elems, m,
|
||||
fds[0].mDistance);
|
||||
for(size_t fi{1u};fi < fds.size();fi++)
|
||||
fprintf(stdout, ", %.3f", fds[fi].mDistance);
|
||||
|
||||
fprintf(stdout, "\nazimuths = ");
|
||||
for(size_t fi{0u};fi < fds.size();++fi)
|
||||
{
|
||||
for(uint ei{0u};ei < fds[fi].mEvStart;++ei)
|
||||
fprintf(stdout, "%d%s", fds[fi].mAzCounts[fds[fi].mEvCount - 1 - ei], ", ");
|
||||
for(uint ei{fds[fi].mEvStart};ei < fds[fi].mEvCount;++ei)
|
||||
fprintf(stdout, "%d%s", fds[fi].mAzCounts[ei],
|
||||
(ei < (fds[fi].mEvCount - 1)) ? ", " :
|
||||
(fi < (fds.size() - 1)) ? ";\n " : "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Load and inspect the given SOFA file.
|
||||
static void SofaInfo(const char *filename)
|
||||
{
|
||||
int err;
|
||||
MySofaHrtfPtr sofa{mysofa_load(filename, &err)};
|
||||
if(!sofa)
|
||||
{
|
||||
fprintf(stdout, "Error: Could not load source file '%s' (%s).\n", filename,
|
||||
SofaErrorStr(err));
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: Some valid SOFA files are failing this check. */
|
||||
err = mysofa_check(sofa.get());
|
||||
if(err != MYSOFA_OK)
|
||||
fprintf(stdout, "Warning: Supposedly malformed source file '%s' (%s).\n", filename,
|
||||
SofaErrorStr(err));
|
||||
|
||||
mysofa_tocartesian(sofa.get());
|
||||
|
||||
PrintSofaAttributes("Info", sofa->attributes);
|
||||
|
||||
fprintf(stdout, "Measurements: %u\n", sofa->M);
|
||||
fprintf(stdout, "Receivers: %u\n", sofa->R);
|
||||
fprintf(stdout, "Emitters: %u\n", sofa->E);
|
||||
fprintf(stdout, "Samples: %u\n", sofa->N);
|
||||
|
||||
PrintSofaArray("SampleRate", &sofa->DataSamplingRate);
|
||||
PrintSofaArray("DataDelay", &sofa->DataDelay);
|
||||
|
||||
PrintCompatibleLayout(sofa->M, sofa->SourcePosition.values);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(argc != 2)
|
||||
{
|
||||
fprintf(stdout, "Usage: %s <sofa-file>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SofaInfo(argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,292 +0,0 @@
|
||||
/*
|
||||
* SOFA utility methods for inspecting SOFA file metrics and determining HRTF
|
||||
* utility compatible layouts.
|
||||
*
|
||||
* Copyright (C) 2018-2019 Christopher Fitzgerald
|
||||
* Copyright (C) 2019 Christopher Robinson
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Or visit: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*/
|
||||
|
||||
#include "sofa-support.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "mysofa.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
using uint = unsigned int;
|
||||
using double3 = std::array<double,3>;
|
||||
|
||||
|
||||
/* Produces a sorted array of unique elements from a particular axis of the
|
||||
* triplets array. The filters are used to focus on particular coordinates
|
||||
* of other axes as necessary. The epsilons are used to constrain the
|
||||
* equality of unique elements.
|
||||
*/
|
||||
std::vector<double> GetUniquelySortedElems(const std::vector<double3> &aers, const uint axis,
|
||||
const double *const (&filters)[3], const double (&epsilons)[3])
|
||||
{
|
||||
std::vector<double> elems;
|
||||
for(const double3 &aer : aers)
|
||||
{
|
||||
const double elem{aer[axis]};
|
||||
|
||||
uint j;
|
||||
for(j = 0;j < 3;j++)
|
||||
{
|
||||
if(filters[j] && std::abs(aer[j] - *filters[j]) > epsilons[j])
|
||||
break;
|
||||
}
|
||||
if(j < 3)
|
||||
continue;
|
||||
|
||||
auto iter = elems.begin();
|
||||
for(;iter != elems.end();++iter)
|
||||
{
|
||||
const double delta{elem - *iter};
|
||||
if(delta > epsilons[axis]) continue;
|
||||
if(delta >= -epsilons[axis]) break;
|
||||
|
||||
iter = elems.emplace(iter, elem);
|
||||
break;
|
||||
}
|
||||
if(iter == elems.end())
|
||||
elems.emplace_back(elem);
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
/* Given a list of azimuths, this will produce the smallest step size that can
|
||||
* uniformly cover the list. Ideally this will be over half, but in degenerate
|
||||
* cases this can fall to a minimum of 5 (the lower limit).
|
||||
*/
|
||||
double GetUniformAzimStep(const double epsilon, const std::vector<double> &elems)
|
||||
{
|
||||
if(elems.size() < 5) return 0.0;
|
||||
|
||||
/* Get the maximum count possible, given the first two elements. It would
|
||||
* be impossible to have more than this since the first element must be
|
||||
* included.
|
||||
*/
|
||||
uint count{static_cast<uint>(std::ceil(360.0 / (elems[1]-elems[0])))};
|
||||
count = std::min(count, 255u);
|
||||
|
||||
for(;count >= 5;--count)
|
||||
{
|
||||
/* Given the stepping value for this number of elements, check each
|
||||
* multiple to ensure there's a matching element.
|
||||
*/
|
||||
const double step{360.0 / count};
|
||||
bool good{true};
|
||||
size_t idx{1u};
|
||||
for(uint mult{1u};mult < count && good;++mult)
|
||||
{
|
||||
const double target{step*mult + elems[0]};
|
||||
while(idx < elems.size() && target-elems[idx] > epsilon)
|
||||
++idx;
|
||||
good &= (idx < elems.size()) && !(std::abs(target-elems[idx++]) > epsilon);
|
||||
}
|
||||
if(good)
|
||||
return step;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Given a list of elevations, this will produce the smallest step size that
|
||||
* can uniformly cover the list. Ideally this will be over half, but in
|
||||
* degenerate cases this can fall to a minimum of 5 (the lower limit).
|
||||
*/
|
||||
double GetUniformElevStep(const double epsilon, std::vector<double> &elems)
|
||||
{
|
||||
if(elems.size() < 5) return 0.0;
|
||||
|
||||
/* Reverse the elevations so it increments starting with -90 (flipped from
|
||||
* +90). This makes it easier to work out a proper stepping value.
|
||||
*/
|
||||
std::reverse(elems.begin(), elems.end());
|
||||
for(auto &v : elems) v *= -1.0;
|
||||
|
||||
uint count{static_cast<uint>(std::ceil(180.0 / (elems[1]-elems[0])))};
|
||||
count = std::min(count, 255u);
|
||||
|
||||
double ret{0.0};
|
||||
for(;count >= 5;--count)
|
||||
{
|
||||
const double step{180.0 / count};
|
||||
bool good{true};
|
||||
size_t idx{1u};
|
||||
/* Elevations don't need to match all multiples if there's not enough
|
||||
* elements to check. Missing elevations can be synthesized.
|
||||
*/
|
||||
for(uint mult{1u};mult <= count && idx < elems.size() && good;++mult)
|
||||
{
|
||||
const double target{step*mult + elems[0]};
|
||||
while(idx < elems.size() && target-elems[idx] > epsilon)
|
||||
++idx;
|
||||
good &= !(idx < elems.size()) || !(std::abs(target-elems[idx++]) > epsilon);
|
||||
}
|
||||
if(good)
|
||||
{
|
||||
ret = step;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Re-reverse the elevations to restore the correct order. */
|
||||
for(auto &v : elems) v *= -1.0;
|
||||
std::reverse(elems.begin(), elems.end());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
const char *SofaErrorStr(int err)
|
||||
{
|
||||
switch(err)
|
||||
{
|
||||
case MYSOFA_OK: return "OK";
|
||||
case MYSOFA_INVALID_FORMAT: return "Invalid format";
|
||||
case MYSOFA_UNSUPPORTED_FORMAT: return "Unsupported format";
|
||||
case MYSOFA_INTERNAL_ERROR: return "Internal error";
|
||||
case MYSOFA_NO_MEMORY: return "Out of memory";
|
||||
case MYSOFA_READ_ERROR: return "Read error";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
std::vector<SofaField> GetCompatibleLayout(const size_t m, const float *xyzs)
|
||||
{
|
||||
auto aers = std::vector<double3>(m, double3{});
|
||||
for(size_t i{0u};i < m;++i)
|
||||
{
|
||||
float vals[3]{xyzs[i*3], xyzs[i*3 + 1], xyzs[i*3 + 2]};
|
||||
mysofa_c2s(&vals[0]);
|
||||
aers[i] = {vals[0], vals[1], vals[2]};
|
||||
}
|
||||
|
||||
auto radii = GetUniquelySortedElems(aers, 2, {}, {0.1, 0.1, 0.001});
|
||||
std::vector<SofaField> fds;
|
||||
fds.reserve(radii.size());
|
||||
|
||||
for(const double dist : radii)
|
||||
{
|
||||
auto elevs = GetUniquelySortedElems(aers, 1, {nullptr, nullptr, &dist}, {0.1, 0.1, 0.001});
|
||||
|
||||
/* Remove elevations that don't have a valid set of azimuths. */
|
||||
auto invalid_elev = [&dist,&aers](const double ev) -> bool
|
||||
{
|
||||
auto azims = GetUniquelySortedElems(aers, 0, {nullptr, &ev, &dist}, {0.1, 0.1, 0.001});
|
||||
|
||||
if(std::abs(ev) > 89.999)
|
||||
return azims.size() != 1;
|
||||
if(azims.empty() || !(std::abs(azims[0]) < 0.1))
|
||||
return true;
|
||||
return GetUniformAzimStep(0.1, azims) <= 0.0;
|
||||
};
|
||||
elevs.erase(std::remove_if(elevs.begin(), elevs.end(), invalid_elev), elevs.end());
|
||||
|
||||
double step{GetUniformElevStep(0.1, elevs)};
|
||||
if(step <= 0.0)
|
||||
{
|
||||
if(elevs.empty())
|
||||
fprintf(stdout, "No usable elevations on field distance %f.\n", dist);
|
||||
else
|
||||
{
|
||||
fprintf(stdout, "Non-uniform elevations on field distance %.3f.\nGot: %+.2f", dist,
|
||||
elevs[0]);
|
||||
for(size_t ei{1u};ei < elevs.size();++ei)
|
||||
fprintf(stdout, ", %+.2f", elevs[ei]);
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
uint evStart{0u};
|
||||
for(uint ei{0u};ei < elevs.size();ei++)
|
||||
{
|
||||
if(!(elevs[ei] < 0.0))
|
||||
{
|
||||
fprintf(stdout, "Too many missing elevations on field distance %f.\n", dist);
|
||||
return fds;
|
||||
}
|
||||
|
||||
double eif{(90.0+elevs[ei]) / step};
|
||||
const double ev_start{std::round(eif)};
|
||||
|
||||
if(std::abs(eif - ev_start) < (0.1/step))
|
||||
{
|
||||
evStart = static_cast<uint>(ev_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto evCount = static_cast<uint>(std::round(180.0 / step)) + 1;
|
||||
if(evCount < 5)
|
||||
{
|
||||
fprintf(stdout, "Too few uniform elevations on field distance %f.\n", dist);
|
||||
continue;
|
||||
}
|
||||
|
||||
SofaField field{};
|
||||
field.mDistance = dist;
|
||||
field.mEvCount = evCount;
|
||||
field.mEvStart = evStart;
|
||||
field.mAzCounts.resize(evCount, 0u);
|
||||
auto &azCounts = field.mAzCounts;
|
||||
|
||||
for(uint ei{evStart};ei < evCount;ei++)
|
||||
{
|
||||
double ev{-90.0 + ei*180.0/(evCount - 1)};
|
||||
auto azims = GetUniquelySortedElems(aers, 0, {nullptr, &ev, &dist}, {0.1, 0.1, 0.001});
|
||||
|
||||
if(ei == 0 || ei == (evCount-1))
|
||||
{
|
||||
if(azims.size() != 1)
|
||||
{
|
||||
fprintf(stdout, "Non-singular poles on field distance %f.\n", dist);
|
||||
return fds;
|
||||
}
|
||||
azCounts[ei] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
step = GetUniformAzimStep(0.1, azims);
|
||||
if(step <= 0.0)
|
||||
{
|
||||
fprintf(stdout, "Non-uniform azimuths on elevation %f, field distance %f.\n",
|
||||
ev, dist);
|
||||
return fds;
|
||||
}
|
||||
azCounts[ei] = static_cast<uint>(std::round(360.0f / step));
|
||||
}
|
||||
}
|
||||
|
||||
fds.emplace_back(std::move(field));
|
||||
}
|
||||
|
||||
return fds;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#ifndef UTILS_SOFA_SUPPORT_H
|
||||
#define UTILS_SOFA_SUPPORT_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "mysofa.h"
|
||||
|
||||
|
||||
struct MySofaDeleter {
|
||||
void operator()(MYSOFA_HRTF *sofa) { mysofa_free(sofa); }
|
||||
};
|
||||
using MySofaHrtfPtr = std::unique_ptr<MYSOFA_HRTF,MySofaDeleter>;
|
||||
|
||||
// Per-field measurement info.
|
||||
struct SofaField {
|
||||
using uint = unsigned int;
|
||||
|
||||
double mDistance{0.0};
|
||||
uint mEvCount{0u};
|
||||
uint mEvStart{0u};
|
||||
std::vector<uint> mAzCounts;
|
||||
};
|
||||
|
||||
const char *SofaErrorStr(int err);
|
||||
|
||||
std::vector<SofaField> GetCompatibleLayout(const size_t m, const float *xyzs);
|
||||
|
||||
#endif /* UTILS_SOFA_SUPPORT_H */
|
@ -1,538 +0,0 @@
|
||||
/*
|
||||
* 2-channel UHJ Decoder
|
||||
*
|
||||
* Copyright (c) Chris Robinson <chris.kcat@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <array>
|
||||
#include <complex>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "albit.h"
|
||||
#include "albyte.h"
|
||||
#include "alcomplex.h"
|
||||
#include "almalloc.h"
|
||||
#include "alnumbers.h"
|
||||
#include "alspan.h"
|
||||
#include "vector.h"
|
||||
#include "opthelpers.h"
|
||||
#include "phase_shifter.h"
|
||||
|
||||
#include "sndfile.h"
|
||||
|
||||
#include "win_main_utf8.h"
|
||||
|
||||
|
||||
struct FileDeleter {
|
||||
void operator()(FILE *file) { fclose(file); }
|
||||
};
|
||||
using FilePtr = std::unique_ptr<FILE,FileDeleter>;
|
||||
|
||||
struct SndFileDeleter {
|
||||
void operator()(SNDFILE *sndfile) { sf_close(sndfile); }
|
||||
};
|
||||
using SndFilePtr = std::unique_ptr<SNDFILE,SndFileDeleter>;
|
||||
|
||||
|
||||
using ubyte = unsigned char;
|
||||
using ushort = unsigned short;
|
||||
using uint = unsigned int;
|
||||
using complex_d = std::complex<double>;
|
||||
|
||||
using byte4 = std::array<al::byte,4>;
|
||||
|
||||
|
||||
constexpr ubyte SUBTYPE_BFORMAT_FLOAT[]{
|
||||
0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
|
||||
0xca, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void fwrite16le(ushort val, FILE *f)
|
||||
{
|
||||
ubyte data[2]{ static_cast<ubyte>(val&0xff), static_cast<ubyte>((val>>8)&0xff) };
|
||||
fwrite(data, 1, 2, f);
|
||||
}
|
||||
|
||||
void fwrite32le(uint val, FILE *f)
|
||||
{
|
||||
ubyte data[4]{ static_cast<ubyte>(val&0xff), static_cast<ubyte>((val>>8)&0xff),
|
||||
static_cast<ubyte>((val>>16)&0xff), static_cast<ubyte>((val>>24)&0xff) };
|
||||
fwrite(data, 1, 4, f);
|
||||
}
|
||||
|
||||
template<al::endian = al::endian::native>
|
||||
byte4 f32AsLEBytes(const float &value) = delete;
|
||||
|
||||
template<>
|
||||
byte4 f32AsLEBytes<al::endian::little>(const float &value)
|
||||
{
|
||||
byte4 ret{};
|
||||
std::memcpy(ret.data(), &value, 4);
|
||||
return ret;
|
||||
}
|
||||
template<>
|
||||
byte4 f32AsLEBytes<al::endian::big>(const float &value)
|
||||
{
|
||||
byte4 ret{};
|
||||
std::memcpy(ret.data(), &value, 4);
|
||||
std::swap(ret[0], ret[3]);
|
||||
std::swap(ret[1], ret[2]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
constexpr uint BufferLineSize{1024};
|
||||
|
||||
using FloatBufferLine = std::array<float,BufferLineSize>;
|
||||
using FloatBufferSpan = al::span<float,BufferLineSize>;
|
||||
|
||||
|
||||
struct UhjDecoder {
|
||||
constexpr static size_t sFilterDelay{1024};
|
||||
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mS{};
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mD{};
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mT{};
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mQ{};
|
||||
|
||||
/* History for the FIR filter. */
|
||||
alignas(16) std::array<float,sFilterDelay-1> mDTHistory{};
|
||||
alignas(16) std::array<float,sFilterDelay-1> mSHistory{};
|
||||
|
||||
alignas(16) std::array<float,BufferLineSize + sFilterDelay*2> mTemp{};
|
||||
|
||||
void decode(const float *RESTRICT InSamples, const size_t InChannels,
|
||||
const al::span<FloatBufferLine> OutSamples, const size_t SamplesToDo);
|
||||
void decode2(const float *RESTRICT InSamples, const al::span<FloatBufferLine> OutSamples,
|
||||
const size_t SamplesToDo);
|
||||
|
||||
DEF_NEWDEL(UhjDecoder)
|
||||
};
|
||||
|
||||
const PhaseShifterT<UhjDecoder::sFilterDelay*2> PShift{};
|
||||
|
||||
|
||||
/* Decoding UHJ is done as:
|
||||
*
|
||||
* S = Left + Right
|
||||
* D = Left - Right
|
||||
*
|
||||
* W = 0.981532*S + 0.197484*j(0.828331*D + 0.767820*T)
|
||||
* X = 0.418496*S - j(0.828331*D + 0.767820*T)
|
||||
* Y = 0.795968*D - 0.676392*T + j(0.186633*S)
|
||||
* Z = 1.023332*Q
|
||||
*
|
||||
* where j is a +90 degree phase shift. 3-channel UHJ excludes Q, while 2-
|
||||
* channel excludes Q and T. The B-Format signal reconstructed from 2-channel
|
||||
* UHJ should not be run through a normal B-Format decoder, as it needs
|
||||
* different shelf filters.
|
||||
*
|
||||
* NOTE: Some sources specify
|
||||
*
|
||||
* S = (Left + Right)/2
|
||||
* D = (Left - Right)/2
|
||||
*
|
||||
* However, this is incorrect. It's halving Left and Right even though they
|
||||
* were already halved during encoding, causing S and D to be half what they
|
||||
* initially were at the encoding stage. This division is not present in
|
||||
* Gerzon's original paper for deriving Sigma (S) or Delta (D) from the L and R
|
||||
* signals. As proof, taking Y for example:
|
||||
*
|
||||
* Y = 0.795968*D - 0.676392*T + j(0.186633*S)
|
||||
*
|
||||
* * Plug in the encoding parameters, using ? as a placeholder for whether S
|
||||
* and D should receive an extra 0.5 factor
|
||||
* Y = 0.795968*(j(-0.3420201*W + 0.5098604*X) + 0.6554516*Y)*? -
|
||||
* 0.676392*(j(-0.1432*W + 0.6512*X) - 0.7071068*Y) +
|
||||
* 0.186633*j(0.9396926*W + 0.1855740*X)*?
|
||||
*
|
||||
* * Move common factors in
|
||||
* Y = (j(-0.3420201*0.795968*?*W + 0.5098604*0.795968*?*X) + 0.6554516*0.795968*?*Y) -
|
||||
* (j(-0.1432*0.676392*W + 0.6512*0.676392*X) - 0.7071068*0.676392*Y) +
|
||||
* j(0.9396926*0.186633*?*W + 0.1855740*0.186633*?*X)
|
||||
*
|
||||
* * Clean up extraneous groupings
|
||||
* Y = j(-0.3420201*0.795968*?*W + 0.5098604*0.795968*?*X) + 0.6554516*0.795968*?*Y -
|
||||
* j(-0.1432*0.676392*W + 0.6512*0.676392*X) + 0.7071068*0.676392*Y +
|
||||
* j*(0.9396926*0.186633*?*W + 0.1855740*0.186633*?*X)
|
||||
*
|
||||
* * Move phase shifts together and combine them
|
||||
* Y = j(-0.3420201*0.795968*?*W + 0.5098604*0.795968*?*X - -0.1432*0.676392*W -
|
||||
* 0.6512*0.676392*X + 0.9396926*0.186633*?*W + 0.1855740*0.186633*?*X) +
|
||||
* 0.6554516*0.795968*?*Y + 0.7071068*0.676392*Y
|
||||
*
|
||||
* * Reorder terms
|
||||
* Y = j(-0.3420201*0.795968*?*W + 0.1432*0.676392*W + 0.9396926*0.186633*?*W +
|
||||
* 0.5098604*0.795968*?*X + -0.6512*0.676392*X + 0.1855740*0.186633*?*X) +
|
||||
* 0.7071068*0.676392*Y + 0.6554516*0.795968*?*Y
|
||||
*
|
||||
* * Move common factors out
|
||||
* Y = j((-0.3420201*0.795968*? + 0.1432*0.676392 + 0.9396926*0.186633*?)*W +
|
||||
* ( 0.5098604*0.795968*? + -0.6512*0.676392 + 0.1855740*0.186633*?)*X) +
|
||||
* (0.7071068*0.676392 + 0.6554516*0.795968*?)*Y
|
||||
*
|
||||
* * Result w/ 0.5 factor:
|
||||
* -0.3420201*0.795968*0.5 + 0.1432*0.676392 + 0.9396926*0.186633*0.5 = 0.04843*W
|
||||
* 0.5098604*0.795968*0.5 + -0.6512*0.676392 + 0.1855740*0.186633*0.5 = -0.22023*X
|
||||
* 0.7071068*0.676392 + 0.6554516*0.795968*0.5 = 0.73914*Y
|
||||
* -> Y = j(0.04843*W + -0.22023*X) + 0.73914*Y
|
||||
*
|
||||
* * Result w/o 0.5 factor:
|
||||
* -0.3420201*0.795968 + 0.1432*0.676392 + 0.9396926*0.186633 = 0.00000*W
|
||||
* 0.5098604*0.795968 + -0.6512*0.676392 + 0.1855740*0.186633 = 0.00000*X
|
||||
* 0.7071068*0.676392 + 0.6554516*0.795968 = 1.00000*Y
|
||||
* -> Y = j(0.00000*W + 0.00000*X) + 1.00000*Y
|
||||
*
|
||||
* Not halving produces a result matching the original input.
|
||||
*/
|
||||
void UhjDecoder::decode(const float *RESTRICT InSamples, const size_t InChannels,
|
||||
const al::span<FloatBufferLine> OutSamples, const size_t SamplesToDo)
|
||||
{
|
||||
ASSUME(SamplesToDo > 0);
|
||||
|
||||
float *woutput{OutSamples[0].data()};
|
||||
float *xoutput{OutSamples[1].data()};
|
||||
float *youtput{OutSamples[2].data()};
|
||||
|
||||
/* Add a delay to the input channels, to align it with the all-passed
|
||||
* signal.
|
||||
*/
|
||||
|
||||
/* S = Left + Right */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mS[sFilterDelay+i] = InSamples[i*InChannels + 0] + InSamples[i*InChannels + 1];
|
||||
|
||||
/* D = Left - Right */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mD[sFilterDelay+i] = InSamples[i*InChannels + 0] - InSamples[i*InChannels + 1];
|
||||
|
||||
if(InChannels > 2)
|
||||
{
|
||||
/* T */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mT[sFilterDelay+i] = InSamples[i*InChannels + 2];
|
||||
}
|
||||
if(InChannels > 3)
|
||||
{
|
||||
/* Q */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mQ[sFilterDelay+i] = InSamples[i*InChannels + 3];
|
||||
}
|
||||
|
||||
/* Precompute j(0.828331*D + 0.767820*T) and store in xoutput. */
|
||||
auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin());
|
||||
std::transform(mD.cbegin(), mD.cbegin()+SamplesToDo+sFilterDelay, mT.cbegin(), tmpiter,
|
||||
[](const float d, const float t) noexcept { return 0.828331f*d + 0.767820f*t; });
|
||||
std::copy_n(mTemp.cbegin()+SamplesToDo, mDTHistory.size(), mDTHistory.begin());
|
||||
PShift.process({xoutput, SamplesToDo}, mTemp.data());
|
||||
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
{
|
||||
/* W = 0.981532*S + 0.197484*j(0.828331*D + 0.767820*T) */
|
||||
woutput[i] = 0.981532f*mS[i] + 0.197484f*xoutput[i];
|
||||
/* X = 0.418496*S - j(0.828331*D + 0.767820*T) */
|
||||
xoutput[i] = 0.418496f*mS[i] - xoutput[i];
|
||||
}
|
||||
|
||||
/* Precompute j*S and store in youtput. */
|
||||
tmpiter = std::copy(mSHistory.cbegin(), mSHistory.cend(), mTemp.begin());
|
||||
std::copy_n(mS.cbegin(), SamplesToDo+sFilterDelay, tmpiter);
|
||||
std::copy_n(mTemp.cbegin()+SamplesToDo, mSHistory.size(), mSHistory.begin());
|
||||
PShift.process({youtput, SamplesToDo}, mTemp.data());
|
||||
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
{
|
||||
/* Y = 0.795968*D - 0.676392*T + j(0.186633*S) */
|
||||
youtput[i] = 0.795968f*mD[i] - 0.676392f*mT[i] + 0.186633f*youtput[i];
|
||||
}
|
||||
|
||||
if(OutSamples.size() > 3)
|
||||
{
|
||||
float *zoutput{OutSamples[3].data()};
|
||||
/* Z = 1.023332*Q */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
zoutput[i] = 1.023332f*mQ[i];
|
||||
}
|
||||
|
||||
std::copy(mS.begin()+SamplesToDo, mS.begin()+SamplesToDo+sFilterDelay, mS.begin());
|
||||
std::copy(mD.begin()+SamplesToDo, mD.begin()+SamplesToDo+sFilterDelay, mD.begin());
|
||||
std::copy(mT.begin()+SamplesToDo, mT.begin()+SamplesToDo+sFilterDelay, mT.begin());
|
||||
std::copy(mQ.begin()+SamplesToDo, mQ.begin()+SamplesToDo+sFilterDelay, mQ.begin());
|
||||
}
|
||||
|
||||
/* This is an alternative equation for decoding 2-channel UHJ. Not sure what
|
||||
* the intended benefit is over the above equation as this slightly reduces the
|
||||
* amount of the original left response and has more of the phase-shifted
|
||||
* forward response on the left response.
|
||||
*
|
||||
* This decoding is done as:
|
||||
*
|
||||
* S = Left + Right
|
||||
* D = Left - Right
|
||||
*
|
||||
* W = 0.981530*S + j*0.163585*D
|
||||
* X = 0.418504*S - j*0.828347*D
|
||||
* Y = 0.762956*D + j*0.384230*S
|
||||
*
|
||||
* where j is a +90 degree phase shift.
|
||||
*
|
||||
* NOTE: As above, S and D should not be halved. The only consequence of
|
||||
* halving here is merely a -6dB reduction in output, but it's still incorrect.
|
||||
*/
|
||||
void UhjDecoder::decode2(const float *RESTRICT InSamples,
|
||||
const al::span<FloatBufferLine> OutSamples, const size_t SamplesToDo)
|
||||
{
|
||||
ASSUME(SamplesToDo > 0);
|
||||
|
||||
float *woutput{OutSamples[0].data()};
|
||||
float *xoutput{OutSamples[1].data()};
|
||||
float *youtput{OutSamples[2].data()};
|
||||
|
||||
/* S = Left + Right */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mS[sFilterDelay+i] = InSamples[i*2 + 0] + InSamples[i*2 + 1];
|
||||
|
||||
/* D = Left - Right */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mD[sFilterDelay+i] = InSamples[i*2 + 0] - InSamples[i*2 + 1];
|
||||
|
||||
/* Precompute j*D and store in xoutput. */
|
||||
auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin());
|
||||
std::copy_n(mD.cbegin(), SamplesToDo+sFilterDelay, tmpiter);
|
||||
std::copy_n(mTemp.cbegin()+SamplesToDo, mDTHistory.size(), mDTHistory.begin());
|
||||
PShift.process({xoutput, SamplesToDo}, mTemp.data());
|
||||
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
{
|
||||
/* W = 0.981530*S + j*0.163585*D */
|
||||
woutput[i] = 0.981530f*mS[i] + 0.163585f*xoutput[i];
|
||||
/* X = 0.418504*S - j*0.828347*D */
|
||||
xoutput[i] = 0.418504f*mS[i] - 0.828347f*xoutput[i];
|
||||
}
|
||||
|
||||
/* Precompute j*S and store in youtput. */
|
||||
tmpiter = std::copy(mSHistory.cbegin(), mSHistory.cend(), mTemp.begin());
|
||||
std::copy_n(mS.cbegin(), SamplesToDo+sFilterDelay, tmpiter);
|
||||
std::copy_n(mTemp.cbegin()+SamplesToDo, mSHistory.size(), mSHistory.begin());
|
||||
PShift.process({youtput, SamplesToDo}, mTemp.data());
|
||||
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
{
|
||||
/* Y = 0.762956*D + j*0.384230*S */
|
||||
youtput[i] = 0.762956f*mD[i] + 0.384230f*youtput[i];
|
||||
}
|
||||
|
||||
std::copy(mS.begin()+SamplesToDo, mS.begin()+SamplesToDo+sFilterDelay, mS.begin());
|
||||
std::copy(mD.begin()+SamplesToDo, mD.begin()+SamplesToDo+sFilterDelay, mD.begin());
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if(argc < 2 || std::strcmp(argv[1], "-h") == 0 || std::strcmp(argv[1], "--help") == 0)
|
||||
{
|
||||
printf("Usage: %s <[options] filename.wav...>\n\n"
|
||||
" Options:\n"
|
||||
" --general Use the general equations for 2-channel UHJ (default).\n"
|
||||
" --alternative Use the alternative equations for 2-channel UHJ.\n"
|
||||
"\n"
|
||||
"Note: When decoding 2-channel UHJ to an .amb file, the result should not use\n"
|
||||
"the normal B-Format shelf filters! Only 3- and 4-channel UHJ can accurately\n"
|
||||
"reconstruct the original B-Format signal.",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t num_files{0}, num_decoded{0};
|
||||
bool use_general{true};
|
||||
for(int fidx{1};fidx < argc;++fidx)
|
||||
{
|
||||
if(std::strcmp(argv[fidx], "--general") == 0)
|
||||
{
|
||||
use_general = true;
|
||||
continue;
|
||||
}
|
||||
if(std::strcmp(argv[fidx], "--alternative") == 0)
|
||||
{
|
||||
use_general = false;
|
||||
continue;
|
||||
}
|
||||
++num_files;
|
||||
SF_INFO ininfo{};
|
||||
SndFilePtr infile{sf_open(argv[fidx], SFM_READ, &ininfo)};
|
||||
if(!infile)
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s\n", argv[fidx]);
|
||||
continue;
|
||||
}
|
||||
if(sf_command(infile.get(), SFC_WAVEX_GET_AMBISONIC, NULL, 0) == SF_AMBISONIC_B_FORMAT)
|
||||
{
|
||||
fprintf(stderr, "%s is already B-Format\n", argv[fidx]);
|
||||
continue;
|
||||
}
|
||||
uint outchans{};
|
||||
if(ininfo.channels == 2)
|
||||
outchans = 3;
|
||||
else if(ininfo.channels == 3 || ininfo.channels == 4)
|
||||
outchans = static_cast<uint>(ininfo.channels);
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s is not a 2-, 3-, or 4-channel file\n", argv[fidx]);
|
||||
continue;
|
||||
}
|
||||
printf("Converting %s from %d-channel UHJ%s...\n", argv[fidx], ininfo.channels,
|
||||
(ininfo.channels == 2) ? use_general ? " (general)" : " (alternative)" : "");
|
||||
|
||||
std::string outname{argv[fidx]};
|
||||
auto lastslash = outname.find_last_of('/');
|
||||
if(lastslash != std::string::npos)
|
||||
outname.erase(0, lastslash+1);
|
||||
auto lastdot = outname.find_last_of('.');
|
||||
if(lastdot != std::string::npos)
|
||||
outname.resize(lastdot+1);
|
||||
outname += "amb";
|
||||
|
||||
FilePtr outfile{fopen(outname.c_str(), "wb")};
|
||||
if(!outfile)
|
||||
{
|
||||
fprintf(stderr, "Failed to create %s\n", outname.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
fputs("RIFF", outfile.get());
|
||||
fwrite32le(0xFFFFFFFF, outfile.get()); // 'RIFF' header len; filled in at close
|
||||
|
||||
fputs("WAVE", outfile.get());
|
||||
|
||||
fputs("fmt ", outfile.get());
|
||||
fwrite32le(40, outfile.get()); // 'fmt ' header len; 40 bytes for EXTENSIBLE
|
||||
|
||||
// 16-bit val, format type id (extensible: 0xFFFE)
|
||||
fwrite16le(0xFFFE, outfile.get());
|
||||
// 16-bit val, channel count
|
||||
fwrite16le(static_cast<ushort>(outchans), outfile.get());
|
||||
// 32-bit val, frequency
|
||||
fwrite32le(static_cast<uint>(ininfo.samplerate), outfile.get());
|
||||
// 32-bit val, bytes per second
|
||||
fwrite32le(static_cast<uint>(ininfo.samplerate)*sizeof(float)*outchans, outfile.get());
|
||||
// 16-bit val, frame size
|
||||
fwrite16le(static_cast<ushort>(sizeof(float)*outchans), outfile.get());
|
||||
// 16-bit val, bits per sample
|
||||
fwrite16le(static_cast<ushort>(sizeof(float)*8), outfile.get());
|
||||
// 16-bit val, extra byte count
|
||||
fwrite16le(22, outfile.get());
|
||||
// 16-bit val, valid bits per sample
|
||||
fwrite16le(static_cast<ushort>(sizeof(float)*8), outfile.get());
|
||||
// 32-bit val, channel mask
|
||||
fwrite32le(0, outfile.get());
|
||||
// 16 byte GUID, sub-type format
|
||||
fwrite(SUBTYPE_BFORMAT_FLOAT, 1, 16, outfile.get());
|
||||
|
||||
fputs("data", outfile.get());
|
||||
fwrite32le(0xFFFFFFFF, outfile.get()); // 'data' header len; filled in at close
|
||||
if(ferror(outfile.get()))
|
||||
{
|
||||
fprintf(stderr, "Error writing wave file header: %s (%d)\n", strerror(errno), errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto DataStart = ftell(outfile.get());
|
||||
|
||||
auto decoder = std::make_unique<UhjDecoder>();
|
||||
auto inmem = std::make_unique<float[]>(BufferLineSize*static_cast<uint>(ininfo.channels));
|
||||
auto decmem = al::vector<std::array<float,BufferLineSize>, 16>(outchans);
|
||||
auto outmem = std::make_unique<byte4[]>(BufferLineSize*outchans);
|
||||
|
||||
/* A number of initial samples need to be skipped to cut the lead-in
|
||||
* from the all-pass filter delay. The same number of samples need to
|
||||
* be fed through the decoder after reaching the end of the input file
|
||||
* to ensure none of the original input is lost.
|
||||
*/
|
||||
size_t LeadIn{UhjDecoder::sFilterDelay};
|
||||
sf_count_t LeadOut{UhjDecoder::sFilterDelay};
|
||||
while(LeadOut > 0)
|
||||
{
|
||||
sf_count_t sgot{sf_readf_float(infile.get(), inmem.get(), BufferLineSize)};
|
||||
sgot = std::max<sf_count_t>(sgot, 0);
|
||||
if(sgot < BufferLineSize)
|
||||
{
|
||||
const sf_count_t remaining{std::min(BufferLineSize - sgot, LeadOut)};
|
||||
std::fill_n(inmem.get() + sgot*ininfo.channels, remaining*ininfo.channels, 0.0f);
|
||||
sgot += remaining;
|
||||
LeadOut -= remaining;
|
||||
}
|
||||
|
||||
auto got = static_cast<size_t>(sgot);
|
||||
if(ininfo.channels > 2 || use_general)
|
||||
decoder->decode(inmem.get(), static_cast<uint>(ininfo.channels), decmem, got);
|
||||
else
|
||||
decoder->decode2(inmem.get(), decmem, got);
|
||||
if(LeadIn >= got)
|
||||
{
|
||||
LeadIn -= got;
|
||||
continue;
|
||||
}
|
||||
|
||||
got -= LeadIn;
|
||||
for(size_t i{0};i < got;++i)
|
||||
{
|
||||
/* Attenuate by -3dB for FuMa output levels. */
|
||||
constexpr auto inv_sqrt2 = static_cast<float>(1.0/al::numbers::sqrt2);
|
||||
for(size_t j{0};j < outchans;++j)
|
||||
outmem[i*outchans + j] = f32AsLEBytes(decmem[j][LeadIn+i] * inv_sqrt2);
|
||||
}
|
||||
LeadIn = 0;
|
||||
|
||||
size_t wrote{fwrite(outmem.get(), sizeof(byte4)*outchans, got, outfile.get())};
|
||||
if(wrote < got)
|
||||
{
|
||||
fprintf(stderr, "Error writing wave data: %s (%d)\n", strerror(errno), errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto DataEnd = ftell(outfile.get());
|
||||
if(DataEnd > DataStart)
|
||||
{
|
||||
long dataLen{DataEnd - DataStart};
|
||||
if(fseek(outfile.get(), 4, SEEK_SET) == 0)
|
||||
fwrite32le(static_cast<uint>(DataEnd-8), outfile.get()); // 'WAVE' header len
|
||||
if(fseek(outfile.get(), DataStart-4, SEEK_SET) == 0)
|
||||
fwrite32le(static_cast<uint>(dataLen), outfile.get()); // 'data' header len
|
||||
}
|
||||
fflush(outfile.get());
|
||||
++num_decoded;
|
||||
}
|
||||
if(num_decoded == 0)
|
||||
fprintf(stderr, "Failed to decode any input files\n");
|
||||
else if(num_decoded < num_files)
|
||||
fprintf(stderr, "Decoded %zu of %zu files\n", num_decoded, num_files);
|
||||
else
|
||||
printf("Decoded %zu file%s\n", num_decoded, (num_decoded==1)?"":"s");
|
||||
return 0;
|
||||
}
|
@ -1,531 +0,0 @@
|
||||
/*
|
||||
* 2-channel UHJ Encoder
|
||||
*
|
||||
* Copyright (c) Chris Robinson <chris.kcat@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <inttypes.h>
|
||||
#include <memory>
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "almalloc.h"
|
||||
#include "alnumbers.h"
|
||||
#include "alspan.h"
|
||||
#include "opthelpers.h"
|
||||
#include "phase_shifter.h"
|
||||
#include "vector.h"
|
||||
|
||||
#include "sndfile.h"
|
||||
|
||||
#include "win_main_utf8.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct SndFileDeleter {
|
||||
void operator()(SNDFILE *sndfile) { sf_close(sndfile); }
|
||||
};
|
||||
using SndFilePtr = std::unique_ptr<SNDFILE,SndFileDeleter>;
|
||||
|
||||
|
||||
using uint = unsigned int;
|
||||
|
||||
constexpr uint BufferLineSize{1024};
|
||||
|
||||
using FloatBufferLine = std::array<float,BufferLineSize>;
|
||||
using FloatBufferSpan = al::span<float,BufferLineSize>;
|
||||
|
||||
|
||||
struct UhjEncoder {
|
||||
constexpr static size_t sFilterDelay{1024};
|
||||
|
||||
/* Delays and processing storage for the unfiltered signal. */
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mW{};
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mX{};
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mY{};
|
||||
alignas(16) std::array<float,BufferLineSize+sFilterDelay> mZ{};
|
||||
|
||||
alignas(16) std::array<float,BufferLineSize> mS{};
|
||||
alignas(16) std::array<float,BufferLineSize> mD{};
|
||||
alignas(16) std::array<float,BufferLineSize> mT{};
|
||||
|
||||
/* History for the FIR filter. */
|
||||
alignas(16) std::array<float,sFilterDelay*2 - 1> mWXHistory1{};
|
||||
alignas(16) std::array<float,sFilterDelay*2 - 1> mWXHistory2{};
|
||||
|
||||
alignas(16) std::array<float,BufferLineSize + sFilterDelay*2> mTemp{};
|
||||
|
||||
void encode(const al::span<FloatBufferLine> OutSamples,
|
||||
const al::span<FloatBufferLine,4> InSamples, const size_t SamplesToDo);
|
||||
|
||||
DEF_NEWDEL(UhjEncoder)
|
||||
};
|
||||
|
||||
const PhaseShifterT<UhjEncoder::sFilterDelay*2> PShift{};
|
||||
|
||||
|
||||
/* Encoding UHJ from B-Format is done as:
|
||||
*
|
||||
* S = 0.9396926*W + 0.1855740*X
|
||||
* D = j(-0.3420201*W + 0.5098604*X) + 0.6554516*Y
|
||||
*
|
||||
* Left = (S + D)/2.0
|
||||
* Right = (S - D)/2.0
|
||||
* T = j(-0.1432*W + 0.6512*X) - 0.7071068*Y
|
||||
* Q = 0.9772*Z
|
||||
*
|
||||
* where j is a wide-band +90 degree phase shift. T is excluded from 2-channel
|
||||
* output, and Q is excluded from 2- and 3-channel output.
|
||||
*/
|
||||
void UhjEncoder::encode(const al::span<FloatBufferLine> OutSamples,
|
||||
const al::span<FloatBufferLine,4> InSamples, const size_t SamplesToDo)
|
||||
{
|
||||
const float *RESTRICT winput{al::assume_aligned<16>(InSamples[0].data())};
|
||||
const float *RESTRICT xinput{al::assume_aligned<16>(InSamples[1].data())};
|
||||
const float *RESTRICT yinput{al::assume_aligned<16>(InSamples[2].data())};
|
||||
const float *RESTRICT zinput{al::assume_aligned<16>(InSamples[3].data())};
|
||||
|
||||
/* Combine the previously delayed input signal with the new input. */
|
||||
std::copy_n(winput, SamplesToDo, mW.begin()+sFilterDelay);
|
||||
std::copy_n(xinput, SamplesToDo, mX.begin()+sFilterDelay);
|
||||
std::copy_n(yinput, SamplesToDo, mY.begin()+sFilterDelay);
|
||||
std::copy_n(zinput, SamplesToDo, mZ.begin()+sFilterDelay);
|
||||
|
||||
/* S = 0.9396926*W + 0.1855740*X */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mS[i] = 0.9396926f*mW[i] + 0.1855740f*mX[i];
|
||||
|
||||
/* Precompute j(-0.3420201*W + 0.5098604*X) and store in mD. */
|
||||
auto tmpiter = std::copy(mWXHistory1.cbegin(), mWXHistory1.cend(), mTemp.begin());
|
||||
std::transform(winput, winput+SamplesToDo, xinput, tmpiter,
|
||||
[](const float w, const float x) noexcept -> float
|
||||
{ return -0.3420201f*w + 0.5098604f*x; });
|
||||
std::copy_n(mTemp.cbegin()+SamplesToDo, mWXHistory1.size(), mWXHistory1.begin());
|
||||
PShift.process({mD.data(), SamplesToDo}, mTemp.data());
|
||||
|
||||
/* D = j(-0.3420201*W + 0.5098604*X) + 0.6554516*Y */
|
||||
for(size_t i{0};i < SamplesToDo;++i)
|
||||
mD[i] = mD[i] + 0.6554516f*mY[i];
|
||||
|
||||
/* Left = (S + D)/2.0 */
|
||||
float *RESTRICT left{al::assume_aligned<16>(OutSamples[0].data())};
|
||||
for(size_t i{0};i < SamplesToDo;i++)
|
||||
left[i] = (mS[i] + mD[i]) * 0.5f;
|
||||
/* Right = (S - D)/2.0 */
|
||||
float *RESTRICT right{al::assume_aligned<16>(OutSamples[1].data())};
|
||||
for(size_t i{0};i < SamplesToDo;i++)
|
||||
right[i] = (mS[i] - mD[i]) * 0.5f;
|
||||
|
||||
if(OutSamples.size() > 2)
|
||||
{
|
||||
/* Precompute j(-0.1432*W + 0.6512*X) and store in mT. */
|
||||
tmpiter = std::copy(mWXHistory2.cbegin(), mWXHistory2.cend(), mTemp.begin());
|
||||
std::transform(winput, winput+SamplesToDo, xinput, tmpiter,
|
||||
[](const float w, const float x) noexcept -> float
|
||||
{ return -0.1432f*w + 0.6512f*x; });
|
||||
std::copy_n(mTemp.cbegin()+SamplesToDo, mWXHistory2.size(), mWXHistory2.begin());
|
||||
PShift.process({mT.data(), SamplesToDo}, mTemp.data());
|
||||
|
||||
/* T = j(-0.1432*W + 0.6512*X) - 0.7071068*Y */
|
||||
float *RESTRICT t{al::assume_aligned<16>(OutSamples[2].data())};
|
||||
for(size_t i{0};i < SamplesToDo;i++)
|
||||
t[i] = mT[i] - 0.7071068f*mY[i];
|
||||
}
|
||||
if(OutSamples.size() > 3)
|
||||
{
|
||||
/* Q = 0.9772*Z */
|
||||
float *RESTRICT q{al::assume_aligned<16>(OutSamples[3].data())};
|
||||
for(size_t i{0};i < SamplesToDo;i++)
|
||||
q[i] = 0.9772f*mZ[i];
|
||||
}
|
||||
|
||||
/* Copy the future samples to the front for next time. */
|
||||
std::copy(mW.cbegin()+SamplesToDo, mW.cbegin()+SamplesToDo+sFilterDelay, mW.begin());
|
||||
std::copy(mX.cbegin()+SamplesToDo, mX.cbegin()+SamplesToDo+sFilterDelay, mX.begin());
|
||||
std::copy(mY.cbegin()+SamplesToDo, mY.cbegin()+SamplesToDo+sFilterDelay, mY.begin());
|
||||
std::copy(mZ.cbegin()+SamplesToDo, mZ.cbegin()+SamplesToDo+sFilterDelay, mZ.begin());
|
||||
}
|
||||
|
||||
|
||||
struct SpeakerPos {
|
||||
int mChannelID;
|
||||
float mAzimuth;
|
||||
float mElevation;
|
||||
};
|
||||
|
||||
/* Azimuth is counter-clockwise. */
|
||||
constexpr SpeakerPos StereoMap[2]{
|
||||
{ SF_CHANNEL_MAP_LEFT, 30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_RIGHT, -30.0f, 0.0f },
|
||||
}, QuadMap[4]{
|
||||
{ SF_CHANNEL_MAP_LEFT, 45.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_RIGHT, -45.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_LEFT, 135.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_RIGHT, -135.0f, 0.0f },
|
||||
}, X51Map[6]{
|
||||
{ SF_CHANNEL_MAP_LEFT, 30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_RIGHT, -30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_CENTER, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_LFE, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_SIDE_LEFT, 110.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_SIDE_RIGHT, -110.0f, 0.0f },
|
||||
}, X51RearMap[6]{
|
||||
{ SF_CHANNEL_MAP_LEFT, 30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_RIGHT, -30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_CENTER, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_LFE, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_LEFT, 110.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_RIGHT, -110.0f, 0.0f },
|
||||
}, X71Map[8]{
|
||||
{ SF_CHANNEL_MAP_LEFT, 30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_RIGHT, -30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_CENTER, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_LFE, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_LEFT, 150.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_RIGHT, -150.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_SIDE_LEFT, 90.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_SIDE_RIGHT, -90.0f, 0.0f },
|
||||
}, X714Map[12]{
|
||||
{ SF_CHANNEL_MAP_LEFT, 30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_RIGHT, -30.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_CENTER, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_LFE, 0.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_LEFT, 150.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_REAR_RIGHT, -150.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_SIDE_LEFT, 90.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_SIDE_RIGHT, -90.0f, 0.0f },
|
||||
{ SF_CHANNEL_MAP_TOP_FRONT_LEFT, 45.0f, 35.0f },
|
||||
{ SF_CHANNEL_MAP_TOP_FRONT_RIGHT, -45.0f, 35.0f },
|
||||
{ SF_CHANNEL_MAP_TOP_REAR_LEFT, 135.0f, 35.0f },
|
||||
{ SF_CHANNEL_MAP_TOP_REAR_RIGHT, -135.0f, 35.0f },
|
||||
};
|
||||
|
||||
constexpr auto GenCoeffs(double x /*+front*/, double y /*+left*/, double z /*+up*/) noexcept
|
||||
{
|
||||
/* Coefficients are +3dB of FuMa. */
|
||||
return std::array<float,4>{{
|
||||
1.0f,
|
||||
static_cast<float>(al::numbers::sqrt2 * x),
|
||||
static_cast<float>(al::numbers::sqrt2 * y),
|
||||
static_cast<float>(al::numbers::sqrt2 * z)
|
||||
}};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if(argc < 2 || std::strcmp(argv[1], "-h") == 0 || std::strcmp(argv[1], "--help") == 0)
|
||||
{
|
||||
printf("Usage: %s <infile...>\n\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint uhjchans{2};
|
||||
size_t num_files{0}, num_encoded{0};
|
||||
for(int fidx{1};fidx < argc;++fidx)
|
||||
{
|
||||
if(strcmp(argv[fidx], "-bhj") == 0)
|
||||
{
|
||||
uhjchans = 2;
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[fidx], "-thj") == 0)
|
||||
{
|
||||
uhjchans = 3;
|
||||
continue;
|
||||
}
|
||||
if(strcmp(argv[fidx], "-phj") == 0)
|
||||
{
|
||||
uhjchans = 4;
|
||||
continue;
|
||||
}
|
||||
++num_files;
|
||||
|
||||
std::string outname{argv[fidx]};
|
||||
size_t lastslash{outname.find_last_of('/')};
|
||||
if(lastslash != std::string::npos)
|
||||
outname.erase(0, lastslash+1);
|
||||
size_t extpos{outname.find_last_of('.')};
|
||||
if(extpos != std::string::npos)
|
||||
outname.resize(extpos);
|
||||
outname += ".uhj.flac";
|
||||
|
||||
SF_INFO ininfo{};
|
||||
SndFilePtr infile{sf_open(argv[fidx], SFM_READ, &ininfo)};
|
||||
if(!infile)
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s\n", argv[fidx]);
|
||||
continue;
|
||||
}
|
||||
printf("Converting %s to %s...\n", argv[fidx], outname.c_str());
|
||||
|
||||
/* Work out the channel map, preferably using the actual channel map
|
||||
* from the file/format, but falling back to assuming WFX order.
|
||||
*/
|
||||
al::span<const SpeakerPos> spkrs;
|
||||
auto chanmap = std::vector<int>(static_cast<uint>(ininfo.channels), SF_CHANNEL_MAP_INVALID);
|
||||
if(sf_command(infile.get(), SFC_GET_CHANNEL_MAP_INFO, chanmap.data(),
|
||||
ininfo.channels*int{sizeof(int)}) == SF_TRUE)
|
||||
{
|
||||
static const std::array<int,2> stereomap{{SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT}};
|
||||
static const std::array<int,4> quadmap{{SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT,
|
||||
SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT}};
|
||||
static const std::array<int,6> x51map{{SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT,
|
||||
SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE,
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, SF_CHANNEL_MAP_SIDE_RIGHT}};
|
||||
static const std::array<int,6> x51rearmap{{SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT,
|
||||
SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE,
|
||||
SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT}};
|
||||
static const std::array<int,8> x71map{{SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT,
|
||||
SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE,
|
||||
SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT,
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, SF_CHANNEL_MAP_SIDE_RIGHT}};
|
||||
static const std::array<int,12> x714map{{SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT,
|
||||
SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE,
|
||||
SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT,
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, SF_CHANNEL_MAP_SIDE_RIGHT,
|
||||
SF_CHANNEL_MAP_TOP_FRONT_LEFT, SF_CHANNEL_MAP_TOP_FRONT_RIGHT,
|
||||
SF_CHANNEL_MAP_TOP_REAR_LEFT, SF_CHANNEL_MAP_TOP_REAR_RIGHT}};
|
||||
static const std::array<int,3> ambi2dmap{{SF_CHANNEL_MAP_AMBISONIC_B_W,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_X, SF_CHANNEL_MAP_AMBISONIC_B_Y}};
|
||||
static const std::array<int,4> ambi3dmap{{SF_CHANNEL_MAP_AMBISONIC_B_W,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_X, SF_CHANNEL_MAP_AMBISONIC_B_Y,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Z}};
|
||||
|
||||
auto match_chanmap = [](const al::span<int> a, const al::span<const int> b) -> bool
|
||||
{
|
||||
if(a.size() != b.size())
|
||||
return false;
|
||||
for(const int id : a)
|
||||
{
|
||||
if(std::find(b.begin(), b.end(), id) != b.end())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if(match_chanmap(chanmap, stereomap))
|
||||
spkrs = StereoMap;
|
||||
else if(match_chanmap(chanmap, quadmap))
|
||||
spkrs = QuadMap;
|
||||
else if(match_chanmap(chanmap, x51map))
|
||||
spkrs = X51Map;
|
||||
else if(match_chanmap(chanmap, x51rearmap))
|
||||
spkrs = X51RearMap;
|
||||
else if(match_chanmap(chanmap, x71map))
|
||||
spkrs = X71Map;
|
||||
else if(match_chanmap(chanmap, x714map))
|
||||
spkrs = X714Map;
|
||||
else if(match_chanmap(chanmap, ambi2dmap) || match_chanmap(chanmap, ambi3dmap))
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string mapstr;
|
||||
if(!chanmap.empty())
|
||||
{
|
||||
mapstr = std::to_string(chanmap[0]);
|
||||
for(int idx : al::span<int>{chanmap}.subspan<1>())
|
||||
{
|
||||
mapstr += ',';
|
||||
mapstr += std::to_string(idx);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, " ... %zu channels not supported (map: %s)\n", chanmap.size(),
|
||||
mapstr.c_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(ininfo.channels == 2)
|
||||
{
|
||||
fprintf(stderr, " ... assuming WFX order stereo\n");
|
||||
spkrs = StereoMap;
|
||||
chanmap[0] = SF_CHANNEL_MAP_FRONT_LEFT;
|
||||
chanmap[1] = SF_CHANNEL_MAP_FRONT_RIGHT;
|
||||
}
|
||||
else if(ininfo.channels == 6)
|
||||
{
|
||||
fprintf(stderr, " ... assuming WFX order 5.1\n");
|
||||
spkrs = X51Map;
|
||||
chanmap[0] = SF_CHANNEL_MAP_FRONT_LEFT;
|
||||
chanmap[1] = SF_CHANNEL_MAP_FRONT_RIGHT;
|
||||
chanmap[2] = SF_CHANNEL_MAP_FRONT_CENTER;
|
||||
chanmap[3] = SF_CHANNEL_MAP_LFE;
|
||||
chanmap[4] = SF_CHANNEL_MAP_SIDE_LEFT;
|
||||
chanmap[5] = SF_CHANNEL_MAP_SIDE_RIGHT;
|
||||
}
|
||||
else if(ininfo.channels == 8)
|
||||
{
|
||||
fprintf(stderr, " ... assuming WFX order 7.1\n");
|
||||
spkrs = X71Map;
|
||||
chanmap[0] = SF_CHANNEL_MAP_FRONT_LEFT;
|
||||
chanmap[1] = SF_CHANNEL_MAP_FRONT_RIGHT;
|
||||
chanmap[2] = SF_CHANNEL_MAP_FRONT_CENTER;
|
||||
chanmap[3] = SF_CHANNEL_MAP_LFE;
|
||||
chanmap[4] = SF_CHANNEL_MAP_REAR_LEFT;
|
||||
chanmap[5] = SF_CHANNEL_MAP_REAR_RIGHT;
|
||||
chanmap[6] = SF_CHANNEL_MAP_SIDE_LEFT;
|
||||
chanmap[7] = SF_CHANNEL_MAP_SIDE_RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " ... unmapped %d-channel audio not supported\n", ininfo.channels);
|
||||
continue;
|
||||
}
|
||||
|
||||
SF_INFO outinfo{};
|
||||
outinfo.frames = ininfo.frames;
|
||||
outinfo.samplerate = ininfo.samplerate;
|
||||
outinfo.channels = static_cast<int>(uhjchans);
|
||||
outinfo.format = SF_FORMAT_PCM_24 | SF_FORMAT_FLAC;
|
||||
SndFilePtr outfile{sf_open(outname.c_str(), SFM_WRITE, &outinfo)};
|
||||
if(!outfile)
|
||||
{
|
||||
fprintf(stderr, " ... failed to create %s\n", outname.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto encoder = std::make_unique<UhjEncoder>();
|
||||
auto splbuf = al::vector<FloatBufferLine, 16>(static_cast<uint>(9+ininfo.channels)+uhjchans);
|
||||
auto ambmem = al::span<FloatBufferLine,4>{splbuf.data(), 4};
|
||||
auto encmem = al::span<FloatBufferLine,4>{&splbuf[4], 4};
|
||||
auto srcmem = al::span<float,BufferLineSize>{splbuf[8].data(), BufferLineSize};
|
||||
auto outmem = al::span<float>{splbuf[9].data(), BufferLineSize*uhjchans};
|
||||
|
||||
/* A number of initial samples need to be skipped to cut the lead-in
|
||||
* from the all-pass filter delay. The same number of samples need to
|
||||
* be fed through the encoder after reaching the end of the input file
|
||||
* to ensure none of the original input is lost.
|
||||
*/
|
||||
size_t total_wrote{0};
|
||||
size_t LeadIn{UhjEncoder::sFilterDelay};
|
||||
sf_count_t LeadOut{UhjEncoder::sFilterDelay};
|
||||
while(LeadIn > 0 || LeadOut > 0)
|
||||
{
|
||||
auto inmem = outmem.data() + outmem.size();
|
||||
auto sgot = sf_readf_float(infile.get(), inmem, BufferLineSize);
|
||||
|
||||
sgot = std::max<sf_count_t>(sgot, 0);
|
||||
if(sgot < BufferLineSize)
|
||||
{
|
||||
const sf_count_t remaining{std::min(BufferLineSize - sgot, LeadOut)};
|
||||
std::fill_n(inmem + sgot*ininfo.channels, remaining*ininfo.channels, 0.0f);
|
||||
sgot += remaining;
|
||||
LeadOut -= remaining;
|
||||
}
|
||||
|
||||
for(auto&& buf : ambmem)
|
||||
buf.fill(0.0f);
|
||||
|
||||
auto got = static_cast<size_t>(sgot);
|
||||
if(spkrs.empty())
|
||||
{
|
||||
/* B-Format is already in the correct order. It just needs a
|
||||
* +3dB boost.
|
||||
*/
|
||||
static constexpr float scale{al::numbers::sqrt2_v<float>};
|
||||
const size_t chans{std::min<size_t>(static_cast<uint>(ininfo.channels), 4u)};
|
||||
for(size_t c{0};c < chans;++c)
|
||||
{
|
||||
for(size_t i{0};i < got;++i)
|
||||
ambmem[c][i] = inmem[i*static_cast<uint>(ininfo.channels)] * scale;
|
||||
++inmem;
|
||||
}
|
||||
}
|
||||
else for(const int chanid : chanmap)
|
||||
{
|
||||
/* Skip LFE. Or mix directly into W? Or W+X? */
|
||||
if(chanid == SF_CHANNEL_MAP_LFE)
|
||||
{
|
||||
++inmem;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto spkr = std::find_if(spkrs.cbegin(), spkrs.cend(),
|
||||
[chanid](const SpeakerPos &pos){return pos.mChannelID == chanid;});
|
||||
if(spkr == spkrs.cend())
|
||||
{
|
||||
fprintf(stderr, " ... failed to find channel ID %d\n", chanid);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(size_t i{0};i < got;++i)
|
||||
srcmem[i] = inmem[i * static_cast<uint>(ininfo.channels)];
|
||||
++inmem;
|
||||
|
||||
static constexpr auto Deg2Rad = al::numbers::pi / 180.0;
|
||||
const auto coeffs = GenCoeffs(
|
||||
std::cos(spkr->mAzimuth*Deg2Rad) * std::cos(spkr->mElevation*Deg2Rad),
|
||||
std::sin(spkr->mAzimuth*Deg2Rad) * std::cos(spkr->mElevation*Deg2Rad),
|
||||
std::sin(spkr->mElevation*Deg2Rad));
|
||||
for(size_t c{0};c < 4;++c)
|
||||
{
|
||||
for(size_t i{0};i < got;++i)
|
||||
ambmem[c][i] += srcmem[i] * coeffs[c];
|
||||
}
|
||||
}
|
||||
|
||||
encoder->encode(encmem.subspan(0, uhjchans), ambmem, got);
|
||||
if(LeadIn >= got)
|
||||
{
|
||||
LeadIn -= got;
|
||||
continue;
|
||||
}
|
||||
|
||||
got -= LeadIn;
|
||||
for(size_t c{0};c < uhjchans;++c)
|
||||
{
|
||||
constexpr float max_val{8388607.0f / 8388608.0f};
|
||||
auto clamp = [](float v, float mn, float mx) noexcept
|
||||
{ return std::min(std::max(v, mn), mx); };
|
||||
for(size_t i{0};i < got;++i)
|
||||
outmem[i*uhjchans + c] = clamp(encmem[c][LeadIn+i], -1.0f, max_val);
|
||||
}
|
||||
LeadIn = 0;
|
||||
|
||||
sf_count_t wrote{sf_writef_float(outfile.get(), outmem.data(),
|
||||
static_cast<sf_count_t>(got))};
|
||||
if(wrote < 0)
|
||||
fprintf(stderr, " ... failed to write samples: %d\n", sf_error(outfile.get()));
|
||||
else
|
||||
total_wrote += static_cast<size_t>(wrote);
|
||||
}
|
||||
printf(" ... wrote %zu samples (%" PRId64 ").\n", total_wrote, int64_t{ininfo.frames});
|
||||
++num_encoded;
|
||||
}
|
||||
if(num_encoded == 0)
|
||||
fprintf(stderr, "Failed to encode any input files\n");
|
||||
else if(num_encoded < num_files)
|
||||
fprintf(stderr, "Encoded %zu of %zu files\n", num_encoded, num_files);
|
||||
else
|
||||
printf("Encoded %s%zu file%s\n", (num_encoded > 1) ? "all " : "", num_encoded,
|
||||
(num_encoded == 1) ? "" : "s");
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user