aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2024-01-05 17:50:19 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2024-01-05 17:50:19 +0100
commit571316f329948dc464cc2be37b210f0b3e7816f7 (patch)
tree8396262af9d84f5a0490af9805cde11cf5fc9eed
parente778887e4e5589528b06b04404ce4c71aaae267a (diff)
parent716f4394641d53f0d79c9ddac3fa93b03a49f278 (diff)
downloadfdk-aac-dabplus2.tar.gz
fdk-aac-dabplus2.tar.bz2
fdk-aac-dabplus2.zip
Merge fdk-aac 'v2.0.3' into dabplus2dabplus2
-rw-r--r--.github/workflows/ci.yml215
-rw-r--r--.gitignore2
-rw-r--r--Android.bp2
-rw-r--r--CMakeLists.txt20
-rw-r--r--ChangeLog5
-rw-r--r--METADATA4
-rw-r--r--Makefile.am7
-rw-r--r--aac-enc.c2
-rw-r--r--configure.ac4
-rw-r--r--documentation/aacDecoder.pdfbin490978 -> 492288 bytes
-rw-r--r--documentation/aacEncoder.pdfbin443728 -> 443831 bytes
-rw-r--r--fuzzer/Android.bp8
-rw-r--r--fuzzer/aac_dec_fuzzer.cpp3
-rw-r--r--libAACdec/include/aacdecoder_lib.h5
-rw-r--r--libAACdec/src/aac_ram.cpp4
-rw-r--r--libAACdec/src/aac_ram.h4
-rw-r--r--libAACdec/src/aacdec_drc.cpp23
-rw-r--r--libAACdec/src/aacdec_drc.h7
-rw-r--r--libAACdec/src/aacdec_drc_types.h7
-rw-r--r--libAACdec/src/aacdec_hcrs.cpp4
-rw-r--r--libAACdec/src/aacdecoder.cpp352
-rw-r--r--libAACdec/src/aacdecoder.h18
-rw-r--r--libAACdec/src/aacdecoder_lib.cpp333
-rw-r--r--libAACdec/src/channel.cpp6
-rw-r--r--libAACdec/src/rvlc.cpp15
-rw-r--r--libAACdec/src/usacdec_acelp.cpp4
-rw-r--r--libAACenc/include/aacenc_lib.h6
-rw-r--r--libAACenc/src/aacenc_lib.cpp24
-rw-r--r--libDRCdec/src/drcDec_reader.cpp13
-rw-r--r--libFDK/include/FDK_archdef.h10
-rw-r--r--libFDK/include/fft.h4
-rw-r--r--libFDK/include/nlc_dec.h5
-rw-r--r--libFDK/src/FDK_hybrid.cpp26
-rw-r--r--libFDK/src/autocorr2nd.cpp43
-rw-r--r--libFDK/src/dct.cpp28
-rw-r--r--libFDK/src/fft.cpp6
-rw-r--r--libFDK/src/nlc_dec.cpp28
-rw-r--r--libMpegTPDec/include/tp_data.h4
-rw-r--r--libMpegTPDec/src/tpdec_asc.cpp243
-rw-r--r--libMpegTPDec/src/tpdec_latm.cpp41
-rw-r--r--libMpegTPDec/src/tpdec_latm.h4
-rw-r--r--libMpegTPDec/src/tpdec_lib.cpp8
-rw-r--r--libMpegTPEnc/include/tp_data.h4
-rw-r--r--libMpegTPEnc/src/tpenc_asc.cpp6
-rw-r--r--libPCMutils/src/limiter.cpp5
-rw-r--r--libPCMutils/src/pcmdmx_lib.cpp58
-rw-r--r--libSACdec/include/sac_dec_lib.h6
-rw-r--r--libSACdec/src/sac_bitdec.cpp18
-rw-r--r--libSACdec/src/sac_dec.cpp75
-rw-r--r--libSACdec/src/sac_dec_lib.cpp21
-rw-r--r--libSACdec/src/sac_process.cpp20
-rw-r--r--libSACdec/src/sac_reshapeBBEnv.cpp77
-rw-r--r--libSACdec/src/sac_stp.cpp32
-rw-r--r--libSBRdec/src/arm/lpp_tran_arm.cpp159
-rw-r--r--libSBRdec/src/env_calc.cpp48
-rw-r--r--libSBRdec/src/hbe.cpp51
-rw-r--r--libSBRdec/src/lpp_tran.cpp112
-rw-r--r--libSBRdec/src/lpp_tran.h4
-rw-r--r--libSBRdec/src/sbr_dec.cpp24
-rw-r--r--libSBRdec/src/sbrdec_drc.cpp53
-rw-r--r--libSBRdec/src/sbrdec_freq_sca.cpp16
-rw-r--r--libSBRdec/src/sbrdecoder.cpp16
-rw-r--r--libSBRenc/src/env_est.cpp26
-rw-r--r--libSBRenc/src/sbr_encoder.cpp5
-rw-r--r--sha1.c399
-rw-r--r--sha1.h85
-rw-r--r--test-encode-decode.c383
-rw-r--r--test/ref-mono.txt2
-rw-r--r--test/ref-stereo.txt2
-rwxr-xr-xtest/run-test.sh28
70 files changed, 2355 insertions, 927 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..c6ba3ea
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,215 @@
+name: CI
+on: [push, pull_request]
+
+jobs:
+ linux-autotools:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ ./autogen.sh
+ ./configure --enable-example
+ make -j$(nproc) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror"
+ - name: Run tests
+ run: |
+ sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg
+ ./test/run-test.sh
+
+ linux-cmake:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror -Wno-stringop-overflow"
+ cmake --build build
+ - name: Run tests
+ run: |
+ sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg
+ cd build
+ ../test/run-test.sh
+
+ linux-sanitizers-gcc-autotools:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ ./autogen.sh
+ FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize=shift-base -DDEBUG -fno-sanitize-recover=all"
+ CC="gcc $FLAGS" CXX="g++ $FLAGS" ./configure --enable-example
+ make -j$(nproc)
+ - name: Run tests
+ run: |
+ sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg
+ ./test/run-test.sh
+
+ linux-sanitizers-clang-cmake:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize=shift-base -DDEBUG -fno-sanitize-recover=all -fno-sanitize=vptr -fno-sanitize=function"
+ cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_FLAGS="$FLAGS" -DCMAKE_CXX_FLAGS="$FLAGS"
+ cmake --build build
+ - name: Run tests
+ run: |
+ sudo apt-get update && sudo apt-get install --no-install-recommends ffmpeg
+ cd build
+ ../test/run-test.sh
+
+ macos-autotools:
+ runs-on: macos-latest
+ steps:
+ - name: Install autotools
+ run: |
+ brew install automake
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ ./autogen.sh
+ ./configure --enable-example
+ make -j$(sysctl -n hw.ncpu) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror -Wno-deprecated-declarations"
+
+ macos-cmake:
+ runs-on: macos-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror -Wno-deprecated-declarations"
+ cmake --build build
+
+ mingw-cross-autotools:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install cross compiler
+ run: |
+ sudo apt-get update && sudo apt-get install g++-mingw-w64-x86-64
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ ./autogen.sh
+ ./configure --enable-example --host=x86_64-w64-mingw32
+ make -j$(nproc) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror"
+
+ mingw-cross-cmake:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install cross compiler
+ run: |
+ sudo apt-get update && sudo apt-get install g++-mingw-w64-x86-64
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ cmake . -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ -DCMAKE_CROSSCOMPILING=TRUE -DCMAKE_SYSTEM_NAME=Windows -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror -Wno-stringop-overflow"
+ cmake --build build
+
+ msys-cmake:
+ runs-on: windows-latest
+ defaults:
+ run:
+ shell: msys2 {0}
+ steps:
+ - uses: msys2/setup-msys2@v2
+ with:
+ msystem: mingw64
+ update: true
+ install: >-
+ git
+ mingw-w64-x86_64-toolchain
+ mingw-w64-x86_64-cmake
+ mingw-w64-x86_64-ninja
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ cmake . -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES
+ cmake --build build
+
+ msvc-cmake:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ cmake . -B build -DBUILD_PROGRAMS=YES
+ cmake --build build --config Release
+
+ msvc-cmake-ninja-arm:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Set up the environment
+ uses: ilammy/msvc-dev-cmd@v1
+ with:
+ arch: amd64_arm
+ - name: Build
+ run: |
+ cmake . -G Ninja -B build -DCMAKE_BUILD_TYPE=Release -DBUILD_PROGRAMS=YES
+ cmake --build build
+
+ msvc-cmake-arm64:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build
+ run: |
+ cmake . -B build -DBUILD_PROGRAMS=YES -A ARM64
+ cmake --build build --config Release
+
+ llvm-mingw:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install llvm-mingw
+ run: |
+ wget https://github.com/mstorsjo/llvm-mingw/releases/download/20231003/llvm-mingw-20231003-ucrt-ubuntu-20.04-x86_64.tar.xz
+ tar -Jxvf llvm-mingw-*-ucrt-ubuntu-*-x86_64.tar.xz
+ rm llvm-mingw-*.tar.xz
+ sudo mv llvm-mingw-* /opt/llvm-mingw
+ echo /opt/llvm-mingw/bin >> $GITHUB_PATH
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build fdk-aac
+ run: |
+ ./autogen.sh
+ ./configure --host=aarch64-w64-mingw32 --enable-example
+ make -j$(nproc) CFLAGS="-g -O2 -Werror" CXXFLAGS="-g -O2 -Werror"
+
+ linux-ffmpeg:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ - name: Build fdk-aac
+ run: |
+ ./autogen.sh
+ mkdir build
+ cd build
+ ../configure --enable-example --prefix=$(pwd)/../prefix
+ make -j$(nproc)
+ make -j$(nproc) install
+ - name: Checkout FFmpeg
+ uses: actions/checkout@v4
+ with:
+ repository: ffmpeg/ffmpeg
+ path: ffmpeg
+ - name: Build FFmpeg
+ run: |
+ sudo apt-get update && sudo apt-get install -y nasm
+ cd ffmpeg
+ PKG_CONFIG_PATH=$(pwd)/../prefix/lib/pkgconfig ./configure --enable-libfdk-aac --enable-nonfree
+ make -j$(nproc)
diff --git a/.gitignore b/.gitignore
index da516d6..d193505 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
*.o
*.lo
*.la
+*~
.deps
.libs
.dirstamp
@@ -26,6 +27,7 @@ m4/lt~obsolete.m4
missing
stamp-h1
aac-enc
+test-encode-decode
compile
CMakeCache.txt
diff --git a/Android.bp b/Android.bp
index 0c67186..6060256 100644
--- a/Android.bp
+++ b/Android.bp
@@ -94,7 +94,7 @@ cc_library_static {
apex_available: [
"//apex_available:platform",
- "com.android.bluetooth.updatable",
+ "com.android.btservices",
"com.android.media.swcodec",
],
min_sdk_version: "29",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4db8c7e..03f46cc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,7 +43,7 @@ if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
-project(fdk-aac VERSION 2.0.2)
+project(fdk-aac VERSION 2.0.3)
# Includes
@@ -62,7 +62,7 @@ include(CPack)
# Options
option(BUILD_SHARED_LIBS "Build shared library" ON)
-option(BUILD_PROGRAMS "Build aac-enc utility" OFF)
+option(BUILD_PROGRAMS "Build extra utilities" OFF)
option(FDK_AAC_INSTALL_CMAKE_CONFIG_MODULE "Install CMake package configuration file" ON)
option(FDK_AAC_INSTALL_PKGCONFIG_MODULE "Install pkg-config .pc file" ON)
@@ -487,10 +487,11 @@ target_link_libraries(fdk-aac PRIVATE $<$<BOOL:${HAVE_LIBM}>:m>)
### Set public headers and shared library version. Version info is critical for Unix-like OSes.
set_target_properties(fdk-aac PROPERTIES
PUBLIC_HEADER "${fdk_aacinclude_HEADERS}"
- VERSION 2.0.2
+ VERSION 2.0.3
SOVERSION 2
MACHO_COMPATIBILITY_VERSION 3.0.0
- MACHO_CURRENT_VERSION 3.2.0)
+ MACHO_CURRENT_VERSION 3.3.0
+ LINKER_LANGUAGE C)
### Some compiler options from Makefile.am
if(MSVC)
@@ -585,4 +586,15 @@ if(BUILD_PROGRAMS)
## Program target installation
install(TARGETS aac-enc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+
+ ## Tool for testing the library
+ set(test_encode_decode_SOURCES
+ test-encode-decode.c
+ wavreader.c
+ wavreader.h
+ sha1.c
+ sha1.h)
+
+ add_executable(test-encode-decode ${test_encode_decode_SOURCES})
+ target_link_libraries(test-encode-decode PRIVATE fdk-aac)
endif()
diff --git a/ChangeLog b/ChangeLog
index c391bd9..3c542e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2.0.3
+ - Minor upstream updates
+ - Fixed one case of a failed assert in SBR encoding
+ - Added build support for s390x
+
2.0.2
- Minor upstream updates
- Lots of upstream and local fuzzing fixes
diff --git a/METADATA b/METADATA
index 5c12860..4dab5e4 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
+# CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+# DEPENDING ON IT IN YOUR PROJECT. ***
third_party {
+ license_note: "Software License for The Fraunhofer FDK AAC Codec Library for Android"
license_type: BY_EXCEPTION_ONLY
}
diff --git a/Makefile.am b/Makefile.am
index a3fdb00..292a6ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -40,10 +40,14 @@ libfdk_aac_la_LDFLAGS = -version-info @FDK_AAC_VERSION@ -no-undefined \
if EXAMPLE
bin_PROGRAMS = aac-enc$(EXEEXT)
+noinst_PROGRAMS = test-encode-decode$(EXEEXT)
aac_enc_LDADD = libfdk-aac.la
aac_enc_SOURCES = aac-enc.c wavreader.c
+test_encode_decode_LDADD = libfdk-aac.la
+test_encode_decode_SOURCES = test-encode-decode.c wavreader.c sha1.c
+
noinst_HEADERS = wavreader.h
endif
@@ -279,7 +283,6 @@ EXTRA_DIST = \
$(top_srcdir)/libSBRenc/src/*.h \
$(top_srcdir)/libSBRenc/include/*.h \
$(top_srcdir)/libSBRdec/src/*.h \
- $(top_srcdir)/libSBRdec/src/arm/*.cpp \
$(top_srcdir)/libSBRdec/include/*.h \
$(top_srcdir)/libSYS/include/*.h \
$(top_srcdir)/libPCMutils/include/*.h \
@@ -297,5 +300,7 @@ EXTRA_DIST = \
$(top_srcdir)/libFDK/src/mips/*.cpp \
$(top_srcdir)/METADATA \
$(top_srcdir)/PREUPLOAD.cfg \
+ $(top_srcdir)/sha1.h \
+ $(top_srcdir)/test/* \
$(top_srcdir)/win32/*.h
diff --git a/aac-enc.c b/aac-enc.c
index c90ff12..7f443f2 100644
--- a/aac-enc.c
+++ b/aac-enc.c
@@ -129,7 +129,7 @@ int main(int argc, char *argv[]) {
}
}
if (aacEncoder_SetParam(handle, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) {
- fprintf(stderr, "Unable to set the AOT\n");
+ fprintf(stderr, "Unable to set the sample rate\n");
return 1;
}
if (aacEncoder_SetParam(handle, AACENC_CHANNELMODE, mode) != AACENC_OK) {
diff --git a/configure.ac b/configure.ac
index c49fa3d..3b0957d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([fdk-aac], [2.0.2], [http://sourceforge.net/projects/opencore-amr/])
+AC_INIT([fdk-aac], [2.0.3], [http://sourceforge.net/projects/opencore-amr/])
AC_CONFIG_AUX_DIR(.)
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([tar-ustar foreign])
@@ -26,7 +26,7 @@ AC_SEARCH_LIBS([sin], [m])
dnl soname version to use
dnl goes by ‘current[:revision[:age]]’ with the soname ending up as
dnl current.age.revision
-FDK_AAC_VERSION=2:2:0
+FDK_AAC_VERSION=2:3:0
AS_IF([test x$enable_shared = xyes], [LIBS_PRIVATE=$LIBS], [LIBS_PUBLIC=$LIBS])
AC_SUBST(FDK_AAC_VERSION)
diff --git a/documentation/aacDecoder.pdf b/documentation/aacDecoder.pdf
index cc7cf41..3d4699e 100644
--- a/documentation/aacDecoder.pdf
+++ b/documentation/aacDecoder.pdf
Binary files differ
diff --git a/documentation/aacEncoder.pdf b/documentation/aacEncoder.pdf
index 77b8f4c..a47708a 100644
--- a/documentation/aacEncoder.pdf
+++ b/documentation/aacEncoder.pdf
Binary files differ
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
index 6739798..3ea7559 100644
--- a/fuzzer/Android.bp
+++ b/fuzzer/Android.bp
@@ -46,6 +46,14 @@ cc_defaults {
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libFraunhoferAAC",
+ vector: "remote",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/fuzzer/aac_dec_fuzzer.cpp b/fuzzer/aac_dec_fuzzer.cpp
index b5545fc..c970197 100644
--- a/fuzzer/aac_dec_fuzzer.cpp
+++ b/fuzzer/aac_dec_fuzzer.cpp
@@ -118,7 +118,8 @@ void Codec::decodeFrames(UCHAR *data, UINT size) {
INT_PCM outputBuf[kMaxOutBufferSize];
do {
mErrorCode =
- aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf, sizeof(outputBuf), 0);
+ aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf,
+ kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0);
} while (mErrorCode == AAC_DEC_OK);
UINT offset = inputSize - valid;
data += offset;
diff --git a/libAACdec/include/aacdecoder_lib.h b/libAACdec/include/aacdecoder_lib.h
index 06272df..02596b2 100644
--- a/libAACdec/include/aacdecoder_lib.h
+++ b/libAACdec/include/aacdecoder_lib.h
@@ -431,12 +431,11 @@ Where N equals to CStreamInfo::frameSize .
#include "machine_type.h"
#include "FDK_audio.h"
-#include "genericStds.h"
-
#define AACDECODER_LIB_VL0 3
#define AACDECODER_LIB_VL1 2
#define AACDECODER_LIB_VL2 0
+#include "genericStds.h"
/**
* \brief AAC decoder error codes.
*/
@@ -1037,7 +1036,7 @@ LINKSPEC_H AAC_DECODER_ERROR aacDecoder_Fill(HANDLE_AACDECODER self,
* \param self AAC decoder handle.
* \param pTimeData Pointer to external output buffer where the decoded PCM
* samples will be stored into.
- * \param timeDataSize Size of external output buffer.
+ * \param timeDataSize Size of external output buffer in PCM samples.
* \param flags Bit field with flags for the decoder: \n
* (flags & AACDEC_CONCEAL) == 1: Do concealment. \n
* (flags & AACDEC_FLUSH) == 2: Discard input data. Flush
diff --git a/libAACdec/src/aac_ram.cpp b/libAACdec/src/aac_ram.cpp
index aa8f6a6..fac1540 100644
--- a/libAACdec/src/aac_ram.cpp
+++ b/libAACdec/src/aac_ram.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -148,7 +148,7 @@ C_ALLOC_MEM(CplxPredictionData, CCplxPredictionData, 1)
/*! The buffer holds time samples for the crossfade in case of an USAC DASH IPF
config change Dimension: (8)
*/
-C_ALLOC_MEM2(TimeDataFlush, INT_PCM, TIME_DATA_FLUSH_SIZE, (8))
+C_ALLOC_MEM2(TimeDataFlush, PCM_DEC, TIME_DATA_FLUSH_SIZE, (8))
/* @} */
diff --git a/libAACdec/src/aac_ram.h b/libAACdec/src/aac_ram.h
index b9b95b7..395b2b2 100644
--- a/libAACdec/src/aac_ram.h
+++ b/libAACdec/src/aac_ram.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -132,7 +132,7 @@ H_ALLOC_MEM(CplxPredictionData, CCplxPredictionData)
H_ALLOC_MEM(SpectralCoeffs, FIXP_DBL)
H_ALLOC_MEM(SpecScale, SHORT)
-H_ALLOC_MEM(TimeDataFlush, INT_PCM)
+H_ALLOC_MEM(TimeDataFlush, PCM_DEC)
H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1)
H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL)
diff --git a/libAACdec/src/aacdec_drc.cpp b/libAACdec/src/aacdec_drc.cpp
index b6f5b49..abb9af7 100644
--- a/libAACdec/src/aacdec_drc.cpp
+++ b/libAACdec/src/aacdec_drc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -150,6 +150,19 @@ static INT convert_drcParam(FIXP_DBL param_dbl) {
}
/*!
+\brief Disable DRC
+
+\self Handle of DRC info
+
+\return none
+*/
+void aacDecoder_drcDisable(HANDLE_AAC_DRC self) {
+ self->enable = 0;
+ self->applyExtGain = 0;
+ self->progRefLevelPresent = 0;
+}
+
+/*!
\brief Reset DRC information
\self Handle of DRC info
@@ -204,7 +217,6 @@ void aacDecoder_drcInit(HANDLE_AAC_DRC self) {
self->progRefLevel = pParams->targetRefLevel;
self->progRefLevelPresent = 0;
self->presMode = -1;
- self->uniDrcPrecedence = 0;
aacDecoder_drcReset(self);
}
@@ -340,12 +352,6 @@ AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self,
self->numOutChannels = (INT)value;
self->update = 1;
break;
- case UNIDRC_PRECEDENCE:
- if (self == NULL) {
- return AAC_DEC_INVALID_HANDLE;
- }
- self->uniDrcPrecedence = (UCHAR)value;
- break;
default:
return AAC_DEC_SET_PARAM_FAIL;
} /* switch(param) */
@@ -1245,7 +1251,6 @@ static void aacDecoder_drcParameterHandling(HANDLE_AAC_DRC self,
/* switch on/off processing */
self->enable = ((p->boost > (FIXP_DBL)0) || (p->cut > (FIXP_DBL)0) ||
(p->applyHeavyCompression == ON) || (p->targetRefLevel >= 0));
- self->enable = (self->enable && !self->uniDrcPrecedence);
self->prevAacNumChannels = aacNumChannels;
self->update = 0;
diff --git a/libAACdec/src/aacdec_drc.h b/libAACdec/src/aacdec_drc.h
index 76a44d6..f2c1390 100644
--- a/libAACdec/src/aacdec_drc.h
+++ b/libAACdec/src/aacdec_drc.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -133,13 +133,14 @@ typedef enum {
APPLY_HEAVY_COMPRESSION,
DEFAULT_PRESENTATION_MODE,
ENCODER_TARGET_LEVEL,
- MAX_OUTPUT_CHANNELS,
- UNIDRC_PRECEDENCE
+ MAX_OUTPUT_CHANNELS
} AACDEC_DRC_PARAM;
/**
* \brief DRC module interface functions
*/
+void aacDecoder_drcDisable(HANDLE_AAC_DRC self);
+
void aacDecoder_drcReset(HANDLE_AAC_DRC self);
void aacDecoder_drcInit(HANDLE_AAC_DRC self);
diff --git a/libAACdec/src/aacdec_drc_types.h b/libAACdec/src/aacdec_drc_types.h
index d4393f7..c4c0794 100644
--- a/libAACdec/src/aacdec_drc_types.h
+++ b/libAACdec/src/aacdec_drc_types.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -207,11 +207,6 @@ typedef struct {
position in the bitstream (only one per frame) */
UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload
positions in the bitstream */
-
- UCHAR
- uniDrcPrecedence; /* Flag for signalling that uniDrc is active and takes
- precedence over legacy DRC */
-
UCHAR applyExtGain; /* Flag is 1 if extGain has to be applied, otherwise 0. */
FIXP_DBL additionalGainPrev; /* Gain of previous frame to be applied to the
diff --git a/libAACdec/src/aacdec_hcrs.cpp b/libAACdec/src/aacdec_hcrs.cpp
index 44b32a5..5e3f9ac 100644
--- a/libAACdec/src/aacdec_hcrs.cpp
+++ b/libAACdec/src/aacdec_hcrs.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -173,7 +173,9 @@ void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) {
pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT;
/* Process sets subsequently */
+ numSet = fMin(numSet, (UCHAR)MAX_HCR_SETS);
for (currentSet = 1; currentSet < numSet; currentSet++) {
+
/* step 1 */
numCodeword -=
*pNumSegment; /* number of remaining non PCWs [for all sets] */
diff --git a/libAACdec/src/aacdecoder.cpp b/libAACdec/src/aacdecoder.cpp
index 965631b..ad8ce0d 100644
--- a/libAACdec/src/aacdecoder.cpp
+++ b/libAACdec/src/aacdecoder.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -494,6 +494,75 @@ static AAC_DECODER_ERROR CDataStreamElement_Read(HANDLE_AACDECODER self,
return error;
}
+static INT findElementInstanceTag(
+ INT elementTag, MP4_ELEMENT_ID elementId,
+ CAacDecoderChannelInfo **pAacDecoderChannelInfo, INT nChannels,
+ MP4_ELEMENT_ID *pElementIdTab, INT nElements) {
+ int el, chCnt = 0;
+
+ for (el = 0; el < nElements; el++) {
+ switch (pElementIdTab[el]) {
+ case ID_CPE:
+ case ID_SCE:
+ case ID_LFE:
+ if ((elementTag == pAacDecoderChannelInfo[chCnt]->ElementInstanceTag) &&
+ (elementId == pElementIdTab[el])) {
+ return 1; /* element instance tag found */
+ }
+ chCnt += (pElementIdTab[el] == ID_CPE) ? 2 : 1;
+ break;
+ default:
+ break;
+ }
+ if (chCnt >= nChannels) break;
+ if (pElementIdTab[el] == ID_END) break;
+ }
+
+ return 0; /* element instance tag not found */
+}
+
+static INT validateElementInstanceTags(
+ CProgramConfig *pce, CAacDecoderChannelInfo **pAacDecoderChannelInfo,
+ INT nChannels, MP4_ELEMENT_ID *pElementIdTab, INT nElements) {
+ if (nChannels >= pce->NumChannels) {
+ for (int el = 0; el < pce->NumFrontChannelElements; el++) {
+ if (!findElementInstanceTag(pce->FrontElementTagSelect[el],
+ pce->FrontElementIsCpe[el] ? ID_CPE : ID_SCE,
+ pAacDecoderChannelInfo, nChannels,
+ pElementIdTab, nElements)) {
+ return 0; /* element instance tag not in raw_data_block() */
+ }
+ }
+ for (int el = 0; el < pce->NumSideChannelElements; el++) {
+ if (!findElementInstanceTag(pce->SideElementTagSelect[el],
+ pce->SideElementIsCpe[el] ? ID_CPE : ID_SCE,
+ pAacDecoderChannelInfo, nChannels,
+ pElementIdTab, nElements)) {
+ return 0; /* element instance tag not in raw_data_block() */
+ }
+ }
+ for (int el = 0; el < pce->NumBackChannelElements; el++) {
+ if (!findElementInstanceTag(pce->BackElementTagSelect[el],
+ pce->BackElementIsCpe[el] ? ID_CPE : ID_SCE,
+ pAacDecoderChannelInfo, nChannels,
+ pElementIdTab, nElements)) {
+ return 0; /* element instance tag not in raw_data_block() */
+ }
+ }
+ for (int el = 0; el < pce->NumLfeChannelElements; el++) {
+ if (!findElementInstanceTag(pce->LfeElementTagSelect[el], ID_LFE,
+ pAacDecoderChannelInfo, nChannels,
+ pElementIdTab, nElements)) {
+ return 0; /* element instance tag not in raw_data_block() */
+ }
+ }
+ } else {
+ return 0; /* too less decoded audio channels */
+ }
+
+ return 1; /* all element instance tags found in raw_data_block() */
+}
+
/*!
\brief Read Program Config Element
@@ -568,7 +637,7 @@ static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs,
\return Error code
*/
LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
- const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+ const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
const INT frameSize, const INT interleaved) {
int i, ch, s1, s2;
AAC_DECODER_ERROR ErrorStatus;
@@ -584,7 +653,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
}
for (ch = 0; ch < numChannels; ch++) {
- const INT_PCM *pIn = &pTimeData[ch * s1];
+ const PCM_DEC *pIn = &pTimeData[ch * s1];
for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
pTimeDataFlush[ch][i] = *pIn;
pIn += s2;
@@ -606,7 +675,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
\return Error code
*/
LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
- INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+ PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
const INT frameSize, const INT interleaved) {
int i, ch, s1, s2;
AAC_DECODER_ERROR ErrorStatus;
@@ -622,15 +691,15 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
}
for (ch = 0; ch < numChannels; ch++) {
- INT_PCM *pIn = &pTimeData[ch * s1];
+ PCM_DEC *pIn = &pTimeData[ch * s1];
for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
FIXP_SGL alpha = (FIXP_SGL)i
<< (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF);
- FIXP_DBL time = FX_PCM2FX_DBL(*pIn);
- FIXP_DBL timeFlush = FX_PCM2FX_DBL(pTimeDataFlush[ch][i]);
+ FIXP_DBL time = PCM_DEC2FIXP_DBL(*pIn);
+ FIXP_DBL timeFlush = PCM_DEC2FIXP_DBL(pTimeDataFlush[ch][i]);
- *pIn = (INT_PCM)(FIXP_PCM)FX_DBL2FX_PCM(
- timeFlush - fMult(timeFlush, alpha) + fMult(time, alpha));
+ *pIn = FIXP_DBL2PCM_DEC(timeFlush - fMult(timeFlush, alpha) +
+ fMult(time, alpha));
pIn += s2;
}
}
@@ -753,7 +822,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse(
/* We are interested in preroll AUs if an explicit or an implicit config
* change is signalized in other words if the build up status is set. */
if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) {
- self->applyCrossfade |= FDKreadBit(hBs);
+ UCHAR applyCrossfade = FDKreadBit(hBs);
+ if (applyCrossfade) {
+ self->applyCrossfade |= AACDEC_CROSSFADE_BITMASK_PREROLL;
+ } else {
+ self->applyCrossfade &= ~AACDEC_CROSSFADE_BITMASK_PREROLL;
+ }
FDKreadBit(hBs); /* reserved */
/* Read num preroll AU's */
*numPrerollAU = escapedValue(hBs, 2, 4, 0);
@@ -838,43 +912,6 @@ static AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse(
}
*count -= readBits;
} break;
- case EXT_UNI_DRC: {
- DRC_DEC_ERROR drcErr = DRC_DEC_OK;
- DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED;
- INT nBitsRemaining = FDKgetValidBits(hBs);
- INT readBits;
-
- switch (self->streamInfo.aot) {
- case AOT_AAC_LC:
- case AOT_SBR:
- case AOT_PS:
- drcDecCodecMode = DRC_DEC_MPEG_4_AAC;
- break;
- default:
- error = AAC_DEC_PARSE_ERROR;
- goto bail;
- }
-
- drcErr = FDK_drcDec_SetCodecMode(self->hUniDrcDecoder, drcDecCodecMode);
- if (drcErr) {
- error = AAC_DEC_PARSE_ERROR;
- goto bail;
- }
-
- drcErr = FDK_drcDec_ReadUniDrc(self->hUniDrcDecoder, hBs);
- if (drcErr) {
- error = AAC_DEC_PARSE_ERROR;
- goto bail;
- }
- readBits = (INT)nBitsRemaining - (INT)FDKgetValidBits(hBs);
- if (readBits > *count) { /* Read too much. Something went wrong! */
- error = AAC_DEC_PARSE_ERROR;
- }
- *count -= readBits;
- /* Skip any trailing bits */
- FDKpushFor(hBs, *count);
- *count = 0;
- } break;
case EXT_LDSAC_DATA:
case EXT_SAC_DATA:
/* Read MPEG Surround Extension payload */
@@ -1397,6 +1434,27 @@ static void CAacDecoder_DeInit(HANDLE_AACDECODER self,
}
/*!
+ * \brief CAacDecoder_AcceptFlags Accept flags and element flags
+ *
+ * \param self [o] handle to AACDECODER structure
+ * \param asc [i] handle to ASC structure
+ * \param flags [i] flags
+ * \param elFlags [i] pointer to element flags
+ * \param streamIndex [i] stream index
+ * \param elementOffset [i] element offset
+ *
+ * \return void
+ */
+static void CAacDecoder_AcceptFlags(HANDLE_AACDECODER self,
+ const CSAudioSpecificConfig *asc,
+ UINT flags, UINT *elFlags, int streamIndex,
+ int elementOffset) {
+ FDKmemcpy(self->elFlags, elFlags, sizeof(self->elFlags));
+
+ self->flags[streamIndex] = flags;
+}
+
+/*!
* \brief CAacDecoder_CtrlCFGChange Set config change parameters.
*
* \param self [i] handle to AACDECODER structure
@@ -1493,6 +1551,15 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
const int streamIndex = 0;
INT flushChannels = 0;
+ UINT flags;
+ /* elFlags[(3*MAX_CHANNELS + (MAX_CHANNELS)/2 + 4 * (MAX_TRACKS) + 1]
+ where MAX_CHANNELS is (8*2) and MAX_TRACKS is 1 */
+ UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)];
+
+ UCHAR sbrEnabled = self->sbrEnabled;
+ UCHAR sbrEnabledPrev = self->sbrEnabledPrev;
+ UCHAR mpsEnableCurr = self->mpsEnableCurr;
+
if (!self) return AAC_DEC_INVALID_HANDLE;
UCHAR downscaleFactor = self->downscaleFactor;
@@ -1649,8 +1716,8 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
}
/* Set syntax flags */
- self->flags[streamIndex] = 0;
- { FDKmemclear(self->elFlags, sizeof(self->elFlags)); }
+ flags = 0;
+ { FDKmemclear(elFlags, sizeof(elFlags)); }
if ((asc->m_channelConfiguration > 0) || IS_USAC(asc->m_aot)) {
if (IS_USAC(asc->m_aot)) {
@@ -1676,7 +1743,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
asc->m_sc.m_usacConfig.m_usacNumElements;
}
- self->mpsEnableCurr = 0;
+ mpsEnableCurr = 0;
for (int _el = 0;
_el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
_el++) {
@@ -1696,35 +1763,34 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
self->usacStereoConfigIndex[el] =
asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex;
if (self->elements[el] == ID_USAC_CPE) {
- self->mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0;
+ mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0;
}
}
- self->elFlags[el] |=
- (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling)
- ? AC_EL_USAC_NOISE
- : 0;
- self->elFlags[el] |=
+ elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling)
+ ? AC_EL_USAC_NOISE
+ : 0;
+ elFlags[el] |=
(asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex > 0)
? AC_EL_USAC_MPS212
: 0;
- self->elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes)
- ? AC_EL_USAC_ITES
- : 0;
- self->elFlags[el] |=
+ elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes)
+ ? AC_EL_USAC_ITES
+ : 0;
+ elFlags[el] |=
(asc->m_sc.m_usacConfig.element[_el].m_pvc) ? AC_EL_USAC_PVC : 0;
- self->elFlags[el] |=
+ elFlags[el] |=
(asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
? AC_EL_USAC_LFE
: 0;
- self->elFlags[el] |=
+ elFlags[el] |=
(asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE)
? AC_EL_LFE
: 0;
if ((asc->m_sc.m_usacConfig.element[_el].usacElementType ==
ID_USAC_CPE) &&
((self->usacStereoConfigIndex[el] == 0))) {
- self->elFlags[el] |= AC_EL_USAC_CP_POSSIBLE;
+ elFlags[el] |= AC_EL_USAC_CP_POSSIBLE;
}
}
@@ -1791,9 +1857,17 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
downscaleFactorInBS =
asc->m_samplingFrequency /
asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency;
- if (downscaleFactorInBS == 1 || downscaleFactorInBS == 2 ||
- downscaleFactorInBS == 3 || downscaleFactorInBS == 4) {
+ if ((downscaleFactorInBS == 1 || downscaleFactorInBS == 2 ||
+ (downscaleFactorInBS == 3 &&
+ asc->m_sc.m_eldSpecificConfig.m_frameLengthFlag) ||
+ downscaleFactorInBS == 4) &&
+ ((asc->m_samplingFrequency %
+ asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency) ==
+ 0)) {
downscaleFactor = downscaleFactorInBS;
+ } else {
+ downscaleFactorInBS = 1;
+ downscaleFactor = 1;
}
}
} else {
@@ -1825,7 +1899,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
self->useLdQmfTimeAlign =
asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
}
- if (self->sbrEnabled != asc->m_sbrPresentFlag) {
+ if (sbrEnabled != asc->m_sbrPresentFlag) {
ascChanged = 1;
}
}
@@ -1838,16 +1912,16 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
if (configMode & AC_CM_ALLOC_MEM) {
self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency;
}
- self->flags[streamIndex] |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
- self->flags[streamIndex] |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
+ flags |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0;
+ flags |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0;
if (asc->m_sbrPresentFlag) {
- self->sbrEnabled = 1;
- self->sbrEnabledPrev = 1;
+ sbrEnabled = 1;
+ sbrEnabledPrev = 1;
} else {
- self->sbrEnabled = 0;
- self->sbrEnabledPrev = 0;
+ sbrEnabled = 0;
+ sbrEnabledPrev = 0;
}
- if (self->sbrEnabled && asc->m_extensionSamplingFrequency) {
+ if (sbrEnabled && asc->m_extensionSamplingFrequency) {
if (downscaleFactor != 1 && (downscaleFactor)&1) {
return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* SBR needs an even downscale
factor */
@@ -1865,51 +1939,47 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
}
/* --------- vcb11 ------------ */
- self->flags[streamIndex] |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
+ flags |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0;
/* ---------- rvlc ------------ */
- self->flags[streamIndex] |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
+ flags |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0;
/* ----------- hcr ------------ */
- self->flags[streamIndex] |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
+ flags |= (asc->m_hcrFlag) ? AC_ER_HCR : 0;
if (asc->m_aot == AOT_ER_AAC_ELD) {
- self->mpsEnableCurr = 0;
- self->flags[streamIndex] |= AC_ELD;
- self->flags[streamIndex] |=
- (asc->m_sbrPresentFlag)
- ? AC_SBR_PRESENT
- : 0; /* Need to set the SBR flag for backward-compatibility
- reasons. Even if SBR is not supported. */
- self->flags[streamIndex] |=
- (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
- self->flags[streamIndex] |=
- (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_MPS_PRESENT
- : 0;
+ mpsEnableCurr = 0;
+ flags |= AC_ELD;
+ flags |= (asc->m_sbrPresentFlag)
+ ? AC_SBR_PRESENT
+ : 0; /* Need to set the SBR flag for backward-compatibility
+ reasons. Even if SBR is not supported. */
+ flags |= (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0;
+ flags |= (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign)
+ ? AC_MPS_PRESENT
+ : 0;
if (self->mpsApplicable) {
- self->mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
+ mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign;
}
}
- self->flags[streamIndex] |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
- self->flags[streamIndex] |= (asc->m_epConfig >= 0) ? AC_ER : 0;
+ flags |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0;
+ flags |= (asc->m_epConfig >= 0) ? AC_ER : 0;
if (asc->m_aot == AOT_USAC) {
- self->flags[streamIndex] |= AC_USAC;
- self->flags[streamIndex] |=
- (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0)
- ? AC_MPS_PRESENT
- : 0;
+ flags |= AC_USAC;
+ flags |= (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0)
+ ? AC_MPS_PRESENT
+ : 0;
}
if (asc->m_aot == AOT_DRM_AAC) {
- self->flags[streamIndex] |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
+ flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE;
}
if (asc->m_aot == AOT_DRM_SURROUND) {
- self->flags[streamIndex] |=
- AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
+ flags |= AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT;
FDK_ASSERT(!asc->m_psPresentFlag);
}
if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) {
- self->flags[streamIndex] |= AC_SCALABLE;
+ flags |= AC_SCALABLE;
}
if ((asc->m_epConfig >= 0) && (asc->m_channelConfiguration <= 0)) {
@@ -1960,13 +2030,17 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
if (ascChanged != 0) {
*configChanged = 1;
}
+
+ CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
+ elementOffset);
+
return err;
}
/* set AC_USAC_SCFGI3 globally if any usac element uses */
switch (asc->m_aot) {
case AOT_USAC:
- if (self->sbrEnabled) {
+ if (sbrEnabled) {
for (int _el = 0;
_el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements;
_el++) {
@@ -1988,7 +2062,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
}
if (usacStereoConfigIndex == 3) {
- self->flags[streamIndex] |= AC_USAC_SCFGI3;
+ flags |= AC_USAC_SCFGI3;
}
}
break;
@@ -2003,7 +2077,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
*/
switch (asc->m_aot) {
case AOT_USAC:
- if (self->sbrEnabled) {
+ if (sbrEnabled) {
const UCHAR map_sbrRatio_2_nAnaBands[] = {16, 24, 32};
FDK_ASSERT(asc->m_sc.m_usacConfig.m_sbrRatioIndex > 0);
@@ -2031,11 +2105,11 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
}
break;
case AOT_ER_AAC_ELD:
- if (self->mpsEnableCurr &&
+ if (mpsEnableCurr &&
asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) {
- SAC_INPUT_CONFIG sac_interface =
- (self->sbrEnabled && self->hSbrDecoder) ? SAC_INTERFACE_QMF
- : SAC_INTERFACE_TIME;
+ SAC_INPUT_CONFIG sac_interface = (sbrEnabled && self->hSbrDecoder)
+ ? SAC_INTERFACE_QMF
+ : SAC_INTERFACE_TIME;
mpegSurroundDecoder_ConfigureQmfDomain(
(CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface,
(UINT)self->streamInfo.aacSampleRate, asc->m_aot);
@@ -2069,14 +2143,14 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
ch = aacChannelsOffset;
int _numElements;
_numElements = (((8)) + (8));
- if (self->flags[streamIndex] & (AC_RSV603DA | AC_USAC)) {
+ if (flags & (AC_RSV603DA | AC_USAC)) {
_numElements = (int)asc->m_sc.m_usacConfig.m_usacNumElements;
}
for (int _el = 0; _el < _numElements; _el++) {
int el_channels = 0;
int el = elementOffset + _el;
- if (self->flags[streamIndex] &
+ if (flags &
(AC_ER | AC_LD | AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) {
if (ch >= ascChannels) {
break;
@@ -2176,15 +2250,14 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) {
goto bail;
}
- if (self->flags[streamIndex] &
- (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) {
+ if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) {
self->pAacDecoderStaticChannelInfo[ch]->hArCo = CArco_Create();
if (self->pAacDecoderStaticChannelInfo[ch]->hArCo == NULL) {
goto bail;
}
}
- if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) {
+ if (!(flags & (AC_USAC | AC_RSV603DA))) {
CPns_UpdateNoiseState(
&self->pAacDecoderChannelInfo[ch]->data.aac.PnsData,
&self->pAacDecoderStaticChannelInfo[ch]->pnsCurrentSeed,
@@ -2195,7 +2268,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
chIdx++;
}
- if (self->flags[streamIndex] & AC_USAC) {
+ if (flags & AC_USAC) {
for (int _ch = 0; _ch < flushChannels; _ch++) {
ch = aacChannelsOffset + _ch;
if (self->pTimeDataFlush[ch] == NULL) {
@@ -2207,7 +2280,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
}
}
- if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+ if (flags & (AC_USAC | AC_RSV603DA)) {
int complexStereoPredPossible = 0;
ch = aacChannelsOffset;
chIdx = aacChannelsOffsetIdx;
@@ -2223,7 +2296,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
elCh = 1;
}
- if (self->elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) {
+ if (elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) {
complexStereoPredPossible = 1;
if (self->cpeStaticData[el2] == NULL) {
self->cpeStaticData[el2] = GetCpePersistentData();
@@ -2360,9 +2433,6 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
}
}
- /* Update externally visible copy of flags */
- self->streamInfo.flags = self->flags[0];
-
if (*configChanged) {
int drcDecSampleRate, drcDecFrameSize;
@@ -2383,8 +2453,7 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
if (*configChanged) {
if (asc->m_aot == AOT_USAC) {
- self->hDrcInfo->enable = 0;
- self->hDrcInfo->progRefLevelPresent = 0;
+ aacDecoder_drcDisable(self->hDrcInfo);
}
}
@@ -2393,6 +2462,15 @@ CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc,
pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f));
}
+ CAacDecoder_AcceptFlags(self, asc, flags, elFlags, streamIndex,
+ elementOffset);
+ self->sbrEnabled = sbrEnabled;
+ self->sbrEnabledPrev = sbrEnabledPrev;
+ self->mpsEnableCurr = mpsEnableCurr;
+
+ /* Update externally visible copy of flags */
+ self->streamInfo.flags = self->flags[0];
+
return err;
bail:
@@ -2927,6 +3005,24 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
} /* while ( (type != ID_END) ... ) */
+ if (!(self->flags[streamIndex] &
+ (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_BSAC | AC_LD | AC_ELD | AC_ER |
+ AC_SCALABLE)) &&
+ (self->streamInfo.channelConfig == 0) && pce->isValid &&
+ (ErrorStatus == AAC_DEC_OK) && self->frameOK &&
+ !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
+ /* Check whether all PCE listed element instance tags are present in
+ * raw_data_block() */
+ if (!validateElementInstanceTags(
+ &self->pce, self->pAacDecoderChannelInfo, aacChannels,
+ channel_elements,
+ fMin(channel_element_count, (int)(sizeof(channel_elements) /
+ sizeof(*channel_elements))))) {
+ ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
+ self->frameOK = 0;
+ }
+ }
+
if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) {
/* float decoder checks if bitsLeft is in range 0-7; only prerollAUs are
* byteAligned with respect to the first bit */
@@ -3177,12 +3273,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR));
}
- /* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is
- * present and one of DRC or Loudness Normalization is switched on */
- aacDecoder_drcSetParam(
- self->hDrcInfo, UNIDRC_PRECEDENCE,
- FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE));
-
/* Extract DRC control data and map it to channels (without bitstream delay)
*/
mapped = aacDecoder_drcProlog(
@@ -3194,11 +3284,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
* data in the bitstream. */
self->flags[streamIndex] |= AC_DRC_PRESENT;
} else {
- self->hDrcInfo->enable = 0;
- self->hDrcInfo->progRefLevelPresent = 0;
ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
}
}
+ if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+ aacDecoder_drcDisable(self->hDrcInfo);
+ }
/* Create a reverse mapping table */
UCHAR Reverse_chMapping[((8) * 2)];
@@ -3441,11 +3532,12 @@ LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame(
* data in the bitstream. */
self->flags[streamIndex] |= AC_DRC_PRESENT;
} else {
- self->hDrcInfo->enable = 0;
- self->hDrcInfo->progRefLevelPresent = 0;
ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT;
}
}
+ if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) {
+ aacDecoder_drcDisable(self->hDrcInfo);
+ }
}
/* Add additional concealment delay */
diff --git a/libAACdec/src/aacdecoder.h b/libAACdec/src/aacdecoder.h
index bd1f38f..002807f 100644
--- a/libAACdec/src/aacdecoder.h
+++ b/libAACdec/src/aacdecoder.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -172,6 +172,12 @@ enum {
AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5
};
+#define AACDEC_CROSSFADE_BITMASK_OFF \
+ ((UCHAR)0) /*!< No cross-fade between frames shall be applied at next \
+ config change. */
+#define AACDEC_CROSSFADE_BITMASK_PREROLL \
+ ((UCHAR)1 << 1) /*!< applyCrossfade is signaled in AudioPreRoll */
+
typedef struct {
/* Usac Extension Elements */
USAC_EXT_ELEMENT_TYPE usacExtElementType[(3)];
@@ -325,7 +331,7 @@ This structure is allocated once for each CPE. */
UINT loudnessInfoSetPosition[3];
SCHAR defaultTargetLoudness;
- INT_PCM
+ PCM_DEC
*pTimeDataFlush[((8) * 2)]; /*!< Pointer to the flushed time data which
will be used for the crossfade in case of
an USAC DASH IPF config change */
@@ -341,8 +347,8 @@ This structure is allocated once for each CPE. */
start position in the
bitstream */
INT accessUnit; /*!< Number of the actual processed preroll accessUnit */
- UCHAR applyCrossfade; /*!< if set crossfade for seamless stream switching is
- applied */
+ UCHAR applyCrossfade; /*!< If any bit is set, cross-fade for seamless stream
+ switching is applied */
FDK_SignalDelay usacResidualDelay; /*!< Delay residual signal to compensate
for eSBR delay of DMX signal in case of
@@ -439,12 +445,12 @@ LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self,
/* Prepare crossfade for USAC DASH IPF config change */
LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade(
- const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+ const PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
const INT frameSize, const INT interleaved);
/* Apply crossfade for USAC DASH IPF config change */
LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade(
- INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels,
+ PCM_DEC *pTimeData, PCM_DEC **pTimeDataFlush, const INT numChannels,
const INT frameSize, const INT interleaved);
/* Set flush and build up mode */
diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp
index bcbd46c..5319b7c 100644
--- a/libAACdec/src/aacdecoder_lib.cpp
+++ b/libAACdec/src/aacdecoder_lib.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -385,21 +385,19 @@ static INT aacDecoder_SbrCallback(
return errTp;
}
-static INT aacDecoder_SscCallback(void *handle, HANDLE_FDK_BITSTREAM hBs,
- const AUDIO_OBJECT_TYPE coreCodec,
- const INT samplingRate, const INT frameSize,
- const INT stereoConfigIndex,
- const INT coreSbrFrameLengthIndex,
- const INT configBytes, const UCHAR configMode,
- UCHAR *configChanged) {
+static INT aacDecoder_SscCallback(
+ void *handle, HANDLE_FDK_BITSTREAM hBs, const AUDIO_OBJECT_TYPE coreCodec,
+ const INT samplingRate, const INT frameSize, const INT numChannels,
+ const INT stereoConfigIndex, const INT coreSbrFrameLengthIndex,
+ const INT configBytes, const UCHAR configMode, UCHAR *configChanged) {
SACDEC_ERROR err;
TRANSPORTDEC_ERROR errTp;
HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle;
err = mpegSurroundDecoder_Config(
(CMpegSurroundDecoder *)hAacDecoder->pMpegSurroundDecoder, hBs, coreCodec,
- samplingRate, frameSize, stereoConfigIndex, coreSbrFrameLengthIndex,
- configBytes, configMode, configChanged);
+ samplingRate, frameSize, numChannels, stereoConfigIndex,
+ coreSbrFrameLengthIndex, configBytes, configMode, configChanged);
switch (err) {
case MPS_UNSUPPORTED_CONFIG:
@@ -443,12 +441,23 @@ static INT aacDecoder_UniDrcCallback(void *handle, HANDLE_FDK_BITSTREAM hBs,
TRANSPORTDEC_ERROR errTp;
HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle;
DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED;
+ UCHAR dummyBuffer[4] = {0};
+ FDK_BITSTREAM dummyBs;
+ HANDLE_FDK_BITSTREAM hReadBs;
if (subStreamIndex != 0) {
return TRANSPORTDEC_OK;
}
- else if (aot == AOT_USAC) {
+ if (hBs == NULL) {
+ /* use dummy zero payload to clear memory */
+ hReadBs = &dummyBs;
+ FDKinitBitStream(hReadBs, dummyBuffer, 4, 24);
+ } else {
+ hReadBs = hBs;
+ }
+
+ if (aot == AOT_USAC) {
drcDecCodecMode = DRC_DEC_MPEG_D_USAC;
}
@@ -457,10 +466,10 @@ static INT aacDecoder_UniDrcCallback(void *handle, HANDLE_FDK_BITSTREAM hBs,
if (payloadType == 0) /* uniDrcConfig */
{
- err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hBs);
+ err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hReadBs);
} else /* loudnessInfoSet */
{
- err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hBs);
+ err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hReadBs);
hAacDecoder->loudnessInfoSetPosition[1] = payloadStart;
hAacDecoder->loudnessInfoSetPosition[2] = fullPayloadLength;
}
@@ -822,6 +831,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_SetParam(
case AAC_DRC_ATTENUATION_FACTOR:
/* DRC compression factor (where 0 is no and 127 is max compression) */
+ if ((value < 0) || (value > 127)) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_CUT_SCALE, value);
uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_COMPRESS,
value * (FL2FXCONST_DBL(0.5f / 127.0f)));
@@ -829,6 +841,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_SetParam(
case AAC_DRC_BOOST_FACTOR:
/* DRC boost factor (where 0 is no and 127 is max boost) */
+ if ((value < 0) || (value > 127)) {
+ return AAC_DEC_SET_PARAM_FAIL;
+ }
errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_BOOST_SCALE, value);
uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_BOOST,
value * (FL2FXCONST_DBL(0.5f / 127.0f)));
@@ -1153,6 +1168,8 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
int applyCrossfade = 1; /* flag indicates if flushing was possible */
PCM_DEC *pTimeData2;
PCM_AAC *pTimeData3;
+ INT pcmLimiterScale = 0;
+ INT interleaved = 0;
if (self == NULL) {
return AAC_DEC_INVALID_HANDLE;
@@ -1175,8 +1192,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
aacDecoder_FreeMemCallback(self, &asc);
self->streamInfo.numChannels = 0;
/* 3) restore AudioSpecificConfig */
- transportDec_OutOfBandConfig(self->hInput, asc.config,
- (asc.configBits + 7) >> 3, 0);
+ if (asc.configBits <= (TP_USAC_MAX_CONFIG_LEN << 3)) {
+ transportDec_OutOfBandConfig(self->hInput, asc.config,
+ (asc.configBits + 7) >> 3, 0);
+ }
}
}
@@ -1609,6 +1628,11 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
/* set params */
sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY,
self->sbrParams.bsDelay);
+ sbrDecoder_SetParam(
+ self->hSbrDecoder, SBR_FLUSH_DATA,
+ (flags & AACDEC_FLUSH) |
+ ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH
+ : 0));
sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1);
@@ -1659,7 +1683,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
{
if ((FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) &&
- !(self->flags[0] & AC_RSV603DA)) {
+ (self->flags[0] & AC_USAC)) {
/* Apply DRC gains*/
int ch, drcDelay = 0;
int needsDeinterleaving = 0;
@@ -1667,8 +1691,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
FIXP_DBL channelGain[(8)];
int reverseInChannelMap[(8)];
int reverseOutChannelMap[(8)];
- int numDrcOutChannels = FDK_drcDec_GetParam(
- self->hUniDrcDecoder, DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED);
FDKmemclear(channelGain, sizeof(channelGain));
for (ch = 0; ch < (8); ch++) {
reverseInChannelMap[ch] = ch;
@@ -1691,17 +1713,6 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
drcDelay += CConcealment_GetDelay(&self->concealCommonData) *
self->streamInfo.frameSize;
- for (ch = 0; ch < self->streamInfo.numChannels; ch++) {
- UCHAR mapValue = FDK_chMapDescr_getMapValue(
- &self->mapDescr, (UCHAR)ch, self->chMapIndex);
- if (mapValue < (8)) reverseInChannelMap[mapValue] = ch;
- }
- for (ch = 0; ch < (int)numDrcOutChannels; ch++) {
- UCHAR mapValue = FDK_chMapDescr_getMapValue(
- &self->mapDescr, (UCHAR)ch, numDrcOutChannels);
- if (mapValue < (8)) reverseOutChannelMap[mapValue] = ch;
- }
-
/* The output of SBR and MPS is interleaved. Deinterleaving may be
* necessary for FDK_drcDec_ProcessTime, which accepts deinterleaved
* audio only. */
@@ -1736,11 +1747,9 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
FDK_drcDec_Preprocess(self->hUniDrcDecoder);
/* apply DRC1 gain sequence */
- for (ch = 0; ch < self->streamInfo.numChannels; ch++) {
- FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay, DRC_DEC_DRC1,
- ch, reverseInChannelMap[ch] - ch, 1,
- drcWorkBuffer, self->streamInfo.frameSize);
- }
+ FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay, DRC_DEC_DRC1,
+ 0, 0, self->streamInfo.numChannels,
+ drcWorkBuffer, self->streamInfo.frameSize);
/* apply downmix */
FDK_drcDec_ApplyDownmix(
self->hUniDrcDecoder, reverseInChannelMap, reverseOutChannelMap,
@@ -1748,12 +1757,10 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
&self->streamInfo.numChannels); /* self->streamInfo.numChannels
may change here */
/* apply DRC2/3 gain sequence */
- for (ch = 0; ch < self->streamInfo.numChannels; ch++) {
- FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay,
- DRC_DEC_DRC2_DRC3, ch,
- reverseOutChannelMap[ch] - ch, 1,
- drcWorkBuffer, self->streamInfo.frameSize);
- }
+ FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay,
+ DRC_DEC_DRC2_DRC3, 0, 0,
+ self->streamInfo.numChannels, drcWorkBuffer,
+ self->streamInfo.frameSize);
if (needsDeinterleaving) {
FDK_interleave(
@@ -1796,8 +1803,7 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
}
if (self->streamInfo.extAot != AOT_AAC_SLS) {
- INT pcmLimiterScale = 0;
- INT interleaved = 0;
+ interleaved = 0;
interleaved |= (self->sbrEnabled) ? 1 : 0;
interleaved |= (self->mpsEnableCurr) ? 1 : 0;
PCMDMX_ERROR dmxErr = PCMDMX_OK;
@@ -1828,145 +1834,38 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
* predictable behavior and thus maybe produce strange output. */
ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR;
}
-
- pcmLimiterScale += PCM_OUT_HEADROOM;
-
- if (flags & AACDEC_CLRHIST) {
- if (!(self->flags[0] & AC_USAC)) {
- /* Reset DRC data */
- aacDecoder_drcReset(self->hDrcInfo);
- /* Delete the delayed signal. */
- pcmLimiter_Reset(self->hLimiter);
- }
- }
-
- /* Set applyExtGain if DRC processing is enabled and if
- progRefLevelPresent is present for the first time. Consequences: The
- headroom of the output signal can be set to AACDEC_DRC_GAIN_SCALING
- only for audio formats which support legacy DRC Level Normalization.
- For all other audio formats the headroom of the output
- signal is set to PCM_OUT_HEADROOM. */
- if (self->hDrcInfo->enable &&
- (self->hDrcInfo->progRefLevelPresent == 1)) {
- self->hDrcInfo->applyExtGain |= 1;
- }
-
- /* Check whether time data buffer is large enough. */
- if (timeDataSize <
- (self->streamInfo.numChannels * self->streamInfo.frameSize)) {
- ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
- goto bail;
- }
-
- if (self->limiterEnableCurr) {
- /* use workBufferCore2 buffer for interleaving */
- PCM_LIM *pInterleaveBuffer;
- int blockLength = self->streamInfo.frameSize;
-
- /* Set actual signal parameters */
- pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
- pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
-
- if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
- (self->mpsEnableCurr)) {
- pInterleaveBuffer = (PCM_LIM *)pTimeData2;
- } else {
- pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
-
- /* applyLimiter requests for interleaved data */
- /* Interleave ouput buffer */
- FDK_interleave(pTimeData2, pInterleaveBuffer,
- self->streamInfo.numChannels, blockLength,
- self->streamInfo.frameSize);
- }
-
- FIXP_DBL *pGainPerSample = NULL;
-
- if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
- pGainPerSample = self->workBufferCore1;
-
- if ((INT)GetRequiredMemWorkBufferCore1() <
- (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) {
- ErrorStatus = AAC_DEC_UNKNOWN;
- goto bail;
- }
-
- pcmLimiterScale = applyDrcLevelNormalization(
- self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain,
- pGainPerSample, pcmLimiterScale, self->extGainDelay,
- self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1);
- }
-
- pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
- pGainPerSample, pcmLimiterScale,
- self->streamInfo.frameSize);
-
- {
- /* Announce the additional limiter output delay */
- self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
- }
- } else {
- if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
- pcmLimiterScale = applyDrcLevelNormalization(
- self->hDrcInfo, pTimeData2, self->extGain, NULL,
- pcmLimiterScale, self->extGainDelay, self->streamInfo.frameSize,
- self->streamInfo.numChannels,
- (interleaved || (self->streamInfo.numChannels == 1))
- ? 1
- : self->streamInfo.frameSize,
- 0);
- }
-
- /* If numChannels = 1 we do not need interleaving. The same applies if
- SBR or MPS are used, since their output is interleaved already
- (resampled or not) */
- if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
- (self->mpsEnableCurr)) {
- scaleValuesSaturate(
- pTimeData, pTimeData2,
- self->streamInfo.frameSize * self->streamInfo.numChannels,
- pcmLimiterScale);
-
- } else {
- scaleValuesSaturate(
- (INT_PCM *)self->workBufferCore2, pTimeData2,
- self->streamInfo.frameSize * self->streamInfo.numChannels,
- pcmLimiterScale);
- /* Interleave ouput buffer */
- FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
- self->streamInfo.numChannels,
- self->streamInfo.frameSize,
- self->streamInfo.frameSize);
- }
- }
- } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/
+ }
if (self->flags[0] & AC_USAC) {
if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON &&
!(flags & AACDEC_CONCEAL)) {
- CAacDecoder_PrepareCrossFade(pTimeData, self->pTimeDataFlush,
+ CAacDecoder_PrepareCrossFade(pTimeData2, self->pTimeDataFlush,
self->streamInfo.numChannels,
- self->streamInfo.frameSize, 1);
+ self->streamInfo.frameSize, interleaved);
}
/* prepare crossfade buffer for fade in */
- if (!applyCrossfade && self->applyCrossfade &&
+ if (!applyCrossfade &&
+ (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) &&
!(flags & AACDEC_CONCEAL)) {
for (int ch = 0; ch < self->streamInfo.numChannels; ch++) {
for (int i = 0; i < TIME_DATA_FLUSH_SIZE; i++) {
- self->pTimeDataFlush[ch][i] = 0;
+ self->pTimeDataFlush[ch][i] = (PCM_DEC)0;
}
}
applyCrossfade = 1;
}
- if (applyCrossfade && self->applyCrossfade &&
+ if (applyCrossfade &&
+ (self->applyCrossfade != AACDEC_CROSSFADE_BITMASK_OFF) &&
!(accessUnit < numPrerollAU) &&
(self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) {
- CAacDecoder_ApplyCrossFade(pTimeData, self->pTimeDataFlush,
+ CAacDecoder_ApplyCrossFade(pTimeData2, self->pTimeDataFlush,
self->streamInfo.numChannels,
- self->streamInfo.frameSize, 1);
- self->applyCrossfade = 0;
+ self->streamInfo.frameSize, interleaved);
+ self->applyCrossfade =
+ AACDEC_CROSSFADE_BITMASK_OFF; /* disable cross-fade between frames
+ at nect config change */
}
}
@@ -2008,6 +1907,116 @@ LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self,
((self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) &&
!(flags & AACDEC_CONCEAL)));
+ if (self->streamInfo.extAot != AOT_AAC_SLS) {
+ pcmLimiterScale += PCM_OUT_HEADROOM;
+
+ if (flags & AACDEC_CLRHIST) {
+ if (!(self->flags[0] & AC_USAC)) {
+ /* Reset DRC data */
+ aacDecoder_drcReset(self->hDrcInfo);
+ /* Delete the delayed signal. */
+ pcmLimiter_Reset(self->hLimiter);
+ }
+ }
+
+ /* Set applyExtGain if DRC processing is enabled and if progRefLevelPresent
+ is present for the first time. Consequences: The headroom of the output
+ signal can be set to AACDEC_DRC_GAIN_SCALING only for audio formats which
+ support legacy DRC Level Normalization. For all other audio formats the
+ headroom of the output signal is set to PCM_OUT_HEADROOM. */
+ if (self->hDrcInfo->enable && (self->hDrcInfo->progRefLevelPresent == 1)) {
+ self->hDrcInfo->applyExtGain |= 1;
+ }
+
+ /* Check whether time data buffer is large enough. */
+ if (timeDataSize <
+ (self->streamInfo.numChannels * self->streamInfo.frameSize)) {
+ ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL;
+ goto bail;
+ }
+
+ if (self->limiterEnableCurr) {
+ /* use workBufferCore2 buffer for interleaving */
+ PCM_LIM *pInterleaveBuffer;
+ int blockLength = self->streamInfo.frameSize;
+
+ /* Set actual signal parameters */
+ pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels);
+ pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate);
+
+ if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
+ (self->mpsEnableCurr)) {
+ pInterleaveBuffer = (PCM_LIM *)pTimeData2;
+ } else {
+ pInterleaveBuffer = (PCM_LIM *)self->workBufferCore2;
+
+ /* applyLimiter requests for interleaved data */
+ /* Interleave ouput buffer */
+ FDK_interleave(pTimeData2, pInterleaveBuffer,
+ self->streamInfo.numChannels, blockLength,
+ self->streamInfo.frameSize);
+ }
+
+ FIXP_DBL *pGainPerSample = NULL;
+
+ if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+ pGainPerSample = self->workBufferCore1;
+
+ if ((INT)GetRequiredMemWorkBufferCore1() <
+ (INT)(self->streamInfo.frameSize * sizeof(FIXP_DBL))) {
+ ErrorStatus = AAC_DEC_UNKNOWN;
+ goto bail;
+ }
+
+ pcmLimiterScale = applyDrcLevelNormalization(
+ self->hDrcInfo, (PCM_DEC *)pInterleaveBuffer, self->extGain,
+ pGainPerSample, pcmLimiterScale, self->extGainDelay,
+ self->streamInfo.frameSize, self->streamInfo.numChannels, 1, 1);
+ }
+
+ pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData,
+ pGainPerSample, pcmLimiterScale,
+ self->streamInfo.frameSize);
+
+ {
+ /* Announce the additional limiter output delay */
+ self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter);
+ }
+ } else {
+ if (self->hDrcInfo->enable && self->hDrcInfo->applyExtGain) {
+ pcmLimiterScale = applyDrcLevelNormalization(
+ self->hDrcInfo, pTimeData2, self->extGain, NULL, pcmLimiterScale,
+ self->extGainDelay, self->streamInfo.frameSize,
+ self->streamInfo.numChannels,
+ (interleaved || (self->streamInfo.numChannels == 1))
+ ? 1
+ : self->streamInfo.frameSize,
+ 0);
+ }
+
+ /* If numChannels = 1 we do not need interleaving. The same applies if SBR
+ or MPS are used, since their output is interleaved already (resampled or
+ not) */
+ if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) ||
+ (self->mpsEnableCurr)) {
+ scaleValuesSaturate(
+ pTimeData, pTimeData2,
+ self->streamInfo.frameSize * self->streamInfo.numChannels,
+ pcmLimiterScale);
+
+ } else {
+ scaleValuesSaturate(
+ (INT_PCM *)self->workBufferCore2, pTimeData2,
+ self->streamInfo.frameSize * self->streamInfo.numChannels,
+ pcmLimiterScale);
+ /* Interleave ouput buffer */
+ FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData,
+ self->streamInfo.numChannels, self->streamInfo.frameSize,
+ self->streamInfo.frameSize);
+ }
+ }
+ } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/
+
bail:
/* error in renderer part occurred, ErrorStatus was set to invalid output */
diff --git a/libAACdec/src/channel.cpp b/libAACdec/src/channel.cpp
index a020034..7e62bfb 100644
--- a/libAACdec/src/channel.cpp
+++ b/libAACdec/src/channel.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -265,7 +265,9 @@ void CChannelElement_Decode(
stereo prediction since scaling has already been carried out. */
int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste);
- if ((!CP_active) || (CP_active && (max_sfb_ste < noSfbs)) ||
+ if (!(CP_active && (max_sfb_ste == noSfbs)) ||
+ !(CP_active &&
+ !(pAacDecoderChannelInfo[ch]->pDynData->TnsData.Active)) ||
((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) &&
(pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr ==
0))) {
diff --git a/libAACdec/src/rvlc.cpp b/libAACdec/src/rvlc.cpp
index b7a9be1..0b80364 100644
--- a/libAACdec/src/rvlc.cpp
+++ b/libAACdec/src/rvlc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -628,7 +628,7 @@ static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd;
SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc;
- UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc);
+ UCHAR escEscCnt = pRvlc->numDecodedEscapeWordsEsc;
UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd);
pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd);
@@ -636,7 +636,7 @@ static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
*pEscBwdCnt = 0;
pRvlc->direction = BWD;
- pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */
+ pScfEsc += escEscCnt - 1; /* set pScfEsc to last entry */
pRvlc->firstScf = 0;
pRvlc->firstNrg = 0;
pRvlc->firstIs = 0;
@@ -651,7 +651,7 @@ static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
}
dpcm -= TABLE_OFFSET;
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
- if (pRvlc->length_of_rvlc_escapes) {
+ if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) {
pRvlc->conceal_min = bnds;
return;
} else {
@@ -694,7 +694,7 @@ static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
}
dpcm -= TABLE_OFFSET;
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
- if (pRvlc->length_of_rvlc_escapes) {
+ if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) {
pScfBwd[bnds] = position;
pRvlc->conceal_min = fMax(0, bnds - offset);
return;
@@ -731,7 +731,8 @@ static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
}
dpcm -= TABLE_OFFSET;
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
- if (pRvlc->length_of_rvlc_escapes) {
+ if ((pRvlc->length_of_rvlc_escapes) ||
+ (*pEscBwdCnt >= escEscCnt)) {
pScfBwd[bnds] = noisenrg;
pRvlc->conceal_min = fMax(0, bnds - offset);
return;
@@ -762,7 +763,7 @@ static void rvlcDecodeBackward(CErRvlcInfo *pRvlc,
}
dpcm -= TABLE_OFFSET;
if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) {
- if (pRvlc->length_of_rvlc_escapes) {
+ if ((pRvlc->length_of_rvlc_escapes) || (*pEscBwdCnt >= escEscCnt)) {
pScfBwd[bnds] = factor;
pRvlc->conceal_min = fMax(0, bnds - offset);
return;
diff --git a/libAACdec/src/usacdec_acelp.cpp b/libAACdec/src/usacdec_acelp.cpp
index fbe3188..9769a07 100644
--- a/libAACdec/src/usacdec_acelp.cpp
+++ b/libAACdec/src/usacdec_acelp.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -719,7 +719,7 @@ static void ConcealPitchLag(CAcelpStaticMem *acelp_mem, const int PIT_MAX,
UCHAR *pold_T0_frac = &acelp_mem->old_T0_frac;
if ((int)*pold_T0 >= PIT_MAX) {
- *pold_T0 = (UCHAR)(PIT_MAX - 5);
+ *pold_T0 = (USHORT)(PIT_MAX - 5);
}
*pT0 = (int)*pold_T0;
*pT0_frac = (int)*pold_T0_frac;
diff --git a/libAACenc/include/aacenc_lib.h b/libAACenc/include/aacenc_lib.h
index 193c6a5..c21daf4 100644
--- a/libAACenc/include/aacenc_lib.h
+++ b/libAACenc/include/aacenc_lib.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1090,7 +1090,7 @@ typedef struct {
write edit lists for gapless playback. The decoder may not
know how much delay is introdcued by SBR, since it may not
know if SBR is active at all (implicit signaling),
- therefore the deocder must take into account any delay
+ therefore the decoder must take into account any delay
caused by the SBR module. */
UCHAR confBuf[64]; /*!< Configuration buffer in binary format as an
@@ -1649,7 +1649,7 @@ AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder,
*
* \return
* - AACENC_OK, on succes.
- * - AACENC_INIT_ERROR, on failure.
+ * - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure.
*/
AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder,
AACENC_InfoStruct *pInfo);
diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp
index fbaf407..212afdf 100644
--- a/libAACenc/src/aacenc_lib.cpp
+++ b/libAACenc/src/aacenc_lib.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1303,7 +1303,7 @@ static INT aacenc_SbrCallback(void *self, HANDLE_FDK_BITSTREAM hBs,
INT aacenc_SscCallback(void *self, HANDLE_FDK_BITSTREAM hBs,
const AUDIO_OBJECT_TYPE coreCodec,
const INT samplingRate, const INT frameSize,
- const INT stereoConfigIndex,
+ const INT numChannels, const INT stereoConfigIndex,
const INT coreSbrFrameLengthIndex, const INT configBytes,
const UCHAR configMode, UCHAR *configChanged) {
HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self;
@@ -1845,8 +1845,8 @@ AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder,
hAacEncoder->nSamplesRead));
INT_PCM *pIn =
hAacEncoder->inputBuffer +
- (hAacEncoder->inputBufferOffset + hAacEncoder->nSamplesRead) /
- hAacEncoder->aacConfig.nChannels;
+ hAacEncoder->inputBufferOffset / hAacEncoder->aacConfig.nChannels +
+ hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels;
newSamples -=
(newSamples %
hAacEncoder->extParam
@@ -1888,12 +1888,13 @@ AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder,
/* clear out until end-of-buffer */
if (nZeros) {
+ INT_PCM *pIn =
+ hAacEncoder->inputBuffer +
+ hAacEncoder->inputBufferOffset /
+ hAacEncoder->aacConfig.nChannels +
+ hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels;
for (i = 0; i < (int)hAacEncoder->extParam.nChannels; i++) {
- FDKmemclear(hAacEncoder->inputBuffer +
- i * hAacEncoder->inputBufferSizePerChannel +
- (hAacEncoder->inputBufferOffset +
- hAacEncoder->nSamplesRead) /
- hAacEncoder->extParam.nChannels,
+ FDKmemclear(pIn + i * hAacEncoder->inputBufferSizePerChannel,
sizeof(INT_PCM) * nZeros);
}
hAacEncoder->nZerosAppended += nZeros;
@@ -2588,6 +2589,11 @@ AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder,
AACENC_InfoStruct *pInfo) {
AACENC_ERROR err = AACENC_OK;
+ if ((hAacEncoder == NULL) || (pInfo == NULL)) {
+ err = AACENC_INVALID_HANDLE;
+ goto bail;
+ }
+
FDKmemclear(pInfo, sizeof(AACENC_InfoStruct));
pInfo->confSize = 64; /* pre-initialize */
diff --git a/libDRCdec/src/drcDec_reader.cpp b/libDRCdec/src/drcDec_reader.cpp
index ca35345..b080f50 100644
--- a/libDRCdec/src/drcDec_reader.cpp
+++ b/libDRCdec/src/drcDec_reader.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -512,10 +512,13 @@ drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs,
fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE));
}
- hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1);
- if (hUniDrcGain->uniDrcGainExtPresent == 1) {
- err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension));
- if (err) return err;
+ if (pCoef && (gainSequenceCount ==
+ pCoef->gainSequenceCount)) { /* all sequences have been read */
+ hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1);
+ if (hUniDrcGain->uniDrcGainExtPresent == 1) {
+ err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension));
+ if (err) return err;
+ }
}
if (err == DE_OK && gainSequenceCount > 0) {
diff --git a/libFDK/include/FDK_archdef.h b/libFDK/include/FDK_archdef.h
index b4fef8a..f3254f2 100644
--- a/libFDK/include/FDK_archdef.h
+++ b/libFDK/include/FDK_archdef.h
@@ -222,8 +222,18 @@ amm-info@iis.fraunhofer.de
#define POW2COEFF_16BIT
#define LDCOEFF_16BIT
+#elif defined(__riscv)
+#define ARCH_PREFER_MULT_32x16
+#define SINETABLE_16BIT
+#define POW2COEFF_16BIT
+#define LDCOEFF_16BIT
+#define WINDOWTABLE_16BIT
+
#elif defined(__powerpc__)
#define ARCH_PREFER_MULT_32x32
+
+#elif defined(__s390x__)
+#define ARCH_PREFER_MULT_32x32
#define ARCH_PREFER_MULT_32x16
#define SINETABLE_16BIT
#define POW2COEFF_16BIT
diff --git a/libFDK/include/fft.h b/libFDK/include/fft.h
index d394046..4ef62b4 100644
--- a/libFDK/include/fft.h
+++ b/libFDK/include/fft.h
@@ -139,7 +139,7 @@ void ifft(int length, FIXP_DBL *pInput, INT *scalefactor);
* bit scale headroom. The values are interleaved, real/imag pairs.
*/
LNK_SECTION_CODE_L1
-static FDK_FORCEINLINE void fft_4(FIXP_DBL *x) {
+static inline void fft_4(FIXP_DBL *x) {
FIXP_DBL a00, a10, a20, a30, tmp0, tmp1;
a00 = (x[0] + x[4]) >> 1; /* Re A + Re B */
@@ -168,7 +168,7 @@ static FDK_FORCEINLINE void fft_4(FIXP_DBL *x) {
#ifndef FUNCTION_fft_8
LNK_SECTION_CODE_L1
-static FDK_FORCEINLINE void fft_8(FIXP_DBL *x) {
+static inline void fft_8(FIXP_DBL *x) {
FIXP_SPK w_PiFOURTH = {{FIXP_SGL(0x5A82), FIXP_SGL(0x5A82)}};
FIXP_DBL a00, a10, a20, a30;
diff --git a/libFDK/include/nlc_dec.h b/libFDK/include/nlc_dec.h
index cca97f1..aded569 100644
--- a/libFDK/include/nlc_dec.h
+++ b/libFDK/include/nlc_dec.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -159,9 +159,6 @@ typedef enum {
#ifndef HUFFDEC_PARAMS
#define HUFFDEC_PARMS
-#define PAIR_SHIFT 4
-#define PAIR_MASK 0xf
-
#define MAX_ENTRIES 168
#define HANDLE_HUFF_NODE const SHORT(*)[MAX_ENTRIES][2]
diff --git a/libFDK/src/FDK_hybrid.cpp b/libFDK/src/FDK_hybrid.cpp
index 08d32a8..d208abd 100644
--- a/libFDK/src/FDK_hybrid.cpp
+++ b/libFDK/src/FDK_hybrid.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -539,11 +539,11 @@ static void dualChannelFiltering(const FIXP_DBL *const pQmfReal,
i6 = pQmfImag[pReadIdx[6]] >> 2;
FDK_ASSERT((invert == 0) || (invert == 1));
- mHybridReal[0 + invert] = (r6 + r1) << 1;
- mHybridImag[0 + invert] = (i6 + i1) << 1;
+ mHybridReal[0 + invert] = SATURATE_LEFT_SHIFT((r6 + r1), 1, DFRACT_BITS);
+ mHybridImag[0 + invert] = SATURATE_LEFT_SHIFT((i6 + i1), 1, DFRACT_BITS);
- mHybridReal[1 - invert] = (r6 - r1) << 1;
- mHybridImag[1 - invert] = (i6 - i1) << 1;
+ mHybridReal[1 - invert] = SATURATE_LEFT_SHIFT((r6 - r1), 1, DFRACT_BITS);
+ mHybridImag[1 - invert] = SATURATE_LEFT_SHIFT((i6 - i1), 1, DFRACT_BITS);
}
static void fourChannelFiltering(const FIXP_DBL *const pQmfReal,
@@ -766,15 +766,15 @@ static void eightChannelFiltering(const FIXP_DBL *const pQmfReal,
mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc;
mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc;
- mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc;
- mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc;
- mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc;
- mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc;
+ mHybridReal[4] = SATURATE_LEFT_SHIFT(
+ (pfft[FFT_IDX_R(2)] + pfft[FFT_IDX_R(5)]), sc, DFRACT_BITS);
+ mHybridImag[4] = SATURATE_LEFT_SHIFT(
+ (pfft[FFT_IDX_I(2)] + pfft[FFT_IDX_I(5)]), sc, DFRACT_BITS);
- mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc;
- mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc;
- mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc;
- mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc;
+ mHybridReal[5] = SATURATE_LEFT_SHIFT(
+ (pfft[FFT_IDX_R(3)] + pfft[FFT_IDX_R(4)]), sc, DFRACT_BITS);
+ mHybridImag[5] = SATURATE_LEFT_SHIFT(
+ (pfft[FFT_IDX_I(3)] + pfft[FFT_IDX_I(4)]), sc, DFRACT_BITS);
} else {
for (k = 0; k < 8; k++) {
mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc;
diff --git a/libFDK/src/autocorr2nd.cpp b/libFDK/src/autocorr2nd.cpp
index 718a555..8c5673c 100644
--- a/libFDK/src/autocorr2nd.cpp
+++ b/libFDK/src/autocorr2nd.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -102,11 +102,6 @@ amm-info@iis.fraunhofer.de
#include "autocorr2nd.h"
-/* If the accumulator does not provide enough overflow bits,
- products have to be shifted down in the autocorrelation below. */
-#define SHIFT_FACTOR (5)
-#define SHIFT >> (SHIFT_FACTOR)
-
/*!
*
* \brief Calculate second order autocorrelation using 2 accumulators
@@ -126,45 +121,49 @@ INT autoCorr2nd_real(
const FIXP_DBL *realBuf = reBuffer;
+ const int len_scale = fMax(DFRACT_BITS - fNormz((FIXP_DBL)(len / 2)), 1);
/*
r11r,r22r
r01r,r12r
r02r
*/
pReBuf = realBuf - 2;
- accu5 = ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3]))
- SHIFT);
+ accu5 =
+ ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) >>
+ len_scale);
pReBuf++;
/* len must be even */
- accu1 = fPow2Div2(pReBuf[0]) SHIFT;
- accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) SHIFT;
+ accu1 = fPow2Div2(pReBuf[0]) >> len_scale;
+ accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) >> len_scale;
pReBuf++;
for (j = (len - 2) >> 1; j != 0; j--, pReBuf += 2) {
- accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pReBuf[1])) SHIFT);
+ accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pReBuf[1])) >> len_scale);
- accu3 += ((fMultDiv2(pReBuf[0], pReBuf[1]) +
- fMultDiv2(pReBuf[1], pReBuf[2])) SHIFT);
+ accu3 +=
+ ((fMultDiv2(pReBuf[0], pReBuf[1]) + fMultDiv2(pReBuf[1], pReBuf[2])) >>
+ len_scale);
- accu5 += ((fMultDiv2(pReBuf[0], pReBuf[2]) +
- fMultDiv2(pReBuf[1], pReBuf[3])) SHIFT);
+ accu5 +=
+ ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) >>
+ len_scale);
}
- accu2 = (fPow2Div2(realBuf[-2]) SHIFT);
+ accu2 = (fPow2Div2(realBuf[-2]) >> len_scale);
accu2 += accu1;
- accu1 += (fPow2Div2(realBuf[len - 2]) SHIFT);
+ accu1 += (fPow2Div2(realBuf[len - 2]) >> len_scale);
- accu4 = (fMultDiv2(realBuf[-1], realBuf[-2]) SHIFT);
+ accu4 = (fMultDiv2(realBuf[-1], realBuf[-2]) >> len_scale);
accu4 += accu3;
- accu3 += (fMultDiv2(realBuf[len - 1], realBuf[len - 2]) SHIFT);
+ accu3 += (fMultDiv2(realBuf[len - 1], realBuf[len - 2]) >> len_scale);
mScale = CntLeadingZeros(
(accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | fAbs(accu5))) -
1;
- autoCorrScaling = mScale - 1 - SHIFT_FACTOR; /* -1 because of fMultDiv2*/
+ autoCorrScaling = mScale - 1 - len_scale; /* -1 because of fMultDiv2*/
/* Scale to common scale factor */
ac->r11r = accu1 << mScale;
@@ -190,7 +189,7 @@ INT autoCorr2nd_cplx(
const FIXP_DBL *imBuffer, /*!< Pointer to imag part of input samples */
const int len /*!< Number of input samples (should be smaller than 128) */
) {
- int j, autoCorrScaling, mScale, len_scale;
+ int j, autoCorrScaling, mScale;
FIXP_DBL accu0, accu1, accu2, accu3, accu4, accu5, accu6, accu7, accu8;
@@ -199,7 +198,7 @@ INT autoCorr2nd_cplx(
const FIXP_DBL *realBuf = reBuffer;
const FIXP_DBL *imagBuf = imBuffer;
- (len > 64) ? (len_scale = 6) : (len_scale = 5);
+ const int len_scale = fMax(DFRACT_BITS - fNormz((FIXP_DBL)len), 1);
/*
r00r,
r11r,r22r
diff --git a/libFDK/src/dct.cpp b/libFDK/src/dct.cpp
index bd26736..35507b5 100644
--- a/libFDK/src/dct.cpp
+++ b/libFDK/src/dct.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -305,9 +305,8 @@ void dct_II(
{
for (i = 0; i < M; i++) {
- tmp[i] = pDat[2 * i] >> 1; /* dit_fft expects 1 bit scaled input values */
- tmp[L - 1 - i] =
- pDat[2 * i + 1] >> 1; /* dit_fft expects 1 bit scaled input values */
+ tmp[i] = pDat[2 * i] >> 2;
+ tmp[L - 1 - i] = pDat[2 * i + 1] >> 2;
}
}
@@ -337,15 +336,14 @@ void dct_II(
a1 = ((pTmp_0[0] >> 1) + (pTmp_1[0] >> 1));
a2 = ((pTmp_0[1] >> 1) - (pTmp_1[1] >> 1));
- cplxMultDiv2(&accu3, &accu4, (a1 + accu2), -(accu1 + a2),
- sin_twiddle[i * inc]);
- pDat[L - i] = accu4;
- pDat[i] = accu3;
+ cplxMult(&accu3, &accu4, (accu1 + a2), (a1 + accu2), sin_twiddle[i * inc]);
+ pDat[L - i] = -accu3;
+ pDat[i] = accu4;
- cplxMultDiv2(&accu3, &accu4, (a1 - accu2), -(accu1 - a2),
- sin_twiddle[(M - i) * inc]);
- pDat[M + i] = accu4;
- pDat[M - i] = accu3;
+ cplxMult(&accu3, &accu4, (accu1 - a2), (a1 - accu2),
+ sin_twiddle[(M - i) * inc]);
+ pDat[M + i] = -accu3;
+ pDat[M - i] = accu4;
/* Create index helper variables for (4*i)*inc indexed equivalent values of
* short tables. */
@@ -356,12 +354,12 @@ void dct_II(
}
}
- cplxMultDiv2(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]);
+ cplxMult(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]);
pDat[L - (M / 2)] = accu2;
pDat[M / 2] = accu1;
- pDat[0] = (tmp[0] >> 1) + (tmp[1] >> 1);
- pDat[M] = fMult(((tmp[0] >> 1) - (tmp[1] >> 1)),
+ pDat[0] = tmp[0] + tmp[1];
+ pDat[M] = fMult(tmp[0] - tmp[1],
sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */
*pDat_e += 2;
diff --git a/libFDK/src/fft.cpp b/libFDK/src/fft.cpp
index 4e6fdd2..c9ee784 100644
--- a/libFDK/src/fft.cpp
+++ b/libFDK/src/fft.cpp
@@ -170,7 +170,7 @@ amm-info@iis.fraunhofer.de
/* Performs the FFT of length 2. Input vector unscaled, output vector scaled
* with factor 0.5 */
-static FDK_FORCEINLINE void fft2(FIXP_DBL *RESTRICT pDat) {
+static inline void fft2(FIXP_DBL *RESTRICT pDat) {
FIXP_DBL r1, i1;
FIXP_DBL r2, i2;
@@ -196,7 +196,7 @@ static FDK_FORCEINLINE void fft2(FIXP_DBL *RESTRICT pDat) {
#ifndef FUNCTION_fft3
/* Performs the FFT of length 3 according to the algorithm after winograd. */
-static FDK_FORCEINLINE void fft3(FIXP_DBL *RESTRICT pDat) {
+static inline void fft3(FIXP_DBL *RESTRICT pDat) {
FIXP_DBL r1, r2;
FIXP_DBL s1, s2;
FIXP_DBL pD;
@@ -233,7 +233,7 @@ static FDK_FORCEINLINE void fft3(FIXP_DBL *RESTRICT pDat) {
/* performs the FFT of length 5 according to the algorithm after winograd */
/* This version works with a prescale of 2 instead of 3 */
-static FDK_FORCEINLINE void fft5(FIXP_DBL *RESTRICT pDat) {
+static inline void fft5(FIXP_DBL *RESTRICT pDat) {
FIXP_DBL r1, r2, r3, r4;
FIXP_DBL s1, s2, s3, s4;
FIXP_DBL t;
diff --git a/libFDK/src/nlc_dec.cpp b/libFDK/src/nlc_dec.cpp
index 8b2f97d..3733d98 100644
--- a/libFDK/src/nlc_dec.cpp
+++ b/libFDK/src/nlc_dec.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -568,12 +568,12 @@ bail:
static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1,
SCHAR* out_data_2, DATA_TYPE data_type,
DIFF_TYPE diff_type_1, DIFF_TYPE diff_type_2,
- int num_val, int* cdg_scheme, int ldMode) {
+ int num_val, PAIRING* pairing_scheme, int ldMode) {
ERROR_t err = HUFFDEC_OK;
+ CODING_SCHEME coding_scheme = HUFF_1D;
DIFF_TYPE diff_type;
int i = 0;
- ULONG data = 0;
SCHAR pair_vec[28][2];
@@ -596,15 +596,13 @@ static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1,
int hufYY;
/* Coding scheme */
- data = FDKreadBits(strm, 1);
- *cdg_scheme = (data << PAIR_SHIFT);
+ coding_scheme = (CODING_SCHEME)FDKreadBits(strm, 1);
- if (*cdg_scheme >> PAIR_SHIFT == HUFF_2D) {
+ if (coding_scheme == HUFF_2D) {
if ((out_data_1 != NULL) && (out_data_2 != NULL) && (ldMode == 0)) {
- data = FDKreadBits(strm, 1);
- *cdg_scheme = (*cdg_scheme | data);
+ *pairing_scheme = (PAIRING)FDKreadBits(strm, 1);
} else {
- *cdg_scheme = (*cdg_scheme | FREQ_PAIR);
+ *pairing_scheme = FREQ_PAIR;
}
}
@@ -613,7 +611,7 @@ static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1,
hufYY2 = diff_type_2;
}
- switch (*cdg_scheme >> PAIR_SHIFT) {
+ switch (coding_scheme) {
case HUFF_1D:
p0_flag[0] = (diff_type_1 == DIFF_FREQ);
p0_flag[1] = (diff_type_2 == DIFF_FREQ);
@@ -634,7 +632,7 @@ static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1,
case HUFF_2D:
- switch (*cdg_scheme & PAIR_MASK) {
+ switch (*pairing_scheme) {
case FREQ_PAIR:
if (out_data_1 != NULL) {
@@ -843,7 +841,7 @@ ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm,
SCHAR* pDataVec[2] = {NULL, NULL};
DIFF_TYPE diff_type[2] = {DIFF_FREQ, DIFF_FREQ};
- int cdg_scheme = HUFF_1D;
+ PAIRING pairing = FREQ_PAIR;
DIRECTION direction = BACKWARDS;
switch (data_type) {
@@ -959,7 +957,7 @@ ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm,
}
/* Huffman decoding */
err = huff_decode(strm, pDataVec[0], pDataVec[1], data_type, diff_type[0],
- diff_type[1], dataBands, &cdg_scheme,
+ diff_type[1], dataBands, &pairing,
(DECODER == SAOC_DECODER));
if (err != HUFFDEC_OK) {
return HUFFDEC_NOTOK;
@@ -986,8 +984,8 @@ ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm,
}
}
- mixed_time_pair = (diff_type[0] != diff_type[1]) &&
- ((cdg_scheme & PAIR_MASK) == TIME_PAIR);
+ mixed_time_pair =
+ (diff_type[0] != diff_type[1]) && (pairing == TIME_PAIR);
if (direction == BACKWARDS) {
if (diff_type[0] == DIFF_FREQ) {
diff --git a/libMpegTPDec/include/tp_data.h b/libMpegTPDec/include/tp_data.h
index b015332..b63087a 100644
--- a/libMpegTPDec/include/tp_data.h
+++ b/libMpegTPDec/include/tp_data.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -368,7 +368,7 @@ typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *);
typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM,
const AUDIO_OBJECT_TYPE coreCodec,
const INT samplingRate, const INT frameSize,
- const INT stereoConfigIndex,
+ const INT numChannels, const INT stereoConfigIndex,
const INT coreSbrFrameLengthIndex, const INT configBytes,
const UCHAR configMode, UCHAR *configChanged);
diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp
index bb4094b..8f77017 100644
--- a/libMpegTPDec/src/tpdec_asc.cpp
+++ b/libMpegTPDec/src/tpdec_asc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -266,11 +266,118 @@ static int CProgramConfig_ReadHeightExt(CProgramConfig *pPce,
return (err);
}
+/**
+ * \brief Sanity checks for program config element.
+ * Check order of elements according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.5.1
+ *
+ * \param pPce pointer to program config element.
+ *
+ * \return 0 if successful, otherwise 1.
+ */
+static int CProgramConfig_Check(CProgramConfig *pPce) {
+ INT i;
+ INT err = 0;
+ INT numBackChannels[3] = {0};
+ INT numSideChannels[3] = {0};
+ INT numFrontChannels[3] = {0};
+ UCHAR *pCpeFront = pPce->FrontElementIsCpe;
+ UCHAR *pCpeSide = pPce->SideElementIsCpe;
+ UCHAR *pCpeBack = pPce->BackElementIsCpe;
+ UCHAR *pHeight;
+
+ pHeight = pPce->BackElementHeightInfo;
+ for (i = 0; i < pPce->NumBackChannelElements; i++) {
+ numBackChannels[*pHeight] += pPce->BackElementIsCpe[i] ? 2 : 1;
+ pHeight++;
+ }
+ pHeight = pPce->SideElementHeightInfo;
+ for (i = 0; i < pPce->NumSideChannelElements; i++) {
+ numSideChannels[*pHeight] += pPce->SideElementIsCpe[i] ? 2 : 1;
+ pHeight++;
+ }
+ pHeight = pPce->FrontElementHeightInfo;
+ for (i = 0; i < pPce->NumFrontChannelElements; i++) {
+ numFrontChannels[*pHeight] += pPce->FrontElementIsCpe[i] ? 2 : 1;
+ pHeight++;
+ }
+
+ /* 0 = normal height channels, 1 = top height channels, 2 = bottom height
+ * channels */
+ for (i = 0; i < 3; i++) {
+ /* if number of channels is odd => first element must be a SCE (front center
+ * channel) */
+ if (numFrontChannels[i] & 1) {
+ if (*pCpeFront++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ numFrontChannels[i]--;
+ }
+ while (numFrontChannels[i] > 0) {
+ /* must be CPE or paired SCE */
+ if (*pCpeFront++ == ID_SCE) {
+ if (*pCpeFront++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ numFrontChannels[i] -= 2;
+ };
+
+ /* in case that a top center surround channel (Ts) is transmitted the number
+ * of channels can be odd */
+ if (i != 1) {
+ /* number of channels must be even */
+ if (numSideChannels[i] & 1) {
+ err = 1;
+ goto bail;
+ }
+ while (numSideChannels[i] > 0) {
+ /* must be CPE or paired SCE */
+ if (*pCpeSide++ == ID_SCE) {
+ if (*pCpeSide++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ numSideChannels[i] -= 2;
+ };
+ }
+
+ while (numBackChannels[i] > 1) {
+ /* must be CPE or paired SCE */
+ if (*pCpeBack++ == ID_SCE) {
+ if (*pCpeBack++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ numBackChannels[i] -= 2;
+ };
+ /* if number of channels is odd => last element must be a SCE (back center
+ * channel) */
+ if (numBackChannels[i]) {
+ if (*pCpeBack++ == ID_CPE) {
+ err = 1;
+ goto bail;
+ }
+ }
+ }
+
+bail:
+
+ return err;
+}
+
void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
UINT alignmentAnchor) {
- int i, err = 0;
+ int i;
int commentBytes;
+ UCHAR tag, isCpe;
+ UCHAR checkElementTagSelect[3][PC_FSB_CHANNELS_MAX] = {{0}};
+ pPce->isValid = 1;
pPce->NumEffectiveChannels = 0;
pPce->NumChannels = 0;
pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4);
@@ -297,28 +404,60 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
}
for (i = 0; i < pPce->NumFrontChannelElements; i++) {
- pPce->FrontElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
- pPce->FrontElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->FrontElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+ pPce->FrontElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[isCpe][tag] == 0) {
+ checkElementTagSelect[isCpe][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
for (i = 0; i < pPce->NumSideChannelElements; i++) {
- pPce->SideElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
- pPce->SideElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->SideElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+ pPce->SideElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[isCpe][tag] == 0) {
+ checkElementTagSelect[isCpe][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
for (i = 0; i < pPce->NumBackChannelElements; i++) {
- pPce->BackElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1);
- pPce->BackElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->BackElementIsCpe[i] = isCpe = (UCHAR)FDKreadBits(bs, 1);
+ pPce->BackElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[isCpe][tag] == 0) {
+ checkElementTagSelect[isCpe][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
pPce->NumEffectiveChannels = pPce->NumChannels;
for (i = 0; i < pPce->NumLfeChannelElements; i++) {
- pPce->LfeElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4);
+ pPce->LfeElementTagSelect[i] = tag = (UCHAR)FDKreadBits(bs, 4);
pPce->NumChannels += 1;
+
+ /* Check element instance tag according to ISO/IEC 13818-7:2003(E),
+ * chapter 8.2.1.1 */
+ if (checkElementTagSelect[2][tag] == 0) {
+ checkElementTagSelect[2][tag] = 1;
+ } else {
+ pPce->isValid = 0;
+ }
}
for (i = 0; i < pPce->NumAssocDataElements; i++) {
@@ -336,7 +475,15 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
commentBytes = pPce->CommentFieldBytes;
/* Search for height info extension and read it if available */
- err = CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor);
+ if (CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor)) {
+ pPce->isValid = 0;
+ }
+
+ /* Check order of elements according to ISO / IEC 13818 - 7:2003(E),
+ * chapter 8.5.1 */
+ if (CProgramConfig_Check(pPce)) {
+ pPce->isValid = 0;
+ }
for (i = 0; i < commentBytes; i++) {
UCHAR text;
@@ -347,8 +494,6 @@ void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs,
pPce->Comment[i] = text;
}
}
-
- pPce->isValid = (err) ? 0 : 1;
}
/*
@@ -1415,7 +1560,7 @@ static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc,
cb->cbSscData, hBs, asc->m_aot,
asc->m_samplingFrequency << esc->m_sbrSamplingRate,
asc->m_samplesPerFrame << esc->m_sbrSamplingRate,
- 1, /* stereoConfigIndex */
+ asc->m_channelConfiguration, 1, /* stereoConfigIndex */
-1, /* nTimeSlots: read from bitstream */
eldExtLen, asc->configMode, &asc->SacConfigChanged);
if (ErrorStatus != TRANSPORTDEC_OK) {
@@ -1549,7 +1694,7 @@ static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement,
const AUDIO_OBJECT_TYPE aot) {
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
- int usacExtElementType = escapedValue(hBs, 4, 8, 16);
+ UINT usacExtElementType = escapedValue(hBs, 4, 8, 16);
/* recurve extension elements which are invalid for USAC */
if (aot == AOT_USAC) {
@@ -1566,7 +1711,6 @@ static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement,
}
}
- extElement->usacExtElementType = (USAC_EXT_ELEMENT_TYPE)usacExtElementType;
int usacExtElementConfigLength = escapedValue(hBs, 4, 8, 16);
extElement->usacExtElementConfigLength = (USHORT)usacExtElementConfigLength;
INT bsAnchor;
@@ -1600,8 +1744,10 @@ static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement,
}
} break;
default:
+ usacExtElementType = ID_EXT_ELE_UNKNOWN;
break;
}
+ extElement->usacExtElementType = (USAC_EXT_ELEMENT_TYPE)usacExtElementType;
/* Adjust bit stream position. This is required because of byte alignment and
* unhandled extensions. */
@@ -1630,8 +1776,12 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc,
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
int numConfigExtensions;
- int usacConfigExtType;
+ UINT usacConfigExtType;
int usacConfigExtLength;
+ int loudnessInfoSetIndex =
+ -1; /* index of loudnessInfoSet config extension. -1 if not contained. */
+ int tmp_subStreamIndex = 0;
+ AUDIO_OBJECT_TYPE tmp_aot = AOT_USAC;
numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1;
for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) {
@@ -1661,10 +1811,12 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc,
ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
cb->cbUniDrcData, hBs, usacConfigExtLength,
1, /* loudnessInfoSet */
- 0, loudnessInfoSetConfigExtensionPosition, AOT_USAC);
+ tmp_subStreamIndex, loudnessInfoSetConfigExtensionPosition,
+ tmp_aot);
if (ErrorStatus != TRANSPORTDEC_OK) {
return ErrorStatus;
}
+ loudnessInfoSetIndex = confExtIdx;
}
} break;
default:
@@ -1680,6 +1832,17 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc,
FDKpushFor(hBs, usacConfigExtLength);
}
+ if (loudnessInfoSetIndex == -1 && cb->cbUniDrc != NULL) {
+ /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding
+ * an empty config extension */
+ ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+ cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, tmp_subStreamIndex,
+ 0, tmp_aot);
+ if (ErrorStatus != TRANSPORTDEC_OK) {
+ return ErrorStatus;
+ }
+ }
+
return ErrorStatus;
}
@@ -1696,6 +1859,8 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
int channelElementIdx =
0; /* index for elements which contain audio channels (sce, cpe, lfe) */
SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0};
+ int uniDrcElement =
+ -1; /* index of uniDrc extension element. -1 if not contained. */
numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1;
usc->m_usacNumElements = numberOfElements;
@@ -1826,6 +1991,8 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
/* Mps212Config() ISO/IEC FDIS 23003-3 */
if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot,
asc->m_extensionSamplingFrequency, samplesPerFrame,
+ 1, /* only downmix channels (residual channels are
+ not counted) */
usc->element[i].m_stereoConfigIndex,
usc->m_coreSbrFrameLengthIndex,
0, /* don't know the length */
@@ -1869,6 +2036,10 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
case ID_USAC_EXT:
ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0,
asc->m_samplesPerFrame, 0, asc->m_aot);
+ if (usc->element[i].extElement.usacExtElementType ==
+ ID_EXT_ELE_UNI_DRC) {
+ uniDrcElement = i;
+ }
if (ErrorStatus) {
return ErrorStatus;
@@ -1897,6 +2068,18 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse(
}
}
+ if (uniDrcElement == -1 && cb->cbUniDrc != NULL) {
+ /* no uniDrcConfig contained. Clear the uniDrcConfig struct by feeding an
+ * empty extension element */
+ int subStreamIndex = 0;
+ ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+ cb->cbUniDrcData, NULL, 0, 0 /* uniDrcConfig */, subStreamIndex, 0,
+ asc->m_aot);
+ if (ErrorStatus != TRANSPORTDEC_OK) {
+ return ErrorStatus;
+ }
+ }
+
return ErrorStatus;
}
@@ -1983,6 +2166,14 @@ static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc,
if (err != TRANSPORTDEC_OK) {
return err;
}
+ } else if (cb->cbUniDrc != NULL) {
+ /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding
+ * an empty config extension */
+ err = (TRANSPORTDEC_ERROR)cb->cbUniDrc(
+ cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, 0, 0, asc->m_aot);
+ if (err != TRANSPORTDEC_OK) {
+ return err;
+ }
}
/* sanity check whether number of channels signaled in UsacDecoderConfig()
@@ -1995,9 +2186,11 @@ static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc,
/* Copy UsacConfig() to asc->m_sc.m_usacConfig.UsacConfig[] buffer. */
INT configSize_bits = (INT)FDKgetValidBits(hBs) - nbits;
- StoreConfigAsBitstream(hBs, configSize_bits,
- asc->m_sc.m_usacConfig.UsacConfig,
- TP_USAC_MAX_CONFIG_LEN);
+ if (StoreConfigAsBitstream(hBs, configSize_bits,
+ asc->m_sc.m_usacConfig.UsacConfig,
+ TP_USAC_MAX_CONFIG_LEN)) {
+ return TRANSPORTDEC_PARSE_ERROR;
+ }
asc->m_sc.m_usacConfig.UsacConfigBits = fAbs(configSize_bits);
return err;
@@ -2218,7 +2411,7 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse(
case AOT_MPEGS:
if (cb->cbSsc != NULL) {
if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency,
- self->m_samplesPerFrame, 1,
+ self->m_samplesPerFrame, self->m_channelConfiguration, 1,
-1, /* nTimeSlots: read from bitstream */
0, /* don't know the length */
self->configMode, &self->SacConfigChanged)) {
@@ -2299,8 +2492,10 @@ TRANSPORTDEC_ERROR AudioSpecificConfig_Parse(
/* Copy config() to asc->config[] buffer. */
if ((ErrorStatus == TRANSPORTDEC_OK) && (self->m_aot == AOT_USAC)) {
INT configSize_bits = (INT)FDKgetValidBits(bs) - (INT)ascStartAnchor;
- StoreConfigAsBitstream(bs, configSize_bits, self->config,
- TP_USAC_MAX_CONFIG_LEN);
+ if (StoreConfigAsBitstream(bs, configSize_bits, self->config,
+ TP_USAC_MAX_CONFIG_LEN)) {
+ return TRANSPORTDEC_PARSE_ERROR;
+ }
self->configBits = fAbs(configSize_bits);
}
@@ -2414,6 +2609,8 @@ static TRANSPORTDEC_ERROR Drm_xHEAACDecoderConfig(
cb->cbSscData, hBs,
AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */
asc->m_extensionSamplingFrequency, samplesPerFrame,
+ 1, /* only downmix channels (residual channels are not
+ counted) */
usc->element[elemIdx].m_stereoConfigIndex,
usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */
asc->configMode, &asc->SacConfigChanged);
diff --git a/libMpegTPDec/src/tpdec_latm.cpp b/libMpegTPDec/src/tpdec_latm.cpp
index 3b71db8..c32be54 100644
--- a/libMpegTPDec/src/tpdec_latm.cpp
+++ b/libMpegTPDec/src/tpdec_latm.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -591,6 +591,18 @@ bail:
return (ErrorStatus);
}
+static int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) {
+ int len = 0, tmp = 255;
+ int validBytes = (int)FDKgetValidBits(bs) >> 3;
+
+ while (tmp == 255 && validBytes-- > 0) {
+ tmp = (int)FDKreadBits(bs, 8);
+ len += tmp;
+ }
+
+ return ((tmp == 255) ? -1 : (len << 3));
+}
+
TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs,
CLatmDemux *pLatmDemux) {
TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK;
@@ -602,11 +614,17 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs,
FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER);
for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) {
LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay];
+ int auChunkLengthInfo = 0;
switch (p_linfo->m_frameLengthType) {
case 0:
- p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs);
- totalPayloadBits += p_linfo->m_frameLengthInBits;
+ auChunkLengthInfo = CLatmDemux_ReadAuChunkLengthInfo(bs);
+ if (auChunkLengthInfo >= 0) {
+ p_linfo->m_frameLengthInBits = (UINT)auChunkLengthInfo;
+ totalPayloadBits += p_linfo->m_frameLengthInBits;
+ } else {
+ return TRANSPORTDEC_PARSE_ERROR;
+ }
break;
case 3:
case 5:
@@ -627,23 +645,6 @@ TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs,
return (ErrorStatus);
}
-int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) {
- UCHAR endFlag;
- int len = 0;
-
- do {
- UCHAR tmp = (UCHAR)FDKreadBits(bs, 8);
- endFlag = (tmp < 255);
-
- len += tmp;
-
- } while (endFlag == 0);
-
- len <<= 3; /* convert from bytes to bits */
-
- return len;
-}
-
UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog,
const UINT layer) {
UINT nFrameLenBits = 0;
diff --git a/libMpegTPDec/src/tpdec_latm.h b/libMpegTPDec/src/tpdec_latm.h
index 6af553d..8b8c971 100644
--- a/libMpegTPDec/src/tpdec_latm.h
+++ b/libMpegTPDec/src/tpdec_latm.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -151,8 +151,6 @@ typedef struct {
AudioPreRoll */
} CLatmDemux;
-int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs);
-
TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs,
CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt,
CSTpCallBacks *pTpDecCallbacks,
diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp
index 091d011..8cd9cb0 100644
--- a/libMpegTPDec/src/tpdec_lib.cpp
+++ b/libMpegTPDec/src/tpdec_lib.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2022 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -351,6 +351,12 @@ TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp,
}
}
}
+
+ /* if an error is detected terminate config parsing to avoid that an invalid
+ * config is accepted in the second pass */
+ if (err != TRANSPORTDEC_OK) {
+ break;
+ }
}
if (err == TRANSPORTDEC_OK && fConfigFound) {
diff --git a/libMpegTPEnc/include/tp_data.h b/libMpegTPEnc/include/tp_data.h
index 00de356..464c485 100644
--- a/libMpegTPEnc/include/tp_data.h
+++ b/libMpegTPEnc/include/tp_data.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -368,7 +368,7 @@ typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *);
typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM,
const AUDIO_OBJECT_TYPE coreCodec,
const INT samplingRate, const INT frameSize,
- const INT stereoConfigIndex,
+ const INT numChannels, const INT stereoConfigIndex,
const INT coreSbrFrameLengthIndex, const INT configBytes,
const UCHAR configMode, UCHAR *configChanged);
diff --git a/libMpegTPEnc/src/tpenc_asc.cpp b/libMpegTPEnc/src/tpenc_asc.cpp
index 0b484a0..9591ba8 100644
--- a/libMpegTPEnc/src/tpenc_asc.cpp
+++ b/libMpegTPEnc/src/tpenc_asc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -795,7 +795,7 @@ static int transportEnc_writeELDSpecificConfig(HANDLE_FDK_BITSTREAM hBs,
const INT eldExtLen =
(cb->cbSsc(cb->cbSscData, NULL, config->aot, config->extSamplingRate, 0,
- 0, 0, 0, 0, NULL) +
+ 0, 0, 0, 0, 0, NULL) +
7) >>
3;
INT cnt = eldExtLen;
@@ -818,7 +818,7 @@ static int transportEnc_writeELDSpecificConfig(HANDLE_FDK_BITSTREAM hBs,
}
cb->cbSsc(cb->cbSscData, hBs, config->aot, config->extSamplingRate, 0, 0, 0,
- 0, 0, NULL);
+ 0, 0, 0, NULL);
}
if (config->downscaleSamplingRate != 0 &&
diff --git a/libPCMutils/src/limiter.cpp b/libPCMutils/src/limiter.cpp
index 598dc0c..c6b8687 100644
--- a/libPCMutils/src/limiter.cpp
+++ b/libPCMutils/src/limiter.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -322,7 +322,8 @@ TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn,
(FIXP_DBL)SATURATE_LEFT_SHIFT(tmp, scaling, DFRACT_BITS));
#else
samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT(
- tmp + ((FIXP_DBL)0x8000 >> scaling), scaling, DFRACT_BITS));
+ (tmp >> 1) + ((FIXP_DBL)0x8000 >> (scaling + 1)), scaling + 1,
+ DFRACT_BITS));
#endif
}
}
diff --git a/libPCMutils/src/pcmdmx_lib.cpp b/libPCMutils/src/pcmdmx_lib.cpp
index 534acad..fca12ce 100644
--- a/libPCMutils/src/pcmdmx_lib.cpp
+++ b/libPCMutils/src/pcmdmx_lib.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -494,13 +494,40 @@ static PCM_DMX_CHANNEL_MODE getChMode4Plain(
return plainChMode;
}
-static inline UINT getIdxSum(UCHAR numCh) {
- UINT result = 0;
- int i;
- for (i = 1; i < numCh; i += 1) {
- result += i;
+/** Validates the channel indices of all channels present in the bitstream.
+ * The channel indices have to be consecutive and unique for each audio channel
+ *type.
+ * @param [in] The total number of channels of the given configuration.
+ * @param [in] The total number of channels of the current audio channel type of
+ *the given configuration.
+ * @param [in] Audio channel type to be examined.
+ * @param [in] Array holding the corresponding channel types for each channel.
+ * @param [in] Array holding the corresponding channel type indices for each
+ *channel.
+ * @returns Returns 1 on success, returns 0 on error.
+ **/
+static UINT validateIndices(UINT numChannels, UINT numChannelsPlaneAndGrp,
+ AUDIO_CHANNEL_TYPE aChType,
+ const AUDIO_CHANNEL_TYPE channelType[],
+ const UCHAR channelIndices[]) {
+ for (UINT reqValue = 0; reqValue < numChannelsPlaneAndGrp; reqValue++) {
+ int found = FALSE;
+ for (UINT i = 0; i < numChannels; i++) {
+ if (channelType[i] == aChType) {
+ if (channelIndices[i] == reqValue) {
+ if (found == TRUE) {
+ return 0; /* Found channel index a second time */
+ } else {
+ found = TRUE; /* Found channel index */
+ }
+ }
+ }
+ }
+ if (found == FALSE) {
+ return 0; /* Did not find channel index */
+ }
}
- return result;
+ return 1; /* Successfully validated channel indices */
}
/** Evaluate a given channel configuration and extract a packed channel mode. In
@@ -523,7 +550,6 @@ static PCMDMX_ERROR getChannelMode(
UCHAR offsetTable[(8)], /* out */
PCM_DMX_CHANNEL_MODE *chMode /* out */
) {
- UINT idxSum[(3)][(4)];
UCHAR numCh[(3)][(4)];
UCHAR mapped[(8)];
PCM_DMX_SPEAKER_POSITION spkrPos[(8)];
@@ -538,7 +564,6 @@ static PCMDMX_ERROR getChannelMode(
FDK_ASSERT(chMode != NULL);
/* For details see ISO/IEC 13818-7:2005(E), 8.5.3 Channel configuration */
- FDKmemclear(idxSum, (3) * (4) * sizeof(UINT));
FDKmemclear(numCh, (3) * (4) * sizeof(UCHAR));
FDKmemclear(mapped, (8) * sizeof(UCHAR));
FDKmemclear(spkrPos, (8) * sizeof(PCM_DMX_SPEAKER_POSITION));
@@ -552,19 +577,22 @@ static PCMDMX_ERROR getChannelMode(
(channelType[ch] & 0x0F) - 1,
0); /* Assign all undefined channels (ACT_NONE) to front channels. */
numCh[channelType[ch] >> 4][chGrp] += 1;
- idxSum[channelType[ch] >> 4][chGrp] += channelIndices[ch];
}
- if (numChannels > TWO_CHANNEL) {
+
+ {
int chGrp;
/* Sanity check on the indices */
for (chGrp = 0; chGrp < (4); chGrp += 1) {
int plane;
for (plane = 0; plane < (3); plane += 1) {
- if (idxSum[plane][chGrp] != getIdxSum(numCh[plane][chGrp])) {
+ if (numCh[plane][chGrp] == 0) continue;
+ AUDIO_CHANNEL_TYPE aChType =
+ (AUDIO_CHANNEL_TYPE)((plane << 4) | ((chGrp + 1) & 0xF));
+ if (!validateIndices(numChannels, numCh[plane][chGrp], aChType,
+ channelType, channelIndices)) {
unsigned idxCnt = 0;
for (ch = 0; ch < numChannels; ch += 1) {
- if (channelType[ch] ==
- (AUDIO_CHANNEL_TYPE)((plane << 4) | ((chGrp + 1) & 0xF))) {
+ if (channelType[ch] == aChType) {
channelIndices[ch] = idxCnt++;
}
}
@@ -583,8 +611,6 @@ static PCMDMX_ERROR getChannelMode(
(channelType[ch] & 0x0F) - 1,
0); /* Assign all undefined channels (ACT_NONE) to front channels. */
- if (channelIndices[ch] >= numCh[channelType[ch] >> 4][chGrp])
- return PCMDMX_INVALID_CH_CONFIG;
spkrPos[ch] = getSpeakerPos(channelType[ch], channelIndices[ch],
numCh[channelType[ch] >> 4][chGrp]);
diff --git a/libSACdec/include/sac_dec_lib.h b/libSACdec/include/sac_dec_lib.h
index 1827504..5aad4e0 100644
--- a/libSACdec/include/sac_dec_lib.h
+++ b/libSACdec/include/sac_dec_lib.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -316,8 +316,8 @@ SACDEC_ERROR mpegSurroundDecoder_Init(
SACDEC_ERROR mpegSurroundDecoder_Config(
CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
- INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes,
- const UCHAR configMode, UCHAR *configChanged);
+ INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex,
+ INT configBytes, const UCHAR configMode, UCHAR *configChanged);
SACDEC_ERROR
mpegSurroundDecoder_ConfigureQmfDomain(
diff --git a/libSACdec/src/sac_bitdec.cpp b/libSACdec/src/sac_bitdec.cpp
index 708ddf1..25b3d9e 100644
--- a/libSACdec/src/sac_bitdec.cpp
+++ b/libSACdec/src/sac_bitdec.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -448,7 +448,6 @@ SACDEC_ERROR SpatialDecParseSpecificConfig(
int bsFreqRes, b3DaudioMode = 0;
int numHeaderBits;
int cfgStartPos, bitsAvailable;
- int treeConfig;
FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG));
@@ -489,13 +488,18 @@ SACDEC_ERROR SpatialDecParseSpecificConfig(
pSpatialSpecificConfig->freqRes =
(SPATIALDEC_FREQ_RES)freqResTable_LD[bsFreqRes];
- treeConfig = FDKreadBits(bitstream, 4);
+ {
+ UINT treeConfig = FDKreadBits(bitstream, 4);
- if (treeConfig != SPATIALDEC_MODE_RSVD7) {
- err = MPS_UNSUPPORTED_CONFIG;
- goto bail;
+ switch (treeConfig) {
+ case SPATIALDEC_MODE_RSVD7:
+ pSpatialSpecificConfig->treeConfig = (SPATIALDEC_TREE_CONFIG)treeConfig;
+ break;
+ default:
+ err = MPS_UNSUPPORTED_CONFIG;
+ goto bail;
+ }
}
- pSpatialSpecificConfig->treeConfig = (SPATIALDEC_TREE_CONFIG) treeConfig;
{
pSpatialSpecificConfig->nOttBoxes =
diff --git a/libSACdec/src/sac_dec.cpp b/libSACdec/src/sac_dec.cpp
index a7b50df..a26e251 100644
--- a/libSACdec/src/sac_dec.cpp
+++ b/libSACdec/src/sac_dec.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1098,6 +1098,28 @@ static void SpatialDecApplyBypass(spatialDec *self, FIXP_DBL **hybInputReal,
}
}
+/**
+ * \brief Set internal error and reset error status
+ *
+ * \param self spatialDec handle.
+ * \param bypassMode pointer to bypassMode.
+ * \param err error status.
+ *
+ * \return error status.
+ */
+static SACDEC_ERROR SpatialDecSetInternalError(spatialDec *self,
+ int *bypassMode,
+ SACDEC_ERROR err) {
+ *bypassMode = 1;
+
+ if (self->errInt == MPS_OK) {
+ /* store internal error before it gets overwritten */
+ self->errInt = err;
+ }
+
+ return MPS_OK;
+}
+
/*******************************************************************************
Functionname: SpatialDecApplyParameterSets
*******************************************************************************
@@ -1118,7 +1140,7 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
const FDK_channelMapDescr *const mapDescr) {
SACDEC_ERROR err = MPS_OK;
- FIXP_SGL alpha;
+ FIXP_SGL alpha = FL2FXCONST_SGL(0.0);
int ts;
int ch;
@@ -1141,20 +1163,22 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
ts++, ts_io++) {
int currSlot = frame->paramSlot[ps];
+ err = (currSlot < ts) ? MPS_WRONG_PARAMETERSETS : MPS_OK;
+ if (err != MPS_OK) {
+ err = SpatialDecSetInternalError(self, &bypassMode, err);
+ }
+
/*
* Get new parameter set
*/
if (ts == prevSlot + 1) {
- err = SpatialDecCalculateM1andM2(self, ps,
- frame); /* input: ottCLD, ottICC, ... */
- /* output: M1param(Real/Imag), M2(Real/Imag) */
- if (err != MPS_OK) {
- bypassMode = 1;
- if (self->errInt == MPS_OK) {
- /* store internal error befor it gets overwritten */
- self->errInt = err;
+ if (bypassMode == 0) {
+ err = SpatialDecCalculateM1andM2(
+ self, ps, frame); /* input: ottCLD, ottICC, ... */
+ /* output: M1param(Real/Imag), M2(Real/Imag) */
+ if (err != MPS_OK) {
+ err = SpatialDecSetInternalError(self, &bypassMode, err);
}
- err = MPS_OK;
}
if ((ps == 0) && (self->bOverwriteM1M2prev != 0)) {
@@ -1168,13 +1192,16 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
self->bOverwriteM1M2prev = 0;
}
- SpatialDecSmoothM1andM2(
- self, frame,
- ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */
- /* output: M1param(Real/Imag), M2(Real/Imag) */
+ if (bypassMode == 0) {
+ SpatialDecSmoothM1andM2(
+ self, frame,
+ ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */
+ } /* output: M1param(Real/Imag), M2(Real/Imag) */
}
- alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot));
+ if (bypassMode == 0) {
+ alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot));
+ }
switch (mode) {
case INPUTMODE_QMF_SBR:
@@ -1182,15 +1209,17 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
self->bShareDelayWithSBR = 0; /* We got no hybrid delay */
else
self->bShareDelayWithSBR = 1;
- SpatialDecFeedQMF(self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode,
- self->qmfInputReal__FDK, self->qmfInputImag__FDK,
- self->numInputChannels);
+ SpatialDecFeedQMF(
+ self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode,
+ self->qmfInputReal__FDK, self->qmfInputImag__FDK,
+ (bypassMode) ? numInputChannels : self->numInputChannels);
break;
case INPUTMODE_TIME:
self->bShareDelayWithSBR = 0;
- SpatialDecQMFAnalysis(self, inData, ts_io, bypassMode,
- self->qmfInputReal__FDK, self->qmfInputImag__FDK,
- self->numInputChannels);
+ SpatialDecQMFAnalysis(
+ self, inData, ts_io, bypassMode, self->qmfInputReal__FDK,
+ self->qmfInputImag__FDK,
+ (bypassMode) ? numInputChannels : self->numInputChannels);
break;
default:
break;
@@ -1360,7 +1389,7 @@ static SACDEC_ERROR SpatialDecApplyParameterSets(
} /* !self->tempShapeConfig == 1 */
} /* !bypassMode */
- if (self->phaseCoding == 1) {
+ if ((self->phaseCoding == 1) && (bypassMode == 0)) {
/* only if bsPhaseCoding == 1 and bsResidualCoding == 0 */
SpatialDecApplyPhase(
diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp
index 57446f8..d30131f 100644
--- a/libSACdec/src/sac_dec_lib.cpp
+++ b/libSACdec/src/sac_dec_lib.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -700,9 +700,10 @@ bail:
SACDEC_ERROR mpegSurroundDecoder_Config(
CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs,
AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize,
- INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes,
- const UCHAR configMode, UCHAR *configChanged) {
+ INT numChannels, INT stereoConfigIndex, INT coreSbrFrameLengthIndex,
+ INT configBytes, const UCHAR configMode, UCHAR *configChanged) {
SACDEC_ERROR err = MPS_OK;
+ INT nInputChannels;
SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig;
SPATIAL_SPECIFIC_CONFIG *pSsc =
&pMpegSurroundDecoder->spatialSpecificConfigBackup;
@@ -716,12 +717,18 @@ SACDEC_ERROR mpegSurroundDecoder_Config(
err = SpatialDecParseMps212Config(
hBs, &spatialSpecificConfig, samplingRate, coreCodec,
stereoConfigIndex, coreSbrFrameLengthIndex);
+ nInputChannels = spatialSpecificConfig.nInputChannels;
pSsc = &spatialSpecificConfig;
} else {
err = SpatialDecParseMps212Config(
hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
samplingRate, coreCodec, stereoConfigIndex,
coreSbrFrameLengthIndex);
+ nInputChannels =
+ pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels;
+ }
+ if ((err == MPS_OK) && (numChannels != nInputChannels)) {
+ err = MPS_PARSE_ERROR;
}
break;
case AOT_ER_AAC_ELD:
@@ -731,11 +738,19 @@ SACDEC_ERROR mpegSurroundDecoder_Config(
* into temporarily allocated structure */
err = SpatialDecParseSpecificConfig(hBs, &spatialSpecificConfig,
configBytes, coreCodec);
+ nInputChannels = spatialSpecificConfig.nInputChannels;
pSsc = &spatialSpecificConfig;
} else {
err = SpatialDecParseSpecificConfig(
hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup,
configBytes, coreCodec);
+ nInputChannels =
+ pMpegSurroundDecoder->spatialSpecificConfigBackup.nInputChannels;
+ }
+ /* check number of channels for channel_configuration > 0 */
+ if ((err == MPS_OK) && (numChannels > 0) &&
+ (numChannels != nInputChannels)) {
+ err = MPS_PARSE_ERROR;
}
break;
default:
diff --git a/libSACdec/src/sac_process.cpp b/libSACdec/src/sac_process.cpp
index 22091a9..33a1647 100644
--- a/libSACdec/src/sac_process.cpp
+++ b/libSACdec/src/sac_process.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -517,12 +517,11 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
maxVal = fAbs(iReal0) | fAbs(iImag0);
maxVal |= fAbs(iReal1);
- s = fMax(CntLeadingZeros(maxVal) - 1, 0);
- s = fMin(s, scale_param_m2);
+ s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
- mReal0 = iReal0 << s;
- mImag0 = iImag0 << s;
- mReal1 = iReal1 << s;
+ mReal0 = scaleValue(iReal0, s);
+ mImag0 = scaleValue(iImag0, s);
+ mReal1 = scaleValue(iReal1, s);
s = scale_param_m2 - s;
@@ -562,12 +561,11 @@ SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding(
maxVal = fAbs(iReal0) | fAbs(iImag0);
maxVal |= fAbs(iReal1);
- s = fMax(CntLeadingZeros(maxVal) - 1, 0);
- s = fMin(s, scale_param_m2);
+ s = fMin(CntLeadingZeros(maxVal) - 2, scale_param_m2);
- mReal0 = FX_DBL2FX_SGL(iReal0 << s);
- mImag0 = FX_DBL2FX_SGL(iImag0 << s);
- mReal1 = FX_DBL2FX_SGL(iReal1 << s);
+ mReal0 = FX_DBL2FX_SGL(scaleValue(iReal0, s));
+ mImag0 = FX_DBL2FX_SGL(scaleValue(iImag0, s));
+ mReal1 = FX_DBL2FX_SGL(scaleValue(iReal1, s));
s = scale_param_m2 - s;
diff --git a/libSACdec/src/sac_reshapeBBEnv.cpp b/libSACdec/src/sac_reshapeBBEnv.cpp
index 272d009..72f4e58 100644
--- a/libSACdec/src/sac_reshapeBBEnv.cpp
+++ b/libSACdec/src/sac_reshapeBBEnv.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -241,29 +241,56 @@ static inline void combineDryWet(FIXP_DBL *RESTRICT pReal,
}
}
-static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry,
- FIXP_DBL *RESTRICT slotAmp_wet,
- FIXP_DBL *RESTRICT pHybOutputRealDry,
- FIXP_DBL *RESTRICT pHybOutputImagDry,
- FIXP_DBL *RESTRICT pHybOutputRealWet,
- FIXP_DBL *RESTRICT pHybOutputImagWet, INT cplxBands,
- INT hybBands) {
- INT qs;
+static inline void slotAmp(
+ FIXP_DBL *RESTRICT slotAmp_dry, INT *RESTRICT slotAmp_dry_e,
+ FIXP_DBL *RESTRICT slotAmp_wet, INT *RESTRICT slotAmp_wet_e,
+ FIXP_DBL *RESTRICT pHybOutputRealDry, FIXP_DBL *RESTRICT pHybOutputImagDry,
+ FIXP_DBL *RESTRICT pHybOutputRealWet, FIXP_DBL *RESTRICT pHybOutputImagWet,
+ INT cplxBands, INT hybBands) {
+ INT qs, s1, s2, headroom_dry, headroom_wet;
FIXP_DBL dry, wet;
+ /* headroom can be reduced by 1 bit due to use of fPow2Div2 */
+ s1 = DFRACT_BITS - 1 - CntLeadingZeros(hybBands + cplxBands);
+ headroom_dry = fMin(getScalefactor(pHybOutputRealDry, hybBands),
+ getScalefactor(pHybOutputImagDry, cplxBands));
+ headroom_wet = fMin(getScalefactor(pHybOutputRealWet, hybBands),
+ getScalefactor(pHybOutputImagWet, cplxBands));
+
dry = wet = FL2FXCONST_DBL(0.0f);
for (qs = 0; qs < cplxBands; qs++) {
- dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)) +
- fPow2Div2(pHybOutputImagDry[qs] << (1)));
- wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)) +
- fPow2Div2(pHybOutputImagWet[qs] << (1)));
+ /* sum up dry part */
+ dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
+ dry += (fPow2Div2(pHybOutputImagDry[qs] << headroom_dry) >> s1);
+ /* sum up wet part */
+ wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
+ wet += (fPow2Div2(pHybOutputImagWet[qs] << headroom_wet) >> s1);
}
for (; qs < hybBands; qs++) {
- dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs] << (1)));
- wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs] << (1)));
+ dry += (fPow2Div2(pHybOutputRealDry[qs] << headroom_dry) >> s1);
+ wet += (fPow2Div2(pHybOutputRealWet[qs] << headroom_wet) >> s1);
+ }
+
+ /* consider fPow2Div2() */
+ s1 += 1;
+
+ /* normalize dry part, ensure that exponent is even */
+ s2 = fixMax(0, CntLeadingZeros(dry) - 1);
+ *slotAmp_dry = dry << s2;
+ *slotAmp_dry_e = s1 - s2 - 2 * headroom_dry;
+ if (*slotAmp_dry_e & 1) {
+ *slotAmp_dry = *slotAmp_dry >> 1;
+ *slotAmp_dry_e += 1;
+ }
+
+ /* normalize wet part, ensure that exponent is even */
+ s2 = fixMax(0, CntLeadingZeros(wet) - 1);
+ *slotAmp_wet = wet << s2;
+ *slotAmp_wet_e = s1 - s2 - 2 * headroom_wet;
+ if (*slotAmp_wet_e & 1) {
+ *slotAmp_wet = *slotAmp_wet >> 1;
+ *slotAmp_wet_e += 1;
}
- *slotAmp_dry = dry >> (2 * (1));
- *slotAmp_wet = wet >> (2 * (1));
}
#if defined(__aarch64__)
@@ -533,6 +560,7 @@ void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame,
INT ts) {
INT ch, scale;
INT dryFacSF, slotAmpSF;
+ INT slotAmp_dry_e, slotAmp_wet_e;
FIXP_DBL tmp, dryFac, envShape;
FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio;
FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2];
@@ -594,22 +622,25 @@ void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame,
dryFacSF = SF_SHAPE + 2 * dryFacSF;
}
+ slotAmp_dry_e = slotAmp_wet_e = 0;
+
/* calculate slotAmp_dry and slotAmp_wet */
- slotAmp(&slotAmp_dry, &slotAmp_wet, &self->hybOutputRealDry__FDK[ch][6],
+ slotAmp(&slotAmp_dry, &slotAmp_dry_e, &slotAmp_wet, &slotAmp_wet_e,
+ &self->hybOutputRealDry__FDK[ch][6],
&self->hybOutputImagDry__FDK[ch][6],
&self->hybOutputRealWet__FDK[ch][6],
&self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands);
+ /* exponents must be even due to subsequent square root calculation */
+ FDK_ASSERT(((slotAmp_dry_e & 1) == 0) && ((slotAmp_wet_e & 1) == 0));
+
/* slotAmp_ratio will be scaled by slotAmpSF bits */
if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) {
- sc = fixMax(0, CntLeadingZeros(slotAmp_wet) - 1);
- sc = sc - (sc & 1);
-
- slotAmp_wet = sqrtFixp(slotAmp_wet << sc);
+ slotAmp_wet = sqrtFixp(slotAmp_wet);
slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF);
slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry);
- slotAmpSF = slotAmpSF - (sc >> 1);
+ slotAmpSF = slotAmpSF + (slotAmp_wet_e >> 1) - (slotAmp_dry_e >> 1);
}
/* calculate common scale factor */
diff --git a/libSACdec/src/sac_stp.cpp b/libSACdec/src/sac_stp.cpp
index bb66277..0e6affa 100644
--- a/libSACdec/src/sac_stp.cpp
+++ b/libSACdec/src/sac_stp.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -229,15 +229,13 @@ inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry,
int n;
FIXP_DBL scaleY;
for (n = bands - 1; n >= 0; n--) {
- scaleY = fMultDiv2(scaleX, *pBP);
+ scaleY = fMult(scaleX, *pBP);
*hybOutputRealDry = SATURATE_LEFT_SHIFT(
- (*hybOutputRealDry >> 1) +
- (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 1)),
- 1, DFRACT_BITS);
+ (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleY),
+ SF_SCALE, DFRACT_BITS);
*hybOutputImagDry = SATURATE_LEFT_SHIFT(
- (*hybOutputImagDry >> 1) +
- (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 1)),
- 1, DFRACT_BITS);
+ (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleY),
+ SF_SCALE, DFRACT_BITS);
hybOutputRealDry++, hybOutputRealWet++;
hybOutputImagDry++, hybOutputImagWet++;
pBP++;
@@ -252,12 +250,12 @@ inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry,
int n;
for (n = bands - 1; n >= 0; n--) {
- *hybOutputRealDry =
- *hybOutputRealDry +
- (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1));
- *hybOutputImagDry =
- *hybOutputImagDry +
- (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1));
+ *hybOutputRealDry = SATURATE_LEFT_SHIFT(
+ (*hybOutputRealDry >> SF_SCALE) + fMult(*hybOutputRealWet, scaleX),
+ SF_SCALE, DFRACT_BITS);
+ *hybOutputImagDry = SATURATE_LEFT_SHIFT(
+ (*hybOutputImagDry >> SF_SCALE) + fMult(*hybOutputImagWet, scaleX),
+ SF_SCALE, DFRACT_BITS);
hybOutputRealDry++, hybOutputRealWet++;
hybOutputImagDry++, hybOutputImagWet++;
}
@@ -369,15 +367,15 @@ SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) {
hStpDec->update_old_ener = 1;
for (ch = 0; ch < self->numInputChannels; ch++) {
hStpDec->oldDryEnerLD64[ch] =
- CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK);
+ CalcLdData(fAddSaturate(hStpDec->runDryEner[ch], ABS_THR__FDK));
}
for (ch = 0; ch < self->numOutputChannels; ch++) {
if (self->treeConfig == TREE_212)
hStpDec->oldWetEnerLD64[ch] =
- CalcLdData(hStpDec->runWetEner[ch] + ABS_THR__FDK);
+ CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR__FDK));
else
hStpDec->oldWetEnerLD64[ch] =
- CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK);
+ CalcLdData(fAddSaturate(hStpDec->runWetEner[ch], ABS_THR2__FDK));
}
} else {
hStpDec->update_old_ener++;
diff --git a/libSBRdec/src/arm/lpp_tran_arm.cpp b/libSBRdec/src/arm/lpp_tran_arm.cpp
deleted file mode 100644
index db1948f..0000000
--- a/libSBRdec/src/arm/lpp_tran_arm.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -----------------------------------------------------------------------------
-Software License for The Fraunhofer FDK AAC Codec Library for Android
-
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
-Forschung e.V. All rights reserved.
-
- 1. INTRODUCTION
-The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
-that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
-scheme for digital audio. This FDK AAC Codec software is intended to be used on
-a wide variety of Android devices.
-
-AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
-general perceptual audio codecs. AAC-ELD is considered the best-performing
-full-bandwidth communications codec by independent studies and is widely
-deployed. AAC has been standardized by ISO and IEC as part of the MPEG
-specifications.
-
-Patent licenses for necessary patent claims for the FDK AAC Codec (including
-those of Fraunhofer) may be obtained through Via Licensing
-(www.vialicensing.com) or through the respective patent owners individually for
-the purpose of encoding or decoding bit streams in products that are compliant
-with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
-Android devices already license these patent claims through Via Licensing or
-directly from the patent owners, and therefore FDK AAC Codec software may
-already be covered under those patent licenses when it is used for those
-licensed purposes only.
-
-Commercially-licensed AAC software libraries, including floating-point versions
-with enhanced sound quality, are also available from Fraunhofer. Users are
-encouraged to check the Fraunhofer website for additional applications
-information and documentation.
-
-2. COPYRIGHT LICENSE
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted without payment of copyright license fees provided that you
-satisfy the following conditions:
-
-You must retain the complete text of this software license in redistributions of
-the FDK AAC Codec or your modifications thereto in source code form.
-
-You must retain the complete text of this software license in the documentation
-and/or other materials provided with redistributions of the FDK AAC Codec or
-your modifications thereto in binary form. You must make available free of
-charge copies of the complete source code of the FDK AAC Codec and your
-modifications thereto to recipients of copies in binary form.
-
-The name of Fraunhofer may not be used to endorse or promote products derived
-from this library without prior written permission.
-
-You may not charge copyright license fees for anyone to use, copy or distribute
-the FDK AAC Codec software or your modifications thereto.
-
-Your modified versions of the FDK AAC Codec must carry prominent notices stating
-that you changed the software and the date of any change. For modified versions
-of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
-must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
-AAC Codec Library for Android."
-
-3. NO PATENT LICENSE
-
-NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
-limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
-Fraunhofer provides no warranty of patent non-infringement with respect to this
-software.
-
-You may use this FDK AAC Codec software or modifications thereto only for
-purposes that are authorized by appropriate patent licenses.
-
-4. DISCLAIMER
-
-This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
-holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
-including but not limited to the implied warranties of merchantability and
-fitness for a particular purpose. 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), arising in any way out of the use of
-this software, even if advised of the possibility of such damage.
-
-5. CONTACT INFORMATION
-
-Fraunhofer Institute for Integrated Circuits IIS
-Attention: Audio and Multimedia Departments - FDK AAC LL
-Am Wolfsmantel 33
-91058 Erlangen, Germany
-
-www.iis.fraunhofer.de/amm
-amm-info@iis.fraunhofer.de
------------------------------------------------------------------------------ */
-
-/**************************** SBR decoder library ******************************
-
- Author(s): Arthur Tritthart
-
- Description: (ARM optimised) LPP transposer subroutines
-
-*******************************************************************************/
-
-#if defined(__arm__)
-
-#define FUNCTION_LPPTRANSPOSER_func1
-
-#ifdef FUNCTION_LPPTRANSPOSER_func1
-
-/* Note: This code requires only 43 cycles per iteration instead of 61 on
- * ARM926EJ-S */
-static void lppTransposer_func1(FIXP_DBL *lowBandReal, FIXP_DBL *lowBandImag,
- FIXP_DBL **qmfBufferReal,
- FIXP_DBL **qmfBufferImag, int loops, int hiBand,
- int dynamicScale, int descale, FIXP_SGL a0r,
- FIXP_SGL a0i, FIXP_SGL a1r, FIXP_SGL a1i,
- const int fPreWhitening,
- FIXP_DBL preWhiteningGain,
- int preWhiteningGains_sf) {
- FIXP_DBL real1, real2, imag1, imag2, accu1, accu2;
-
- real2 = lowBandReal[-2];
- real1 = lowBandReal[-1];
- imag2 = lowBandImag[-2];
- imag1 = lowBandImag[-1];
- for (int i = 0; i < loops; i++) {
- accu1 = fMultDiv2(a0r, real1);
- accu2 = fMultDiv2(a0i, imag1);
- accu1 = fMultAddDiv2(accu1, a1r, real2);
- accu2 = fMultAddDiv2(accu2, a1i, imag2);
- real2 = fMultDiv2(a1i, real2);
- accu1 = accu1 - accu2;
- accu1 = accu1 >> dynamicScale;
-
- accu2 = fMultAddDiv2(real2, a1r, imag2);
- real2 = real1;
- imag2 = imag1;
- accu2 = fMultAddDiv2(accu2, a0i, real1);
- real1 = lowBandReal[i];
- accu2 = fMultAddDiv2(accu2, a0r, imag1);
- imag1 = lowBandImag[i];
- accu2 = accu2 >> dynamicScale;
-
- accu1 <<= 1;
- accu2 <<= 1;
- accu1 += (real1 >> descale);
- accu2 += (imag1 >> descale);
- if (fPreWhitening) {
- accu1 = scaleValueSaturate(fMultDiv2(accu1, preWhiteningGain),
- preWhiteningGains_sf);
- accu2 = scaleValueSaturate(fMultDiv2(accu2, preWhiteningGain),
- preWhiteningGains_sf);
- }
- qmfBufferReal[i][hiBand] = accu1;
- qmfBufferImag[i][hiBand] = accu2;
- }
-}
-#endif /* #ifdef FUNCTION_LPPTRANSPOSER_func1 */
-
-#endif /* __arm__ */
diff --git a/libSBRdec/src/env_calc.cpp b/libSBRdec/src/env_calc.cpp
index 0b2f651..cefa612 100644
--- a/libSBRdec/src/env_calc.cpp
+++ b/libSBRdec/src/env_calc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -664,7 +664,7 @@ static void apply_inter_tes(FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
gain_sf[i] = mult_sf - total_power_low_sf + sf2;
gain[i] = sqrtFixp_lookup(gain[i], &gain_sf[i]);
if (gain_sf[i] < 0) {
- gain[i] >>= -gain_sf[i];
+ gain[i] >>= fMin(DFRACT_BITS - 1, -gain_sf[i]);
gain_sf[i] = 0;
}
} else {
@@ -683,11 +683,6 @@ static void apply_inter_tes(FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
/* gain[i] = g_inter[i] */
for (i = 0; i < nbSubsample; ++i) {
- if (gain_sf[i] < 0) {
- gain[i] >>= -gain_sf[i];
- gain_sf[i] = 0;
- }
-
/* calculate: gain[i] = 1.0f + gamma * (gain[i] - 1.0f); */
FIXP_DBL one = (FIXP_DBL)MAXVAL_DBL >>
gain_sf[i]; /* to substract this from gain[i] */
@@ -755,23 +750,15 @@ static void apply_inter_tes(FIXP_DBL **qmfReal, FIXP_DBL **qmfImag,
int gain_adj_sf = gain_adj_2_sf;
for (i = 0; i < nbSubsample; ++i) {
- gain[i] = fMult(gain[i], gain_adj);
- gain_sf[i] += gain_adj_sf;
-
- /* limit gain */
- if (gain_sf[i] > INTER_TES_SF_CHANGE) {
- gain[i] = (FIXP_DBL)MAXVAL_DBL;
- gain_sf[i] = INTER_TES_SF_CHANGE;
- }
- }
-
- for (i = 0; i < nbSubsample; ++i) {
- /* equalize gain[]'s scale factors */
- gain[i] >>= INTER_TES_SF_CHANGE - gain_sf[i];
+ int gain_e = fMax(
+ fMin(gain_sf[i] + gain_adj_sf - INTER_TES_SF_CHANGE, DFRACT_BITS - 1),
+ -(DFRACT_BITS - 1));
+ FIXP_DBL gain_final = fMult(gain[i], gain_adj);
+ gain_final = scaleValueSaturate(gain_final, gain_e);
for (j = lowSubband; j < highSubband; j++) {
- qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain[i]);
- qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain[i]);
+ qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain_final);
+ qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain_final);
}
}
} else { /* gamma_idx == 0 */
@@ -1398,6 +1385,17 @@ void calculateSbrEnvelope(
*/
noise_e = (start_pos < no_cols) ? adj_e : final_e;
+ if (start_pos >= no_cols) {
+ int diff = h_sbr_cal_env->filtBufferNoise_e - noise_e;
+ if (diff > 0) {
+ int s = getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands);
+ if (diff > s) {
+ final_e += diff - s;
+ noise_e = final_e;
+ }
+ }
+ }
+
/*
Convert energies to amplitude levels
*/
@@ -2741,6 +2739,9 @@ static void adjustTimeSlotHQ_GainAndNoise(
fMult(direct_ratio, noiseLevel[k]);
}
+ smoothedNoise = fMax(fMin(smoothedNoise, (FIXP_DBL)(MAXVAL_DBL / 2)),
+ (FIXP_DBL)(MINVAL_DBL / 2));
+
/*
The next 2 multiplications constitute the actual envelope adjustment
of the signal and should be carried out with full accuracy
@@ -2930,6 +2931,9 @@ static void adjustTimeSlotHQ(
fMult(direct_ratio, noiseLevel[k]);
}
+ smoothedNoise = fMax(fMin(smoothedNoise, (FIXP_DBL)(MAXVAL_DBL / 2)),
+ (FIXP_DBL)(MINVAL_DBL / 2));
+
/*
The next 2 multiplications constitute the actual envelope adjustment
of the signal and should be carried out with full accuracy
diff --git a/libSBRdec/src/hbe.cpp b/libSBRdec/src/hbe.cpp
index 77cb8af..9485823 100644
--- a/libSBRdec/src/hbe.cpp
+++ b/libSBRdec/src/hbe.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1400,42 +1400,27 @@ void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer,
if (shift_ov != 0) {
for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) {
- for (band = 0; band < QMF_SYNTH_CHANNELS; band++) {
- if (shift_ov >= 0) {
- hQmfTransposer->qmfHBEBufReal_F[i][band] <<= shift_ov;
- hQmfTransposer->qmfHBEBufImag_F[i][band] <<= shift_ov;
- } else {
- hQmfTransposer->qmfHBEBufReal_F[i][band] >>= (-shift_ov);
- hQmfTransposer->qmfHBEBufImag_F[i][band] >>= (-shift_ov);
- }
- }
+ scaleValuesSaturate(&hQmfTransposer->qmfHBEBufReal_F[i][0],
+ QMF_SYNTH_CHANNELS, shift_ov);
+ scaleValuesSaturate(&hQmfTransposer->qmfHBEBufImag_F[i][0],
+ QMF_SYNTH_CHANNELS, shift_ov);
}
- }
- if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) && shift_ov != 0) {
- for (i = timeStep * firstSlotOffsset; i < ov_len; i++) {
- for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand;
- band++) {
- if (shift_ov >= 0) {
- ppQmfBufferOutReal_F[i][band] <<= shift_ov;
- ppQmfBufferOutImag_F[i][band] <<= shift_ov;
- } else {
- ppQmfBufferOutReal_F[i][band] >>= (-shift_ov);
- ppQmfBufferOutImag_F[i][band] >>= (-shift_ov);
- }
+ if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) {
+ int nBands =
+ fMax(0, hQmfTransposer->stopBand - hQmfTransposer->startBand);
+
+ for (i = timeStep * firstSlotOffsset; i < ov_len; i++) {
+ scaleValuesSaturate(&ppQmfBufferOutReal_F[i][hQmfTransposer->startBand],
+ nBands, shift_ov);
+ scaleValuesSaturate(&ppQmfBufferOutImag_F[i][hQmfTransposer->startBand],
+ nBands, shift_ov);
}
- }
- /* shift lpc filterstates */
- for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) {
- for (band = 0; band < (64); band++) {
- if (shift_ov >= 0) {
- lpcFilterStatesReal[i][band] <<= shift_ov;
- lpcFilterStatesImag[i][band] <<= shift_ov;
- } else {
- lpcFilterStatesReal[i][band] >>= (-shift_ov);
- lpcFilterStatesImag[i][band] >>= (-shift_ov);
- }
+ /* shift lpc filterstates */
+ for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) {
+ scaleValuesSaturate(&lpcFilterStatesReal[i][0], (64), shift_ov);
+ scaleValuesSaturate(&lpcFilterStatesImag[i][0], (64), shift_ov);
}
}
}
diff --git a/libSBRdec/src/lpp_tran.cpp b/libSBRdec/src/lpp_tran.cpp
index 93e1158..68a25bf 100644
--- a/libSBRdec/src/lpp_tran.cpp
+++ b/libSBRdec/src/lpp_tran.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -132,10 +132,6 @@ amm-info@iis.fraunhofer.de
#include "HFgen_preFlat.h"
-#if defined(__arm__)
-#include "arm/lpp_tran_arm.cpp"
-#endif
-
#define LPC_SCALE_FACTOR 2
/*!
@@ -220,19 +216,21 @@ static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal,
const FIXP_DBL *const lowBandReal,
const int startSample,
const int stopSample, const UCHAR hiBand,
- const int dynamicScale, const int descale,
+ const int dynamicScale,
const FIXP_SGL a0r, const FIXP_SGL a1r) {
- FIXP_DBL accu1, accu2;
- int i;
+ const int dynscale = fixMax(0, dynamicScale - 1) + 1;
+ const int rescale = -fixMin(0, dynamicScale - 1) + 1;
+ const int descale =
+ fixMin(DFRACT_BITS - 1, LPC_SCALE_FACTOR + dynamicScale + rescale);
+
+ for (int i = 0; i < stopSample - startSample; i++) {
+ FIXP_DBL accu;
- for (i = 0; i < stopSample - startSample; i++) {
- accu1 = fMultDiv2(a1r, lowBandReal[i]);
- accu1 = (fMultDiv2(a0r, lowBandReal[i + 1]) + accu1);
- accu1 = accu1 >> dynamicScale;
+ accu = fMultDiv2(a1r, lowBandReal[i]) + fMultDiv2(a0r, lowBandReal[i + 1]);
+ accu = (lowBandReal[i + 2] >> descale) + (accu >> dynscale);
- accu1 <<= 1;
- accu2 = (lowBandReal[i + 2] >> descale);
- qmfBufferReal[i + startSample][hiBand] = accu1 + accu2;
+ qmfBufferReal[i + startSample][hiBand] =
+ SATURATE_LEFT_SHIFT(accu, rescale, DFRACT_BITS);
}
}
@@ -529,7 +527,7 @@ void lppTransposer(
if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
resetLPCCoeffs = 1;
} else {
- alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
alphar[1] = -alphar[1];
}
@@ -557,7 +555,7 @@ void lppTransposer(
scale)) {
resetLPCCoeffs = 1;
} else {
- alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
alphai[1] = -alphai[1];
}
@@ -596,7 +594,7 @@ void lppTransposer(
} else {
INT scale;
FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
- alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+ alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
alphar[0] = -alphar[0];
@@ -616,7 +614,7 @@ void lppTransposer(
} else {
INT scale;
FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
- alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+ alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
alphai[0] = -alphai[0];
}
@@ -659,7 +657,7 @@ void lppTransposer(
INT scale;
FIXP_DBL result =
fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale);
- k1 = scaleValue(result, scale);
+ k1 = scaleValueSaturate(result, scale);
if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) {
k1 = -k1;
@@ -771,52 +769,50 @@ void lppTransposer(
} else { /* bw <= 0 */
if (!useLP) {
- int descale =
- fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale));
-#ifdef FUNCTION_LPPTRANSPOSER_func1
- lppTransposer_func1(
- lowBandReal + LPC_ORDER + startSample,
- lowBandImag + LPC_ORDER + startSample,
- qmfBufferReal + startSample, qmfBufferImag + startSample,
- stopSample - startSample, (int)hiBand, dynamicScale, descale, a0r,
- a0i, a1r, a1i, fPreWhitening, preWhiteningGains[loBand],
- preWhiteningGains_exp[loBand] + 1);
-#else
+ const int dynscale = fixMax(0, dynamicScale - 2) + 1;
+ const int rescale = -fixMin(0, dynamicScale - 2) + 1;
+ const int descale = fixMin(DFRACT_BITS - 1,
+ LPC_SCALE_FACTOR + dynamicScale + rescale);
+
for (i = startSample; i < stopSample; i++) {
FIXP_DBL accu1, accu2;
- accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
- fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) +
- fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
- fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
- dynamicScale;
- accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
- fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) +
- fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
- fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
- dynamicScale;
-
- accu1 = (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1);
- accu2 = (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1);
+ accu1 = ((fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) -
+ fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1])) >>
+ 1) +
+ ((fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) -
+ fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >>
+ 1);
+ accu2 = ((fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) +
+ fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1])) >>
+ 1) +
+ ((fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) +
+ fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >>
+ 1);
+
+ accu1 =
+ (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 >> dynscale);
+ accu2 =
+ (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 >> dynscale);
if (fPreWhitening) {
- accu1 = scaleValueSaturate(
+ qmfBufferReal[i][hiBand] = scaleValueSaturate(
fMultDiv2(accu1, preWhiteningGains[loBand]),
- preWhiteningGains_exp[loBand] + 1);
- accu2 = scaleValueSaturate(
+ preWhiteningGains_exp[loBand] + 1 + rescale);
+ qmfBufferImag[i][hiBand] = scaleValueSaturate(
fMultDiv2(accu2, preWhiteningGains[loBand]),
- preWhiteningGains_exp[loBand] + 1);
+ preWhiteningGains_exp[loBand] + 1 + rescale);
+ } else {
+ qmfBufferReal[i][hiBand] =
+ SATURATE_LEFT_SHIFT(accu1, rescale, DFRACT_BITS);
+ qmfBufferImag[i][hiBand] =
+ SATURATE_LEFT_SHIFT(accu2, rescale, DFRACT_BITS);
}
- qmfBufferReal[i][hiBand] = accu1;
- qmfBufferImag[i][hiBand] = accu2;
}
-#endif
} else {
FDK_ASSERT(dynamicScale >= 0);
calc_qmfBufferReal(
qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]),
- startSample, stopSample, hiBand, dynamicScale,
- fMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)), a0r,
- a1r);
+ startSample, stopSample, hiBand, dynamicScale, a0r, a1r);
}
} /* bw <= 0 */
@@ -1066,7 +1062,7 @@ void lppTransposerHBE(
if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) {
resetLPCCoeffs = 1;
} else {
- alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ alphar[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
alphar[1] = -alphar[1];
}
@@ -1092,7 +1088,7 @@ void lppTransposerHBE(
(result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) {
resetLPCCoeffs = 1;
} else {
- alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale));
+ alphai[1] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale));
if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) {
alphai[1] = -alphai[1];
}
@@ -1121,7 +1117,7 @@ void lppTransposerHBE(
} else {
INT scale;
FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
- alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+ alphar[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))
alphar[0] = -alphar[0];
@@ -1140,7 +1136,7 @@ void lppTransposerHBE(
} else {
INT scale;
FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale);
- alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1));
+ alphai[0] = FX_DBL2FX_SGL(scaleValueSaturate(result, scale + 1));
if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) {
alphai[0] = -alphai[0];
}
diff --git a/libSBRdec/src/lpp_tran.h b/libSBRdec/src/lpp_tran.h
index 51b4395..21c4101 100644
--- a/libSBRdec/src/lpp_tran.h
+++ b/libSBRdec/src/lpp_tran.h
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2023 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -207,7 +207,7 @@ typedef struct {
inverse filtering levels */
PATCH_PARAM
- patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */
+ patchParam[MAX_NUM_PATCHES + 1]; /*!< new parameter set for patching */
WHITENING_FACTORS
whFactors; /*!< the pole moving factors for certain
whitening levels as indicated in the bitstream
diff --git a/libSBRdec/src/sbr_dec.cpp b/libSBRdec/src/sbr_dec.cpp
index b1fb0da..919e9bb 100644
--- a/libSBRdec/src/sbr_dec.cpp
+++ b/libSBRdec/src/sbr_dec.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -713,7 +713,8 @@ void sbr_dec(
} else { /* (flags & SBRDEC_PS_DECODED) */
INT sdiff;
- INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov;
+ INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov,
+ outScalefactor, outScalefactorR, outScalefactorL;
HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb;
HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb;
@@ -744,7 +745,7 @@ void sbr_dec(
*/
FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <=
QMF_MAX_SYNTHESIS_BANDS);
- qmfChangeOutScalefactor(synQmfRight, -(8));
+ synQmfRight->outScalefactor = synQmf->outScalefactor;
FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates,
9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis *
sizeof(FIXP_QSS));
@@ -788,9 +789,11 @@ void sbr_dec(
FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel,
sizeof(SBRDEC_DRC_CHANNEL));
- for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */
+ outScalefactor = maxShift - (8);
+ outScalefactorL = outScalefactorR =
+ sbrInDataHeadroom + 1; /* +1: psDiffScale! (MPEG-PS) */
- INT outScalefactorR, outScalefactorL;
+ for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */
/* qmf timeslot of right channel */
FIXP_DBL *rQmfReal = pWorkBuffer;
@@ -815,27 +818,20 @@ void sbr_dec(
? scaleFactorLowBand_ov
: scaleFactorLowBand_no_ov,
scaleFactorHighBand, synQmf->lsb, synQmf->usb);
-
- outScalefactorL = outScalefactorR =
- 1 + sbrInDataHeadroom; /* psDiffScale! (MPEG-PS) */
}
sbrDecoder_drcApplySlot(/* right channel */
&hSbrDecRight->sbrDrcChannel, rQmfReal,
rQmfImag, i, synQmfRight->no_col, maxShift);
- outScalefactorR += maxShift;
-
sbrDecoder_drcApplySlot(/* left channel */
&hSbrDec->sbrDrcChannel, *(pLowBandReal + i),
*(pLowBandImag + i), i, synQmf->no_col,
maxShift);
- outScalefactorL += maxShift;
-
if (!(flags & SBRDEC_SKIP_QMF_SYN)) {
- qmfChangeOutScalefactor(synQmf, -(8));
- qmfChangeOutScalefactor(synQmfRight, -(8));
+ qmfChangeOutScalefactor(synQmf, outScalefactor);
+ qmfChangeOutScalefactor(synQmfRight, outScalefactor);
qmfSynthesisFilteringSlot(
synQmfRight, rQmfReal, /* QMF real buffer */
diff --git a/libSBRdec/src/sbrdec_drc.cpp b/libSBRdec/src/sbrdec_drc.cpp
index 2d73f32..089d046 100644
--- a/libSBRdec/src/sbrdec_drc.cpp
+++ b/libSBRdec/src/sbrdec_drc.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -233,14 +233,19 @@ void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData,
if (hDrcData->winSequenceCurr != 2) { /* long window */
int j = col + (numQmfSubSamples >> 1);
- if (hDrcData->drcInterpolationSchemeCurr == 0) {
- INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
+ if (j < winBorderToColMap[15]) {
+ if (hDrcData->drcInterpolationSchemeCurr == 0) {
+ INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
- alphaValue = (FIXP_DBL)(j * k);
- } else {
- if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) {
- alphaValue = (FIXP_DBL)MAXVAL_DBL;
+ alphaValue = (FIXP_DBL)(j * k);
+ } else {
+ if (j >=
+ (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) {
+ alphaValue = (FIXP_DBL)MAXVAL_DBL;
+ }
}
+ } else {
+ alphaValue = (FIXP_DBL)MAXVAL_DBL;
}
} else { /* short windows */
shortDrc = 1;
@@ -254,14 +259,19 @@ void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData,
if (hDrcData->winSequenceNext != 2) { /* next: long window */
int j = col - (numQmfSubSamples >> 1);
- if (hDrcData->drcInterpolationSchemeNext == 0) {
- INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
+ if (j < winBorderToColMap[15]) {
+ if (hDrcData->drcInterpolationSchemeNext == 0) {
+ INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
- alphaValue = (FIXP_DBL)(j * k);
- } else {
- if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
- alphaValue = (FIXP_DBL)MAXVAL_DBL;
+ alphaValue = (FIXP_DBL)(j * k);
+ } else {
+ if (j >=
+ (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
+ alphaValue = (FIXP_DBL)MAXVAL_DBL;
+ }
}
+ } else {
+ alphaValue = (FIXP_DBL)MAXVAL_DBL;
}
fact_mag = hDrcData->nextFact_mag;
@@ -289,14 +299,19 @@ void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData,
if (hDrcData->winSequenceNext != 2) { /* long window */
int j = col - (numQmfSubSamples >> 1);
- if (hDrcData->drcInterpolationSchemeNext == 0) {
- INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
+ if (j < winBorderToColMap[15]) {
+ if (hDrcData->drcInterpolationSchemeNext == 0) {
+ INT k = (frameLenFlag) ? 0x4444445 : 0x4000000;
- alphaValue = (FIXP_DBL)(j * k);
- } else {
- if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
- alphaValue = (FIXP_DBL)MAXVAL_DBL;
+ alphaValue = (FIXP_DBL)(j * k);
+ } else {
+ if (j >=
+ (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) {
+ alphaValue = (FIXP_DBL)MAXVAL_DBL;
+ }
}
+ } else {
+ alphaValue = (FIXP_DBL)MAXVAL_DBL;
}
} else { /* short windows */
shortDrc = 1;
diff --git a/libSBRdec/src/sbrdec_freq_sca.cpp b/libSBRdec/src/sbrdec_freq_sca.cpp
index e187656..daa3554 100644
--- a/libSBRdec/src/sbrdec_freq_sca.cpp
+++ b/libSBRdec/src/sbrdec_freq_sca.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -765,9 +765,6 @@ resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) {
sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1],
nBandsHi);
- hFreq->nSfb[0] = nBandsLo;
- hFreq->nSfb[1] = nBandsHi;
-
/* Check index to freqBandTable[0] */
if (!(nBandsLo > 0) ||
(nBandsLo > (((hHeaderData->numberOfAnalysisBands == 16)
@@ -777,6 +774,9 @@ resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) {
return SBRDEC_UNSUPPORTED_CONFIG;
}
+ hFreq->nSfb[0] = nBandsLo;
+ hFreq->nSfb[1] = nBandsHi;
+
lsb = hFreq->freqBandTable[0][0];
usb = hFreq->freqBandTable[0][nBandsLo];
@@ -814,15 +814,15 @@ resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) {
if (intTemp == 0) intTemp = 1;
+ if (intTemp > MAX_NOISE_COEFFS) {
+ return SBRDEC_UNSUPPORTED_CONFIG;
+ }
+
hFreq->nNfb = intTemp;
}
hFreq->nInvfBands = hFreq->nNfb;
- if (hFreq->nNfb > MAX_NOISE_COEFFS) {
- return SBRDEC_UNSUPPORTED_CONFIG;
- }
-
/* Get noise bands */
sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, hFreq->nNfb,
hFreq->freqBandTable[0], nBandsLo);
diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp
index b101a4a..7718695 100644
--- a/libSBRdec/src/sbrdecoder.cpp
+++ b/libSBRdec/src/sbrdecoder.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2021 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -961,8 +961,10 @@ SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param,
/* Set sync state UPSAMPLING for the corresponding slot.
This switches off bitstream parsing until a new header arrives. */
- hSbrHeader->syncState = UPSAMPLING;
- hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
+ if (hSbrHeader->syncState != SBR_NOT_INITIALIZED) {
+ hSbrHeader->syncState = UPSAMPLING;
+ hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE;
+ }
}
}
} break;
@@ -1371,7 +1373,9 @@ SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs,
}
if (headerStatus == HEADER_ERROR) {
/* Corrupt SBR info data, do not decode and switch to UPSAMPLING */
- hSbrHeader->syncState = UPSAMPLING;
+ hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING
+ ? UPSAMPLING
+ : hSbrHeader->syncState;
fDoDecodeSbrData = 0;
sbrHeaderPresent = 0;
}
@@ -1610,7 +1614,9 @@ static SBR_ERROR sbrDecoder_DecodeElement(
/* No valid SBR payload available, hence switch to upsampling (in all
* headers) */
for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) {
- self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
+ if (self->sbrHeader[elementIndex][hdrIdx].syncState > UPSAMPLING) {
+ self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING;
+ }
}
} else {
/* Move frame pointer to the next slot which is up to be decoded/applied
diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp
index 4af561b..3936d88 100644
--- a/libSBRenc/src/env_est.cpp
+++ b/libSBRenc/src/env_est.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -637,8 +637,8 @@ static FIXP_DBL getEnvSfbEnergy(
for (; l < stop_pos; l++) {
nrg2 += YBuffer[l >> YBufferSzShift][k] >> sc1;
}
- accu1 += (nrg1 >> dynScale1);
- accu2 += (nrg2 >> dynScale2);
+ accu1 = fAddSaturate(accu1, (nrg1 >> dynScale1));
+ accu2 = fAddSaturate(accu2, (nrg2 >> dynScale2));
}
/* This shift factor is always positive. See comment above. */
nrgSum +=
@@ -1268,6 +1268,7 @@ void FDKsbrEnc_extractSbrEnvelope2(
sbrExtrEnv->pre_transient_info[1] = ed->transient_info[1]; /* tran_flag */
hEnvChan->encEnvData.noOfEnvelopes = ed->nEnvelopes =
ed->frame_info->nEnvelopes; /* number of envelopes of current frame */
+ hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF;
/*
Check if the current frame is divided into one envelope only. If so, set
@@ -1275,8 +1276,9 @@ void FDKsbrEnc_extractSbrEnvelope2(
*/
if ((hEnvChan->encEnvData.hSbrBSGrid->frameClass == FIXFIX) &&
(ed->nEnvelopes == 1)) {
+ AMP_RES currentAmpResFF = SBR_AMP_RES_1_5;
if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) {
- /* Note: global_tonaliy_float_value ==
+ /* Note: global_tonality_float_value ==
((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0)));
threshold_float_value ==
((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0)));
@@ -1290,14 +1292,13 @@ void FDKsbrEnc_extractSbrEnvelope2(
} else {
hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0;
}
- } else
- hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5;
+ currentAmpResFF = hEnvChan->encEnvData.currentAmpResFF;
+ }
- if (hEnvChan->encEnvData.currentAmpResFF !=
- hEnvChan->encEnvData.init_sbr_amp_res) {
+ if (currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) {
FDKsbrEnc_InitSbrHuffmanTables(
&hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope,
- &hEnvChan->sbrCodeNoiseFloor, hEnvChan->encEnvData.currentAmpResFF);
+ &hEnvChan->sbrCodeNoiseFloor, currentAmpResFF);
}
} else {
if (sbrHeaderData->sbr_amp_res != hEnvChan->encEnvData.init_sbr_amp_res) {
@@ -1356,6 +1357,13 @@ void FDKsbrEnc_extractSbrEnvelope2(
}
}
+ if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY &&
+ stereoMode == SBR_SWITCH_LRC &&
+ h_envChan[0]->encEnvData.currentAmpResFF !=
+ h_envChan[1]->encEnvData.currentAmpResFF) {
+ stereoMode = SBR_LEFT_RIGHT;
+ }
+
/*
Extract envelope of current frame.
*/
diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp
index e495dea..048c734 100644
--- a/libSBRenc/src/sbr_encoder.cpp
+++ b/libSBRenc/src/sbr_encoder.cpp
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android
-© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten
+© Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved.
1. INTRODUCTION
@@ -1450,8 +1450,6 @@ static INT initEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData,
params->deltaTAcrossFrames, 0, 0))
return (1);
- sbrConfigData->initAmpResFF = params->init_amp_res_FF;
-
if (FDKsbrEnc_InitSbrHuffmanTables(&hEnv->encEnvData, &hEnv->sbrCodeEnvelope,
&hEnv->sbrCodeNoiseFloor,
sbrHeaderData->sbr_amp_res))
@@ -1749,6 +1747,7 @@ static INT FDKsbrEnc_EnvInit(HANDLE_SBR_ELEMENT hSbrElement,
hSbrElement->sbrHeaderData.sbr_data_extra = 1;
hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res;
+ hSbrElement->sbrConfigData.initAmpResFF = params->init_amp_res_FF;
/* header_extra_1 */
hSbrElement->sbrHeaderData.freqScale = params->freqScale;
diff --git a/sha1.c b/sha1.c
new file mode 100644
index 0000000..08a93d1
--- /dev/null
+++ b/sha1.c
@@ -0,0 +1,399 @@
+/*!
+ * \copy
+ * Copyright (c) 1998, 2009 Paul E. Jones <paulej@packetizer.com>
+ * 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.
+ *
+ */
+
+/*
+ * Description:
+ * This file implements the Secure Hashing Standard as defined
+ * in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * The Secure Hashing Standard, which uses the Secure Hashing
+ * Algorithm (SHA), produces a 160-bit message digest for a
+ * given data stream. In theory, it is highly improbable that
+ * two messages will produce the same message digest. Therefore,
+ * this algorithm can serve as a means of providing a "fingerprint"
+ * for a message.
+ *
+ * Portability Issues:
+ * SHA-1 is defined in terms of 32-bit "words". This code was
+ * written with the expectation that the processor has at least
+ * a 32-bit machine word size. If the machine word size is larger,
+ * the code should still function properly. One caveat to that
+ * is that the input functions taking characters and character
+ * arrays assume that only 8 bits of information are stored in each
+ * character.
+ *
+ * Caveats:
+ * SHA-1 is designed to work with messages less than 2^64 bits
+ * long. Although SHA-1 allows a message digest to be generated for
+ * messages of any number of bits less than 2^64, this
+ * implementation only works with messages with a length that is a
+ * multiple of the size of an 8-bit character.
+ *
+ */
+
+#include "sha1.h"
+
+/*
+ * Define the circular shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+ ((((word) << (bits)) & 0xFFFFFFFF) | \
+ ((word) >> (32-(bits))))
+
+/* Function prototypes */
+void SHA1ProcessMessageBlock(SHA1Context *);
+void SHA1PadMessage(SHA1Context *);
+
+/*
+ * SHA1Reset
+ *
+ * Description:
+ * This function will initialize the SHA1Context in preparation
+ * for computing a new message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1Reset(SHA1Context *context)
+{
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+ context->Message_Digest[0] = 0x67452301;
+ context->Message_Digest[1] = 0xEFCDAB89;
+ context->Message_Digest[2] = 0x98BADCFE;
+ context->Message_Digest[3] = 0x10325476;
+ context->Message_Digest[4] = 0xC3D2E1F0;
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+}
+
+/*
+ * SHA1Result
+ *
+ * Description:
+ * This function will return the 160-bit message digest into the
+ * digest array provided as a parameter.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA-1 hash.
+ * digest: [out]
+ * An array of characters where the digest is written.
+ *
+ * Returns:
+ * 1 if successful, 0 if it failed.
+ *
+ * Comments:
+ *
+ */
+int SHA1Result(SHA1Context *context, unsigned char *digest)
+{
+ int i;
+
+ if (context->Corrupted)
+ {
+ return 0;
+ }
+
+ if (!context->Computed)
+ {
+ SHA1PadMessage(context);
+ context->Computed = 1;
+ }
+
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++)
+ digest[i] = context->Message_Digest[i / 4] >> (8 * (3 - (i % 4)));
+
+ return 1;
+}
+
+/*
+ * SHA1Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion of
+ * the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA-1 context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of the
+ * message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1Input( SHA1Context *context,
+ const unsigned char *message_array,
+ unsigned length)
+{
+ if (!length)
+ {
+ return;
+ }
+
+ if (context->Computed || context->Corrupted)
+ {
+ context->Corrupted = 1;
+ return;
+ }
+
+ while(length-- && !context->Corrupted)
+ {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ context->Length_Low += 8;
+ /* Force it to 32 bits */
+ context->Length_Low &= 0xFFFFFFFF;
+ if (context->Length_Low == 0)
+ {
+ context->Length_High++;
+ /* Force it to 32 bits */
+ context->Length_High &= 0xFFFFFFFF;
+ if (context->Length_High == 0)
+ {
+ /* Message is too long */
+ context->Corrupted = 1;
+ }
+ }
+
+ if (context->Message_Block_Index == 64)
+ {
+ SHA1ProcessMessageBlock(context);
+ }
+
+ message_array++;
+ }
+}
+
+/*
+ * SHA1ProcessMessageBlock
+ *
+ * Description:
+ * This function will process the next 512 bits of the message
+ * stored in the Message_Block array.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in the SHAContext, especially the
+ * single character names, were used because those were the names
+ * used in the publication.
+ *
+ *
+ */
+void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+ const unsigned K[] = /* Constants defined in SHA-1 */
+ {
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int t; /* Loop counter */
+ unsigned temp; /* Temporary word value */
+ unsigned W[80]; /* Word sequence */
+ unsigned A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for(t = 0; t < 16; t++)
+ {
+ W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
+ W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
+ W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
+ W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
+ }
+
+ for(t = 16; t < 80; t++)
+ {
+ W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = context->Message_Digest[0];
+ B = context->Message_Digest[1];
+ C = context->Message_Digest[2];
+ D = context->Message_Digest[3];
+ E = context->Message_Digest[4];
+
+ for(t = 0; t < 20; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 20; t < 40; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 40; t < 60; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 60; t < 80; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ temp &= 0xFFFFFFFF;
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ context->Message_Digest[0] =
+ (context->Message_Digest[0] + A) & 0xFFFFFFFF;
+ context->Message_Digest[1] =
+ (context->Message_Digest[1] + B) & 0xFFFFFFFF;
+ context->Message_Digest[2] =
+ (context->Message_Digest[2] + C) & 0xFFFFFFFF;
+ context->Message_Digest[3] =
+ (context->Message_Digest[3] + D) & 0xFFFFFFFF;
+ context->Message_Digest[4] =
+ (context->Message_Digest[4] + E) & 0xFFFFFFFF;
+
+ context->Message_Block_Index = 0;
+}
+
+/*
+ * SHA1PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64
+ * bits represent the length of the original message. All bits in
+ * between should be 0. This function will pad the message
+ * according to those rules by filling the Message_Block array
+ * accordingly. It will also call SHA1ProcessMessageBlock()
+ * appropriately. When it returns, it can be assumed that the
+ * message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ *
+ */
+void SHA1PadMessage(SHA1Context *context)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index > 55)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 64)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+
+ SHA1ProcessMessageBlock(context);
+
+ while(context->Message_Block_Index < 56)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+ else
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 56)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
+ context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
+ context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
+ context->Message_Block[59] = (context->Length_High) & 0xFF;
+ context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
+ context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
+ context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
+ context->Message_Block[63] = (context->Length_Low) & 0xFF;
+
+ SHA1ProcessMessageBlock(context);
+}
diff --git a/sha1.h b/sha1.h
new file mode 100644
index 0000000..7ca10f8
--- /dev/null
+++ b/sha1.h
@@ -0,0 +1,85 @@
+/*!
+ * \copy
+ * Copyright (c) 1998, 2009 Paul E. Jones <paulej@packetizer.com>
+ * 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.
+ *
+ */
+
+/*
+ * Description:
+ * This class implements the Secure Hashing Standard as defined
+ * in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * Many of the variable names in the SHA1Context, especially the
+ * single character names, were used because those were the names
+ * used in the publication.
+ *
+ * Please read the file sha1.c for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure will hold context information for the hashing
+ * operation
+ */
+typedef struct SHA1Context {
+ unsigned Message_Digest[5]; /* Message Digest (output) */
+
+ unsigned Length_Low; /* Message length in bits */
+ unsigned Length_High; /* Message length in bits */
+
+ unsigned char Message_Block[64]; /* 512-bit message blocks */
+ int Message_Block_Index; /* Index into message block array */
+
+ int Computed; /* Is the digest computed? */
+ int Corrupted; /* Is the message digest corruped? */
+} SHA1Context;
+
+/*
+ * Function Prototypes
+ */
+void SHA1Reset (SHA1Context*);
+int SHA1Result (SHA1Context*, unsigned char*);
+void SHA1Input (SHA1Context*,
+ const unsigned char*,
+ unsigned);
+
+#define SHA_DIGEST_LENGTH 20
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/test-encode-decode.c b/test-encode-decode.c
new file mode 100644
index 0000000..a216c18
--- /dev/null
+++ b/test-encode-decode.c
@@ -0,0 +1,383 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 2017 Martin Storsjo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "aacenc_lib.h"
+#include "aacdecoder_lib.h"
+#include "wavreader.h"
+#include "sha1.h"
+
+
+static int encoder_input_samples, encoder_input_size;
+static int decoder_output_skip;
+static int16_t *encoder_input;
+static int max_diff;
+static uint64_t diff_sum, diff_samples;
+static SHA1Context encode_hash, decode_hash;
+
+static void init_encoder_input(void) {
+ encoder_input_samples = 0;
+ max_diff = 0;
+ diff_sum = diff_samples = 0;
+}
+
+static void free_encoder_input(void) {
+ free(encoder_input);
+ encoder_input = NULL;
+ encoder_input_size = 0;
+}
+
+static void append_encoder_input(const int16_t *input, int samples) {
+ if (encoder_input_samples + samples > encoder_input_size) {
+ int size = 2*(encoder_input_samples + samples);
+ int16_t *ptr = realloc(encoder_input, size * sizeof(*encoder_input));
+ if (!ptr)
+ abort();
+ encoder_input = ptr;
+ encoder_input_size = size;
+ }
+ memcpy(encoder_input + encoder_input_samples, input, samples * sizeof(*input));
+ encoder_input_samples += samples;
+}
+
+static void compare_decoder_output(const int16_t *output, int samples) {
+ int i;
+ // TODO: Stereo upconvert?
+ SHA1Input(&decode_hash, (const unsigned char*) output, samples * sizeof(*output));
+ if (decoder_output_skip > 0) {
+ int n = samples;
+ if (n > decoder_output_skip)
+ n = decoder_output_skip;
+ output += n;
+ samples -= n;
+ decoder_output_skip -= n;
+ if (samples <= 0)
+ return;
+ }
+ if (samples > encoder_input_samples)
+ samples = encoder_input_samples;
+ for (i = 0; i < samples; i++) {
+ int diff = abs(encoder_input[i] - output[i]);
+ if (diff > max_diff)
+ max_diff = diff;
+ diff_sum += diff;
+ diff_samples++;
+ }
+ memmove(encoder_input, encoder_input + samples, (encoder_input_samples - samples) * sizeof(*encoder_input));
+ encoder_input_samples -= samples;
+}
+
+static int decode(HANDLE_AACDECODER decoder, const uint8_t *ptr, int size, uint8_t *decoder_buffer, int decoder_buffer_size, int channels) {
+ AAC_DECODER_ERROR err;
+ CStreamInfo *info;
+ UINT valid, buffer_size;
+ SHA1Input(&encode_hash, ptr, size);
+ do {
+ valid = buffer_size = size;
+ err = aacDecoder_Fill(decoder, (UCHAR**) &ptr, &buffer_size, &valid);
+ ptr += buffer_size - valid;
+ size -= buffer_size - valid;
+ if (err == AAC_DEC_NOT_ENOUGH_BITS)
+ continue;
+ if (err != AAC_DEC_OK)
+ break;
+ err = aacDecoder_DecodeFrame(decoder, (INT_PCM *) decoder_buffer, decoder_buffer_size / sizeof(INT_PCM), 0);
+ if (!ptr && err != AAC_DEC_OK)
+ break;
+ if (err == AAC_DEC_NOT_ENOUGH_BITS)
+ continue;
+ if (err != AAC_DEC_OK) {
+ fprintf(stderr, "Decoding failed\n");
+ return 1;
+ }
+ info = aacDecoder_GetStreamInfo(decoder);
+ if (info->numChannels != channels) {
+ fprintf(stderr, "Mismatched number of channels, input %d, output %d\n", channels, info->numChannels);
+ return 1;
+ }
+ compare_decoder_output((int16_t*) decoder_buffer, info->numChannels * info->frameSize);
+ } while (size > 0);
+ return 0;
+}
+
+static int test_encode_decode(const char *infile, int aot, int afterburner, int eld_sbr, int vbr, int bitrate, int adts) {
+ void *wav;
+ int format, sample_rate, channels, bits_per_sample;
+ int input_size;
+ uint8_t* input_buf;
+ int16_t* convert_buf;
+ HANDLE_AACENCODER encoder;
+ CHANNEL_MODE mode;
+ AACENC_InfoStruct info = { 0 };
+ HANDLE_AACDECODER decoder;
+ int ret = 0;
+ int decoder_buffer_size = 2048 * 2 * 8;
+ uint8_t* decoder_buffer = malloc(decoder_buffer_size);
+ int avg_diff;
+
+ fprintf(stderr, "Testing encoding with aot %d afterburner %d eld_sbr %d vbr %d bitrate %d adts %d\n", aot, afterburner, eld_sbr, vbr, bitrate, adts);
+ init_encoder_input();
+
+ wav = wav_read_open(infile);
+ if (!wav) {
+ fprintf(stderr, "Unable to open wav file %s\n", infile);
+ return 1;
+ }
+ if (!wav_get_header(wav, &format, &channels, &sample_rate, &bits_per_sample, NULL)) {
+ fprintf(stderr, "Bad wav file %s\n", infile);
+ return 1;
+ }
+ if (format != 1) {
+ fprintf(stderr, "Unsupported WAV format %d\n", format);
+ return 1;
+ }
+ if (bits_per_sample != 16) {
+ fprintf(stderr, "Unsupported WAV sample depth %d\n", bits_per_sample);
+ return 1;
+ }
+ switch (channels) {
+ case 1: mode = MODE_1; break;
+ case 2: mode = MODE_2; break;
+ case 3: mode = MODE_1_2; break;
+ case 4: mode = MODE_1_2_1; break;
+ case 5: mode = MODE_1_2_2; break;
+ case 6: mode = MODE_1_2_2_1; break;
+ default:
+ fprintf(stderr, "Unsupported WAV channels %d\n", channels);
+ return 1;
+ }
+ if (aacEncOpen(&encoder, 0, channels) != AACENC_OK) {
+ fprintf(stderr, "Unable to open encoder\n");
+ return 1;
+ }
+ if (aacEncoder_SetParam(encoder, AACENC_AOT, aot) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the AOT\n");
+ return 1;
+ }
+ if (aot == 39 && eld_sbr) {
+ if (aacEncoder_SetParam(encoder, AACENC_SBR_MODE, 1) != AACENC_OK) {
+ fprintf(stderr, "Unable to set SBR mode for ELD\n");
+ return 1;
+ }
+ }
+ if (aacEncoder_SetParam(encoder, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the AOT\n");
+ return 1;
+ }
+ if (aacEncoder_SetParam(encoder, AACENC_CHANNELMODE, mode) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the channel mode\n");
+ return 1;
+ }
+ if (aacEncoder_SetParam(encoder, AACENC_CHANNELORDER, 1) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the wav channel order\n");
+ return 1;
+ }
+ if (vbr) {
+ if (aacEncoder_SetParam(encoder, AACENC_BITRATEMODE, vbr) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the VBR bitrate mode\n");
+ return 1;
+ }
+ } else {
+ if (aacEncoder_SetParam(encoder, AACENC_BITRATE, bitrate) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the bitrate\n");
+ return 1;
+ }
+ }
+ if (aacEncoder_SetParam(encoder, AACENC_TRANSMUX, adts ? 2 : 0) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the ADTS transmux\n");
+ return 1;
+ }
+ if (aacEncoder_SetParam(encoder, AACENC_AFTERBURNER, afterburner) != AACENC_OK) {
+ fprintf(stderr, "Unable to set the afterburner mode\n");
+ return 1;
+ }
+ if (aacEncEncode(encoder, NULL, NULL, NULL, NULL) != AACENC_OK) {
+ fprintf(stderr, "Unable to initialize the encoder\n");
+ return 1;
+ }
+ if (aacEncInfo(encoder, &info) != AACENC_OK) {
+ fprintf(stderr, "Unable to get the encoder info\n");
+ return 1;
+ }
+
+ input_size = channels*2*info.frameLength;
+ input_buf = (uint8_t*) malloc(input_size);
+ convert_buf = (int16_t*) malloc(input_size);
+
+ decoder_output_skip = channels * info.nDelay;
+
+ decoder = aacDecoder_Open(adts ? TT_MP4_ADTS : TT_MP4_RAW, 1);
+ if (!adts) {
+ UCHAR *bufArray[] = { info.confBuf };
+ if (aacDecoder_ConfigRaw(decoder, (UCHAR**) bufArray, &info.confSize) != AAC_DEC_OK) {
+ fprintf(stderr, "Unable to set ASC\n");
+ ret = 1;
+ goto end;
+ }
+ }
+ aacDecoder_SetParam(decoder, AAC_CONCEAL_METHOD, 1);
+ aacDecoder_SetParam(decoder, AAC_PCM_LIMITER_ENABLE, 0);
+ while (1) {
+ AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };
+ AACENC_InArgs in_args = { 0 };
+ AACENC_OutArgs out_args = { 0 };
+ int in_identifier = IN_AUDIO_DATA;
+ int in_size, in_elem_size;
+ int out_identifier = OUT_BITSTREAM_DATA;
+ int out_size, out_elem_size;
+ int read, i;
+ void *in_ptr, *out_ptr;
+ uint8_t outbuf[20480];
+ AACENC_ERROR err;
+
+ read = wav_read_data(wav, input_buf, input_size);
+ for (i = 0; i < read/2; i++) {
+ const uint8_t* in = &input_buf[2*i];
+ convert_buf[i] = in[0] | (in[1] << 8);
+ }
+ in_ptr = convert_buf;
+ in_size = read;
+ in_elem_size = 2;
+
+ in_buf.numBufs = 1;
+ in_buf.bufs = &in_ptr;
+ in_buf.bufferIdentifiers = &in_identifier;
+ in_buf.bufSizes = &in_size;
+ in_buf.bufElSizes = &in_elem_size;
+
+ if (read <= 0) {
+ in_args.numInSamples = -1;
+ } else {
+ in_args.numInSamples = read/2;
+ append_encoder_input(convert_buf, in_args.numInSamples);
+ }
+ out_ptr = outbuf;
+ out_size = sizeof(outbuf);
+ out_elem_size = 1;
+ out_buf.numBufs = 1;
+ out_buf.bufs = &out_ptr;
+ out_buf.bufferIdentifiers = &out_identifier;
+ out_buf.bufSizes = &out_size;
+ out_buf.bufElSizes = &out_elem_size;
+
+ if ((err = aacEncEncode(encoder, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) {
+ if (err == AACENC_ENCODE_EOF)
+ break;
+ fprintf(stderr, "Encoding failed\n");
+ ret = 1;
+ goto end;
+ }
+ if (out_args.numOutBytes == 0)
+ continue;
+
+ if (decode(decoder, outbuf, out_args.numOutBytes, decoder_buffer, decoder_buffer_size, channels)) {
+ ret = 1;
+ goto end;
+ }
+ }
+
+ if (encoder_input_samples > 0) {
+ fprintf(stderr, "%d unmatched samples left at the end\n", encoder_input_samples);
+ ret = 1;
+ goto end;
+ }
+ avg_diff = 0;
+ if (diff_samples > 0)
+ avg_diff = diff_sum / diff_samples;
+ if (/*max_diff > 10000 ||*/ avg_diff > ((aot == 23) ? 2500 : (aot == 29) ? 1500 : 300)) {
+ fprintf(stderr, "max_diff %d, avg_diff %d\n", max_diff, avg_diff);
+ ret = 1;
+ goto end;
+ }
+
+end:
+ free(input_buf);
+ free(convert_buf);
+ wav_read_close(wav);
+ aacEncClose(&encoder);
+ free(decoder_buffer);
+ aacDecoder_Close(decoder);
+
+ return ret;
+}
+
+int main(int argc, char *argv[]) {
+ const char* infile;
+ void *wav;
+ int sample_rate, channels;
+ int failures = 0;
+ int i;
+ unsigned char encode_digest[SHA_DIGEST_LENGTH], decode_digest[SHA_DIGEST_LENGTH];
+ if (argc < 2) {
+ printf("%s input.wav\n", argv[0]);
+ return 1;
+ }
+ infile = argv[1];
+
+ wav = wav_read_open(infile);
+ if (!wav) {
+ fprintf(stderr, "Unable to open wav file %s\n", infile);
+ return 1;
+ }
+ if (!wav_get_header(wav, NULL, &channels, &sample_rate, NULL, NULL)) {
+ fprintf(stderr, "Bad wav file %s\n", infile);
+ return 1;
+ }
+ wav_read_close(wav);
+
+ SHA1Reset(&encode_hash);
+ SHA1Reset(&decode_hash);
+
+ failures += test_encode_decode(infile, 2, 0, 0, 0, 64000, 0); // AAC-LC, without afterburner
+ for (i = 0; i < 2; i++)
+ failures += test_encode_decode(infile, 2, 1, 0, 0, 64000, i); // AAC-LC
+ for (i = 1; i <= 5; i++)
+ failures += test_encode_decode(infile, 2, 1, 0, i, 0, 0); // AAC-LC VBR
+ if (channels == 2) {
+ // HE-AACv2 only works for stereo; HE-AACv1 gets upconverted to stereo (which we don't match properly)
+ for (i = 0; i < 2; i++)
+ failures += test_encode_decode(infile, 5, 1, 0, 0, 64000, i); // HE-AAC
+ for (i = 1; i <= 5; i++)
+ failures += test_encode_decode(infile, 5, 1, 0, i, 0, 0); // HE-AAC VBR
+ for (i = 0; i < 2; i++)
+ failures += test_encode_decode(infile, 29, 1, 0, 0, 64000, i); // HE-AACv2
+ for (i = 1; i <= 5; i++)
+ failures += test_encode_decode(infile, 29, 1, 0, i, 0, 0); // HE-AACv2 VBR
+ }
+ if (channels == 1)
+ failures += test_encode_decode(infile, 23, 1, 0, 0, 64000, 0); // AAC-LD
+ failures += test_encode_decode(infile, 39, 1, 0, 0, 64000, 0); // AAC-ELD
+ failures += test_encode_decode(infile, 39, 1, 1, 0, 64000, 0); // AAC-ELD with SBR
+
+ free_encoder_input();
+ fprintf(stderr, "%d failures\n", failures);
+ SHA1Result(&encode_hash, encode_digest);
+ SHA1Result(&decode_hash, decode_digest);
+ printf("encode hash: ");
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++)
+ printf("%02x", encode_digest[i]);
+ printf("\n");
+ printf("decode hash: ");
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++)
+ printf("%02x", decode_digest[i]);
+ printf("\n");
+ return failures;
+}
diff --git a/test/ref-mono.txt b/test/ref-mono.txt
new file mode 100644
index 0000000..39fa6df
--- /dev/null
+++ b/test/ref-mono.txt
@@ -0,0 +1,2 @@
+encode hash: 7f00e85a1eda67964e1b4044a5659a62e3952af2
+decode hash: af682b197a94e32fce09643857fa77b364574571
diff --git a/test/ref-stereo.txt b/test/ref-stereo.txt
new file mode 100644
index 0000000..a765c93
--- /dev/null
+++ b/test/ref-stereo.txt
@@ -0,0 +1,2 @@
+encode hash: 8411e71bf6b32576d287764cfa577ea0e9b73280
+decode hash: 30ad42bc97b53c03139cca5437b7d9a861de0e92
diff --git a/test/run-test.sh b/test/run-test.sh
new file mode 100755
index 0000000..b2ef548
--- /dev/null
+++ b/test/run-test.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -e
+set -o pipefail
+
+if [ ! -f Sample01_4.wav ]; then
+ curl -LO https://media.xiph.org/audio/HA_2011/Sample01_4.wav
+fi
+
+if [ "$(md5sum Sample01_4.wav | awk '{print $1}')" != "a5c105544c64ce92c6c5c06d280e6b9c" ]; then
+ echo Incorrect checksum for Sample01_4.wav
+ exit 1
+fi
+
+if [ ! -f Sample01_4-mono.wav ]; then
+ ffmpeg -i Sample01_4.wav -ac 1 -fflags +bitexact -y Sample01_4-mono.wav
+fi
+
+if [ "$(md5sum Sample01_4-mono.wav | awk '{print $1}')" != "3bfccac9f2e527ba3ef888874f09a409" ]; then
+ echo Incorrect checksum for Sample01_4-mono.wav
+ exit 1
+fi
+
+./test-encode-decode Sample01_4.wav | tee log-stereo.txt
+./test-encode-decode Sample01_4-mono.wav | tee log-mono.txt
+
+diff -u log-stereo.txt $(dirname $0)/ref-stereo.txt
+diff -u log-mono.txt $(dirname $0)/ref-mono.txt