Compare commits

..

No commits in common. 'master' and 'adpcm' have entirely different histories.

2
.gitignore vendored

@ -42,6 +42,4 @@ DerivedData
*.reapeaks
*.opendb
encoded.wav

@ -1,34 +0,0 @@
language: cpp
sudo: true
matrix:
include:
- os: linux
env: CXXFLAGS="-std=c++11"
- os: osx
env: CXXFLAGS="-std=c++11"
install:
# install latest cmake
- |
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
CMAKE_URL="https://cmake.org/files/v3.11/cmake-3.11.1-Linux-x86_64.tar.gz";
mkdir cmake_latest && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake_latest;
export PATH=$(pwd)/cmake_latest/bin:${PATH};
fi
- |
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
brew update;
brew uninstall cmake;
brew install cmake;
fi
- which ${CC}
- which ${CXX}
- which cmake
script:
- mkdir build
- cd build
- cmake -DBUILD_EXAMPLE=FALSE ..
- cmake --build .

@ -1,296 +0,0 @@
cmake_minimum_required(VERSION 3.13)
set(LIBNYQUIST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
set(CMAKE_MODULE_PATH ${LIBNYQUIST_ROOT}/cmake)
include(CXXhelpers)
if (CMAKE_OSX_ARCHITECTURES)
if(CMAKE_OSX_SYSROOT MATCHES ".*iphoneos.*")
# RtAudio is not portable to ios currently
option(BUILD_EXAMPLE "Build example application" OFF)
else()
option(BUILD_EXAMPLE "Build example application" ON)
endif()
else()
option(BUILD_EXAMPLE "Build example application" ON)
endif()
#-------------------------------------------------------------------------------
# libopus
if (BUILD_LIBOPUS)
project(libopus)
file(GLOB third_opus_src
"${LIBNYQUIST_ROOT}/third_party/opus/celt/*.c"
"${LIBNYQUIST_ROOT}/third_party/opus/opusfile/src/*.c"
"${LIBNYQUIST_ROOT}/third_party/opus/silk/*.c"
"${LIBNYQUIST_ROOT}/third_party/opus/silk/float/*.c"
)
set(lib_opus_src
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/analysis.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/mlp_data.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/mlp.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/opus_decoder.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/opus_multistream_decoder.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/opus_multistream_encoder.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/opus.c"
"${LIBNYQUIST_ROOT}/third_party/opus/libopus/src/repacketizer.c"
)
add_library(libopus STATIC ${third_opus_src} ${lib_opus_src})
set_cxx_version(libopus)
_set_compile_options(libopus)
if (WIN32)
_disable_warning(4244)
_disable_warning(4018)
endif()
target_include_directories(libopus PRIVATE
${LIBNYQUIST_ROOT}/third_party/libogg/include
${LIBNYQUIST_ROOT}/third_party/opus/celt
${LIBNYQUIST_ROOT}/third_party/opus/libopus/include
${LIBNYQUIST_ROOT}/third_party/opus/opusfile/include
${LIBNYQUIST_ROOT}/third_party/opus/opusfile/src/include
${LIBNYQUIST_ROOT}/third_party/opus/silk
${LIBNYQUIST_ROOT}/third_party/opus/silk/float)
if (MSVC_IDE)
# hack to get around the "Debug" and "Release" directories cmake tries to add on Windows
#set_target_properties(libnyquist PROPERTIES PREFIX "../")
set_target_properties(libopus PROPERTIES IMPORT_PREFIX "../")
endif()
target_compile_definitions(libopus PRIVATE OPUS_BUILD)
target_compile_definitions(libopus PRIVATE USE_ALLOCA)
set_target_properties(libopus
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
set_target_properties(libopus PROPERTIES OUTPUT_NAME_DEBUG libopus_d)
install (TARGETS libopus
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin)
install (TARGETS libopus DESTINATION lib)
# folders
source_group(src FILES ${third_opus_src})
endif()
#-------------------------------------------------------------------------------
# libwavpack
project(libwavpack)
if(MSVC)
# Disable warning C4996 regarding fopen(), strcpy(), etc.
_add_define("_CRT_SECURE_NO_WARNINGS")
# Disable warning C4996 regarding unchecked iterators for std::transform,
# std::copy, std::equal, et al.
_add_define("_SCL_SECURE_NO_WARNINGS")
# Make sure WinDef.h does not define min and max macros which
# will conflict with std::min() and std::max().
_add_define("NOMINMAX")
endif()
add_definitions(${_NQR_CXX_DEFINITIONS})
set(CMAKE_CXX_FLAGS "${_NQR_CXX_FLAGS} ${CMAKE_CXX_FLAGS}")
file(GLOB third_wavpack_src "${LIBNYQUIST_ROOT}/third_party/wavpack/src/*")
add_library(libwavpack STATIC ${third_wavpack_src})
set_cxx_version(libwavpack)
_set_compile_options(libwavpack)
if (WIN32)
_disable_warning(181)
_disable_warning(111)
_disable_warning(4267)
_disable_warning(4996)
_disable_warning(4244)
_disable_warning(4701)
_disable_warning(4702)
_disable_warning(4133)
_disable_warning(4100)
_disable_warning(4127)
_disable_warning(4206)
_disable_warning(4312)
_disable_warning(4505)
_disable_warning(4365)
_disable_warning(4005)
_disable_warning(4013)
_disable_warning(4334)
_disable_warning(4703)
endif()
target_include_directories(libwavpack PRIVATE ${LIBNYQUIST_ROOT}/third_party/wavpack/include)
if (MSVC_IDE)
set_target_properties(libwavpack PROPERTIES IMPORT_PREFIX "../")
endif()
set_target_properties(libwavpack
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
set_target_properties(libwavpack PROPERTIES OUTPUT_NAME_DEBUG libwavpack_d)
install(TARGETS libwavpack
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin)
install (TARGETS libwavpack DESTINATION lib)
#-------------------------------------------------------------------------------
# libnyquist static library
project(libnyquist)
file(GLOB nyquist_include "${LIBNYQUIST_ROOT}/include/libnyquist/*")
file(GLOB nyquist_src "${LIBNYQUIST_ROOT}/src/*")
file(GLOB wavpack_src "${LIBNYQUIST_ROOT}/third_party/wavpack/src/*")
add_library(libnyquist STATIC
${nyquist_include}
${nyquist_src}
)
set_cxx_version(libnyquist)
_set_compile_options(libnyquist)
if (WIN32)
_disable_warning(4244)
_disable_warning(4018)
endif()
target_include_directories(libnyquist
PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${LIBNYQUIST_ROOT}/include>
PRIVATE
${LIBNYQUIST_ROOT}/include/libnyquist
${LIBNYQUIST_ROOT}/third_party
${LIBNYQUIST_ROOT}/third_party/FLAC/src/include
${LIBNYQUIST_ROOT}/third_party/libogg/include
${LIBNYQUIST_ROOT}/third_party/libvorbis/include
${LIBNYQUIST_ROOT}/third_party/libvorbis/src
${LIBNYQUIST_ROOT}/third_party/musepack/include
${LIBNYQUIST_ROOT}/third_party/opus/celt
${LIBNYQUIST_ROOT}/third_party/opus/libopus/include
${LIBNYQUIST_ROOT}/third_party/opus/opusfile/include
${LIBNYQUIST_ROOT}/third_party/opus/opusfile/src/include
${LIBNYQUIST_ROOT}/third_party/opus/silk
${LIBNYQUIST_ROOT}/third_party/opus/silk/float
${LIBNYQUIST_ROOT}/third_party/wavpack/include
${LIBNYQUIST_ROOT}/src
)
if (MSVC_IDE)
# hack to get around the "Debug" and "Release" directories cmake tries to add on Windows
#set_target_properties(libnyquist PROPERTIES PREFIX "../")
set_target_properties(libnyquist PROPERTIES IMPORT_PREFIX "../")
endif()
set_target_properties(libnyquist PROPERTIES OUTPUT_NAME_DEBUG libnyquist_d)
set_target_properties(libnyquist
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
target_link_libraries(libnyquist PRIVATE libwavpack)
install(TARGETS libnyquist
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin)
install(TARGETS libnyquist DESTINATION lib)
# folders
source_group(src FILES ${nyquist_src})
#-------------------------------------------------------------------------------
# libnyquist-examples
if(BUILD_EXAMPLE)
set(NQR_EXAMPLE_APP_NAME "libnyquist-examples")
set(
EXAMPLE_SOURCES
${LIBNYQUIST_ROOT}/examples/src/Main.cpp
${LIBNYQUIST_ROOT}/examples/src/AudioDevice.cpp
${LIBNYQUIST_ROOT}/examples/src/AudioDevice.h
${LIBNYQUIST_ROOT}/examples/src/RingBuffer.h
${LIBNYQUIST_ROOT}/third_party/rtaudio/RtAudio.cpp
${LIBNYQUIST_ROOT}/third_party/rtaudio/RtAudio.h
)
add_executable(${NQR_EXAMPLE_APP_NAME} ${EXAMPLE_SOURCES})
if(WIN32)
target_compile_definitions(${NQR_EXAMPLE_APP_NAME} PRIVATE __WINDOWS_WASAPI__)
elseif(APPLE)
target_compile_definitions(${NQR_EXAMPLE_APP_NAME} PRIVATE __MACOSX_CORE__)
elseif(LIBNYQUIST_JACK)
target_compile_definitions(${NQR_EXAMPLE_APP_NAME} PRIVATE __UNIX_JACK__)
target_link_libraries(${NQR_EXAMPLE_APP_NAME} PRIVATE jack pthread)
elseif(LIBNYQUIST_PULSE)
target_compile_definitions(${NQR_EXAMPLE_APP_NAME} PRIVATE __LINUX_PULSE__)
target_link_libraries(${NQR_EXAMPLE_APP_NAME} PRIVATE pulse pthread)
elseif(LIBNYQUIST_ASOUND)
target_compile_definitions(${NQR_EXAMPLE_APP_NAME} PRIVATE __LINUX_ALSA__)
target_link_libraries(${NQR_EXAMPLE_APP_NAME} PRIVATE asound pthread)
else()
message(FATAL, "On Linux, one of LIBNYQUIST_JACK, LIBNYQUIST_PULSE, or LIBNYQUIST_ASOUND must be set.")
endif()
target_include_directories(${NQR_EXAMPLE_APP_NAME} PRIVATE
${LIBNYQUIST_ROOT}/examples/src
${LIBNYQUIST_ROOT}/third_party
)
target_link_libraries(${NQR_EXAMPLE_APP_NAME} PRIVATE libnyquist)
set_target_properties(${NQR_EXAMPLE_APP_NAME}
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
if(APPLE)
target_link_libraries(${NQR_EXAMPLE_APP_NAME} PRIVATE
"-framework AudioToolbox"
"-framework AudioUnit"
"-framework Accelerate"
"-framework CoreAudio"
"-framework Cocoa"
)
ENDIF(APPLE)
endif()

@ -234,6 +234,28 @@ 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.
libmodplug (Public Domain)
Catch (Boost)
===============================================================================
ModPlug-XMMS and libmodplug are now in the public domain.
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute, execute,
and transmit the Software, and to prepare derivative works of the Software,
and to permit third-parties to whom the Software is furnished to do so, all
subject to the following:
The copyright notices in the Software and this entire statement, including the
above license grant, this restriction and the following disclaimer, must be
included in all copies of the Software, in whole or in part, and all
derivative works of the Software, unless such copies or derivative works are
solely in the form of machine-executable object code generated by a source
language processor.
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR
ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

@ -1,4 +1,4 @@
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos 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,33 +1,34 @@
# Libnyquist
Libnyquist is a small C++11 library for reading sampled audio data from disk or memory. It's ideal to use as an audio asset frontend for games, audio sequencers, music players, and more.
The library steers away from patent-encumbered formats and those with non-BSD licensed codec implementations (such as MP3 and AAC, respectively).
Platform | Build Status |
-------- | ------------ |
Microsoft VS2017 x64 | [![Build status](https://ci.appveyor.com/api/projects/status/2xeuyuxy618ndf4r?svg=true)](https://ci.appveyor.com/project/ddiakopoulos/libnyquist) |
Clang (OSX) & GCC (Linux) | [![Build Status](https://travis-ci.org/ddiakopoulos/libnyquist.svg?branch=master)](https://travis-ci.org/ddiakopoulos/libnyquist) |
Libnyquist is a small C++11 library for reading sampled audio data from disk or memory. It is intended to be used an audio loading frontend for games, audio sequencers, music players, and more.
The library does not include patent or license encumbered formats (such as AAC). For portability, libnyquist does not link against platform-specific APIs like Windows Media Foundation or CoreAudio, and instead bundles the source code of reference decoders as an implementation detail.
Libnyquist is meant to be statically linked, which is not the case with other popular libraries like libsndfile (which is licensed under the LGPL). Furthermore, the library is not concerned with supporting very rare encodings (for instance, A-law PCM or the SND format).
Libnyquist is meant to be statically linked, which is not the case with other popular libraries like libsndfile (LGPL). Furthermore, the library is not concerned with legacy format support (for instance, A-law PCM encoding or SND files).
While untested, there are no technical conditions that preclude compilation on other platforms with C++11 support (Android NDK r10e+, Linux, iOS, etc).
## Format Support
Regardless of input bit depth, the library produces a channel-interleaved float vector, normalized between [-1.0,+1.0]. At present, the library does not provide comprehensive resampling functionality.
Regardless of input bit depth, the library hands over an interleaved float array, normalized between [-1.0,+1.0]. At present, the library does not provide resampling functionality.
* Wave (+ IMA-ADPCM encoding)
* MP3
* Wave
* Ogg Vorbis
* Ogg Opus
* FLAC
* WavPack
* Musepack
* Core Audio Format (Apple Lossless / AIFF) (WIP)
## Encoding
Simple but robust WAV format encoder now included. Extentions in the near future might include Ogg.
## Supported Project Files
* Visual Studio 2013
* Visual Studio 2015
* XCode 6
## Known Issues & Bugs
* See the Github issue tracker.
## License
This library is released under the simplied 2 clause BSD license. All included dependencies have been released under identical or similarly permissive licenses.
Libyquist is released under the 2-Clause BSD license. All dependencies and codecs are under similar open licenses.

@ -1,13 +0,0 @@
# appveyor file
# http://www.appveyor.com/docs/appveyor-yml
os: Visual Studio 2017
platform:
- x64
build_script:
- mkdir build
- cd build
- cmake -G "Visual Studio 15 2017 Win64" ..
- cmake --build . --config Release

@ -1,24 +0,0 @@
function(_add_define definition)
list(APPEND _NQR_CXX_DEFINITIONS "-D${definition}")
set(_NQR_CXX_DEFINITIONS ${_NQR_CXX_DEFINITIONS} PARENT_SCOPE)
endfunction()
function(_disable_warning flag)
if(MSVC)
list(APPEND _NQR_CXX_WARNING_FLAGS "/wd${flag}")
else()
list(APPEND _NQR_CXX_WARNING_FLAGS "-Wno-${flag}")
endif()
set(_NQR_CXX_WARNING_FLAGS ${_NQR_CXX_WARNING_FLAGS} PARENT_SCOPE)
endfunction()
function(_set_compile_options proj)
if(MSVC)
target_compile_options(${proj} PRIVATE /arch:AVX /Zi )
endif()
endfunction()
function(set_cxx_version proj)
target_compile_features(${proj} INTERFACE cxx_std_14)
endfunction()

@ -0,0 +1,347 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
083DB3F11B0871D700FB0661 /* RtAudio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 083DB3EF1B0871D700FB0661 /* RtAudio.cpp */; };
08B91D791AC273A900335131 /* libpthread.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 08B91D781AC273A900335131 /* libpthread.dylib */; };
08B91D7B1AC273AE00335131 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08B91D7A1AC273AE00335131 /* CoreAudio.framework */; };
08B91D7D1AC273E400335131 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08B91D7C1AC273E400335131 /* CoreFoundation.framework */; };
08B91D7F1AC273EA00335131 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08B91D7E1AC273EA00335131 /* CoreServices.framework */; };
08B91D9F1AC73B8A00335131 /* Main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D951AC73B8A00335131 /* Main.cpp */; };
08BD8BD61B087097006C227C /* libnyquist.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 08BD8BD51B087097006C227C /* libnyquist.a */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
08B91D241AC26FC100335131 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
083DB3EF1B0871D700FB0661 /* RtAudio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RtAudio.cpp; path = ../third_party/rtaudio/RtAudio.cpp; sourceTree = SOURCE_ROOT; };
083DB3F01B0871D700FB0661 /* RtAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RtAudio.h; path = ../third_party/rtaudio/RtAudio.h; sourceTree = SOURCE_ROOT; };
08B91D261AC26FC100335131 /* nyquist-example */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "nyquist-example"; sourceTree = BUILT_PRODUCTS_DIR; };
08B91D781AC273A900335131 /* libpthread.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpthread.dylib; path = usr/lib/libpthread.dylib; sourceTree = SDKROOT; };
08B91D7A1AC273AE00335131 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
08B91D7C1AC273E400335131 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
08B91D7E1AC273EA00335131 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
08B91D951AC73B8A00335131 /* Main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Main.cpp; path = src/Main.cpp; sourceTree = SOURCE_ROOT; };
08BD8BD51B087097006C227C /* libnyquist.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libnyquist.a; path = ../../../Library/Developer/Xcode/DerivedData/bin/Debug/libnyquist.a; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
08B91D231AC26FC100335131 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
08BD8BD61B087097006C227C /* libnyquist.a in Frameworks */,
08B91D7F1AC273EA00335131 /* CoreServices.framework in Frameworks */,
08B91D7D1AC273E400335131 /* CoreFoundation.framework in Frameworks */,
08B91D7B1AC273AE00335131 /* CoreAudio.framework in Frameworks */,
08B91D791AC273A900335131 /* libpthread.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
083DB3EB1B0871B300FB0661 /* third_party */ = {
isa = PBXGroup;
children = (
083DB3EF1B0871D700FB0661 /* RtAudio.cpp */,
083DB3F01B0871D700FB0661 /* RtAudio.h */,
);
name = third_party;
sourceTree = "<group>";
};
08B91D1D1AC26FC100335131 = {
isa = PBXGroup;
children = (
08B91D281AC26FC100335131 /* Example */,
08B91D801AC73B3B00335131 /* Frameworks */,
08B91D271AC26FC100335131 /* Products */,
);
sourceTree = "<group>";
};
08B91D271AC26FC100335131 /* Products */ = {
isa = PBXGroup;
children = (
08B91D261AC26FC100335131 /* nyquist-example */,
);
name = Products;
sourceTree = "<group>";
};
08B91D281AC26FC100335131 /* Example */ = {
isa = PBXGroup;
children = (
08B91D821AC73B6900335131 /* src */,
083DB3EB1B0871B300FB0661 /* third_party */,
);
name = Example;
path = libnyquist;
sourceTree = "<group>";
};
08B91D801AC73B3B00335131 /* Frameworks */ = {
isa = PBXGroup;
children = (
08B91D7E1AC273EA00335131 /* CoreServices.framework */,
08B91D7C1AC273E400335131 /* CoreFoundation.framework */,
08B91D7A1AC273AE00335131 /* CoreAudio.framework */,
08B91D781AC273A900335131 /* libpthread.dylib */,
08BD8BD51B087097006C227C /* libnyquist.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
08B91D821AC73B6900335131 /* src */ = {
isa = PBXGroup;
children = (
08B91D951AC73B8A00335131 /* Main.cpp */,
);
name = src;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
08B91D251AC26FC100335131 /* nyquist-example */ = {
isa = PBXNativeTarget;
buildConfigurationList = 08B91D2D1AC26FC100335131 /* Build configuration list for PBXNativeTarget "nyquist-example" */;
buildPhases = (
08B91D221AC26FC100335131 /* Sources */,
08B91D231AC26FC100335131 /* Frameworks */,
08B91D241AC26FC100335131 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = "nyquist-example";
productName = libnyquist;
productReference = 08B91D261AC26FC100335131 /* nyquist-example */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08B91D1E1AC26FC100335131 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = "Dimitri Diakopoulos";
TargetAttributes = {
08B91D251AC26FC100335131 = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 08B91D211AC26FC100335131 /* Build configuration list for PBXProject "libnyquist-example" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 08B91D1D1AC26FC100335131;
productRefGroup = 08B91D271AC26FC100335131 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
08B91D251AC26FC100335131 /* nyquist-example */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
08B91D221AC26FC100335131 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
083DB3F11B0871D700FB0661 /* RtAudio.cpp in Sources */,
08B91D9F1AC73B8A00335131 /* Main.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
08B91D2B1AC26FC100335131 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
08B91D2C1AC26FC100335131 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
08B91D2E1AC26FC100335131 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
GCC_CHAR_IS_UNSIGNED_CHAR = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_BUILTIN_FUNCTIONS = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_INPUT_FILETYPE = automatic;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = YES;
GCC_NO_COMMON_BLOCKS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
__MACOSX_CORE__,
USE_ALLOCA,
OPUS_BUILD,
);
GCC_STRICT_ALIASING = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../include",
"$(SRCROOT)/../third_party",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/bin/Debug",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
};
name = Debug;
};
08B91D2F1AC26FC100335131 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
GCC_CHAR_IS_UNSIGNED_CHAR = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_BUILTIN_FUNCTIONS = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_INPUT_FILETYPE = automatic;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = YES;
GCC_NO_COMMON_BLOCKS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
__MACOSX_CORE__,
USE_ALLOCA,
OPUS_BUILD,
);
GCC_STRICT_ALIASING = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../include",
"$(SRCROOT)/../third_party",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/bin/Debug",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
08B91D211AC26FC100335131 /* Build configuration list for PBXProject "libnyquist-example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
08B91D2B1AC26FC100335131 /* Debug */,
08B91D2C1AC26FC100335131 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
08B91D2D1AC26FC100335131 /* Build configuration list for PBXNativeTarget "nyquist-example" */ = {
isa = XCConfigurationList;
buildConfigurations = (
08B91D2E1AC26FC100335131 /* Debug */,
08B91D2F1AC26FC100335131 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08B91D1E1AC26FC100335131 /* Project object */;
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:libnyquist-example.xcodeproj">
</FileRef>
</Workspace>

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "libnyquist"
BlueprintName = "libnyquist"
ReferencedContainer = "container:libnyquist.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "nyquist-example"
BlueprintName = "nyquist-example"
ReferencedContainer = "container:libnyquist-example.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "$(PROJECT_DIR)/../"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "nyquist-example"
BlueprintName = "nyquist-example"
ReferencedContainer = "container:libnyquist-example.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "libnyquist"
BlueprintName = "libnyquist"
ReferencedContainer = "container:libnyquist.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnyquist-examples", "libnyquist-examples.vcxproj", "{C0C0C270-FB9E-4EEB-8F22-180BB2FA800B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnyquist", "..\..\libnyquist.vcxproj\v120\libnyquist.vcxproj", "{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C0C0C270-FB9E-4EEB-8F22-180BB2FA800B}.Debug|Win32.ActiveCfg = Debug|Win32
{C0C0C270-FB9E-4EEB-8F22-180BB2FA800B}.Debug|Win32.Build.0 = Debug|Win32
{C0C0C270-FB9E-4EEB-8F22-180BB2FA800B}.Release|Win32.ActiveCfg = Release|Win32
{C0C0C270-FB9E-4EEB-8F22-180BB2FA800B}.Release|Win32.Build.0 = Release|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|Win32.ActiveCfg = Debug|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|Win32.Build.0 = Debug|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|Win32.ActiveCfg = Release|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C0C0C270-FB9E-4EEB-8F22-180BB2FA800B}</ProjectGuid>
<RootNamespace>libnyquistexamples</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)../../include;$(SolutionDir)../../third_party;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__WINDOWS_DS__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(SolutionDir)../../include;$(SolutionDir)../../third_party;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__WINDOWS_DS__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\third_party\rtaudio\RtAudio.cpp" />
<ClCompile Include="..\src\Main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\third_party\rtaudio\RtAudio.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\libnyquist.vcxproj\v120\libnyquist.vcxproj">
<Project>{0eec3739-f60a-4b90-8b75-9e1aff28106a}</Project>
<Private>false</Private>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
<CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="third_party">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\Main.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\rtaudio\RtAudio.cpp">
<Filter>third_party</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\third_party\rtaudio\RtAudio.h">
<Filter>third_party</Filter>
</ClInclude>
</ItemGroup>
</Project>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:../libnyquist.xcodeproj">
</FileRef>
<FileRef
location = "container:libnyquist-example.xcodeproj">
</FileRef>
</Workspace>

@ -1,167 +1,104 @@
// Note to Visual Studio / Windows users: you must set the working directory manually on the project file
// to $(ProjectDir)../ since these settings are not saved directly in project. The loader
// will be unable to find the example assets unless the proper working directory is set.
#if defined(_MSC_VER)
#pragma comment(lib, "dsound.lib")
#endif
#include "AudioDevice.h"
#include "libnyquist/Decoders.h"
#include "libnyquist/Encoders.h"
#include "libnyquist/AudioDevice.h"
#include "libnyquist/AudioDecoder.h"
#include "libnyquist/WavEncoder.h"
#include "libnyquist/PostProcess.h"
#include <thread>
using namespace nqr;
int main(int argc, const char **argv) try
int main()
{
AudioDevice::ListAudioDevices();
AudioDevice::ListAudioDevices();
const int desiredSampleRate = 44100;
const int desiredChannelCount = 2;
AudioDevice myDevice(desiredChannelCount, desiredSampleRate);
myDevice.Open(myDevice.info.id);
int desiredSampleRate = 44100;
AudioDevice myDevice(2, desiredSampleRate);
myDevice.Open(myDevice.info.id);
AudioData * fileData = new AudioData();
NyquistIO loader;
WavEncoder encoder;
try
{
// Circular libnyquist testing!
//auto result = loader.Load(fileData, "encoded.wav");
//auto result = loader.Load(fileData, "test_data/1ch/44100/8/test.wav");
//auto result = loader.Load(fileData, "test_data/1ch/44100/16/test.wav");
//auto result = loader.Load(fileData, "test_data/1ch/44100/24/test.wav");
//auto result = loader.Load(fileData, "test_data/1ch/44100/32/test.wav");
//auto result = loader.Load(fileData, "test_data/1ch/44100/64/test.wav");
//auto result = loader.Load(fileData, "test_data/2ch/44100/8/test.wav");
//auto result = loader.Load(fileData, "test_data/2ch/44100/16/test.wav");
//auto result = loader.Load(fileData, "test_data/2ch/44100/24/test.wav");
//auto result = loader.Load(fileData, "test_data/2ch/44100/32/test.wav");
//auto result = loader.Load(fileData, "test_data/2ch/44100/64/test.wav");
//auto result = loader.Load(fileData, "test_data/ad_hoc/6_channel_44k_16b.wav");
//auto result = loader.Load(fileData, "test_data/ad_hoc/LR_Stereo.ogg");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestLaugh_44k.ogg");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat.ogg");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeatMono.ogg");
//auto result = loader.Load(fileData, "test_data/ad_hoc/BlockWoosh_Stereo.ogg");
//auto result = loader.Load(fileData, "test_data/ad_hoc/KittyPurr8_Stereo_Dithered.flac");
//auto result = loader.Load(fileData, "test_data/ad_hoc/KittyPurr16_Stereo.flac");
//auto result = loader.Load(fileData, "test_data/ad_hoc/KittyPurr16_Mono.flac");
//auto result = loader.Load(fileData, "test_data/ad_hoc/KittyPurr24_Stereo.flac");
//auto result = loader.Load(fileData, "test_data/ad_hoc/detodos.opus"); // "Firefox: From All, To All"
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_Float32.wv");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_Float32_Mono.wv");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_Int16.wv");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_Int24.wv");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_Int32.wv");
//auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_Int24_Mono.wv");
//auto result = loader.Load(fileData, "test_data/ad_hoc/44_16_stereo.mpc");
//auto result = loader.Load(fileData, "test_data/ad_hoc/44_16_mono.mpc");
auto result = loader.Load(fileData, "test_data/ad_hoc/TestBeat_44_16_stereo-ima4.wav");
std::cout << "[Debug] Loader Status: " << result << std::endl;
}
catch (std::exception e)
{
std::cerr << "Caught: " << e.what() << std::endl;
std::exit(1);
}
std::shared_ptr<AudioData> fileData = std::make_shared<AudioData>();
NyquistIO loader;
if (argc > 1)
{
std::string cli_arg = std::string(argv[1]);
loader.Load(fileData.get(), cli_arg);
}
else
{
// Circular libnyquist testing
//loader.Load(fileData.get(), "libnyquist_example_output.opus");
// 1-channel wave
//loader.Load(fileData.get(), "test_data/1ch/44100/8/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/16/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/24/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/32/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/64/test.wav");
// 2-channel wave
//loader.Load(fileData.get(), "test_data/2ch/44100/8/test.wav");
//loader.Load(fileData.get(), "test_data/2ch/44100/16/test.wav");
//loader.Load(fileData.get(), "test_data/2ch/44100/24/test.wav");
//loader.Load(fileData.get(), "test_data/2ch/44100/32/test.wav");
//loader.Load(fileData.get(), "test_data/2ch/44100/64/test.wav");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_44_16_mono-ima4-reaper.wav");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_44_16_stereo-ima4-reaper.wav");
// Multi-channel wave
//loader.Load(fileData.get(), "test_data/ad_hoc/6_channel_44k_16b.wav");
// 1 + 2 channel ogg
//loader.Load(fileData.get(), "test_data/ad_hoc/LR_Stereo.ogg");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestLaugh_44k.ogg");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat.ogg");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeatMono.ogg");
//loader.Load(fileData.get(), "test_data/ad_hoc/BlockWoosh_Stereo.ogg");
// 1 + 2 channel flac
//loader.Load(fileData.get(), "test_data/ad_hoc/KittyPurr8_Stereo_Dithered.flac");
//loader.Load(fileData.get(), "test_data/ad_hoc/KittyPurr16_Stereo.flac");
//loader.Load(fileData.get(), "test_data/ad_hoc/KittyPurr16_Mono.flac");
//loader.Load(fileData.get(), "test_data/ad_hoc/KittyPurr24_Stereo.flac");
//auto memory = ReadFile("test_data/ad_hoc/KittyPurr24_Stereo.flac"); // broken
//loader.Load(fileData.get(), "flac", memory.buffer); // broken
// Single-channel opus
//loader.Load(fileData.get(), "test_data/ad_hoc/detodos.opus"); // "Firefox: From All, To All"
// 1 + 2 channel wavpack
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_Float32.wv");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_Float32_Mono.wv");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_Int16.wv");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_Int24.wv");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_Int32.wv");
//loader.Load(fileData.get(), "test_data/ad_hoc/TestBeat_Int24_Mono.wv");
// In-memory wavpack
auto memory = ReadFile("test_data/ad_hoc/TestBeat_Float32.wv");
loader.Load(fileData.get(), "wv", memory.buffer);
// 1 + 2 channel musepack
//loader.Load(fileData.get(), "test_data/ad_hoc/44_16_stereo.mpc");
//loader.Load(fileData.get(), "test_data/ad_hoc/44_16_mono.mpc");
// In-memory ogg
//auto memory = ReadFile("test_data/ad_hoc/BlockWoosh_Stereo.ogg");
//loader.Load(fileData.get(), "ogg", memory.buffer);
// In-memory Mp3
//auto memory = ReadFile("test_data/ad_hoc/acetylene.mp3");
//loader.Load(fileData.get(), "mp3", memory.buffer);
}
/* Test Recording Capabilities of AudioDevice
fileData->samples.reserve(44100 * 5);
fileData->channelCount = 1;
fileData->frameSize = 32;
fileData->lengthSeconds = 5.0;
fileData->sampleRate = 44100;
std::cout << "Starting recording ..." << std::endl;
myDevice.Record(fileData->sampleRate * fileData->lengthSeconds, fileData->samples);
*/
if (fileData->sampleRate != desiredSampleRate)
{
std::cout << "[Warning - Sample Rate Mismatch] - file is sampled at " << fileData->sampleRate << " and output is " << desiredSampleRate << std::endl;
}
std::cout << "Input Samples: " << fileData->samples.size() << std::endl;
// Convert mono to stereo for testing playback
if (fileData->channelCount == 1)
{
std::cout << "Playing MONO for: " << fileData->lengthSeconds << " seconds..." << std::endl;
std::vector<float> stereoCopy(fileData->samples.size() * 2);
// Libnyquist does not do sample rate conversion
if (fileData->sampleRate != desiredSampleRate)
{
std::cout << "[Warning - Sample Rate Mismatch] - file is sampled at " << fileData->sampleRate << " and output is " << desiredSampleRate << std::endl;
}
// Convert mono to stereo for testing playback
if (fileData->channelCount == 1)
{
std::vector<float> stereoCopy(fileData->samples.size() * 2);
MonoToStereo(fileData->samples.data(), stereoCopy.data(), fileData->samples.size());
myDevice.Play(stereoCopy);
}
else
{
std::cout << "Playing STEREO for: " << fileData->lengthSeconds << " seconds..." << std::endl;
myDevice.Play(fileData->samples);
}
// Test Opus Encoding
{
// Resample
std::vector<float> outputBuffer;
std::cout << "Output Samples: " << outputBuffer.size() << std::endl;
outputBuffer.reserve(fileData->samples.size() * 2);
linear_resample(fileData->sampleRate / 48000.0f, fileData->samples, outputBuffer, (uint32_t)fileData->samples.size());
fileData->samples = outputBuffer;
int encoderStatus = encode_opus_to_disk({ fileData->channelCount, PCM_FLT, DITHER_NONE }, fileData.get(), "libnyquist_example_output.opus");
std::cout << "Encoder Status: " << encoderStatus << std::endl;
}
return EXIT_SUCCESS;
}
catch (const UnsupportedExtensionEx & e)
{
std::cerr << "Caught: " << e.what() << std::endl;
}
catch (const LoadPathNotImplEx & e)
{
std::cerr << "Caught: " << e.what() << std::endl;
}
catch (const LoadBufferNotImplEx & e)
{
std::cerr << "Caught: " << e.what() << std::endl;
}
catch (const std::exception & e)
{
std::cerr << "Caught: " << e.what() << std::endl;
myDevice.Play(stereoCopy);
}
else
{
std::cout << "Playing for: " << fileData->lengthSeconds << " seconds..." << std::endl;
myDevice.Play(fileData->samples);
}
// Test wav file encoder
int encoderStatus = encoder.WriteFile({2, PCM_16, DITHER_NONE}, fileData, "encoded.wav");
std::cout << "Encoder Status: " << encoderStatus << std::endl;
return 0;
}

@ -0,0 +1,98 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef AUDIO_DECODER_H
#define AUDIO_DECODER_H
#include "Common.h"
#include <utility>
#include <map>
#include <memory>
namespace nqr
{
// Individual decoder classes will throw std::exceptions for bad things,
// but NyquistIO implements this enum for high-level error notifications.
enum IOError
{
NoError,
NoDecodersLoaded,
ExtensionNotSupported,
LoadPathNotImplemented,
LoadBufferNotImplemented,
UnknownError
};
struct BaseDecoder
{
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) = 0;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) = 0;
virtual std::vector<std::string> GetSupportedFileExtensions() = 0;
//@todo implement streaming helper methods here
};
typedef std::pair<std::string, std::shared_ptr<nqr::BaseDecoder>> DecoderPair;
class NyquistIO
{
public:
NyquistIO();
~NyquistIO();
int Load(AudioData * data, const std::string & path);
int Load(AudioData *data, std::string extension, const std::vector<uint8_t> & buffer);
bool IsFileSupported(const std::string path) const;
private:
std::string ParsePathForExtension(const std::string & path) const;
std::shared_ptr<nqr::BaseDecoder> GetDecoderForExtension(const std::string ext);
void BuildDecoderTable();
template<typename T>
void AddDecoderToTable(std::shared_ptr<T> decoder)
{
auto supportedExtensions = decoder->GetSupportedFileExtensions();
//@todo: basic sanity checking that the extension isn't already supported
for (const auto ext : supportedExtensions)
{
decoderTable.insert(DecoderPair(ext, decoder));
}
}
std::map<std::string, std::shared_ptr<BaseDecoder>> decoderTable;
NO_MOVE(NyquistIO);
};
} // end namespace nqr
#endif

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,43 +23,73 @@ 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.
*/
// This file implements a simple sound file player based on RtAudio for testing / example purposes.
#ifndef AUDIO_DEVICE_H
#define AUDIO_DEVICE_H
// This file implements a simple sound file player based on RtAudio for testing / example purposes.
#include "Common.h"
#include "RingBuffer.h"
#include "rtaudio/RtAudio.h"
#include <vector>
#include <iostream>
#include <memory>
static const uint32_t FRAME_SIZE = 512;
static const int32_t CHANNELS = 2;
static const int32_t BUFFER_LENGTH = FRAME_SIZE * CHANNELS;
struct AudioDeviceInfo
namespace nqr
{
uint32_t id;
uint32_t numChannels;
uint32_t sampleRate;
uint32_t frameSize;
const unsigned int FRAME_SIZE = 512;
const int CHANNELS = 2;
const int BUFFER_LENGTH = FRAME_SIZE * CHANNELS;
struct DeviceInfo
{
int id;
int numChannels;
int sampleRate;
unsigned int frameSize;
bool isPlaying = false;
};
class AudioDevice
{
NO_MOVE(AudioDevice);
std::unique_ptr<RtAudio> rtaudio;
protected:
AudioDevice(const AudioDevice& r) = delete;
AudioDevice & operator = (const AudioDevice& r) = delete;
public:
AudioDeviceInfo info;
AudioDevice(int numChannels, int sampleRate, int deviceId = -1);
~AudioDevice();
DeviceInfo info;
static void ListAudioDevices();
AudioDevice(int numChannels, int sampleRate, int deviceId = -1)
{
rtaudio = std::unique_ptr<RtAudio>(new RtAudio);
info.id = deviceId != -1 ? deviceId : rtaudio->getDefaultOutputDevice();
info.numChannels = numChannels;
info.sampleRate = sampleRate;
info.frameSize = FRAME_SIZE;
}
~AudioDevice()
{
if (rtaudio)
{
rtaudio->stopStream();
if (rtaudio->isStreamOpen())
rtaudio->closeStream();
}
}
bool Open(const int deviceId);
bool Play(const std::vector<float> & data);
bool Record(const uint32_t lengthInSamples, std::vector<float> & recordingBuffer);
};
} // end namespace nqr
#endif

@ -0,0 +1,45 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef CAF_DECODER_H
#define CAF_DECODER_H
#include "AudioDecoder.h"
namespace nqr
{
struct CAFDecoder : public nqr::BaseDecoder
{
CAFDecoder() {};
virtual ~CAFDecoder() {};
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -26,7 +26,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef LIBNYQUIST_COMMON_H
#define LIBNYQUIST_COMMON_H
#include <memory>
#include <vector>
#include <algorithm>
#include <cmath>
@ -37,12 +36,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <type_traits>
#include <numeric>
#include <array>
#include <map>
#include <random>
#include "PostProcess.h"
#include "Dither.h"
namespace nqr
{
/////////////////
// Util Macros //
/////////////////
@ -200,90 +199,10 @@ inline std::array<uint8_t, 3> Unpack(uint32_t a)
return output;
}
//////////////////////////
// Resampling Utilities //
//////////////////////////
// This is a naieve implementation of a resampling filter where a lerp is used as a bad low-pass.
// It very far from the ideal case and should be used with caution (or not at all) on signals that matter.
// It is included here to upsample 44.1k to 48k for the purposes of microphone input => Opus, where the the
// nominal frequencies of speech are particularly far from Nyquist.
inline void linear_resample(const double rate, const std::vector<float> & input, std::vector<float> & output, const uint32_t samplesToProcess)
{
double virtualReadIndex = 0;
double a, b, i, sample;
uint32_t n = samplesToProcess - 1;
while (n--)
{
uint32_t readIndex = static_cast<uint32_t>(virtualReadIndex);
i = virtualReadIndex - readIndex;
a = input[readIndex + 0];
b = input[readIndex + 1];
sample = (1.0 - i) * a + i * b; // linear interpolate
output.push_back(static_cast<float>(sample));
virtualReadIndex += rate;
}
}
inline double sample_hermite_4p_3o(double x, double * y)
{
static double c0, c1, c2, c3;
c0 = y[1];
c1 = (1.0 / 2.0)*(y[2] - y[0]);
c2 = (y[0] - (5.0 / 2.0)*y[1]) + (2.0*y[2] - (1.0 / 2.0)*y[3]);
c3 = (1.0 / 2.0)*(y[3] - y[0]) + (3.0 / 2.0)*(y[1] - y[2]);
return ((c3*x + c2)*x + c1)*x + c0;
}
inline void hermite_resample(const double rate, const std::vector<float> & input, std::vector<float> & output, const uint32_t samplesToProcess)
{
double virtualReadIndex = 1;
double i, sample;
uint32_t n = samplesToProcess - 1;
while (n--)
{
uint32_t readIndex = static_cast<uint32_t>(virtualReadIndex);
i = virtualReadIndex - readIndex;
double samps[4] = { input[readIndex - 1], input[readIndex], input[readIndex + 1], input[readIndex + 2] };
sample = sample_hermite_4p_3o(i, samps); // cubic hermite interpolate over 4 samples
output.push_back(static_cast<float>(sample));
virtualReadIndex += rate;
}
}
//////////////////////////
// Conversion Utilities //
//////////////////////////
enum DitherType
{
DITHER_NONE,
DITHER_TRIANGLE
};
class Dither
{
std::uniform_real_distribution<float> distribution;
std::mt19937 gen;
float previous;
DitherType d;
public:
Dither(DitherType d) : distribution(-0.5f, +0.5f), previous(0.f), d(d) {}
float operator()(float s)
{
if (d == DITHER_TRIANGLE)
{
const float value = distribution(gen);
s = s + value - previous;
previous = value;
return s;
}
else return s;
}
};
// Signed maxes, defined for readabilty/convenience
#define NQR_INT16_MAX 32767.f
#define NQR_INT24_MAX 8388608.f
@ -331,9 +250,6 @@ void ConvertToFloat32(float * dst, const int16_t * src, const size_t N, PCMForma
void ConvertFromFloat32(uint8_t * dst, const float * src, const size_t N, PCMFormat f, DitherType t = DITHER_NONE);
int GetFormatBitsPerSample(PCMFormat f);
PCMFormat MakeFormatForBits(int bits, bool floatingPt, bool isSigned);
//////////////////////////
// User Data + File Ops //
//////////////////////////
@ -366,328 +282,10 @@ struct NyquistFileBuffer
size_t size;
};
NyquistFileBuffer ReadFile(const std::string & pathToFile);
////////////////////
// Encoding Utils //
////////////////////
struct EncoderParams
{
int channelCount;
PCMFormat targetFormat;
DitherType dither;
};
enum EncoderError
{
NoError,
InsufficientSampleData,
FileIOError,
UnsupportedSamplerate,
UnsupportedChannelConfiguration,
UnsupportedBitdepth,
UnsupportedChannelMix,
BufferTooBig,
};
//////////////////////
// Wav Format Utils //
//////////////////////
enum WaveFormatCode
{
FORMAT_UNKNOWN = 0x0, // Unknown Wave Format
FORMAT_PCM = 0x1, // PCM Format
FORMAT_ADPCM = 0x2, // Microsoft ADPCM Format
FORMAT_IEEE = 0x3, // IEEE float/double
FORMAT_ALAW = 0x6, // 8-bit ITU-T G.711 A-law
FORMAT_MULAW = 0x7, // 8-bit ITU-T G.711 µ-law
FORMAT_IMA_ADPCM = 0x11, // IMA ADPCM Format
FORMAT_EXT = 0xFFFE // Set via subformat
};
struct RiffChunkHeader
{
uint32_t id_riff; // Chunk ID: 'RIFF'
uint32_t file_size; // Entire file in bytes
uint32_t id_wave; // Chunk ID: 'WAVE'
};
struct WaveChunkHeader
{
uint32_t fmt_id; // Chunk ID: 'fmt '
uint32_t chunk_size; // Size in bytes
uint16_t format; // Format code
uint16_t channel_count; // Num interleaved channels
uint32_t sample_rate; // SR
uint32_t data_rate; // Data rate
uint16_t frame_size; // 1 frame = channels * bits per sample (also known as block align)
uint16_t bit_depth; // Bits per sample
};
struct BextChunk
{
uint32_t fmt_id; // Chunk ID: 'bext'
uint32_t chunk_size; // Size in bytes
uint8_t description[256]; // Description of the sound (ascii)
uint8_t origin[32]; // Name of the originator (ascii)
uint8_t origin_ref[32]; // Reference of the originator (ascii)
uint8_t orgin_date[10]; // yyyy-mm-dd (ascii)
uint8_t origin_time[8]; // hh-mm-ss (ascii)
uint64_t time_ref; // First sample count since midnight
uint32_t version; // Version of the BWF
uint8_t uimd[64]; // Byte 0 of SMPTE UMID
uint8_t reserved[188]; // 190 bytes, reserved for future use & set to NULL
};
struct FactChunk
{
uint32_t fact_id; // Chunk ID: 'fact'
uint32_t chunk_size; // Size in bytes
uint32_t sample_length; // number of samples per channel
};
struct ExtensibleData
{
uint16_t size;
uint16_t valid_bits_per_sample;
uint32_t channel_mask;
struct GUID
{
uint32_t data0;
uint16_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[6];
};
};
template<class C, class R>
std::basic_ostream<C,R> & operator << (std::basic_ostream<C,R> & a, const WaveChunkHeader & b)
{
return a <<
"Format ID:\t\t" << b.fmt_id <<
"\nChunk Size:\t\t" << b.chunk_size <<
"\nFormat Code:\t\t" << b.format <<
"\nChannels:\t\t" << b.channel_count <<
"\nSample Rate:\t\t" << b.sample_rate <<
"\nData Rate:\t\t" << b.data_rate <<
"\nFrame Size:\t\t" << b.frame_size <<
"\nBit Depth:\t\t" << b.bit_depth << std::endl;
}
//@todo expose speaker/channel/layout masks in the API:
NyquistFileBuffer ReadFile(std::string pathToFile);
enum SpeakerChannelMask
{
SPEAKER_FRONT_LEFT = 0x00000001,
SPEAKER_FRONT_RIGHT = 0x00000002,
SPEAKER_FRONT_CENTER = 0x00000004,
SPEAKER_LOW_FREQUENCY = 0x00000008,
SPEAKER_BACK_LEFT = 0x00000010,
SPEAKER_BACK_RIGHT = 0x00000020,
SPEAKER_FRONT_LEFT_OF_CENTER = 0x00000040,
SPEAKER_FRONT_RIGHT_OF_CENTER = 0x00000080,
SPEAKER_BACK_CENTER = 0x00000100,
SPEAKER_SIDE_LEFT = 0x00000200,
SPEAKER_SIDE_RIGHT = 0x00000400,
SPEAKER_TOP_CENTER = 0x00000800,
SPEAKER_TOP_FRONT_LEFT = 0x00001000,
SPEAKER_TOP_FRONT_CENTER = 0x00002000,
SPEAKER_TOP_FRONT_RIGHT = 0x00004000,
SPEAKER_TOP_BACK_LEFT = 0x00008000,
SPEAKER_TOP_BACK_CENTER = 0x00010000,
SPEAKER_TOP_BACK_RIGHT = 0x00020000,
SPEAKER_RESERVED = 0x7FFC0000,
SPEAKER_ALL = 0x80000000
};
enum SpeakerLayoutMask
{
SPEAKER_MONO = (SPEAKER_FRONT_CENTER),
SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT),
SPEAKER_2POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY),
SPEAKER_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER),
SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_4POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_5POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_7POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER),
SPEAKER_5POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),
SPEAKER_7POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),
};
//@todo verify mask values
inline int ComputeChannelMask(const size_t channels)
{
switch (channels)
{
case 1: return SPEAKER_MONO;
case 2: return SPEAKER_STEREO;
case 3: return SPEAKER_2POINT1;
case 4: return SPEAKER_QUAD;
case 5: return SPEAKER_4POINT1;
case 6: return SPEAKER_5POINT1;
default: return -1;
}
}
/////////////////////
// Chunk utilities //
/////////////////////
struct ChunkHeaderInfo
{
uint32_t offset; // Byte offset into chunk
uint32_t size; // Size of the chunk in bytes
};
inline uint32_t GenerateChunkCode(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
#ifdef ARCH_CPU_LITTLE_ENDIAN
return ((uint32_t)((a) | ((b) << 8) | ((c) << 16) | (((uint32_t)(d)) << 24)));
#else
return ((uint32_t)((((uint32_t)(a)) << 24) | ((b) << 16) | ((c) << 8) | (d)));
#endif
}
inline char * GenerateChunkCodeChar(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
auto chunk = GenerateChunkCode(a, b, c, d);
char * outArr = new char[4];
uint32_t t = 0x000000FF;
for (size_t i = 0; i < 4; i++)
{
outArr[i] = chunk & t;
chunk >>= 8;
}
return outArr;
}
inline ChunkHeaderInfo ScanForChunk(const std::vector<uint8_t> & fileData, uint32_t chunkMarker)
{
// D[n] aligned to 16 bytes now
const uint16_t * d = reinterpret_cast<const uint16_t *>(fileData.data());
for (size_t i = 0; i < fileData.size() / sizeof(uint16_t); i++)
{
// This will be in machine endianess
uint32_t m = Pack(Read16(d[i]), Read16(d[i + 1]));
if (m == chunkMarker)
{
uint32_t cSz = Pack(Read16(d[i + 2]), Read16(d[i + 3]));
return { (uint32_t(i * sizeof(uint16_t))), cSz }; // return i in bytes to the start of the data
}
else continue;
}
return { 0, 0 };
};
inline WaveChunkHeader MakeWaveHeader(const EncoderParams param, const int sampleRate)
{
WaveChunkHeader header;
int bitdepth = GetFormatBitsPerSample(param.targetFormat);
header.fmt_id = GenerateChunkCode('f', 'm', 't', ' ');
header.chunk_size = 16;
header.format = (param.targetFormat <= PCMFormat::PCM_32) ? WaveFormatCode::FORMAT_PCM : WaveFormatCode::FORMAT_IEEE;
header.channel_count = param.channelCount;
header.sample_rate = sampleRate;
header.data_rate = sampleRate * param.channelCount * (bitdepth / 8);
header.frame_size = param.channelCount * (bitdepth / 8);
header.bit_depth = bitdepth;
return header;
}
// @todo expose this in the FLAC API
inline std::map<int, std::string> GetFlacQualityTable()
{
return {
{ 0, "0 (Fastest)" },
{ 1, "1" },
{ 2, "2" },
{ 3, "3" },
{ 4, "4" },
{ 5, "5 (Default)" },
{ 6, "6" },
{ 7, "7" },
{ 8, "8 (Highest)" },
};
}
template <typename T>
inline void DeinterleaveStereo(T * c1, T * c2, T const * src, size_t count)
{
auto src_end = src + count;
while (src != src_end)
{
*c1 = src[0];
*c2 = src[1];
c1++;
c2++;
src += 2;
}
}
template<typename T>
void InterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N)
{
for (size_t ch = 0; ch < numChannels; ch++)
{
size_t x = ch;
const T * srcChannel = &src[ch * numFramesPerChannel];
for (size_t i = 0; i < N; i++)
{
dest[x] = srcChannel[i];
x += numChannels;
}
}
}
template<typename T>
void DeinterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N)
{
for (size_t ch = 0; ch < numChannels; ch++)
{
size_t x = ch;
T *destChannel = &dest[ch * numFramesPerChannel];
for (size_t i = 0; i < N; i++)
{
destChannel[i] = (T)src[x];
x += numChannels;
}
}
}
template <typename T>
void StereoToMono(const T * src, T * dest, size_t N)
{
for (size_t i = 0, j = 0; i < N; i += 2, ++j)
{
dest[j] = (src[i] + src[i + 1]) / 2.0f;
}
}
template <typename T>
void MonoToStereo(const T * src, T * dest, size_t N)
{
for (size_t i = 0, j = 0; i < N; ++i, j += 2)
{
dest[j] = src[i];
dest[j + 1] = src[i];
}
}
inline void TrimSilenceInterleaved(std::vector<float> & buffer, float v, bool fromFront, bool fromEnd)
{
//@todo implement me!
}
int GetFormatBitsPerSample(PCMFormat f);
PCMFormat MakeFormatForBits(int bits, bool floatingPt, bool isSigned);
} // end namespace nqr

@ -1,136 +0,0 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef AUDIO_DECODER_H
#define AUDIO_DECODER_H
#include "Common.h"
#include <utility>
#include <map>
#include <memory>
#include <exception>
namespace nqr
{
struct BaseDecoder
{
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) = 0;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) = 0;
virtual std::vector<std::string> GetSupportedFileExtensions() = 0;
virtual ~BaseDecoder() {}
};
typedef std::pair< std::string, std::shared_ptr<nqr::BaseDecoder> > DecoderPair;
class NyquistIO
{
std::string ParsePathForExtension(const std::string & path) const;
std::shared_ptr<nqr::BaseDecoder> GetDecoderForExtension(const std::string & ext);
void BuildDecoderTable();
void AddDecoderToTable(std::shared_ptr<nqr::BaseDecoder> decoder);
std::map< std::string, std::shared_ptr<BaseDecoder> > decoderTable;
NO_MOVE(NyquistIO);
public:
NyquistIO();
~NyquistIO();
void Load(AudioData * data, const std::string & path);
void Load(AudioData * data, const std::vector<uint8_t> & buffer);
void Load(AudioData * data, const std::string & extension, const std::vector<uint8_t> & buffer);
bool IsFileSupported(const std::string & path) const;
};
struct UnsupportedExtensionEx : public std::runtime_error { UnsupportedExtensionEx() : std::runtime_error("Unsupported file extension") {} };
struct LoadPathNotImplEx : public std::runtime_error { LoadPathNotImplEx() : std::runtime_error("Loading from path not implemented") {} };
struct LoadBufferNotImplEx : public std::runtime_error { LoadBufferNotImplEx() : std::runtime_error("Loading from buffer not implemented") {} };
struct WavDecoder final : public nqr::BaseDecoder
{
WavDecoder() = default;
virtual ~WavDecoder() {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct WavPackDecoder final : public nqr::BaseDecoder
{
WavPackDecoder() = default;
virtual ~WavPackDecoder() override {};
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct VorbisDecoder final : public nqr::BaseDecoder
{
VorbisDecoder() = default;
virtual ~VorbisDecoder() override {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct OpusDecoder final : public nqr::BaseDecoder
{
OpusDecoder() = default;
virtual ~OpusDecoder() override {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct MusepackDecoder final : public nqr::BaseDecoder
{
MusepackDecoder() = default;
virtual ~MusepackDecoder() override {};
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct Mp3Decoder final : public nqr::BaseDecoder
{
Mp3Decoder() = default;
virtual ~Mp3Decoder() override {};
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
struct FlacDecoder final : public nqr::BaseDecoder
{
FlacDecoder() = default;
virtual ~FlacDecoder() override {}
virtual void LoadFromPath(nqr::AudioData * data, const std::string & path) override final;
virtual void LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override final;
virtual std::vector<std::string> GetSupportedFileExtensions() override final;
};
} // end namespace nqr
#endif

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,22 +23,47 @@ 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.
*/
#ifndef NYQUIST_ENCODERS_H
#define NYQUIST_ENCODERS_H
#ifndef DITHER_OPERATIONS_H
#define DITHER_OPERATIONS_H
#include "Common.h"
#include <random>
namespace nqr
{
// A simplistic encoder that takes a buffer of audio, conforms it to the user's
// EncoderParams preference, and writes to disk. Be warned, does not support resampling!
// @todo support dithering, samplerate conversion, etc.
int encode_wav_to_disk(const EncoderParams p, const AudioData * d, const std::string & path);
enum DitherType
{
DITHER_NONE,
DITHER_TRIANGLE
};
class Dither
{
std::uniform_real_distribution<float> distribution;
std::mt19937 rndGen;
float prev = 0.0f;
DitherType d;
public:
Dither(DitherType d) : distribution(-0.5f, +0.5f), d(d) {}
float operator()(float s)
{
if (d == DITHER_TRIANGLE)
{
const float value = distribution(rndGen);
s = s + value - prev;
prev = value;
return s;
}
else
{
return s;
}
// Assume data adheres to EncoderParams, except for bit depth and fmt which are re-formatted
// to satisfy the Ogg/Opus spec.
int encode_opus_to_disk(const EncoderParams p, const AudioData * d, const std::string & path);
}
};
} // end namespace nqr
#endif // end NYQUIST_ENCODERS_H
#endif

@ -0,0 +1,65 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef FLAC_DECODER_H
#define FLAC_DECODER_H
// http://lists.xiph.org/pipermail/flac-dev/2012-March/003276.html
#define FLAC__NO_DLL
#include "AudioDecoder.h"
#include <map>
namespace nqr
{
//@todo expose this in API
inline std::map<int, std::string> GetQualityTable()
{
return {
{ 0, "0 (Fastest)" },
{ 1, "1" },
{ 2, "2" },
{ 3, "3" },
{ 4, "4" },
{ 5, "5 (Default)" },
{ 6, "6" },
{ 7, "7" },
{ 8, "8 (Highest)" },
};
}
struct FlacDecoder : public nqr::BaseDecoder
{
FlacDecoder() {}
virtual ~FlacDecoder() {}
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -0,0 +1,140 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef IMA4_UTIL_H
#define IMA4_UTIL_H
#include "AudioDecoder.h"
namespace nqr
{
struct ADPCMState
{
int frame_size;
int firstDataBlockByte;
int dataSize;
int currentByte;
const uint8_t * inBuffer;
};
static const int ima_index_table[16] =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
static inline int ima_clamp_index(int index)
{
if (index < 0) return 0;
else if (index > 88) return 88;
return index;
}
static inline int16_t ima_clamp_predict(int16_t predict)
{
if (predict < -32768) return -32768;
else if (predict > 32767) return 32767;
return predict;
}
static const int ima_step_table[89] =
{
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};
// Decodes an IMA ADPCM nibble to a 16 bit pcm sample
static inline int16_t decode_nibble(uint8_t nibble, int16_t & p, int & s)
{
// Compute a delta to add to the predictor value
int diff = 0;
if (nibble & 4) diff += ima_step_table[s];
if (nibble & 2) diff += ima_step_table[s] >> 1;
if (nibble & 1) diff += ima_step_table[s] >> 2;
diff += ima_step_table[s] >> 3;
// Sign
if (nibble & 8) diff = -diff;
// Add delta
p += diff;
p = ima_clamp_predict(p);
s += ima_index_table[nibble];
s = ima_clamp_index(s);
return p;
}
void decode_ima_adpcm(ADPCMState & state, int16_t * outBuffer, uint32_t num_channels)
{
const uint8_t * data = state.inBuffer;
// Loop over the interleaved words
for (int32_t ch = 0; ch < num_channels; ch++)
{
const int byteOffset = ch * 4;
// Get step table index and predicted value from the header word for the current channel
int16_t predictedSample = (data[byteOffset] | (data[byteOffset + 1] << 8));
int stepIndex = data[byteOffset + 2];
// Reserved byte of the header word should be 0.
uint8_t reserved = data[byteOffset + 3];
if (reserved != 0) std::cout << "Fuck" << std::endl;
int byteIdx = num_channels * 4 + byteOffset; //the byte index of the first data word for this channel
int idx = ch;
// Decode each nibble of the current data word, containing 8 encoded samples, for the current channel
while (byteIdx < state.frame_size)
{
for (int j = 0; j < 4; j++)
{
outBuffer[idx] = decode_nibble(data[byteIdx] & 0xf, predictedSample, stepIndex); // low nibble
idx += num_channels;
outBuffer[idx] = decode_nibble(data[byteIdx] >> 4, predictedSample, stepIndex); // high nibble
idx += num_channels;
byteIdx++;
}
byteIdx += (num_channels - 1) << 2; // Jump to the next data word for the current channel
}
}
}
} // end namespace nqr
#endif

@ -0,0 +1,45 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef MUSEPACK_DECODER_H
#define MUSEPACK_DECODER_H
#include "AudioDecoder.h"
namespace nqr
{
struct MusepackDecoder : public nqr::BaseDecoder
{
MusepackDecoder() {};
virtual ~MusepackDecoder() {};
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -0,0 +1,50 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef OPUS_DECODER_H
#define OPUS_DECODER_H
#include "AudioDecoder.h"
namespace nqr
{
// Opus is a general-purpose codec designed to replace Vorbis at some point. Primarily, it's a low
// delay format making it suitable for high-quality, real time streaming. It's not really
// an archival format or something designed for heavy DSP post-processing since
// it's fundamentally limited to encode/decode at 48khz.
// https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/index.html
struct OpusDecoder : public nqr::BaseDecoder
{
OpusDecoder() {}
virtual ~OpusDecoder() {}
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -0,0 +1,104 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef POSTPROCESS_H
#define POSTPROCESS_H
#include <vector>
namespace nqr
{
template <typename T>
inline void DeinterleaveStereo(T * c1, T * c2, T const * src, size_t count)
{
auto src_end = src + count;
while (src != src_end)
{
*c1 = src[0];
*c2 = src[1];
c1++;
c2++;
src += 2;
}
}
template<typename T>
void InterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N)
{
for (size_t ch = 0; ch < numChannels; ch++)
{
size_t x = ch;
const T * srcChannel = &src[ch * numFramesPerChannel];
for(size_t i = 0; i < N; i++)
{
dest[x] = srcChannel[i];
x += numChannels;
}
}
}
template<typename T>
void DeinterleaveChannels(const T * src, T * dest, size_t numFramesPerChannel, size_t numChannels, size_t N)
{
for(size_t ch = 0; ch < numChannels; ch++)
{
size_t x = ch;
T *destChannel = &dest[ch * numFramesPerChannel];
for (size_t i = 0; i < N; i++)
{
destChannel[i] = (T) src[x];
x += numChannels;
}
}
}
template <typename T>
void StereoToMono(const T * src, T * dest, size_t N)
{
for (size_t i = 0, j = 0; i < N; i += 2, ++j)
{
dest[j] = (src[i] + src[i + 1]) / 2.0f;
}
}
template <typename T>
void MonoToStereo(const T * src, T * dest, size_t N)
{
for(size_t i = 0, j = 0; i < N; ++i, j += 2)
{
dest[j] = src[i];
dest[j + 1] = src[i];
}
}
inline void TrimSilenceInterleaved(std::vector<float> & buffer, float v, bool fromFront, bool fromEnd)
{
//@todo implement me!
}
} // end namespace nqr
#endif

@ -0,0 +1,84 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef RIFF_UTILS_H
#define RIFF_UTILS_H
#include "Common.h"
#include "WavDecoder.h"
#include "Dither.h"
namespace nqr
{
/////////////////////
// Chunk utilities //
/////////////////////
struct EncoderParams
{
int channelCount;
PCMFormat targetFormat;
DitherType dither;
};
struct ChunkHeaderInfo
{
uint32_t offset; // Byte offset into chunk
uint32_t size; // Size of the chunk in bytes
};
inline uint32_t GenerateChunkCode(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
#ifdef ARCH_CPU_LITTLE_ENDIAN
return ((uint32_t) ((a) | ((b) << 8) | ((c) << 16) | (((uint32_t) (d)) << 24)));
#else
return ((uint32_t) ((((uint32_t) (a)) << 24) | ((b) << 16) | ((c) << 8) | (d)));
#endif
}
inline char * GenerateChunkCodeChar(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
auto chunk = GenerateChunkCode(a, b, c, d);
char * outArr = new char[4];
uint32_t t = 0x000000FF;
for(size_t i = 0; i < 4; i++)
{
outArr[i] = chunk & t;
chunk >>= 8;
}
return outArr;
}
ChunkHeaderInfo ScanForChunk(const std::vector<uint8_t> & fileData, uint32_t chunkMarker);
WaveChunkHeader MakeWaveHeader(const EncoderParams param, const int sampleRate);
} // end namespace nqr
#endif

@ -36,8 +36,6 @@
#include <atomic>
#include <assert.h>
#include <cstring>
#include <cstdlib>
template <typename T>
class RingBufferT
@ -45,12 +43,18 @@ class RingBufferT
public:
// Constructs a RingBufferT with size = 0
RingBufferT() : mData(nullptr), mAllocatedSize(0), mWriteIndex(0), mReadIndex(0) {}
RingBufferT() : mData(nullptr), mAllocatedSize(0), mWriteIndex(0), mReadIndex(0) {
}
// Constructs a RingBufferT with \a count maximum elements.
RingBufferT(size_t count) : mAllocatedSize(0) { resize(count); }
RingBufferT(size_t count) : mAllocatedSize(0)
{
resize(count);
}
RingBufferT(RingBufferT &&other) : mData(other.mData), mAllocatedSize(other.mAllocatedSize), mWriteIndex(0), mReadIndex(0)
RingBufferT(RingBufferT &&other)
: mData(other.mData), mAllocatedSize(other.mAllocatedSize), mWriteIndex(0), mReadIndex(0)
{
other.mData = nullptr;
other.mAllocatedSize = 0;
@ -67,9 +71,9 @@ class RingBufferT
size_t allocatedSize = count + 1; // one bin is used to distinguish between the read and write indices when full.
if (mAllocatedSize)
mData = (T *) std::realloc(mData, allocatedSize * sizeof(T));
mData = (T *)::realloc(mData, allocatedSize * sizeof(T));
else
mData = (T *) std::calloc(allocatedSize, sizeof(T));
mData = (T *)::calloc(allocatedSize, sizeof(T));
assert(mData);
@ -77,7 +81,7 @@ class RingBufferT
clear();
}
// Invalidates the internal buffer and resets read / write indices to 0. Must be synchronized with both read and write threads.
// Invalidates the internal buffer and resets read / write indices to 0. \note Must be synchronized with both read and write threads.
void clear()
{
mWriteIndex = 0;
@ -87,16 +91,16 @@ class RingBufferT
// Returns the maximum number of elements.
size_t getSize() const
{
return mAllocatedSize - 1;
}
// Returns the number of elements available for writing. Only safe to call from the write thread.
// Returns the number of elements available for wrtiing. \note Only safe to call from the write thread.
size_t getAvailableWrite() const
{
return getAvailableWrite(mWriteIndex, mReadIndex);
}
// Returns the number of elements available for reading. Only safe to call from the read thread.
// Returns the number of elements available for wrtiing. \note Only safe to call from the read thread.
size_t getAvailableRead() const
{
return getAvailableRead(mWriteIndex, mReadIndex);
@ -184,7 +188,7 @@ class RingBufferT
return writeIndex + mAllocatedSize - readIndex;
}
T * mData;
T *mData;
size_t mAllocatedSize;
std::atomic<size_t> mWriteIndex, mReadIndex;
};
@ -192,3 +196,4 @@ class RingBufferT
typedef RingBufferT<float> RingBuffer;
#endif

@ -0,0 +1,44 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef VORBIS_DECODER_H
#define VORBIS_DECODER_H
#include "AudioDecoder.h"
namespace nqr
{
struct VorbisDecoder : public nqr::BaseDecoder
{
VorbisDecoder() {}
virtual ~VorbisDecoder() {}
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -0,0 +1,182 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef WAVE_DECODER_H
#define WAVE_DECODER_H
#include "AudioDecoder.h"
namespace nqr
{
enum WaveFormatCode
{
FORMAT_UNKNOWN = 0x0, // Unknown Wave Format
FORMAT_PCM = 0x1, // PCM Format
FORMAT_ADPCM = 0x2, // Microsoft ADPCM Format
FORMAT_IEEE = 0x3, // IEEE float/double
FORMAT_ALAW = 0x6, // 8-bit ITU-T G.711 A-law
FORMAT_MULAW = 0x7, // 8-bit ITU-T G.711 µ-law
FORMAT_IMA_ADPCM = 0x11, // IMA ADPCM Format
FORMAT_EXT = 0xFFFE // Set via subformat
};
struct RiffChunkHeader
{
uint32_t id_riff; // Chunk ID: 'RIFF'
uint32_t file_size; // Entire file in bytes
uint32_t id_wave; // Chunk ID: 'WAVE'
};
struct WaveChunkHeader
{
uint32_t fmt_id; // Chunk ID: 'fmt '
uint32_t chunk_size; // Size in bytes
uint16_t format; // Format code
uint16_t channel_count; // Num interleaved channels
uint32_t sample_rate; // SR
uint32_t data_rate; // Data rate
uint16_t frame_size; // 1 frame = channels * bits per sample (also known as block align)
uint16_t bit_depth; // Bits per sample
};
struct BextChunk
{
uint32_t fmt_id; // Chunk ID: 'bext'
uint32_t chunk_size; // Size in bytes
uint8_t description[256]; // Description of the sound (ascii)
uint8_t origin[32]; // Name of the originator (ascii)
uint8_t origin_ref[32]; // Reference of the originator (ascii)
uint8_t orgin_date[10]; // yyyy-mm-dd (ascii)
uint8_t origin_time[8]; // hh-mm-ss (ascii)
uint64_t time_ref; // First sample count since midnight
uint32_t version; // Version of the BWF
uint8_t uimd[64]; // Byte 0 of SMPTE UMID
uint8_t reserved[188]; // 190 bytes, reserved for future use & set to NULL
};
struct FactChunk
{
uint32_t fact_id; // Chunk ID: 'fact'
uint32_t chunk_size; // Size in bytes
uint32_t sample_length; // number of samples per channel
};
struct ExtensibleData
{
uint16_t size;
uint16_t valid_bits_per_sample;
uint32_t channel_mask;
struct GUID
{
uint32_t data0;
uint16_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[6];
};
};
template<class C, class R>
std::basic_ostream<C,R> & operator << (std::basic_ostream<C,R> & a, const WaveChunkHeader & b)
{
return a <<
"Format ID:\t\t" << b.fmt_id <<
"\nChunk Size:\t\t" << b.chunk_size <<
"\nFormat Code:\t\t" << b.format <<
"\nChannels:\t\t" << b.channel_count <<
"\nSample Rate:\t\t" << b.sample_rate <<
"\nData Rate:\t\t" << b.data_rate <<
"\nFrame Size:\t\t" << b.frame_size <<
"\nBit Depth:\t\t" << b.bit_depth << std::endl;
}
//@todo expose speaker/channel/layout masks in the API:
enum SpeakerChannelMask
{
SPEAKER_FRONT_LEFT = 0x00000001,
SPEAKER_FRONT_RIGHT = 0x00000002,
SPEAKER_FRONT_CENTER = 0x00000004,
SPEAKER_LOW_FREQUENCY = 0x00000008,
SPEAKER_BACK_LEFT = 0x00000010,
SPEAKER_BACK_RIGHT = 0x00000020,
SPEAKER_FRONT_LEFT_OF_CENTER = 0x00000040,
SPEAKER_FRONT_RIGHT_OF_CENTER = 0x00000080,
SPEAKER_BACK_CENTER = 0x00000100,
SPEAKER_SIDE_LEFT = 0x00000200,
SPEAKER_SIDE_RIGHT = 0x00000400,
SPEAKER_TOP_CENTER = 0x00000800,
SPEAKER_TOP_FRONT_LEFT = 0x00001000,
SPEAKER_TOP_FRONT_CENTER = 0x00002000,
SPEAKER_TOP_FRONT_RIGHT = 0x00004000,
SPEAKER_TOP_BACK_LEFT = 0x00008000,
SPEAKER_TOP_BACK_CENTER = 0x00010000,
SPEAKER_TOP_BACK_RIGHT = 0x00020000,
SPEAKER_RESERVED = 0x7FFC0000,
SPEAKER_ALL = 0x80000000
};
enum SpeakerLayoutMask
{
SPEAKER_MONO = (SPEAKER_FRONT_CENTER),
SPEAKER_STEREO = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT),
SPEAKER_2POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY),
SPEAKER_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_CENTER),
SPEAKER_QUAD = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_4POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_5POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT),
SPEAKER_7POINT1 = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_FRONT_LEFT_OF_CENTER | SPEAKER_FRONT_RIGHT_OF_CENTER),
SPEAKER_5POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),
SPEAKER_7POINT1_SURROUND = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT),
};
//@todo verify mask values
inline int ComputeChannelMask(const size_t channels)
{
switch (channels)
{
case 1: return SPEAKER_MONO;
case 2: return SPEAKER_STEREO;
case 3: return SPEAKER_2POINT1;
case 4: return SPEAKER_QUAD;
case 5: return SPEAKER_4POINT1;
case 6: return SPEAKER_5POINT1;
default: return -1;
}
}
struct WavDecoder : public nqr::BaseDecoder
{
WavDecoder() {}
virtual ~WavDecoder() {}
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -0,0 +1,62 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef WAVE_ENCODER_H
#define WAVE_ENCODER_H
#include "Common.h"
#include "WavDecoder.h"
#include "RiffUtils.h"
namespace nqr
{
// A simplistic encoder that takes a blob of data, conforms it to the user's
// EncoderParams preference, and writes to disk. Be warned, does not support resampling!
// @todo support dithering, samplerate conversion, etc.
class WavEncoder
{
enum EncoderError
{
NoError,
InsufficientSampleData,
FileIOError,
UnsupportedSamplerate,
UnsupportedChannelConfiguration,
UnsupportedBitdepth,
UnsupportedChannelMix,
BufferTooBig,
};
public:
// Assume data adheres to EncoderParams, except for bit depth and fmt
static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path);
};
} // end namespace nqr
#endif

@ -0,0 +1,45 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#ifndef WAVEPACK_DECODER_H
#define WAVEPACK_DECODER_H
#include "AudioDecoder.h"
namespace nqr
{
struct WavPackDecoder : public nqr::BaseDecoder
{
WavPackDecoder() {};
virtual ~WavPackDecoder() {};
virtual int LoadFromPath(nqr::AudioData * data, const std::string & path) override;
virtual int LoadFromBuffer(nqr::AudioData * data, const std::vector<uint8_t> & memory) override;
virtual std::vector<std::string> GetSupportedFileExtensions() override;
};
} // end namespace nqr
#endif

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnyquist", "libnyquist.vcxproj", "{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|Win32.ActiveCfg = Debug|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|Win32.Build.0 = Debug|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|x64.ActiveCfg = Debug|x64
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|x64.Build.0 = Debug|x64
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|Win32.ActiveCfg = Release|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|Win32.Build.0 = Release|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|x64.ActiveCfg = Release|x64
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(ProjectDir)..\..\src\AudioDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\Common.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\FlacDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\OpusDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\WavDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\AudioDevice.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\WavPackDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\CafDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\FlacDependencies.c" />
<ClCompile Include="$(ProjectDir)..\..\src\OpusDependencies.c" />
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDependencies.c" />
<ClCompile Include="$(ProjectDir)..\..\src\WavEncoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\RiffUtils.cpp" />
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_decoder.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_encoder.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\bits.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra1.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra2.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\float.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\metadata.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\pack.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\tags.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack3.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\words.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\wputils.c" />
<ClCompile Include="..\..\src\MusepackDecoder.cpp" />
<ClCompile Include="..\..\src\MusepackDependencies.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_bits_reader.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_decoder.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_demux.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_reader.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\FlacDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\OpusDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\PostProcess.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDevice.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Common.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Dither.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RingBuffer.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavPackDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\CafDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\VorbisDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavEncoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RiffUtils.h" />
<ClInclude Include="..\..\include\libnyquist\MusepackDecoder.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}</ProjectGuid>
<RootNamespace>libaudiodata</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcdec;$(ProjectDir)..\..\third_party\musepack\libmpcenc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcdec;$(ProjectDir)..\..\third_party\musepack\libmpcenc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcdec;$(ProjectDir)..\..\third_party\musepack\libmpcenc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcdec;$(ProjectDir)..\..\third_party\musepack\libmpcenc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_encoder.c">
<Filter>third_party\celt</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_decoder.c">
<Filter>third_party\celt</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\bits.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra1.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra2.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\float.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\pack.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\tags.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack3.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\words.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\wputils.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\metadata.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\OpusDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\AudioDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\CafDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\AudioDevice.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\FlacDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\WavDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\WavPackDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\WavEncoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\OpusDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\Common.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\RiffUtils.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\FlacDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="..\..\src\MusepackDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="..\..\src\MusepackDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_reader.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_bits_reader.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_decoder.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_demux.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\OpusDecoder.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDevice.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\CafDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Common.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\FlacDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\VorbisDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavEncoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavPackDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RingBuffer.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\PostProcess.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Dither.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RiffUtils.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="..\..\include\libnyquist\MusepackDecoder.h">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="include">
<UniqueIdentifier>{f4ea8340-b8ea-4a42-bafb-6cb461e7a2f3}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{a18b19d5-5cd3-49fc-beec-ed17d8e81d6b}</UniqueIdentifier>
</Filter>
<Filter Include="third_party">
<UniqueIdentifier>{33572766-230e-4a7f-8c06-885c4780c1d1}</UniqueIdentifier>
</Filter>
<Filter Include="third_party\wavpack">
<UniqueIdentifier>{d40a1038-d11f-45dc-820b-e32743336269}</UniqueIdentifier>
</Filter>
<Filter Include="third_party\celt">
<UniqueIdentifier>{d38860a7-b4e5-4a1e-99a5-c4eac7e1c013}</UniqueIdentifier>
</Filter>
<Filter Include="include\util">
<UniqueIdentifier>{f27e7823-c56c-4e03-af63-2ef0b1e83cbd}</UniqueIdentifier>
</Filter>
<Filter Include="src\deps">
<UniqueIdentifier>{d839471f-71d1-471e-95e0-c33af9bb64bc}</UniqueIdentifier>
</Filter>
<Filter Include="third_party\mpc">
<UniqueIdentifier>{cc5d22ad-1a3e-46cf-8f65-7d33f02629fb}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libnyquist", "libnyquist.vcxproj", "{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|Win32.ActiveCfg = Debug|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|Win32.Build.0 = Debug|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|x64.ActiveCfg = Debug|x64
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Debug|x64.Build.0 = Debug|x64
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|Win32.ActiveCfg = Release|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|Win32.Build.0 = Release|Win32
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|x64.ActiveCfg = Release|x64
{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,180 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(ProjectDir)..\..\src\AudioDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\Common.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\FlacDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\OpusDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\WavDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\AudioDevice.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\WavPackDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\CafDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\FlacDependencies.c" />
<ClCompile Include="$(ProjectDir)..\..\src\OpusDependencies.c" />
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDecoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDependencies.c" />
<ClCompile Include="$(ProjectDir)..\..\src\WavEncoder.cpp" />
<ClCompile Include="$(ProjectDir)..\..\src\RiffUtils.cpp" />
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_decoder.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_encoder.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\bits.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra1.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra2.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\float.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\metadata.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\pack.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\tags.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack3.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\words.c" />
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\wputils.c" />
<ClCompile Include="..\..\src\MusepackDecoder.cpp" />
<ClCompile Include="..\..\src\MusepackDependencies.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_bits_reader.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_decoder.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_demux.c" />
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_reader.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\FlacDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\OpusDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\PostProcess.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDevice.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Common.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Dither.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RingBuffer.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavPackDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\CafDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\VorbisDecoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavEncoder.h" />
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RiffUtils.h" />
<ClInclude Include="..\..\include\libnyquist\MusepackDecoder.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0EEC3739-F60A-4B90-8B75-9E1AFF28106A}</ProjectGuid>
<RootNamespace>libaudiodata</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcenc;$(ProjectDir)..\..\third_party\musepack\libmpcdec;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcenc;$(ProjectDir)..\..\third_party\musepack\libmpcdec;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcenc;$(ProjectDir)..\..\third_party\musepack\libmpcdec;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_MBCS;D_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNING;WIN32;_WIN32;USE_ALLOCA;OPUS_BUILD;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\third_party\;$(ProjectDir)..\..\include\libnyquist\;$(ProjectDir)..\..\third_party\libvorbis\include;$(ProjectDir)..\..\third_party\libogg\include;$(ProjectDir)..\..\third_party\wavpack\include;$(ProjectDir)..\..\third_party\flac\src\include;$(ProjectDir)..\..\third_party\opus\celt;$(ProjectDir)..\..\third_party\opus\libopus\include;$(ProjectDir)..\..\third_party\opus\libopus\src;$(ProjectDir)..\..\third_party\opus\opusfile\include;$(ProjectDir)..\..\third_party\opus\opusfile\src;$(ProjectDir)..\..\third_party\opus\opusfile\src\include;$(ProjectDir)..\..\third_party\opus\silk;$(ProjectDir)..\..\third_party\opus\silk\float;$(ProjectDir)..\..\third_party\musepack\include;$(ProjectDir)..\..\third_party\musepack\libmpcenc;$(ProjectDir)..\..\third_party\musepack\libmpcdec;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_encoder.c">
<Filter>third_party\celt</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\opus\celt\celt_decoder.c">
<Filter>third_party\celt</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\bits.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra1.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\extra2.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\float.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\pack.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\tags.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\unpack3.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\words.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\wputils.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\third_party\wavpack\src\metadata.c">
<Filter>third_party\wavpack</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\OpusDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\AudioDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\CafDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\AudioDevice.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\FlacDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\VorbisDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\WavDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\WavPackDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\WavEncoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\OpusDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\Common.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\RiffUtils.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="$(ProjectDir)..\..\src\FlacDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="..\..\src\MusepackDependencies.c">
<Filter>src\deps</Filter>
</ClCompile>
<ClCompile Include="..\..\src\MusepackDecoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_bits_reader.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_decoder.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_demux.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
<ClCompile Include="..\..\third_party\musepack\libmpcdec\mpc_reader.c">
<Filter>third_party\mpc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\OpusDecoder.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\AudioDevice.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\CafDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Common.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\FlacDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\VorbisDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavEncoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\WavPackDecoder.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RingBuffer.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\PostProcess.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\Dither.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\libnyquist\RiffUtils.h">
<Filter>include\util</Filter>
</ClInclude>
<ClInclude Include="..\..\include\libnyquist\MusepackDecoder.h">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="include">
<UniqueIdentifier>{f4ea8340-b8ea-4a42-bafb-6cb461e7a2f3}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{a18b19d5-5cd3-49fc-beec-ed17d8e81d6b}</UniqueIdentifier>
</Filter>
<Filter Include="third_party">
<UniqueIdentifier>{33572766-230e-4a7f-8c06-885c4780c1d1}</UniqueIdentifier>
</Filter>
<Filter Include="third_party\wavpack">
<UniqueIdentifier>{d40a1038-d11f-45dc-820b-e32743336269}</UniqueIdentifier>
</Filter>
<Filter Include="third_party\celt">
<UniqueIdentifier>{d38860a7-b4e5-4a1e-99a5-c4eac7e1c013}</UniqueIdentifier>
</Filter>
<Filter Include="include\util">
<UniqueIdentifier>{f27e7823-c56c-4e03-af63-2ef0b1e83cbd}</UniqueIdentifier>
</Filter>
<Filter Include="src\deps">
<UniqueIdentifier>{d839471f-71d1-471e-95e0-c33af9bb64bc}</UniqueIdentifier>
</Filter>
<Filter Include="third_party\mpc">
<UniqueIdentifier>{5e7b9ab1-a3bf-4934-96d8-38ad1c4b08d7}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

@ -0,0 +1,553 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
0804D13F1AE69F0100F4B1FD /* OpusDependencies.c in Sources */ = {isa = PBXBuildFile; fileRef = 0804D13E1AE69F0100F4B1FD /* OpusDependencies.c */; };
0804D1451AE6BA5100F4B1FD /* celt_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0804D1431AE6BA5100F4B1FD /* celt_decoder.c */; settings = {COMPILER_FLAGS = "-w"; }; };
0804D1461AE6BA5100F4B1FD /* celt_encoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 0804D1441AE6BA5100F4B1FD /* celt_encoder.c */; settings = {COMPILER_FLAGS = "-w"; }; };
080A58581B0866F600302850 /* RiffUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 080A58571B0866F600302850 /* RiffUtils.cpp */; };
081FFB191ADF803800673073 /* FlacDependencies.c in Sources */ = {isa = PBXBuildFile; fileRef = 081FFB181ADF803800673073 /* FlacDependencies.c */; };
083730B91BE52B9600216BDC /* MusepackDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 083730B81BE52B9600216BDC /* MusepackDecoder.cpp */; settings = {COMPILER_FLAGS = "-w"; }; };
083730BC1BE5350C00216BDC /* MusepackDependencies.c in Sources */ = {isa = PBXBuildFile; fileRef = 083730BB1BE5350C00216BDC /* MusepackDependencies.c */; };
083730C21BE5372300216BDC /* mpc_bits_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 083730BE1BE5372300216BDC /* mpc_bits_reader.c */; settings = {COMPILER_FLAGS = "-w"; }; };
083730C31BE5372300216BDC /* mpc_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 083730BF1BE5372300216BDC /* mpc_decoder.c */; settings = {COMPILER_FLAGS = "-w"; }; };
083730C41BE5372300216BDC /* mpc_demux.c in Sources */ = {isa = PBXBuildFile; fileRef = 083730C01BE5372300216BDC /* mpc_demux.c */; settings = {COMPILER_FLAGS = "-w"; }; };
083730C51BE5372300216BDC /* mpc_reader.c in Sources */ = {isa = PBXBuildFile; fileRef = 083730C11BE5372300216BDC /* mpc_reader.c */; settings = {COMPILER_FLAGS = "-w"; }; };
083DB3F31B091C1100FB0661 /* WavEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 083DB3F21B091C1100FB0661 /* WavEncoder.cpp */; };
086DADAD1AE029860031F793 /* VorbisDependencies.c in Sources */ = {isa = PBXBuildFile; fileRef = 086DADAB1ADF9DF30031F793 /* VorbisDependencies.c */; };
08894F291AEAA5D7007AAF90 /* bits.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F1E1AEAA5D7007AAF90 /* bits.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F2A1AEAA5D7007AAF90 /* extra1.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F1F1AEAA5D7007AAF90 /* extra1.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F2B1AEAA5D7007AAF90 /* extra2.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F201AEAA5D7007AAF90 /* extra2.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F2C1AEAA5D7007AAF90 /* float.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F211AEAA5D7007AAF90 /* float.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F2D1AEAA5D7007AAF90 /* metadata.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F221AEAA5D7007AAF90 /* metadata.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F2E1AEAA5D7007AAF90 /* pack.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F231AEAA5D7007AAF90 /* pack.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F2F1AEAA5D7007AAF90 /* tags.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F241AEAA5D7007AAF90 /* tags.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F301AEAA5D7007AAF90 /* unpack.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F251AEAA5D7007AAF90 /* unpack.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F311AEAA5D7007AAF90 /* unpack3.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F261AEAA5D7007AAF90 /* unpack3.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F321AEAA5D7007AAF90 /* words.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F271AEAA5D7007AAF90 /* words.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08894F331AEAA5D7007AAF90 /* wputils.c in Sources */ = {isa = PBXBuildFile; fileRef = 08894F281AEAA5D7007AAF90 /* wputils.c */; settings = {COMPILER_FLAGS = "-w"; }; };
08B91D9A1AC73B8A00335131 /* CafDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D901AC73B8A00335131 /* CafDecoder.cpp */; };
08B91D9B1AC73B8A00335131 /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D911AC73B8A00335131 /* AudioDecoder.cpp */; };
08B91D9C1AC73B8A00335131 /* AudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D921AC73B8A00335131 /* AudioDevice.cpp */; };
08B91D9D1AC73B8A00335131 /* Common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D931AC73B8A00335131 /* Common.cpp */; };
08B91D9E1AC73B8A00335131 /* FlacDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D941AC73B8A00335131 /* FlacDecoder.cpp */; };
08B91DA01AC73B8A00335131 /* VorbisDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D961AC73B8A00335131 /* VorbisDecoder.cpp */; };
08B91DA11AC73B8A00335131 /* OpusDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D971AC73B8A00335131 /* OpusDecoder.cpp */; };
08B91DA21AC73B8A00335131 /* WavDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D981AC73B8A00335131 /* WavDecoder.cpp */; };
08B91DA31AC73B8A00335131 /* WavPackDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08B91D991AC73B8A00335131 /* WavPackDecoder.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
08B91D241AC26FC100335131 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0804D13E1AE69F0100F4B1FD /* OpusDependencies.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = OpusDependencies.c; path = src/OpusDependencies.c; sourceTree = SOURCE_ROOT; };
0804D1431AE6BA5100F4B1FD /* celt_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = celt_decoder.c; path = third_party/opus/celt/celt_decoder.c; sourceTree = SOURCE_ROOT; };
0804D1441AE6BA5100F4B1FD /* celt_encoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = celt_encoder.c; path = third_party/opus/celt/celt_encoder.c; sourceTree = SOURCE_ROOT; };
080A58561B0866AA00302850 /* RiffUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RiffUtils.h; path = include/libnyquist/RiffUtils.h; sourceTree = SOURCE_ROOT; };
080A58571B0866F600302850 /* RiffUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RiffUtils.cpp; path = src/RiffUtils.cpp; sourceTree = SOURCE_ROOT; };
081FFB181ADF803800673073 /* FlacDependencies.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FlacDependencies.c; path = src/FlacDependencies.c; sourceTree = SOURCE_ROOT; };
083730B81BE52B9600216BDC /* MusepackDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MusepackDecoder.cpp; path = src/MusepackDecoder.cpp; sourceTree = SOURCE_ROOT; };
083730BA1BE52BA900216BDC /* MusepackDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MusepackDecoder.h; path = include/libnyquist/MusepackDecoder.h; sourceTree = SOURCE_ROOT; };
083730BB1BE5350C00216BDC /* MusepackDependencies.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = MusepackDependencies.c; path = src/MusepackDependencies.c; sourceTree = SOURCE_ROOT; };
083730BE1BE5372300216BDC /* mpc_bits_reader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mpc_bits_reader.c; path = third_party/musepack/libmpcdec/mpc_bits_reader.c; sourceTree = SOURCE_ROOT; };
083730BF1BE5372300216BDC /* mpc_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mpc_decoder.c; path = third_party/musepack/libmpcdec/mpc_decoder.c; sourceTree = SOURCE_ROOT; };
083730C01BE5372300216BDC /* mpc_demux.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mpc_demux.c; path = third_party/musepack/libmpcdec/mpc_demux.c; sourceTree = SOURCE_ROOT; };
083730C11BE5372300216BDC /* mpc_reader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mpc_reader.c; path = third_party/musepack/libmpcdec/mpc_reader.c; sourceTree = SOURCE_ROOT; };
083DB3F21B091C1100FB0661 /* WavEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WavEncoder.cpp; path = src/WavEncoder.cpp; sourceTree = SOURCE_ROOT; };
083DB3F41B091C1E00FB0661 /* WavEncoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WavEncoder.h; path = include/libnyquist/WavEncoder.h; sourceTree = SOURCE_ROOT; };
086DADAB1ADF9DF30031F793 /* VorbisDependencies.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = VorbisDependencies.c; path = src/VorbisDependencies.c; sourceTree = SOURCE_ROOT; };
08894F1E1AEAA5D7007AAF90 /* bits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bits.c; path = third_party/wavpack/src/bits.c; sourceTree = SOURCE_ROOT; };
08894F1F1AEAA5D7007AAF90 /* extra1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = extra1.c; path = third_party/wavpack/src/extra1.c; sourceTree = SOURCE_ROOT; };
08894F201AEAA5D7007AAF90 /* extra2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = extra2.c; path = third_party/wavpack/src/extra2.c; sourceTree = SOURCE_ROOT; };
08894F211AEAA5D7007AAF90 /* float.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = float.c; path = third_party/wavpack/src/float.c; sourceTree = SOURCE_ROOT; };
08894F221AEAA5D7007AAF90 /* metadata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = metadata.c; path = third_party/wavpack/src/metadata.c; sourceTree = SOURCE_ROOT; };
08894F231AEAA5D7007AAF90 /* pack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pack.c; path = third_party/wavpack/src/pack.c; sourceTree = SOURCE_ROOT; };
08894F241AEAA5D7007AAF90 /* tags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tags.c; path = third_party/wavpack/src/tags.c; sourceTree = SOURCE_ROOT; };
08894F251AEAA5D7007AAF90 /* unpack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unpack.c; path = third_party/wavpack/src/unpack.c; sourceTree = SOURCE_ROOT; };
08894F261AEAA5D7007AAF90 /* unpack3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = unpack3.c; path = third_party/wavpack/src/unpack3.c; sourceTree = SOURCE_ROOT; };
08894F271AEAA5D7007AAF90 /* words.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = words.c; path = third_party/wavpack/src/words.c; sourceTree = SOURCE_ROOT; };
08894F281AEAA5D7007AAF90 /* wputils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wputils.c; path = third_party/wavpack/src/wputils.c; sourceTree = SOURCE_ROOT; };
08B91D261AC26FC100335131 /* libnyquist.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libnyquist.a; sourceTree = BUILT_PRODUCTS_DIR; };
08B91D831AC73B8000335131 /* CafDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CafDecoder.h; path = include/libnyquist/CafDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D841AC73B8000335131 /* AudioDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioDecoder.h; path = include/libnyquist/AudioDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D851AC73B8000335131 /* AudioDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = AudioDevice.h; path = include/libnyquist/AudioDevice.h; sourceTree = SOURCE_ROOT; };
08B91D861AC73B8000335131 /* Common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Common.h; path = include/libnyquist/Common.h; sourceTree = SOURCE_ROOT; };
08B91D871AC73B8000335131 /* Dither.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dither.h; path = include/libnyquist/Dither.h; sourceTree = SOURCE_ROOT; };
08B91D881AC73B8000335131 /* FlacDecoder.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = FlacDecoder.h; path = include/libnyquist/FlacDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D891AC73B8000335131 /* VorbisDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VorbisDecoder.h; path = include/libnyquist/VorbisDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D8A1AC73B8000335131 /* OpusDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OpusDecoder.h; path = include/libnyquist/OpusDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D8B1AC73B8000335131 /* PostProcess.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PostProcess.h; path = include/libnyquist/PostProcess.h; sourceTree = SOURCE_ROOT; };
08B91D8C1AC73B8000335131 /* RingBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RingBuffer.h; path = include/libnyquist/RingBuffer.h; sourceTree = SOURCE_ROOT; };
08B91D8E1AC73B8000335131 /* WavDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WavDecoder.h; path = include/libnyquist/WavDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D8F1AC73B8000335131 /* WavPackDecoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WavPackDecoder.h; path = include/libnyquist/WavPackDecoder.h; sourceTree = SOURCE_ROOT; };
08B91D901AC73B8A00335131 /* CafDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CafDecoder.cpp; path = src/CafDecoder.cpp; sourceTree = SOURCE_ROOT; };
08B91D911AC73B8A00335131 /* AudioDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AudioDecoder.cpp; path = src/AudioDecoder.cpp; sourceTree = SOURCE_ROOT; };
08B91D921AC73B8A00335131 /* AudioDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AudioDevice.cpp; path = src/AudioDevice.cpp; sourceTree = SOURCE_ROOT; };
08B91D931AC73B8A00335131 /* Common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Common.cpp; path = src/Common.cpp; sourceTree = SOURCE_ROOT; };
08B91D941AC73B8A00335131 /* FlacDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FlacDecoder.cpp; path = src/FlacDecoder.cpp; sourceTree = SOURCE_ROOT; };
08B91D961AC73B8A00335131 /* VorbisDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VorbisDecoder.cpp; path = src/VorbisDecoder.cpp; sourceTree = SOURCE_ROOT; };
08B91D971AC73B8A00335131 /* OpusDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpusDecoder.cpp; path = src/OpusDecoder.cpp; sourceTree = SOURCE_ROOT; };
08B91D981AC73B8A00335131 /* WavDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WavDecoder.cpp; path = src/WavDecoder.cpp; sourceTree = SOURCE_ROOT; };
08B91D991AC73B8A00335131 /* WavPackDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WavPackDecoder.cpp; path = src/WavPackDecoder.cpp; sourceTree = SOURCE_ROOT; };
08C83B7C1C25D7780071EED6 /* IMA4Util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IMA4Util.h; path = include/libnyquist/IMA4Util.h; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
08B91D231AC26FC100335131 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0804D1421AE6BA2F00F4B1FD /* celt */ = {
isa = PBXGroup;
children = (
0804D1431AE6BA5100F4B1FD /* celt_decoder.c */,
0804D1441AE6BA5100F4B1FD /* celt_encoder.c */,
);
name = celt;
sourceTree = "<group>";
};
080A58551B083D5100302850 /* deps */ = {
isa = PBXGroup;
children = (
081FFB181ADF803800673073 /* FlacDependencies.c */,
086DADAB1ADF9DF30031F793 /* VorbisDependencies.c */,
0804D13E1AE69F0100F4B1FD /* OpusDependencies.c */,
083730BB1BE5350C00216BDC /* MusepackDependencies.c */,
);
name = deps;
sourceTree = "<group>";
};
080A58591B0867E500302850 /* util */ = {
isa = PBXGroup;
children = (
08B91D871AC73B8000335131 /* Dither.h */,
080A58561B0866AA00302850 /* RiffUtils.h */,
08B91D8C1AC73B8000335131 /* RingBuffer.h */,
08B91D8B1AC73B8000335131 /* PostProcess.h */,
);
name = util;
sourceTree = "<group>";
};
083730BD1BE5370400216BDC /* musepack */ = {
isa = PBXGroup;
children = (
083730BE1BE5372300216BDC /* mpc_bits_reader.c */,
083730BF1BE5372300216BDC /* mpc_decoder.c */,
083730C01BE5372300216BDC /* mpc_demux.c */,
083730C11BE5372300216BDC /* mpc_reader.c */,
);
name = musepack;
sourceTree = "<group>";
};
08894F1D1AEAA5B7007AAF90 /* wavpack */ = {
isa = PBXGroup;
children = (
08894F1E1AEAA5D7007AAF90 /* bits.c */,
08894F1F1AEAA5D7007AAF90 /* extra1.c */,
08894F201AEAA5D7007AAF90 /* extra2.c */,
08894F211AEAA5D7007AAF90 /* float.c */,
08894F221AEAA5D7007AAF90 /* metadata.c */,
08894F231AEAA5D7007AAF90 /* pack.c */,
08894F241AEAA5D7007AAF90 /* tags.c */,
08894F251AEAA5D7007AAF90 /* unpack.c */,
08894F261AEAA5D7007AAF90 /* unpack3.c */,
08894F271AEAA5D7007AAF90 /* words.c */,
08894F281AEAA5D7007AAF90 /* wputils.c */,
);
name = wavpack;
sourceTree = "<group>";
};
08B91D1D1AC26FC100335131 = {
isa = PBXGroup;
children = (
08B91D281AC26FC100335131 /* libnyquist */,
08B91D511AC270BB00335131 /* third_party */,
08B91D801AC73B3B00335131 /* Frameworks */,
08B91D271AC26FC100335131 /* Products */,
);
sourceTree = "<group>";
};
08B91D271AC26FC100335131 /* Products */ = {
isa = PBXGroup;
children = (
08B91D261AC26FC100335131 /* libnyquist.a */,
);
name = Products;
sourceTree = "<group>";
};
08B91D281AC26FC100335131 /* libnyquist */ = {
isa = PBXGroup;
children = (
08B91D811AC73B5A00335131 /* include */,
08B91D821AC73B6900335131 /* src */,
);
path = libnyquist;
sourceTree = "<group>";
};
08B91D511AC270BB00335131 /* third_party */ = {
isa = PBXGroup;
children = (
083730BD1BE5370400216BDC /* musepack */,
08894F1D1AEAA5B7007AAF90 /* wavpack */,
0804D1421AE6BA2F00F4B1FD /* celt */,
);
name = third_party;
path = libnyquist;
sourceTree = "<group>";
};
08B91D801AC73B3B00335131 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
08B91D811AC73B5A00335131 /* include */ = {
isa = PBXGroup;
children = (
080A58591B0867E500302850 /* util */,
08B91D841AC73B8000335131 /* AudioDecoder.h */,
08B91D851AC73B8000335131 /* AudioDevice.h */,
08B91D861AC73B8000335131 /* Common.h */,
08B91D831AC73B8000335131 /* CafDecoder.h */,
083730BA1BE52BA900216BDC /* MusepackDecoder.h */,
08B91D881AC73B8000335131 /* FlacDecoder.h */,
08B91D891AC73B8000335131 /* VorbisDecoder.h */,
08B91D8A1AC73B8000335131 /* OpusDecoder.h */,
083DB3F41B091C1E00FB0661 /* WavEncoder.h */,
08B91D8E1AC73B8000335131 /* WavDecoder.h */,
08B91D8F1AC73B8000335131 /* WavPackDecoder.h */,
08C83B7C1C25D7780071EED6 /* IMA4Util.h */,
);
name = include;
sourceTree = "<group>";
};
08B91D821AC73B6900335131 /* src */ = {
isa = PBXGroup;
children = (
080A58551B083D5100302850 /* deps */,
08B91D901AC73B8A00335131 /* CafDecoder.cpp */,
083730B81BE52B9600216BDC /* MusepackDecoder.cpp */,
08B91D911AC73B8A00335131 /* AudioDecoder.cpp */,
08B91D921AC73B8A00335131 /* AudioDevice.cpp */,
08B91D931AC73B8A00335131 /* Common.cpp */,
080A58571B0866F600302850 /* RiffUtils.cpp */,
08B91D941AC73B8A00335131 /* FlacDecoder.cpp */,
08B91D961AC73B8A00335131 /* VorbisDecoder.cpp */,
08B91D971AC73B8A00335131 /* OpusDecoder.cpp */,
083DB3F21B091C1100FB0661 /* WavEncoder.cpp */,
08B91D981AC73B8A00335131 /* WavDecoder.cpp */,
08B91D991AC73B8A00335131 /* WavPackDecoder.cpp */,
);
name = src;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
08B91D251AC26FC100335131 /* libnyquist */ = {
isa = PBXNativeTarget;
buildConfigurationList = 08B91D2D1AC26FC100335131 /* Build configuration list for PBXNativeTarget "libnyquist" */;
buildPhases = (
08B91D221AC26FC100335131 /* Sources */,
08B91D231AC26FC100335131 /* Frameworks */,
08B91D241AC26FC100335131 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = libnyquist;
productName = libnyquist;
productReference = 08B91D261AC26FC100335131 /* libnyquist.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08B91D1E1AC26FC100335131 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = "Dimitri Diakopoulos";
TargetAttributes = {
08B91D251AC26FC100335131 = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 08B91D211AC26FC100335131 /* Build configuration list for PBXProject "libnyquist" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 08B91D1D1AC26FC100335131;
productRefGroup = 08B91D271AC26FC100335131 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
08B91D251AC26FC100335131 /* libnyquist */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
08B91D221AC26FC100335131 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
08894F2C1AEAA5D7007AAF90 /* float.c in Sources */,
083730C51BE5372300216BDC /* mpc_reader.c in Sources */,
08894F2E1AEAA5D7007AAF90 /* pack.c in Sources */,
08894F2A1AEAA5D7007AAF90 /* extra1.c in Sources */,
08894F321AEAA5D7007AAF90 /* words.c in Sources */,
08894F291AEAA5D7007AAF90 /* bits.c in Sources */,
08894F2B1AEAA5D7007AAF90 /* extra2.c in Sources */,
08894F301AEAA5D7007AAF90 /* unpack.c in Sources */,
083730B91BE52B9600216BDC /* MusepackDecoder.cpp in Sources */,
0804D1451AE6BA5100F4B1FD /* celt_decoder.c in Sources */,
0804D1461AE6BA5100F4B1FD /* celt_encoder.c in Sources */,
08894F331AEAA5D7007AAF90 /* wputils.c in Sources */,
08894F2F1AEAA5D7007AAF90 /* tags.c in Sources */,
08894F2D1AEAA5D7007AAF90 /* metadata.c in Sources */,
08894F311AEAA5D7007AAF90 /* unpack3.c in Sources */,
083730C21BE5372300216BDC /* mpc_bits_reader.c in Sources */,
083730C41BE5372300216BDC /* mpc_demux.c in Sources */,
083730C31BE5372300216BDC /* mpc_decoder.c in Sources */,
083730BC1BE5350C00216BDC /* MusepackDependencies.c in Sources */,
081FFB191ADF803800673073 /* FlacDependencies.c in Sources */,
0804D13F1AE69F0100F4B1FD /* OpusDependencies.c in Sources */,
083DB3F31B091C1100FB0661 /* WavEncoder.cpp in Sources */,
08B91D9B1AC73B8A00335131 /* AudioDecoder.cpp in Sources */,
08B91DA01AC73B8A00335131 /* VorbisDecoder.cpp in Sources */,
08B91DA21AC73B8A00335131 /* WavDecoder.cpp in Sources */,
08B91D9A1AC73B8A00335131 /* CafDecoder.cpp in Sources */,
080A58581B0866F600302850 /* RiffUtils.cpp in Sources */,
08B91DA11AC73B8A00335131 /* OpusDecoder.cpp in Sources */,
08B91D9E1AC73B8A00335131 /* FlacDecoder.cpp in Sources */,
08B91D9C1AC73B8A00335131 /* AudioDevice.cpp in Sources */,
086DADAD1AE029860031F793 /* VorbisDependencies.c in Sources */,
08B91DA31AC73B8A00335131 /* WavPackDecoder.cpp in Sources */,
08B91D9D1AC73B8A00335131 /* Common.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
08B91D2B1AC26FC100335131 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
08B91D2C1AC26FC100335131 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
08B91D2E1AC26FC100335131 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
EXECUTABLE_EXTENSION = a;
EXECUTABLE_PREFIX = "";
GCC_CHAR_IS_UNSIGNED_CHAR = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_BUILTIN_FUNCTIONS = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_INPUT_FILETYPE = automatic;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = YES;
GCC_NO_COMMON_BLOCKS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
__MACOSX_CORE__,
USE_ALLOCA,
OPUS_BUILD,
);
GCC_STRICT_ALIASING = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/third_party",
"$(SRCROOT)/third_party/rtaudio",
"$(SRCROOT)/third_party/flac/src/include",
"$(SRCROOT)/third_party/libogg/include",
"$(SRCROOT)/third_party/libvorbis/src",
"$(SRCROOT)/third_party/libvorbis/include",
"$(SRCROOT)/third_party/opus/silk",
"$(SRCROOT)/third_party/opus/silk/float",
"$(SRCROOT)/third_party/opus/celt",
"$(SRCROOT)/third_party/opus/libopus/include",
"$(SRCROOT)/third_party/opus/opusfile/src/include",
"$(SRCROOT)/third_party/opus/opusfile/include",
"$(SRCROOT)/third_party/wavpack/include",
"$(SRCROOT)/third_party/wavpack/src",
"$(SRCROOT)/third_party/musepack/include",
"$(SRCROOT)/third_party/musepack/libmpcdec",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
};
name = Debug;
};
08B91D2F1AC26FC100335131 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
EXECUTABLE_EXTENSION = a;
EXECUTABLE_PREFIX = "";
GCC_CHAR_IS_UNSIGNED_CHAR = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_BUILTIN_FUNCTIONS = YES;
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
GCC_INPUT_FILETYPE = automatic;
GCC_LINK_WITH_DYNAMIC_LIBRARIES = YES;
GCC_NO_COMMON_BLOCKS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
__MACOSX_CORE__,
USE_ALLOCA,
OPUS_BUILD,
);
GCC_STRICT_ALIASING = NO;
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/third_party",
"$(SRCROOT)/third_party/rtaudio",
"$(SRCROOT)/third_party/flac/src/include",
"$(SRCROOT)/third_party/libogg/include",
"$(SRCROOT)/third_party/libvorbis/src",
"$(SRCROOT)/third_party/libvorbis/include",
"$(SRCROOT)/third_party/opus/silk",
"$(SRCROOT)/third_party/opus/silk/float",
"$(SRCROOT)/third_party/opus/celt",
"$(SRCROOT)/third_party/opus/libopus/include",
"$(SRCROOT)/third_party/opus/opusfile/src/include",
"$(SRCROOT)/third_party/opus/opusfile/include",
"$(SRCROOT)/third_party/wavpack/include",
"$(SRCROOT)/third_party/wavpack/src",
"$(SRCROOT)/third_party/musepack/include",
"$(SRCROOT)/third_party/musepack/libmpcdec",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
08B91D211AC26FC100335131 /* Build configuration list for PBXProject "libnyquist" */ = {
isa = XCConfigurationList;
buildConfigurations = (
08B91D2B1AC26FC100335131 /* Debug */,
08B91D2C1AC26FC100335131 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
08B91D2D1AC26FC100335131 /* Build configuration list for PBXNativeTarget "libnyquist" */ = {
isa = XCConfigurationList;
buildConfigurations = (
08B91D2E1AC26FC100335131 /* Debug */,
08B91D2F1AC26FC100335131 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08B91D1E1AC26FC100335131 /* Project object */;
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:libnyquist.xcodeproj">
</FileRef>
</Workspace>

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "libnyquist.a"
BlueprintName = "libnyquist"
ReferencedContainer = "container:libnyquist.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "libnyquist.a"
BlueprintName = "libnyquist"
ReferencedContainer = "container:libnyquist.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "YES"
customWorkingDirectory = "$(PROJECT_DIR)"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "libnyquist.a"
BlueprintName = "libnyquist"
ReferencedContainer = "container:libnyquist.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "08B91D251AC26FC100335131"
BuildableName = "libnyquist.a"
BlueprintName = "libnyquist"
ReferencedContainer = "container:libnyquist.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -0,0 +1,138 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "AudioDecoder.h"
#include "WavDecoder.h"
#include "WavPackDecoder.h"
#include "FlacDecoder.h"
#include "VorbisDecoder.h"
#include "OpusDecoder.h"
#include "CafDecoder.h"
#include "MusepackDecoder.h"
using namespace nqr;
NyquistIO::NyquistIO()
{
BuildDecoderTable();
}
NyquistIO::~NyquistIO() { }
int NyquistIO::Load(AudioData * data, const std::string & path)
{
if (IsFileSupported(path))
{
if (decoderTable.size())
{
auto fileExtension = ParsePathForExtension(path);
auto decoder = GetDecoderForExtension(fileExtension);
try
{
return decoder->LoadFromPath(data, path);
}
catch (std::exception e)
{
std::cerr << "Caught fatal exception: " << e.what() << std::endl;
}
}
return IOError::NoDecodersLoaded;
}
else
{
return IOError::ExtensionNotSupported;
}
// Should never be reached
return IOError::UnknownError;
}
int NyquistIO::Load(AudioData * data, std::string extension, const std::vector<uint8_t> & buffer)
{
if (decoderTable.find(extension) == decoderTable.end())
{
return IOError::ExtensionNotSupported;
}
if (decoderTable.size())
{
auto decoder = GetDecoderForExtension(extension);
try
{
return decoder->LoadFromBuffer(data, buffer);
}
catch (std::exception e)
{
std::cerr << "Caught fatal exception: " << e.what() << std::endl;
}
}
else
{
return IOError::NoDecodersLoaded;
}
// Should never be reached
return IOError::UnknownError;
}
bool NyquistIO::IsFileSupported(const std::string path) const
{
auto fileExtension = ParsePathForExtension(path);
if (decoderTable.find(fileExtension) == decoderTable.end())
{
return false;
}
else
{
return true;
}
}
std::string NyquistIO::ParsePathForExtension(const std::string & path) const
{
if (path.find_last_of(".") != std::string::npos)
return path.substr(path.find_last_of(".") + 1);
return std::string("");
}
std::shared_ptr<BaseDecoder> NyquistIO::GetDecoderForExtension(const std::string ext)
{
return decoderTable[ext];
}
void NyquistIO::BuildDecoderTable()
{
AddDecoderToTable(std::make_shared<WavDecoder>());
AddDecoderToTable(std::make_shared<WavPackDecoder>());
AddDecoderToTable(std::make_shared<FlacDecoder>());
AddDecoderToTable(std::make_shared<VorbisDecoder>());
AddDecoderToTable(std::make_shared<OpusDecoder>());
AddDecoderToTable(std::make_shared<CAFDecoder>());
AddDecoderToTable(std::make_shared<MusepackDecoder>());
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -28,61 +28,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <thread>
#include <chrono>
#include <iostream>
using namespace nqr;
static RingBufferT<float> buffer(BUFFER_LENGTH);
static RingBufferT<float> record_buffer(BUFFER_LENGTH / 2);
static int rt_callback(void * output_buffer, void * input_buffer, uint32_t num_bufferframes, double stream_time, RtAudioStreamStatus status, void * user_data)
static int rt_callback(void * output_buffer, void * input_buffer, unsigned int num_bufferframes, double stream_time, RtAudioStreamStatus status, void * user_data)
{
if (status) std::cerr << "[rtaudio] buffer over or underflow" << std::endl;
if (status) std::cerr << "[rtaudio] Buffer over or underflow" << std::endl;
// Playback
if (buffer.getAvailableRead()) buffer.read((float*) output_buffer, BUFFER_LENGTH);
else memset(output_buffer, 0, BUFFER_LENGTH * sizeof(float));
// Recording
if (record_buffer.getAvailableWrite()) record_buffer.write((float*) input_buffer, BUFFER_LENGTH / 2);
if (buffer.getAvailableRead())
{
buffer.read((float*) output_buffer, BUFFER_LENGTH);
}
else
{
memset(output_buffer, 0, BUFFER_LENGTH * sizeof(float));
}
return 0;
}
AudioDevice::AudioDevice(int numChannels, int sampleRate, int deviceId)
{
rtaudio = std::unique_ptr<RtAudio>(new RtAudio);
info.id = (deviceId != -1) ? deviceId : rtaudio->getDefaultOutputDevice();
info.numChannels = numChannels;
info.sampleRate = sampleRate;
info.frameSize = FRAME_SIZE;
}
AudioDevice::~AudioDevice()
{
if (rtaudio)
{
rtaudio->stopStream();
if (rtaudio->isStreamOpen())
{
rtaudio->closeStream();
}
}
}
bool AudioDevice::Open(const int deviceId)
{
if (!rtaudio) throw std::runtime_error("rtaudio not created yet");
RtAudio::StreamParameters outputParams;
outputParams.deviceId = info.id;
outputParams.nChannels = info.numChannels;
outputParams.firstChannel = 0;
RtAudio::StreamParameters parameters;
parameters.deviceId = info.id;
parameters.nChannels = info.numChannels;
parameters.firstChannel = 0;
RtAudio::StreamParameters inputParams;
inputParams.deviceId = rtaudio->getDefaultInputDevice();
inputParams.nChannels = 1;
inputParams.firstChannel = 0;
rtaudio->openStream(&outputParams, &inputParams, RTAUDIO_FLOAT32, info.sampleRate, &info.frameSize, &rt_callback, (void*) & buffer);
rtaudio->openStream(&parameters, NULL, RTAUDIO_FLOAT32, info.sampleRate, &info.frameSize, &rt_callback, (void*) & buffer);
if (rtaudio->isStreamOpen())
{
@ -97,11 +73,11 @@ void AudioDevice::ListAudioDevices()
std::unique_ptr<RtAudio> tempDevice(new RtAudio);
RtAudio::DeviceInfo info;
uint32_t devices = tempDevice->getDeviceCount();
unsigned int devices = tempDevice->getDeviceCount();
std::cout << "[rtaudio] Found: " << devices << " device(s)\n";
for (uint32_t i = 0; i < devices; ++i)
for (unsigned int i = 0; i < devices; ++i)
{
info = tempDevice->getDeviceInfo(i);
std::cout << "\tDevice: " << i << " - " << info.name << std::endl;
@ -118,32 +94,11 @@ bool AudioDevice::Play(const std::vector<float> & data)
int writeCount = 0;
while (writeCount < sizeInFrames)
while(writeCount < sizeInFrames)
{
bool status = buffer.write((data.data() + (writeCount * BUFFER_LENGTH)), BUFFER_LENGTH);
if (status) writeCount++;
}
return true;
}
bool AudioDevice::Record(const uint32_t lengthInSamples, std::vector<float> & recordingBuffer)
{
uint64_t recordedSamples = 0;
// Allocate memory upfront (revisit this later...)
recordingBuffer.resize(lengthInSamples + (BUFFER_LENGTH)); // + a little padding
while (recordedSamples < lengthInSamples)
{
if (record_buffer.getAvailableRead())
{
if (record_buffer.read(recordingBuffer.data() + recordedSamples, BUFFER_LENGTH / 2))
{
recordedSamples += (BUFFER_LENGTH / 2);
}
}
}
return true;
}
}

@ -0,0 +1,47 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "CafDecoder.h"
using namespace nqr;
//////////////////////
// Public Interface //
//////////////////////
int CAFDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
return IOError::LoadPathNotImplemented;
}
int CAFDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
return IOError::LoadBufferNotImplemented;
}
std::vector<std::string> CAFDecoder::GetSupportedFileExtensions()
{
return {};
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -24,193 +24,38 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Common.h"
#include "Decoders.h"
#include <cstring>
#include <unordered_map>
using namespace nqr;
NyquistIO::NyquistIO() { BuildDecoderTable(); }
NyquistIO::~NyquistIO() { }
void NyquistIO::Load(AudioData * data, const std::string & path)
NyquistFileBuffer nqr::ReadFile(std::string pathToFile)
{
if (IsFileSupported(path))
{
if (decoderTable.size())
{
auto fileExtension = ParsePathForExtension(path);
auto decoder = GetDecoderForExtension(fileExtension);
try
{
decoder->LoadFromPath(data, path);
}
catch (const std::exception & e)
{
std::cerr << "NyquistIO::Load(" << path << ") caught internal exception: " << e.what() << std::endl;
throw;
}
}
else throw std::runtime_error("No available decoders.");
}
else
{
throw UnsupportedExtensionEx();
}
}
void NyquistIO::Load(AudioData * data, const std::vector<uint8_t> & buffer)
{
const std::map<std::vector<int16_t>, std::string> magic_map{
{{ 'w', 'v', 'p', 'k' }, "wv" },
{{ 'M', 'P', 'C', 'K' }, "mpc" },
{{ 0xFF, 0xFB }, "mp3" }, // ÿû, mp3 without ID3 header
{{ 'I', 'D', '3' }, "mp3" }, // mp3 with ID3 header
{{ 'O', 'g', 'g', 'S' }, "ogg_or_vorbis" }, // see `match_ogg_subtype`
{{ 'f', 'L', 'a', 'C' }, "flac" },
{{ 0x52, 0x49, 0x46, 0x46, -0x1, -0x1, -0x1, -0x1, 0x57, 0x41, 0x56, 0x45 }, "wav" } // RIFF....WAVE
};
auto match_magic = [](const uint8_t * data, const std::vector<int16_t> & magic)
{
for (int i = 0; i < magic.size(); ++i)
{
if (magic[i] != data[i] && magic[i] != -0x1) // -0x1 skips things that don't contribute to the magic number
{
return false;
}
}
return true;
};
auto match_ogg_subtype = [](const uint8_t * data)
{
std::string header; // arbitrarily read the first 64 bytes as ascii characters
for (int i = 0; i < 64; ++i) header += data[i];
std::size_t found_opus = header.find("OpusHead");
if (found_opus != std::string::npos) return "opus";
std::size_t found_vorbis = header.find("vorbis");
if (found_vorbis != std::string::npos) return "ogg";
return "none";
};
std::string ext = "none";
for (auto & filetype : magic_map)
{
if (match_magic(buffer.data(), filetype.first))
{
ext = filetype.second;
}
if (ext == "ogg_or_vorbis")
{
ext = match_ogg_subtype(buffer.data());
}
}
NyquistIO::Load(data, ext, buffer);
}
void NyquistIO::Load(AudioData * data, const std::string & extension, const std::vector<uint8_t> & buffer)
{
if (decoderTable.find(extension) == decoderTable.end())
{
throw UnsupportedExtensionEx();
}
if (decoderTable.size())
{
auto decoder = GetDecoderForExtension(extension);
try
{
decoder->LoadFromBuffer(data, buffer);
}
catch (const std::exception & e)
{
std::cerr << "caught internal loading exception: " << e.what() << std::endl;
throw;
}
}
else throw std::runtime_error("fatal: no decoders available");
}
bool NyquistIO::IsFileSupported(const std::string & path) const
{
auto fileExtension = ParsePathForExtension(path);
if (decoderTable.find(fileExtension) == decoderTable.end()) return false;
else return true;
}
std::string NyquistIO::ParsePathForExtension(const std::string & path) const
{
if (path.find_last_of(".") != std::string::npos) return path.substr(path.find_last_of(".") + 1);
return std::string("");
}
std::shared_ptr<BaseDecoder> NyquistIO::GetDecoderForExtension(const std::string & ext)
{
if (decoderTable.size()) return decoderTable[ext];
else throw std::runtime_error("No available decoders.");
return nullptr;
}
void NyquistIO::AddDecoderToTable(std::shared_ptr<nqr::BaseDecoder> decoder)
{
auto supportedExtensions = decoder->GetSupportedFileExtensions();
for (const auto ext : supportedExtensions)
{
if (decoderTable.count(ext) >= 1) throw std::runtime_error("decoder already exists for extension");
decoderTable.insert(DecoderPair(ext, decoder));
}
}
void NyquistIO::BuildDecoderTable()
{
AddDecoderToTable(std::make_shared<WavDecoder>());
AddDecoderToTable(std::make_shared<WavPackDecoder>());
AddDecoderToTable(std::make_shared<FlacDecoder>());
AddDecoderToTable(std::make_shared<VorbisDecoder>());
AddDecoderToTable(std::make_shared<OpusDecoder>());
AddDecoderToTable(std::make_shared<MusepackDecoder>());
AddDecoderToTable(std::make_shared<Mp3Decoder>());
}
NyquistFileBuffer nqr::ReadFile(const std::string & pathToFile)
{
//std::cout << "[Debug] Open: " << pathToFile << std::endl;
std::cout << "[Debug] Open: " << pathToFile << std::endl;
FILE * audioFile = fopen(pathToFile.c_str(), "rb");
if (!audioFile)
{
throw std::runtime_error("file not found");
}
fseek(audioFile, 0, SEEK_END);
size_t lengthInBytes = ftell(audioFile);
fseek(audioFile, 0, SEEK_SET);
// Allocate temporary buffer
std::vector<uint8_t> fileBuffer(lengthInBytes);
size_t elementsRead = fread(fileBuffer.data(), 1, lengthInBytes, audioFile);
if (elementsRead == 0 || fileBuffer.size() < 64)
{
throw std::runtime_error("error reading file or file too small");
}
NyquistFileBuffer data = {std::move(fileBuffer), elementsRead};
fclose(audioFile);
// Copy out to user
return data;
}
@ -219,7 +64,7 @@ NyquistFileBuffer nqr::ReadFile(const std::string & pathToFile)
void nqr::ConvertToFloat32(float * dst, const uint8_t * src, const size_t N, PCMFormat f)
{
assert(f != PCM_END);
if (f == PCM_U8)
{
const uint8_t * dataPtr = reinterpret_cast<const uint8_t *>(src);
@ -255,15 +100,14 @@ void nqr::ConvertToFloat32(float * dst, const uint8_t * src, const size_t N, PCM
for (size_t i = 0; i < N; ++i)
dst[i] = int32_to_float32(Read32(dataPtr[i]));
}
//@todo add int64 format
else if (f == PCM_FLT)
{
std::memcpy(dst, src, N * sizeof(float));
/* const float * dataPtr = reinterpret_cast<const float *>(src);
const float * dataPtr = reinterpret_cast<const float *>(src);
for (size_t i = 0; i < N; ++i)
dst[i] = (float) Read32(dataPtr[i]); */
dst[i] = (float) Read32(dataPtr[i]);
}
else if (f == PCM_DBL)
{
@ -277,7 +121,7 @@ void nqr::ConvertToFloat32(float * dst, const uint8_t * src, const size_t N, PCM
void nqr::ConvertToFloat32(float * dst, const int32_t * src, const size_t N, PCMFormat f)
{
assert(f != PCM_END);
if (f == PCM_16)
{
for (size_t i = 0; i < N; ++i)
@ -316,7 +160,7 @@ void nqr::ConvertFromFloat32(uint8_t * dst, const float * src, const size_t N, P
assert(f != PCM_END);
Dither dither(t);
if (f == PCM_U8)
{
uint8_t * destPtr = reinterpret_cast<uint8_t *>(dst);

@ -1,442 +0,0 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "Encoders.h"
#include <fstream>
using namespace nqr;
static inline void to_bytes(uint8_t value, char * arr)
{
arr[0] = (value) & 0xFF;
}
static inline void to_bytes(uint16_t value, char * arr)
{
arr[0] = (value) & 0xFF;
arr[1] = (value >> 8) & 0xFF;
}
static inline void to_bytes(uint32_t value, char * arr)
{
arr[0] = (value) & 0xFF;
arr[1] = (value >> 8) & 0xFF;
arr[2] = (value >> 16) & 0xFF;
arr[3] = (value >> 24) & 0xFF;
}
////////////////////////////
// Wave File Encoding //
////////////////////////////
int nqr::encode_wav_to_disk(const EncoderParams p, const AudioData * d, const std::string & path)
{
if (!d->samples.size())
return EncoderError::InsufficientSampleData;
// Cast away const because we know what we are doing (Hopefully?)
float * sampleData = const_cast<float *>(d->samples.data());
size_t sampleDataSize = d->samples.size();
std::vector<float> sampleDataOptionalMix;
if (sampleDataSize <= 32)
{
return EncoderError::InsufficientSampleData;
}
if (d->channelCount < 1 || d->channelCount > 8)
{
return EncoderError::UnsupportedChannelConfiguration;
}
// Handle Channel Mixing --
// Mono => Stereo
if (d->channelCount == 1 && p.channelCount == 2)
{
sampleDataOptionalMix.resize(sampleDataSize * 2);
MonoToStereo(sampleData, sampleDataOptionalMix.data(), sampleDataSize); // Mix
// Re-point data
sampleData = sampleDataOptionalMix.data();
sampleDataSize = sampleDataOptionalMix.size();
}
// Stereo => Mono
else if (d->channelCount == 2 && p.channelCount == 1)
{
sampleDataOptionalMix.resize(sampleDataSize / 2);
StereoToMono(sampleData, sampleDataOptionalMix.data(), sampleDataSize); // Mix
// Re-point data
sampleData = sampleDataOptionalMix.data();
sampleDataSize = sampleDataOptionalMix.size();
}
else if (d->channelCount == p.channelCount) { /* do nothing */ }
else return EncoderError::UnsupportedChannelMix;
// -- End Channel Mixing
auto maxFileSizeInBytes = std::numeric_limits<uint32_t>::max();
auto samplesSizeInBytes = (sampleDataSize * GetFormatBitsPerSample(p.targetFormat)) / 8;
// 64 arbitrary
if ((samplesSizeInBytes - 64) >= maxFileSizeInBytes)
{
return EncoderError::BufferTooBig;
}
// Don't support PC64 or PCDBL
if (GetFormatBitsPerSample(p.targetFormat) > 32)
{
return EncoderError::UnsupportedBitdepth;
}
std::ofstream fout(path.c_str(), std::ios::out | std::ios::binary);
if (!fout.is_open())
{
return EncoderError::FileIOError;
}
char * chunkSizeBuff = new char[4];
// Initial size (this is changed after we're done writing the file)
to_bytes(uint32_t(36), chunkSizeBuff);
// RIFF file header
fout.write(GenerateChunkCodeChar('R', 'I', 'F', 'F'), 4);
fout.write(chunkSizeBuff, 4);
fout.write(GenerateChunkCodeChar('W', 'A', 'V', 'E'), 4);
// Fmt header
auto header = MakeWaveHeader(p, d->sampleRate);
fout.write(reinterpret_cast<char*>(&header), sizeof(WaveChunkHeader));
auto sourceBits = GetFormatBitsPerSample(d->sourceFormat);
auto targetBits = GetFormatBitsPerSample(p.targetFormat);
//@todo - channel mixing!
// Write out fact chunk
if (p.targetFormat == PCM_FLT)
{
uint32_t four = 4;
uint32_t dataSz = int(sampleDataSize / p.channelCount);
fout.write(GenerateChunkCodeChar('f', 'a', 'c', 't'), 4);
fout.write(reinterpret_cast<const char *>(&four), 4);
fout.write(reinterpret_cast<const char *>(&dataSz), 4); // Number of samples (per channel)
}
// Data header
fout.write(GenerateChunkCodeChar('d', 'a', 't', 'a'), 4);
// + data chunk size
to_bytes(uint32_t(samplesSizeInBytes), chunkSizeBuff);
fout.write(chunkSizeBuff, 4);
if (targetBits <= sourceBits && p.targetFormat != PCM_FLT)
{
// At most need this number of bytes in our copy
std::vector<uint8_t> samplesCopy(samplesSizeInBytes);
ConvertFromFloat32(samplesCopy.data(), sampleData, sampleDataSize, p.targetFormat, p.dither);
fout.write(reinterpret_cast<const char*>(samplesCopy.data()), samplesSizeInBytes);
}
else
{
// Handle PCFLT. Coming in from AudioData ensures we start with 32 bits, so we're fine
// since we've also rejected formats with more than 32 bits above.
fout.write(reinterpret_cast<const char*>(sampleData), samplesSizeInBytes);
}
// Padding byte
if (isOdd(samplesSizeInBytes))
{
const char * zero = "";
fout.write(zero, 1);
}
// Find size
long totalSize = fout.tellp();
// Modify RIFF header
fout.seekp(4);
// Total size of the file, less 8 bytes for the RIFF header
to_bytes(uint32_t(totalSize - 8), chunkSizeBuff);
fout.write(chunkSizeBuff, 4);
delete[] chunkSizeBuff;
return EncoderError::NoError;
}
////////////////////////////
// Opus File Encoding //
////////////////////////////
#include "opus/opusfile/include/opusfile.h"
#include "ogg/ogg.h"
typedef std::pair<std::string, std::string> metadata_t;
class OggWriter
{
void write_to_ostream(bool flush)
{
while (ogg_stream_pageout(&oss, &page))
{
ostream->write(reinterpret_cast<char*>(page.header), static_cast<std::streamsize>(page.header_len));
ostream->write(reinterpret_cast<char*>(page.body), static_cast<std::streamsize>(page.body_len));
}
if (flush && ogg_stream_flush(&oss, &page))
{
ostream->write(reinterpret_cast<char*>(page.header), static_cast<std::streamsize>(page.header_len));
ostream->write(reinterpret_cast<char*>(page.body), static_cast<std::streamsize>(page.body_len));
}
}
std::vector<char> make_header(int channel_count, int preskip, long sample_rate, int gain)
{
std::vector<char> header;
std::array<char, 9> steam_count = { { 0x0, 0x1, 0x1, 0x2, 0x2, 0x3, 0x4, 0x5, 0x5 } };
std::array<char, 9> coupled_streacount = { { 0x0, 0x0, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2, 0x3 } };
std::array<char, 1> chan_map_1 = { { 0x0 } };
std::array<char, 2> chan_map_2 = { { 0x0, 0x1 } };
std::array<char, 9> _preamble = { { 'O', 'p', 'u', 's', 'H', 'e', 'a', 'd', 0x1 } };
std::array<char, 1> _channel_count;
std::array<char, 2> _preskip;
std::array<char, 4> _sample_rate;
std::array<char, 2> _gain;
std::array<char, 1> _channel_family = { { 0x1 } };
to_bytes(uint8_t(channel_count), _channel_count.data());
to_bytes(uint16_t(preskip), _preskip.data());
to_bytes(uint32_t(sample_rate), _sample_rate.data());
to_bytes(uint16_t(gain), _gain.data());
header.insert(header.end(), _preamble.cbegin(), _preamble.cend());
header.insert(header.end(), _channel_count.cbegin(), _channel_count.cend());
header.insert(header.end(), _preskip.cbegin(), _preskip.cend());
header.insert(header.end(), _sample_rate.cbegin(), _sample_rate.cend());
header.insert(header.end(), _gain.cbegin(), _gain.cend());
header.insert(header.end(), _channel_family.cbegin(), _channel_family.cend());
header.push_back(steam_count[channel_count]);
header.push_back(coupled_streacount[channel_count]);
switch (channel_count)
{
case 1: header.insert(header.end(), chan_map_1.cbegin(), chan_map_1.cend()); break;
case 2: header.insert(header.end(), chan_map_2.cbegin(), chan_map_2.cend()); break;
default: throw std::runtime_error("couldn't map channel data");
}
return header;
}
std::vector<char> make_tags(const std::string & vendor, const std::vector<metadata_t> & metadata)
{
std::vector<char> tags;
std::array<char, 8> _preamble = { { 'O', 'p', 'u', 's', 'T', 'a', 'g', 's' } };
std::array<char, 4> _vendor_length;
std::array<char, 4> _metadata_count;
to_bytes(uint32_t(vendor.size()), _vendor_length.data());
to_bytes(uint32_t(metadata.size()), _metadata_count.data());
tags.insert(tags.end(), _preamble.cbegin(), _preamble.cend());
tags.insert(tags.end(), _vendor_length.cbegin(), _vendor_length.cend());
tags.insert(tags.end(), vendor.cbegin(), vendor.cend());
tags.insert(tags.end(), _metadata_count.cbegin(), _metadata_count.cend());
// Process metadata.
for (const auto & metadata_entry : metadata)
{
std::array<char, 4> _metadata_entry_length;
std::string entry = metadata_entry.first + "=" + metadata_entry.second;
to_bytes(uint32_t(entry.size()), _metadata_entry_length.data());
tags.insert(tags.end(), _metadata_entry_length.cbegin(), _metadata_entry_length.cend());
tags.insert(tags.end(), entry.cbegin(), entry.cend());
}
return tags;
}
ogg_int64_t packet_number;
ogg_int64_t granule;
ogg_page page;
ogg_stream_state oss;
int channel_count;
long sample_rate;
int bits_per_sample;
std::ofstream * ostream;
std::string description;
std::vector<metadata_t> metadata;
public:
OggWriter(int channel_count, long sample_rate, int bits_per_sample, std::ofstream & stream, const std::vector<metadata_t> & md)
{
this->channel_count = channel_count;
this->sample_rate = sample_rate;
this->bits_per_sample = bits_per_sample;
this->ostream = &stream;
this->metadata = md;
int oggInitErr, packetErr;
ogg_packet header_packet;
ogg_packet tags_packet;
std::vector<char> header_vector;
std::vector<char> tags_vector;
description = "Ogg";
packet_number = 0;
granule = 0;
// Validate parameters
if (channel_count < 1 && channel_count > 255) throw std::runtime_error("Channel count must be between 1 and 255.");
// Initialize the Ogg stream.
oggInitErr = ogg_stream_init(&oss, 12345);
if (oggInitErr) throw std::runtime_error("Could not initialize the Ogg stream state.");
// Initialize the header packet.
header_vector = make_header(channel_count, 3840, sample_rate, 0);
header_packet.packet = reinterpret_cast<unsigned char*>(header_vector.data());
header_packet.bytes = header_vector.size();
header_packet.b_o_s = 1;
header_packet.e_o_s = 0;
header_packet.granulepos = 0;
header_packet.packetno = packet_number++;
// Initialize tags
tags_vector = make_tags("libnyquist", metadata);
tags_packet.packet = reinterpret_cast<unsigned char*>(tags_vector.data());
tags_packet.bytes = tags_vector.size();
tags_packet.b_o_s = 0;
tags_packet.e_o_s = 0;
tags_packet.granulepos = 0;
tags_packet.packetno = packet_number++;
// Write header page
packetErr = ogg_stream_packetin(&oss, &header_packet);
if (packetErr) throw std::runtime_error("Could not write header packet to the Ogg stream.");
write_to_ostream(true);
// Write tags page
packetErr = ogg_stream_packetin(&oss, &tags_packet);
if (packetErr) throw std::runtime_error("Could not write tags packet to the Ogg stream.");
write_to_ostream(true);
}
~OggWriter()
{
write_to_ostream(true);
ogg_stream_clear(&oss);
}
bool write(char * data, std::streamsize length, size_t sampleCount, bool end)
{
int err;
ogg_packet packet;
granule += sampleCount;
packet.packet = reinterpret_cast<unsigned char*>(data);
packet.bytes = static_cast<long>(length);
packet.b_o_s = 0;
packet.e_o_s = end ? 1 : 0;
packet.granulepos = granule;
packet.packetno = packet_number++;
err = ogg_stream_packetin(&oss, &packet);
if (err) throw std::runtime_error("could not write packet to stream");
write_to_ostream(false);
return true;
}
};
#define OPUS_MAX_PACKET_SIZE (1024 * 8)
#define OPUS_FRAME_SIZE 960
// Opus only supports a 48k samplerate...
// This encoder only supports mono for the time being
int nqr::encode_opus_to_disk(const EncoderParams p, const AudioData * d, const std::string & path)
{
assert(d->samples.size() > 0);
//assert(d->sampleRate == 48000);
float * sampleData = const_cast<float *>(d->samples.data());
const size_t sampleDataSize = d->samples.size();
int opus_error;
OpusEncoder * enc;
enc = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &opus_error);
if (!enc) throw std::runtime_error("opus_encoder_create caused an error!");
std::ofstream fout(path.c_str(), std::ios::out | std::ios::binary);
std::vector<metadata_t> oggMetadata = { { "artist", "dimitri" } };
OggWriter writer(d->channelCount, d->sampleRate, GetFormatBitsPerSample(d->sourceFormat), fout, oggMetadata);
std::vector<uint8_t> outBuffer(OPUS_MAX_PACKET_SIZE);
int framesToEncode = (sampleDataSize / OPUS_FRAME_SIZE) - 1; // fixme
while (framesToEncode >= 0)
{
auto encoded_size = opus_encode_float(enc, sampleData, OPUS_FRAME_SIZE, outBuffer.data(), OPUS_MAX_PACKET_SIZE);
if (encoded_size < 0)
{
std::cerr << "Bad Opus Status: " << encoded_size << std::endl;
return EncoderError::FileIOError;
}
writer.write((char*)outBuffer.data(), encoded_size, OPUS_FRAME_SIZE, (framesToEncode == 0) ? true : false);
framesToEncode--;
sampleData += OPUS_FRAME_SIZE;
}
fout.close();
opus_encoder_destroy(enc);
return EncoderError::NoError;
}
#undef OPUS_MAX_PACKET_SIZE

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,26 +23,27 @@ 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.
*/
#include "Decoders.h"
#include "FlacDecoder.h"
#include "flac/all.h"
#include "flac/stream_decoder.h"
// http://lists.xiph.org/pipermail/flac-dev/2012-March/003276.html
#define FLAC__NO_DLL
#include "FLAC/all.h"
#include "FLAC/stream_decoder.h"
#include <cstring>
#include "AudioDecoder.h"
using namespace nqr;
// FLAC is a big-endian format. All values are unsigned.
class FlacDecoderInternal
{
public:
FlacDecoderInternal(AudioData * d, const std::string & filepath) : d(d)
// N.B.: FLAC is a big-endian format. All values are unsigned.
FlacDecoderInternal(AudioData * d, std::string filepath) : d(d)
{
/////////////////////////////
// Initialize FLAC library //
/////////////////////////////
decoderInternal = FLAC__stream_decoder_new();
FLAC__stream_decoder_set_metadata_respond(decoderInternal, FLAC__METADATA_TYPE_STREAMINFO);
@ -56,49 +57,10 @@ public:
this) == FLAC__STREAM_DECODER_INIT_STATUS_OK;
FLAC__stream_decoder_set_md5_checking(decoderInternal, true);
if (initialized)
{
// Find the size and allocate memory
FLAC__stream_decoder_process_until_end_of_metadata(decoderInternal);
// Read memory out into our temporary internalBuffer
FLAC__stream_decoder_process_until_end_of_stream(decoderInternal);
// Presently unneeded, but useful for reference
// FLAC__ChannelAssignment channelAssignment = FLAC__stream_decoder_get_channel_assignment(decoderInternal);
// Fill out remaining user data
d->lengthSeconds = (float) numSamples / (float) d->sampleRate;
auto totalSamples = numSamples * d->channelCount;
// Next, process internal buffer into the user-visible samples array
ConvertToFloat32(d->samples.data(), internalBuffer.data(), totalSamples, d->sourceFormat);
}
else throw std::runtime_error("Unable to initialize FLAC decoder");
}
FlacDecoderInternal(AudioData * d, const std::vector<uint8_t> & memory) : d(d), data(std::move(memory)), dataPos(0)
{
decoderInternal = FLAC__stream_decoder_new();
FLAC__stream_decoder_set_metadata_respond(decoderInternal, FLAC__METADATA_TYPE_STREAMINFO);
bool initialized = FLAC__stream_decoder_init_stream(
decoderInternal,
read_callback,
seek_callback,
tell_callback,
length_callback,
eof_callback,
s_writeCallback,
s_metadataCallback,
s_errorCallback,
this
) == FLAC__STREAM_DECODER_INIT_STATUS_OK;
FLAC__stream_decoder_set_md5_checking(decoderInternal, true);
//////////////////////
// Read Stream Data //
/////////////////////
if (initialized)
{
@ -119,7 +81,12 @@ public:
// Next, process internal buffer into the user-visible samples array
ConvertToFloat32(d->samples.data(), internalBuffer.data(), totalSamples, d->sourceFormat);
}
else throw std::runtime_error("Unable to initialize FLAC decoder");
else
{
throw std::runtime_error("Unable to initialize FLAC decoder");
}
}
~FlacDecoderInternal()
@ -133,7 +100,7 @@ public:
void processMetadata(const FLAC__StreamMetadata_StreamInfo & info)
{
// Currently the reference encoder and decoders only support up to 24 bits per sample.
// N.B.: "Currently the reference encoder and decoders only support up to 24 bits per sample."
d->sampleRate = info.sample_rate;
d->channelCount = info.channels; // Assert 1 to 8
d->sourceFormat = MakeFormatForBits(info.bits_per_sample, false, true);
@ -148,20 +115,22 @@ public:
}
///////////////////////
// libflac callbacks //
// libflab callbacks //
///////////////////////
static FLAC__StreamDecoderWriteStatus s_writeCallback(const FLAC__StreamDecoder *, const FLAC__Frame* frame, const FLAC__int32 * const buffer[], void * userPtr)
static FLAC__StreamDecoderWriteStatus s_writeCallback(const FLAC__StreamDecoder*, const FLAC__Frame* frame, const FLAC__int32* const buffer[], void* userPtr)
{
FlacDecoderInternal * decoder = reinterpret_cast<FlacDecoderInternal *>(userPtr);
const size_t bytesPerSample = GetFormatBitsPerSample(decoder->d->sourceFormat) / 8;
auto dataPtr = decoder->internalBuffer.data();
for (uint32_t i = 0; i < frame->header.blocksize; i++)
for(unsigned int i = 0; i < frame->header.blocksize; i++)
{
for (int j = 0; j < decoder->d->channelCount; j++)
for(int j = 0; j < decoder->d->channelCount; j++)
{
std::memcpy(dataPtr + decoder->bufferPosition, &buffer[j][i], bytesPerSample);
memcpy(dataPtr + decoder->bufferPosition, &buffer[j][i], bytesPerSample);
decoder->bufferPosition += bytesPerSample;
}
}
@ -169,58 +138,14 @@ public:
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
static void s_metadataCallback (const FLAC__StreamDecoder *, const FLAC__StreamMetadata * metadata, void * userPtr)
static void s_metadataCallback (const FLAC__StreamDecoder*, const FLAC__StreamMetadata* metadata, void* userPtr)
{
static_cast<FlacDecoderInternal*>(userPtr)->processMetadata(metadata->data.stream_info);
}
static void s_errorCallback (const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus status, void *)
static void s_errorCallback (const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus status, void*)
{
throw std::runtime_error("FLAC decode exception " + std::string(FLAC__StreamDecoderErrorStatusString[status]));
}
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
{
FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data;
size_t readLength = std::min<size_t>(*bytes, decoderInternal->data.size() - decoderInternal->dataPos);
if (readLength > 0)
{
std::memcpy(buffer, decoderInternal->data.data(), readLength);
decoderInternal->dataPos += readLength;
*bytes = readLength;
if (decoderInternal->dataPos < decoderInternal->data.size()) return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
else return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
else return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
static FLAC__StreamDecoderSeekStatus seek_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
{
FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data;
size_t newPos = std::min<size_t>(absolute_byte_offset, decoderInternal->data.size() - decoderInternal->dataPos);
decoderInternal->dataPos = newPos;
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
}
static FLAC__StreamDecoderTellStatus tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
{
FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data;
*absolute_byte_offset = decoderInternal->dataPos;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
static FLAC__StreamDecoderLengthStatus length_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
{
FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data;
*stream_length = decoderInternal->data.size();
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
}
static FLAC__bool eof_callback(const FLAC__StreamDecoder *decoder, void *client_data)
{
FlacDecoderInternal *decoderInternal = (FlacDecoderInternal *)client_data;
return decoderInternal->dataPos == decoderInternal->data.size();
std::cerr << "FLAC Decoder Error: " << FLAC__StreamDecoderErrorStatusString[status] << std::endl;
}
private:
@ -228,8 +153,7 @@ private:
NO_COPY(FlacDecoderInternal);
FLAC__StreamDecoder * decoderInternal;
std::vector<uint8_t> data;
size_t dataPos;
size_t bufferPosition = 0;
size_t numSamples = 0;
@ -242,17 +166,18 @@ private:
// Public Interface //
//////////////////////
void FlacDecoder::LoadFromPath(AudioData * data, const std::string & path)
int FlacDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
FlacDecoderInternal decoder(data, path);
return IOError::NoError;
}
void FlacDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
int FlacDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
FlacDecoderInternal decoder(data, memory);
return IOError::LoadBufferNotImplemented;
}
std::vector<std::string> FlacDecoder::GetSupportedFileExtensions()
{
return {"flac"};
}
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -77,25 +77,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define HAVE_LROUND 1
#include "FLAC/all.h"
#include "flac/all.h"
#if defined(_WIN32) || defined(_WIN64)
#include "FLAC/src/win_utf8_io.c"
#if defined(_MSC_VER)
#include "flac/src/win_utf8_io.c"
#endif
#include "FLAC/src/bitmath.c"
#include "FLAC/src/bitreader.c"
#include "FLAC/src/bitwriter.c"
#include "FLAC/src/cpu.c"
#include "FLAC/src/crc.c"
#include "FLAC/src/fixed.c"
#include "FLAC/src/float.c"
#include "FLAC/src/format.c"
#include "FLAC/src/lpc.c"
#include "FLAC/src/md5.c"
#include "FLAC/src/memory.c"
#include "FLAC/src/stream_decoder.c"
#include "FLAC/src/window.c"
#include "flac/src/bitmath.c"
#include "flac/src/bitreader.c"
#include "flac/src/bitwriter.c"
#include "flac/src/cpu.c"
#include "flac/src/crc.c"
#include "flac/src/fixed.c"
#include "flac/src/float.c"
#include "flac/src/format.c"
#include "flac/src/lpc.c"
#include "flac/src/md5.c"
#include "flac/src/memory.c"
#include "flac/src/stream_decoder.c"
#include "flac/src/window.c"
#undef VERSION
@ -105,4 +105,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#if (_MSC_VER)
#pragma warning (pop)
#endif
#endif

@ -1,80 +0,0 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "Decoders.h"
using namespace nqr;
#include "mpc/mpcdec.h"
#include "mpc/reader.h"
#include "musepack/libmpcdec/decoder.h"
#include "musepack/libmpcdec/internal.h"
#define MINIMP3_FLOAT_OUTPUT
#define MINIMP3_IMPLEMENTATION
#include "minimp3/minimp3.h"
#include "minimp3/minimp3_ex.h"
#include <cstdlib>
#include <cstring>
void mp3_decode_internal(AudioData * d, const std::vector<uint8_t> & fileData)
{
mp3dec_t mp3d;
mp3dec_file_info_t info;
mp3dec_load_buf(&mp3d, (const uint8_t*)fileData.data(), fileData.size(), &info, 0, 0);
d->sampleRate = info.hz;
d->channelCount = info.channels;
d->sourceFormat = MakeFormatForBits(32, true, false);
d->lengthSeconds = ((float)info.samples / (float)d->channelCount) / (float)d->sampleRate;
if (info.samples == 0) throw std::runtime_error("mp3: could not read any data");
d->samples.resize(info.samples);
std::memcpy(d->samples.data(), info.buffer, sizeof(float) * info.samples);
std::free(info.buffer);
}
//////////////////////
// Public Interface //
//////////////////////
void Mp3Decoder::LoadFromPath(AudioData * data, const std::string & path)
{
auto fileBuffer = nqr::ReadFile(path);
mp3_decode_internal(data, fileBuffer.buffer);
}
void Mp3Decoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
mp3_decode_internal(data, memory);
}
std::vector<std::string> Mp3Decoder::GetSupportedFileExtensions()
{
return {"mp3"};
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,7 +23,7 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Decoders.h"
#include "MusepackDecoder.h"
using namespace nqr;
@ -50,7 +50,7 @@ class MusepackInternal
{
mpc_reader_state *p_mem = (mpc_reader_state*) p_reader->data;
if (p_mem->magic != STDIO_MAGIC) return MPC_STATUS_FAIL;
mpc_int32_t max = mpc_int32_t(p_mem->p_end - p_mem->p_file);
mpc_int32_t max = (p_mem->p_end - p_mem->p_file);
if (size >= max) size = max;
memcpy((unsigned char *)ptr, p_mem->p_file, size);
p_mem->p_file += size;
@ -72,14 +72,14 @@ class MusepackInternal
{
mpc_reader_state *p_mem = (mpc_reader_state*) p_reader->data;
if(p_mem->magic != STDIO_MAGIC) return MPC_STATUS_FAIL;
return mpc_int32_t(p_mem->p_file - p_mem->p_begin);
return p_mem->p_file - p_mem->p_begin;
}
static mpc_int32_t get_size_mem(mpc_reader *p_reader)
{
mpc_reader_state *p_mem = (mpc_reader_state*) p_reader->data;
if (p_mem->magic != STDIO_MAGIC) return MPC_STATUS_FAIL;
return mpc_int32_t(p_mem->p_end - p_mem->p_begin);
return p_mem->p_end - p_mem->p_begin;
}
static mpc_bool_t canseek_mem(mpc_reader *p_reader)
@ -94,7 +94,7 @@ public:
// Musepack is a purely variable bitrate format and does not work at a constant bitrate.
MusepackInternal(AudioData * d, const std::vector<uint8_t> & fileData) : d(d)
{
decoderMemory = std::make_shared<mpc_reader_state>();
decoderMemory.reset(new mpc_reader_state());
decoderMemory->magic = STDIO_MAGIC;
decoderMemory->p_file = (unsigned char *) fileData.data();
@ -110,17 +110,18 @@ public:
reader.tell = tell_mem;
mpcDemux = mpc_demux_init(&reader);
if (!mpcDemux) throw std::runtime_error("could not initialize mpc demuxer");
if (!mpcDemux)
throw std::runtime_error("could not initialize mpc demuxer");
mpc_demux_get_info(mpcDemux, &streamInfo);
d->sampleRate = (int) streamInfo.sample_freq;
d->sampleRate = (float) streamInfo.sample_freq;
d->channelCount = streamInfo.channels;
d->sourceFormat = MakeFormatForBits(32, true, false);
d->lengthSeconds = (double) mpc_streaminfo_get_length(&streamInfo);
auto totalSamples = size_t(mpc_streaminfo_get_length_samples(&streamInfo));
d->samples.reserve(totalSamples * d->channelCount + (MPC_DECODER_BUFFER_LENGTH / sizeof(MPC_SAMPLE_FORMAT))); // demux writes in chunks
d->samples.resize(totalSamples * d->channelCount);
if (!readInternal())
@ -129,29 +130,32 @@ public:
size_t readInternal()
{
mpc_status err = MPC_STATUS_OK;
mpc_status err;
size_t totalSamplesRead = 0;
while (true)
while(MPC_TRUE)
{
mpc_frame_info frame;
frame.buffer = d->samples.data() + totalSamplesRead;
err = mpc_demux_decode(mpcDemux, &frame);
if (frame.bits == -1 || err != MPC_STATUS_OK) break;
if (frame.bits == -1) break;
totalSamplesRead += (frame.samples * streamInfo.channels);
}
if (err != MPC_STATUS_OK)
std::cerr << "An internal error occured in mpc_demux_decode" << std::endl;
std::cerr << "Something went wrong... " << err << std::endl;
return totalSamplesRead;
}
~MusepackInternal()
{
if (mpcDemux) mpc_demux_exit(mpcDemux);
mpc_demux_exit(mpcDemux);
}
@ -162,7 +166,7 @@ private:
mpc_decoder decoder;
mpc_demux * mpcDemux;
std::shared_ptr<mpc_reader_state> decoderMemory;
std::unique_ptr<mpc_reader_state> decoderMemory;
NO_MOVE(MusepackInternal);
@ -174,18 +178,20 @@ private:
// Public Interface //
//////////////////////
void MusepackDecoder::LoadFromPath(AudioData * data, const std::string & path)
int MusepackDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
auto fileBuffer = nqr::ReadFile(path);
MusepackInternal decoder(data, fileBuffer.buffer);
return IOError::NoError;
}
void MusepackDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
int MusepackDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
MusepackInternal decoder(data, memory);
return IOError::NoError;
}
std::vector<std::string> MusepackDecoder::GetSupportedFileExtensions()
{
return {"mpc", "mpp"};
}
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -36,14 +36,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#include "musepack/libmpcdec/huffman.c"
//#include "musepack/libmpcdec/mpc_decoder.c"
//#include "musepack/libmpcdec/mpc_reader.c"
//#include "musepack/libmpcdec/mpc_bits_reader.c"
//#include "musepack/libmpcdec/mpc_demux.c"
#include "musepack/libmpcdec/requant.c"
#include "musepack/libmpcdec/streaminfo.c"
#include "musepack/libmpcdec/synth_filter.c"
#include "musepack/libmpcdec/crc32.c"
#include "musepack/libmpcdec/mpc_reader.c"
#include "musepack/libmpcdec/mpc_decoder.c"
#include "musepack/libmpcdec/mpc_demux.c"
#include "musepack/libmpcdec/mpc_bits_reader.c"
#ifdef __clang__
#pragma clang diagnostic pop

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,19 +23,13 @@ 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.
*/
#include "Decoders.h"
#include "OpusDecoder.h"
#include "opus/opusfile/include/opusfile.h"
using namespace nqr;
static const int OPUS_SAMPLE_RATE = 48000;
// Opus is a general-purpose codec designed to replace Vorbis at some point. Primarily, it's a low
// delay format making it suitable for high-quality, real time streaming. It's not really
// an archival format or something designed for heavy DSP post-processing since
// it's fundamentally limited to encode/decode at 48khz.
// https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/index.html
class OpusDecoderInternal
{
@ -166,18 +160,20 @@ private:
// Public Interface //
//////////////////////
void nqr::OpusDecoder::LoadFromPath(AudioData * data, const std::string & path)
int nqr::OpusDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
auto fileBuffer = nqr::ReadFile(path);
OpusDecoderInternal decoder(data, fileBuffer.buffer);
return IOError::NoError;
}
void nqr::OpusDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
int nqr::OpusDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
OpusDecoderInternal decoder(data, memory);
return IOError::NoError;
}
std::vector<std::string> nqr::OpusDecoder::GetSupportedFileExtensions()
{
return {"opus"};
}
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -39,12 +39,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#undef HAVE_CONFIG_H
#define USE_ALLOCA 1
#define OPUS_BUILD 1
#define USE_ALLOCA 1
#define OPUS_BUILD 1
/* Enable SSE functions, if compiled with SSE/SSE2 (note that AMD64 implies SSE2) */
#if defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1))
#define __SSE__ 1
#define __SSE__ 1
#endif
//////////
@ -92,9 +92,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "opus/celt/rate.c"
#include "opus/celt/vq.c"
//#define opus_custom_encoder_get_size opus_custom_encoder_get_size_alt
#include "opus/celt/celt_decoder.c"
#include "opus/celt/celt_encoder.c"
// Disabled inline because of name clash of opus_custom_encoder_get_size.
//#include "opus/celt/celt_decoder.c"
//#include "opus/celt/celt_encoder.c"
/*
See celt/celt_decoder.c + celt/celt_encoder.c in the project browser.
These files need to be in separate translation units due to name clashes,
unfortunately.
*/
/////////////////
// SILK Common //

@ -0,0 +1,66 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "RiffUtils.h"
using namespace nqr;
ChunkHeaderInfo nqr::ScanForChunk(const std::vector<uint8_t> & fileData, uint32_t chunkMarker)
{
// D[n] aligned to 16 bytes now
const uint16_t * d = reinterpret_cast<const uint16_t *>(fileData.data());
for (size_t i = 0; i < fileData.size() / sizeof(uint16_t); i++)
{
// This will be in machine endianess
uint32_t m = Pack(Read16(d[i]), Read16(d[i+1]));
if (m == chunkMarker)
{
uint32_t cSz = Pack(Read16(d[i+2]), Read16(d[i+3]));
return {(uint32_t (i * sizeof(uint16_t))), cSz}; // return i in bytes to the start of the data
}
else continue;
}
return {0, 0};
};
WaveChunkHeader nqr::MakeWaveHeader(const EncoderParams param, const int sampleRate)
{
WaveChunkHeader header;
int bitdepth = GetFormatBitsPerSample(param.targetFormat);
header.fmt_id = GenerateChunkCode('f', 'm', 't', ' ');
header.chunk_size = 16;
header.format = (param.targetFormat <= PCMFormat::PCM_32) ? WaveFormatCode::FORMAT_PCM : WaveFormatCode::FORMAT_IEEE;
header.channel_count = param.channelCount;
header.sample_rate = sampleRate;
header.data_rate = sampleRate * param.channelCount * (bitdepth / 8);
header.frame_size = param.channelCount * (bitdepth/ 8);
header.bit_depth = bitdepth;
return header;
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,44 +23,75 @@ 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.
*/
#include "Decoders.h"
#include "VorbisDecoder.h"
#include "libvorbis/include/vorbis/vorbisfile.h"
#include <string.h>
using namespace nqr;
//@todo: implement decoding from memory (c.f. http://stackoverflow.com/questions/13437422/libvorbis-audio-decode-from-memory-in-c)
class VorbisDecoderInternal
{
public:
VorbisDecoderInternal(AudioData * d, const std::vector<uint8_t> & memory) : d(d)
{
void * data = const_cast<uint8_t*>(memory.data());
ogg_file t;
t.curPtr = t.filePtr = static_cast<char*>(data);
t.fileSize = memory.size();
fileHandle = new OggVorbis_File;
memset(fileHandle, 0, sizeof(OggVorbis_File));
ov_callbacks callbacks;
callbacks.read_func = AR_readOgg;
callbacks.seek_func = AR_seekOgg;
callbacks.close_func = AR_closeOgg;
callbacks.tell_func = AR_tellOgg;
loadAudioData(&t, callbacks);
}
VorbisDecoderInternal(AudioData * d, std::string filepath) : d(d)
{
fileHandle = new OggVorbis_File();
/* @todo proper steaming support + classes
const ov_callbacks callbacks =
{
.read_func = s_readCallback,
.seek_func = s_seekCallback,
.tell_func = s_tellCallback,
.close_func = nullptr
};
*/
FILE * f = fopen(filepath.c_str(), "rb");
if (!f) throw std::runtime_error("Can't open file");
loadAudioData(f, OV_CALLBACKS_DEFAULT);
if (!f)
throw std::runtime_error("Can't open file");
if (auto r = ov_test_callbacks(f, fileHandle, nullptr, 0, OV_CALLBACKS_DEFAULT) != 0)
{
std::cerr << errorAsString(r) << std::endl;
throw std::runtime_error("File is not a valid ogg vorbis file");
}
if (auto r = ov_test_open(fileHandle) != 0)
{
std::cerr << errorAsString(r) << std::endl;
throw std::runtime_error("ov_test_open failed");
}
// N.B.: Don't need to fclose() after an open -- vorbis does this internally
vorbis_info *ovInfo = ov_info(fileHandle, -1);
if (ovInfo == nullptr)
{
throw std::runtime_error("Reading metadata failed");
}
if (auto r = ov_streams(fileHandle) != 1)
{
std::cerr << errorAsString(r) << std::endl;
throw std::runtime_error( "Unsupported: file contains multiple bitstreams");
}
d->sampleRate = int(ovInfo->rate);
d->channelCount = ovInfo->channels;
d->sourceFormat = MakeFormatForBits(32, true, false);
d->lengthSeconds = double(getLengthInSeconds());
d->frameSize = ovInfo->channels * GetFormatBitsPerSample(d->sourceFormat);
// Samples in a single channel
auto totalSamples = size_t(getTotalSamples());
d->samples.resize(totalSamples * d->channelCount);
if (!readInternal(totalSamples))
throw std::runtime_error("could not read any data");
}
~VorbisDecoderInternal()
@ -70,6 +101,7 @@ public:
size_t readInternal(size_t requestedFrameCount, size_t frameOffset = 0)
{
//@todo support offset
float **buffer = nullptr;
@ -81,12 +113,13 @@ public:
{
int64_t framesRead = ov_read_float(fileHandle, &buffer, std::min(2048, (int) framesRemaining), &bitstream);
// end of file
if(!framesRead) break;
// EOF
if(!framesRead)
break;
// Probably OV_HOLE, OV_EBADLINK, OV_EINVAL. @todo - log warning here.
if (framesRead < 0)
{
// Probably OV_HOLE, OV_EBADLINK, OV_EINVAL. Log warning here.
continue;
}
@ -98,6 +131,7 @@ public:
totalFramesRead++;
}
}
}
return totalFramesRead;
@ -133,13 +167,6 @@ public:
private:
struct ogg_file
{
char* curPtr;
char* filePtr;
size_t fileSize;
};
NO_COPY(VorbisDecoderInternal);
OggVorbis_File * fileHandle;
@ -149,111 +176,21 @@ private:
inline int64_t getLengthInSeconds() const { return int64_t(ov_time_total(const_cast<OggVorbis_File *>(fileHandle), -1)); }
inline int64_t getCurrentSample() const { return int64_t(ov_pcm_tell(const_cast<OggVorbis_File *>(fileHandle))); }
static size_t AR_readOgg(void* dst, size_t size1, size_t size2, void* fh)
{
ogg_file* of = reinterpret_cast<ogg_file*>(fh);
size_t len = size1 * size2;
if ( of->curPtr + len > of->filePtr + of->fileSize )
{
len = of->filePtr + of->fileSize - of->curPtr;
}
memcpy( dst, of->curPtr, len );
of->curPtr += len;
return len;
}
static int AR_seekOgg(void * fh, ogg_int64_t to, int type)
{
ogg_file * of = reinterpret_cast<ogg_file*>(fh);
switch (type)
{
case SEEK_CUR: of->curPtr += to; break;
case SEEK_END: of->curPtr = of->filePtr + of->fileSize - to; break;
case SEEK_SET: of->curPtr = of->filePtr + to; break;
default: return -1;
}
if (of->curPtr < of->filePtr)
{
of->curPtr = of->filePtr;
return -1;
}
if (of->curPtr > of->filePtr + of->fileSize)
{
of->curPtr = of->filePtr + of->fileSize;
return -1;
}
return 0;
}
static int AR_closeOgg(void * fh)
{
return 0;
}
static long AR_tellOgg(void * fh)
{
ogg_file * of = reinterpret_cast<ogg_file*>(fh);
return (of->curPtr - of->filePtr);
}
void loadAudioData(void *source, ov_callbacks callbacks)
{
if (auto r = ov_test_callbacks(source, fileHandle, nullptr, 0, callbacks) != 0)
{
std::cerr << errorAsString(r) << std::endl;
throw std::runtime_error("File is not a valid ogg vorbis file");
}
if (auto r = ov_test_open(fileHandle) != 0)
{
std::cerr << errorAsString(r) << std::endl;
throw std::runtime_error("ov_test_open failed");
}
// Don't need to fclose() after an open -- vorbis does this internally
vorbis_info * ovInfo = ov_info(fileHandle, -1);
if (ovInfo == nullptr) throw std::runtime_error("Reading metadata failed");
if (auto r = ov_streams(fileHandle) != 1)
{
std::cerr << errorAsString(r) << std::endl;
throw std::runtime_error( "Unsupported: file contains multiple bitstreams");
}
d->sampleRate = int(ovInfo->rate);
d->channelCount = ovInfo->channels;
d->sourceFormat = MakeFormatForBits(32, true, false);
d->lengthSeconds = double(getLengthInSeconds());
d->frameSize = ovInfo->channels * GetFormatBitsPerSample(d->sourceFormat);
// Samples in a single channel
auto totalSamples = size_t(getTotalSamples());
d->samples.resize(totalSamples * d->channelCount);
if (!readInternal(totalSamples)) throw std::runtime_error("could not read any data");
}
};
//////////////////////
// Public Interface //
//////////////////////
void VorbisDecoder::LoadFromPath(AudioData * data, const std::string & path)
int VorbisDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
VorbisDecoderInternal decoder(data, path);
return IOError::NoError;
}
void VorbisDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
int VorbisDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
VorbisDecoderInternal decoder(data, memory);
return IOError::LoadBufferNotImplemented;
}
std::vector<std::string> VorbisDecoder::GetSupportedFileExtensions()

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos 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,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,127 +23,23 @@ 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.
*/
#include "Decoders.h"
#include <cstring>
#include "WavDecoder.h"
#include "RiffUtils.h"
#include "IMA4Util.h"
using namespace nqr;
struct ADPCMState
{
int frame_size;
int firstDataBlockByte;
int dataSize;
int currentByte;
const uint8_t * inBuffer;
};
static const int ima_index_table[16] =
{
-1, -1, -1, -1, // +0 / +3 : - the step
2, 4, 6, 8, // +4 / +7 : + the step
-1, -1, -1, -1, // -0 / -3 : - the step
2, 4, 6, 8, // -4 / -7 : + the step
};
static inline int ima_clamp_index(int index)
{
if (index < 0) return 0;
else if (index > 88) return 88;
return index;
}
static inline int16_t ima_clamp_predict(int16_t predict)
{
if (predict < -32768) return -32768;
else if (predict > 32767) return 32767;
return predict;
}
static const int ima_step_table[89] =
{
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34,
37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494,
544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552,
1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026,
4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623,
27086, 29794, 32767
};
// Decodes an IMA ADPCM nibble to a 16 bit pcm sample
static inline int16_t decode_nibble(uint8_t nibble, int16_t & p, int & s)
{
// Compute a delta to add to the predictor value
int diff = ima_step_table[s] >> 3;
if (nibble & 4) diff += ima_step_table[s];
if (nibble & 2) diff += ima_step_table[s] >> 1;
if (nibble & 1) diff += ima_step_table[s] >> 2;
// Sign
if (nibble & 8) diff = -diff;
// Add delta
p += diff;
s += ima_index_table[nibble];
s = ima_clamp_index(s);
return ima_clamp_predict(p);
}
void decode_ima_adpcm(ADPCMState & state, int16_t * outBuffer, uint32_t num_channels)
{
const uint8_t * data = state.inBuffer;
// Loop over the interleaved channels
for (uint32_t ch = 0; ch < num_channels; ch++)
{
const int byteOffset = ch * 4;
// Header Structure:
// Byte0: packed low byte of the initial predictor
// Byte1: packed high byte of the initial predictor
// Byte2: initial step index
// Byte3: Reserved empty value
int16_t predictor = ((int16_t)data[byteOffset + 1] << 8) | data[byteOffset];
int stepIndex = data[byteOffset + 2];
uint8_t reserved = data[byteOffset + 3];
if (reserved != 0) throw std::runtime_error("adpcm decode error");
int byteIdx = num_channels * 4 + byteOffset; //the byte index of the first data word for this channel
int idx = ch;
// Decode nibbles of the remaining data
while (byteIdx < state.frame_size)
{
for (int j = 0; j < 4; j++)
{
outBuffer[idx] = decode_nibble(data[byteIdx] & 0xf, predictor, stepIndex); // low nibble
idx += num_channels;
outBuffer[idx] = decode_nibble(data[byteIdx] >> 4, predictor, stepIndex); // high nibble
idx += num_channels;
byteIdx++;
}
byteIdx += (num_channels - 1) << 2; // Jump to the next data word for the current channel
}
}
}
//////////////////////
// Public Interface //
//////////////////////
void WavDecoder::LoadFromPath(AudioData * data, const std::string & path)
int WavDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
auto fileBuffer = nqr::ReadFile(path);
return LoadFromBuffer(data, fileBuffer.buffer);
}
void WavDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
int WavDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
//////////////////////
// Read RIFF Header //
@ -214,13 +110,16 @@ void WavDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & m
case 64: data->sourceFormat = (wavHeader.format == WaveFormatCode::FORMAT_IEEE) ? PCMFormat::PCM_DBL : PCMFormat::PCM_64; break;
}
//std::cout << wavHeader << std::endl;
std::cout << wavHeader << std::endl;
bool scanForFact = false;
bool grabExtensibleData = false;
bool adpcmEncoded = false;
if (wavHeader.format == WaveFormatCode::FORMAT_IEEE)
if (wavHeader.format == WaveFormatCode::FORMAT_PCM)
{
}
else if (wavHeader.format == WaveFormatCode::FORMAT_IEEE)
{
scanForFact = true;
}
@ -231,7 +130,8 @@ void WavDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & m
}
else if (wavHeader.format == WaveFormatCode::FORMAT_EXT)
{
// Used when (1) PCM data has more than 16 bits; (2) channels > 2; (3) bits/sample !== container size; (4) channel/speaker mapping specified;
// Used when (1) PCM data has more than 16 bits; (2) channels > 2; (3) bits/sample !== container size; (4) channel/speaker mapping specified
//std::cout << "[format id] extended" << std::endl;
scanForFact = true;
grabExtensibleData = true;
}
@ -294,17 +194,19 @@ void WavDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & m
s.currentByte = 0;
s.inBuffer = const_cast<uint8_t*>(memory.data() + DataChunkInfo.offset);
size_t totalSamples = (factChunk.sample_length * wavHeader.channel_count); // Samples per channel times channel count
std::vector<int16_t> adpcm_pcm16(totalSamples * 2, 0); // Each frame decodes into twice as many pcm samples
// An encoded sample is 4 bits that expands to 16
size_t totalSamples = factChunk.sample_length * 4;
std::vector<int16_t> adpcm_pcm16(totalSamples, 0);
uint32_t frameOffset = 0;
uint32_t frameCount = DataChunkInfo.size / s.frame_size;
for (uint32_t i = 0; i < frameCount; ++i)
unsigned numFrames = DataChunkInfo.size / s.frame_size;
for (int i = 0; i < numFrames; ++i)
{
decode_ima_adpcm(s, adpcm_pcm16.data() + frameOffset, wavHeader.channel_count);
s.inBuffer += s.frame_size;
frameOffset += (s.frame_size * 2) - (8 * wavHeader.channel_count);
frameOffset += (wavHeader.channel_count * s.frame_size);
}
data->lengthSeconds = ((float) totalSamples / (float) wavHeader.sample_rate) / wavHeader.channel_count;
@ -318,6 +220,8 @@ void WavDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & m
data->samples.resize(totalSamples);
ConvertToFloat32(data->samples.data(), memory.data() + DataChunkInfo.offset, totalSamples, data->sourceFormat);
}
return IOError::NoError;
}
std::vector<std::string> WavDecoder::GetSupportedFileExtensions()

@ -0,0 +1,189 @@
/*
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
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.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*/
#include "WavEncoder.h"
#include <fstream>
using namespace nqr;
inline void toBytes(int value, char * arr)
{
arr[0] = (value) & 0xFF;
arr[1] = (value >> 8) & 0xFF;
arr[2] = (value >> 16) & 0xFF;
arr[3] = (value >> 24) & 0xFF;
}
int WavEncoder::WriteFile(const EncoderParams p, const AudioData * d, const std::string & path)
{
// Cast away const because we know what we are doing (Hopefully?)
float * sampleData = const_cast<float *>(d->samples.data());
size_t sampleDataSize = d->samples.size();
std::vector<float> sampleDataOptionalMix;
if (sampleDataSize <= 32)
{
return EncoderError::InsufficientSampleData;
}
if (d->channelCount < 1 || d->channelCount > 8)
{
return EncoderError::UnsupportedChannelConfiguration;
}
// Handle Channel Mixing --
// Mono => Stereo
if (d->channelCount == 1 && p.channelCount == 2)
{
sampleDataOptionalMix.resize(sampleDataSize * 2);
MonoToStereo(sampleData, sampleDataOptionalMix.data(), sampleDataSize); // Mix
// Re-point data
sampleData = sampleDataOptionalMix.data();
sampleDataSize = sampleDataOptionalMix.size();
}
// Stereo => Mono
else if (d->channelCount == 2 && p.channelCount == 1)
{
sampleDataOptionalMix.resize(sampleDataSize / 2);
StereoToMono(sampleData, sampleDataOptionalMix.data(), sampleDataSize); // Mix
// Re-point data
sampleData = sampleDataOptionalMix.data();
sampleDataSize = sampleDataOptionalMix.size();
}
else if (d->channelCount == p.channelCount)
{
// No op
}
else
{
return EncoderError::UnsupportedChannelMix;
}
// -- End Channel Mixing
auto maxFileSizeInBytes = std::numeric_limits<uint32_t>::max();
auto samplesSizeInBytes = (sampleDataSize * GetFormatBitsPerSample(p.targetFormat)) / 8;
// 64 arbitrary
if ((samplesSizeInBytes - 64) >= maxFileSizeInBytes)
{
return EncoderError::BufferTooBig;
}
// Don't support PCM_64 or PCM_DBL
if (GetFormatBitsPerSample(p.targetFormat) > 32)
{
return EncoderError::UnsupportedBitdepth;
}
std::ofstream fout(path.c_str(), std::ios::out | std::ios::binary);
if (!fout.is_open())
{
return EncoderError::FileIOError;
}
char * chunkSizeBuff = new char[4];
// Initial size (this is changed after we're done writing the file)
toBytes(36, chunkSizeBuff);
// RIFF file header
fout.write(GenerateChunkCodeChar('R', 'I', 'F', 'F'), 4);
fout.write(chunkSizeBuff, 4);
fout.write(GenerateChunkCodeChar('W', 'A', 'V', 'E'), 4);
// Fmt header
auto header = MakeWaveHeader(p, d->sampleRate);
fout.write(reinterpret_cast<char*>(&header), sizeof(WaveChunkHeader));
auto sourceBits = GetFormatBitsPerSample(d->sourceFormat);
auto targetBits = GetFormatBitsPerSample(p.targetFormat);
////////////////////////////
//@todo - channel mixing! //
////////////////////////////
// Write out fact chunk
if (p.targetFormat == PCM_FLT)
{
uint32_t four = 4;
uint32_t dataSz = int(sampleDataSize / p.channelCount);
fout.write(GenerateChunkCodeChar('f', 'a', 'c', 't'), 4);
fout.write(reinterpret_cast<const char *>(&four), 4);
fout.write(reinterpret_cast<const char *>(&dataSz), 4); // Number of samples (per channel)
}
// Data header
fout.write(GenerateChunkCodeChar('d', 'a', 't', 'a'), 4);
// + data chunk size
toBytes(int(samplesSizeInBytes), chunkSizeBuff);
fout.write(chunkSizeBuff, 4);
if (targetBits <= sourceBits && p.targetFormat != PCM_FLT)
{
// At most need this number of bytes in our copy
std::vector<uint8_t> samplesCopy(samplesSizeInBytes);
ConvertFromFloat32(samplesCopy.data(), sampleData, sampleDataSize, p.targetFormat, p.dither);
fout.write(reinterpret_cast<const char*>(samplesCopy.data()), samplesSizeInBytes);
}
else
{
// Handle PCM_FLT. Coming in from AudioData ensures we start with 32 bits, so we're fine
// since we've also rejected formats with more than 32 bits above.
fout.write(reinterpret_cast<const char*>(sampleData), samplesSizeInBytes);
}
// Padding byte
if (isOdd(samplesSizeInBytes))
{
const char * zero = "";
fout.write(zero, 1);
}
// Find size
long totalSize = fout.tellp();
// Modify RIFF header
fout.seekp(4);
// Total size of the file, less 8 bytes for the RIFF header
toBytes(int(totalSize - 8), chunkSizeBuff);
fout.write(chunkSizeBuff, 4);
delete[] chunkSizeBuff;
return EncoderError::NoError;
}

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.
Copyright (c) 2015, Dimitri Diakopoulos All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
@ -23,10 +23,8 @@ 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.
*/
#include "Decoders.h"
#include "WavPackDecoder.h"
#include "wavpack.h"
#include <string.h>
#include <cstring>
using namespace nqr;
@ -35,36 +33,50 @@ class WavPackInternal
public:
WavPackInternal(AudioData * d, const std::string & path) : d(d)
WavPackInternal(AudioData * d, const std::string path) : d(d)
{
char errorStr[128];
context = WavpackOpenFileInput(path.c_str(), errorStr, OPEN_WVC | OPEN_NORMALIZE, 0);
if (!context) throw std::runtime_error("Not a WavPack file");
auto totalSamples = size_t(WavpackGetNumSamples(context));
decode(totalSamples);
}
WavPackInternal(AudioData * d, const std::vector<uint8_t> & memory) : d(d)
{
char errorStr[128];
context = WavpackOpenRawDecoder((void *) memory.data(), memory.size(), nullptr, 0, 0, errorStr, OPEN_WVC | OPEN_NORMALIZE, 0);
// Since we are using OpenRawDecoder, WavpackGetNumSamples won't work.
// Instead, find the first block and get totalSamples from its header.
WavpackHeader wph;
auto headerOffset = readNextHeader(memory, &wph, 0);
if (!context || headerOffset == -1)
if (!context)
{
throw std::runtime_error("Not a WavPack file");
}
auto bitdepth = WavpackGetBitsPerSample(context);
d->sampleRate = WavpackGetSampleRate(context);
d->channelCount = WavpackGetNumChannels(context);
d->lengthSeconds = double(getLengthInSeconds());
d->frameSize = d->channelCount * bitdepth;
//@todo support channel masks
// WavpackGetChannelMask
auto totalSamples = size_t(getTotalSamples());
int mode = WavpackGetMode(context);
bool isFloatingPoint = (MODE_FLOAT & mode);
d->sourceFormat = MakeFormatForBits(bitdepth, isFloatingPoint, false);
auto totalSamples = wph.total_samples;
decode(totalSamples);
/* From the docs:
"... required memory at "buffer" is 4 * samples * num_channels bytes. The
audio data is returned right-justified in 32-bit longs in the endian
mode native to the executing processor."
*/
d->samples.resize(totalSamples * d->channelCount);
if (!isFloatingPoint)
internalBuffer.resize(totalSamples * d->channelCount);
if (!readInternal(totalSamples))
throw std::runtime_error("could not read any data");
// Next, process internal buffer into the user-visible samples array
if (!isFloatingPoint)
ConvertToFloat32(d->samples.data(), internalBuffer.data(), totalSamples * d->channelCount, d->sourceFormat);
}
~WavPackInternal()
@ -77,6 +89,8 @@ public:
size_t framesRemaining = requestedFrameCount;
size_t totalFramesRead = 0;
// int frameSize = d->channelCount * WavpackGetBitsPerSample(context);
// The samples returned are handled differently based on the file's mode
int mode = WavpackGetMode(context);
@ -97,69 +111,17 @@ public:
}
// EOF
//if (framesRead == 0) break;
//if (framesRead == 0)
// break;
totalFramesRead += framesRead;
framesRemaining -= framesRead;
}
return totalFramesRead;
}
private:
void decode(size_t totalSamples) {
auto bitdepth = WavpackGetBitsPerSample(context);
d->sampleRate = WavpackGetSampleRate(context);
d->channelCount = WavpackGetNumChannels(context);
d->lengthSeconds = double(totalSamples / WavpackGetSampleRate(context));
d->frameSize = d->channelCount * bitdepth;
//@todo support channel masks
// WavpackGetChannelMask
int mode = WavpackGetMode(context);
bool isFloatingPoint = (MODE_FLOAT & mode);
d->sourceFormat = MakeFormatForBits(bitdepth, isFloatingPoint, false);
d->samples.resize(totalSamples * d->channelCount);
if (!isFloatingPoint)
internalBuffer.resize(totalSamples * d->channelCount);
if (!readInternal(totalSamples))
throw std::runtime_error("could not read any data");
// Next, process internal buffer into the user-visible samples array
if (!isFloatingPoint)
ConvertToFloat32(d->samples.data(), internalBuffer.data(), totalSamples * d->channelCount, d->sourceFormat);
}
int64_t readNextHeader(const std::vector<uint8_t> & memory, WavpackHeader *wphdr, size_t startOffset) {
/// Based on read_next_header function in wavpack's openutils.c.
/// This will find the position of the next WavPack header in the given vector, at or after startOffset.
/// If a header is found, it will write the header to *wphdr and return the position of its first byte in the vector.
/// Otherwise, it will return -1.
unsigned char* sp;
for (size_t i = startOffset; i < memory.size(); i++) {
sp = const_cast<unsigned char *>(memory.data() + i);
auto headerStartPoint = sp;
if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
!(*++sp & 1) && sp [2] < 16 && !sp [3] && (sp [2] || sp [1] || *sp >= 24) && sp [5] == 4 &&
sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff) && sp [18] < 3 && !sp [19]) {
memcpy (wphdr, headerStartPoint, sizeof (*wphdr));
WavpackLittleEndianToNative (wphdr, (char*)WavpackHeaderFormat);
return i;
}
}
return -1;
}
NO_MOVE(WavPackInternal);
@ -168,7 +130,7 @@ private:
WavpackContext * context; //@todo unique_ptr
AudioData * d;
std::vector<int32_t> internalBuffer;
inline int64_t getTotalSamples() const { return WavpackGetNumSamples(context); }
@ -180,14 +142,15 @@ private:
// Public Interface //
//////////////////////
void WavPackDecoder::LoadFromPath(AudioData * data, const std::string & path)
int WavPackDecoder::LoadFromPath(AudioData * data, const std::string & path)
{
WavPackInternal decoder(data, path);
return IOError::NoError;
}
void WavPackDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
int WavPackDecoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
WavPackInternal decoder(data, memory);
return IOError::LoadBufferNotImplemented;
}
std::vector<std::string> WavPackDecoder::GetSupportedFileExtensions()

Binary file not shown.

Binary file not shown.

@ -1,43 +0,0 @@
QUEST STUDIOS
SOFTWARE SOUNDTRACK SERIES
====================================================
THE SECRET OF MONKEY ISLAND
"INTRODUCTION/OPENING THEMES"
Michael Z. Land
====================================================
Copyright (c)1989 LucasArts Entertainment Co.
====================================================
G E N E R A L M I D I V E R S I O N
System Requirements:
- MIDI Playback Software capable of reading Type 1 Standard
MIDI File format
- General MIDI sound device (Wave Table recommended.)
This Standard MIDI File was recorded directly from LucasFilm Game's
"The Secret of Monkey Island" adventure game. It has been converted
from the MT-32 version for playback on General MIDI sound cards. A
Wave Table sound card is highly recommended for optimal playback.
Recorded/Converted to Standard MIDI File format by Tom Lewandowski.
Address questions or comments to:
QUEST STUDIOS
Tom Lewandowski
tom+di@netnet.net
THE ROLAND MT-32 SOUND MODULE RESOURCE CENTER
THE SIERRA SOUNDTRACK SERIES/SOFTWARE SOUNDTRACK SERIES
http://bayland.net/~tom+di/sierra/roland.html

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save