mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-15 22:20:59 +00:00
Merge branch 'develop'
This commit is contained in:
commit
4a9eead824
4
3rd-party/README.md
vendored
4
3rd-party/README.md
vendored
@ -6,8 +6,7 @@ Library
|
||||
----------------------------------------------------------------------------------------------------------------|----------|---------------|------------------|----------
|
||||
[Android SBC Codec](https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/embdrv/sbc) | e8c3d75b | Apache 2.0 | HFP WBS, A2DP | optimized audio codec
|
||||
[hxcmod-player](https://github.com/jfdelnero/HxCModPlayer) | 03d495c8 | Public Domain | A2DP Source Demo | mod music player
|
||||
[kiss-fft](https://github.com/mborgerding/kissfft) | 131.1.0 | BSD 2-Clause | LE Audio | FFT library
|
||||
[EHIMA LC3 Codec](https://github.com/zephyrproject-rtos/liblc3codec) | 6e8ad0bd | Apache 2.0 | LE Audio | audio codec
|
||||
[Google LC3 Codec](https://android.googlesource.com/platform/packages/modules/Bluetooth) | 49b925f1 | Apache 2.0 | LE Audio | audio codec
|
||||
[lwIP](http://savannah.nongnu.org/projects/lwip/) | b3a93941 | BSD 3-Clause | PAN Demo | complete network stack
|
||||
[md5](http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5) | 1.0 | Public Domain | PBAP | cryptographic hash function
|
||||
[micro-ecc](https://github.com/kmackay/micro-ecc) | e4d264b5 | BSD 2-Clause | LE SC, Mesh | elliptic curve library
|
||||
@ -15,3 +14,4 @@ Library
|
||||
[segger-rtt](https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer/) | v6.20d | BSD 3-Clause | HCI PacketLog | high-speed logging with SEGGER J-Link debug probes (development)
|
||||
[tinydir](https://github.com/cxong/tinydir) | 677733da | BSD 2-Clause | GAP Bonding | get a directory listing on POSIX + Windwows systems
|
||||
[Yxml](https://dev.yorhel.nl/yxml) | 10f968b0 | MIT | PBAP | minimal stream XML parser
|
||||
|
6
3rd-party/bluedroid/decoder/srce/alloc.c
vendored
6
3rd-party/bluedroid/decoder/srce/alloc.c
vendored
@ -57,13 +57,13 @@ PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common,
|
||||
if (filterBufferCount < SBC_CODEC_MIN_FILTER_BUFFERS) {
|
||||
return OI_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
common->filterBufferLen = filterBufferCount * SBC_MAX_BANDS;
|
||||
common->filterBufferLen = (uint32_t) filterBufferCount * SBC_MAX_BANDS;
|
||||
|
||||
/* Allocate memory for the subband data */
|
||||
common->subdata = (OI_INT32*)codecData;
|
||||
codecData += subdataSize;
|
||||
OI_ASSERT(codecDataBytes >= subdataSize);
|
||||
codecDataBytes -= subdataSize;
|
||||
codecDataBytes -= (uint32_t) subdataSize;
|
||||
|
||||
/* Allocate memory for the synthesis buffers */
|
||||
for (i = 0; i < maxChannels; ++i) {
|
||||
@ -71,7 +71,7 @@ PRIVATE OI_STATUS OI_CODEC_SBC_Alloc(OI_CODEC_SBC_COMMON_CONTEXT *common,
|
||||
common->filterBuffer[i] = (SBC_BUFFER_T*)codecData;
|
||||
OI_ASSERT(codecDataBytes >= allocSize);
|
||||
codecData += allocSize;
|
||||
codecDataBytes -= allocSize;
|
||||
codecDataBytes -= (uint32_t) allocSize;
|
||||
}
|
||||
|
||||
return OI_OK;
|
||||
|
@ -53,7 +53,7 @@ PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRIC
|
||||
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(26479, buffer[ 60]))>> 2;
|
||||
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(23167, buffer[ 68]))>> 3;
|
||||
/* 1 - stage 0 */ pcm_b +=(MUL_16S_16S(8235, buffer[ 76]))>> 3;
|
||||
/* 1 - stage 0 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[0<<strideShift] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 0 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(0<<strideShift)] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 1 */ pcm_a = 0;
|
||||
/* 1 - stage 1 */ pcm_b = 0;
|
||||
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(-3263, buffer[ 5]))>> 5;
|
||||
@ -76,8 +76,8 @@ PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRIC
|
||||
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(685, buffer[ 69]))<< 1;
|
||||
/* 1 - stage 1 */ pcm_a +=(MUL_16S_16S(12419, buffer[ 75]))>> 4;
|
||||
/* 1 - stage 1 */ pcm_b +=(MUL_16S_16S(8721, buffer[ 75]))>> 7;
|
||||
/* 1 - stage 1 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[1<<strideShift] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 1 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[7<<strideShift] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 1 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(1<<strideShift)] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 1 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(7<<strideShift)] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 2 */ pcm_a = 0;
|
||||
/* 1 - stage 2 */ pcm_b = 0;
|
||||
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(-10385, buffer[ 6]))>> 6;
|
||||
@ -100,8 +100,8 @@ PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRIC
|
||||
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(7543, buffer[ 70]))>> 3;
|
||||
/* 1 - stage 2 */ pcm_a +=(MUL_16S_16S(9251, buffer[ 74]))>> 4;
|
||||
/* 1 - stage 2 */ pcm_b +=(MUL_16S_16S(8603, buffer[ 74]))>> 6;
|
||||
/* 1 - stage 2 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[2<<strideShift] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 2 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[6<<strideShift] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 2 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(2<<strideShift)] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 2 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(6<<strideShift)] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 3 */ pcm_a = 0;
|
||||
/* 1 - stage 3 */ pcm_b = 0;
|
||||
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(-16457, buffer[ 7]))>> 6;
|
||||
@ -124,13 +124,13 @@ PRIVATE void SynthWindow80_generated(OI_INT16 *pcm, SBC_BUFFER_T const * RESTRIC
|
||||
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(1499, buffer[ 71]))>> 1;
|
||||
/* 1 - stage 3 */ pcm_a +=(MUL_16S_16S(26913, buffer[ 73]))>> 6;
|
||||
/* 1 - stage 3 */ pcm_b +=(MUL_16S_16S(26189, buffer[ 73]))>> 7;
|
||||
/* 1 - stage 3 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[3<<strideShift] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 3 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[5<<strideShift] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 3 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(3<<strideShift)] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 3 */ pcm_b /= 32768; CLIP_INT16(pcm_b); pcm[(uint32_t)(5<<strideShift)] = (OI_INT16)pcm_b;
|
||||
/* 1 - stage 4 */ pcm_a = 0;
|
||||
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10445, buffer[ 8]))>> 4;
|
||||
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(-5297, buffer[ 24]))<< 1;
|
||||
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(22299, buffer[ 40]))<< 2;
|
||||
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(10603, buffer[ 56]));
|
||||
/* 1 - stage 4 */ pcm_a +=(MUL_16S_16S(9539, buffer[ 72]))>> 4;
|
||||
/* 1 - stage 4 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[4<<strideShift] = (OI_INT16)pcm_a;
|
||||
/* 1 - stage 4 */ pcm_a /= 32768; CLIP_INT16(pcm_a); pcm[(uint32_t)(4<<strideShift)] = (OI_INT16)pcm_a;
|
||||
}
|
||||
|
@ -418,7 +418,7 @@ void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buf
|
||||
pa += dec_window_4[20] * buffer[44];
|
||||
pa = SCALE(-pa, 15);
|
||||
CLIP_INT16(pa);
|
||||
pcm[0 << strideShift] = (OI_INT16)pa;
|
||||
pcm[(uint32_t)(0 << strideShift)] = (OI_INT16)pa;
|
||||
|
||||
|
||||
pa = dec_window_4[ 1] * buffer[ 1]; pb = dec_window_4[ 1] * buffer[79];
|
||||
@ -433,10 +433,10 @@ void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buf
|
||||
pb += dec_window_4[19] * buffer[35]; pa += dec_window_4[19] * buffer[45];
|
||||
pa = SCALE(-pa, 15);
|
||||
CLIP_INT16(pa);
|
||||
pcm[1 << strideShift] = (OI_INT16)(pa);
|
||||
pcm[(uint32_t)(1 << strideShift)] = (OI_INT16)(pa);
|
||||
pb = SCALE(-pb, 15);
|
||||
CLIP_INT16(pb);
|
||||
pcm[3 << strideShift] = (OI_INT16)(pb);
|
||||
pcm[(uint32_t)(3 << strideShift)] = (OI_INT16)(pb);
|
||||
|
||||
|
||||
pa = dec_window_4[2] * (/*buffer[ 2] + */ buffer[78]); /* buffer[ 2] is always zero */
|
||||
@ -446,7 +446,7 @@ void SynthWindow40_int32_int32_symmetry_with_sum(OI_INT16 *pcm, SBC_BUFFER_T buf
|
||||
pa += dec_window_4[18] * (/*buffer[34] + */ buffer[46]); /* buffer[34] is always zero */
|
||||
pa = SCALE(-pa, 15);
|
||||
CLIP_INT16(pa);
|
||||
pcm[2 << strideShift] = (OI_INT16)(pa);
|
||||
pcm[(uint32_t)(2 << strideShift)] = (OI_INT16)(pa);
|
||||
}
|
||||
|
||||
|
||||
|
@ -234,7 +234,7 @@ void EncPacking(SBC_ENC_PARAMS *pstrEncParams)
|
||||
|
||||
Temp <<= s32PresentBit;
|
||||
*pu8PacketPtr=Temp;
|
||||
pstrEncParams->u16PacketLength=pu8PacketPtr-pstrEncParams->pu8NextPacket+1;
|
||||
pstrEncParams->u16PacketLength= (uint16_t)(pu8PacketPtr-pstrEncParams->pu8NextPacket)+1;
|
||||
/*find CRC*/
|
||||
pu8PacketPtr = pstrEncParams->pu8NextPacket+1; /*Initialize the ptr*/
|
||||
u8CRC = 0x0F;
|
||||
|
49
3rd-party/kissfft/.gitignore
vendored
49
3rd-party/kissfft/.gitignore
vendored
@ -1,49 +0,0 @@
|
||||
*.o
|
||||
*.swp
|
||||
*.so
|
||||
*.so.*
|
||||
*.a
|
||||
*.dylib
|
||||
test/testcpp
|
||||
test/bm_fftw_double
|
||||
test/bm_fftw_float
|
||||
test/bm_fftw_int16_t
|
||||
test/bm_fftw_int32_t
|
||||
test/bm_fftw_simd
|
||||
test/bm_kiss_double
|
||||
test/bm_kiss_float
|
||||
test/bm_kiss_int16_t
|
||||
test/bm_kiss_int32_t
|
||||
test/bm_kiss_simd
|
||||
test/st_double
|
||||
test/st_float
|
||||
test/st_int16_t
|
||||
test/st_int32_t
|
||||
test/st_simd
|
||||
test/tkfc_double
|
||||
test/tkfc_float
|
||||
test/tkfc_int16_t
|
||||
test/tkfc_int32_t
|
||||
test/tkfc_simd
|
||||
test/tr_double
|
||||
test/tr_float
|
||||
test/tr_int16_t
|
||||
test/tr_int32_t
|
||||
test/tr_simd
|
||||
tools/fastconv_double
|
||||
tools/fastconv_float
|
||||
tools/fastconv_int16_t
|
||||
tools/fastconv_int32_t
|
||||
tools/fastconv_simd
|
||||
tools/fastconvr_double
|
||||
tools/fastconvr_float
|
||||
tools/fastconvr_int16_t
|
||||
tools/fastconvr_int32_t
|
||||
tools/fastconvr_simd
|
||||
tools/fft_double
|
||||
tools/fft_float
|
||||
tools/fft_int16_t
|
||||
tools/fft_int32_t
|
||||
tools/fft_simd
|
||||
test/test_simd
|
||||
build
|
27
3rd-party/kissfft/.travis.yml
vendored
27
3rd-party/kissfft/.travis.yml
vendored
@ -1,27 +0,0 @@
|
||||
language: python
|
||||
|
||||
python:
|
||||
- "3.7"
|
||||
|
||||
dist: focal
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install -y libfftw3-dev
|
||||
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
|
||||
install: true
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "build (make)"
|
||||
script:
|
||||
- make all
|
||||
- make testall
|
||||
- name: "build (cmake)"
|
||||
script:
|
||||
- mkdir build && cd build
|
||||
- cmake ..
|
||||
- make
|
123
3rd-party/kissfft/CHANGELOG
vendored
123
3rd-party/kissfft/CHANGELOG
vendored
@ -1,123 +0,0 @@
|
||||
1.3.0 2012-07-18
|
||||
removed non-standard malloc.h from kiss_fft.h
|
||||
|
||||
moved -lm to end of link line
|
||||
|
||||
checked various return values
|
||||
|
||||
converted python Numeric code to NumPy
|
||||
|
||||
fixed test of int32_t on 64 bit OS
|
||||
|
||||
added padding in a couple of places to allow SIMD alignment of structs
|
||||
|
||||
1.2.9 2010-05-27
|
||||
threadsafe ( including OpenMP )
|
||||
|
||||
first edition of kissfft.hh the C++ template fft engine
|
||||
|
||||
1.2.8
|
||||
Changed memory.h to string.h -- apparently more standard
|
||||
|
||||
Added openmp extensions. This can have fairly linear speedups for larger FFT sizes.
|
||||
|
||||
1.2.7
|
||||
Shrank the real-fft memory footprint. Thanks to Galen Seitz.
|
||||
|
||||
1.2.6 (Nov 14, 2006) The "thanks to GenArts" release.
|
||||
Added multi-dimensional real-optimized FFT, see tools/kiss_fftndr
|
||||
Thanks go to GenArts, Inc. for sponsoring the development.
|
||||
|
||||
1.2.5 (June 27, 2006) The "release for no good reason" release.
|
||||
Changed some harmless code to make some compilers' warnings go away.
|
||||
Added some more digits to pi -- why not.
|
||||
Added kiss_fft_next_fast_size() function to help people decide how much to pad.
|
||||
Changed multidimensional test from 8 dimensions to only 3 to avoid testing
|
||||
problems with fixed point (sorry Buckaroo Banzai).
|
||||
|
||||
1.2.4 (Oct 27, 2005) The "oops, inverse fixed point real fft was borked" release.
|
||||
Fixed scaling bug for inverse fixed point real fft -- also fixed test code that should've been failing.
|
||||
Thanks to Jean-Marc Valin for bug report.
|
||||
|
||||
Use sys/types.h for more portable types than short,int,long => int16_t,int32_t,int64_t
|
||||
If your system does not have these, you may need to define them -- but at least it breaks in a
|
||||
loud and easily fixable way -- unlike silently using the wrong size type.
|
||||
|
||||
Hopefully tools/psdpng.c is fixed -- thanks to Steve Kellog for pointing out the weirdness.
|
||||
|
||||
1.2.3 (June 25, 2005) The "you want to use WHAT as a sample" release.
|
||||
Added ability to use 32 bit fixed point samples -- requires a 64 bit intermediate result, a la 'long long'
|
||||
|
||||
Added ability to do 4 FFTs in parallel by using SSE SIMD instructions. This is accomplished by
|
||||
using the __m128 (vector of 4 floats) as kiss_fft_scalar. Define USE_SIMD to use this.
|
||||
|
||||
I know, I know ... this is drifting a bit from the "kiss" principle, but the speed advantages
|
||||
make it worth it for some. Also recent gcc makes it SOO easy to use vectors of 4 floats like a POD type.
|
||||
|
||||
1.2.2 (May 6, 2005) The Matthew release
|
||||
Replaced fixed point division with multiply&shift. Thanks to Jean-Marc Valin for
|
||||
discussions regarding. Considerable speedup for fixed-point.
|
||||
|
||||
Corrected overflow protection in real fft routines when using fixed point.
|
||||
Finder's Credit goes to Robert Oschler of robodance for pointing me at the bug.
|
||||
This also led to the CHECK_OVERFLOW_OP macro.
|
||||
|
||||
1.2.1 (April 4, 2004)
|
||||
compiles cleanly with just about every -W warning flag under the sun
|
||||
|
||||
reorganized kiss_fft_state so it could be read-only/const. This may be useful for embedded systems
|
||||
that are willing to predeclare twiddle factors, factorization.
|
||||
|
||||
Fixed C_MUL,S_MUL on 16-bit platforms.
|
||||
|
||||
tmpbuf will only be allocated if input & output buffers are same
|
||||
scratchbuf will only be allocated for ffts that are not multiples of 2,3,5
|
||||
|
||||
NOTE: The tmpbuf,scratchbuf changes may require synchronization code for multi-threaded apps.
|
||||
|
||||
|
||||
1.2 (Feb 23, 2004)
|
||||
interface change -- cfg object is forward declaration of struct instead of void*
|
||||
This maintains type saftey and lets the compiler warn/error about stupid mistakes.
|
||||
(prompted by suggestion from Erik de Castro Lopo)
|
||||
|
||||
small speed improvements
|
||||
|
||||
added psdpng.c -- sample utility that will create png spectrum "waterfalls" from an input file
|
||||
( not terribly useful yet)
|
||||
|
||||
1.1.1 (Feb 1, 2004 )
|
||||
minor bug fix -- only affects odd rank, in-place, multi-dimensional FFTs
|
||||
|
||||
1.1 : (Jan 30,2004)
|
||||
split sample_code/ into test/ and tools/
|
||||
|
||||
Removed 2-D fft and added N-D fft (arbitrary)
|
||||
|
||||
modified fftutil.c to allow multi-d FFTs
|
||||
|
||||
Modified core fft routine to allow an input stride via kiss_fft_stride()
|
||||
(eased support of multi-D ffts)
|
||||
|
||||
Added fast convolution filtering (FIR filtering using overlap-scrap method, with tail scrap)
|
||||
|
||||
Add kfc.[ch]: the KISS FFT Cache. It takes care of allocs for you ( suggested by Oscar Lesta ).
|
||||
|
||||
1.0.1 (Dec 15, 2003)
|
||||
fixed bug that occurred when nfft==1. Thanks to Steven Johnson.
|
||||
|
||||
1.0 : (Dec 14, 2003)
|
||||
changed kiss_fft function from using a single buffer, to two buffers.
|
||||
If the same buffer pointer is supplied for both in and out, kiss will
|
||||
manage the buffer copies.
|
||||
|
||||
added kiss_fft2d and kiss_fftr as separate source files (declarations in kiss_fft.h )
|
||||
|
||||
0.4 :(Nov 4,2003) optimized for radix 2,3,4,5
|
||||
|
||||
0.3 :(Oct 28, 2003) woops, version 2 didn't actually factor out any radices other than 2.
|
||||
Thanks to Steven Johnson for finding this one.
|
||||
|
||||
0.2 :(Oct 27, 2003) added mixed radix, only radix 2,4 optimized versions
|
||||
|
||||
0.1 :(May 19 2003) initial release, radix 2 only
|
371
3rd-party/kissfft/CMakeLists.txt
vendored
371
3rd-party/kissfft/CMakeLists.txt
vendored
@ -1,371 +0,0 @@
|
||||
# Directory for easier includes
|
||||
# Anywhere you see include(...) you can check <root>/cmake for that file
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
#
|
||||
# Extract version from Makefile
|
||||
#
|
||||
|
||||
file(READ Makefile _MAKEFILE_CONTENTS)
|
||||
|
||||
string(REGEX MATCH "KFVER_MAJOR = ([0-9]+)\n" KFVER_MAJOR_MATCH "${_MAKEFILE_CONTENTS}")
|
||||
if(NOT KFVER_MAJOR_MATCH)
|
||||
message(FATAL_ERROR "Cannot extract major (ABI) version from Makefile")
|
||||
endif()
|
||||
set(KFVER_MAJOR "${CMAKE_MATCH_1}")
|
||||
|
||||
string(REGEX MATCH "KFVER_MINOR = ([0-9]+)\n" KFVER_MINOR_MATCH "${_MAKEFILE_CONTENTS}")
|
||||
if(NOT KFVER_MINOR_MATCH)
|
||||
message(FATAL_ERROR "Cannot extract minor version from Makefile")
|
||||
endif()
|
||||
set(KFVER_MINOR "${CMAKE_MATCH_1}")
|
||||
|
||||
string(REGEX MATCH "KFVER_PATCH = ([0-9]+)\n" KFVER_PATCH_MATCH "${_MAKEFILE_CONTENTS}")
|
||||
if(NOT KFVER_PATCH_MATCH)
|
||||
message(FATAL_ERROR "Cannot extract patch version from Makefile")
|
||||
endif()
|
||||
set(KFVER_PATCH "${CMAKE_MATCH_1}")
|
||||
|
||||
set(MAKEFILE_EXTRACTED_VERSION "${KFVER_MAJOR}.${KFVER_MINOR}.${KFVER_PATCH}")
|
||||
|
||||
#
|
||||
# Declare CMake project
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.6)
|
||||
project(kissfft VERSION "${MAKEFILE_EXTRACTED_VERSION}")
|
||||
|
||||
#
|
||||
# CMake configuration options
|
||||
#
|
||||
|
||||
# Principal datatype: double, float (default), int16_t, int32_t, simd
|
||||
|
||||
set(KISSFFT_DATATYPE "float" CACHE STRING "Principal datatype of kissfft: double, float (default), int16_t, int32_t, simd")
|
||||
|
||||
# Additional options
|
||||
|
||||
option(KISSFFT_OPENMP "Build kissfft with OpenMP support" OFF)
|
||||
option(KISSFFT_PKGCONFIG "Build pkg-config files" ON)
|
||||
option(KISSFFT_STATIC "Build kissfft as static (ON) or shared library (OFF)" OFF)
|
||||
option(KISSFFT_TEST "Build kissfft tests" ON)
|
||||
option(KISSFFT_TOOLS "Build kissfft command-line tools" ON)
|
||||
option(KISSFFT_USE_ALLOCA "Use alloca instead of malloc" OFF)
|
||||
|
||||
#
|
||||
# Validate datatype
|
||||
#
|
||||
|
||||
if (NOT KISSFFT_DATATYPE MATCHES "^double$" AND
|
||||
NOT KISSFFT_DATATYPE MATCHES "^float$" AND
|
||||
NOT KISSFFT_DATATYPE MATCHES "^int16_t$" AND
|
||||
NOT KISSFFT_DATATYPE MATCHES "^int32_t$" AND
|
||||
NOT KISSFFT_DATATYPE MATCHES "^simd$")
|
||||
message(FATAL_ERROR "Incorrect value of KISSFFT_DATATYPE! It can be one of: double, float, int16_t, int32_t, simd")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Print principal datatype
|
||||
#
|
||||
|
||||
message(STATUS "Building KissFFT with datatype: ${KISSFFT_DATATYPE}")
|
||||
set(KISSFFT_OUTPUT_NAME "kissfft-${KISSFFT_DATATYPE}")
|
||||
|
||||
#
|
||||
# Validate KISSFFT_STATIC
|
||||
#
|
||||
|
||||
if (BUILD_SHARED_LIBS AND KISSFFT_STATIC)
|
||||
message(FATAL_ERROR "Conflicting CMake configuration: -DBUILD_SHARED_LIBS=ON and -DKISSFFT_STATIC=ON")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Enable BUILD_SHARED_LIBS for shared library build before
|
||||
# kissfft library is declared
|
||||
#
|
||||
|
||||
if (NOT KISSFFT_STATIC)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
message(STATUS "Building shared library")
|
||||
else()
|
||||
message(STATUS "Building static library")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Detect C compiler and pass appropriate flags
|
||||
#
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||
add_compile_options(-ffast-math -fomit-frame-pointer
|
||||
-W -Wall -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings
|
||||
"$<$<COMPILE_LANGUAGE:C>:-Wstrict-prototypes;-Wmissing-prototypes;-Wnested-externs;-Wbad-function-cast>")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Add GNUInstallDirs for GNU infrastructure before target)include_directories
|
||||
#
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" AND NOT CMAKE_CROSSCOMPILING)
|
||||
include(GNUInstallDirs)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Declare PKGINCLUDEDIR for kissfft include path
|
||||
#
|
||||
|
||||
set(PKGINCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/kissfft")
|
||||
message(STATUS "PKGINCLUDEDIR is ${PKGINCLUDEDIR}")
|
||||
|
||||
#
|
||||
# Declare kissfft library ( libkissfft.a / libkissfft-${KISSFFT_DATATYPE}.so.${MAKEFILE_EXTRACTED_VERSION} )
|
||||
#
|
||||
|
||||
add_library(kissfft
|
||||
kiss_fft.c
|
||||
kfc.c
|
||||
kiss_fftnd.c
|
||||
kiss_fftndr.c
|
||||
kiss_fftr.c)
|
||||
|
||||
target_include_directories(kissfft PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${PKGINCLUDEDIR}>)
|
||||
|
||||
#
|
||||
# Set compile definitions based on datatype and additional support flags
|
||||
#
|
||||
|
||||
set(KISSFFT_COMPILE_DEFINITIONS)
|
||||
|
||||
#
|
||||
# double / float
|
||||
#
|
||||
|
||||
if(KISSFFT_DATATYPE MATCHES "^float$" OR KISSFFT_DATATYPE MATCHES "^double$")
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS kiss_fft_scalar=${KISSFFT_DATATYPE})
|
||||
else()
|
||||
|
||||
#
|
||||
# int16_t
|
||||
#
|
||||
|
||||
if(KISSFFT_DATATYPE MATCHES "^int16_t$")
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS FIXED_POINT=16)
|
||||
else()
|
||||
|
||||
#
|
||||
# int32_t
|
||||
#
|
||||
|
||||
if(KISSFFT_DATATYPE MATCHES "^int32_t$")
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS FIXED_POINT=32)
|
||||
else()
|
||||
|
||||
#
|
||||
# simd
|
||||
#
|
||||
|
||||
if(KISSFFT_DATATYPE MATCHES "^simd$")
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS USE_SIMD)
|
||||
if (NOT MSVC)
|
||||
target_compile_options(kissfft PRIVATE -msse)
|
||||
else()
|
||||
target_compile_options(kissfft PRIVATE "/arch:SSE")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
# OpenMP support
|
||||
#
|
||||
|
||||
if(KISSFFT_OPENMP)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||
if (NOT MSVC)
|
||||
target_compile_options(kissfft PRIVATE -fopenmp)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
|
||||
target_link_libraries(kissfft PRIVATE "-fopenmp")
|
||||
else()
|
||||
target_link_options(kissfft PRIVATE -fopenmp)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(kissfft PRIVATE "/openmp")
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
|
||||
target_link_libraries(kissfft PRIVATE "/openmp")
|
||||
else()
|
||||
target_link_options(kissfft PRIVATE "/openmp")
|
||||
endif()
|
||||
endif()
|
||||
set(KISSFFT_EXPORT_SUFFIX "-openmp")
|
||||
set(KISSFFT_OUTPUT_NAME "kissfft-${KISSFFT_DATATYPE}-openmp")
|
||||
else()
|
||||
message(FATAL_ERROR "Don't know how to enable OpenMP for this compiler")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
# Shared / static library
|
||||
#
|
||||
|
||||
if(NOT KISSFFT_STATIC)
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS KISS_FFT_SHARED)
|
||||
set_target_properties(kissfft PROPERTIES
|
||||
C_VISIBILITY_PRESET hidden)
|
||||
set(KISSFFT_EXPORT_SUFFIX "${KISSFFT_EXPORT_SUFFIX}-shared")
|
||||
else()
|
||||
set(KISSFFT_EXPORT_SUFFIX "${KISSFFT_EXPORT_SUFFIX}-static")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Alloca support
|
||||
#
|
||||
|
||||
if(KISSFFT_USE_ALLOCA)
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS KISS_FFT_USE_ALLOCA)
|
||||
endif()
|
||||
|
||||
# Set library name, version, soversion and aliases
|
||||
|
||||
target_compile_definitions(kissfft PUBLIC ${KISSFFT_COMPILE_DEFINITIONS})
|
||||
set_target_properties(kissfft PROPERTIES
|
||||
OUTPUT_NAME "${KISSFFT_OUTPUT_NAME}"
|
||||
DEFINE_SYMBOL KISS_FFT_BUILD
|
||||
EXPORT_NAME "${KISSFFT_OUTPUT_NAME}"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${KFVER_MAJOR})
|
||||
add_library(kissfft::kissfft ALIAS kissfft)
|
||||
add_library(kissfft::kissfft-${KISSFFT_DATATYPE} ALIAS kissfft)
|
||||
|
||||
#
|
||||
# Build with libm (-lm) on Linux and kFreeBSD
|
||||
#
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" AND NOT CMAKE_CROSSCOMPILING)
|
||||
target_link_libraries(kissfft PRIVATE m)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Define a helper function to define executable file
|
||||
#
|
||||
|
||||
function(add_kissfft_executable NAME)
|
||||
add_executable(${NAME} ${ARGN})
|
||||
target_link_libraries(${NAME} PRIVATE kissfft::kissfft)
|
||||
|
||||
#
|
||||
# Build with libm (-lm) on Linux and kFreeBSD
|
||||
#
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" AND NOT CMAKE_CROSSCOMPILING)
|
||||
target_link_libraries(${NAME} PRIVATE m)
|
||||
endif()
|
||||
|
||||
if (NOT KISSFFT_OPENMP)
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
OUTPUT_NAME "${NAME}-${KISSFFT_DATATYPE}")
|
||||
else()
|
||||
if (NOT MSVC)
|
||||
target_compile_options(${NAME} PRIVATE -fopenmp)
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
|
||||
target_link_libraries(${NAME} PRIVATE "-fopenmp")
|
||||
else()
|
||||
target_link_options(${NAME} PRIVATE -fopenmp)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(${NAME} PRIVATE "/openmp")
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
|
||||
target_link_libraries(${NAME} PRIVATE "/openmp")
|
||||
else()
|
||||
target_link_options(${NAME} PRIVATE "/openmp")
|
||||
endif()
|
||||
endif()
|
||||
set_target_properties(${NAME} PROPERTIES
|
||||
OUTPUT_NAME "${NAME}-${KISSFFT_DATATYPE}-openmp")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# Perform installation of kissfft library and development files
|
||||
#
|
||||
|
||||
install(TARGETS kissfft EXPORT kissfft
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
|
||||
install(FILES kiss_fft.h
|
||||
kissfft.hh
|
||||
kiss_fftnd.h
|
||||
kiss_fftndr.h
|
||||
kiss_fftr.h
|
||||
DESTINATION "${PKGINCLUDEDIR}")
|
||||
|
||||
set(KISSFFT_INSTALL_CMAKE "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
|
||||
CACHE FILEPATH "Install destination of kissfft cmake modules")
|
||||
mark_as_advanced(KISSFFT_INSTALL_CMAKE)
|
||||
|
||||
install(EXPORT kissfft DESTINATION "${KISSFFT_INSTALL_CMAKE}"
|
||||
NAMESPACE "kissfft::"
|
||||
FILE "${PROJECT_NAME}-${KISSFFT_DATATYPE}${KISSFFT_EXPORT_SUFFIX}-targets.cmake")
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(kissfft-config.cmake.in kissfft-config.cmake
|
||||
INSTALL_DESTINATION "${KISSFFT_INSTALL_CMAKE}")
|
||||
write_basic_package_version_file(kissfft-config-version.cmake COMPATIBILITY AnyNewerVersion)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kissfft-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/kissfft-config-version.cmake"
|
||||
DESTINATION "${KISSFFT_INSTALL_CMAKE}")
|
||||
|
||||
set(PKG_KISSFFT_DEFS)
|
||||
foreach(_def ${KISSFFT_COMPILE_DEFINITIONS})
|
||||
set(PKG_KISSFFT_DEFS "${PKG_KISSFFT_DEFS} -D${_def}")
|
||||
endforeach()
|
||||
if (KISSFFT_PKGCONFIG)
|
||||
include(JoinPaths)
|
||||
set(PKGCONFIG_KISSFFT_PKGINCLUDEDIR "\${includedir}/kissfft")
|
||||
set(PKGCONFIG_KISSFFT_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
set(PKGCONFIG_KISSFFT_VERSION "${kissfft_VERSION}")
|
||||
join_paths(PKGCONFIG_KISSFFT_LIBDIR "\${prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
||||
join_paths(PKGCONFIG_KISSFFT_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
if(KISSFFT_DATATYPE MATCHES "^simd$")
|
||||
list(APPEND KISSFFT_COMPILE_DEFINITIONS USE_SIMD)
|
||||
if (NOT MSVC)
|
||||
set(PKG_KISSFFT_DEFS "${PKG_KISSFFT_DEFS} -msse")
|
||||
else()
|
||||
set(PKG_KISSFFT_DEFS "${PKG_KISSFFT_DEFS} /ARCH:SSE")
|
||||
endif()
|
||||
endif()
|
||||
if (NOT KISSFFT_OPENMP)
|
||||
configure_file(kissfft.pc.in "kissfft-${KISSFFT_DATATYPE}.pc" @ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kissfft-${KISSFFT_DATATYPE}.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
else()
|
||||
if (NOT MSVC)
|
||||
set(PKG_OPENMP "-fopenmp")
|
||||
set(PKG_KISSFFT_DEFS "${PKG_KISSFFT_DEFS} -fopenmp")
|
||||
else()
|
||||
set(PKG_KISSFFT_DEFS "${PKG_KISSFFT_DEFS} /openmp")
|
||||
set(PKG_OPENMP "/openmp")
|
||||
endif()
|
||||
configure_file(kissfft.pc.in "kissfft-${KISSFFT_DATATYPE}-openmp.pc" @ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kissfft-${KISSFFT_DATATYPE}-openmp.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
# Build and install tools if requested by user
|
||||
#
|
||||
|
||||
if(KISSFFT_TOOLS)
|
||||
add_subdirectory(tools)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Build and run tests if requested by user
|
||||
#
|
||||
|
||||
if(KISSFFT_TEST)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
11
3rd-party/kissfft/COPYING
vendored
11
3rd-party/kissfft/COPYING
vendored
@ -1,11 +0,0 @@
|
||||
Copyright (c) 2003-2010 Mark Borgerding . All rights reserved.
|
||||
|
||||
KISS FFT is provided under:
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
Being under the terms of the BSD 3-clause "New" or "Revised" License,
|
||||
according with:
|
||||
|
||||
LICENSES/BSD-3-Clause
|
||||
|
35
3rd-party/kissfft/LICENSES/BSD-3-Clause
vendored
35
3rd-party/kissfft/LICENSES/BSD-3-Clause
vendored
@ -1,35 +0,0 @@
|
||||
Valid-License-Identifier: BSD-3-Clause
|
||||
SPDX-URL: https://spdx.org/licenses/BSD-3-Clause.html
|
||||
Usage-Guide:
|
||||
To use the BSD 3-clause "New" or "Revised" License put the following SPDX
|
||||
tag/value pair into a comment according to the placement guidelines in
|
||||
the licensing rules documentation:
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
License-Text:
|
||||
|
||||
Copyright (c) <year> <owner> . All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE 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.
|
30
3rd-party/kissfft/LICENSES/Unlicense
vendored
30
3rd-party/kissfft/LICENSES/Unlicense
vendored
@ -1,30 +0,0 @@
|
||||
Valid-License-Identifier: Unlicense
|
||||
SPDX-URL: https://spdx.org/licenses/Unlicense.html
|
||||
Usage-Guide:
|
||||
To use the Unlicense put the following SPDX tag/value pair into a
|
||||
comment according to the placement guidelines in the licensing rules
|
||||
documentation:
|
||||
SPDX-License-Identifier: Unlicense
|
||||
License-Text:
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute
|
||||
this software, either in source code form or as a compiled binary, for any
|
||||
purpose, commercial or non-commercial, and by any means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and
|
||||
to the detriment of our heirs and successors. We intend this dedication to be
|
||||
an overt act of relinquishment in perpetuity of all present and future rights
|
||||
to this software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
323
3rd-party/kissfft/Makefile
vendored
323
3rd-party/kissfft/Makefile
vendored
@ -1,323 +0,0 @@
|
||||
#
|
||||
# Semantic versioning
|
||||
#
|
||||
# KFVER_MAJOR denotes the ABI version.
|
||||
#
|
||||
# - It must be bumped only if API public members are removed or
|
||||
# changed in the incompatible
|
||||
#
|
||||
# KFVER_MINOR denotes the minor version within a compatible ABI.
|
||||
#
|
||||
# - It should be bumped if new API public members are added
|
||||
# (but not removed!) so programs linked against the same library
|
||||
# version continue operating properly
|
||||
#
|
||||
# KFVER_PATCH denotes bugfix count since the last minor update.
|
||||
#
|
||||
# - It should be bumped whenever a bug fix is pushed.
|
||||
#
|
||||
|
||||
export KFVER_MAJOR = 131
|
||||
export KFVER_MINOR = 1
|
||||
export KFVER_PATCH = 0
|
||||
|
||||
#
|
||||
# Data type (float / int16_t / int32_t / simd)
|
||||
#
|
||||
|
||||
export KISSFFT_DATATYPE ?= float
|
||||
|
||||
#
|
||||
# Default options
|
||||
#
|
||||
|
||||
export KISSFFT_OPENMP ?= 0
|
||||
export KISSFFT_STATIC ?= 0
|
||||
export KISSFFT_TOOLS ?= 1
|
||||
export KISSFFT_USE_ALLOCA ?= 0
|
||||
|
||||
#
|
||||
# Installation directories
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
export ABS_PREFIX = $(abspath $(PREFIX))
|
||||
|
||||
BINDIR ?= $(ABS_PREFIX)/bin
|
||||
export ABS_BINDIR = $(abspath $(BINDIR))
|
||||
|
||||
INCLUDEDIR ?= $(ABS_PREFIX)/include
|
||||
export ABS_INCLUDEDIR = $(abspath $(INCLUDEDIR))
|
||||
export ABS_PKGINCLUDEDIR = $(ABS_INCLUDEDIR)/kissfft
|
||||
|
||||
#
|
||||
# Override LIBDIR with lib64 following CMake's
|
||||
# GNUInstallDirs logic:
|
||||
#
|
||||
|
||||
CANDIDATE_LIBDIR_NAME = lib
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifeq ($(shell uname -s),Linux)
|
||||
_UNAME_ARCH = $(shell uname -i)
|
||||
|
||||
ifeq (,$(_UNAME_ARCH))
|
||||
_UNAME_ARCH = $(shell uname -m)
|
||||
|
||||
ifeq (,$(_UNAME_ARCH))
|
||||
$(warning WARNING: Can not detect system architecture!)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(_UNAME_ARCH),x86_64)
|
||||
CANDIDATE_LIBDIR_NAME = lib64
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CANDIDATE_LIBDIR = $(PREFIX)/$(CANDIDATE_LIBDIR_NAME)
|
||||
LIBDIR ?= $(CANDIDATE_LIBDIR)
|
||||
|
||||
export ABS_LIBDIR = $(abspath $(LIBDIR))
|
||||
|
||||
export INSTALL ?= install
|
||||
|
||||
#
|
||||
# Library name and version
|
||||
#
|
||||
|
||||
ifeq ($(KISSFFT_OPENMP), 1)
|
||||
KISSFFTLIB_SHORTNAME = kissfft-$(KISSFFT_DATATYPE)-openmp
|
||||
KISSFFT_PKGCONFIG = kissfft-$(KISSFFT_DATATYPE)-openmp.pc
|
||||
KISSFFTLIB_FLAGS = -fopenmp
|
||||
TYPEFLAGS = -fopenmp
|
||||
PKGCONFIG_OPENMP = -fopenmp
|
||||
else
|
||||
KISSFFTLIB_SHORTNAME = kissfft-$(KISSFFT_DATATYPE)
|
||||
KISSFFT_PKGCONFIG = kissfft-$(KISSFFT_DATATYPE).pc
|
||||
TYPEFLAGS =
|
||||
PKGCONFIG_OPENMP =
|
||||
endif
|
||||
|
||||
ifeq ($(KISSFFT_STATIC), 1)
|
||||
KISSFFTLIB_NAME = lib$(KISSFFTLIB_SHORTNAME).a
|
||||
KISSFFTLIB_FLAGS += -static
|
||||
else ifeq ($(shell uname -s),Darwin)
|
||||
KISSFFTLIB_NAME = lib$(KISSFFTLIB_SHORTNAME).dylib
|
||||
KISSFFTLIB_FLAGS += -shared -Wl,-install_name,$(KISSFFTLIB_NAME)
|
||||
else
|
||||
KISSFFTLIB_SODEVELNAME = lib$(KISSFFTLIB_SHORTNAME).so
|
||||
KISSFFTLIB_SONAME = $(KISSFFTLIB_SODEVELNAME).$(KFVER_MAJOR)
|
||||
KISSFFTLIB_NAME = $(KISSFFTLIB_SONAME).$(KFVER_MINOR).$(KFVER_PATCH)
|
||||
KISSFFTLIB_FLAGS += -shared -Wl,-soname,$(KISSFFTLIB_SONAME)
|
||||
endif
|
||||
|
||||
export KISSFFTLIB_SHORTNAME
|
||||
|
||||
#
|
||||
# Compile-time definitions by datatype
|
||||
#
|
||||
#
|
||||
# Note: -DKISS_FFT_BUILD and -DKISS_FFT_SHARED control
|
||||
# C symbol visibility.
|
||||
#
|
||||
|
||||
ifeq "$(KISSFFT_DATATYPE)" "int32_t"
|
||||
TYPEFLAGS += -DFIXED_POINT=32
|
||||
else ifeq "$(KISSFFT_DATATYPE)" "int16_t"
|
||||
TYPEFLAGS += -DFIXED_POINT=16
|
||||
else ifeq "$(KISSFFT_DATATYPE)" "simd"
|
||||
TYPEFLAGS += -DUSE_SIMD=1 -msse
|
||||
else ifeq "$(KISSFFT_DATATYPE)" "float"
|
||||
TYPEFLAGS += -Dkiss_fft_scalar=$(KISSFFT_DATATYPE)
|
||||
else ifeq "$(KISSFFT_DATATYPE)" "double"
|
||||
TYPEFLAGS += -Dkiss_fft_scalar=$(KISSFFT_DATATYPE)
|
||||
else
|
||||
$(error ERROR: KISSFFT_DATATYPE must be one of: float double int16_t int32_t simd)
|
||||
endif
|
||||
|
||||
ifneq ($(KISSFFT_STATIC), 1)
|
||||
TYPEFLAGS += -DKISS_FFT_SHARED
|
||||
endif
|
||||
|
||||
ifeq ($(KISSFFT_USE_ALLOCA), 1)
|
||||
TYPEFLAGS += -DKISS_FFT_USE_ALLOCA=1
|
||||
endif
|
||||
|
||||
#
|
||||
# Compile-time definitions
|
||||
#
|
||||
|
||||
#
|
||||
# Save pkgconfig variables before appending
|
||||
# -DKISS_FFT_BUILD to TYPEFLAGS
|
||||
#
|
||||
|
||||
ifneq ($(shell uname -s),Darwin)
|
||||
PKGCONFIG_KISSFFT_VERSION = $(KFVER_MAJOR).$(KFVER_MINOR).$(KFVER_PATCH)
|
||||
PKGCONFIG_KISSFFT_OUTPUT_NAME = $(KISSFFTLIB_SHORTNAME)
|
||||
PKGCONFIG_PKG_KISSFFT_DEFS = $(TYPEFLAGS)
|
||||
PKGCONFIG_KISSFFT_PREFIX = $(ABS_PREFIX)
|
||||
ifeq ($(ABS_INCLUDEDIR),$(ABS_PREFIX)/include)
|
||||
PKGCONFIG_KISSFFT_INCLUDEDIR = $${prefix}/include
|
||||
else
|
||||
PKGCONFIG_KISSFFT_INCLUDEDIR = $(ABS_INCLUDEDIR)
|
||||
|
||||
endif
|
||||
ifeq ($(ABS_LIBDIR),$(ABS_PREFIX)/$(CANDIDATE_LIBDIR_NAME))
|
||||
PKGCONFIG_KISSFFT_LIBDIR = $${prefix}/$(CANDIDATE_LIBDIR_NAME)
|
||||
else
|
||||
PKGCONFIG_KISSFFT_LIBDIR = $(ABS_LIBDIR)
|
||||
endif
|
||||
PKGCONFIG_KISSFFT_PKGINCLUDEDIR = $${includedir}/kissfft
|
||||
endif
|
||||
|
||||
export TYPEFLAGS
|
||||
|
||||
# Compile .c into .o
|
||||
#
|
||||
|
||||
#
|
||||
# -DKISS_FFT_BUILD is used for library artifacts, so
|
||||
# consumer executable in 'test' and 'tools' do _NOT_
|
||||
# need it. pkg-config output does not need it either.
|
||||
#
|
||||
|
||||
%.c.o: %.c
|
||||
$(CC) -Wall -fPIC \
|
||||
-o $@ \
|
||||
$(CFLAGS) $(TYPEFLAGS) -DKISS_FFT_BUILD \
|
||||
-c $<
|
||||
|
||||
#
|
||||
# Target: "make all"
|
||||
#
|
||||
|
||||
all: kfc.c.o kiss_fft.c.o kiss_fftnd.c.o kiss_fftndr.c.o kiss_fftr.c.o
|
||||
ifneq ($(KISSFFT_STATIC), 1)
|
||||
$(CC) $(KISSFFTLIB_FLAGS) -o $(KISSFFTLIB_NAME) $^
|
||||
ifneq ($(shell uname -s),Darwin)
|
||||
ln -sf $(KISSFFTLIB_NAME) $(KISSFFTLIB_SONAME)
|
||||
ln -sf $(KISSFFTLIB_NAME) $(KISSFFTLIB_SODEVELNAME)
|
||||
endif
|
||||
else
|
||||
$(AR) crus $(KISSFFTLIB_NAME) $^
|
||||
endif
|
||||
ifneq ($(KISSFFT_TOOLS), 0)
|
||||
make -C tools CFLAGADD="$(CFLAGADD)" all
|
||||
endif
|
||||
|
||||
#
|
||||
# Target: "make install"
|
||||
#
|
||||
|
||||
install: all
|
||||
$(INSTALL) -Dt $(ABS_PKGINCLUDEDIR) -m 644 \
|
||||
kiss_fft.h \
|
||||
kissfft.hh \
|
||||
kiss_fftnd.h \
|
||||
kiss_fftndr.h \
|
||||
kiss_fftr.h
|
||||
$(INSTALL) -Dt $(ABS_LIBDIR) -m 644 $(KISSFFTLIB_NAME)
|
||||
ifneq ($(KISSFFT_STATIC), 1)
|
||||
ifneq ($(shell uname -s),Darwin)
|
||||
cd $(LIBDIR) && \
|
||||
ln -sf $(KISSFFTLIB_NAME) $(KISSFFTLIB_SONAME) && \
|
||||
ln -sf $(KISSFFTLIB_NAME) $(KISSFFTLIB_SODEVELNAME)
|
||||
endif
|
||||
endif
|
||||
ifneq ($(shell uname -s),Darwin)
|
||||
mkdir "$(ABS_LIBDIR)/pkgconfig"
|
||||
sed \
|
||||
-e 's+@PKGCONFIG_KISSFFT_VERSION@+$(PKGCONFIG_KISSFFT_VERSION)+' \
|
||||
-e 's+@KISSFFT_OUTPUT_NAME@+$(PKGCONFIG_KISSFFT_OUTPUT_NAME)+' \
|
||||
-e 's+@PKG_KISSFFT_DEFS@+$(PKGCONFIG_PKG_KISSFFT_DEFS)+' \
|
||||
-e 's+@PKG_OPENMP@+$(PKGCONFIG_OPENMP)+' \
|
||||
-e 's+@PKGCONFIG_KISSFFT_PREFIX@+$(PKGCONFIG_KISSFFT_PREFIX)+' \
|
||||
-e 's+@PKGCONFIG_KISSFFT_INCLUDEDIR@+$(PKGCONFIG_KISSFFT_INCLUDEDIR)+' \
|
||||
-e 's+@PKGCONFIG_KISSFFT_LIBDIR@+$(PKGCONFIG_KISSFFT_LIBDIR)+' \
|
||||
-e 's+@PKGCONFIG_KISSFFT_PKGINCLUDEDIR@+$(PKGCONFIG_KISSFFT_PKGINCLUDEDIR)+' \
|
||||
kissfft.pc.in 1>"$(ABS_LIBDIR)/pkgconfig/$(KISSFFT_PKGCONFIG)"
|
||||
endif
|
||||
ifneq ($(KISSFFT_TOOLS), 0)
|
||||
make -C tools install
|
||||
endif
|
||||
|
||||
#
|
||||
# Target: "make doc"
|
||||
#
|
||||
|
||||
doc:
|
||||
$(warning Start by reading the README file. If you want to build and test lots of stuff, do a 'make testall')
|
||||
$(warning but be aware that 'make testall' has dependencies that the basic kissfft software does not.)
|
||||
$(warning It is generally unneeded to run these tests yourself, unless you plan on changing the inner workings)
|
||||
$(warning of kissfft and would like to make use of its regression tests.)
|
||||
|
||||
#
|
||||
# Target: "make testsingle"
|
||||
#
|
||||
|
||||
testsingle:
|
||||
make clean
|
||||
make all
|
||||
make -C test CFLAGADD="$(CFLAGADD)" test testcpp
|
||||
|
||||
#
|
||||
# Target: "make testall"
|
||||
#
|
||||
|
||||
testall:
|
||||
# Shared libraries
|
||||
make KISSFFT_DATATYPE=double testsingle
|
||||
make KISSFFT_DATATYPE=float testsingle
|
||||
make KISSFFT_DATATYPE=int16_t testsingle
|
||||
# The simd and int32_t types may or may not work on your machine
|
||||
make KISSFFT_DATATYPE=int32_t testsingle
|
||||
make KISSFFT_DATATYPE=simd testsingle
|
||||
# Static libraries
|
||||
make KISSFFT_DATATYPE=double KISSFFT_STATIC=1 testsingle
|
||||
make KISSFFT_DATATYPE=float KISSFFT_STATIC=1 testsingle
|
||||
make KISSFFT_DATATYPE=int16_t KISSFFT_STATIC=1 testsingle
|
||||
# The simd and int32_t types may or may not work on your machine
|
||||
make KISSFFT_DATATYPE=int32_t KISSFFT_STATIC=1 testsingle
|
||||
make KISSFFT_DATATYPE=simd KISSFFT_STATIC=1 testsingle
|
||||
# OpenMP libraries
|
||||
make KISSFFT_DATATYPE=double KISSFFT_OPENMP=1 testsingle
|
||||
make KISSFFT_DATATYPE=float KISSFFT_OPENMP=1 testsingle
|
||||
make KISSFFT_DATATYPE=int16_t KISSFFT_OPENMP=1 testsingle
|
||||
# The simd and int32_t types may or may not work on your machine
|
||||
make KISSFFT_DATATYPE=int32_t KISSFFT_OPENMP=1 testsingle
|
||||
make KISSFFT_DATATYPE=simd KISSFFT_OPENMP=1 testsingle
|
||||
$(warning All tests passed!)
|
||||
|
||||
#
|
||||
# Target: "make tarball"
|
||||
#
|
||||
|
||||
tarball: clean
|
||||
git archive --prefix=kissfft/ -o kissfft$(KFVER).tar.gz v$(KFVER)
|
||||
git archive --prefix=kissfft/ -o kissfft$(KFVER).zip v$(KFVER)
|
||||
|
||||
#
|
||||
# Target: "make clean"
|
||||
#
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *.so *.so.*
|
||||
cd test && make clean
|
||||
cd tools && make clean
|
||||
rm -f kiss_fft*.tar.gz *~ *.pyc kiss_fft*.zip
|
||||
|
||||
#
|
||||
# Target: "make asm"
|
||||
#
|
||||
|
||||
asm: kiss_fft.s
|
||||
|
||||
# TODO: Sort out if we should add kfc / other C headers
|
||||
|
||||
kiss_fft.s: kiss_fft.c kiss_fft.h _kiss_fft_guts.h
|
||||
[ -e kiss_fft.s ] && mv kiss_fft.s kiss_fft.s~ || true
|
||||
$(CC) -S kiss_fft.c -O3 -mtune=native -ffast-math -fomit-frame-pointer -unroll-loops -dA -fverbose-asm
|
||||
$(CC) -o kiss_fft_short.s -S kiss_fft.c -O3 -mtune=native -ffast-math -fomit-frame-pointer -dA -fverbose-asm -DFIXED_POINT
|
||||
[ -e kiss_fft.s~ ] && diff kiss_fft.s~ kiss_fft.s || true
|
245
3rd-party/kissfft/README.md
vendored
245
3rd-party/kissfft/README.md
vendored
@ -1,245 +0,0 @@
|
||||
# KISS FFT [](https://travis-ci.com/mborgerding/kissfft)
|
||||
|
||||
KISS FFT - A mixed-radix Fast Fourier Transform based up on the principle,
|
||||
"Keep It Simple, Stupid."
|
||||
|
||||
There are many great fft libraries already around. Kiss FFT is not trying
|
||||
to be better than any of them. It only attempts to be a reasonably efficient,
|
||||
moderately useful FFT that can use fixed or floating data types and can be
|
||||
incorporated into someone's C program in a few minutes with trivial licensing.
|
||||
|
||||
## USAGE:
|
||||
|
||||
The basic usage for 1-d complex FFT is:
|
||||
|
||||
```c
|
||||
#include "kiss_fft.h"
|
||||
kiss_fft_cfg cfg = kiss_fft_alloc( nfft ,is_inverse_fft ,0,0 );
|
||||
while ...
|
||||
|
||||
... // put kth sample in cx_in[k].r and cx_in[k].i
|
||||
|
||||
kiss_fft( cfg , cx_in , cx_out );
|
||||
|
||||
... // transformed. DC is in cx_out[0].r and cx_out[0].i
|
||||
|
||||
kiss_fft_free(cfg);
|
||||
```
|
||||
- **Note**: frequency-domain data is stored from dc up to 2pi.
|
||||
so cx_out[0] is the dc bin of the FFT
|
||||
and cx_out[nfft/2] is the Nyquist bin (if exists)
|
||||
|
||||
Declarations are in "kiss_fft.h", along with a brief description of the
|
||||
functions you'll need to use.
|
||||
|
||||
Code definitions for 1d complex FFTs are in kiss_fft.c.
|
||||
|
||||
You can do other cool stuff with the extras you'll find in tools/
|
||||
> - multi-dimensional FFTs
|
||||
> - real-optimized FFTs (returns the positive half-spectrum:
|
||||
(nfft/2+1) complex frequency bins)
|
||||
> - fast convolution FIR filtering (not available for fixed point)
|
||||
> - spectrum image creation
|
||||
|
||||
The core fft and most tools/ code can be compiled to use float, double,
|
||||
Q15 short or Q31 samples. The default is float.
|
||||
|
||||
## BUILDING:
|
||||
|
||||
There are two functionally-equivalent build systems supported by kissfft:
|
||||
|
||||
- Make (traditional Makefiles for Unix / Linux systems)
|
||||
- CMake (more modern and feature-rich build system developed by Kitware)
|
||||
|
||||
To build kissfft, the following build environment can be used:
|
||||
|
||||
- GNU build environment with GCC, Clang and GNU Make or CMake (>= 3.6)
|
||||
- Microsoft Visual C++ (MSVC) with CMake (>= 3.6)
|
||||
|
||||
Additional libraries required to build and test kissfft include:
|
||||
|
||||
- libpng for psdpng tool,
|
||||
- libfftw3 to validate kissfft results against it,
|
||||
- python 2/3 with Numpy to validate kissfft results against it.
|
||||
- OpenMP supported by GCC, Clang or MSVC for multi-core FFT transformations
|
||||
|
||||
Environments like Cygwin and MinGW can be highly likely used to build kissfft
|
||||
targeting Windows platform, but no tests were performed to the date.
|
||||
|
||||
Both Make and CMake builds are easily configurable:
|
||||
|
||||
- `KISSFFT_DATATYPE=<datatype>` (for Make) or `-DKISSFFT_DATATYPE=<datatype>`
|
||||
(for CMake) denote the principal datatype used by kissfft. It can be one
|
||||
of the following:
|
||||
|
||||
- float (default)
|
||||
- double
|
||||
- int16_t
|
||||
- int32_t
|
||||
- SIMD (requires SSE instruction set support on target CPU)
|
||||
|
||||
- `KISSFFT_OPENMP=1` (for Make) or `-DKISSFFT_OPENMP=ON` (for CMake) builds kissfft
|
||||
with OpenMP support. Please note that a supported compiler is required and this
|
||||
option is turned off by default.
|
||||
|
||||
- `KISSFFT_STATIC=1` (for Make) or `-DKISSFFT_STATIC=ON` (for CMake) instructs
|
||||
the builder to create static library ('.lib' for Windows / '.a' for Unix or Linux).
|
||||
By default, this option is turned off and the shared library is created
|
||||
('.dll' for Windows, '.so' for Linux or Unix, '.dylib' for Mac OSX)
|
||||
|
||||
- `-DKISSFFT_TEST=OFF` (for CMake) disables building tests for kissfft. On Make,
|
||||
building tests is done separately by 'make testall' or 'make testsingle', so
|
||||
no specific setting is required.
|
||||
|
||||
- `KISSFFT_TOOLS=0` (for Make) or `-DKISSFFT_TOOLS=OFF` (for CMake) builds kissfft
|
||||
without command-line tools like 'fastconv'. By default the tools are built.
|
||||
|
||||
- `KISSFFT_USE_ALLOCA=1` (for Make) or `-DKISSFFT_USE_ALLOCA=ON` (for CMake)
|
||||
build kissfft with 'alloca' usage instead of 'malloc' / 'free'.
|
||||
|
||||
- `PREFIX=/full/path/to/installation/prefix/directory` (for Make) or
|
||||
`-DCMAKE_INSTALL_PREFIX=/full/path/to/installation/prefix/directory` (for CMake)
|
||||
specifies the prefix directory to install kissfft into.
|
||||
|
||||
For example, to build kissfft as a static library with 'int16_t' datatype and
|
||||
OpenMP support using Make, run the command from kissfft source tree:
|
||||
|
||||
```
|
||||
make KISSFFT_DATATYPE=int16_t KISSFFT_STATIC=1 KISSFFT_OPENMP=1 all
|
||||
```
|
||||
|
||||
The same configuration for CMake is:
|
||||
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake -DKISSFFT_DATATYPE=int16_t -DKISSFFT_STATIC=ON -DKISSFFT_OPENMP=ON ..
|
||||
make all
|
||||
```
|
||||
|
||||
To specify '/tmp/1234' as installation prefix directory, run:
|
||||
|
||||
|
||||
```
|
||||
make PREFIX=/tmp/1234 KISSFFT_DATATYPE=int16_t KISSFFT_STATIC=1 KISSFFT_OPENMP=1 install
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/1234 -DKISSFFT_DATATYPE=int16_t -DKISSFFT_STATIC=ON -DKISSFFT_OPENMP=ON ..
|
||||
make all
|
||||
make install
|
||||
```
|
||||
|
||||
## TESTING:
|
||||
|
||||
To validate the build configured as an example above, run the following command from
|
||||
kissfft source tree:
|
||||
|
||||
```
|
||||
make KISSFFT_DATATYPE=int16_t KISSFFT_STATIC=1 KISSFFT_OPENMP=1 testsingle
|
||||
```
|
||||
|
||||
if using Make, or:
|
||||
|
||||
```
|
||||
make test
|
||||
```
|
||||
|
||||
if using CMake.
|
||||
|
||||
To test all possible build configurations, please run an extended testsuite from
|
||||
kissfft source tree:
|
||||
|
||||
```
|
||||
sh test/kissfft-testsuite.sh
|
||||
```
|
||||
|
||||
Please note that the extended testsuite takes around 20-40 minutes depending on device
|
||||
it runs on. This testsuite is useful for reporting bugs or testing the pull requests.
|
||||
|
||||
## BACKGROUND
|
||||
|
||||
I started coding this because I couldn't find a fixed point FFT that didn't
|
||||
use assembly code. I started with floating point numbers so I could get the
|
||||
theory straight before working on fixed point issues. In the end, I had a
|
||||
little bit of code that could be recompiled easily to do ffts with short, float
|
||||
or double (other types should be easy too).
|
||||
|
||||
Once I got my FFT working, I was curious about the speed compared to
|
||||
a well respected and highly optimized fft library. I don't want to criticize
|
||||
this great library, so let's call it FFT_BRANDX.
|
||||
During this process, I learned:
|
||||
|
||||
> 1. FFT_BRANDX has more than 100K lines of code. The core of kiss_fft is about 500 lines (cpx 1-d).
|
||||
> 2. It took me an embarrassingly long time to get FFT_BRANDX working.
|
||||
> 3. A simple program using FFT_BRANDX is 522KB. A similar program using kiss_fft is 18KB (without optimizing for size).
|
||||
> 4. FFT_BRANDX is roughly twice as fast as KISS FFT in default mode.
|
||||
|
||||
It is wonderful that free, highly optimized libraries like FFT_BRANDX exist.
|
||||
But such libraries carry a huge burden of complexity necessary to extract every
|
||||
last bit of performance.
|
||||
|
||||
**Sometimes simpler is better, even if it's not better.**
|
||||
|
||||
## FREQUENTLY ASKED QUESTIONS:
|
||||
> Q: Can I use kissfft in a project with a ___ license?</br>
|
||||
> A: Yes. See LICENSE below.
|
||||
|
||||
> Q: Why don't I get the output I expect?</br>
|
||||
> A: The two most common causes of this are
|
||||
> 1) scaling : is there a constant multiplier between what you got and what you want?
|
||||
> 2) mixed build environment -- all code must be compiled with same preprocessor
|
||||
> definitions for FIXED_POINT and kiss_fft_scalar
|
||||
|
||||
> Q: Will you write/debug my code for me?</br>
|
||||
> A: Probably not unless you pay me. I am happy to answer pointed and topical questions, but
|
||||
> I may refer you to a book, a forum, or some other resource.
|
||||
|
||||
|
||||
## PERFORMANCE
|
||||
(on Athlon XP 2100+, with gcc 2.96, float data type)
|
||||
|
||||
Kiss performed 10000 1024-pt cpx ffts in .63 s of cpu time.
|
||||
For comparison, it took md5sum twice as long to process the same amount of data.
|
||||
Transforming 5 minutes of CD quality audio takes less than a second (nfft=1024).
|
||||
|
||||
**DO NOT:**
|
||||
- use Kiss if you need the Fastest Fourier Transform in the World
|
||||
- ask me to add features that will bloat the code
|
||||
|
||||
## UNDER THE HOOD
|
||||
|
||||
Kiss FFT uses a time decimation, mixed-radix, out-of-place FFT. If you give it an input buffer
|
||||
and output buffer that are the same, a temporary buffer will be created to hold the data.
|
||||
|
||||
No static data is used. The core routines of kiss_fft are thread-safe (but not all of the tools directory).[
|
||||
|
||||
No scaling is done for the floating point version (for speed).
|
||||
Scaling is done both ways for the fixed-point version (for overflow prevention).
|
||||
|
||||
Optimized butterflies are used for factors 2,3,4, and 5.
|
||||
|
||||
The real (i.e. not complex) optimization code only works for even length ffts. It does two half-length
|
||||
FFTs in parallel (packed into real&imag), and then combines them via twiddling. The result is
|
||||
nfft/2+1 complex frequency bins from DC to Nyquist. If you don't know what this means, search the web.
|
||||
|
||||
The fast convolution filtering uses the overlap-scrap method, slightly
|
||||
modified to put the scrap at the tail.
|
||||
|
||||
## LICENSE
|
||||
Revised BSD License, see COPYING for verbiage.
|
||||
Basically, "free to use&change, give credit where due, no guarantees"
|
||||
Note this license is compatible with GPL at one end of the spectrum and closed, commercial software at
|
||||
the other end. See http://www.fsf.org/licensing/licenses
|
||||
|
||||
## TODO
|
||||
- Add real optimization for odd length FFTs
|
||||
- Document/revisit the input/output fft scaling
|
||||
- Make doc describing the overlap (tail) scrap fast convolution filtering in kiss_fastfir.c
|
||||
- Test all the ./tools/ code with fixed point (kiss_fastfir.c doesn't work, maybe others)
|
||||
|
||||
## AUTHOR
|
||||
Mark Borgerding
|
||||
Mark@Borgerding.net
|
78
3rd-party/kissfft/README.simd
vendored
78
3rd-party/kissfft/README.simd
vendored
@ -1,78 +0,0 @@
|
||||
If you are reading this, it means you think you may be interested in using the SIMD extensions in kissfft
|
||||
to do 4 *separate* FFTs at once.
|
||||
|
||||
Beware! Beyond here there be dragons!
|
||||
|
||||
This API is not easy to use, is not well documented, and breaks the KISS principle.
|
||||
|
||||
|
||||
Still reading? Okay, you may get rewarded for your patience with a considerable speedup
|
||||
(2-3x) on intel x86 machines with SSE if you are willing to jump through some hoops.
|
||||
|
||||
The basic idea is to use the packed 4 float __m128 data type as a scalar element.
|
||||
This means that the format is pretty convoluted. It performs 4 FFTs per fft call on signals A,B,C,D.
|
||||
|
||||
For complex data, the data is interlaced as follows:
|
||||
rA0,rB0,rC0,rD0, iA0,iB0,iC0,iD0, rA1,rB1,rC1,rD1, iA1,iB1,iC1,iD1 ...
|
||||
where "rA0" is the real part of the zeroth sample for signal A
|
||||
|
||||
Real-only data is laid out:
|
||||
rA0,rB0,rC0,rD0, rA1,rB1,rC1,rD1, ...
|
||||
|
||||
Compile with gcc flags something like
|
||||
-O3 -mpreferred-stack-boundary=4 -DUSE_SIMD=1 -msse
|
||||
|
||||
Be aware of SIMD alignment. This is the most likely cause of segfaults.
|
||||
The code within kissfft uses scratch variables on the stack.
|
||||
With SIMD, these must have addresses on 16 byte boundaries.
|
||||
Search on "SIMD alignment" for more info.
|
||||
|
||||
|
||||
|
||||
Robin at Divide Concept was kind enough to share his code for formatting to/from the SIMD kissfft.
|
||||
I have not run it -- use it at your own risk. It appears to do 4xN and Nx4 transpositions
|
||||
(out of place).
|
||||
|
||||
void SSETools::pack128(float* target, float* source, unsigned long size128)
|
||||
{
|
||||
__m128* pDest = (__m128*)target;
|
||||
__m128* pDestEnd = pDest+size128;
|
||||
float* source0=source;
|
||||
float* source1=source0+size128;
|
||||
float* source2=source1+size128;
|
||||
float* source3=source2+size128;
|
||||
|
||||
while(pDest<pDestEnd)
|
||||
{
|
||||
*pDest=_mm_set_ps(*source3,*source2,*source1,*source0);
|
||||
source0++;
|
||||
source1++;
|
||||
source2++;
|
||||
source3++;
|
||||
pDest++;
|
||||
}
|
||||
}
|
||||
|
||||
void SSETools::unpack128(float* target, float* source, unsigned long size128)
|
||||
{
|
||||
|
||||
float* pSrc = source;
|
||||
float* pSrcEnd = pSrc+size128*4;
|
||||
float* target0=target;
|
||||
float* target1=target0+size128;
|
||||
float* target2=target1+size128;
|
||||
float* target3=target2+size128;
|
||||
|
||||
while(pSrc<pSrcEnd)
|
||||
{
|
||||
*target0=pSrc[0];
|
||||
*target1=pSrc[1];
|
||||
*target2=pSrc[2];
|
||||
*target3=pSrc[3];
|
||||
target0++;
|
||||
target1++;
|
||||
target2++;
|
||||
target3++;
|
||||
pSrc+=4;
|
||||
}
|
||||
}
|
39
3rd-party/kissfft/TIPS
vendored
39
3rd-party/kissfft/TIPS
vendored
@ -1,39 +0,0 @@
|
||||
Speed:
|
||||
* If you want to use multiple cores, then compile with -openmp or -fopenmp (see your compiler docs).
|
||||
Realize that larger FFTs will reap more benefit than smaller FFTs. This generally uses more CPU time, but
|
||||
less wall time.
|
||||
|
||||
* experiment with compiler flags
|
||||
Special thanks to Oscar Lesta. He suggested some compiler flags
|
||||
for gcc that make a big difference. They shave 10-15% off
|
||||
execution time on some systems. Try some combination of:
|
||||
-march=pentiumpro
|
||||
-ffast-math
|
||||
-fomit-frame-pointer
|
||||
|
||||
* If the input data has no imaginary component, use the kiss_fftr code under tools/.
|
||||
Real ffts are roughly twice as fast as complex.
|
||||
|
||||
* If you can rearrange your code to do 4 FFTs in parallel and you are on a recent Intel or AMD machine,
|
||||
then you might want to experiment with the USE_SIMD code. See README.simd
|
||||
|
||||
|
||||
Reducing code size:
|
||||
* remove some of the butterflies. There are currently butterflies optimized for radices
|
||||
2,3,4,5. It is worth mentioning that you can still use FFT sizes that contain
|
||||
other factors, they just won't be quite as fast. You can decide for yourself
|
||||
whether to keep radix 2 or 4. If you do some work in this area, let me
|
||||
know what you find.
|
||||
|
||||
* For platforms where ROM/code space is more plentiful than RAM,
|
||||
consider creating a hardcoded kiss_fft_state. In other words, decide which
|
||||
FFT size(s) you want and make a structure with the correct factors and twiddles.
|
||||
|
||||
* Frank van der Hulst offered numerous suggestions for smaller code size and correct operation
|
||||
on embedded targets. "I'm happy to help anyone who is trying to implement KISSFFT on a micro"
|
||||
|
||||
Some of these were rolled into the mainline code base:
|
||||
- using long casts to promote intermediate results of short*short multiplication
|
||||
- delaying allocation of buffers that are sometimes unused.
|
||||
In some cases, it may be desirable to limit capability in order to better suit the target:
|
||||
- predefining the twiddle tables for the desired fft size.
|
167
3rd-party/kissfft/_kiss_fft_guts.h
vendored
167
3rd-party/kissfft/_kiss_fft_guts.h
vendored
@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
/* kiss_fft.h
|
||||
defines kiss_fft_scalar as either short or a float type
|
||||
and defines
|
||||
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
|
||||
|
||||
#ifndef _kiss_fft_guts_h
|
||||
#define _kiss_fft_guts_h
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fft_log.h"
|
||||
#include <limits.h>
|
||||
|
||||
#define MAXFACTORS 32
|
||||
/* e.g. an fft of length 128 has 4 factors
|
||||
as far as kissfft is concerned
|
||||
4*4*4*2
|
||||
*/
|
||||
|
||||
struct kiss_fft_state{
|
||||
int nfft;
|
||||
int inverse;
|
||||
int factors[2*MAXFACTORS];
|
||||
kiss_fft_cpx twiddles[1];
|
||||
};
|
||||
|
||||
/*
|
||||
Explanation of macros dealing with complex math:
|
||||
|
||||
C_MUL(m,a,b) : m = a*b
|
||||
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
|
||||
C_SUB( res, a,b) : res = a - b
|
||||
C_SUBFROM( res , a) : res -= a
|
||||
C_ADDTO( res , a) : res += a
|
||||
* */
|
||||
#ifdef FIXED_POINT
|
||||
#include <stdint.h>
|
||||
#if (FIXED_POINT==32)
|
||||
# define FRACBITS 31
|
||||
# define SAMPPROD int64_t
|
||||
#define SAMP_MAX INT32_MAX
|
||||
#define SAMP_MIN INT32_MIN
|
||||
#else
|
||||
# define FRACBITS 15
|
||||
# define SAMPPROD int32_t
|
||||
#define SAMP_MAX INT16_MAX
|
||||
#define SAMP_MIN INT16_MIN
|
||||
#endif
|
||||
|
||||
#if defined(CHECK_OVERFLOW)
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) \
|
||||
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
|
||||
KISS_FFT_WARNING("overflow (%d " #op" %d) = %ld", (a),(b),(SAMPPROD)(a) op (SAMPPROD)(b)); }
|
||||
#endif
|
||||
|
||||
|
||||
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
|
||||
# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
|
||||
|
||||
# define S_MUL(a,b) sround( smul(a,b) )
|
||||
|
||||
# define C_MUL(m,a,b) \
|
||||
do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
|
||||
(m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
|
||||
|
||||
# define DIVSCALAR(x,k) \
|
||||
(x) = sround( smul( x, SAMP_MAX/k ) )
|
||||
|
||||
# define C_FIXDIV(c,div) \
|
||||
do { DIVSCALAR( (c).r , div); \
|
||||
DIVSCALAR( (c).i , div); }while (0)
|
||||
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r = sround( smul( (c).r , s ) ) ;\
|
||||
(c).i = sround( smul( (c).i , s ) ) ; }while(0)
|
||||
|
||||
#else /* not FIXED_POINT*/
|
||||
|
||||
# define S_MUL(a,b) ( (a)*(b) )
|
||||
#define C_MUL(m,a,b) \
|
||||
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
|
||||
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
|
||||
# define C_FIXDIV(c,div) /* NOOP */
|
||||
# define C_MULBYSCALAR( c, s ) \
|
||||
do{ (c).r *= (s);\
|
||||
(c).i *= (s); }while(0)
|
||||
#endif
|
||||
|
||||
#ifndef CHECK_OVERFLOW_OP
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
|
||||
#endif
|
||||
|
||||
#define C_ADD( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
|
||||
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
|
||||
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
|
||||
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do { \
|
||||
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
|
||||
(res).r += (a).r; (res).i += (a).i;\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {\
|
||||
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
|
||||
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
|
||||
(res).r -= (a).r; (res).i -= (a).i; \
|
||||
}while(0)
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
# define KISS_FFT_COS(phase) floor(.5+SAMP_MAX * cos (phase))
|
||||
# define KISS_FFT_SIN(phase) floor(.5+SAMP_MAX * sin (phase))
|
||||
# define HALF_OF(x) ((x)>>1)
|
||||
#elif defined(USE_SIMD)
|
||||
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
|
||||
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
|
||||
# define HALF_OF(x) ((x)*_mm_set1_ps(.5))
|
||||
#else
|
||||
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
|
||||
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
|
||||
# define HALF_OF(x) ((x)*((kiss_fft_scalar).5))
|
||||
#endif
|
||||
|
||||
#define kf_cexp(x,phase) \
|
||||
do{ \
|
||||
(x)->r = KISS_FFT_COS(phase);\
|
||||
(x)->i = KISS_FFT_SIN(phase);\
|
||||
}while(0)
|
||||
|
||||
|
||||
/* a debugging function */
|
||||
#define pcpx(c)\
|
||||
KISS_FFT_DEBUG("%g + %gi\n",(double)((c)->r),(double)((c)->i))
|
||||
|
||||
|
||||
#ifdef KISS_FFT_USE_ALLOCA
|
||||
// define this to allow use of alloca instead of malloc for temporary buffers
|
||||
// Temporary buffers are used in two case:
|
||||
// 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
|
||||
// 2. "in-place" FFTs. Notice the quotes, since kissfft does not really do an in-place transform.
|
||||
#include <alloca.h>
|
||||
#define KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
|
||||
#define KISS_FFT_TMP_FREE(ptr)
|
||||
#else
|
||||
#define KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
|
||||
#define KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
|
||||
#endif
|
||||
|
||||
#endif /* _kiss_fft_guts_h */
|
||||
|
23
3rd-party/kissfft/cmake/JoinPaths.cmake
vendored
23
3rd-party/kissfft/cmake/JoinPaths.cmake
vendored
@ -1,23 +0,0 @@
|
||||
# This module provides function for joining paths
|
||||
# known from most languages
|
||||
#
|
||||
# SPDX-License-Identifier: (MIT OR CC0-1.0)
|
||||
# Copyright 2020 Jan Tojnar
|
||||
# https://github.com/jtojnar/cmake-snips
|
||||
#
|
||||
# Modelled after Python’s os.path.join
|
||||
# https://docs.python.org/3.7/library/os.path.html#os.path.join
|
||||
# Windows not supported
|
||||
function(join_paths joined_path first_path_segment)
|
||||
set(temp_path "${first_path_segment}")
|
||||
foreach(current_segment IN LISTS ARGN)
|
||||
if(NOT ("${current_segment}" STREQUAL ""))
|
||||
if(IS_ABSOLUTE "${current_segment}")
|
||||
set(temp_path "${current_segment}")
|
||||
else()
|
||||
set(temp_path "${temp_path}/${current_segment}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(${joined_path} "${temp_path}" PARENT_SCOPE)
|
||||
endfunction()
|
109
3rd-party/kissfft/kfc.c
vendored
109
3rd-party/kissfft/kfc.c
vendored
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include "kfc.h"
|
||||
|
||||
typedef struct cached_fft *kfc_cfg;
|
||||
|
||||
struct cached_fft
|
||||
{
|
||||
int nfft;
|
||||
int inverse;
|
||||
kiss_fft_cfg cfg;
|
||||
kfc_cfg next;
|
||||
};
|
||||
|
||||
static kfc_cfg cache_root=NULL;
|
||||
static int ncached=0;
|
||||
|
||||
static kiss_fft_cfg find_cached_fft(int nfft,int inverse)
|
||||
{
|
||||
size_t len;
|
||||
kfc_cfg cur=cache_root;
|
||||
kfc_cfg prev=NULL;
|
||||
while ( cur ) {
|
||||
if ( cur->nfft == nfft && inverse == cur->inverse )
|
||||
break;/*found the right node*/
|
||||
prev = cur;
|
||||
cur = prev->next;
|
||||
}
|
||||
if (cur== NULL) {
|
||||
/* no cached node found, need to create a new one*/
|
||||
kiss_fft_alloc(nfft,inverse,0,&len);
|
||||
#ifdef USE_SIMD
|
||||
int padding = (16-sizeof(struct cached_fft)) & 15;
|
||||
// make sure the cfg aligns on a 16 byte boundary
|
||||
len += padding;
|
||||
#endif
|
||||
cur = (kfc_cfg)KISS_FFT_MALLOC((sizeof(struct cached_fft) + len ));
|
||||
if (cur == NULL)
|
||||
return NULL;
|
||||
cur->cfg = (kiss_fft_cfg)(cur+1);
|
||||
#ifdef USE_SIMD
|
||||
cur->cfg = (kiss_fft_cfg) ((char*)(cur+1)+padding);
|
||||
#endif
|
||||
kiss_fft_alloc(nfft,inverse,cur->cfg,&len);
|
||||
cur->nfft=nfft;
|
||||
cur->inverse=inverse;
|
||||
cur->next = NULL;
|
||||
if ( prev )
|
||||
prev->next = cur;
|
||||
else
|
||||
cache_root = cur;
|
||||
++ncached;
|
||||
}
|
||||
return cur->cfg;
|
||||
}
|
||||
|
||||
void kfc_cleanup(void)
|
||||
{
|
||||
kfc_cfg cur=cache_root;
|
||||
kfc_cfg next=NULL;
|
||||
while (cur){
|
||||
next = cur->next;
|
||||
free(cur);
|
||||
cur=next;
|
||||
}
|
||||
ncached=0;
|
||||
cache_root = NULL;
|
||||
}
|
||||
void kfc_fft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout)
|
||||
{
|
||||
kiss_fft( find_cached_fft(nfft,0),fin,fout );
|
||||
}
|
||||
|
||||
void kfc_ifft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout)
|
||||
{
|
||||
kiss_fft( find_cached_fft(nfft,1),fin,fout );
|
||||
}
|
||||
|
||||
#ifdef KFC_TEST
|
||||
static void check(int nc)
|
||||
{
|
||||
if (ncached != nc) {
|
||||
fprintf(stderr,"ncached should be %d,but it is %d\n",nc,ncached);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
kiss_fft_cpx buf1[1024],buf2[1024];
|
||||
memset(buf1,0,sizeof(buf1));
|
||||
check(0);
|
||||
kfc_fft(512,buf1,buf2);
|
||||
check(1);
|
||||
kfc_fft(512,buf1,buf2);
|
||||
check(1);
|
||||
kfc_ifft(512,buf1,buf2);
|
||||
check(2);
|
||||
kfc_cleanup();
|
||||
check(0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
54
3rd-party/kissfft/kfc.h
vendored
54
3rd-party/kissfft/kfc.h
vendored
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef KFC_H
|
||||
#define KFC_H
|
||||
#include "kiss_fft.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
KFC -- Kiss FFT Cache
|
||||
|
||||
Not needing to deal with kiss_fft_alloc and a config
|
||||
object may be handy for a lot of programs.
|
||||
|
||||
KFC uses the underlying KISS FFT functions, but caches the config object.
|
||||
The first time kfc_fft or kfc_ifft for a given FFT size, the cfg
|
||||
object is created for it. All subsequent calls use the cached
|
||||
configuration object.
|
||||
|
||||
NOTE:
|
||||
You should probably not use this if your program will be using a lot
|
||||
of various sizes of FFTs. There is a linear search through the
|
||||
cached objects. If you are only using one or two FFT sizes, this
|
||||
will be negligible. Otherwise, you may want to use another method
|
||||
of managing the cfg objects.
|
||||
|
||||
There is no automated cleanup of the cached objects. This could lead
|
||||
to large memory usage in a program that uses a lot of *DIFFERENT*
|
||||
sized FFTs. If you want to force all cached cfg objects to be freed,
|
||||
call kfc_cleanup.
|
||||
|
||||
*/
|
||||
|
||||
/*forward complex FFT */
|
||||
void KISS_FFT_API kfc_fft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout);
|
||||
/*reverse complex FFT */
|
||||
void KISS_FFT_API kfc_ifft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout);
|
||||
|
||||
/*free all cached objects*/
|
||||
void KISS_FFT_API kfc_cleanup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
420
3rd-party/kissfft/kiss_fft.c
vendored
420
3rd-party/kissfft/kiss_fft.c
vendored
@ -1,420 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
|
||||
#include "_kiss_fft_guts.h"
|
||||
/* The guts header contains all the multiplication and addition macros that are defined for
|
||||
fixed or floating point complex numbers. It also delares the kf_ internal functions.
|
||||
*/
|
||||
|
||||
static void kf_bfly2(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
kiss_fft_cpx * tw1 = st->twiddles;
|
||||
kiss_fft_cpx t;
|
||||
Fout2 = Fout + m;
|
||||
do{
|
||||
C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
|
||||
|
||||
C_MUL (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}while (--m);
|
||||
}
|
||||
|
||||
static void kf_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
const size_t m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
size_t k=m;
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
|
||||
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
|
||||
do {
|
||||
C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
|
||||
|
||||
C_MUL(scratch[0],Fout[m] , *tw1 );
|
||||
C_MUL(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MUL(scratch[2],Fout[m3] , *tw3 );
|
||||
|
||||
C_SUB( scratch[5] , *Fout, scratch[1] );
|
||||
C_ADDTO(*Fout, scratch[1]);
|
||||
C_ADD( scratch[3] , scratch[0] , scratch[2] );
|
||||
C_SUB( scratch[4] , scratch[0] , scratch[2] );
|
||||
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
tw3 += fstride*3;
|
||||
C_ADDTO( *Fout , scratch[3] );
|
||||
|
||||
if(st->inverse) {
|
||||
Fout[m].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m].i = scratch[5].i + scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i - scratch[4].r;
|
||||
}else{
|
||||
Fout[m].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m].i = scratch[5].i - scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i + scratch[4].r;
|
||||
}
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
static void kf_bfly3(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
size_t m
|
||||
)
|
||||
{
|
||||
size_t k=m;
|
||||
const size_t m2 = 2*m;
|
||||
kiss_fft_cpx *tw1,*tw2;
|
||||
kiss_fft_cpx scratch[5];
|
||||
kiss_fft_cpx epi3;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
|
||||
tw1=tw2=st->twiddles;
|
||||
|
||||
do{
|
||||
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
||||
|
||||
C_MUL(scratch[1],Fout[m] , *tw1);
|
||||
C_MUL(scratch[2],Fout[m2] , *tw2);
|
||||
|
||||
C_ADD(scratch[3],scratch[1],scratch[2]);
|
||||
C_SUB(scratch[0],scratch[1],scratch[2]);
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
|
||||
Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
static void kf_bfly5(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||
int u;
|
||||
kiss_fft_cpx scratch[13];
|
||||
kiss_fft_cpx * twiddles = st->twiddles;
|
||||
kiss_fft_cpx *tw;
|
||||
kiss_fft_cpx ya,yb;
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
|
||||
Fout0=Fout;
|
||||
Fout1=Fout0+m;
|
||||
Fout2=Fout0+2*m;
|
||||
Fout3=Fout0+3*m;
|
||||
Fout4=Fout0+4*m;
|
||||
|
||||
tw=st->twiddles;
|
||||
for ( u=0; u<m; ++u ) {
|
||||
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
|
||||
|
||||
C_ADD( scratch[7],scratch[1],scratch[4]);
|
||||
C_SUB( scratch[10],scratch[1],scratch[4]);
|
||||
C_ADD( scratch[8],scratch[2],scratch[3]);
|
||||
C_SUB( scratch[9],scratch[2],scratch[3]);
|
||||
|
||||
Fout0->r += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
|
||||
|
||||
C_SUB(*Fout1,scratch[5],scratch[6]);
|
||||
C_ADD(*Fout4,scratch[5],scratch[6]);
|
||||
|
||||
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
|
||||
|
||||
C_ADD(*Fout2,scratch[11],scratch[12]);
|
||||
C_SUB(*Fout3,scratch[11],scratch[12]);
|
||||
|
||||
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform the butterfly for one stage of a mixed radix FFT */
|
||||
static void kf_bfly_generic(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_cfg st,
|
||||
int m,
|
||||
int p
|
||||
)
|
||||
{
|
||||
int u,k,q1,q;
|
||||
kiss_fft_cpx * twiddles = st->twiddles;
|
||||
kiss_fft_cpx t;
|
||||
int Norig = st->nfft;
|
||||
|
||||
kiss_fft_cpx * scratch = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC(sizeof(kiss_fft_cpx)*p);
|
||||
if (scratch == NULL){
|
||||
KISS_FFT_ERROR("Memory allocation failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
for ( u=0; u<m; ++u ) {
|
||||
k=u;
|
||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||
scratch[q1] = Fout[ k ];
|
||||
C_FIXDIV(scratch[q1],p);
|
||||
k += m;
|
||||
}
|
||||
|
||||
k=u;
|
||||
for ( q1=0 ; q1<p ; ++q1 ) {
|
||||
int twidx=0;
|
||||
Fout[ k ] = scratch[0];
|
||||
for (q=1;q<p;++q ) {
|
||||
twidx += fstride * k;
|
||||
if (twidx>=Norig) twidx-=Norig;
|
||||
C_MUL(t,scratch[q] , twiddles[twidx] );
|
||||
C_ADDTO( Fout[ k ] ,t);
|
||||
}
|
||||
k += m;
|
||||
}
|
||||
}
|
||||
KISS_FFT_TMP_FREE(scratch);
|
||||
}
|
||||
|
||||
static
|
||||
void kf_work(
|
||||
kiss_fft_cpx * Fout,
|
||||
const kiss_fft_cpx * f,
|
||||
const size_t fstride,
|
||||
int in_stride,
|
||||
int * factors,
|
||||
const kiss_fft_cfg st
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout_beg=Fout;
|
||||
const int p=*factors++; /* the radix */
|
||||
const int m=*factors++; /* stage's fft length/p */
|
||||
const kiss_fft_cpx * Fout_end = Fout + p*m;
|
||||
|
||||
#ifdef _OPENMP
|
||||
// use openmp extensions at the
|
||||
// top-level (not recursive)
|
||||
if (fstride==1 && p<=5 && m!=1)
|
||||
{
|
||||
int k;
|
||||
|
||||
// execute the p different work units in different threads
|
||||
# pragma omp parallel for
|
||||
for (k=0;k<p;++k)
|
||||
kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
|
||||
// all threads have joined by this point
|
||||
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m==1) {
|
||||
do{
|
||||
*Fout = *f;
|
||||
f += fstride*in_stride;
|
||||
}while(++Fout != Fout_end );
|
||||
}else{
|
||||
do{
|
||||
// recursive call:
|
||||
// DFT of size m*p performed by doing
|
||||
// p instances of smaller DFTs of size m,
|
||||
// each one takes a decimated version of the input
|
||||
kf_work( Fout , f, fstride*p, in_stride, factors,st);
|
||||
f += fstride*in_stride;
|
||||
}while( (Fout += m) != Fout_end );
|
||||
}
|
||||
|
||||
Fout=Fout_beg;
|
||||
|
||||
// recombine the p smaller DFTs
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m); break;
|
||||
case 3: kf_bfly3(Fout,fstride,st,m); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m); break;
|
||||
default: kf_bfly_generic(Fout,fstride,st,m,p); break;
|
||||
}
|
||||
}
|
||||
|
||||
/* facbuf is populated by p1,m1,p2,m2, ...
|
||||
where
|
||||
p[i] * m[i] = m[i-1]
|
||||
m0 = n */
|
||||
static
|
||||
void kf_factor(int n,int * facbuf)
|
||||
{
|
||||
int p=4;
|
||||
double floor_sqrt;
|
||||
floor_sqrt = floor( sqrt((double)n) );
|
||||
|
||||
/*factor out powers of 4, powers of 2, then any remaining primes */
|
||||
do {
|
||||
while (n % p) {
|
||||
switch (p) {
|
||||
case 4: p = 2; break;
|
||||
case 2: p = 3; break;
|
||||
default: p += 2; break;
|
||||
}
|
||||
if (p > floor_sqrt)
|
||||
p = n; /* no more factors, skip to end */
|
||||
}
|
||||
n /= p;
|
||||
*facbuf++ = p;
|
||||
*facbuf++ = n;
|
||||
} while (n > 1);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* User-callable function to allocate all necessary storage space for the fft.
|
||||
*
|
||||
* The return value is a contiguous block of memory, allocated with malloc. As such,
|
||||
* It can be freed with free(), rather than a kiss_fft-specific function.
|
||||
* */
|
||||
kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
|
||||
{
|
||||
KISS_FFT_ALIGN_CHECK(mem)
|
||||
|
||||
kiss_fft_cfg st=NULL;
|
||||
size_t memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fft_state)
|
||||
+ sizeof(kiss_fft_cpx)*(nfft-1)); /* twiddle factors*/
|
||||
|
||||
if ( lenmem==NULL ) {
|
||||
st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded );
|
||||
}else{
|
||||
if (mem != NULL && *lenmem >= memneeded)
|
||||
st = (kiss_fft_cfg)mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (st) {
|
||||
int i;
|
||||
st->nfft=nfft;
|
||||
st->inverse = inverse_fft;
|
||||
|
||||
for (i=0;i<nfft;++i) {
|
||||
const double pi=3.141592653589793238462643383279502884197169399375105820974944;
|
||||
double phase = -2*pi*i / nfft;
|
||||
if (st->inverse)
|
||||
phase *= -1;
|
||||
kf_cexp(st->twiddles+i, phase );
|
||||
}
|
||||
|
||||
kf_factor(nfft,st->factors);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||
{
|
||||
if (fin == fout) {
|
||||
//NOTE: this is not really an in-place FFT algorithm.
|
||||
//It just performs an out-of-place FFT into a temp buffer
|
||||
if (fout == NULL){
|
||||
KISS_FFT_ERROR("fout buffer NULL.");
|
||||
return;
|
||||
}
|
||||
|
||||
kiss_fft_cpx * tmpbuf = (kiss_fft_cpx*)KISS_FFT_TMP_ALLOC( sizeof(kiss_fft_cpx)*st->nfft);
|
||||
if (tmpbuf == NULL){
|
||||
KISS_FFT_ERROR("Memory allocation error.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
|
||||
memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
|
||||
KISS_FFT_TMP_FREE(tmpbuf);
|
||||
}else{
|
||||
kf_work( fout, fin, 1,in_stride, st->factors,st );
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
kiss_fft_stride(cfg,fin,fout,1);
|
||||
}
|
||||
|
||||
|
||||
void kiss_fft_cleanup(void)
|
||||
{
|
||||
// nothing needed any more
|
||||
}
|
||||
|
||||
int kiss_fft_next_fast_size(int n)
|
||||
{
|
||||
while(1) {
|
||||
int m=n;
|
||||
while ( (m%2) == 0 ) m/=2;
|
||||
while ( (m%3) == 0 ) m/=3;
|
||||
while ( (m%5) == 0 ) m/=5;
|
||||
if (m<=1)
|
||||
break; /* n is completely factorable by twos, threes, and fives */
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
160
3rd-party/kissfft/kiss_fft.h
vendored
160
3rd-party/kissfft/kiss_fft.h
vendored
@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef KISS_FFT_H
|
||||
#define KISS_FFT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
// Define KISS_FFT_SHARED macro to properly export symbols
|
||||
#ifdef KISS_FFT_SHARED
|
||||
# ifdef _WIN32
|
||||
# ifdef KISS_FFT_BUILD
|
||||
# define KISS_FFT_API __declspec(dllexport)
|
||||
# else
|
||||
# define KISS_FFT_API __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define KISS_FFT_API __attribute__ ((visibility ("default")))
|
||||
# endif
|
||||
#else
|
||||
# define KISS_FFT_API
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
ATTENTION!
|
||||
If you would like a :
|
||||
-- a utility that will handle the caching of fft objects
|
||||
-- real-only (no imaginary time component ) FFT
|
||||
-- a multi-dimensional FFT
|
||||
-- a command-line utility to perform ffts
|
||||
-- a command-line utility to perform fast-convolution filtering
|
||||
|
||||
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
|
||||
in the tools/ directory.
|
||||
*/
|
||||
|
||||
/* User may override KISS_FFT_MALLOC and/or KISS_FFT_FREE. */
|
||||
#ifdef USE_SIMD
|
||||
# include <xmmintrin.h>
|
||||
# define kiss_fft_scalar __m128
|
||||
# ifndef KISS_FFT_MALLOC
|
||||
# define KISS_FFT_MALLOC(nbytes) _mm_malloc(nbytes,16)
|
||||
# define KISS_FFT_ALIGN_CHECK(ptr)
|
||||
# define KISS_FFT_ALIGN_SIZE_UP(size) ((size + 15UL) & ~0xFUL)
|
||||
# endif
|
||||
# ifndef KISS_FFT_FREE
|
||||
# define KISS_FFT_FREE _mm_free
|
||||
# endif
|
||||
#else
|
||||
# define KISS_FFT_ALIGN_CHECK(ptr)
|
||||
# define KISS_FFT_ALIGN_SIZE_UP(size) (size)
|
||||
# ifndef KISS_FFT_MALLOC
|
||||
# define KISS_FFT_MALLOC malloc
|
||||
# endif
|
||||
# ifndef KISS_FFT_FREE
|
||||
# define KISS_FFT_FREE free
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#include <stdint.h>
|
||||
# if (FIXED_POINT == 32)
|
||||
# define kiss_fft_scalar int32_t
|
||||
# else
|
||||
# define kiss_fft_scalar int16_t
|
||||
# endif
|
||||
#else
|
||||
# ifndef kiss_fft_scalar
|
||||
/* default is float */
|
||||
# define kiss_fft_scalar float
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kiss_fft_scalar r;
|
||||
kiss_fft_scalar i;
|
||||
}kiss_fft_cpx;
|
||||
|
||||
typedef struct kiss_fft_state* kiss_fft_cfg;
|
||||
|
||||
/*
|
||||
* kiss_fft_alloc
|
||||
*
|
||||
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
|
||||
*
|
||||
* typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
|
||||
*
|
||||
* The return value from fft_alloc is a cfg buffer used internally
|
||||
* by the fft routine or NULL.
|
||||
*
|
||||
* If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
|
||||
* The returned value should be free()d when done to avoid memory leaks.
|
||||
*
|
||||
* The state can be placed in a user supplied buffer 'mem':
|
||||
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
|
||||
* then the function places the cfg in mem and the size used in *lenmem
|
||||
* and returns mem.
|
||||
*
|
||||
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
|
||||
* then the function returns NULL and places the minimum cfg
|
||||
* buffer size in *lenmem.
|
||||
* */
|
||||
|
||||
kiss_fft_cfg KISS_FFT_API kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
|
||||
|
||||
/*
|
||||
* kiss_fft(cfg,in_out_buf)
|
||||
*
|
||||
* Perform an FFT on a complex input buffer.
|
||||
* for a forward FFT,
|
||||
* fin should be f[0] , f[1] , ... ,f[nfft-1]
|
||||
* fout will be F[0] , F[1] , ... ,F[nfft-1]
|
||||
* Note that each element is complex and can be accessed like
|
||||
f[k].r and f[k].i
|
||||
* */
|
||||
void KISS_FFT_API kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
|
||||
/*
|
||||
A more generic version of the above function. It reads its input from every Nth sample.
|
||||
* */
|
||||
void KISS_FFT_API kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
|
||||
|
||||
/* If kiss_fft_alloc allocated a buffer, it is one contiguous
|
||||
buffer and can be simply free()d when no longer needed*/
|
||||
#define kiss_fft_free KISS_FFT_FREE
|
||||
|
||||
/*
|
||||
Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
|
||||
your compiler output to call this before you exit.
|
||||
*/
|
||||
void KISS_FFT_API kiss_fft_cleanup(void);
|
||||
|
||||
|
||||
/*
|
||||
* Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
|
||||
*/
|
||||
int KISS_FFT_API kiss_fft_next_fast_size(int n);
|
||||
|
||||
/* for real ffts, we need an even size */
|
||||
#define kiss_fftr_next_fast_size_real(n) \
|
||||
(kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
36
3rd-party/kissfft/kiss_fft_log.h
vendored
36
3rd-party/kissfft/kiss_fft_log.h
vendored
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef kiss_fft_log_h
|
||||
#define kiss_fft_log_h
|
||||
|
||||
#define ERROR 1
|
||||
#define WARNING 2
|
||||
#define INFO 3
|
||||
#define DEBUG 4
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define KISS_FFT_LOG_MSG(severity, ...) ((void)0)
|
||||
#else
|
||||
# define KISS_FFT_LOG_MSG(severity, ...) \
|
||||
fprintf(stderr, "[" #severity "] " __FILE__ ":" TOSTRING(__LINE__) " "); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n")
|
||||
#endif
|
||||
|
||||
#define KISS_FFT_ERROR(...) KISS_FFT_LOG_MSG(ERROR, __VA_ARGS__)
|
||||
#define KISS_FFT_WARNING(...) KISS_FFT_LOG_MSG(WARNING, __VA_ARGS__)
|
||||
#define KISS_FFT_INFO(...) KISS_FFT_LOG_MSG(INFO, __VA_ARGS__)
|
||||
#define KISS_FFT_DEBUG(...) KISS_FFT_LOG_MSG(DEBUG, __VA_ARGS__)
|
||||
|
||||
|
||||
|
||||
#endif /* kiss_fft_log_h */
|
188
3rd-party/kissfft/kiss_fftnd.c
vendored
188
3rd-party/kissfft/kiss_fftnd.c
vendored
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include "kiss_fftnd.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
|
||||
struct kiss_fftnd_state{
|
||||
int dimprod; /* dimsum would be mighty tasty right now */
|
||||
int ndims;
|
||||
int *dims;
|
||||
kiss_fft_cfg *states; /* cfg states for each dimension */
|
||||
kiss_fft_cpx * tmpbuf; /*buffer capable of hold the entire input */
|
||||
};
|
||||
|
||||
kiss_fftnd_cfg kiss_fftnd_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem)
|
||||
{
|
||||
KISS_FFT_ALIGN_CHECK(mem)
|
||||
|
||||
kiss_fftnd_cfg st = NULL;
|
||||
int i;
|
||||
int dimprod=1;
|
||||
size_t memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftnd_state));
|
||||
char * ptr = NULL;
|
||||
|
||||
for (i=0;i<ndims;++i) {
|
||||
size_t sublen=0;
|
||||
kiss_fft_alloc (dims[i], inverse_fft, NULL, &sublen);
|
||||
memneeded += sublen; /* st->states[i] */
|
||||
dimprod *= dims[i];
|
||||
}
|
||||
memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(int) * ndims);/* st->dims */
|
||||
memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(void*) * ndims);/* st->states */
|
||||
memneeded += KISS_FFT_ALIGN_SIZE_UP(sizeof(kiss_fft_cpx) * dimprod); /* st->tmpbuf */
|
||||
|
||||
if (lenmem == NULL) {/* allocate for the caller*/
|
||||
ptr = (char *) malloc (memneeded);
|
||||
} else { /* initialize supplied buffer if big enough */
|
||||
if (*lenmem >= memneeded)
|
||||
ptr = (char *) mem;
|
||||
*lenmem = memneeded; /*tell caller how big struct is (or would be) */
|
||||
}
|
||||
if (!ptr)
|
||||
return NULL; /*malloc failed or buffer too small */
|
||||
|
||||
st = (kiss_fftnd_cfg) ptr;
|
||||
st->dimprod = dimprod;
|
||||
st->ndims = ndims;
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftnd_state));
|
||||
|
||||
st->states = (kiss_fft_cfg *)ptr;
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(void*) * ndims);
|
||||
|
||||
st->dims = (int*)ptr;
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(int) * ndims);
|
||||
|
||||
st->tmpbuf = (kiss_fft_cpx*)ptr;
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(kiss_fft_cpx) * dimprod);
|
||||
|
||||
for (i=0;i<ndims;++i) {
|
||||
size_t len;
|
||||
st->dims[i] = dims[i];
|
||||
kiss_fft_alloc (st->dims[i], inverse_fft, NULL, &len);
|
||||
st->states[i] = kiss_fft_alloc (st->dims[i], inverse_fft, ptr,&len);
|
||||
ptr += len;
|
||||
}
|
||||
/*
|
||||
Hi there!
|
||||
|
||||
If you're looking at this particular code, it probably means you've got a brain-dead bounds checker
|
||||
that thinks the above code overwrites the end of the array.
|
||||
|
||||
It doesn't.
|
||||
|
||||
-- Mark
|
||||
|
||||
P.S.
|
||||
The below code might give you some warm fuzzies and help convince you.
|
||||
*/
|
||||
if ( ptr - (char*)st != (int)memneeded ) {
|
||||
fprintf(stderr,
|
||||
"################################################################################\n"
|
||||
"Internal error! Memory allocation miscalculation\n"
|
||||
"################################################################################\n"
|
||||
);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
/*
|
||||
This works by tackling one dimension at a time.
|
||||
|
||||
In effect,
|
||||
Each stage starts out by reshaping the matrix into a DixSi 2d matrix.
|
||||
A Di-sized fft is taken of each column, transposing the matrix as it goes.
|
||||
|
||||
Here's a 3-d example:
|
||||
Take a 2x3x4 matrix, laid out in memory as a contiguous buffer
|
||||
[ [ [ a b c d ] [ e f g h ] [ i j k l ] ]
|
||||
[ [ m n o p ] [ q r s t ] [ u v w x ] ] ]
|
||||
|
||||
Stage 0 ( D=2): treat the buffer as a 2x12 matrix
|
||||
[ [a b ... k l]
|
||||
[m n ... w x] ]
|
||||
|
||||
FFT each column with size 2.
|
||||
Transpose the matrix at the same time using kiss_fft_stride.
|
||||
|
||||
[ [ a+m a-m ]
|
||||
[ b+n b-n]
|
||||
...
|
||||
[ k+w k-w ]
|
||||
[ l+x l-x ] ]
|
||||
|
||||
Note fft([x y]) == [x+y x-y]
|
||||
|
||||
Stage 1 ( D=3) treats the buffer (the output of stage D=2) as an 3x8 matrix,
|
||||
[ [ a+m a-m b+n b-n c+o c-o d+p d-p ]
|
||||
[ e+q e-q f+r f-r g+s g-s h+t h-t ]
|
||||
[ i+u i-u j+v j-v k+w k-w l+x l-x ] ]
|
||||
|
||||
And perform FFTs (size=3) on each of the columns as above, transposing
|
||||
the matrix as it goes. The output of stage 1 is
|
||||
(Legend: ap = [ a+m e+q i+u ]
|
||||
am = [ a-m e-q i-u ] )
|
||||
|
||||
[ [ sum(ap) fft(ap)[0] fft(ap)[1] ]
|
||||
[ sum(am) fft(am)[0] fft(am)[1] ]
|
||||
[ sum(bp) fft(bp)[0] fft(bp)[1] ]
|
||||
[ sum(bm) fft(bm)[0] fft(bm)[1] ]
|
||||
[ sum(cp) fft(cp)[0] fft(cp)[1] ]
|
||||
[ sum(cm) fft(cm)[0] fft(cm)[1] ]
|
||||
[ sum(dp) fft(dp)[0] fft(dp)[1] ]
|
||||
[ sum(dm) fft(dm)[0] fft(dm)[1] ] ]
|
||||
|
||||
Stage 2 ( D=4) treats this buffer as a 4*6 matrix,
|
||||
[ [ sum(ap) fft(ap)[0] fft(ap)[1] sum(am) fft(am)[0] fft(am)[1] ]
|
||||
[ sum(bp) fft(bp)[0] fft(bp)[1] sum(bm) fft(bm)[0] fft(bm)[1] ]
|
||||
[ sum(cp) fft(cp)[0] fft(cp)[1] sum(cm) fft(cm)[0] fft(cm)[1] ]
|
||||
[ sum(dp) fft(dp)[0] fft(dp)[1] sum(dm) fft(dm)[0] fft(dm)[1] ] ]
|
||||
|
||||
Then FFTs each column, transposing as it goes.
|
||||
|
||||
The resulting matrix is the 3d FFT of the 2x3x4 input matrix.
|
||||
|
||||
Note as a sanity check that the first element of the final
|
||||
stage's output (DC term) is
|
||||
sum( [ sum(ap) sum(bp) sum(cp) sum(dp) ] )
|
||||
, i.e. the summation of all 24 input elements.
|
||||
|
||||
*/
|
||||
void kiss_fftnd(kiss_fftnd_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
int i,k;
|
||||
const kiss_fft_cpx * bufin=fin;
|
||||
kiss_fft_cpx * bufout;
|
||||
|
||||
/*arrange it so the last bufout == fout*/
|
||||
if ( st->ndims & 1 ) {
|
||||
bufout = fout;
|
||||
if (fin==fout) {
|
||||
memcpy( st->tmpbuf, fin, sizeof(kiss_fft_cpx) * st->dimprod );
|
||||
bufin = st->tmpbuf;
|
||||
}
|
||||
}else
|
||||
bufout = st->tmpbuf;
|
||||
|
||||
for ( k=0; k < st->ndims; ++k) {
|
||||
int curdim = st->dims[k];
|
||||
int stride = st->dimprod / curdim;
|
||||
|
||||
for ( i=0 ; i<stride ; ++i )
|
||||
kiss_fft_stride( st->states[k], bufin+i , bufout+i*curdim, stride );
|
||||
|
||||
/*toggle back and forth between the two buffers*/
|
||||
if (bufout == st->tmpbuf){
|
||||
bufout = fout;
|
||||
bufin = st->tmpbuf;
|
||||
}else{
|
||||
bufout = st->tmpbuf;
|
||||
bufin = fout;
|
||||
}
|
||||
}
|
||||
}
|
26
3rd-party/kissfft/kiss_fftnd.h
vendored
26
3rd-party/kissfft/kiss_fftnd.h
vendored
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef KISS_FFTND_H
|
||||
#define KISS_FFTND_H
|
||||
|
||||
#include "kiss_fft.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kiss_fftnd_state * kiss_fftnd_cfg;
|
||||
|
||||
kiss_fftnd_cfg KISS_FFT_API kiss_fftnd_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem);
|
||||
void KISS_FFT_API kiss_fftnd(kiss_fftnd_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
120
3rd-party/kissfft/kiss_fftndr.c
vendored
120
3rd-party/kissfft/kiss_fftndr.c
vendored
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include "kiss_fftndr.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
#define MAX(x,y) ( ( (x)<(y) )?(y):(x) )
|
||||
|
||||
struct kiss_fftndr_state
|
||||
{
|
||||
int dimReal;
|
||||
int dimOther;
|
||||
kiss_fftr_cfg cfg_r;
|
||||
kiss_fftnd_cfg cfg_nd;
|
||||
void * tmpbuf;
|
||||
};
|
||||
|
||||
static int prod(const int *dims, int ndims)
|
||||
{
|
||||
int x=1;
|
||||
while (ndims--)
|
||||
x *= *dims++;
|
||||
return x;
|
||||
}
|
||||
|
||||
kiss_fftndr_cfg kiss_fftndr_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem)
|
||||
{
|
||||
KISS_FFT_ALIGN_CHECK(mem)
|
||||
|
||||
kiss_fftndr_cfg st = NULL;
|
||||
size_t nr=0 , nd=0,ntmp=0;
|
||||
int dimReal = dims[ndims-1];
|
||||
int dimOther = prod(dims,ndims-1);
|
||||
size_t memneeded;
|
||||
char * ptr = NULL;
|
||||
|
||||
(void)kiss_fftr_alloc(dimReal,inverse_fft,NULL,&nr);
|
||||
(void)kiss_fftnd_alloc(dims,ndims-1,inverse_fft,NULL,&nd);
|
||||
ntmp =
|
||||
MAX( 2*dimOther , dimReal+2) * sizeof(kiss_fft_scalar) // freq buffer for one pass
|
||||
+ dimOther*(dimReal+2) * sizeof(kiss_fft_scalar); // large enough to hold entire input in case of in-place
|
||||
|
||||
memneeded = KISS_FFT_ALIGN_SIZE_UP(sizeof( struct kiss_fftndr_state )) + KISS_FFT_ALIGN_SIZE_UP(nr) + KISS_FFT_ALIGN_SIZE_UP(nd) + KISS_FFT_ALIGN_SIZE_UP(ntmp);
|
||||
|
||||
if (lenmem==NULL) {
|
||||
ptr = (char*) malloc(memneeded);
|
||||
}else{
|
||||
if (*lenmem >= memneeded)
|
||||
ptr = (char *)mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (ptr==NULL)
|
||||
return NULL;
|
||||
|
||||
st = (kiss_fftndr_cfg) ptr;
|
||||
memset( st , 0 , memneeded);
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(sizeof(struct kiss_fftndr_state));
|
||||
|
||||
st->dimReal = dimReal;
|
||||
st->dimOther = dimOther;
|
||||
st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,ptr,&nr);
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(nr);
|
||||
st->cfg_nd = kiss_fftnd_alloc(dims,ndims-1,inverse_fft, ptr,&nd);
|
||||
ptr += KISS_FFT_ALIGN_SIZE_UP(nd);
|
||||
st->tmpbuf = ptr;
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
void kiss_fftndr(kiss_fftndr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
|
||||
{
|
||||
int k1,k2;
|
||||
int dimReal = st->dimReal;
|
||||
int dimOther = st->dimOther;
|
||||
int nrbins = dimReal/2+1;
|
||||
|
||||
kiss_fft_cpx * tmp1 = (kiss_fft_cpx*)st->tmpbuf;
|
||||
kiss_fft_cpx * tmp2 = tmp1 + MAX(nrbins,dimOther);
|
||||
|
||||
// timedata is N0 x N1 x ... x Nk real
|
||||
|
||||
// take a real chunk of data, fft it and place the output at correct intervals
|
||||
for (k1=0;k1<dimOther;++k1) {
|
||||
kiss_fftr( st->cfg_r, timedata + k1*dimReal , tmp1 ); // tmp1 now holds nrbins complex points
|
||||
for (k2=0;k2<nrbins;++k2)
|
||||
tmp2[ k2*dimOther+k1 ] = tmp1[k2];
|
||||
}
|
||||
|
||||
for (k2=0;k2<nrbins;++k2) {
|
||||
kiss_fftnd(st->cfg_nd, tmp2+k2*dimOther, tmp1); // tmp1 now holds dimOther complex points
|
||||
for (k1=0;k1<dimOther;++k1)
|
||||
freqdata[ k1*(nrbins) + k2] = tmp1[k1];
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fftndri(kiss_fftndr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
|
||||
{
|
||||
int k1,k2;
|
||||
int dimReal = st->dimReal;
|
||||
int dimOther = st->dimOther;
|
||||
int nrbins = dimReal/2+1;
|
||||
kiss_fft_cpx * tmp1 = (kiss_fft_cpx*)st->tmpbuf;
|
||||
kiss_fft_cpx * tmp2 = tmp1 + MAX(nrbins,dimOther);
|
||||
|
||||
for (k2=0;k2<nrbins;++k2) {
|
||||
for (k1=0;k1<dimOther;++k1)
|
||||
tmp1[k1] = freqdata[ k1*(nrbins) + k2 ];
|
||||
kiss_fftnd(st->cfg_nd, tmp1, tmp2+k2*dimOther);
|
||||
}
|
||||
|
||||
for (k1=0;k1<dimOther;++k1) {
|
||||
for (k2=0;k2<nrbins;++k2)
|
||||
tmp1[k2] = tmp2[ k2*dimOther+k1 ];
|
||||
kiss_fftri( st->cfg_r,tmp1,timedata + k1*dimReal);
|
||||
}
|
||||
}
|
55
3rd-party/kissfft/kiss_fftndr.h
vendored
55
3rd-party/kissfft/kiss_fftndr.h
vendored
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef KISS_NDR_H
|
||||
#define KISS_NDR_H
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fftr.h"
|
||||
#include "kiss_fftnd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct kiss_fftndr_state *kiss_fftndr_cfg;
|
||||
|
||||
|
||||
kiss_fftndr_cfg KISS_FFT_API kiss_fftndr_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem);
|
||||
/*
|
||||
dims[0] must be even
|
||||
|
||||
If you don't care to allocate space, use mem = lenmem = NULL
|
||||
*/
|
||||
|
||||
|
||||
void KISS_FFT_API kiss_fftndr(
|
||||
kiss_fftndr_cfg cfg,
|
||||
const kiss_fft_scalar *timedata,
|
||||
kiss_fft_cpx *freqdata);
|
||||
/*
|
||||
input timedata has dims[0] X dims[1] X ... X dims[ndims-1] scalar points
|
||||
output freqdata has dims[0] X dims[1] X ... X dims[ndims-1]/2+1 complex points
|
||||
*/
|
||||
|
||||
void KISS_FFT_API kiss_fftndri(
|
||||
kiss_fftndr_cfg cfg,
|
||||
const kiss_fft_cpx *freqdata,
|
||||
kiss_fft_scalar *timedata);
|
||||
/*
|
||||
input and output dimensions are the exact opposite of kiss_fftndr
|
||||
*/
|
||||
|
||||
|
||||
#define kiss_fftndr_free free
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
155
3rd-party/kissfft/kiss_fftr.c
vendored
155
3rd-party/kissfft/kiss_fftr.c
vendored
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include "kiss_fftr.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
|
||||
struct kiss_fftr_state{
|
||||
kiss_fft_cfg substate;
|
||||
kiss_fft_cpx * tmpbuf;
|
||||
kiss_fft_cpx * super_twiddles;
|
||||
#ifdef USE_SIMD
|
||||
void * pad;
|
||||
#endif
|
||||
};
|
||||
|
||||
kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
|
||||
{
|
||||
KISS_FFT_ALIGN_CHECK(mem)
|
||||
|
||||
int i;
|
||||
kiss_fftr_cfg st = NULL;
|
||||
size_t subsize = 0, memneeded;
|
||||
|
||||
if (nfft & 1) {
|
||||
KISS_FFT_ERROR("Real FFT optimization must be even.");
|
||||
return NULL;
|
||||
}
|
||||
nfft >>= 1;
|
||||
|
||||
kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
|
||||
memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
|
||||
|
||||
if (lenmem == NULL) {
|
||||
st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
|
||||
} else {
|
||||
if (*lenmem >= memneeded)
|
||||
st = (kiss_fftr_cfg) mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
|
||||
st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
|
||||
st->super_twiddles = st->tmpbuf + nfft;
|
||||
kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
|
||||
|
||||
for (i = 0; i < nfft/2; ++i) {
|
||||
double phase =
|
||||
-3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
|
||||
if (inverse_fft)
|
||||
phase *= -1;
|
||||
kf_cexp (st->super_twiddles+i,phase);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
|
||||
{
|
||||
/* input buffer timedata is stored row-wise */
|
||||
int k,ncfft;
|
||||
kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
|
||||
|
||||
if ( st->substate->inverse) {
|
||||
KISS_FFT_ERROR("kiss fft usage error: improper alloc");
|
||||
return;/* The caller did not call the correct function */
|
||||
}
|
||||
|
||||
ncfft = st->substate->nfft;
|
||||
|
||||
/*perform the parallel fft of two real signals packed in real,imag*/
|
||||
kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
|
||||
/* The real part of the DC element of the frequency spectrum in st->tmpbuf
|
||||
* contains the sum of the even-numbered elements of the input time sequence
|
||||
* The imag part is the sum of the odd-numbered elements
|
||||
*
|
||||
* The sum of tdc.r and tdc.i is the sum of the input time sequence.
|
||||
* yielding DC of input time sequence
|
||||
* The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
|
||||
* yielding Nyquist bin of input time sequence
|
||||
*/
|
||||
|
||||
tdc.r = st->tmpbuf[0].r;
|
||||
tdc.i = st->tmpbuf[0].i;
|
||||
C_FIXDIV(tdc,2);
|
||||
CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
|
||||
CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
|
||||
freqdata[0].r = tdc.r + tdc.i;
|
||||
freqdata[ncfft].r = tdc.r - tdc.i;
|
||||
#ifdef USE_SIMD
|
||||
freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
|
||||
#else
|
||||
freqdata[ncfft].i = freqdata[0].i = 0;
|
||||
#endif
|
||||
|
||||
for ( k=1;k <= ncfft/2 ; ++k ) {
|
||||
fpk = st->tmpbuf[k];
|
||||
fpnk.r = st->tmpbuf[ncfft-k].r;
|
||||
fpnk.i = - st->tmpbuf[ncfft-k].i;
|
||||
C_FIXDIV(fpk,2);
|
||||
C_FIXDIV(fpnk,2);
|
||||
|
||||
C_ADD( f1k, fpk , fpnk );
|
||||
C_SUB( f2k, fpk , fpnk );
|
||||
C_MUL( tw , f2k , st->super_twiddles[k-1]);
|
||||
|
||||
freqdata[k].r = HALF_OF(f1k.r + tw.r);
|
||||
freqdata[k].i = HALF_OF(f1k.i + tw.i);
|
||||
freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
|
||||
freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
|
||||
}
|
||||
}
|
||||
|
||||
void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
|
||||
{
|
||||
/* input buffer timedata is stored row-wise */
|
||||
int k, ncfft;
|
||||
|
||||
if (st->substate->inverse == 0) {
|
||||
KISS_FFT_ERROR("kiss fft usage error: improper alloc");
|
||||
return;/* The caller did not call the correct function */
|
||||
}
|
||||
|
||||
ncfft = st->substate->nfft;
|
||||
|
||||
st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
|
||||
st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
|
||||
C_FIXDIV(st->tmpbuf[0],2);
|
||||
|
||||
for (k = 1; k <= ncfft / 2; ++k) {
|
||||
kiss_fft_cpx fk, fnkc, fek, fok, tmp;
|
||||
fk = freqdata[k];
|
||||
fnkc.r = freqdata[ncfft - k].r;
|
||||
fnkc.i = -freqdata[ncfft - k].i;
|
||||
C_FIXDIV( fk , 2 );
|
||||
C_FIXDIV( fnkc , 2 );
|
||||
|
||||
C_ADD (fek, fk, fnkc);
|
||||
C_SUB (tmp, fk, fnkc);
|
||||
C_MUL (fok, tmp, st->super_twiddles[k-1]);
|
||||
C_ADD (st->tmpbuf[k], fek, fok);
|
||||
C_SUB (st->tmpbuf[ncfft - k], fek, fok);
|
||||
#ifdef USE_SIMD
|
||||
st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
|
||||
#else
|
||||
st->tmpbuf[ncfft - k].i *= -1;
|
||||
#endif
|
||||
}
|
||||
kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
|
||||
}
|
54
3rd-party/kissfft/kiss_fftr.h
vendored
54
3rd-party/kissfft/kiss_fftr.h
vendored
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef KISS_FTR_H
|
||||
#define KISS_FTR_H
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Real optimized version can save about 45% cpu time vs. complex fft of a real seq.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
typedef struct kiss_fftr_state *kiss_fftr_cfg;
|
||||
|
||||
|
||||
kiss_fftr_cfg KISS_FFT_API kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem);
|
||||
/*
|
||||
nfft must be even
|
||||
|
||||
If you don't care to allocate space, use mem = lenmem = NULL
|
||||
*/
|
||||
|
||||
|
||||
void KISS_FFT_API kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata);
|
||||
/*
|
||||
input timedata has nfft scalar points
|
||||
output freqdata has nfft/2+1 complex points
|
||||
*/
|
||||
|
||||
void KISS_FFT_API kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata);
|
||||
/*
|
||||
input freqdata has nfft/2+1 complex points
|
||||
output timedata has nfft scalar points
|
||||
*/
|
||||
|
||||
#define kiss_fftr_free KISS_FFT_FREE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
82
3rd-party/kissfft/kissfft-config.cmake.in
vendored
82
3rd-party/kissfft/kissfft-config.cmake.in
vendored
@ -1,82 +0,0 @@
|
||||
# kissfft-config.ccmake accept the following components:
|
||||
#
|
||||
# SHARED/STATIC:
|
||||
# This components allows one to choose a shared/static kissfft library.
|
||||
# The default is selected by BUILD_SHARED_LIBS.
|
||||
# They are to be used exclusively. Using them together is an error.
|
||||
#
|
||||
# example:
|
||||
# find_package(kissfft CONFIG REQUIRED COMPONENTS STATIC)
|
||||
#
|
||||
# simd/int16/int32/float/double:
|
||||
# This components allows one to choose the datatype.
|
||||
# When using this component, the target kissfft::kissfft becomes available.
|
||||
# When not using this component, you will have to choose the correct kissfft target.
|
||||
#
|
||||
# example:
|
||||
# find_package(kissfft CONFIG REQUIRED)
|
||||
# # - kissfft::kissfft-float, kissfft::kissfft-int32_t/ ... are available (if they are installed)
|
||||
# # - kissfft::kissfft is not available,
|
||||
#
|
||||
# find_package(kissfft CONFIG REQUIRED COMPONENTS int32_t)
|
||||
# # - kissfft::kissfft-float, kissfft::kissfft-int32_t/ ... are available (if they are installed)
|
||||
# # - kissfft::kissfft is available (as an alias for kissfft::kissfft-int32_t),
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
|
||||
# Set include glob of config files using SHARED/static component, BUILD_SHARED_LIBS by default
|
||||
set(_kissfft_shared_detected OFF)
|
||||
set(_kissfft_shared ${BUILD_SHARED_LIBS})
|
||||
if("SHARED" IN_LIST kissfft_FIND_COMPONENTS)
|
||||
set(_kissfft_shared_detected ON)
|
||||
set(_kissfft_shared ON)
|
||||
endif()
|
||||
if("STATIC" IN_LIST kissfft_FIND_COMPONENTS)
|
||||
if(_kissfft_shared_detected)
|
||||
message(FATAL_ERROR "SHARED and STATIC components cannot be used together")
|
||||
endif()
|
||||
set(_kissfft_shared_detected ON)
|
||||
set(_kissfft_shared OFF)
|
||||
endif()
|
||||
|
||||
if(_kissfft_shared)
|
||||
set(_kissfft_config_glob "kissfft-*-shared-targets.cmake")
|
||||
else()
|
||||
set(_kissfft_config_glob "kissfft-*-static-targets.cmake")
|
||||
endif()
|
||||
|
||||
# Load information for all configured kissfft
|
||||
get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
file(GLOB CONFIG_FILES "${_DIR}/${_kissfft_config_glob}")
|
||||
foreach(f ${CONFIG_FILES})
|
||||
include(${f})
|
||||
endforeach()
|
||||
|
||||
# If a datatype component is passed, create kissfft::kissfft
|
||||
set(_kissfft_datatype_detected)
|
||||
foreach(_kissfft_datatype simd int16 int32 float double)
|
||||
if(_kissfft_datatype IN_LIST kissfft_FIND_COMPONENTS)
|
||||
if(_kissfft_datatype_detected)
|
||||
message(FATAL_ERROR "Cannot define datatype COMPONENT twice: ${_kissfft_datatype_detected} and ${_kissfft_datatype}")
|
||||
endif()
|
||||
set(_kissfft_datatype_detected ${_kissfft_datatype})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(_kissfft_datatype_detected)
|
||||
if(NOT TARGET kissfft::kissfft-${_kissfft_datatype_detected})
|
||||
message(FATAL_ERROR "kissfft with datatype=${_kissfft_datatype_detected} is not installed")
|
||||
endif()
|
||||
if(TARGET kissfft::kissfft)
|
||||
message(SEND_ERROR "kissfft::kissfft already exists. You cannot use 2 find_package's with datatype that are visible to eachother.")
|
||||
else()
|
||||
add_library(kissfft::kissfft INTERFACE IMPORTED)
|
||||
set_property(TARGET kissfft::kissfft PROPERTY INTERFACE_LINK_LIBRARIES kissfft::kissfft-${_kissfft_datatype_detected})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(kissfft_FOUND ON)
|
||||
set(KISSFFT_VERSION @kissfft_VERSION@)
|
||||
|
361
3rd-party/kissfft/kissfft.hh
vendored
361
3rd-party/kissfft/kissfft.hh
vendored
@ -1,361 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#ifndef KISSFFT_CLASS_HH
|
||||
#define KISSFFT_CLASS_HH
|
||||
#include <complex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
template <typename scalar_t>
|
||||
class kissfft
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::complex<scalar_t> cpx_t;
|
||||
|
||||
kissfft( const std::size_t nfft,
|
||||
const bool inverse )
|
||||
:_nfft(nfft)
|
||||
,_inverse(inverse)
|
||||
{
|
||||
// fill twiddle factors
|
||||
_twiddles.resize(_nfft);
|
||||
const scalar_t phinc = (_inverse?2:-2)* std::acos( (scalar_t) -1) / _nfft;
|
||||
for (std::size_t i=0;i<_nfft;++i)
|
||||
_twiddles[i] = std::exp( cpx_t(0,i*phinc) );
|
||||
|
||||
//factorize
|
||||
//start factoring out 4's, then 2's, then 3,5,7,9,...
|
||||
std::size_t n= _nfft;
|
||||
std::size_t p=4;
|
||||
do {
|
||||
while (n % p) {
|
||||
switch (p) {
|
||||
case 4: p = 2; break;
|
||||
case 2: p = 3; break;
|
||||
default: p += 2; break;
|
||||
}
|
||||
if (p*p>n)
|
||||
p = n;// no more factors
|
||||
}
|
||||
n /= p;
|
||||
_stageRadix.push_back(p);
|
||||
_stageRemainder.push_back(n);
|
||||
}while(n>1);
|
||||
}
|
||||
|
||||
|
||||
/// Changes the FFT-length and/or the transform direction.
|
||||
///
|
||||
/// @post The @c kissfft object will be in the same state as if it
|
||||
/// had been newly constructed with the passed arguments.
|
||||
/// However, the implementation may be faster than constructing a
|
||||
/// new fft object.
|
||||
void assign( const std::size_t nfft,
|
||||
const bool inverse )
|
||||
{
|
||||
if ( nfft != _nfft )
|
||||
{
|
||||
kissfft tmp( nfft, inverse ); // O(n) time.
|
||||
std::swap( tmp, *this ); // this is O(1) in C++11, O(n) otherwise.
|
||||
}
|
||||
else if ( inverse != _inverse )
|
||||
{
|
||||
// conjugate the twiddle factors.
|
||||
for ( typename std::vector<cpx_t>::iterator it = _twiddles.begin();
|
||||
it != _twiddles.end(); ++it )
|
||||
it->imag( -it->imag() );
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the complex Discrete Fourier Transform.
|
||||
///
|
||||
/// The size of the passed arrays must be passed in the constructor.
|
||||
/// The sum of the squares of the absolute values in the @c dst
|
||||
/// array will be @c N times the sum of the squares of the absolute
|
||||
/// values in the @c src array, where @c N is the size of the array.
|
||||
/// In other words, the l_2 norm of the resulting array will be
|
||||
/// @c sqrt(N) times as big as the l_2 norm of the input array.
|
||||
/// This is also the case when the inverse flag is set in the
|
||||
/// constructor. Hence when applying the same transform twice, but with
|
||||
/// the inverse flag changed the second time, then the result will
|
||||
/// be equal to the original input times @c N.
|
||||
void transform(const cpx_t * fft_in, cpx_t * fft_out, const std::size_t stage = 0, const std::size_t fstride = 1, const std::size_t in_stride = 1) const
|
||||
{
|
||||
const std::size_t p = _stageRadix[stage];
|
||||
const std::size_t m = _stageRemainder[stage];
|
||||
cpx_t * const Fout_beg = fft_out;
|
||||
cpx_t * const Fout_end = fft_out + p*m;
|
||||
|
||||
if (m==1) {
|
||||
do{
|
||||
*fft_out = *fft_in;
|
||||
fft_in += fstride*in_stride;
|
||||
}while(++fft_out != Fout_end );
|
||||
}else{
|
||||
do{
|
||||
// recursive call:
|
||||
// DFT of size m*p performed by doing
|
||||
// p instances of smaller DFTs of size m,
|
||||
// each one takes a decimated version of the input
|
||||
transform(fft_in, fft_out, stage+1, fstride*p,in_stride);
|
||||
fft_in += fstride*in_stride;
|
||||
}while( (fft_out += m) != Fout_end );
|
||||
}
|
||||
|
||||
fft_out=Fout_beg;
|
||||
|
||||
// recombine the p smaller DFTs
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(fft_out,fstride,m); break;
|
||||
case 3: kf_bfly3(fft_out,fstride,m); break;
|
||||
case 4: kf_bfly4(fft_out,fstride,m); break;
|
||||
case 5: kf_bfly5(fft_out,fstride,m); break;
|
||||
default: kf_bfly_generic(fft_out,fstride,m,p); break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculates the Discrete Fourier Transform (DFT) of a real input
|
||||
/// of size @c 2*N.
|
||||
///
|
||||
/// The 0-th and N-th value of the DFT are real numbers. These are
|
||||
/// stored in @c dst[0].real() and @c dst[0].imag() respectively.
|
||||
/// The remaining DFT values up to the index N-1 are stored in
|
||||
/// @c dst[1] to @c dst[N-1].
|
||||
/// The other half of the DFT values can be calculated from the
|
||||
/// symmetry relation
|
||||
/// @code
|
||||
/// DFT(src)[2*N-k] == conj( DFT(src)[k] );
|
||||
/// @endcode
|
||||
/// The same scaling factors as in @c transform() apply.
|
||||
///
|
||||
/// @note For this to work, the types @c scalar_t and @c cpx_t
|
||||
/// must fulfill the following requirements:
|
||||
///
|
||||
/// For any object @c z of type @c cpx_t,
|
||||
/// @c reinterpret_cast<scalar_t(&)[2]>(z)[0] is the real part of @c z and
|
||||
/// @c reinterpret_cast<scalar_t(&)[2]>(z)[1] is the imaginary part of @c z.
|
||||
/// For any pointer to an element of an array of @c cpx_t named @c p
|
||||
/// and any valid array index @c i, @c reinterpret_cast<T*>(p)[2*i]
|
||||
/// is the real part of the complex number @c p[i], and
|
||||
/// @c reinterpret_cast<T*>(p)[2*i+1] is the imaginary part of the
|
||||
/// complex number @c p[i].
|
||||
///
|
||||
/// Since C++11, these requirements are guaranteed to be satisfied for
|
||||
/// @c scalar_ts being @c float, @c double or @c long @c double
|
||||
/// together with @c cpx_t being @c std::complex<scalar_t>.
|
||||
void transform_real( const scalar_t * const src,
|
||||
cpx_t * const dst ) const
|
||||
{
|
||||
const std::size_t N = _nfft;
|
||||
if ( N == 0 )
|
||||
return;
|
||||
|
||||
// perform complex FFT
|
||||
transform( reinterpret_cast<const cpx_t*>(src), dst );
|
||||
|
||||
// post processing for k = 0 and k = N
|
||||
dst[0] = cpx_t( dst[0].real() + dst[0].imag(),
|
||||
dst[0].real() - dst[0].imag() );
|
||||
|
||||
// post processing for all the other k = 1, 2, ..., N-1
|
||||
const scalar_t pi = std::acos( (scalar_t) -1);
|
||||
const scalar_t half_phi_inc = ( _inverse ? pi : -pi ) / N;
|
||||
const cpx_t twiddle_mul = std::exp( cpx_t(0, half_phi_inc) );
|
||||
for ( std::size_t k = 1; 2*k < N; ++k )
|
||||
{
|
||||
const cpx_t w = (scalar_t)0.5 * cpx_t(
|
||||
dst[k].real() + dst[N-k].real(),
|
||||
dst[k].imag() - dst[N-k].imag() );
|
||||
const cpx_t z = (scalar_t)0.5 * cpx_t(
|
||||
dst[k].imag() + dst[N-k].imag(),
|
||||
-dst[k].real() + dst[N-k].real() );
|
||||
const cpx_t twiddle =
|
||||
k % 2 == 0 ?
|
||||
_twiddles[k/2] :
|
||||
_twiddles[k/2] * twiddle_mul;
|
||||
dst[ k] = w + twiddle * z;
|
||||
dst[N-k] = std::conj( w - twiddle * z );
|
||||
}
|
||||
if ( N % 2 == 0 )
|
||||
dst[N/2] = std::conj( dst[N/2] );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void kf_bfly2( cpx_t * Fout, const size_t fstride, const std::size_t m) const
|
||||
{
|
||||
for (std::size_t k=0;k<m;++k) {
|
||||
const cpx_t t = Fout[m+k] * _twiddles[k*fstride];
|
||||
Fout[m+k] = Fout[k] - t;
|
||||
Fout[k] += t;
|
||||
}
|
||||
}
|
||||
|
||||
void kf_bfly3( cpx_t * Fout, const std::size_t fstride, const std::size_t m) const
|
||||
{
|
||||
std::size_t k=m;
|
||||
const std::size_t m2 = 2*m;
|
||||
const cpx_t *tw1,*tw2;
|
||||
cpx_t scratch[5];
|
||||
const cpx_t epi3 = _twiddles[fstride*m];
|
||||
|
||||
tw1=tw2=&_twiddles[0];
|
||||
|
||||
do{
|
||||
scratch[1] = Fout[m] * *tw1;
|
||||
scratch[2] = Fout[m2] * *tw2;
|
||||
|
||||
scratch[3] = scratch[1] + scratch[2];
|
||||
scratch[0] = scratch[1] - scratch[2];
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
|
||||
Fout[m] = Fout[0] - scratch[3]*scalar_t(0.5);
|
||||
scratch[0] *= epi3.imag();
|
||||
|
||||
Fout[0] += scratch[3];
|
||||
|
||||
Fout[m2] = cpx_t( Fout[m].real() + scratch[0].imag() , Fout[m].imag() - scratch[0].real() );
|
||||
|
||||
Fout[m] += cpx_t( -scratch[0].imag(),scratch[0].real() );
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
|
||||
void kf_bfly4( cpx_t * const Fout, const std::size_t fstride, const std::size_t m) const
|
||||
{
|
||||
cpx_t scratch[7];
|
||||
const scalar_t negative_if_inverse = _inverse ? -1 : +1;
|
||||
for (std::size_t k=0;k<m;++k) {
|
||||
scratch[0] = Fout[k+ m] * _twiddles[k*fstride ];
|
||||
scratch[1] = Fout[k+2*m] * _twiddles[k*fstride*2];
|
||||
scratch[2] = Fout[k+3*m] * _twiddles[k*fstride*3];
|
||||
scratch[5] = Fout[k] - scratch[1];
|
||||
|
||||
Fout[k] += scratch[1];
|
||||
scratch[3] = scratch[0] + scratch[2];
|
||||
scratch[4] = scratch[0] - scratch[2];
|
||||
scratch[4] = cpx_t( scratch[4].imag()*negative_if_inverse ,
|
||||
-scratch[4].real()*negative_if_inverse );
|
||||
|
||||
Fout[k+2*m] = Fout[k] - scratch[3];
|
||||
Fout[k ]+= scratch[3];
|
||||
Fout[k+ m] = scratch[5] + scratch[4];
|
||||
Fout[k+3*m] = scratch[5] - scratch[4];
|
||||
}
|
||||
}
|
||||
|
||||
void kf_bfly5( cpx_t * const Fout, const std::size_t fstride, const std::size_t m) const
|
||||
{
|
||||
cpx_t *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
|
||||
cpx_t scratch[13];
|
||||
const cpx_t ya = _twiddles[fstride*m];
|
||||
const cpx_t yb = _twiddles[fstride*2*m];
|
||||
|
||||
Fout0=Fout;
|
||||
Fout1=Fout0+m;
|
||||
Fout2=Fout0+2*m;
|
||||
Fout3=Fout0+3*m;
|
||||
Fout4=Fout0+4*m;
|
||||
|
||||
for ( std::size_t u=0; u<m; ++u ) {
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
scratch[1] = *Fout1 * _twiddles[ u*fstride];
|
||||
scratch[2] = *Fout2 * _twiddles[2*u*fstride];
|
||||
scratch[3] = *Fout3 * _twiddles[3*u*fstride];
|
||||
scratch[4] = *Fout4 * _twiddles[4*u*fstride];
|
||||
|
||||
scratch[7] = scratch[1] + scratch[4];
|
||||
scratch[10]= scratch[1] - scratch[4];
|
||||
scratch[8] = scratch[2] + scratch[3];
|
||||
scratch[9] = scratch[2] - scratch[3];
|
||||
|
||||
*Fout0 += scratch[7];
|
||||
*Fout0 += scratch[8];
|
||||
|
||||
scratch[5] = scratch[0] + cpx_t(
|
||||
scratch[7].real()*ya.real() + scratch[8].real()*yb.real(),
|
||||
scratch[7].imag()*ya.real() + scratch[8].imag()*yb.real()
|
||||
);
|
||||
|
||||
scratch[6] = cpx_t(
|
||||
scratch[10].imag()*ya.imag() + scratch[9].imag()*yb.imag(),
|
||||
-scratch[10].real()*ya.imag() - scratch[9].real()*yb.imag()
|
||||
);
|
||||
|
||||
*Fout1 = scratch[5] - scratch[6];
|
||||
*Fout4 = scratch[5] + scratch[6];
|
||||
|
||||
scratch[11] = scratch[0] +
|
||||
cpx_t(
|
||||
scratch[7].real()*yb.real() + scratch[8].real()*ya.real(),
|
||||
scratch[7].imag()*yb.real() + scratch[8].imag()*ya.real()
|
||||
);
|
||||
|
||||
scratch[12] = cpx_t(
|
||||
-scratch[10].imag()*yb.imag() + scratch[9].imag()*ya.imag(),
|
||||
scratch[10].real()*yb.imag() - scratch[9].real()*ya.imag()
|
||||
);
|
||||
|
||||
*Fout2 = scratch[11] + scratch[12];
|
||||
*Fout3 = scratch[11] - scratch[12];
|
||||
|
||||
++Fout0;
|
||||
++Fout1;
|
||||
++Fout2;
|
||||
++Fout3;
|
||||
++Fout4;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform the butterfly for one stage of a mixed radix FFT */
|
||||
void kf_bfly_generic(
|
||||
cpx_t * const Fout,
|
||||
const size_t fstride,
|
||||
const std::size_t m,
|
||||
const std::size_t p
|
||||
) const
|
||||
{
|
||||
const cpx_t * twiddles = &_twiddles[0];
|
||||
|
||||
if(p > _scratchbuf.size()) _scratchbuf.resize(p);
|
||||
|
||||
for ( std::size_t u=0; u<m; ++u ) {
|
||||
std::size_t k = u;
|
||||
for ( std::size_t q1=0 ; q1<p ; ++q1 ) {
|
||||
_scratchbuf[q1] = Fout[ k ];
|
||||
k += m;
|
||||
}
|
||||
|
||||
k=u;
|
||||
for ( std::size_t q1=0 ; q1<p ; ++q1 ) {
|
||||
std::size_t twidx=0;
|
||||
Fout[ k ] = _scratchbuf[0];
|
||||
for ( std::size_t q=1;q<p;++q ) {
|
||||
twidx += fstride * k;
|
||||
if (twidx>=_nfft)
|
||||
twidx-=_nfft;
|
||||
Fout[ k ] += _scratchbuf[q] * twiddles[twidx];
|
||||
}
|
||||
k += m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t _nfft;
|
||||
bool _inverse;
|
||||
std::vector<cpx_t> _twiddles;
|
||||
std::vector<std::size_t> _stageRadix;
|
||||
std::vector<std::size_t> _stageRemainder;
|
||||
mutable std::vector<cpx_t> _scratchbuf;
|
||||
};
|
||||
#endif
|
10
3rd-party/kissfft/kissfft.pc.in
vendored
10
3rd-party/kissfft/kissfft.pc.in
vendored
@ -1,10 +0,0 @@
|
||||
prefix=@PKGCONFIG_KISSFFT_PREFIX@
|
||||
libdir=@PKGCONFIG_KISSFFT_LIBDIR@
|
||||
includedir=@PKGCONFIG_KISSFFT_INCLUDEDIR@
|
||||
|
||||
Name: kissfft
|
||||
Description: A Fast Fourier Transform (FFT) library that tries to Keep it Simple, Stupid
|
||||
Version: @PKGCONFIG_KISSFFT_VERSION@
|
||||
|
||||
Libs: @PKG_OPENMP@ -L${libdir} -l@KISSFFT_OUTPUT_NAME@
|
||||
Cflags: -I@PKGCONFIG_KISSFFT_PKGINCLUDEDIR@ @PKG_KISSFFT_DEFS@
|
304
3rd-party/kissfft/kissfft_i32.hh
vendored
304
3rd-party/kissfft/kissfft_i32.hh
vendored
@ -1,304 +0,0 @@
|
||||
#ifndef KISSFFT_I32_CLASS_HH
|
||||
#define KISSFFT_I32_CLASS_HH
|
||||
|
||||
#include <complex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// TODO1: substitute complex<type> (behaviour not defined for nonfloats), should be faster
|
||||
// TODO2: use std:: namespace
|
||||
// TODO3: make unittests for all ffts (c, cpp, i32)
|
||||
|
||||
template <typename DType>
|
||||
struct complex_s
|
||||
{
|
||||
DType real;
|
||||
DType imag;
|
||||
};
|
||||
|
||||
class kissfft_i32
|
||||
{
|
||||
private:
|
||||
|
||||
using scalar_type = int32_t;
|
||||
using cpx_type = complex<int32_t>;
|
||||
|
||||
scalar_type _scale_factor;
|
||||
std::size_t _nfft;
|
||||
bool _inverse;
|
||||
std::vector<cpx_type> _twiddles;
|
||||
std::vector<std::size_t> _stageRadix;
|
||||
std::vector<std::size_t> _stageRemainder;
|
||||
|
||||
public:
|
||||
|
||||
// scale_factor: upscale twiddle-factors otherwise they lie between 0..1 (out of range for integer) --> fixed point math
|
||||
kissfft_i32(const std::size_t nfft, const bool inverse, const double scale_factor = 1024.0)
|
||||
: _scale_factor(scalar_type(scale_factor)), _nfft(nfft), _inverse(inverse)
|
||||
{
|
||||
// fill twiddle factors
|
||||
_twiddles.resize(_nfft);
|
||||
const double phinc = (_inverse ? 2 : -2) * acos(-1.0) / _nfft;
|
||||
for (std::size_t i = 0; i < _nfft; ++i)
|
||||
{
|
||||
_twiddles[i] = scale_factor * exp(complex<double>(0, i * phinc));
|
||||
}
|
||||
//factorize
|
||||
//start factoring out 4's, then 2's, then 3,5,7,9,...
|
||||
std::size_t n = _nfft;
|
||||
std::size_t p = 4;
|
||||
do
|
||||
{
|
||||
while (n % p)
|
||||
{
|
||||
switch (p)
|
||||
{
|
||||
case 4:
|
||||
p = 2;
|
||||
break;
|
||||
case 2:
|
||||
p = 3;
|
||||
break;
|
||||
default:
|
||||
p += 2;
|
||||
break;
|
||||
}
|
||||
if (p * p > n) p = n;// no more factors
|
||||
}
|
||||
n /= p;
|
||||
_stageRadix.push_back(p);
|
||||
_stageRemainder.push_back(n);
|
||||
} while (n > 1);
|
||||
}
|
||||
|
||||
/// Calculates the complex Discrete Fourier Transform.
|
||||
///
|
||||
/// The size of the passed arrays must be passed in the constructor.
|
||||
/// The sum of the squares of the absolute values in the @c dst
|
||||
/// array will be @c N times the sum of the squares of the absolute
|
||||
/// values in the @c src array, where @c N is the size of the array.
|
||||
/// In other words, the l_2 norm of the resulting array will be
|
||||
/// @c sqrt(N) times as big as the l_2 norm of the input array.
|
||||
/// This is also the case when the inverse flag is set in the
|
||||
/// constructor. Hence when applying the same transform twice, but with
|
||||
/// the inverse flag changed the second time, then the result will
|
||||
/// be equal to the original input times @c N.
|
||||
void transform(const cpx_type * FSrc,
|
||||
cpx_type * FDst,
|
||||
const std::size_t stage = 0,
|
||||
const std::size_t fstride = 1,
|
||||
const std::size_t in_stride = 1) const
|
||||
{
|
||||
const std::size_t p = _stageRadix[stage];
|
||||
const std::size_t m = _stageRemainder[stage];
|
||||
cpx_type *const Fout_beg = FDst;
|
||||
cpx_type *const Fout_end = FDst + p * m;
|
||||
|
||||
if (m == 1)
|
||||
{
|
||||
do
|
||||
{
|
||||
*FDst = *FSrc;
|
||||
FSrc += fstride * in_stride;
|
||||
} while (++FDst != Fout_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
// recursive call:
|
||||
// DFT of size m*p performed by doing
|
||||
// p instances of smaller DFTs of size m,
|
||||
// each one takes a decimated version of the input
|
||||
transform(FSrc, FDst, stage + 1, fstride * p, in_stride);
|
||||
FSrc += fstride * in_stride;
|
||||
} while ((FDst += m) != Fout_end);
|
||||
}
|
||||
|
||||
FDst = Fout_beg;
|
||||
|
||||
// recombine the p smaller DFTs
|
||||
switch (p)
|
||||
{
|
||||
case 2:
|
||||
kf_bfly2(FDst, fstride, m);
|
||||
break;
|
||||
case 3:
|
||||
kf_bfly3(FDst, fstride, m);
|
||||
break;
|
||||
case 4:
|
||||
kf_bfly4(FDst, fstride, m);
|
||||
break;
|
||||
case 5:
|
||||
kf_bfly5(FDst, fstride, m);
|
||||
break;
|
||||
default:
|
||||
kf_bfly_generic(FDst, fstride, m, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void kf_bfly2(cpx_type *const Fout, const size_t fstride, const std::size_t m) const
|
||||
{
|
||||
for (std::size_t k = 0; k < m; ++k)
|
||||
{
|
||||
const cpx_type t = (Fout[m + k] * _twiddles[k * fstride]) / _scale_factor;
|
||||
Fout[m + k] = Fout[k] - t;
|
||||
Fout[k] += t;
|
||||
}
|
||||
}
|
||||
|
||||
void kf_bfly3(cpx_type *Fout, const std::size_t fstride, const std::size_t m) const
|
||||
{
|
||||
std::size_t k = m;
|
||||
const std::size_t m2 = 2 * m;
|
||||
const cpx_type *tw1, *tw2;
|
||||
cpx_type scratch[5];
|
||||
const cpx_type epi3 = _twiddles[fstride * m];
|
||||
|
||||
tw1 = tw2 = &_twiddles[0];
|
||||
|
||||
do
|
||||
{
|
||||
scratch[1] = (Fout[m] * *tw1) / _scale_factor;
|
||||
scratch[2] = (Fout[m2] * *tw2) / _scale_factor;
|
||||
|
||||
scratch[3] = scratch[1] + scratch[2];
|
||||
scratch[0] = scratch[1] - scratch[2];
|
||||
tw1 += fstride;
|
||||
tw2 += fstride * 2;
|
||||
|
||||
Fout[m] = Fout[0] - (scratch[3] / 2);
|
||||
scratch[0] *= epi3.imag();
|
||||
scratch[0] /= _scale_factor;
|
||||
|
||||
Fout[0] += scratch[3];
|
||||
|
||||
Fout[m2] = cpx_type(Fout[m].real() + scratch[0].imag(), Fout[m].imag() - scratch[0].real());
|
||||
|
||||
Fout[m] += cpx_type(-scratch[0].imag(), scratch[0].real());
|
||||
++Fout;
|
||||
} while (--k);
|
||||
}
|
||||
|
||||
void kf_bfly4(cpx_type *const Fout, const std::size_t fstride, const std::size_t m) const
|
||||
{
|
||||
cpx_type scratch[7];
|
||||
const scalar_type negative_if_inverse = _inverse ? -1 : +1;
|
||||
|
||||
for (std::size_t k = 0; k < m; ++k)
|
||||
{
|
||||
scratch[0] = (Fout[k + m] * _twiddles[k * fstride]) / _scale_factor;
|
||||
scratch[1] = (Fout[k + 2 * m] * _twiddles[k * fstride * 2]) / _scale_factor;
|
||||
scratch[2] = (Fout[k + 3 * m] * _twiddles[k * fstride * 3]) / _scale_factor;
|
||||
scratch[5] = Fout[k] - scratch[1];
|
||||
|
||||
Fout[k] += scratch[1];
|
||||
scratch[3] = scratch[0] + scratch[2];
|
||||
scratch[4] = scratch[0] - scratch[2];
|
||||
scratch[4] = cpx_type(scratch[4].imag() * negative_if_inverse,
|
||||
-scratch[4].real() * negative_if_inverse);
|
||||
|
||||
Fout[k + 2 * m] = Fout[k] - scratch[3];
|
||||
Fout[k] += scratch[3];
|
||||
Fout[k + m] = scratch[5] + scratch[4];
|
||||
Fout[k + 3 * m] = scratch[5] - scratch[4];
|
||||
}
|
||||
}
|
||||
|
||||
void kf_bfly5(cpx_type *const Fout, const std::size_t fstride, const std::size_t m) const
|
||||
{
|
||||
cpx_type *Fout0, *Fout1, *Fout2, *Fout3, *Fout4;
|
||||
cpx_type scratch[13];
|
||||
const cpx_type ya = _twiddles[fstride * m];
|
||||
const cpx_type yb = _twiddles[fstride * 2 * m];
|
||||
|
||||
Fout0 = Fout;
|
||||
Fout1 = Fout0 + m;
|
||||
Fout2 = Fout0 + 2 * m;
|
||||
Fout3 = Fout0 + 3 * m;
|
||||
Fout4 = Fout0 + 4 * m;
|
||||
|
||||
for (std::size_t u = 0; u < m; ++u)
|
||||
{
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
scratch[1] = (*Fout1 * _twiddles[u * fstride]) / _scale_factor;
|
||||
scratch[2] = (*Fout2 * _twiddles[2 * u * fstride]) / _scale_factor;
|
||||
scratch[3] = (*Fout3 * _twiddles[3 * u * fstride]) / _scale_factor;
|
||||
scratch[4] = (*Fout4 * _twiddles[4 * u * fstride]) / _scale_factor;
|
||||
|
||||
scratch[7] = scratch[1] + scratch[4];
|
||||
scratch[10] = scratch[1] - scratch[4];
|
||||
scratch[8] = scratch[2] + scratch[3];
|
||||
scratch[9] = scratch[2] - scratch[3];
|
||||
|
||||
*Fout0 += scratch[7];
|
||||
*Fout0 += scratch[8];
|
||||
|
||||
scratch[5] = scratch[0] + (cpx_type(
|
||||
scratch[7].real() * ya.real() + scratch[8].real() * yb.real(),
|
||||
scratch[7].imag() * ya.real() + scratch[8].imag() * yb.real() ) / _scale_factor);
|
||||
|
||||
scratch[6] = cpx_type(
|
||||
scratch[10].imag() * ya.imag() + scratch[9].imag() * yb.imag(),
|
||||
-scratch[10].real() * ya.imag() - scratch[9].real() * yb.imag() ) / _scale_factor;
|
||||
|
||||
*Fout1 = scratch[5] - scratch[6];
|
||||
*Fout4 = scratch[5] + scratch[6];
|
||||
|
||||
scratch[11] = scratch[0] + (cpx_type(
|
||||
scratch[7].real() * yb.real() + scratch[8].real() * ya.real(),
|
||||
scratch[7].imag() * yb.real() + scratch[8].imag() * ya.real() ) / _scale_factor);
|
||||
|
||||
scratch[12] = cpx_type(
|
||||
-scratch[10].imag() * yb.imag() + scratch[9].imag() * ya.imag(),
|
||||
scratch[10].real() * yb.imag() - scratch[9].real() * ya.imag() ) / _scale_factor;
|
||||
|
||||
*Fout2 = scratch[11] + scratch[12];
|
||||
*Fout3 = scratch[11] - scratch[12];
|
||||
|
||||
++Fout0;
|
||||
++Fout1;
|
||||
++Fout2;
|
||||
++Fout3;
|
||||
++Fout4;
|
||||
}
|
||||
}
|
||||
|
||||
/* perform the butterfly for one stage of a mixed radix FFT */
|
||||
void kf_bfly_generic(cpx_type * const Fout, const size_t fstride, const std::size_t m, const std::size_t p) const
|
||||
{
|
||||
const cpx_type *twiddles = &_twiddles[0];
|
||||
cpx_type scratchbuf[p];
|
||||
|
||||
for (std::size_t u = 0; u < m; ++u)
|
||||
{
|
||||
std::size_t k = u;
|
||||
for (std::size_t q1 = 0; q1 < p; ++q1)
|
||||
{
|
||||
scratchbuf[q1] = Fout[k];
|
||||
k += m;
|
||||
}
|
||||
|
||||
k = u;
|
||||
for (std::size_t q1 = 0; q1 < p; ++q1)
|
||||
{
|
||||
std::size_t twidx = 0;
|
||||
Fout[k] = scratchbuf[0];
|
||||
for (std::size_t q = 1; q < p; ++q)
|
||||
{
|
||||
twidx += fstride * k;
|
||||
if (twidx >= _nfft)
|
||||
twidx -= _nfft;
|
||||
Fout[k] += (scratchbuf[q] * twiddles[twidx]) / _scale_factor;
|
||||
}
|
||||
k += m;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
63
3rd-party/kissfft/test/CMakeLists.txt
vendored
63
3rd-party/kissfft/test/CMakeLists.txt
vendored
@ -1,63 +0,0 @@
|
||||
function(add_kissfft_test_executable NAME)
|
||||
add_kissfft_executable(${NAME} ${ARGN})
|
||||
target_include_directories(${NAME} PRIVATE ..)
|
||||
|
||||
add_test(NAME ${NAME} COMMAND ${NAME})
|
||||
set_tests_properties(${NAME} PROPERTIES TIMEOUT 3600)
|
||||
endfunction()
|
||||
|
||||
set(KISSFFT_TEST_NUMFFTS 10000)
|
||||
|
||||
#
|
||||
# Add tools-independent fastfilt_* (../tools/fft_*) executable without adding a test
|
||||
#
|
||||
|
||||
add_kissfft_executable(fastfilt ../tools/fftutil.c)
|
||||
target_include_directories(fastfilt PRIVATE ..)
|
||||
|
||||
#
|
||||
# Add test executables and define tests
|
||||
#
|
||||
|
||||
add_kissfft_test_executable(bm_kiss benchkiss.c pstats.c)
|
||||
# add_test(NAME benchmar COMMAND ${NAME})
|
||||
# set_tests_properties(${NAME} PROPERTIES TIMEOUT 3600)
|
||||
|
||||
include(FindPkgConfig)
|
||||
if(KISSFFT_FLOAT)
|
||||
set(fftw3_pkg fftw3f)
|
||||
else()
|
||||
set(fftw3_pkg fftw3)
|
||||
endif()
|
||||
pkg_check_modules(fftw3 REQUIRED IMPORTED_TARGET ${fftw3_pkg})
|
||||
add_kissfft_test_executable(bm_fftw benchfftw.c pstats.c)
|
||||
target_link_libraries(bm_fftw PRIVATE PkgConfig::fftw3)
|
||||
|
||||
add_kissfft_test_executable(st twotonetest.c)
|
||||
|
||||
add_kissfft_test_executable(tkfc twotonetest.c)
|
||||
target_compile_definitions(tkfc PRIVATE KFC_TEST)
|
||||
|
||||
add_kissfft_test_executable(ffr twotonetest.c)
|
||||
add_kissfft_test_executable(tr test_real.c)
|
||||
|
||||
add_kissfft_test_executable(testcpp testcpp.cc)
|
||||
|
||||
if(KISSFFT_DATATYPE MATCHES "^simd$")
|
||||
add_kissfft_test_executable(tsimd test_simd.c)
|
||||
target_compile_definitions(tsimd PRIVATE USE_SIMD)
|
||||
if (NOT MSVC)
|
||||
target_compile_options(kissfft PRIVATE -msse)
|
||||
else()
|
||||
target_compile_options(kissfft PRIVATE "/arch:SSE")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(PythonInterp REQUIRED)
|
||||
add_test(NAME testkiss.py COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/testkiss.py")
|
||||
list(APPEND TESTKISS_PY_ENV "KISSFFT_DATATYPE=${KISSFFT_DATATYPE}")
|
||||
list(APPEND TESTKISS_PY_ENV "KISSFFT_OPENMP=${KISSFFT_OPENMP}")
|
||||
set_tests_properties(testkiss.py PROPERTIES
|
||||
TIMEOUT 3600
|
||||
ENVIRONMENT "${TESTKISS_PY_ENV}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
188
3rd-party/kissfft/test/Makefile
vendored
188
3rd-party/kissfft/test/Makefile
vendored
@ -1,188 +0,0 @@
|
||||
#
|
||||
# Warnings
|
||||
#
|
||||
|
||||
WARNINGS = -W -Wall -Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast \
|
||||
-Wwrite-strings
|
||||
|
||||
#
|
||||
# Compile-time definitions
|
||||
#
|
||||
|
||||
CFLAGS = -O3 -I.. -I../tools $(WARNINGS)
|
||||
CFLAGS += -ffast-math -fomit-frame-pointer
|
||||
#CFLAGS += -funroll-loops
|
||||
#CFLAGS += -march=prescott
|
||||
#CFLAGS += -mtune=native
|
||||
# TIP: try adding -openmp or -fopenmp to enable OPENMP directives and use of multiple cores
|
||||
#CFLAGS += -fopenmp
|
||||
CFLAGS += $(CFLAGADD)
|
||||
|
||||
CXXFLAGS = -O3 -ffast-math -fomit-frame-pointer -I.. -W -Wall -march=native -mtune=native
|
||||
|
||||
#
|
||||
# Count of FFT runs tested
|
||||
#
|
||||
|
||||
ifeq "$(NFFT)" ""
|
||||
NFFT = 1800
|
||||
endif
|
||||
ifeq "$(NUMFFTS)" ""
|
||||
NUMFFTS = 10000
|
||||
endif
|
||||
|
||||
#
|
||||
# Test binary executable names
|
||||
#
|
||||
|
||||
SELFTESTSRC = twotonetest.c
|
||||
|
||||
ifneq ($(KISSFFT_OPENMP),1)
|
||||
BENCHKISS = bm-kiss-$(KISSFFT_DATATYPE)
|
||||
BENCHFFTW = bm-fftw-$(KISSFFT_DATATYPE)
|
||||
SELFTEST = st-$(KISSFFT_DATATYPE)
|
||||
TESTREAL = tr-$(KISSFFT_DATATYPE)
|
||||
TESTKFC = tkfc-$(KISSFFT_DATATYPE)
|
||||
TESTFASTFILT = fastfilt-$(KISSFFT_DATATYPE)
|
||||
TESTCPP = testcpp-$(KISSFFT_DATATYPE)
|
||||
TESTSIMD = testsimd
|
||||
else
|
||||
BENCHKISS = bm-kiss-$(KISSFFT_DATATYPE)-openmp
|
||||
BENCHFFTW = bm-fftw-$(KISSFFT_DATATYPE)-openmp
|
||||
SELFTEST = st-$(KISSFFT_DATATYPE)-openmp
|
||||
TESTREAL = tr-$(KISSFFT_DATATYPE)-openmp
|
||||
TESTKFC = tkfc-$(KISSFFT_DATATYPE)-openmp
|
||||
TESTFASTFILT = fastfilt-$(KISSFFT_DATATYPE)-openmp
|
||||
TESTCPP = testcpp-$(KISSFFT_DATATYPE)-openmp
|
||||
TESTSIMD = testsimd-openmp
|
||||
CFLAGS += -fopenmp
|
||||
CXXFLAGS += -fopenmp
|
||||
endif
|
||||
|
||||
ifeq "$(KISSFFT_DATATYPE)" "float"
|
||||
# fftw needs to be built with --enable-float to build this lib
|
||||
FFTWLIB = -lfftw3f
|
||||
else
|
||||
FFTWLIB = -lfftw3
|
||||
endif
|
||||
|
||||
FFTWLIBDIR ?= $(ABS_LIBDIR)
|
||||
ABS_FFTWLIBDIR = $(abspath $(FFTWLIBDIR))
|
||||
|
||||
#
|
||||
# Check missing external libraries
|
||||
#
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
LIBFFTW_MISSING = $(shell echo "int main(){return 0;}" > _test_library_dummy.c; \
|
||||
$(CC) -o _test_library_dummy _test_library_dummy.c $(FFTWLIB) -L$(ABS_FFTWLIBDIR); \
|
||||
echo $$?; \
|
||||
rm -f _test_library_dummy.c _test_library_dummy)
|
||||
endif
|
||||
|
||||
#
|
||||
# Find Python interpreter
|
||||
#
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
PYTHON_INTERPRETER = $(shell python --version)
|
||||
ifeq ($(PYTHON_INTERPRETER), )
|
||||
PYTHON_INTERPRETER = $(shell python2 --version)
|
||||
ifeq ($(PYTHON_INTERPRETER), )
|
||||
PYTHON_INTERPRETER = $(shell python3 --version)
|
||||
ifeq ($(PYTHON_INTERPRETER), )
|
||||
$(error ERROR: Can not find Python interpreter!)
|
||||
else
|
||||
PYTHON_INTERPRETER = "python3"
|
||||
endif
|
||||
else
|
||||
PYTHON_INTERPRETER = "python2"
|
||||
endif
|
||||
else
|
||||
PYTHON_INTERPRETER = "python"
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Target: "make all"
|
||||
#
|
||||
|
||||
all: $(BENCHKISS) $(SELFTEST) $(BENCHFFTW) $(TESTREAL) $(TESTKFC) $(TESTFASTFILT)
|
||||
|
||||
#
|
||||
# Individual test make rules
|
||||
#
|
||||
|
||||
$(SELFTEST): $(SELFTESTSRC)
|
||||
$(CC) -o $@ $(CFLAGS) $(TYPEFLAGS) $< -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(TESTKFC): ../kfc.c
|
||||
$(CC) -o $@ $(CFLAGS) -DKFC_TEST $(TYPEFLAGS) $^ -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(TESTREAL): test_real.c
|
||||
$(CC) -o $@ $(CFLAGS) $(TYPEFLAGS) $< -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(BENCHKISS): benchkiss.c pstats.c
|
||||
$(CC) -o $@ $(CFLAGS) $(TYPEFLAGS) $^ -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(TESTFASTFILT): ../tools/fftutil.c
|
||||
$(CC) -o $@ $(CFLAGS) -DKFC_TEST $(TYPEFLAGS) $^ -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(BENCHFFTW): benchfftw.c pstats.c
|
||||
$(warning ======attempting to build FFTW benchmark)
|
||||
ifeq ($(LIBFFTW_MISSING), 0)
|
||||
$(CC) -o $@ $(CFLAGS) -DDATATYPE$(KISSFFT_DATATYPE) $^ $(FFTWLIB) -L$(ABS_FFTWLIBDIR) -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
else
|
||||
$(warning WARNING: No FFTW development files found! FFTW not available for comparison!0
|
||||
endif
|
||||
|
||||
#
|
||||
# Test SSE
|
||||
#
|
||||
|
||||
$(TESTSIMD): test_simd.c
|
||||
ifeq "$(KISSFFT_DATATYPE)" "simd"
|
||||
$(CC) -o $@ -g $(CFLAGS) -DUSE_SIMD=1 -msse $< -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
else
|
||||
$(error ERROR: This test makes sense only with KISSFFT_DATATYPE=simd)
|
||||
endif
|
||||
|
||||
testsse: $(TESTSIMD)
|
||||
LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(TESTSIMD)
|
||||
|
||||
#
|
||||
# Test C++
|
||||
#
|
||||
|
||||
$(TESTCPP): testcpp.cc ../kissfft.hh
|
||||
$(CXX) -o $@ $(CXXFLAGS) testcpp.cc -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
testcpp: $(TESTCPP)
|
||||
LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(TESTCPP)
|
||||
|
||||
#
|
||||
# Target: "make test"
|
||||
#
|
||||
|
||||
test: all
|
||||
ifeq "$(KISSFFT_DATATYPE)" "simd"
|
||||
make testsse
|
||||
endif
|
||||
@LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(TESTKFC)
|
||||
$(warning ======1d & 2-d complex fft self test (type= $(KISSFFT_DATATYPE) ))
|
||||
@LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(SELFTEST)
|
||||
$(warning ======real FFT (type= $(KISSFFT_DATATYPE) ))
|
||||
@LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(TESTREAL)
|
||||
$(warning ======timing test (type=$(KISSFFT_DATATYPE)))
|
||||
@LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(BENCHKISS) -x $(NUMFFTS) -n $(NFFT)
|
||||
@[ -x ./$(BENCHFFTW) ] && LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." ./$(BENCHFFTW) -x $(NUMFFTS) -n $(NFFT) || true
|
||||
$(warning ======higher dimensions (type=$(KISSFFT_DATATYPE)))
|
||||
@LD_LIBRARY_PATH="$(LD_LIBRARY_PATH):.." $(PYTHON_INTERPRETER) ./testkiss.py
|
||||
|
||||
#
|
||||
# Target: "make clean"
|
||||
#
|
||||
|
||||
clean:
|
||||
rm -f *~ bm-* st-* tr-* kf-* tkfc-* ff-* fastfilt-* *.pyc *.pyo *.dat testcpp-* testsimd testsimd-* _test_library_dummy _test_library_dummy.c
|
101
3rd-party/kissfft/test/benchfftw.c
vendored
101
3rd-party/kissfft/test/benchfftw.c
vendored
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fftw3.h>
|
||||
#include <unistd.h>
|
||||
#include "pstats.h"
|
||||
|
||||
#ifdef DATATYPEdouble
|
||||
|
||||
#define CPXTYPE fftw_complex
|
||||
#define PLAN fftw_plan
|
||||
#define FFTMALLOC fftw_malloc
|
||||
#define MAKEPLAN fftw_plan_dft_1d
|
||||
#define DOFFT fftw_execute
|
||||
#define DESTROYPLAN fftw_destroy_plan
|
||||
#define FFTFREE fftw_free
|
||||
|
||||
#elif defined(DATATYPEfloat)
|
||||
|
||||
#define CPXTYPE fftwf_complex
|
||||
#define PLAN fftwf_plan
|
||||
#define FFTMALLOC fftwf_malloc
|
||||
#define MAKEPLAN fftwf_plan_dft_1d
|
||||
#define DOFFT fftwf_execute
|
||||
#define DESTROYPLAN fftwf_destroy_plan
|
||||
#define FFTFREE fftwf_free
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CPXTYPE
|
||||
int main(void)
|
||||
{
|
||||
fprintf(stderr,"Datatype not available in FFTW\n" );
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
int nfft=1024;
|
||||
int isinverse=0;
|
||||
int numffts=1000,i;
|
||||
|
||||
CPXTYPE * in=NULL;
|
||||
CPXTYPE * out=NULL;
|
||||
PLAN p;
|
||||
|
||||
pstats_init();
|
||||
|
||||
while (1) {
|
||||
int c = getopt (argc, argv, "n:ix:h");
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'n':
|
||||
nfft = atoi (optarg);
|
||||
break;
|
||||
case 'x':
|
||||
numffts = atoi (optarg);
|
||||
break;
|
||||
case 'i':
|
||||
isinverse = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
fprintf(stderr,"options:\n-n N: complex fft length\n-i: inverse\n-x N: number of ffts to compute\n"
|
||||
"");
|
||||
}
|
||||
}
|
||||
|
||||
in=FFTMALLOC(sizeof(CPXTYPE) * nfft);
|
||||
out=FFTMALLOC(sizeof(CPXTYPE) * nfft);
|
||||
for (i=0;i<nfft;++i ) {
|
||||
in[i][0] = rand() - RAND_MAX/2;
|
||||
in[i][1] = rand() - RAND_MAX/2;
|
||||
}
|
||||
|
||||
if ( isinverse )
|
||||
p = MAKEPLAN(nfft, in, out, FFTW_BACKWARD, FFTW_ESTIMATE);
|
||||
else
|
||||
p = MAKEPLAN(nfft, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
|
||||
|
||||
for (i=0;i<numffts;++i)
|
||||
DOFFT(p);
|
||||
|
||||
DESTROYPLAN(p);
|
||||
|
||||
FFTFREE(in); FFTFREE(out);
|
||||
|
||||
fprintf(stderr,"fftw\tnfft=%d\tnumffts=%d\n", nfft,numffts);
|
||||
pstats_report();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
129
3rd-party/kissfft/test/benchkiss.c
vendored
129
3rd-party/kissfft/test/benchkiss.c
vendored
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/times.h>
|
||||
#include <unistd.h>
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fftr.h"
|
||||
#include "kiss_fftnd.h"
|
||||
#include "kiss_fftndr.h"
|
||||
|
||||
#include "pstats.h"
|
||||
|
||||
static
|
||||
int getdims(int * dims, char * arg)
|
||||
{
|
||||
char *s;
|
||||
int ndims=0;
|
||||
while ( (s=strtok( arg , ",") ) ) {
|
||||
dims[ndims++] = atoi(s);
|
||||
//printf("%s=%d\n",s,dims[ndims-1]);
|
||||
arg=NULL;
|
||||
}
|
||||
return ndims;
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
int k;
|
||||
int nfft[32];
|
||||
int ndims = 1;
|
||||
int isinverse=0;
|
||||
int numffts=1000,i;
|
||||
kiss_fft_cpx * buf;
|
||||
kiss_fft_cpx * bufout;
|
||||
int real = 0;
|
||||
|
||||
nfft[0] = 1024;// default
|
||||
|
||||
while (1) {
|
||||
int c = getopt (argc, argv, "n:ix:r");
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'r':
|
||||
real = 1;
|
||||
break;
|
||||
case 'n':
|
||||
ndims = getdims(nfft, optarg );
|
||||
if (nfft[0] != kiss_fft_next_fast_size(nfft[0]) ) {
|
||||
int ng = kiss_fft_next_fast_size(nfft[0]);
|
||||
fprintf(stderr,"warning: %d might be a better choice for speed than %d\n",ng,nfft[0]);
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
numffts = atoi (optarg);
|
||||
break;
|
||||
case 'i':
|
||||
isinverse = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int nbytes = sizeof(kiss_fft_cpx);
|
||||
for (k=0;k<ndims;++k)
|
||||
nbytes *= nfft[k];
|
||||
|
||||
#ifdef USE_SIMD
|
||||
numffts /= 4;
|
||||
fprintf(stderr,"since SIMD implementation does 4 ffts at a time, numffts is being reduced to %d\n",numffts);
|
||||
#endif
|
||||
|
||||
buf=(kiss_fft_cpx*)KISS_FFT_MALLOC(nbytes);
|
||||
bufout=(kiss_fft_cpx*)KISS_FFT_MALLOC(nbytes);
|
||||
memset(buf,0,nbytes);
|
||||
|
||||
pstats_init();
|
||||
|
||||
if (ndims==1) {
|
||||
if (real) {
|
||||
kiss_fftr_cfg st = kiss_fftr_alloc( nfft[0] ,isinverse ,0,0);
|
||||
if (isinverse)
|
||||
for (i=0;i<numffts;++i)
|
||||
kiss_fftri( st ,(kiss_fft_cpx*)buf,(kiss_fft_scalar*)bufout );
|
||||
else
|
||||
for (i=0;i<numffts;++i)
|
||||
kiss_fftr( st ,(kiss_fft_scalar*)buf,(kiss_fft_cpx*)bufout );
|
||||
free(st);
|
||||
}else{
|
||||
kiss_fft_cfg st = kiss_fft_alloc( nfft[0] ,isinverse ,0,0);
|
||||
for (i=0;i<numffts;++i)
|
||||
kiss_fft( st ,buf,bufout );
|
||||
free(st);
|
||||
}
|
||||
}else{
|
||||
if (real) {
|
||||
kiss_fftndr_cfg st = kiss_fftndr_alloc( nfft,ndims ,isinverse ,0,0);
|
||||
if (isinverse)
|
||||
for (i=0;i<numffts;++i)
|
||||
kiss_fftndri( st ,(kiss_fft_cpx*)buf,(kiss_fft_scalar*)bufout );
|
||||
else
|
||||
for (i=0;i<numffts;++i)
|
||||
kiss_fftndr( st ,(kiss_fft_scalar*)buf,(kiss_fft_cpx*)bufout );
|
||||
free(st);
|
||||
}else{
|
||||
kiss_fftnd_cfg st= kiss_fftnd_alloc(nfft,ndims,isinverse ,0,0);
|
||||
for (i=0;i<numffts;++i)
|
||||
kiss_fftnd( st ,buf,bufout );
|
||||
free(st);
|
||||
}
|
||||
}
|
||||
|
||||
free(buf); free(bufout);
|
||||
|
||||
fprintf(stderr,"KISS\tnfft=");
|
||||
for (k=0;k<ndims;++k)
|
||||
fprintf(stderr, "%d,",nfft[k]);
|
||||
fprintf(stderr,"\tnumffts=%d\n" ,numffts);
|
||||
pstats_report();
|
||||
|
||||
kiss_fft_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
134
3rd-party/kissfft/test/doit.c
vendored
134
3rd-party/kissfft/test/doit.c
vendored
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* This program is in the public domain
|
||||
* A program that helps the authors of the fine fftw library benchmark kiss
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense
|
||||
* See LICENSES/Unlicense for more information.
|
||||
*/
|
||||
|
||||
#include "bench-user.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fftnd.h"
|
||||
#include "kiss_fftr.h"
|
||||
|
||||
BEGIN_BENCH_DOC
|
||||
BENCH_DOC("name", "kissfft")
|
||||
BENCH_DOC("version", "1.0.1")
|
||||
BENCH_DOC("year", "2004")
|
||||
BENCH_DOC("author", "Mark Borgerding")
|
||||
BENCH_DOC("language", "C")
|
||||
BENCH_DOC("url", "http://sourceforge.net/projects/kissfft/")
|
||||
BENCH_DOC("copyright",
|
||||
"Copyright (c) 2003,4 Mark Borgerding\n"
|
||||
"\n"
|
||||
"All rights reserved.\n"
|
||||
"\n"
|
||||
"Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n"
|
||||
"\n"
|
||||
" * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n"
|
||||
" * 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.\n"
|
||||
" * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n"
|
||||
"\n"
|
||||
"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 OWNER 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.\n")
|
||||
END_BENCH_DOC
|
||||
|
||||
int can_do(struct problem *p)
|
||||
{
|
||||
if (p->rank == 1) {
|
||||
if (p->kind == PROBLEM_REAL) {
|
||||
return (p->n[0] & 1) == 0; /* only even real is okay */
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return p->kind == PROBLEM_COMPLEX;
|
||||
}
|
||||
}
|
||||
|
||||
static kiss_fft_cfg cfg=NULL;
|
||||
static kiss_fftr_cfg cfgr=NULL;
|
||||
static kiss_fftnd_cfg cfgnd=NULL;
|
||||
|
||||
#define FAILIF( c ) \
|
||||
if ( c ) do {\
|
||||
fprintf(stderr,\
|
||||
"kissfft: " #c " (file=%s:%d errno=%d %s)\n",\
|
||||
__FILE__,__LINE__ , errno,strerror( errno ) ) ;\
|
||||
exit(1);\
|
||||
}while(0)
|
||||
|
||||
|
||||
|
||||
void setup(struct problem *p)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
fprintf(stderr,"%s %s %d-d ",
|
||||
(p->sign == 1)?"Inverse":"Forward",
|
||||
p->kind == PROBLEM_COMPLEX?"Complex":"Real",
|
||||
p->rank);
|
||||
*/
|
||||
if (p->rank == 1) {
|
||||
if (p->kind == PROBLEM_COMPLEX) {
|
||||
cfg = kiss_fft_alloc (p->n[0], (p->sign == 1), 0, 0);
|
||||
FAILIF(cfg==NULL);
|
||||
}else{
|
||||
cfgr = kiss_fftr_alloc (p->n[0], (p->sign == 1), 0, 0);
|
||||
FAILIF(cfgr==NULL);
|
||||
}
|
||||
}else{
|
||||
int dims[5];
|
||||
for (i=0;i<p->rank;++i){
|
||||
dims[i] = p->n[i];
|
||||
}
|
||||
/* multi-dimensional */
|
||||
if (p->kind == PROBLEM_COMPLEX) {
|
||||
cfgnd = kiss_fftnd_alloc( dims , p->rank, (p->sign == 1), 0, 0 );
|
||||
FAILIF(cfgnd==NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doit(int iter, struct problem *p)
|
||||
{
|
||||
int i;
|
||||
void *in = p->in;
|
||||
void *out = p->out;
|
||||
|
||||
if (p->in_place)
|
||||
out = p->in;
|
||||
|
||||
if (p->rank == 1) {
|
||||
if (p->kind == PROBLEM_COMPLEX){
|
||||
for (i = 0; i < iter; ++i)
|
||||
kiss_fft (cfg, in, out);
|
||||
} else {
|
||||
/* PROBLEM_REAL */
|
||||
if (p->sign == -1) /* FORWARD */
|
||||
for (i = 0; i < iter; ++i)
|
||||
kiss_fftr (cfgr, in, out);
|
||||
else
|
||||
for (i = 0; i < iter; ++i)
|
||||
kiss_fftri (cfgr, in, out);
|
||||
}
|
||||
}else{
|
||||
/* multi-dimensional */
|
||||
for (i = 0; i < iter; ++i)
|
||||
kiss_fftnd(cfgnd,in,out);
|
||||
}
|
||||
}
|
||||
|
||||
void done(struct problem *p)
|
||||
{
|
||||
free(cfg);
|
||||
cfg=NULL;
|
||||
free(cfgr);
|
||||
cfgr=NULL;
|
||||
free(cfgnd);
|
||||
cfgnd=NULL;
|
||||
UNUSED(p);
|
||||
}
|
275
3rd-party/kissfft/test/kissfft-testsuite.sh
vendored
275
3rd-party/kissfft/test/kissfft-testsuite.sh
vendored
@ -1,275 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Test suite for kissfft
|
||||
#
|
||||
# Copyright (c) 2021, Vasyl Gello.
|
||||
# This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# See COPYING file for more information.
|
||||
#
|
||||
|
||||
if [ ! -f CHANGELOG ] && [ ! -f kiss_fft.h ]; then
|
||||
echo "ERROR: Please run this testsuite from top level of kissfft source tree!" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
TESTSUITEOUTDIR="$2"
|
||||
|
||||
if [ -z "$TESTSUITEOUTDIR" ]; then
|
||||
TESTSUITEOUTDIR="/tmp/kissfft-testsuite"
|
||||
fi
|
||||
|
||||
if ! mkdir -p "$TESTSUITEOUTDIR"; then
|
||||
echo "ERROR: Can not create directory '$TESTSUITEOUTDIR'!" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Test runner function
|
||||
#
|
||||
# Parameters:
|
||||
#
|
||||
# $1 - Action: "test" or "install"
|
||||
# $2 - Build type: "make" or "cmake"
|
||||
# $3 - Data type: "float" "double" "int16_t" "int32_t" "simd"
|
||||
# $4 - library type: "shared" or "static"
|
||||
# $5 - Include tools: "yes" or "no"
|
||||
# $6 - Install root dir: "existing writable directory"
|
||||
#
|
||||
|
||||
test_runner() {
|
||||
_ACTION="$1"
|
||||
_BUILD_TYPE="$2"
|
||||
_DATA_TYPE="$3"
|
||||
_LIB_TYPE="$4"
|
||||
_OPENMP="$5"
|
||||
_INCLUDE_TOOLS="$6"
|
||||
_INSTALL_ROOT_DIR="$7"
|
||||
|
||||
_CMAKE_OPTS=""
|
||||
_MAKE_OPTS=""
|
||||
|
||||
# Prepare install directory name without "$_OPENMP" and "$_INCLUDE_TOOLS"
|
||||
|
||||
_INSTALL_DIR="$_INSTALL_ROOT_DIR/$_BUILD_TYPE/$_DATA_TYPE/$_LIB_TYPE"
|
||||
|
||||
# Prepare log file without "$_OPENMP" and "$_INCLUDE_TOOLS"
|
||||
|
||||
_LOG_FILE="$_INSTALL_ROOT_DIR/$_ACTION-$_BUILD_TYPE-$_DATA_TYPE-$_LIB_TYPE"
|
||||
|
||||
# Validate parameters
|
||||
|
||||
# Create install root directory
|
||||
|
||||
if [ -z "$_INSTALL_ROOT_DIR" ]; then
|
||||
echo "" >&2
|
||||
echo "ERROR: Empty path to writeable directory" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$_INSTALL_ROOT_DIR" ]; then
|
||||
if ! mkdir -p "$_INSTALL_ROOT_DIR"; then
|
||||
echo "" >&2
|
||||
echo "ERROR: Can not create directory '$_INSTALL_ROOT_DIR'" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_BUILD_TYPE" != "make" ] && [ "$_BUILD_TYPE" != "cmake" ]; then
|
||||
echo "ERROR: Build type must be one of: cmake make" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$_DATA_TYPE" != "double" ] &&
|
||||
[ "$_DATA_TYPE" != "float" ] &&
|
||||
[ "$_DATA_TYPE" != "int16_t" ] &&
|
||||
[ "$_DATA_TYPE" != "int32_t" ] &&
|
||||
[ "$_DATA_TYPE" != "simd" ];
|
||||
then
|
||||
echo "ERROR: Data type must be one of: double float int16_t int32_t simd" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
else
|
||||
_MAKE_OPTS="$_MAKE_OPTS KISSFFT_DATATYPE=$_DATA_TYPE"
|
||||
_CMAKE_OPTS="$_CMAKE_OPTS -DKISSFFT_DATATYPE=$_DATA_TYPE"
|
||||
fi
|
||||
|
||||
if [ "$_LIB_TYPE" != "shared" ] && [ "$_LIB_TYPE" != "static" ]; then
|
||||
echo "ERROR: Library type must be one of: shared static" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
case "$_LIB_TYPE" in
|
||||
"shared")
|
||||
;;
|
||||
"static")
|
||||
_MAKE_OPTS="$_MAKE_OPTS KISSFFT_STATIC=1"
|
||||
_CMAKE_OPTS="$_CMAKE_OPTS -DKISSFFT_STATIC=ON"
|
||||
;;
|
||||
"*")
|
||||
echo "ERROR: OpenMP inclusion must be one of: no yes" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$_OPENMP" in
|
||||
"yes")
|
||||
_INSTALL_DIR="$_INSTALL_DIR/openmp"
|
||||
_LOG_FILE="$_LOG_FILE-openmp"
|
||||
_MAKE_OPTS="$_MAKE_OPTS KISSFFT_OPENMP=1"
|
||||
_CMAKE_OPTS="$_CMAKE_OPTS -DKISSFFT_OPENMP=ON"
|
||||
;;
|
||||
"no")
|
||||
_INSTALL_DIR="$_INSTALL_DIR/noopenmp"
|
||||
_LOG_FILE="$_LOG_FILE-noopenmp"
|
||||
;;
|
||||
"*")
|
||||
echo "ERROR: OpenMP inclusion must be one of: no yes" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$_INCLUDE_TOOLS" in
|
||||
"yes")
|
||||
_INSTALL_DIR="$_INSTALL_DIR/tools"
|
||||
_LOG_FILE="$_LOG_FILE-tools"
|
||||
;;
|
||||
"no")
|
||||
_INSTALL_DIR="$_INSTALL_DIR/notools"
|
||||
_LOG_FILE="$_LOG_FILE-notools"
|
||||
_MAKE_OPTS="$_MAKE_OPTS KISSFFT_TOOLS=0"
|
||||
_CMAKE_OPTS="$_CMAKE_OPTS -DKISSFFT_TOOLS=OFF"
|
||||
;;
|
||||
"*")
|
||||
echo "ERROR: Tools inclusion must be one of: no yes" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Clean kissfft
|
||||
|
||||
rm -rf build 1>/dev/null 2>/dev/null
|
||||
make clean 1>/dev/null 2>&1
|
||||
|
||||
# Prepare status line
|
||||
|
||||
_STATUS_LINE="Running: $(printf "% 10s" "$_ACTION") |"
|
||||
_STATUS_LINE="$_STATUS_LINE Build Type: $(printf "% 7s" "$_BUILD_TYPE") |"
|
||||
_STATUS_LINE="$_STATUS_LINE Data Type: $(printf "% 7s" "$_DATA_TYPE") |"
|
||||
_STATUS_LINE="$_STATUS_LINE Lib Type: $(printf "% 7s" "$_LIB_TYPE") |"
|
||||
_STATUS_LINE="$_STATUS_LINE OpenMP: $(printf "% 3s" "$_OPENMP") |"
|
||||
_STATUS_LINE="$_STATUS_LINE Tools: $(printf "% 3s" "$_INCLUDE_TOOLS") |"
|
||||
|
||||
# Skip tests with tools not installed as they are same as with tools
|
||||
|
||||
if [ "$_ACTION" = "test" ] && [ "$_INCLUDE_TOOLS" = "no" ]; then
|
||||
return 2
|
||||
fi
|
||||
|
||||
# Run selected action
|
||||
|
||||
echo "$_STATUS_LINE"
|
||||
|
||||
case "$_ACTION" in
|
||||
"test")
|
||||
_MAKE_OPTS="$_MAKE_OPTS PREFIX=$_INSTALL_DIR"
|
||||
_CMAKE_OPTS="$_CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=$_INSTALL_DIR"
|
||||
|
||||
case "$_BUILD_TYPE" in
|
||||
"make")
|
||||
make $_MAKE_OPTS all 1>>"$_LOG_FILE" 2>&1 &&
|
||||
make $_MAKE_OPTS testsingle 1>>"$_LOG_FILE" 2>&1 &&
|
||||
_RET=$?
|
||||
;;
|
||||
"cmake")
|
||||
mkdir build 1>/dev/null 2>&1 &&
|
||||
cd build &&
|
||||
cmake $_CMAKE_OPTS .. 1>"$_LOG_FILE" 2>&1 &&
|
||||
make all 1>>"$_LOG_FILE" 2>&1 &&
|
||||
make test 1>>"$_LOG_FILE" 2>&1
|
||||
_RET=$?
|
||||
cd ..
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"install")
|
||||
_MAKE_OPTS="$_MAKE_OPTS PREFIX=$_INSTALL_DIR"
|
||||
_CMAKE_OPTS="$_CMAKE_OPTS -DCMAKE_INSTALL_PREFIX=$_INSTALL_DIR"
|
||||
|
||||
case "$_BUILD_TYPE" in
|
||||
"make")
|
||||
make $_MAKE_OPTS install 1>>"$_LOG_FILE" 2>&1
|
||||
_RET=$?
|
||||
;;
|
||||
"cmake")
|
||||
mkdir build 1>/dev/null 2>&1 &&
|
||||
cd build &&
|
||||
cmake $_CMAKE_OPTS .. 1>"$_LOG_FILE" 2>&1 &&
|
||||
make all 1>>"$_LOG_FILE" 2>&1 &&
|
||||
make install 1>>"$_LOG_FILE" 2>&1
|
||||
_RET=$?
|
||||
cd ..
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Action must be one of: test install" >&2
|
||||
echo "" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Clean kissfft
|
||||
|
||||
rm -rf build 1>/dev/null 2>/dev/null
|
||||
make clean 1>/dev/null 2>&1
|
||||
|
||||
# Return result
|
||||
|
||||
[ $_RET -eq 0 ] && return 0 || return 1
|
||||
}
|
||||
|
||||
# Main script
|
||||
|
||||
for ACTION in test install; do
|
||||
for BUILD_TYPE in make cmake; do
|
||||
for DATA_TYPE in float double int16_t int32_t simd; do
|
||||
for LIB_TYPE in shared static; do
|
||||
for OPENMP in no yes; do
|
||||
for INCLUDE_TOOLS in no yes; do
|
||||
test_runner \
|
||||
"$ACTION" \
|
||||
"$BUILD_TYPE" \
|
||||
"$DATA_TYPE" \
|
||||
"$LIB_TYPE" \
|
||||
"$OPENMP" \
|
||||
"$INCLUDE_TOOLS" \
|
||||
"$TESTSUITEOUTDIR"
|
||||
|
||||
case $? in
|
||||
0)
|
||||
echo "Result: OK"
|
||||
;;
|
||||
1)
|
||||
echo "Result: FAIL"
|
||||
;;
|
||||
2)
|
||||
# Ignore it
|
||||
echo "Result: IGNORE" 1>/dev/null
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
done 2>&1 | tee "$TESTSUITEOUTDIR/all-tests.log"
|
56
3rd-party/kissfft/test/pstats.c
vendored
56
3rd-party/kissfft/test/pstats.c
vendored
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pstats.h"
|
||||
|
||||
static struct tms tms_beg;
|
||||
static struct tms tms_end;
|
||||
static int has_times = 0;
|
||||
|
||||
|
||||
void pstats_init(void)
|
||||
{
|
||||
has_times = times(&tms_beg) != -1;
|
||||
}
|
||||
|
||||
static void tms_report(void)
|
||||
{
|
||||
double cputime;
|
||||
if (! has_times )
|
||||
return;
|
||||
times(&tms_end);
|
||||
cputime = ( ((float)tms_end.tms_utime + tms_end.tms_stime + tms_end.tms_cutime + tms_end.tms_cstime ) -
|
||||
((float)tms_beg.tms_utime + tms_beg.tms_stime + tms_beg.tms_cutime + tms_beg.tms_cstime ) )
|
||||
/ sysconf(_SC_CLK_TCK);
|
||||
fprintf(stderr,"\tcputime=%.3f\n" , cputime);
|
||||
}
|
||||
|
||||
static void ps_report(void)
|
||||
{
|
||||
char buf[1024];
|
||||
#ifdef __APPLE__ /* MAC OS X */
|
||||
sprintf(buf,"ps -o command,majflt,minflt,rss,pagein,vsz -p %d 1>&2",getpid() );
|
||||
#else /* GNU/Linux */
|
||||
sprintf(buf,"ps -o comm,majflt,minflt,rss,drs,pagein,sz,trs,vsz %d 1>&2",getpid() );
|
||||
#endif
|
||||
if (system( buf )==-1) {
|
||||
perror("system call to ps failed");
|
||||
}
|
||||
}
|
||||
|
||||
void pstats_report()
|
||||
{
|
||||
ps_report();
|
||||
tms_report();
|
||||
}
|
||||
|
14
3rd-party/kissfft/test/pstats.h
vendored
14
3rd-party/kissfft/test/pstats.h
vendored
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#ifndef PSTATS_H
|
||||
#define PSTATS_H
|
||||
|
||||
void pstats_init(void);
|
||||
void pstats_report(void);
|
||||
|
||||
#endif
|
179
3rd-party/kissfft/test/test_real.c
vendored
179
3rd-party/kissfft/test/test_real.c
vendored
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#include "kiss_fftr.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
#include <sys/times.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static double cputime(void)
|
||||
{
|
||||
struct tms t;
|
||||
times(&t);
|
||||
return (double)(t.tms_utime + t.tms_stime)/ sysconf(_SC_CLK_TCK) ;
|
||||
}
|
||||
|
||||
static
|
||||
kiss_fft_scalar rand_scalar(void)
|
||||
{
|
||||
#ifdef USE_SIMD
|
||||
return _mm_set1_ps(rand()-RAND_MAX/2);
|
||||
#else
|
||||
kiss_fft_scalar s = (kiss_fft_scalar)(rand() -RAND_MAX/2);
|
||||
return s/2;
|
||||
#endif
|
||||
}
|
||||
|
||||
static
|
||||
double snr_compare( kiss_fft_cpx * vec1,kiss_fft_cpx * vec2, int n)
|
||||
{
|
||||
int k;
|
||||
double sigpow=1e-10,noisepow=1e-10,err,snr,scale=0;
|
||||
|
||||
#ifdef USE_SIMD
|
||||
float *fv1 = (float*)vec1;
|
||||
float *fv2 = (float*)vec2;
|
||||
for (k=0;k<8*n;++k) {
|
||||
sigpow += *fv1 * *fv1;
|
||||
err = *fv1 - *fv2;
|
||||
noisepow += err*err;
|
||||
++fv1;
|
||||
++fv2;
|
||||
}
|
||||
#else
|
||||
for (k=0;k<n;++k) {
|
||||
sigpow += (double)vec1[k].r * (double)vec1[k].r +
|
||||
(double)vec1[k].i * (double)vec1[k].i;
|
||||
err = (double)vec1[k].r - (double)vec2[k].r;
|
||||
noisepow += err * err;
|
||||
err = (double)vec1[k].i - (double)vec2[k].i;
|
||||
noisepow += err * err;
|
||||
|
||||
if (vec1[k].r)
|
||||
scale +=(double) vec2[k].r / (double)vec1[k].r;
|
||||
}
|
||||
#endif
|
||||
snr = 10*log10( sigpow / noisepow );
|
||||
scale /= n;
|
||||
if (snr<10) {
|
||||
printf( "\npoor snr, try a scaling factor %f\n" , scale );
|
||||
exit(1);
|
||||
}
|
||||
return snr;
|
||||
}
|
||||
|
||||
#ifndef NUMFFTS
|
||||
#define NUMFFTS 10000
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
int nfft = 8*3*5;
|
||||
double ts,tfft,trfft;
|
||||
int i;
|
||||
if (argc>1)
|
||||
nfft = atoi(argv[1]);
|
||||
kiss_fft_cpx cin[nfft];
|
||||
kiss_fft_cpx cout[nfft];
|
||||
kiss_fft_cpx sout[nfft];
|
||||
kiss_fft_cfg kiss_fft_state;
|
||||
kiss_fftr_cfg kiss_fftr_state;
|
||||
|
||||
kiss_fft_scalar rin[nfft+2];
|
||||
kiss_fft_scalar rout[nfft+2];
|
||||
kiss_fft_scalar zero;
|
||||
memset(&zero,0,sizeof(zero) ); // ugly way of setting short,int,float,double, or __m128 to zero
|
||||
|
||||
srand(time(0));
|
||||
|
||||
for (i=0;i<nfft;++i) {
|
||||
rin[i] = rand_scalar();
|
||||
cin[i].r = rin[i];
|
||||
cin[i].i = zero;
|
||||
}
|
||||
|
||||
kiss_fft_state = kiss_fft_alloc(nfft,0,0,0);
|
||||
kiss_fftr_state = kiss_fftr_alloc(nfft,0,0,0);
|
||||
kiss_fft(kiss_fft_state,cin,cout);
|
||||
kiss_fftr(kiss_fftr_state,rin,sout);
|
||||
/*
|
||||
printf(" results from kiss_fft : (%f,%f), (%f,%f), (%f,%f) ...\n "
|
||||
, (float)cout[0].r , (float)cout[0].i
|
||||
, (float)cout[1].r , (float)cout[1].i
|
||||
, (float)cout[2].r , (float)cout[2].i);
|
||||
printf(" results from kiss_fftr: (%f,%f), (%f,%f), (%f,%f) ...\n "
|
||||
, (float)sout[0].r , (float)sout[0].i
|
||||
, (float)sout[1].r , (float)sout[1].i
|
||||
, (float)sout[2].r , (float)sout[2].i);
|
||||
*/
|
||||
|
||||
printf( "nfft=%d, inverse=%d, snr=%g\n",
|
||||
nfft,0, snr_compare(cout,sout,(nfft/2)+1) );
|
||||
ts = cputime();
|
||||
for (i=0;i<NUMFFTS;++i) {
|
||||
kiss_fft(kiss_fft_state,cin,cout);
|
||||
}
|
||||
tfft = cputime() - ts;
|
||||
|
||||
ts = cputime();
|
||||
for (i=0;i<NUMFFTS;++i) {
|
||||
kiss_fftr( kiss_fftr_state, rin, cout );
|
||||
/* kiss_fftri(kiss_fftr_state,cout,rin); */
|
||||
}
|
||||
trfft = cputime() - ts;
|
||||
|
||||
printf("%d complex ffts took %gs, real took %gs\n",NUMFFTS,tfft,trfft);
|
||||
|
||||
free(kiss_fft_state);
|
||||
free(kiss_fftr_state);
|
||||
|
||||
kiss_fft_state = kiss_fft_alloc(nfft,1,0,0);
|
||||
kiss_fftr_state = kiss_fftr_alloc(nfft,1,0,0);
|
||||
|
||||
memset(cin,0,sizeof(cin));
|
||||
#if 1
|
||||
for (i=1;i< nfft/2;++i) {
|
||||
//cin[i].r = (kiss_fft_scalar)(rand()-RAND_MAX/2);
|
||||
cin[i].r = rand_scalar();
|
||||
cin[i].i = rand_scalar();
|
||||
}
|
||||
#else
|
||||
cin[0].r = 12000;
|
||||
cin[3].r = 12000;
|
||||
cin[nfft/2].r = 12000;
|
||||
#endif
|
||||
|
||||
// conjugate symmetry of real signal
|
||||
for (i=1;i< nfft/2;++i) {
|
||||
cin[nfft-i].r = cin[i].r;
|
||||
cin[nfft-i].i = - cin[i].i;
|
||||
}
|
||||
|
||||
kiss_fft(kiss_fft_state,cin,cout);
|
||||
kiss_fftri(kiss_fftr_state,cin,rout);
|
||||
/*
|
||||
printf(" results from inverse kiss_fft : (%f,%f), (%f,%f), (%f,%f), (%f,%f), (%f,%f) ...\n "
|
||||
, (float)cout[0].r , (float)cout[0].i , (float)cout[1].r , (float)cout[1].i , (float)cout[2].r , (float)cout[2].i , (float)cout[3].r , (float)cout[3].i , (float)cout[4].r , (float)cout[4].i
|
||||
);
|
||||
|
||||
printf(" results from inverse kiss_fftr: %f,%f,%f,%f,%f ... \n"
|
||||
,(float)rout[0] ,(float)rout[1] ,(float)rout[2] ,(float)rout[3] ,(float)rout[4]);
|
||||
*/
|
||||
for (i=0;i<nfft;++i) {
|
||||
sout[i].r = rout[i];
|
||||
sout[i].i = zero;
|
||||
}
|
||||
|
||||
printf( "nfft=%d, inverse=%d, snr=%g\n",
|
||||
nfft,1, snr_compare(cout,sout,nfft/2) );
|
||||
free(kiss_fft_state);
|
||||
free(kiss_fftr_state);
|
||||
|
||||
return 0;
|
||||
}
|
25
3rd-party/kissfft/test/test_simd.c
vendored
25
3rd-party/kissfft/test/test_simd.c
vendored
@ -1,25 +0,0 @@
|
||||
#include <kiss_fftnd.h>
|
||||
|
||||
static void test1(void)
|
||||
{
|
||||
int is_inverse = 1;
|
||||
int n[2] = {256,256};
|
||||
size_t nbytes = sizeof(kiss_fft_cpx)*n[0]*n[1];
|
||||
|
||||
kiss_fft_cpx * inbuf = _mm_malloc(nbytes,16);
|
||||
kiss_fft_cpx * outbuf = _mm_malloc(nbytes,16);
|
||||
memset(inbuf,0,nbytes);
|
||||
memset(outbuf,0,nbytes);
|
||||
|
||||
kiss_fftnd_cfg cfg = kiss_fftnd_alloc(n,2,is_inverse,0,0);
|
||||
kiss_fftnd(cfg,inbuf,outbuf);
|
||||
kiss_fft_free(cfg);
|
||||
_mm_free(inbuf);
|
||||
_mm_free(outbuf);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test1();
|
||||
return 0;
|
||||
}
|
80
3rd-party/kissfft/test/testcpp.cc
vendored
80
3rd-party/kissfft/test/testcpp.cc
vendored
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#include "kissfft.hh"
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <sys/time.h>
|
||||
static inline
|
||||
double curtime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (double)tv.tv_sec + (double)tv.tv_usec*.000001;
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
template <class T>
|
||||
void dotest(int nfft)
|
||||
{
|
||||
typedef kissfft<T> FFT;
|
||||
typedef std::complex<T> cpx_type;
|
||||
|
||||
cout << "type:" << typeid(T).name() << " nfft:" << nfft;
|
||||
|
||||
FFT fft(nfft,false);
|
||||
|
||||
vector<cpx_type> inbuf(nfft);
|
||||
vector<cpx_type> outbuf(nfft);
|
||||
for (int k=0;k<nfft;++k)
|
||||
inbuf[k]= cpx_type(
|
||||
(T)(rand()/(double)RAND_MAX - .5),
|
||||
(T)(rand()/(double)RAND_MAX - .5) );
|
||||
fft.transform( &inbuf[0] , &outbuf[0] );
|
||||
|
||||
long double totalpower=0;
|
||||
long double difpower=0;
|
||||
for (int k0=0;k0<nfft;++k0) {
|
||||
complex<long double> acc = 0;
|
||||
long double phinc = 2*k0* M_PIl / nfft;
|
||||
for (int k1=0;k1<nfft;++k1) {
|
||||
complex<long double> x(inbuf[k1].real(),inbuf[k1].imag());
|
||||
acc += x * exp( complex<long double>(0,-k1*phinc) );
|
||||
}
|
||||
totalpower += norm(acc);
|
||||
complex<long double> x(outbuf[k0].real(),outbuf[k0].imag());
|
||||
complex<long double> dif = acc - x;
|
||||
difpower += norm(dif);
|
||||
}
|
||||
cout << " RMSE:" << sqrt(difpower/totalpower) << "\t";
|
||||
|
||||
double t0 = curtime();
|
||||
int nits=20e6/nfft;
|
||||
for (int k=0;k<nits;++k) {
|
||||
fft.transform( &inbuf[0] , &outbuf[0] );
|
||||
}
|
||||
double t1 = curtime();
|
||||
cout << " MSPS:" << ( (nits*nfft)*1e-6/ (t1-t0) ) << endl;
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
if (argc>1) {
|
||||
for (int k=1;k<argc;++k) {
|
||||
int nfft = atoi(argv[k]);
|
||||
dotest<float>(nfft); dotest<double>(nfft); dotest<long double>(nfft);
|
||||
}
|
||||
}else{
|
||||
dotest<float>(32); dotest<double>(32); dotest<long double>(32);
|
||||
dotest<float>(1024); dotest<double>(1024); dotest<long double>(1024);
|
||||
dotest<float>(840); dotest<double>(840); dotest<long double>(840);
|
||||
}
|
||||
return 0;
|
||||
}
|
143
3rd-party/kissfft/test/testkiss.py
vendored
143
3rd-party/kissfft/test/testkiss.py
vendored
@ -1,143 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2003-2019, Mark Borgerding. All rights reserved.
|
||||
# This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
# See COPYING file for more information.
|
||||
from __future__ import absolute_import, division, print_function
|
||||
import math
|
||||
import sys
|
||||
import os
|
||||
import random
|
||||
import struct
|
||||
import getopt
|
||||
import numpy as np
|
||||
|
||||
po = math.pi
|
||||
e = math.e
|
||||
do_real = False
|
||||
datatype = os.environ.get('KISSFFT_DATATYPE', 'float')
|
||||
openmp = os.environ.get('KISSFFT_OPENMP', 'float')
|
||||
|
||||
util = './fastfilt-' + datatype
|
||||
|
||||
if openmp == '1' or openmp == 'ON':
|
||||
util = util + '-openmp'
|
||||
|
||||
minsnr = 90
|
||||
if datatype == 'double':
|
||||
dtype = np.float64
|
||||
elif datatype == 'float':
|
||||
dtype = np.float32
|
||||
elif datatype == 'int16_t':
|
||||
dtype = np.int16
|
||||
minsnr = 10
|
||||
elif datatype == 'int32_t':
|
||||
dtype = np.int32
|
||||
elif datatype == 'simd':
|
||||
sys.stderr.write('testkiss.py does not yet test simd')
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.stderr.write('unrecognized datatype {0}\n'.format(datatype))
|
||||
sys.exit(1)
|
||||
|
||||
def dopack(x):
|
||||
if np.iscomplexobj(x):
|
||||
x = x.astype(np.complex128).view(np.float64)
|
||||
else:
|
||||
x = x.astype(np.float64)
|
||||
return x.astype(dtype).tobytes()
|
||||
|
||||
def dounpack(x, cpx):
|
||||
x = np.frombuffer(x, dtype).astype(np.float64)
|
||||
if cpx:
|
||||
x = x[::2] + 1j * x[1::2]
|
||||
return x
|
||||
|
||||
def make_random(shape):
|
||||
'create random uniform (-1,1) data of the given shape'
|
||||
if do_real:
|
||||
return np.random.uniform(-1, 1, shape)
|
||||
else:
|
||||
return (np.random.uniform(-1, 1, shape) + 1j * np.random.uniform(-1, 1, shape))
|
||||
|
||||
def randmat(ndim):
|
||||
'create a random multidimensional array in range (-1,1)'
|
||||
dims = np.random.randint(2, 5, ndim)
|
||||
if do_real:
|
||||
dims[-1] = (dims[-1] // 2) * 2 # force even last dimension if real
|
||||
return make_random(dims)
|
||||
|
||||
def test_fft(ndim):
|
||||
x = randmat(ndim)
|
||||
|
||||
if do_real:
|
||||
xver = np.fft.rfftn(x)
|
||||
else:
|
||||
xver = np.fft.fftn(x)
|
||||
|
||||
x2 = dofft(x, do_real)
|
||||
err = xver - x2
|
||||
errf = err.ravel()
|
||||
xverf = xver.ravel()
|
||||
errpow = np.vdot(errf, errf) + 1e-10
|
||||
sigpow = np.vdot(xverf, xverf) + 1e-10
|
||||
snr = 10 * math.log10(abs(sigpow / errpow))
|
||||
print('SNR (compared to NumPy) : {0:.1f}dB'.format(float(snr)))
|
||||
|
||||
if snr < minsnr:
|
||||
print('xver=', xver)
|
||||
print('x2=', x2)
|
||||
print('err', err)
|
||||
sys.exit(1)
|
||||
|
||||
def dofft(x, isreal):
|
||||
dims = list(np.shape(x))
|
||||
x = x.ravel()
|
||||
|
||||
scale = 1
|
||||
if datatype == 'int16_t':
|
||||
x = 32767 * x
|
||||
scale = len(x) / 32767.0
|
||||
elif datatype == 'int32_t':
|
||||
x = 2147483647.0 * x
|
||||
scale = len(x) / 2147483647.0
|
||||
|
||||
cmd = util + ' -n '
|
||||
cmd += ','.join([str(d) for d in dims])
|
||||
if do_real:
|
||||
cmd += ' -R '
|
||||
|
||||
print(cmd)
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
|
||||
|
||||
p.stdin.write(dopack(x))
|
||||
p.stdin.close()
|
||||
|
||||
res = dounpack(p.stdout.read(), 1)
|
||||
if do_real:
|
||||
dims[-1] = (dims[-1] // 2) + 1
|
||||
|
||||
res = scale * res
|
||||
|
||||
p.wait()
|
||||
return np.reshape(res, dims)
|
||||
|
||||
def main():
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'r')
|
||||
opts = dict(opts)
|
||||
global do_real
|
||||
do_real = '-r' in opts
|
||||
if do_real:
|
||||
print('Testing multi-dimensional real FFTs')
|
||||
else:
|
||||
print('Testing multi-dimensional FFTs')
|
||||
|
||||
for dim in range(1, 4):
|
||||
test_fft(dim)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
101
3rd-party/kissfft/test/twotonetest.c
vendored
101
3rd-party/kissfft/test/twotonetest.c
vendored
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fftr.h"
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
static
|
||||
double two_tone_test( int nfft, int bin1,int bin2)
|
||||
{
|
||||
kiss_fftr_cfg cfg = NULL;
|
||||
kiss_fft_cpx *kout = NULL;
|
||||
kiss_fft_scalar *tbuf = NULL;
|
||||
|
||||
int i;
|
||||
double f1 = bin1*2*M_PI/nfft;
|
||||
double f2 = bin2*2*M_PI/nfft;
|
||||
double sigpow=0;
|
||||
double noisepow=0;
|
||||
#if FIXED_POINT==32
|
||||
long maxrange = LONG_MAX;
|
||||
#else
|
||||
long maxrange = SHRT_MAX;/* works fine for float too*/
|
||||
#endif
|
||||
|
||||
cfg = kiss_fftr_alloc(nfft , 0, NULL, NULL);
|
||||
tbuf = KISS_FFT_MALLOC(nfft * sizeof(kiss_fft_scalar));
|
||||
kout = KISS_FFT_MALLOC(nfft * sizeof(kiss_fft_cpx));
|
||||
|
||||
/* generate a signal with two tones*/
|
||||
for (i = 0; i < nfft; i++) {
|
||||
#ifdef USE_SIMD
|
||||
tbuf[i] = _mm_set1_ps( (maxrange>>1)*cos(f1*i)
|
||||
+ (maxrange>>1)*cos(f2*i) );
|
||||
#else
|
||||
tbuf[i] = (maxrange>>1)*cos(f1*i)
|
||||
+ (maxrange>>1)*cos(f2*i);
|
||||
#endif
|
||||
}
|
||||
|
||||
kiss_fftr(cfg, tbuf, kout);
|
||||
|
||||
for (i=0;i < (nfft/2+1);++i) {
|
||||
#ifdef USE_SIMD
|
||||
double tmpr = (double)*(float*)&kout[i].r / (double)maxrange;
|
||||
double tmpi = (double)*(float*)&kout[i].i / (double)maxrange;
|
||||
#else
|
||||
double tmpr = (double)kout[i].r / (double)maxrange;
|
||||
double tmpi = (double)kout[i].i / (double)maxrange;
|
||||
#endif
|
||||
double mag2 = tmpr*tmpr + tmpi*tmpi;
|
||||
if (i!=0 && i!= nfft/2)
|
||||
mag2 *= 2; /* all bins except DC and Nyquist have symmetric counterparts implied*/
|
||||
|
||||
/* if there is power in one of the expected bins, it is signal, otherwise noise*/
|
||||
if ( i!=bin1 && i != bin2 )
|
||||
noisepow += mag2;
|
||||
else
|
||||
sigpow += mag2;
|
||||
}
|
||||
kiss_fft_cleanup();
|
||||
/*printf("TEST %d,%d,%d noise @ %fdB\n",nfft,bin1,bin2,10*log10(noisepow/sigpow +1e-30) );*/
|
||||
return 10*log10(sigpow/(noisepow+1e-50) );
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
int nfft = 4*2*2*3*5;
|
||||
if (argc>1) nfft = atoi(argv[1]);
|
||||
|
||||
int i,j;
|
||||
double minsnr = 500;
|
||||
double maxsnr = -500;
|
||||
double snr;
|
||||
for (i=0;i<nfft/2;i+= (nfft>>4)+1) {
|
||||
for (j=i;j<nfft/2;j+=(nfft>>4)+7) {
|
||||
snr = two_tone_test(nfft,i,j);
|
||||
if (snr<minsnr) {
|
||||
minsnr=snr;
|
||||
}
|
||||
if (snr>maxsnr) {
|
||||
maxsnr=snr;
|
||||
}
|
||||
}
|
||||
}
|
||||
snr = two_tone_test(nfft,nfft/2,nfft/2);
|
||||
if (snr<minsnr) minsnr=snr;
|
||||
if (snr>maxsnr) maxsnr=snr;
|
||||
|
||||
printf("TwoToneTest: snr ranges from %ddB to %ddB\n",(int)minsnr,(int)maxsnr);
|
||||
printf("sizeof(kiss_fft_scalar) = %d\n",(int)sizeof(kiss_fft_scalar) );
|
||||
return 0;
|
||||
}
|
29
3rd-party/kissfft/tools/CMakeLists.txt
vendored
29
3rd-party/kissfft/tools/CMakeLists.txt
vendored
@ -1,29 +0,0 @@
|
||||
add_kissfft_executable(fastconvr kiss_fastfir.c)
|
||||
target_compile_definitions(fastconvr PRIVATE REAL_FASTFIR FAST_FILT_UTIL)
|
||||
|
||||
add_kissfft_executable(fastconv kiss_fastfir.c)
|
||||
target_compile_definitions(fastconv PRIVATE FAST_FILT_UTIL)
|
||||
|
||||
add_kissfft_executable(fft fftutil.c)
|
||||
|
||||
install(TARGETS fastconv fastconvr fft
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PUBLIC_HEADER DESTINATION ${PKGINCLUDEDIR})
|
||||
|
||||
# psdpng does not build with "simd" datatype
|
||||
if(NOT KISSFFT_DATATYPE MATCHES "simd")
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(libpng REQUIRED IMPORTED_TARGET libpng)
|
||||
add_kissfft_executable(psdpng psdpng.c)
|
||||
target_link_libraries(psdpng PRIVATE PkgConfig::libpng)
|
||||
install(TARGETS psdpng
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
PUBLIC_HEADER DESTINATION ${PKGINCLUDEDIR})
|
||||
endif()
|
||||
|
||||
#FIXME: dumphdr.c is not available
|
||||
#add_kissfft_executable(dumphdr dumphdr.c)
|
101
3rd-party/kissfft/tools/Makefile
vendored
101
3rd-party/kissfft/tools/Makefile
vendored
@ -1,101 +0,0 @@
|
||||
#
|
||||
# Warnings
|
||||
#
|
||||
|
||||
WARNINGS = -W -Wall -Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast \
|
||||
-Wwrite-strings
|
||||
|
||||
#
|
||||
# Compile-time definitions
|
||||
#
|
||||
|
||||
CFLAGS = -Wall -O3 $(WARNINGS)
|
||||
#CFLAGS = -Wall -O3 -pedantic -march=pentiumpro -ffast-math -fomit-frame-pointer $(WARNINGS)
|
||||
# If the above flags do not work, try the following
|
||||
# tip: try -openmp or -fopenmp to use multiple cores
|
||||
|
||||
CFLAGS += $(CFLAGADD)
|
||||
|
||||
#
|
||||
# Check missing external libraries
|
||||
#
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
LIBPNG_MISSING = $(shell echo "int main(){return 0;}" > _test_library_dummy.c; \
|
||||
$(CC) -o _test_library_dummy _test_library_dummy.c -lpng; \
|
||||
echo $$?; \
|
||||
rm -f _test_library_dummy.c _test_library_dummy)
|
||||
endif
|
||||
|
||||
#
|
||||
# Tool names
|
||||
#
|
||||
|
||||
ifneq ($(KISSFFT_OPENMP),1)
|
||||
FFTUTIL = fft-$(KISSFFT_DATATYPE)
|
||||
FASTFILT = fastconv-$(KISSFFT_DATATYPE)
|
||||
FASTFILTREAL = fastconvr-$(KISSFFT_DATATYPE)
|
||||
PSDPNG = psdpng-$(KISSFFT_DATATYPE)
|
||||
DUMPHDR = dumphdr-$(KISSFFT_DATATYPE)
|
||||
else
|
||||
FFTUTIL = fft-$(KISSFFT_DATATYPE)-openmp
|
||||
FASTFILT = fastconv-$(KISSFFT_DATATYPE)-openmp
|
||||
FASTFILTREAL = fastconvr-$(KISSFFT_DATATYPE)-openmp
|
||||
PSDPNG = psdpng-$(KISSFFT_DATATYPE)-openmp
|
||||
DUMPHDR = dumphdr-$(KISSFFT_DATATYPE)-openmp
|
||||
endif
|
||||
|
||||
#
|
||||
# Target: "make all"
|
||||
#
|
||||
|
||||
all: $(FFTUTIL) $(FASTFILT) $(FASTFILTREAL) $(PSDPNG)
|
||||
# $(DUMPHDR)
|
||||
|
||||
#
|
||||
# Individual tool make rules
|
||||
#
|
||||
|
||||
$(FASTFILTREAL): kiss_fastfir.c
|
||||
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) -DREAL_FASTFIR $< -DFAST_FILT_UTIL -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(FASTFILT): kiss_fastfir.c
|
||||
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) $< -DFAST_FILT_UTIL -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(FFTUTIL): fftutil.c
|
||||
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) $< -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
$(PSDPNG): psdpng.c
|
||||
ifeq "$(KISSFFT_DATATYPE)" "simd"
|
||||
$(warning WARNING: psdpng can not utilize SIMD!)
|
||||
else ifeq ($(LIBPNG_MISSING), 0)
|
||||
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) $< -L.. -l$(KISSFFTLIB_SHORTNAME) -lpng -lm
|
||||
else
|
||||
$(error ERROR: no libpng development files found!)
|
||||
endif
|
||||
|
||||
$(DUMPHDR): dumphdr.c
|
||||
$(CC) -o $@ $(CFLAGS) -I.. $(TYPEFLAGS) $< -L.. -l$(KISSFFTLIB_SHORTNAME) -lm
|
||||
|
||||
#
|
||||
# Target: "make install"
|
||||
#
|
||||
|
||||
install: all
|
||||
$(INSTALL) -Dt $(ABS_BINDIR) -m 755 \
|
||||
$(FFTUTIL) \
|
||||
$(FASTFILT) \
|
||||
$(FASTFILTREAL)
|
||||
|
||||
ifneq "$(KISSFFT_DATATYPE)" "simd"
|
||||
$(INSTALL) -Dt $(ABS_BINDIR) -m 755 \
|
||||
$(PSDPNG)
|
||||
endif
|
||||
|
||||
#
|
||||
# Target: "make clean"
|
||||
#
|
||||
|
||||
clean:
|
||||
rm -f *~ fft fft-* fastconv fastconv-* fastconvr fastconvr-* psdpng psdpng-* _test_library_dummy _test_library_dummy.c
|
202
3rd-party/kissfft/tools/fftutil.c
vendored
202
3rd-party/kissfft/tools/fftutil.c
vendored
@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fftndr.h"
|
||||
|
||||
static
|
||||
void fft_file(FILE * fin,FILE * fout,int nfft,int isinverse)
|
||||
{
|
||||
kiss_fft_cfg st;
|
||||
kiss_fft_cpx * buf;
|
||||
kiss_fft_cpx * bufout;
|
||||
|
||||
buf = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * nfft );
|
||||
bufout = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * nfft );
|
||||
st = kiss_fft_alloc( nfft ,isinverse ,0,0);
|
||||
|
||||
while ( fread( buf , sizeof(kiss_fft_cpx) * nfft ,1, fin ) > 0 ) {
|
||||
kiss_fft( st , buf ,bufout);
|
||||
fwrite( bufout , sizeof(kiss_fft_cpx) , nfft , fout );
|
||||
}
|
||||
free(st);
|
||||
free(buf);
|
||||
free(bufout);
|
||||
}
|
||||
|
||||
static
|
||||
void fft_filend(FILE * fin,FILE * fout,int *dims,int ndims,int isinverse)
|
||||
{
|
||||
kiss_fftnd_cfg st;
|
||||
kiss_fft_cpx *buf;
|
||||
int dimprod=1,i;
|
||||
for (i=0;i<ndims;++i)
|
||||
dimprod *= dims[i];
|
||||
|
||||
buf = (kiss_fft_cpx *) malloc (sizeof (kiss_fft_cpx) * dimprod);
|
||||
st = kiss_fftnd_alloc (dims, ndims, isinverse, 0, 0);
|
||||
|
||||
while (fread (buf, sizeof (kiss_fft_cpx) * dimprod, 1, fin) > 0) {
|
||||
kiss_fftnd (st, buf, buf);
|
||||
fwrite (buf, sizeof (kiss_fft_cpx), dimprod, fout);
|
||||
}
|
||||
free (st);
|
||||
free (buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static
|
||||
void fft_filend_real(FILE * fin,FILE * fout,int *dims,int ndims,int isinverse)
|
||||
{
|
||||
int dimprod=1,i;
|
||||
kiss_fftndr_cfg st;
|
||||
void *ibuf;
|
||||
void *obuf;
|
||||
int insize,outsize; // size in bytes
|
||||
|
||||
for (i=0;i<ndims;++i)
|
||||
dimprod *= dims[i];
|
||||
insize = outsize = dimprod;
|
||||
int rdim = dims[ndims-1];
|
||||
|
||||
if (isinverse)
|
||||
insize = insize*2*(rdim/2+1)/rdim;
|
||||
else
|
||||
outsize = outsize*2*(rdim/2+1)/rdim;
|
||||
|
||||
ibuf = malloc(insize*sizeof(kiss_fft_scalar));
|
||||
obuf = malloc(outsize*sizeof(kiss_fft_scalar));
|
||||
|
||||
st = kiss_fftndr_alloc(dims, ndims, isinverse, 0, 0);
|
||||
|
||||
while ( fread (ibuf, sizeof(kiss_fft_scalar), insize, fin) > 0) {
|
||||
if (isinverse) {
|
||||
kiss_fftndri(st,
|
||||
(kiss_fft_cpx*)ibuf,
|
||||
(kiss_fft_scalar*)obuf);
|
||||
}else{
|
||||
kiss_fftndr(st,
|
||||
(kiss_fft_scalar*)ibuf,
|
||||
(kiss_fft_cpx*)obuf);
|
||||
}
|
||||
fwrite (obuf, sizeof(kiss_fft_scalar), outsize,fout);
|
||||
}
|
||||
free(st);
|
||||
free(ibuf);
|
||||
free(obuf);
|
||||
}
|
||||
|
||||
static
|
||||
void fft_file_real(FILE * fin,FILE * fout,int nfft,int isinverse)
|
||||
{
|
||||
kiss_fftr_cfg st;
|
||||
kiss_fft_scalar * rbuf;
|
||||
kiss_fft_cpx * cbuf;
|
||||
|
||||
rbuf = (kiss_fft_scalar*)malloc(sizeof(kiss_fft_scalar) * nfft );
|
||||
cbuf = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * (nfft/2+1) );
|
||||
st = kiss_fftr_alloc( nfft ,isinverse ,0,0);
|
||||
|
||||
if (isinverse==0) {
|
||||
while ( fread( rbuf , sizeof(kiss_fft_scalar) * nfft ,1, fin ) > 0 ) {
|
||||
kiss_fftr( st , rbuf ,cbuf);
|
||||
fwrite( cbuf , sizeof(kiss_fft_cpx) , (nfft/2 + 1) , fout );
|
||||
}
|
||||
}else{
|
||||
while ( fread( cbuf , sizeof(kiss_fft_cpx) * (nfft/2+1) ,1, fin ) > 0 ) {
|
||||
kiss_fftri( st , cbuf ,rbuf);
|
||||
fwrite( rbuf , sizeof(kiss_fft_scalar) , nfft , fout );
|
||||
}
|
||||
}
|
||||
free(st);
|
||||
free(rbuf);
|
||||
free(cbuf);
|
||||
}
|
||||
|
||||
static
|
||||
int get_dims(char * arg,int * dims)
|
||||
{
|
||||
char *p0;
|
||||
int ndims=0;
|
||||
|
||||
do{
|
||||
p0 = strchr(arg,',');
|
||||
if (p0)
|
||||
*p0++ = '\0';
|
||||
dims[ndims++] = atoi(arg);
|
||||
// fprintf(stderr,"dims[%d] = %d\n",ndims-1,dims[ndims-1]);
|
||||
arg = p0;
|
||||
}while (p0);
|
||||
return ndims;
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
int isinverse=0;
|
||||
int isreal=0;
|
||||
FILE *fin=stdin;
|
||||
FILE *fout=stdout;
|
||||
int ndims=1;
|
||||
int dims[32];
|
||||
dims[0] = 1024; /*default fft size*/
|
||||
|
||||
while (1) {
|
||||
int c=getopt(argc,argv,"n:iR");
|
||||
if (c==-1) break;
|
||||
switch (c) {
|
||||
case 'n':
|
||||
ndims = get_dims(optarg,dims);
|
||||
break;
|
||||
case 'i':isinverse=1;break;
|
||||
case 'R':isreal=1;break;
|
||||
case '?':
|
||||
fprintf(stderr,"usage options:\n"
|
||||
"\t-n d1[,d2,d3...]: fft dimension(s)\n"
|
||||
"\t-i : inverse\n"
|
||||
"\t-R : real input samples, not complex\n");
|
||||
exit (1);
|
||||
default:fprintf(stderr,"bad %c\n",c);break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( optind < argc ) {
|
||||
if (strcmp("-",argv[optind]) !=0)
|
||||
fin = fopen(argv[optind],"rb");
|
||||
++optind;
|
||||
}
|
||||
|
||||
if ( optind < argc ) {
|
||||
if ( strcmp("-",argv[optind]) !=0 )
|
||||
fout = fopen(argv[optind],"wb");
|
||||
++optind;
|
||||
}
|
||||
|
||||
if (ndims==1) {
|
||||
if (isreal)
|
||||
fft_file_real(fin,fout,dims[0],isinverse);
|
||||
else
|
||||
fft_file(fin,fout,dims[0],isinverse);
|
||||
}else{
|
||||
if (isreal)
|
||||
fft_filend_real(fin,fout,dims,ndims,isinverse);
|
||||
else
|
||||
fft_filend(fin,fout,dims,ndims,isinverse);
|
||||
}
|
||||
|
||||
if (fout!=stdout) fclose(fout);
|
||||
if (fin!=stdin) fclose(fin);
|
||||
|
||||
return 0;
|
||||
}
|
464
3rd-party/kissfft/tools/kiss_fastfir.c
vendored
464
3rd-party/kissfft/tools/kiss_fastfir.c
vendored
@ -1,464 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include "_kiss_fft_guts.h"
|
||||
|
||||
|
||||
/*
|
||||
Some definitions that allow real or complex filtering
|
||||
*/
|
||||
#ifdef REAL_FASTFIR
|
||||
#define MIN_FFT_LEN 2048
|
||||
#include "kiss_fftr.h"
|
||||
typedef kiss_fft_scalar kffsamp_t;
|
||||
typedef kiss_fftr_cfg kfcfg_t;
|
||||
#define FFT_ALLOC kiss_fftr_alloc
|
||||
#define FFTFWD kiss_fftr
|
||||
#define FFTINV kiss_fftri
|
||||
#else
|
||||
#define MIN_FFT_LEN 1024
|
||||
typedef kiss_fft_cpx kffsamp_t;
|
||||
typedef kiss_fft_cfg kfcfg_t;
|
||||
#define FFT_ALLOC kiss_fft_alloc
|
||||
#define FFTFWD kiss_fft
|
||||
#define FFTINV kiss_fft
|
||||
#endif
|
||||
|
||||
typedef struct kiss_fastfir_state *kiss_fastfir_cfg;
|
||||
|
||||
|
||||
|
||||
kiss_fastfir_cfg kiss_fastfir_alloc(const kffsamp_t * imp_resp,size_t n_imp_resp,
|
||||
size_t * nfft,void * mem,size_t*lenmem);
|
||||
|
||||
/* see do_file_filter for usage */
|
||||
size_t kiss_fastfir( kiss_fastfir_cfg cfg, kffsamp_t * inbuf, kffsamp_t * outbuf, size_t n, size_t *offset);
|
||||
|
||||
|
||||
|
||||
static int verbose=0;
|
||||
|
||||
|
||||
struct kiss_fastfir_state{
|
||||
size_t nfft;
|
||||
size_t ngood;
|
||||
kfcfg_t fftcfg;
|
||||
kfcfg_t ifftcfg;
|
||||
kiss_fft_cpx * fir_freq_resp;
|
||||
kiss_fft_cpx * freqbuf;
|
||||
size_t n_freq_bins;
|
||||
kffsamp_t * tmpbuf;
|
||||
};
|
||||
|
||||
|
||||
kiss_fastfir_cfg kiss_fastfir_alloc(
|
||||
const kffsamp_t * imp_resp,size_t n_imp_resp,
|
||||
size_t *pnfft, /* if <= 0, an appropriate size will be chosen */
|
||||
void * mem,size_t*lenmem)
|
||||
{
|
||||
kiss_fastfir_cfg st = NULL;
|
||||
size_t len_fftcfg,len_ifftcfg;
|
||||
size_t memneeded = sizeof(struct kiss_fastfir_state);
|
||||
char * ptr;
|
||||
size_t i;
|
||||
size_t nfft=0;
|
||||
float scale;
|
||||
int n_freq_bins;
|
||||
if (pnfft)
|
||||
nfft=*pnfft;
|
||||
|
||||
if (nfft<=0) {
|
||||
/* determine fft size as next power of two at least 2x
|
||||
the impulse response length*/
|
||||
i=n_imp_resp-1;
|
||||
nfft=2;
|
||||
do{
|
||||
nfft<<=1;
|
||||
}while (i>>=1);
|
||||
#ifdef MIN_FFT_LEN
|
||||
if ( nfft < MIN_FFT_LEN )
|
||||
nfft=MIN_FFT_LEN;
|
||||
#endif
|
||||
}
|
||||
if (pnfft)
|
||||
*pnfft = nfft;
|
||||
|
||||
#ifdef REAL_FASTFIR
|
||||
n_freq_bins = nfft/2 + 1;
|
||||
#else
|
||||
n_freq_bins = nfft;
|
||||
#endif
|
||||
/*fftcfg*/
|
||||
FFT_ALLOC (nfft, 0, NULL, &len_fftcfg);
|
||||
memneeded += len_fftcfg;
|
||||
/*ifftcfg*/
|
||||
FFT_ALLOC (nfft, 1, NULL, &len_ifftcfg);
|
||||
memneeded += len_ifftcfg;
|
||||
/* tmpbuf */
|
||||
memneeded += sizeof(kffsamp_t) * nfft;
|
||||
/* fir_freq_resp */
|
||||
memneeded += sizeof(kiss_fft_cpx) * n_freq_bins;
|
||||
/* freqbuf */
|
||||
memneeded += sizeof(kiss_fft_cpx) * n_freq_bins;
|
||||
|
||||
if (lenmem == NULL) {
|
||||
st = (kiss_fastfir_cfg) malloc (memneeded);
|
||||
} else {
|
||||
if (*lenmem >= memneeded)
|
||||
st = (kiss_fastfir_cfg) mem;
|
||||
*lenmem = memneeded;
|
||||
}
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
st->nfft = nfft;
|
||||
st->ngood = nfft - n_imp_resp + 1;
|
||||
st->n_freq_bins = n_freq_bins;
|
||||
ptr=(char*)(st+1);
|
||||
|
||||
st->fftcfg = (kfcfg_t)ptr;
|
||||
ptr += len_fftcfg;
|
||||
|
||||
st->ifftcfg = (kfcfg_t)ptr;
|
||||
ptr += len_ifftcfg;
|
||||
|
||||
st->tmpbuf = (kffsamp_t*)ptr;
|
||||
ptr += sizeof(kffsamp_t) * nfft;
|
||||
|
||||
st->freqbuf = (kiss_fft_cpx*)ptr;
|
||||
ptr += sizeof(kiss_fft_cpx) * n_freq_bins;
|
||||
|
||||
st->fir_freq_resp = (kiss_fft_cpx*)ptr;
|
||||
ptr += sizeof(kiss_fft_cpx) * n_freq_bins;
|
||||
|
||||
FFT_ALLOC (nfft,0,st->fftcfg , &len_fftcfg);
|
||||
FFT_ALLOC (nfft,1,st->ifftcfg , &len_ifftcfg);
|
||||
|
||||
memset(st->tmpbuf,0,sizeof(kffsamp_t)*nfft);
|
||||
/*zero pad in the middle to left-rotate the impulse response
|
||||
This puts the scrap samples at the end of the inverse fft'd buffer */
|
||||
st->tmpbuf[0] = imp_resp[ n_imp_resp - 1 ];
|
||||
for (i=0;i<n_imp_resp - 1; ++i) {
|
||||
st->tmpbuf[ nfft - n_imp_resp + 1 + i ] = imp_resp[ i ];
|
||||
}
|
||||
|
||||
FFTFWD(st->fftcfg,st->tmpbuf,st->fir_freq_resp);
|
||||
|
||||
/* TODO: this won't work for fixed point */
|
||||
scale = 1.0 / st->nfft;
|
||||
|
||||
for ( i=0; i < st->n_freq_bins; ++i ) {
|
||||
#ifdef USE_SIMD
|
||||
st->fir_freq_resp[i].r *= _mm_set1_ps(scale);
|
||||
st->fir_freq_resp[i].i *= _mm_set1_ps(scale);
|
||||
#else
|
||||
st->fir_freq_resp[i].r *= scale;
|
||||
st->fir_freq_resp[i].i *= scale;
|
||||
#endif
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
static void fastconv1buf(const kiss_fastfir_cfg st,const kffsamp_t * in,kffsamp_t * out)
|
||||
{
|
||||
size_t i;
|
||||
/* multiply the frequency response of the input signal by
|
||||
that of the fir filter*/
|
||||
FFTFWD( st->fftcfg, in , st->freqbuf );
|
||||
for ( i=0; i<st->n_freq_bins; ++i ) {
|
||||
kiss_fft_cpx tmpsamp;
|
||||
C_MUL(tmpsamp,st->freqbuf[i],st->fir_freq_resp[i]);
|
||||
st->freqbuf[i] = tmpsamp;
|
||||
}
|
||||
|
||||
/* perform the inverse fft*/
|
||||
FFTINV(st->ifftcfg,st->freqbuf,out);
|
||||
}
|
||||
|
||||
/* n : the size of inbuf and outbuf in samples
|
||||
return value: the number of samples completely processed
|
||||
n-retval samples should be copied to the front of the next input buffer */
|
||||
static size_t kff_nocopy(
|
||||
kiss_fastfir_cfg st,
|
||||
const kffsamp_t * inbuf,
|
||||
kffsamp_t * outbuf,
|
||||
size_t n)
|
||||
{
|
||||
size_t norig=n;
|
||||
while (n >= st->nfft ) {
|
||||
fastconv1buf(st,inbuf,outbuf);
|
||||
inbuf += st->ngood;
|
||||
outbuf += st->ngood;
|
||||
n -= st->ngood;
|
||||
}
|
||||
return norig - n;
|
||||
}
|
||||
|
||||
static
|
||||
size_t kff_flush(kiss_fastfir_cfg st,const kffsamp_t * inbuf,kffsamp_t * outbuf,size_t n)
|
||||
{
|
||||
size_t zpad=0,ntmp;
|
||||
|
||||
ntmp = kff_nocopy(st,inbuf,outbuf,n);
|
||||
n -= ntmp;
|
||||
inbuf += ntmp;
|
||||
outbuf += ntmp;
|
||||
|
||||
zpad = st->nfft - n;
|
||||
memset(st->tmpbuf,0,sizeof(kffsamp_t)*st->nfft );
|
||||
memcpy(st->tmpbuf,inbuf,sizeof(kffsamp_t)*n );
|
||||
|
||||
fastconv1buf(st,st->tmpbuf,st->tmpbuf);
|
||||
|
||||
memcpy(outbuf,st->tmpbuf,sizeof(kffsamp_t)*( st->ngood - zpad ));
|
||||
return ntmp + st->ngood - zpad;
|
||||
}
|
||||
|
||||
size_t kiss_fastfir(
|
||||
kiss_fastfir_cfg vst,
|
||||
kffsamp_t * inbuf,
|
||||
kffsamp_t * outbuf,
|
||||
size_t n_new,
|
||||
size_t *offset)
|
||||
{
|
||||
size_t ntot = n_new + *offset;
|
||||
if (n_new==0) {
|
||||
return kff_flush(vst,inbuf,outbuf,ntot);
|
||||
}else{
|
||||
size_t nwritten = kff_nocopy(vst,inbuf,outbuf,ntot);
|
||||
*offset = ntot - nwritten;
|
||||
/*save the unused or underused samples at the front of the input buffer */
|
||||
memcpy( inbuf , inbuf+nwritten , *offset * sizeof(kffsamp_t) );
|
||||
return nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FAST_FILT_UTIL
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
|
||||
static
|
||||
void direct_file_filter(
|
||||
FILE * fin,
|
||||
FILE * fout,
|
||||
const kffsamp_t * imp_resp,
|
||||
size_t n_imp_resp)
|
||||
{
|
||||
size_t nlag = n_imp_resp - 1;
|
||||
|
||||
const kffsamp_t *tmph;
|
||||
kffsamp_t *buf, *circbuf;
|
||||
kffsamp_t outval;
|
||||
size_t nread;
|
||||
size_t nbuf;
|
||||
size_t oldestlag = 0;
|
||||
size_t k, tap;
|
||||
#ifndef REAL_FASTFIR
|
||||
kffsamp_t tmp;
|
||||
#endif
|
||||
|
||||
nbuf = 4096;
|
||||
buf = (kffsamp_t *) malloc ( sizeof (kffsamp_t) * nbuf);
|
||||
circbuf = (kffsamp_t *) malloc (sizeof (kffsamp_t) * nlag);
|
||||
if (!circbuf || !buf) {
|
||||
perror("circbuf allocation");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( fread (circbuf, sizeof (kffsamp_t), nlag, fin) != nlag ) {
|
||||
perror ("insufficient data to overcome transient");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
do {
|
||||
nread = fread (buf, sizeof (kffsamp_t), nbuf, fin);
|
||||
if (nread <= 0)
|
||||
break;
|
||||
|
||||
for (k = 0; k < nread; ++k) {
|
||||
tmph = imp_resp+nlag;
|
||||
#ifdef REAL_FASTFIR
|
||||
# ifdef USE_SIMD
|
||||
outval = _mm_set1_ps(0);
|
||||
#else
|
||||
outval = 0;
|
||||
#endif
|
||||
for (tap = oldestlag; tap < nlag; ++tap)
|
||||
outval += circbuf[tap] * *tmph--;
|
||||
for (tap = 0; tap < oldestlag; ++tap)
|
||||
outval += circbuf[tap] * *tmph--;
|
||||
outval += buf[k] * *tmph;
|
||||
#else
|
||||
# ifdef USE_SIMD
|
||||
outval.r = outval.i = _mm_set1_ps(0);
|
||||
#else
|
||||
outval.r = outval.i = 0;
|
||||
#endif
|
||||
for (tap = oldestlag; tap < nlag; ++tap){
|
||||
C_MUL(tmp,circbuf[tap],*tmph);
|
||||
--tmph;
|
||||
C_ADDTO(outval,tmp);
|
||||
}
|
||||
|
||||
for (tap = 0; tap < oldestlag; ++tap) {
|
||||
C_MUL(tmp,circbuf[tap],*tmph);
|
||||
--tmph;
|
||||
C_ADDTO(outval,tmp);
|
||||
}
|
||||
C_MUL(tmp,buf[k],*tmph);
|
||||
C_ADDTO(outval,tmp);
|
||||
#endif
|
||||
|
||||
circbuf[oldestlag++] = buf[k];
|
||||
buf[k] = outval;
|
||||
|
||||
if (oldestlag == nlag)
|
||||
oldestlag = 0;
|
||||
}
|
||||
|
||||
if (fwrite (buf, sizeof (buf[0]), nread, fout) != nread) {
|
||||
perror ("short write");
|
||||
exit (1);
|
||||
}
|
||||
} while (nread);
|
||||
free (buf);
|
||||
free (circbuf);
|
||||
}
|
||||
|
||||
static
|
||||
void do_file_filter(
|
||||
FILE * fin,
|
||||
FILE * fout,
|
||||
const kffsamp_t * imp_resp,
|
||||
size_t n_imp_resp,
|
||||
size_t nfft )
|
||||
{
|
||||
int fdout;
|
||||
size_t n_samps_buf;
|
||||
|
||||
kiss_fastfir_cfg cfg;
|
||||
kffsamp_t *inbuf,*outbuf;
|
||||
int nread,nwrite;
|
||||
size_t idx_inbuf;
|
||||
|
||||
fdout = fileno(fout);
|
||||
|
||||
cfg=kiss_fastfir_alloc(imp_resp,n_imp_resp,&nfft,0,0);
|
||||
|
||||
/* use length to minimize buffer shift*/
|
||||
n_samps_buf = 8*4096/sizeof(kffsamp_t);
|
||||
n_samps_buf = nfft + 4*(nfft-n_imp_resp+1);
|
||||
|
||||
if (verbose) fprintf(stderr,"bufsize=%d\n",(int)(sizeof(kffsamp_t)*n_samps_buf) );
|
||||
|
||||
|
||||
/*allocate space and initialize pointers */
|
||||
inbuf = (kffsamp_t*)malloc(sizeof(kffsamp_t)*n_samps_buf);
|
||||
outbuf = (kffsamp_t*)malloc(sizeof(kffsamp_t)*n_samps_buf);
|
||||
|
||||
idx_inbuf=0;
|
||||
do{
|
||||
/* start reading at inbuf[idx_inbuf] */
|
||||
nread = fread( inbuf + idx_inbuf, sizeof(kffsamp_t), n_samps_buf - idx_inbuf,fin );
|
||||
|
||||
/* If nread==0, then this is a flush.
|
||||
The total number of samples in input is idx_inbuf + nread . */
|
||||
nwrite = kiss_fastfir(cfg, inbuf, outbuf,nread,&idx_inbuf) * sizeof(kffsamp_t);
|
||||
/* kiss_fastfir moved any unused samples to the front of inbuf and updated idx_inbuf */
|
||||
|
||||
if ( write(fdout, outbuf, nwrite) != nwrite ) {
|
||||
perror("short write");
|
||||
exit(1);
|
||||
}
|
||||
}while ( nread );
|
||||
free(cfg);
|
||||
free(inbuf);
|
||||
free(outbuf);
|
||||
}
|
||||
|
||||
int main(int argc,char**argv)
|
||||
{
|
||||
kffsamp_t * h;
|
||||
int use_direct=0;
|
||||
size_t nh,nfft=0;
|
||||
FILE *fin=stdin;
|
||||
FILE *fout=stdout;
|
||||
FILE *filtfile=NULL;
|
||||
while (1) {
|
||||
int c=getopt(argc,argv,"n:h:i:o:vd");
|
||||
if (c==-1) break;
|
||||
switch (c) {
|
||||
case 'v':
|
||||
verbose=1;
|
||||
break;
|
||||
case 'n':
|
||||
nfft=atoi(optarg);
|
||||
break;
|
||||
case 'i':
|
||||
fin = fopen(optarg,"rb");
|
||||
if (fin==NULL) {
|
||||
perror(optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
fout = fopen(optarg,"w+b");
|
||||
if (fout==NULL) {
|
||||
perror(optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
filtfile = fopen(optarg,"rb");
|
||||
if (filtfile==NULL) {
|
||||
perror(optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
use_direct=1;
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr,"usage options:\n"
|
||||
"\t-n nfft: fft size to use\n"
|
||||
"\t-d : use direct FIR filtering, not fast convolution\n"
|
||||
"\t-i filename: input file\n"
|
||||
"\t-o filename: output(filtered) file\n"
|
||||
"\t-n nfft: fft size to use\n"
|
||||
"\t-h filename: impulse response\n");
|
||||
exit (1);
|
||||
default:fprintf(stderr,"bad %c\n",c);break;
|
||||
}
|
||||
}
|
||||
if (filtfile==NULL) {
|
||||
fprintf(stderr,"You must supply the FIR coeffs via -h\n");
|
||||
exit(1);
|
||||
}
|
||||
fseek(filtfile,0,SEEK_END);
|
||||
nh = ftell(filtfile) / sizeof(kffsamp_t);
|
||||
if (verbose) fprintf(stderr,"%d samples in FIR filter\n",(int)nh);
|
||||
h = (kffsamp_t*)malloc(sizeof(kffsamp_t)*nh);
|
||||
fseek(filtfile,0,SEEK_SET);
|
||||
if (fread(h,sizeof(kffsamp_t),nh,filtfile) != nh)
|
||||
fprintf(stderr,"short read on filter file\n");
|
||||
|
||||
fclose(filtfile);
|
||||
|
||||
if (use_direct)
|
||||
direct_file_filter( fin, fout, h,nh);
|
||||
else
|
||||
do_file_filter( fin, fout, h,nh,nfft);
|
||||
|
||||
if (fout!=stdout) fclose(fout);
|
||||
if (fin!=stdin) fclose(fin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
232
3rd-party/kissfft/tools/psdpng.c
vendored
232
3rd-party/kissfft/tools/psdpng.c
vendored
@ -1,232 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2004, Mark Borgerding. All rights reserved.
|
||||
* This file is part of KISS FFT - https://github.com/mborgerding/kissfft
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
* See COPYING file for more information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <png.h>
|
||||
|
||||
#include "kiss_fft.h"
|
||||
#include "kiss_fftr.h"
|
||||
|
||||
int nfft=1024;
|
||||
FILE * fin=NULL;
|
||||
FILE * fout=NULL;
|
||||
|
||||
int navg=20;
|
||||
int remove_dc=0;
|
||||
int nrows=0;
|
||||
float * vals=NULL;
|
||||
int stereo=0;
|
||||
|
||||
static
|
||||
void config(int argc,char** argv)
|
||||
{
|
||||
while (1) {
|
||||
int c = getopt (argc, argv, "n:r:as");
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case 'n': nfft=(int)atoi(optarg);break;
|
||||
case 'r': navg=(int)atoi(optarg);break;
|
||||
case 'a': remove_dc=1;break;
|
||||
case 's': stereo=1;break;
|
||||
case '?':
|
||||
fprintf (stderr, "usage options:\n"
|
||||
"\t-n d: fft dimension(s) [1024]\n"
|
||||
"\t-r d: number of rows to average [20]\n"
|
||||
"\t-a : remove average from each fft buffer\n"
|
||||
"\t-s : input is stereo, channels will be combined before fft\n"
|
||||
"16 bit machine format real input is assumed\n"
|
||||
);
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "bad %c\n", c);
|
||||
exit (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( optind < argc ) {
|
||||
if (strcmp("-",argv[optind]) !=0)
|
||||
fin = fopen(argv[optind],"rb");
|
||||
++optind;
|
||||
}
|
||||
|
||||
if ( optind < argc ) {
|
||||
if ( strcmp("-",argv[optind]) !=0 )
|
||||
fout = fopen(argv[optind],"wb");
|
||||
++optind;
|
||||
}
|
||||
if (fin==NULL)
|
||||
fin=stdin;
|
||||
if (fout==NULL)
|
||||
fout=stdout;
|
||||
}
|
||||
|
||||
#define CHECKNULL(p) if ( (p)==NULL ) do { fprintf(stderr,"CHECKNULL failed @ %s(%d): %s\n",__FILE__,__LINE__,#p );exit(1);} while(0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
png_byte r;
|
||||
png_byte g;
|
||||
png_byte b;
|
||||
} rgb_t;
|
||||
|
||||
static
|
||||
void val2rgb(float x,rgb_t *p)
|
||||
{
|
||||
const double pi = 3.14159265358979;
|
||||
p->g = (int)(255*sin(x*pi));
|
||||
p->r = (int)(255*abs(sin(x*pi*3/2)));
|
||||
p->b = (int)(255*abs(sin(x*pi*5/2)));
|
||||
//fprintf(stderr,"%.2f : %d,%d,%d\n",x,(int)p->r,(int)p->g,(int)p->b);
|
||||
}
|
||||
|
||||
static
|
||||
void cpx2pixels(rgb_t * res,const float * fbuf,size_t n)
|
||||
{
|
||||
size_t i;
|
||||
float minval,maxval,valrange;
|
||||
minval=maxval=fbuf[0];
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (fbuf[i] > maxval) maxval = fbuf[i];
|
||||
if (fbuf[i] < minval) minval = fbuf[i];
|
||||
}
|
||||
|
||||
fprintf(stderr,"min ==%f,max=%f\n",minval,maxval);
|
||||
valrange = maxval-minval;
|
||||
if (valrange == 0) {
|
||||
fprintf(stderr,"min == max == %f\n",minval);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
val2rgb( (fbuf[i] - minval)/valrange , res+i );
|
||||
}
|
||||
|
||||
static
|
||||
void transform_signal(void)
|
||||
{
|
||||
short *inbuf;
|
||||
kiss_fftr_cfg cfg=NULL;
|
||||
kiss_fft_scalar *tbuf;
|
||||
kiss_fft_cpx *fbuf;
|
||||
float *mag2buf;
|
||||
int i;
|
||||
int n;
|
||||
int avgctr=0;
|
||||
|
||||
int nfreqs=nfft/2+1;
|
||||
|
||||
CHECKNULL( cfg=kiss_fftr_alloc(nfft,0,0,0) );
|
||||
CHECKNULL( inbuf=(short*)malloc(sizeof(short)*2*nfft ) );
|
||||
CHECKNULL( tbuf=(kiss_fft_scalar*)malloc(sizeof(kiss_fft_scalar)*nfft ) );
|
||||
CHECKNULL( fbuf=(kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx)*nfreqs ) );
|
||||
CHECKNULL( mag2buf=(float*)calloc(nfreqs,sizeof(float) ) );
|
||||
|
||||
while (1) {
|
||||
if (stereo) {
|
||||
n = fread(inbuf,sizeof(short)*2,nfft,fin);
|
||||
if (n != nfft )
|
||||
break;
|
||||
for (i=0;i<nfft;++i)
|
||||
tbuf[i] = inbuf[2*i] + inbuf[2*i+1];
|
||||
}else{
|
||||
n = fread(inbuf,sizeof(short),nfft,fin);
|
||||
if (n != nfft )
|
||||
break;
|
||||
for (i=0;i<nfft;++i)
|
||||
tbuf[i] = inbuf[i];
|
||||
}
|
||||
|
||||
if (remove_dc) {
|
||||
float avg = 0;
|
||||
for (i=0;i<nfft;++i) avg += tbuf[i];
|
||||
avg /= nfft;
|
||||
for (i=0;i<nfft;++i) tbuf[i] -= (kiss_fft_scalar)avg;
|
||||
}
|
||||
|
||||
/* do FFT */
|
||||
kiss_fftr(cfg,tbuf,fbuf);
|
||||
|
||||
for (i=0;i<nfreqs;++i)
|
||||
mag2buf[i] += fbuf[i].r * fbuf[i].r + fbuf[i].i * fbuf[i].i;
|
||||
|
||||
if (++avgctr == navg) {
|
||||
avgctr=0;
|
||||
++nrows;
|
||||
CHECKNULL( vals = (float*)realloc(vals,sizeof(float)*nrows*nfreqs) );
|
||||
float eps = 1;
|
||||
for (i=0;i<nfreqs;++i)
|
||||
vals[(nrows - 1) * nfreqs + i] = 10 * log10 ( mag2buf[i] / navg + eps );
|
||||
memset(mag2buf,0,sizeof(mag2buf[0])*nfreqs);
|
||||
}
|
||||
}
|
||||
|
||||
free(cfg);
|
||||
free(inbuf);
|
||||
free(tbuf);
|
||||
free(fbuf);
|
||||
free(mag2buf);
|
||||
}
|
||||
|
||||
static
|
||||
void make_png(void)
|
||||
{
|
||||
png_bytepp row_pointers=NULL;
|
||||
rgb_t * row_data=NULL;
|
||||
int i;
|
||||
int nfreqs = nfft/2+1;
|
||||
|
||||
png_structp png_ptr=NULL;
|
||||
png_infop info_ptr=NULL;
|
||||
|
||||
CHECKNULL( png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,0,0,0) );
|
||||
CHECKNULL( info_ptr = png_create_info_struct(png_ptr) );
|
||||
|
||||
|
||||
png_init_io(png_ptr, fout );
|
||||
png_set_IHDR(png_ptr, info_ptr ,nfreqs,nrows,8,PNG_COLOR_TYPE_RGB,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT );
|
||||
|
||||
|
||||
CHECKNULL( row_data = (rgb_t*)malloc(sizeof(rgb_t) * nrows * nfreqs) );
|
||||
cpx2pixels(row_data, vals, nfreqs*nrows );
|
||||
|
||||
CHECKNULL( row_pointers = malloc(nrows*sizeof(png_bytep)) );
|
||||
for (i=0;i<nrows;++i) {
|
||||
row_pointers[i] = (png_bytep)(row_data + i*nfreqs);
|
||||
}
|
||||
png_set_rows(png_ptr, info_ptr, row_pointers);
|
||||
|
||||
|
||||
fprintf(stderr,"creating %dx%d png\n",nfreqs,nrows);
|
||||
fprintf(stderr,"bitdepth %d \n",png_get_bit_depth(png_ptr,info_ptr ) );
|
||||
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY , NULL);
|
||||
|
||||
free(row_pointers);
|
||||
free(row_data);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
config(argc,argv);
|
||||
|
||||
transform_signal();
|
||||
|
||||
make_png();
|
||||
|
||||
if (fout!=stdout) fclose(fout);
|
||||
if (fin!=stdin) fclose(fin);
|
||||
free(vals);
|
||||
return 0;
|
||||
}
|
61
3rd-party/lc3-google/Android.bp
vendored
Normal file
61
3rd-party/lc3-google/Android.bp
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "system_bt_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["system_bt_license"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "liblc3",
|
||||
host_supported: true,
|
||||
apex_available: [
|
||||
|
||||
"//apex_available:platform",
|
||||
"com.android.bluetooth"
|
||||
],
|
||||
defaults: ["fluoride_defaults"],
|
||||
srcs: [
|
||||
"src/*.c",
|
||||
],
|
||||
cflags: [
|
||||
"-O3",
|
||||
"-ffast-math",
|
||||
"-Werror",
|
||||
"-Wmissing-braces",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-#warnings",
|
||||
"-Wuninitialized",
|
||||
"-Wno-self-assign",
|
||||
"-Wno-implicit-fallthrough",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
sanitize: {
|
||||
misc_undefined:[
|
||||
"unsigned-integer-overflow",
|
||||
"signed-integer-overflow",
|
||||
"bounds",
|
||||
],
|
||||
cfi: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
export_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
}
|
||||
|
||||
cc_fuzz {
|
||||
name: "liblc3_fuzzer",
|
||||
|
||||
srcs: [
|
||||
"fuzzer/liblc3_fuzzer.cpp",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"liblc3",
|
||||
],
|
||||
}
|
||||
|
93
3rd-party/lc3-google/fuzzer/liblc3_fuzzer.cpp
vendored
Normal file
93
3rd-party/lc3-google/fuzzer/liblc3_fuzzer.cpp
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* 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 <fuzzer/FuzzedDataProvider.h>
|
||||
|
||||
#include "include/lc3.h"
|
||||
|
||||
void TestEncoder(FuzzedDataProvider& fdp) {
|
||||
enum lc3_pcm_format pcm_format =
|
||||
fdp.PickValueInArray({LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24});
|
||||
int dt_us = fdp.PickValueInArray({10000, 7500});
|
||||
int sr_hz =
|
||||
fdp.PickValueInArray({8000, 16000, 24000, 32000, /*44100,*/ 48000});
|
||||
unsigned enc_size = lc3_encoder_size(dt_us, sr_hz);
|
||||
uint16_t output_byte_count = fdp.ConsumeIntegralInRange(20, 400);
|
||||
uint16_t num_frames = lc3_frame_samples(dt_us, sr_hz);
|
||||
uint8_t bytes_per_frame = (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 4);
|
||||
|
||||
if (fdp.remaining_bytes() < num_frames * bytes_per_frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> input_frames(
|
||||
num_frames / (pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 1));
|
||||
fdp.ConsumeData(input_frames.data(), num_frames * bytes_per_frame);
|
||||
|
||||
void* lc3_encoder_mem = nullptr;
|
||||
lc3_encoder_mem = malloc(enc_size);
|
||||
lc3_encoder_t lc3_encoder =
|
||||
lc3_setup_encoder(dt_us, sr_hz, 0, lc3_encoder_mem);
|
||||
|
||||
std::vector<uint8_t> output(output_byte_count);
|
||||
lc3_encode(lc3_encoder, pcm_format, (const int16_t*)input_frames.data(), 1,
|
||||
output.size(), output.data());
|
||||
|
||||
free(lc3_encoder_mem);
|
||||
lc3_encoder_mem = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
void TestDecoder(FuzzedDataProvider& fdp) {
|
||||
enum lc3_pcm_format pcm_format =
|
||||
fdp.PickValueInArray({LC3_PCM_FORMAT_S16, LC3_PCM_FORMAT_S24});
|
||||
int dt_us = fdp.PickValueInArray({10000, 7500});
|
||||
int sr_hz =
|
||||
fdp.PickValueInArray({8000, 16000, 24000, 32000, /*44100,*/ 48000});
|
||||
unsigned dec_size = lc3_decoder_size(dt_us, sr_hz);
|
||||
uint16_t input_byte_count = fdp.ConsumeIntegralInRange(20, 400);
|
||||
uint16_t num_frames = lc3_frame_samples(dt_us, sr_hz);
|
||||
|
||||
if (fdp.remaining_bytes() < input_byte_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> input(input_byte_count);
|
||||
fdp.ConsumeData(input.data(), input.size());
|
||||
|
||||
void* lc3_decoder_mem = nullptr;
|
||||
lc3_decoder_mem = malloc(dec_size);
|
||||
lc3_decoder_t lc3_decoder =
|
||||
lc3_setup_decoder(dt_us, sr_hz, 0, lc3_decoder_mem);
|
||||
|
||||
std::vector<uint32_t> output(num_frames /
|
||||
(pcm_format == LC3_PCM_FORMAT_S16 ? 2 : 1));
|
||||
lc3_decode(lc3_decoder, input.data(), input.size(), pcm_format,
|
||||
(int16_t*)output.data(), 1);
|
||||
|
||||
/* Empty input performs PLC (packet loss concealment) */
|
||||
lc3_decode(lc3_decoder, nullptr, 0, pcm_format, (int16_t*)output.data(), 1);
|
||||
|
||||
free(lc3_decoder_mem);
|
||||
lc3_decoder_mem = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
FuzzedDataProvider fdp(data, size);
|
||||
TestEncoder(fdp);
|
||||
TestDecoder(fdp);
|
||||
return 0;
|
||||
}
|
300
3rd-party/lc3-google/include/lc3.h
vendored
Normal file
300
3rd-party/lc3-google/include/lc3.h
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Low Complexity Communication Codec (LC3)
|
||||
*
|
||||
* This implementation conforms to :
|
||||
* Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*
|
||||
*
|
||||
* The LC3 is an efficient low latency audio codec.
|
||||
*
|
||||
* - Unlike most other codecs, the LC3 codec is focused on audio streaming
|
||||
* in constrained (on packet sizes and interval) tranport layer.
|
||||
* In this way, the LC3 does not handle :
|
||||
* VBR (Variable Bitrate), based on input signal complexity
|
||||
* ABR (Adaptative Bitrate). It does not rely on any bit reservoir,
|
||||
* a frame will be strictly encoded in the bytes budget given by
|
||||
* the user (or transport layer).
|
||||
*
|
||||
* However, the bitrate (bytes budget for encoding a frame) can be
|
||||
* freely changed at any time. But will not rely on signal complexity,
|
||||
* it can follow a temporary bandwidth increase or reduction.
|
||||
*
|
||||
* - Unlike classic codecs, the LC3 codecs does not run on fixed amount
|
||||
* of samples as input. It operate only on fixed frame duration, for
|
||||
* any supported samplerates (8 to 48 KHz). Two frame duration are
|
||||
* available 7.5ms and 10ms.
|
||||
*
|
||||
*
|
||||
* --- About 44.1 KHz samplerate ---
|
||||
*
|
||||
* The Bluetooth specification oddly add the 44.1 KHz samplerate. Although
|
||||
* there is NO SUPPORT in the core algorithm of the codec of 44.1 KHz.
|
||||
* We can summarize the 44.1 KHz support by "you can put any samplerate
|
||||
* around the base defined samplerates". But be concerned by :
|
||||
*
|
||||
* 1. The frame size will not be 7.5 ms or 10 ms, but is scaled
|
||||
* by 'supported samplerate' / 'input samplerate'
|
||||
*
|
||||
* 2. The bandwidth will be hard limited (to 20 KHz) if you select 48 KHz.
|
||||
* The encoded bandwidth will also be affected by the above inverse
|
||||
* factor of 20 KHz.
|
||||
*
|
||||
* Applied to 44.1 KHz, we get :
|
||||
*
|
||||
* 1. About 8.16 ms frame duration, instead of 7.5 ms
|
||||
* About 10.88 ms frame duration, instead of 10 ms
|
||||
*
|
||||
* 2. The bandwidth becomes limited to 18.375 KHz
|
||||
*
|
||||
*
|
||||
* --- How to encode / decode ---
|
||||
*
|
||||
* An encoder / decoder context need to be setup. This context keep states
|
||||
* on the current stream to proceed, and samples that overlapped across
|
||||
* frames.
|
||||
*
|
||||
* You have two ways to setup the encoder / decoder :
|
||||
*
|
||||
* - Using static memory allocation (this module does not rely on
|
||||
* any dynamic memory allocation). The types `lc3_xxcoder_mem_16k_t`,
|
||||
* and `lc3_xxcoder_mem_48k_t` have size of the memory needed for
|
||||
* encoding up to 16 KHz or 48 KHz.
|
||||
*
|
||||
* - Using dynamic memory allocation. The `lc3_xxcoder_size()` procedure
|
||||
* returns the needed memory size, for a given configuration. The memory
|
||||
* space must be aligned to a pointer size. As an example, you can setup
|
||||
* encoder like this :
|
||||
*
|
||||
* | enc = lc3_setup_encoder(frame_us, samplerate,
|
||||
* | malloc(lc3_encoder_size(frame_us, samplerate)));
|
||||
* | ...
|
||||
* | free(enc);
|
||||
*
|
||||
* Note :
|
||||
* - A NULL memory adress as input, will return a NULL encoder context.
|
||||
* - The returned encoder handle is set at the address of the allocated
|
||||
* memory space, you can directly free the handle.
|
||||
*
|
||||
* Next, call the `lc3_encode()` encoding procedure, for each frames.
|
||||
* To handle multichannel streams (Stereo or more), you can proceed with
|
||||
* inerleaved channels PCM stream like this :
|
||||
*
|
||||
* | for(int ich = 0; ich < nch: ich++)
|
||||
* | lc3_encode(encoder[ich], pcm + ich, nch, ...);
|
||||
*
|
||||
* with `nch` as the number of channels in the PCM stream
|
||||
*/
|
||||
|
||||
#ifndef __LC3_H
|
||||
#define __LC3_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lc3_private.h"
|
||||
|
||||
|
||||
/**
|
||||
* Limitations
|
||||
* - On the bitrate, in bps, of a stream
|
||||
* - On the size of the frames in bytes
|
||||
*/
|
||||
|
||||
#define LC3_MIN_BITRATE 16000
|
||||
#define LC3_MAX_BITRATE 320000
|
||||
|
||||
#define LC3_MIN_FRAME_BYTES 20
|
||||
#define LC3_MAX_FRAME_BYTES 400
|
||||
|
||||
|
||||
/**
|
||||
* Parameters check
|
||||
* LC3_CHECK_DT_US(us) True when frame duration in us is suitable
|
||||
* LC3_CHECK_SR_HZ(sr) True when samplerate in Hz is suitable
|
||||
*/
|
||||
|
||||
#define LC3_CHECK_DT_US(us) \
|
||||
( ((us) == 7500) || ((us) == 10000) )
|
||||
|
||||
#define LC3_CHECK_SR_HZ(sr) \
|
||||
( ((sr) == 8000) || ((sr) == 16000) || ((sr) == 24000) || \
|
||||
((sr) == 32000) || ((sr) == 48000) )
|
||||
|
||||
|
||||
/**
|
||||
* PCM Sample Format
|
||||
* S16 Signed 16 bits, in 16 bits words (int16_t)
|
||||
* S24 Signed 24 bits, using low three bytes of 32 bits words (int32_t).
|
||||
* The high byte sign extends the sample value (bits 31..24 set to b23).
|
||||
*/
|
||||
|
||||
enum lc3_pcm_format {
|
||||
LC3_PCM_FORMAT_S16,
|
||||
LC3_PCM_FORMAT_S24,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handle
|
||||
*/
|
||||
|
||||
typedef struct lc3_encoder *lc3_encoder_t;
|
||||
typedef struct lc3_decoder *lc3_decoder_t;
|
||||
|
||||
|
||||
/**
|
||||
* Static memory of encoder context
|
||||
*
|
||||
* Propose types suitable for static memory allocation, supporting
|
||||
* any frame duration, and maximum samplerates 16k and 48k respectively
|
||||
* You can customize your type using the `LC3_ENCODER_MEM_T` or
|
||||
* `LC3_DECODER_MEM_T` macro.
|
||||
*/
|
||||
|
||||
typedef LC3_ENCODER_MEM_T(10000, 16000) lc3_encoder_mem_16k_t;
|
||||
typedef LC3_ENCODER_MEM_T(10000, 48000) lc3_encoder_mem_48k_t;
|
||||
|
||||
typedef LC3_DECODER_MEM_T(10000, 16000) lc3_decoder_mem_16k_t;
|
||||
typedef LC3_DECODER_MEM_T(10000, 48000) lc3_decoder_mem_48k_t;
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of PCM samples in a frame
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
|
||||
* return Number of PCM samples, -1 on bad parameters
|
||||
*/
|
||||
int lc3_frame_samples(int dt_us, int sr_hz);
|
||||
|
||||
/**
|
||||
* Return the size of frames, from bitrate
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* bitrate Target bitrate in bit per seconds
|
||||
* return The floor size in bytes of the frames, -1 on bad parameters
|
||||
*/
|
||||
int lc3_frame_bytes(int dt_us, int bitrate);
|
||||
|
||||
/**
|
||||
* Resolve the bitrate, from the size of frames
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* nbytes Size in bytes of the frames
|
||||
* return The according bitrate in bps, -1 on bad parameters
|
||||
*/
|
||||
int lc3_resolve_bitrate(int dt_us, int nbytes);
|
||||
|
||||
/**
|
||||
* Return algorithmic delay, as a number of samples
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
|
||||
* return Number of algorithmic delay samples, -1 on bad parameters
|
||||
*/
|
||||
int lc3_delay_samples(int dt_us, int sr_hz);
|
||||
|
||||
/**
|
||||
* Return size needed for an encoder
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
|
||||
* return Size of then encoder in bytes, 0 on bad parameters
|
||||
*
|
||||
* The `sr_hz` parameter is the samplerate of the PCM input stream,
|
||||
* and will match `sr_pcm_hz` of `lc3_setup_encoder()`.
|
||||
*/
|
||||
unsigned lc3_encoder_size(int dt_us, int sr_hz);
|
||||
|
||||
/**
|
||||
* Setup encoder
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
|
||||
* sr_pcm_hz Input samplerate, downsampling option of input, or 0
|
||||
* mem Encoder memory space, aligned to pointer type
|
||||
* return Encoder as an handle, NULL on bad parameters
|
||||
*
|
||||
* The `sr_pcm_hz` parameter is a downsampling option of PCM input,
|
||||
* the value `0` fallback to the samplerate of the encoded stream `sr_hz`.
|
||||
* When used, `sr_pcm_hz` is intended to be higher or equal to the encoder
|
||||
* samplerate `sr_hz`. The size of the context needed, given by
|
||||
* `lc3_encoder_size()` will be set accordingly to `sr_pcm_hz`.
|
||||
*/
|
||||
lc3_encoder_t lc3_setup_encoder(
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem);
|
||||
|
||||
/**
|
||||
* Encode a frame
|
||||
* encoder Handle of the encoder
|
||||
* fmt PCM input format
|
||||
* pcm, stride Input PCM samples, and count between two consecutives
|
||||
* nbytes Target size, in bytes, of the frame (20 to 400)
|
||||
* out Output buffer of `nbytes` size
|
||||
* return 0: On success -1: Wrong parameters
|
||||
*/
|
||||
int lc3_encode(lc3_encoder_t encoder, enum lc3_pcm_format fmt,
|
||||
const void *pcm, int stride, int nbytes, void *out);
|
||||
|
||||
/**
|
||||
* Return size needed for an decoder
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
|
||||
* return Size of then decoder in bytes, 0 on bad parameters
|
||||
*
|
||||
* The `sr_hz` parameter is the samplerate of the PCM output stream,
|
||||
* and will match `sr_pcm_hz` of `lc3_setup_decoder()`.
|
||||
*/
|
||||
unsigned lc3_decoder_size(int dt_us, int sr_hz);
|
||||
|
||||
/**
|
||||
* Setup decoder
|
||||
* dt_us Frame duration in us, 7500 or 10000
|
||||
* sr_hz Samplerate in Hz, 8000, 16000, 24000, 32000 or 48000
|
||||
* sr_pcm_hz Output samplerate, upsampling option of output (or 0)
|
||||
* mem Decoder memory space, aligned to pointer type
|
||||
* return Decoder as an handle, NULL on bad parameters
|
||||
*
|
||||
* The `sr_pcm_hz` parameter is an upsampling option of PCM output,
|
||||
* the value `0` fallback to the samplerate of the decoded stream `sr_hz`.
|
||||
* When used, `sr_pcm_hz` is intended to be higher or equal to the decoder
|
||||
* samplerate `sr_hz`. The size of the context needed, given by
|
||||
* `lc3_decoder_size()` will be set accordingly to `sr_pcm_hz`.
|
||||
*/
|
||||
lc3_decoder_t lc3_setup_decoder(
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem);
|
||||
|
||||
/**
|
||||
* Decode a frame
|
||||
* decoder Handle of the decoder
|
||||
* in, nbytes Input bitstream, and size in bytes, NULL performs PLC
|
||||
* fmt PCM output format
|
||||
* pcm, stride Output PCM samples, and count between two consecutives
|
||||
* return 0: On success 1: PLC operated -1: Wrong parameters
|
||||
*/
|
||||
int lc3_decode(lc3_decoder_t decoder, const void *in, int nbytes,
|
||||
enum lc3_pcm_format fmt, void *pcm, int stride);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LC3_H */
|
158
3rd-party/lc3-google/include/lc3_private.h
vendored
Normal file
158
3rd-party/lc3-google/include/lc3_private.h
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2015 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __LC3_PRIVATE_H
|
||||
#define __LC3_PRIVATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/**
|
||||
* Return number of samples, delayed samples and
|
||||
* encoded spectrum coefficients within a frame
|
||||
* For decoding, add number of samples of 18 ms history
|
||||
*/
|
||||
|
||||
#define __LC3_NS(dt_us, sr_hz) \
|
||||
((dt_us * sr_hz) / 1000 / 1000)
|
||||
|
||||
#define __LC3_ND(dt_us, sr_hz) \
|
||||
( (dt_us) == 7500 ? 23 * __LC3_NS(dt_us, sr_hz) / 30 \
|
||||
: 5 * __LC3_NS(dt_us, sr_hz) / 8 )
|
||||
|
||||
#define __LC3_NH(sr_hz) \
|
||||
( (18 * sr_hz) / 1000 )
|
||||
|
||||
|
||||
/**
|
||||
* Frame duration 7.5ms or 10ms
|
||||
*/
|
||||
|
||||
enum lc3_dt {
|
||||
LC3_DT_7M5,
|
||||
LC3_DT_10M,
|
||||
|
||||
LC3_NUM_DT
|
||||
};
|
||||
|
||||
/**
|
||||
* Sampling frequency
|
||||
*/
|
||||
|
||||
enum lc3_srate {
|
||||
LC3_SRATE_8K,
|
||||
LC3_SRATE_16K,
|
||||
LC3_SRATE_24K,
|
||||
LC3_SRATE_32K,
|
||||
LC3_SRATE_48K,
|
||||
|
||||
LC3_NUM_SRATE,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Encoder state and memory
|
||||
*/
|
||||
|
||||
typedef struct lc3_attdet_analysis {
|
||||
float en1, an1;
|
||||
int p_att;
|
||||
} lc3_attdet_analysis_t;
|
||||
|
||||
struct lc3_ltpf_hp50_state {
|
||||
float s1, s2;
|
||||
};
|
||||
|
||||
typedef struct lc3_ltpf_analysis {
|
||||
bool active;
|
||||
int pitch;
|
||||
float nc[2];
|
||||
|
||||
struct lc3_ltpf_hp50_state hp50;
|
||||
float x_12k8[384];
|
||||
float x_6k4[178];
|
||||
int tc;
|
||||
} lc3_ltpf_analysis_t;
|
||||
|
||||
typedef struct lc3_spec_analysis {
|
||||
float nbits_off;
|
||||
int nbits_spare;
|
||||
} lc3_spec_analysis_t;
|
||||
|
||||
struct lc3_encoder {
|
||||
enum lc3_dt dt;
|
||||
enum lc3_srate sr, sr_pcm;
|
||||
|
||||
lc3_attdet_analysis_t attdet;
|
||||
lc3_ltpf_analysis_t ltpf;
|
||||
lc3_spec_analysis_t spec;
|
||||
|
||||
// BK: s[0] -> s[1] to avoid compiler warning for zero sized warning
|
||||
float *xs, *xf, s[1];
|
||||
};
|
||||
|
||||
#define LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) \
|
||||
( 2*__LC3_NS(dt_us, sr_hz) + __LC3_ND(dt_us, sr_hz) )
|
||||
|
||||
#define LC3_ENCODER_MEM_T(dt_us, sr_hz) \
|
||||
struct { \
|
||||
struct lc3_encoder __e; \
|
||||
float __s[LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz)]; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decoder state and memory
|
||||
*/
|
||||
|
||||
typedef struct lc3_ltpf_synthesis {
|
||||
bool active;
|
||||
int pitch;
|
||||
float c[12][2], x[12];
|
||||
} lc3_ltpf_synthesis_t;
|
||||
|
||||
typedef struct lc3_plc_state {
|
||||
uint16_t seed;
|
||||
int count;
|
||||
float alpha;
|
||||
} lc3_plc_state_t;
|
||||
|
||||
struct lc3_decoder {
|
||||
enum lc3_dt dt;
|
||||
enum lc3_srate sr, sr_pcm;
|
||||
|
||||
lc3_ltpf_synthesis_t ltpf;
|
||||
lc3_plc_state_t plc;
|
||||
|
||||
// BK: s[0] -> s[1] to avoid compiler warning for zero sized warning
|
||||
float *xs, *xd, *xg, s[1];
|
||||
};
|
||||
|
||||
#define LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) \
|
||||
( __LC3_NH(sr_hz) + __LC3_NS(dt_us, sr_hz) + \
|
||||
__LC3_ND(dt_us, sr_hz) + __LC3_NS(dt_us, sr_hz) )
|
||||
|
||||
#define LC3_DECODER_MEM_T(dt_us, sr_hz) \
|
||||
struct { \
|
||||
struct lc3_decoder __d; \
|
||||
float __s[LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz)]; \
|
||||
}
|
||||
|
||||
|
||||
#endif /* __LC3_PRIVATE_H */
|
92
3rd-party/lc3-google/src/attdet.c
vendored
Normal file
92
3rd-party/lc3-google/src/attdet.c
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "attdet.h"
|
||||
|
||||
|
||||
/**
|
||||
* Time domain attack detector
|
||||
*/
|
||||
bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, struct lc3_attdet_analysis *attdet, const float *x)
|
||||
{
|
||||
/* --- Check enabling --- */
|
||||
|
||||
const int nbytes_ranges[LC3_NUM_DT][LC3_NUM_SRATE - LC3_SRATE_32K][2] = {
|
||||
[LC3_DT_7M5] = { { 61, 149 }, { 75, 149 } },
|
||||
[LC3_DT_10M] = { { 81, INT_MAX }, { 100, INT_MAX } },
|
||||
};
|
||||
|
||||
if (sr < LC3_SRATE_32K ||
|
||||
nbytes < nbytes_ranges[dt][sr - LC3_SRATE_32K][0] ||
|
||||
nbytes > nbytes_ranges[dt][sr - LC3_SRATE_32K][1] )
|
||||
return 0;
|
||||
|
||||
/* --- Filtering & Energy calculation --- */
|
||||
|
||||
int nblk = 4 - (dt == LC3_DT_7M5);
|
||||
float e[4];
|
||||
|
||||
for (int i = 0; i < nblk; i++) {
|
||||
e[i] = 0;
|
||||
|
||||
if (sr == LC3_SRATE_32K) {
|
||||
float xn2 = x[-4] + x[-3];
|
||||
float xn1 = x[-2] + x[-1];
|
||||
float xn, xf;
|
||||
|
||||
for (int j = 0; j < 40; j++, x += 2, xn2 = xn1, xn1 = xn) {
|
||||
xn = x[0] + x[1];
|
||||
xf = 0.375 * xn - 0.5 * xn1 + 0.125 * xn2;
|
||||
e[i] += xf * xf;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
float xn2 = x[-6] + x[-5] + x[-4];
|
||||
float xn1 = x[-3] + x[-2] + x[-1];
|
||||
float xn, xf;
|
||||
|
||||
for (int j = 0; j < 40; j++, x += 3, xn2 = xn1, xn1 = xn) {
|
||||
xn = x[0] + x[1] + x[2];
|
||||
xf = 0.375 * xn - 0.5 * xn1 + 0.125 * xn2;
|
||||
e[i] += xf * xf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Attack detection ---
|
||||
* The attack block `p_att` is defined as the normative value + 1,
|
||||
* in such way, it will be initialized to 0 */
|
||||
|
||||
int p_att = 0;
|
||||
float a[4];
|
||||
|
||||
for (int i = 0; i < nblk; i++) {
|
||||
a[i] = fmaxf(0.25 * attdet->an1, attdet->en1);
|
||||
attdet->en1 = e[i], attdet->an1 = a[i];
|
||||
|
||||
if (e[i] > 8.5 * a[i])
|
||||
p_att = i + 1;
|
||||
}
|
||||
|
||||
int att = attdet->p_att >= 1 + (nblk >> 1) || p_att > 0;
|
||||
attdet->p_att = p_att;
|
||||
|
||||
return att;
|
||||
}
|
44
3rd-party/lc3-google/src/attdet.h
vendored
Normal file
44
3rd-party/lc3-google/src/attdet.h
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Time domain attack detector
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_ATTDET_H
|
||||
#define __LC3_ATTDET_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Time domain attack detector
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* nbytes Size in bytes of the frame
|
||||
* attdet Context of the Attack Detector
|
||||
* x [-6..-1] Previous, [0..ns-1] Current samples
|
||||
* return 1: Attack detected 0: Otherwise
|
||||
*/
|
||||
bool lc3_attdet_run(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, lc3_attdet_analysis_t *attdet, const float *x);
|
||||
|
||||
|
||||
#endif /* __LC3_ATTDET_H */
|
375
3rd-party/lc3-google/src/bits.c
vendored
Normal file
375
3rd-party/lc3-google/src/bits.c
vendored
Normal file
@ -0,0 +1,375 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "bits.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Common
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static inline int ac_get(struct lc3_bits_buffer *);
|
||||
static inline void accu_load(struct lc3_bits_accu *, struct lc3_bits_buffer *);
|
||||
|
||||
/**
|
||||
* Arithmetic coder return range bits
|
||||
* ac Arithmetic coder
|
||||
* return 1 + log2(ac->range)
|
||||
*/
|
||||
static int ac_get_range_bits(const struct lc3_bits_ac *ac)
|
||||
{
|
||||
int nbits = 0;
|
||||
|
||||
for (unsigned r = ac->range; r; r >>= 1, nbits++);
|
||||
|
||||
return nbits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arithmetic coder return pending bits
|
||||
* ac Arithmetic coder
|
||||
* return Pending bits
|
||||
*/
|
||||
static int ac_get_pending_bits(const struct lc3_bits_ac *ac)
|
||||
{
|
||||
return 26 - ac_get_range_bits(ac) +
|
||||
((ac->cache >= 0) + ac->carry_count) * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bits left in the bitstream
|
||||
* bits Bitstream context
|
||||
* return >= 0: Number of bits left < 0: Overflow
|
||||
*/
|
||||
static int get_bits_left(const struct lc3_bits *bits)
|
||||
{
|
||||
const struct lc3_bits_buffer *buffer = &bits->buffer;
|
||||
const struct lc3_bits_accu *accu = &bits->accu;
|
||||
const struct lc3_bits_ac *ac = &bits->ac;
|
||||
|
||||
uintptr_t end = (uintptr_t)buffer->p_bw +
|
||||
(bits->mode == LC3_BITS_MODE_READ ? LC3_ACCU_BITS/8 : 0);
|
||||
|
||||
uintptr_t start = (uintptr_t)buffer->p_fw -
|
||||
(bits->mode == LC3_BITS_MODE_READ ? LC3_AC_BITS/8 : 0);
|
||||
|
||||
int n = end > start ? (int)(end - start) : -(int)(start - end);
|
||||
|
||||
return 8 * n - (accu->n + accu->nover + ac_get_pending_bits(ac));
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup bitstream writing
|
||||
*/
|
||||
void lc3_setup_bits(struct lc3_bits *bits,
|
||||
enum lc3_bits_mode mode, void *buffer, int len)
|
||||
{
|
||||
*bits = (struct lc3_bits){
|
||||
.mode = mode,
|
||||
.accu = {
|
||||
.n = mode == LC3_BITS_MODE_READ ? LC3_ACCU_BITS : 0,
|
||||
},
|
||||
.ac = {
|
||||
.range = 0xffffff,
|
||||
.cache = -1
|
||||
},
|
||||
.buffer = {
|
||||
.start = (uint8_t *)buffer, .end = (uint8_t *)buffer + len,
|
||||
.p_fw = (uint8_t *)buffer, .p_bw = (uint8_t *)buffer + len,
|
||||
}
|
||||
};
|
||||
|
||||
if (mode == LC3_BITS_MODE_READ) {
|
||||
struct lc3_bits_ac *ac = &bits->ac;
|
||||
struct lc3_bits_accu *accu = &bits->accu;
|
||||
struct lc3_bits_buffer *buffer = &bits->buffer;
|
||||
|
||||
ac->low = ac_get(buffer) << 16;
|
||||
ac->low |= ac_get(buffer) << 8;
|
||||
ac->low |= ac_get(buffer);
|
||||
|
||||
accu_load(accu, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bits left in the bitstream
|
||||
*/
|
||||
int lc3_get_bits_left(const struct lc3_bits *bits)
|
||||
{
|
||||
return LC3_MAX(get_bits_left(bits), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bits left in the bitstream
|
||||
*/
|
||||
int lc3_check_bits(const struct lc3_bits *bits)
|
||||
{
|
||||
const struct lc3_bits_ac *ac = &bits->ac;
|
||||
|
||||
return -(get_bits_left(bits) < 0 || ac->error);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Writing
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Flush the bits accumulator
|
||||
* accu Bitstream accumulator
|
||||
* buffer Bitstream buffer
|
||||
*/
|
||||
static inline void accu_flush(
|
||||
struct lc3_bits_accu *accu, struct lc3_bits_buffer *buffer)
|
||||
{
|
||||
int nbytes = LC3_MIN(accu->n >> 3,
|
||||
LC3_MAX(buffer->p_bw - buffer->p_fw, 0));
|
||||
|
||||
accu->n -= 8 * nbytes;
|
||||
|
||||
for ( ; nbytes; accu->v >>= 8, nbytes--)
|
||||
*(--buffer->p_bw) = accu->v & 0xff;
|
||||
|
||||
if (accu->n >= 8)
|
||||
accu->n = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arithmetic coder put byte
|
||||
* buffer Bitstream buffer
|
||||
* byte Byte to output
|
||||
*/
|
||||
static inline void ac_put(struct lc3_bits_buffer *buffer, int byte)
|
||||
{
|
||||
if (buffer->p_fw < buffer->end)
|
||||
*(buffer->p_fw++) = byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arithmetic coder range shift
|
||||
* ac Arithmetic coder
|
||||
* buffer Bitstream buffer
|
||||
*/
|
||||
static inline void ac_shift(
|
||||
struct lc3_bits_ac *ac, struct lc3_bits_buffer *buffer)
|
||||
{
|
||||
if (ac->low < 0xff0000 || ac->carry)
|
||||
{
|
||||
if (ac->cache >= 0)
|
||||
ac_put(buffer, ac->cache + ac->carry);
|
||||
|
||||
for ( ; ac->carry_count > 0; ac->carry_count--)
|
||||
ac_put(buffer, ac->carry ? 0x00 : 0xff);
|
||||
|
||||
ac->cache = ac->low >> 16;
|
||||
ac->carry = 0;
|
||||
}
|
||||
else
|
||||
ac->carry_count++;
|
||||
|
||||
ac->low = (ac->low << 8) & 0xffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arithmetic coder termination
|
||||
* ac Arithmetic coder
|
||||
* buffer Bitstream buffer
|
||||
* end_val/nbits End value and count of bits to terminate (1 to 8)
|
||||
*/
|
||||
static void ac_terminate(struct lc3_bits_ac *ac,
|
||||
struct lc3_bits_buffer *buffer)
|
||||
{
|
||||
int nbits = 25 - ac_get_range_bits(ac);
|
||||
unsigned mask = 0xffffff >> nbits;
|
||||
unsigned val = ac->low + mask;
|
||||
unsigned high = ac->low + ac->range;
|
||||
|
||||
bool over_val = val >> 24;
|
||||
bool over_high = high >> 24;
|
||||
|
||||
val = (val & 0xffffff) & ~mask;
|
||||
high = (high & 0xffffff);
|
||||
|
||||
if (over_val == over_high) {
|
||||
|
||||
if (val + mask >= high) {
|
||||
nbits++;
|
||||
mask >>= 1;
|
||||
val = ((ac->low + mask) & 0xffffff) & ~mask;
|
||||
}
|
||||
|
||||
ac->carry |= val < ac->low;
|
||||
}
|
||||
|
||||
ac->low = val;
|
||||
|
||||
for (; nbits > 8; nbits -= 8)
|
||||
ac_shift(ac, buffer);
|
||||
ac_shift(ac, buffer);
|
||||
|
||||
int end_val = ac->cache >> (8 - nbits);
|
||||
|
||||
if (ac->carry_count) {
|
||||
ac_put(buffer, ac->cache);
|
||||
for ( ; ac->carry_count > 1; ac->carry_count--)
|
||||
ac_put(buffer, 0xff);
|
||||
|
||||
end_val = nbits < 8 ? 0 : 0xff;
|
||||
}
|
||||
|
||||
if (buffer->p_fw < buffer->end) {
|
||||
*buffer->p_fw &= 0xff >> nbits;
|
||||
*buffer->p_fw |= end_val << (8 - nbits);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush and terminate bitstream
|
||||
*/
|
||||
void lc3_flush_bits(struct lc3_bits *bits)
|
||||
{
|
||||
struct lc3_bits_ac *ac = &bits->ac;
|
||||
struct lc3_bits_accu *accu = &bits->accu;
|
||||
struct lc3_bits_buffer *buffer = &bits->buffer;
|
||||
|
||||
int nleft = buffer->p_bw - buffer->p_fw;
|
||||
for (int n = 8 * nleft - accu->n; n > 0; n -= 32)
|
||||
lc3_put_bits(bits, 0, LC3_MIN(n, 32));
|
||||
|
||||
accu_flush(accu, buffer);
|
||||
|
||||
ac_terminate(ac, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write from 1 to 32 bits,
|
||||
* exceeding the capacity of the accumulator
|
||||
*/
|
||||
void lc3_put_bits_generic(struct lc3_bits *bits, unsigned v, int n)
|
||||
{
|
||||
struct lc3_bits_accu *accu = &bits->accu;
|
||||
|
||||
/* --- Fulfill accumulator and flush -- */
|
||||
|
||||
int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n);
|
||||
if (n1) {
|
||||
accu->v |= v << accu->n;
|
||||
accu->n = LC3_ACCU_BITS;
|
||||
}
|
||||
|
||||
accu_flush(accu, &bits->buffer);
|
||||
|
||||
/* --- Accumulate remaining bits -- */
|
||||
|
||||
accu->v = v >> n1;
|
||||
accu->n = n - n1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arithmetic coder renormalization
|
||||
*/
|
||||
void lc3_ac_write_renorm(struct lc3_bits *bits)
|
||||
{
|
||||
struct lc3_bits_ac *ac = &bits->ac;
|
||||
|
||||
for ( ; ac->range < 0x10000; ac->range <<= 8)
|
||||
ac_shift(ac, &bits->buffer);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Reading
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Arithmetic coder get byte
|
||||
* buffer Bitstream buffer
|
||||
* return Byte read, 0 on overflow
|
||||
*/
|
||||
static inline int ac_get(struct lc3_bits_buffer *buffer)
|
||||
{
|
||||
return buffer->p_fw < buffer->end ? *(buffer->p_fw++) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the accumulator
|
||||
* accu Bitstream accumulator
|
||||
* buffer Bitstream buffer
|
||||
*/
|
||||
static inline void accu_load(struct lc3_bits_accu *accu,
|
||||
struct lc3_bits_buffer *buffer)
|
||||
{
|
||||
int nbytes = LC3_MIN(accu->n >> 3, buffer->p_bw - buffer->start);
|
||||
|
||||
accu->n -= 8 * nbytes;
|
||||
|
||||
for ( ; nbytes; nbytes--) {
|
||||
accu->v >>= 8;
|
||||
accu->v |= *(--buffer->p_bw) << (LC3_ACCU_BITS - 8);
|
||||
}
|
||||
|
||||
if (accu->n >= 8) {
|
||||
accu->nover = LC3_MIN(accu->nover + accu->n, LC3_ACCU_BITS);
|
||||
accu->v >>= accu->n;
|
||||
accu->n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from 1 to 32 bits,
|
||||
* exceeding the capacity of the accumulator
|
||||
*/
|
||||
unsigned lc3_get_bits_generic(struct lc3_bits *bits, int n)
|
||||
{
|
||||
struct lc3_bits_accu *accu = &bits->accu;
|
||||
struct lc3_bits_buffer *buffer = &bits->buffer;
|
||||
|
||||
/* --- Fulfill accumulator and read -- */
|
||||
|
||||
accu_load(accu, buffer);
|
||||
|
||||
int n1 = LC3_MIN(LC3_ACCU_BITS - accu->n, n);
|
||||
unsigned v = (accu->v >> accu->n) & ((1u << n1) - 1);
|
||||
accu->n += n1;
|
||||
|
||||
/* --- Second round --- */
|
||||
|
||||
int n2 = n - n1;
|
||||
|
||||
if (n2) {
|
||||
accu_load(accu, buffer);
|
||||
|
||||
v |= ((accu->v >> accu->n) & ((1u << n2) - 1)) << n1;
|
||||
accu->n += n2;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arithmetic coder renormalization
|
||||
*/
|
||||
void lc3_ac_read_renorm(struct lc3_bits *bits)
|
||||
{
|
||||
struct lc3_bits_ac *ac = &bits->ac;
|
||||
|
||||
for ( ; ac->range < 0x10000; ac->range <<= 8)
|
||||
ac->low = ((ac->low << 8) | ac_get(&bits->buffer)) & 0xffffff;
|
||||
}
|
314
3rd-party/lc3-google/src/bits.h
vendored
Normal file
314
3rd-party/lc3-google/src/bits.h
vendored
Normal file
@ -0,0 +1,314 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Bitstream management
|
||||
*
|
||||
* The bitstream is written by the 2 ends of the buffer :
|
||||
*
|
||||
* - Arthmetic coder put bits while increasing memory addresses
|
||||
* in the buffer (forward)
|
||||
*
|
||||
* - Plain bits are puts starting the end of the buffer, with memeory
|
||||
* addresses decreasing (backward)
|
||||
*
|
||||
* .---------------------------------------------------.
|
||||
* | > > > > > > > > > > : : < < < < < < < < < |
|
||||
* '---------------------------------------------------'
|
||||
* |---------------------> - - - - - - - - - - - - - ->|
|
||||
* |< - - - <-------------------|
|
||||
* Arithmetic coding Plain bits
|
||||
* `lc3_put_symbol()` `lc3_put_bits()`
|
||||
*
|
||||
* - The forward writing is protected against buffer overflow, it cannot
|
||||
* write after the buffer, but can overwrite plain bits previously
|
||||
* written in the buffer.
|
||||
*
|
||||
* - The backward writing is protected against overwrite of the arithmetic
|
||||
* coder bitstream. In such way, the backward bitstream is always limited
|
||||
* by the aritmetic coder bitstream, and can be overwritten by him.
|
||||
*
|
||||
* .---------------------------------------------------.
|
||||
* | > > > > > > > > > > : : < < < < < < < < < |
|
||||
* '---------------------------------------------------'
|
||||
* |---------------------> - - - - - - - - - - - - - ->|
|
||||
* |< - - - - - - - - - - - - - - <-------------------|
|
||||
* Arithmetic coding Plain bits
|
||||
* `lc3_get_symbol()` `lc3_get_bits()`
|
||||
*
|
||||
* - Reading is limited to read of the complementary end of the buffer.
|
||||
*
|
||||
* - The procedure `lc3_check_bits()` returns indication that read has been
|
||||
* made crossing the other bit plane.
|
||||
*
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LC3_BITS_H
|
||||
#define __LC3_BITS_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Bitstream mode
|
||||
*/
|
||||
|
||||
enum lc3_bits_mode {
|
||||
LC3_BITS_MODE_READ,
|
||||
LC3_BITS_MODE_WRITE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Arithmetic coder symbol interval
|
||||
* The model split the interval in 17 symbols
|
||||
*/
|
||||
|
||||
struct lc3_ac_symbol {
|
||||
uint16_t low : 16;
|
||||
uint16_t range : 16;
|
||||
};
|
||||
|
||||
struct lc3_ac_model {
|
||||
struct lc3_ac_symbol s[17];
|
||||
};
|
||||
|
||||
/**
|
||||
* Bitstream context
|
||||
*/
|
||||
|
||||
#define LC3_ACCU_BITS (int)(8 * sizeof(unsigned))
|
||||
|
||||
struct lc3_bits_accu {
|
||||
unsigned v;
|
||||
int n, nover;
|
||||
};
|
||||
|
||||
#define LC3_AC_BITS (int)(24)
|
||||
|
||||
struct lc3_bits_ac {
|
||||
unsigned low, range;
|
||||
int cache, carry, carry_count;
|
||||
bool error;
|
||||
};
|
||||
|
||||
struct lc3_bits_buffer {
|
||||
const uint8_t *start, *end;
|
||||
uint8_t *p_fw, *p_bw;
|
||||
};
|
||||
|
||||
typedef struct lc3_bits {
|
||||
enum lc3_bits_mode mode;
|
||||
struct lc3_bits_ac ac;
|
||||
struct lc3_bits_accu accu;
|
||||
struct lc3_bits_buffer buffer;
|
||||
} lc3_bits_t;
|
||||
|
||||
|
||||
/**
|
||||
* Setup bitstream reading/writing
|
||||
* bits Bitstream context
|
||||
* mode Either READ or WRITE mode
|
||||
* buffer, len Output buffer and length (in bytes)
|
||||
*/
|
||||
void lc3_setup_bits(lc3_bits_t *bits,
|
||||
enum lc3_bits_mode mode, void *buffer, int len);
|
||||
|
||||
/**
|
||||
* Return number of bits left in the bitstream
|
||||
* bits Bitstream context
|
||||
* return Number of bits left
|
||||
*/
|
||||
int lc3_get_bits_left(const lc3_bits_t *bits);
|
||||
|
||||
/**
|
||||
* Check if error occured on bitstream reading/writing
|
||||
* bits Bitstream context
|
||||
* return 0: Ok -1: Bitstream overflow or AC reading error
|
||||
*/
|
||||
int lc3_check_bits(const lc3_bits_t *bits);
|
||||
|
||||
/**
|
||||
* Put a bit
|
||||
* bits Bitstream context
|
||||
* v Bit value, 0 or 1
|
||||
*/
|
||||
static inline void lc3_put_bit(lc3_bits_t *bits, int v);
|
||||
|
||||
/**
|
||||
* Put from 1 to 32 bits
|
||||
* bits Bitstream context
|
||||
* v, n Value, in range 0 to 2^n - 1, and bits count (1 to 32)
|
||||
*/
|
||||
static inline void lc3_put_bits(lc3_bits_t *bits, unsigned v, int n);
|
||||
|
||||
/**
|
||||
* Put arithmetic coder symbol
|
||||
* bits Bitstream context
|
||||
* model, s Model distribution and symbol value
|
||||
*/
|
||||
static inline void lc3_put_symbol(lc3_bits_t *bits,
|
||||
const struct lc3_ac_model *model, unsigned s);
|
||||
|
||||
/**
|
||||
* Flush and terminate bitstream writing
|
||||
* bits Bitstream context
|
||||
*/
|
||||
void lc3_flush_bits(lc3_bits_t *bits);
|
||||
|
||||
/**
|
||||
* Get a bit
|
||||
* bits Bitstream context
|
||||
*/
|
||||
static inline int lc3_get_bit(lc3_bits_t *bits);
|
||||
|
||||
/**
|
||||
* Get from 1 to 32 bits
|
||||
* bits Bitstream context
|
||||
* n Number of bits to read (1 to 32)
|
||||
* return The value read
|
||||
*/
|
||||
static inline unsigned lc3_get_bits(lc3_bits_t *bits, int n);
|
||||
|
||||
/**
|
||||
* Get arithmetic coder symbol
|
||||
* bits Bitstream context
|
||||
* model Model distribution
|
||||
* return The value read
|
||||
*/
|
||||
static inline unsigned lc3_get_symbol(lc3_bits_t *bits,
|
||||
const struct lc3_ac_model *model);
|
||||
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Inline implementations
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
void lc3_put_bits_generic(lc3_bits_t *bits, unsigned v, int n);
|
||||
unsigned lc3_get_bits_generic(struct lc3_bits *bits, int n);
|
||||
|
||||
void lc3_ac_read_renorm(lc3_bits_t *bits);
|
||||
void lc3_ac_write_renorm(lc3_bits_t *bits);
|
||||
|
||||
|
||||
/**
|
||||
* Put a bit
|
||||
*/
|
||||
static inline void lc3_put_bit(lc3_bits_t *bits, int v)
|
||||
{
|
||||
lc3_put_bits(bits, v, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put from 1 to 32 bits
|
||||
*/
|
||||
static inline void lc3_put_bits(struct lc3_bits *bits, unsigned v, int n)
|
||||
{
|
||||
struct lc3_bits_accu *accu = &bits->accu;
|
||||
|
||||
if (accu->n + n <= LC3_ACCU_BITS) {
|
||||
accu->v |= v << accu->n;
|
||||
accu->n += n;
|
||||
} else {
|
||||
lc3_put_bits_generic(bits, v, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a bit
|
||||
*/
|
||||
static inline int lc3_get_bit(lc3_bits_t *bits)
|
||||
{
|
||||
return lc3_get_bits(bits, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get from 1 to 32 bits
|
||||
*/
|
||||
static inline unsigned lc3_get_bits(struct lc3_bits *bits, int n)
|
||||
{
|
||||
struct lc3_bits_accu *accu = &bits->accu;
|
||||
|
||||
if (accu->n + n <= LC3_ACCU_BITS) {
|
||||
int v = (accu->v >> accu->n) & ((1u << n) - 1);
|
||||
return (accu->n += n), v;
|
||||
}
|
||||
else {
|
||||
return lc3_get_bits_generic(bits, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put arithmetic coder symbol
|
||||
*/
|
||||
static inline void lc3_put_symbol(
|
||||
struct lc3_bits *bits, const struct lc3_ac_model *model, unsigned s)
|
||||
{
|
||||
const struct lc3_ac_symbol *symbols = model->s;
|
||||
struct lc3_bits_ac *ac = &bits->ac;
|
||||
unsigned range = ac->range >> 10;
|
||||
|
||||
ac->low += range * symbols[s].low;
|
||||
ac->range = range * symbols[s].range;
|
||||
|
||||
ac->carry |= ac->low >> 24;
|
||||
ac->low &= 0xffffff;
|
||||
|
||||
if (ac->range < 0x10000)
|
||||
lc3_ac_write_renorm(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get arithmetic coder symbol
|
||||
*/
|
||||
static inline unsigned lc3_get_symbol(
|
||||
lc3_bits_t *bits, const struct lc3_ac_model *model)
|
||||
{
|
||||
const struct lc3_ac_symbol *symbols = model->s;
|
||||
struct lc3_bits_ac *ac = &bits->ac;
|
||||
|
||||
unsigned range = (ac->range >> 10) & 0xffff;
|
||||
|
||||
ac->error |= (ac->low >= (range << 10));
|
||||
if (ac->error)
|
||||
ac->low = 0;
|
||||
|
||||
int s = 16;
|
||||
|
||||
if (ac->low < range * symbols[s].low) {
|
||||
s >>= 1;
|
||||
s -= ac->low < range * symbols[s].low ? 4 : -4;
|
||||
s -= ac->low < range * symbols[s].low ? 2 : -2;
|
||||
s -= ac->low < range * symbols[s].low ? 1 : -1;
|
||||
s -= ac->low < range * symbols[s].low;
|
||||
}
|
||||
|
||||
ac->low -= range * symbols[s].low;
|
||||
ac->range = range * symbols[s].range;
|
||||
|
||||
if (ac->range < 0x10000)
|
||||
lc3_ac_read_renorm(bits);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif /* __LC3_BITS_H */
|
129
3rd-party/lc3-google/src/bwdet.c
vendored
Normal file
129
3rd-party/lc3-google/src/bwdet.c
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "bwdet.h"
|
||||
|
||||
|
||||
/**
|
||||
* Bandwidth detector
|
||||
*/
|
||||
enum lc3_bandwidth lc3_bwdet_run(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *e)
|
||||
{
|
||||
/* Bandwidth regions (Table 3.6) */
|
||||
|
||||
struct region { int is : 8; int ie : 8; };
|
||||
|
||||
static const struct region bws_table[LC3_NUM_DT]
|
||||
[LC3_NUM_BANDWIDTH-1][LC3_NUM_BANDWIDTH-1] = {
|
||||
|
||||
[LC3_DT_7M5] = {
|
||||
{ { 51, 63+1 } },
|
||||
{ { 45, 55+1 }, { 58, 63+1 } },
|
||||
{ { 42, 51+1 }, { 53, 58+1 }, { 60, 63+1 } },
|
||||
{ { 40, 48+1 }, { 51, 55+1 }, { 57, 60+1 }, { 61, 63+1 } },
|
||||
},
|
||||
|
||||
[LC3_DT_10M] = {
|
||||
{ { 53, 63+1 } },
|
||||
{ { 47, 56+1 }, { 59, 63+1 } },
|
||||
{ { 44, 52+1 }, { 54, 59+1 }, { 60, 63+1 } },
|
||||
{ { 41, 49+1 }, { 51, 55+1 }, { 57, 60+1 }, { 61, 63+1 } },
|
||||
},
|
||||
};
|
||||
|
||||
static const int l_table[LC3_NUM_DT][LC3_NUM_BANDWIDTH-1] = {
|
||||
[LC3_DT_7M5] = { 4, 4, 3, 2 },
|
||||
[LC3_DT_10M] = { 4, 4, 3, 1 },
|
||||
};
|
||||
|
||||
/* --- Stage 1 ---
|
||||
* Determine bw0 candidate */
|
||||
|
||||
enum lc3_bandwidth bw0 = LC3_BANDWIDTH_NB;
|
||||
enum lc3_bandwidth bwn = (enum lc3_bandwidth)sr;
|
||||
|
||||
if (bwn <= bw0)
|
||||
return bwn;
|
||||
|
||||
const struct region *bwr = bws_table[dt][bwn-1];
|
||||
|
||||
for (enum lc3_bandwidth bw = bw0; bw < bwn; bw++) {
|
||||
int i = bwr[bw].is, ie = bwr[bw].ie;
|
||||
int n = ie - i;
|
||||
|
||||
float se = e[i];
|
||||
for (i++; i < ie; i++)
|
||||
se += e[i];
|
||||
|
||||
if (se >= (10 << (bw == LC3_BANDWIDTH_NB)) * n)
|
||||
bw0 = bw + 1;
|
||||
}
|
||||
|
||||
/* --- Stage 2 ---
|
||||
* Detect drop above cut-off frequency.
|
||||
* The Tc condition (13) is precalculated, as
|
||||
* Tc[] = 10 ^ (n / 10) , n = { 15, 23, 20, 20 } */
|
||||
|
||||
int hold = bw0 >= bwn;
|
||||
|
||||
if (!hold) {
|
||||
int i0 = bwr[bw0].is, l = l_table[dt][bw0];
|
||||
float tc = (const float []){
|
||||
31.62277660, 199.52623150, 100, 100 }[bw0];
|
||||
|
||||
for (int i = i0 - l + 1; !hold && i <= i0 + 1; i++) {
|
||||
hold = e[i-l] > tc * e[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return hold ? bw0 : bwn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bits coding the bandwidth value
|
||||
*/
|
||||
int lc3_bwdet_get_nbits(enum lc3_srate sr)
|
||||
{
|
||||
return (sr > 0) + (sr > 1) + (sr > 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put bandwidth indication
|
||||
*/
|
||||
void lc3_bwdet_put_bw(lc3_bits_t *bits,
|
||||
enum lc3_srate sr, enum lc3_bandwidth bw)
|
||||
{
|
||||
int nbits_bw = lc3_bwdet_get_nbits(sr);
|
||||
if (nbits_bw > 0)
|
||||
lc3_put_bits(bits, bw, nbits_bw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bandwidth indication
|
||||
*/
|
||||
int lc3_bwdet_get_bw(lc3_bits_t *bits,
|
||||
enum lc3_srate sr, enum lc3_bandwidth *bw)
|
||||
{
|
||||
enum lc3_bandwidth max_bw = (enum lc3_bandwidth)sr;
|
||||
int nbits_bw = lc3_bwdet_get_nbits(sr);
|
||||
|
||||
*bw = nbits_bw > 0 ? lc3_get_bits(bits, nbits_bw) : LC3_BANDWIDTH_NB;
|
||||
return *bw > max_bw ? (*bw = max_bw), -1 : 0;
|
||||
}
|
69
3rd-party/lc3-google/src/bwdet.h
vendored
Normal file
69
3rd-party/lc3-google/src/bwdet.h
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Bandwidth detector
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_BWDET_H
|
||||
#define __LC3_BWDET_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
/**
|
||||
* Bandwidth detector (cf. 3.3.5)
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* e Energy estimation per bands
|
||||
* return Return detected bandwitdth
|
||||
*/
|
||||
enum lc3_bandwidth lc3_bwdet_run(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *e);
|
||||
|
||||
/**
|
||||
* Return number of bits coding the bandwidth value
|
||||
* sr Samplerate of the frame
|
||||
* return Number of bits coding the bandwidth value
|
||||
*/
|
||||
int lc3_bwdet_get_nbits(enum lc3_srate sr);
|
||||
|
||||
/**
|
||||
* Put bandwidth indication
|
||||
* bits Bitstream context
|
||||
* sr Samplerate of the frame
|
||||
* bw Bandwidth detected
|
||||
*/
|
||||
void lc3_bwdet_put_bw(lc3_bits_t *bits,
|
||||
enum lc3_srate sr, enum lc3_bandwidth bw);
|
||||
|
||||
/**
|
||||
* Get bandwidth indication
|
||||
* bits Bitstream context
|
||||
* sr Samplerate of the frame
|
||||
* bw Return bandwidth indication
|
||||
* return 0: Ok -1: Invalid bandwidth indication
|
||||
*/
|
||||
int lc3_bwdet_get_bw(lc3_bits_t *bits,
|
||||
enum lc3_srate sr, enum lc3_bandwidth *bw);
|
||||
|
||||
|
||||
#endif /* __LC3_BWDET_H */
|
105
3rd-party/lc3-google/src/common.h
vendored
Normal file
105
3rd-party/lc3-google/src/common.h
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Common constants and types
|
||||
*/
|
||||
|
||||
#ifndef __LC3_COMMON_H
|
||||
#define __LC3_COMMON_H
|
||||
|
||||
#include <lc3.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
/**
|
||||
* Macros
|
||||
* MIN/MAX Minimum and maximum between 2 values
|
||||
* CLIP Clip a value between low and high limits
|
||||
* ABS Return the absolute value
|
||||
*/
|
||||
|
||||
#define LC3_MIN(a, b) ( (a) < (b) ? (a) : (b) )
|
||||
#define LC3_MAX(a, b) ( (a) > (b) ? (a) : (b) )
|
||||
#define LC3_CLIP(v, min, max) LC3_MIN(LC3_MAX(v, min), max)
|
||||
|
||||
#define LC3_ABS(n) ( (n) < 0 ? -(n) : (n) )
|
||||
|
||||
|
||||
/**
|
||||
* Convert `dt` in us and `sr` in KHz
|
||||
*/
|
||||
|
||||
#define LC3_DT_US(dt) \
|
||||
( (3 + (dt)) * 2500 )
|
||||
|
||||
#define LC3_SRATE_KHZ(sr) \
|
||||
( (1 + (sr) + ((sr) == LC3_SRATE_48K)) * 8 )
|
||||
|
||||
|
||||
/**
|
||||
* Return number of samples, delayed samples and
|
||||
* encoded spectrum coefficients within a frame
|
||||
* For decoding, add number of samples of 18 ms history
|
||||
*/
|
||||
|
||||
#define LC3_NS(dt, sr) \
|
||||
( 20 * (3 + (dt)) * (1 + (sr) + ((sr) == LC3_SRATE_48K)) )
|
||||
|
||||
#define LC3_ND(dt, sr) \
|
||||
( (dt) == LC3_DT_7M5 ? 23 * LC3_NS(dt, sr) / 30 \
|
||||
: 5 * LC3_NS(dt, sr) / 8 )
|
||||
#define LC3_NE(dt, sr) \
|
||||
( 20 * (3 + (dt)) * (1 + (sr)) )
|
||||
|
||||
#define LC3_MAX_NE \
|
||||
LC3_NE(LC3_DT_10M, LC3_SRATE_48K)
|
||||
|
||||
#define LC3_NH(sr) \
|
||||
(18 * LC3_SRATE_KHZ(sr))
|
||||
|
||||
|
||||
/**
|
||||
* Bandwidth, mapped to Nyquist frequency of samplerates
|
||||
*/
|
||||
|
||||
enum lc3_bandwidth {
|
||||
LC3_BANDWIDTH_NB = LC3_SRATE_8K,
|
||||
LC3_BANDWIDTH_WB = LC3_SRATE_16K,
|
||||
LC3_BANDWIDTH_SSWB = LC3_SRATE_24K,
|
||||
LC3_BANDWIDTH_SWB = LC3_SRATE_32K,
|
||||
LC3_BANDWIDTH_FB = LC3_SRATE_48K,
|
||||
|
||||
LC3_NUM_BANDWIDTH,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Complex floating point number
|
||||
*/
|
||||
|
||||
struct lc3_complex
|
||||
{
|
||||
float re, im;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __LC3_COMMON_H */
|
70
3rd-party/lc3-google/src/energy.c
vendored
Normal file
70
3rd-party/lc3-google/src/energy.c
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "energy.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
/**
|
||||
* Energy estimation per band
|
||||
*/
|
||||
bool lc3_energy_compute(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *e)
|
||||
{
|
||||
static const int n1_table[LC3_NUM_DT][LC3_NUM_SRATE] = {
|
||||
[LC3_DT_7M5] = { 56, 34, 27, 24, 22 },
|
||||
[LC3_DT_10M] = { 49, 28, 23, 20, 18 },
|
||||
};
|
||||
|
||||
/* First bands are 1 coefficient width */
|
||||
|
||||
int n1 = n1_table[dt][sr];
|
||||
float e_sum[2] = { 0, 0 };
|
||||
int iband;
|
||||
|
||||
for (iband = 0; iband < n1; iband++) {
|
||||
*e = x[iband] * x[iband];
|
||||
e_sum[0] += *(e++);
|
||||
}
|
||||
|
||||
/* Mean the square of coefficients within each band,
|
||||
* note that 7.5ms 8KHz frame has more bands than samples */
|
||||
|
||||
int nb = LC3_MIN(LC3_NUM_BANDS, LC3_NS(dt, sr));
|
||||
int iband_h = nb - 2*(2 - dt);
|
||||
const int *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
for (int i = lim[iband]; iband < nb; iband++) {
|
||||
int ie = lim[iband+1];
|
||||
int n = ie - i;
|
||||
|
||||
float sx2 = x[i] * x[i];
|
||||
for (i++; i < ie; i++)
|
||||
sx2 += x[i] * x[i];
|
||||
|
||||
*e = sx2 / n;
|
||||
e_sum[iband >= iband_h] += *(e++);
|
||||
}
|
||||
|
||||
for (; iband < LC3_NUM_BANDS; iband++)
|
||||
*(e++) = 0;
|
||||
|
||||
/* Return the near nyquist flag */
|
||||
|
||||
return e_sum[1] > 30 * e_sum[0];
|
||||
}
|
43
3rd-party/lc3-google/src/energy.h
vendored
Normal file
43
3rd-party/lc3-google/src/energy.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Energy estimation per band
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_ENERGY_H
|
||||
#define __LC3_ENERGY_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Energy estimation per band
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* x Input MDCT coefficient
|
||||
* e Energy estimation per bands
|
||||
* return True when high energy detected near Nyquist frequency
|
||||
*/
|
||||
bool lc3_energy_compute(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *e);
|
||||
|
||||
|
||||
#endif /* __LC3_ENERGY_H */
|
570
3rd-party/lc3-google/src/lc3.c
vendored
Normal file
570
3rd-party/lc3-google/src/lc3.c
vendored
Normal file
@ -0,0 +1,570 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 <lc3.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "bits.h"
|
||||
|
||||
#include "attdet.h"
|
||||
#include "bwdet.h"
|
||||
#include "ltpf.h"
|
||||
#include "mdct.h"
|
||||
#include "energy.h"
|
||||
#include "sns.h"
|
||||
#include "tns.h"
|
||||
#include "spec.h"
|
||||
#include "plc.h"
|
||||
|
||||
|
||||
/**
|
||||
* Frame side data
|
||||
*/
|
||||
|
||||
struct side_data {
|
||||
enum lc3_bandwidth bw;
|
||||
bool pitch_present;
|
||||
lc3_ltpf_data_t ltpf;
|
||||
lc3_sns_data_t sns;
|
||||
lc3_tns_data_t tns;
|
||||
lc3_spec_side_t spec;
|
||||
};
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* General
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resolve frame duration in us
|
||||
* us Frame duration in us
|
||||
* return Frame duration identifier, or LC3_NUM_DT
|
||||
*/
|
||||
static enum lc3_dt resolve_dt(int us)
|
||||
{
|
||||
return us == 7500 ? LC3_DT_7M5 :
|
||||
us == 10000 ? LC3_DT_10M : LC3_NUM_DT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve samplerate in Hz
|
||||
* hz Samplerate in Hz
|
||||
* return Sample rate identifier, or LC3_NUM_SRATE
|
||||
*/
|
||||
static enum lc3_srate resolve_sr(int hz)
|
||||
{
|
||||
return hz == 8000 ? LC3_SRATE_8K : hz == 16000 ? LC3_SRATE_16K :
|
||||
hz == 24000 ? LC3_SRATE_24K : hz == 32000 ? LC3_SRATE_32K :
|
||||
hz == 48000 ? LC3_SRATE_48K : LC3_NUM_SRATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of PCM samples in a frame
|
||||
*/
|
||||
int lc3_frame_samples(int dt_us, int sr_hz)
|
||||
{
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
|
||||
return -1;
|
||||
|
||||
return LC3_NS(dt, sr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of frames, from bitrate
|
||||
*/
|
||||
int lc3_frame_bytes(int dt_us, int bitrate)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT)
|
||||
return -1;
|
||||
|
||||
if (bitrate < LC3_MIN_BITRATE)
|
||||
return LC3_MIN_FRAME_BYTES;
|
||||
|
||||
if (bitrate > LC3_MAX_BITRATE)
|
||||
return LC3_MAX_FRAME_BYTES;
|
||||
|
||||
int nbytes = ((unsigned)bitrate * dt_us) / (1000*1000*8);
|
||||
|
||||
return LC3_CLIP(nbytes, LC3_MIN_FRAME_BYTES, LC3_MAX_FRAME_BYTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the bitrate, from the size of frames
|
||||
*/
|
||||
int lc3_resolve_bitrate(int dt_us, int nbytes)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT)
|
||||
return -1;
|
||||
|
||||
if (nbytes < LC3_MIN_FRAME_BYTES)
|
||||
return LC3_MIN_BITRATE;
|
||||
|
||||
if (nbytes > LC3_MAX_FRAME_BYTES)
|
||||
return LC3_MAX_BITRATE;
|
||||
|
||||
int bitrate = ((unsigned)nbytes * (1000*1000*8) + dt_us/2) / dt_us;
|
||||
|
||||
return LC3_CLIP(bitrate, LC3_MIN_BITRATE, LC3_MAX_BITRATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return algorithmic delay, as a number of samples
|
||||
*/
|
||||
int lc3_delay_samples(int dt_us, int sr_hz)
|
||||
{
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
|
||||
return -1;
|
||||
|
||||
return (dt == LC3_DT_7M5 ? 8 : 5) * (LC3_SRATE_KHZ(sr) / 2);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Encoder
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Input PCM Samples from signed 16 bits
|
||||
* encoder Encoder state
|
||||
* pcm, stride Input PCM samples, and count between two consecutives
|
||||
*/
|
||||
static void load_s16(
|
||||
struct lc3_encoder *encoder, const void *_pcm, int stride)
|
||||
{
|
||||
const int16_t *pcm = _pcm;
|
||||
|
||||
enum lc3_dt dt = encoder->dt;
|
||||
enum lc3_srate sr = encoder->sr_pcm;
|
||||
float *xs = encoder->xs;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
|
||||
for (int i = 0; i < ns; i++)
|
||||
xs[i] = pcm[i*stride];
|
||||
}
|
||||
|
||||
/**
|
||||
* Input PCM Samples from signed 24 bits
|
||||
* encoder Encoder state
|
||||
* pcm, stride Input PCM samples, and count between two consecutives
|
||||
*/
|
||||
static void load_s24(
|
||||
struct lc3_encoder *encoder, const void *_pcm, int stride)
|
||||
{
|
||||
const int32_t *pcm = _pcm;
|
||||
|
||||
enum lc3_dt dt = encoder->dt;
|
||||
enum lc3_srate sr = encoder->sr_pcm;
|
||||
float *xs = encoder->xs;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
|
||||
for (int i = 0; i < ns; i++)
|
||||
xs[i] = ldexpf(pcm[i*stride], -8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frame Analysis
|
||||
* encoder Encoder state
|
||||
* nbytes Size in bytes of the frame
|
||||
* side, xq Return frame data
|
||||
*/
|
||||
static void analyze(struct lc3_encoder *encoder,
|
||||
int nbytes, struct side_data *side, int16_t *xq)
|
||||
{
|
||||
enum lc3_dt dt = encoder->dt;
|
||||
enum lc3_srate sr = encoder->sr;
|
||||
enum lc3_srate sr_pcm = encoder->sr_pcm;
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nd = LC3_ND(dt, sr_pcm);
|
||||
|
||||
float *xs = encoder->xs;
|
||||
float *xf = encoder->xf;
|
||||
|
||||
/* --- Temporal --- */
|
||||
|
||||
bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xs);
|
||||
|
||||
side->pitch_present =
|
||||
lc3_ltpf_analyse(dt, sr_pcm, &encoder->ltpf, xs, &side->ltpf);
|
||||
|
||||
/* --- Spectral --- */
|
||||
|
||||
float e[LC3_NUM_BANDS];
|
||||
|
||||
lc3_mdct_forward(dt, sr_pcm, sr, xs, xf);
|
||||
memmove(xs - nd, xs + ns-nd, nd * sizeof(float));
|
||||
|
||||
bool nn_flag = lc3_energy_compute(dt, sr, xf, e);
|
||||
if (nn_flag)
|
||||
lc3_ltpf_disable(&side->ltpf);
|
||||
|
||||
side->bw = lc3_bwdet_run(dt, sr, e);
|
||||
|
||||
lc3_sns_analyze(dt, sr, e, att, &side->sns, xf, xf);
|
||||
|
||||
lc3_tns_analyze(dt, side->bw, nn_flag, nbytes, &side->tns, xf);
|
||||
|
||||
lc3_spec_analyze(dt, sr,
|
||||
nbytes, side->pitch_present, &side->tns,
|
||||
&encoder->spec, xf, xq, &side->spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode bitstream
|
||||
* encoder Encoder state
|
||||
* side, xq The frame data
|
||||
* nbytes Target size of the frame (20 to 400)
|
||||
* buffer Output bitstream buffer of `nbytes` size
|
||||
*/
|
||||
static void encode(struct lc3_encoder *encoder,
|
||||
const struct side_data *side, int16_t *xq, int nbytes, void *buffer)
|
||||
{
|
||||
enum lc3_dt dt = encoder->dt;
|
||||
enum lc3_srate sr = encoder->sr;
|
||||
enum lc3_bandwidth bw = side->bw;
|
||||
float *xf = encoder->xf;
|
||||
|
||||
lc3_bits_t bits;
|
||||
|
||||
lc3_setup_bits(&bits, LC3_BITS_MODE_WRITE, buffer, nbytes);
|
||||
|
||||
lc3_bwdet_put_bw(&bits, sr, bw);
|
||||
|
||||
lc3_spec_put_side(&bits, dt, sr, &side->spec);
|
||||
|
||||
lc3_tns_put_data(&bits, &side->tns);
|
||||
|
||||
lc3_put_bit(&bits, side->pitch_present);
|
||||
|
||||
lc3_sns_put_data(&bits, &side->sns);
|
||||
|
||||
if (side->pitch_present)
|
||||
lc3_ltpf_put_data(&bits, &side->ltpf);
|
||||
|
||||
lc3_spec_encode(&bits,
|
||||
dt, sr, bw, nbytes, xq, &side->spec, xf);
|
||||
|
||||
lc3_flush_bits(&bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size needed for an encoder
|
||||
*/
|
||||
unsigned lc3_encoder_size(int dt_us, int sr_hz)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT ||
|
||||
resolve_sr(sr_hz) >= LC3_NUM_SRATE)
|
||||
return 0;
|
||||
|
||||
return sizeof(struct lc3_encoder) +
|
||||
LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) * sizeof(float);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup encoder
|
||||
*/
|
||||
struct lc3_encoder *lc3_setup_encoder(
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
|
||||
{
|
||||
if (sr_pcm_hz <= 0)
|
||||
sr_pcm_hz = sr_hz;
|
||||
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
|
||||
return NULL;
|
||||
|
||||
struct lc3_encoder *encoder = mem;
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nd = LC3_ND(dt, sr_pcm);
|
||||
|
||||
*encoder = (struct lc3_encoder){
|
||||
.dt = dt, .sr = sr,
|
||||
.sr_pcm = sr_pcm,
|
||||
.xs = encoder->s + nd,
|
||||
.xf = encoder->s + nd+ns,
|
||||
};
|
||||
|
||||
memset(encoder->s, 0,
|
||||
LC3_ENCODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float));
|
||||
|
||||
return encoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a frame
|
||||
*/
|
||||
int lc3_encode(struct lc3_encoder *encoder, enum lc3_pcm_format fmt,
|
||||
const void *pcm, int stride, int nbytes, void *out)
|
||||
{
|
||||
static void (* const load[])(struct lc3_encoder *, const void *, int) = {
|
||||
[LC3_PCM_FORMAT_S16] = load_s16,
|
||||
[LC3_PCM_FORMAT_S24] = load_s24,
|
||||
};
|
||||
|
||||
/* --- Check parameters --- */
|
||||
|
||||
if (!encoder || nbytes < LC3_MIN_FRAME_BYTES
|
||||
|| nbytes > LC3_MAX_FRAME_BYTES)
|
||||
return -1;
|
||||
|
||||
/* --- Processing --- */
|
||||
|
||||
struct side_data side;
|
||||
int16_t xq[LC3_NE(encoder->dt, encoder->sr)];
|
||||
|
||||
load[fmt](encoder, pcm, stride);
|
||||
|
||||
analyze(encoder, nbytes, &side, xq);
|
||||
|
||||
encode(encoder, &side, xq, nbytes, out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Decoder
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Output PCM Samples to signed 16 bits
|
||||
* decoder Decoder state
|
||||
* pcm, stride Output PCM samples, and count between two consecutives
|
||||
*/
|
||||
static void store_s16(
|
||||
struct lc3_decoder *decoder, void *_pcm, int stride)
|
||||
{
|
||||
int16_t *pcm = _pcm;
|
||||
|
||||
enum lc3_dt dt = decoder->dt;
|
||||
enum lc3_srate sr = decoder->sr_pcm;
|
||||
float *xs = decoder->xs;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
|
||||
for ( ; ns > 0; ns--, xs++, pcm += stride) {
|
||||
int s = *xs >= 0 ? (int)(*xs + 0.5f) : (int)(*xs - 0.5f);
|
||||
*pcm = LC3_CLIP(s, INT16_MIN, INT16_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output PCM Samples to signed 24 bits
|
||||
* decoder Decoder state
|
||||
* pcm, stride Output PCM samples, and count between two consecutives
|
||||
*/
|
||||
static void store_s24(
|
||||
struct lc3_decoder *decoder, void *_pcm, int stride)
|
||||
{
|
||||
int32_t *pcm = _pcm;
|
||||
const int32_t int24_max = (1 << 23) - 1;
|
||||
const int32_t int24_min = -(1 << 23);
|
||||
|
||||
enum lc3_dt dt = decoder->dt;
|
||||
enum lc3_srate sr = decoder->sr_pcm;
|
||||
float *xs = decoder->xs;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
|
||||
for ( ; ns > 0; ns--, xs++, pcm += stride) {
|
||||
int32_t s = *xs >= 0 ? (int32_t)(ldexpf(*xs, 8) + 0.5f)
|
||||
: (int32_t)(ldexpf(*xs, 8) - 0.5f);
|
||||
*pcm = LC3_CLIP(s, int24_min, int24_max);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode bitstream
|
||||
* decoder Decoder state
|
||||
* data, nbytes Input bitstream buffer
|
||||
* side Return the side data
|
||||
* return 0: Ok < 0: Bitsream error detected
|
||||
*/
|
||||
static int decode(struct lc3_decoder *decoder,
|
||||
const void *data, int nbytes, struct side_data *side)
|
||||
{
|
||||
enum lc3_dt dt = decoder->dt;
|
||||
enum lc3_srate sr = decoder->sr;
|
||||
float *xf = decoder->xs;
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
|
||||
lc3_bits_t bits;
|
||||
int ret = 0;
|
||||
|
||||
lc3_setup_bits(&bits, LC3_BITS_MODE_READ, (void *)data, nbytes);
|
||||
|
||||
if ((ret = lc3_bwdet_get_bw(&bits, sr, &side->bw)) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = lc3_spec_get_side(&bits, dt, sr, &side->spec)) < 0)
|
||||
return ret;
|
||||
|
||||
lc3_tns_get_data(&bits, dt, side->bw, nbytes, &side->tns);
|
||||
|
||||
side->pitch_present = lc3_get_bit(&bits);
|
||||
|
||||
if ((ret = lc3_sns_get_data(&bits, &side->sns)) < 0)
|
||||
return ret;
|
||||
|
||||
if (side->pitch_present)
|
||||
lc3_ltpf_get_data(&bits, &side->ltpf);
|
||||
|
||||
if ((ret = lc3_spec_decode(&bits, dt, sr,
|
||||
side->bw, nbytes, &side->spec, xf)) < 0)
|
||||
return ret;
|
||||
|
||||
memset(xf + ne, 0, (ns - ne) * sizeof(float));
|
||||
|
||||
return lc3_check_bits(&bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frame synthesis
|
||||
* decoder Decoder state
|
||||
* side Frame data, NULL performs PLC
|
||||
* nbytes Size in bytes of the frame
|
||||
*/
|
||||
static void synthesize(struct lc3_decoder *decoder,
|
||||
const struct side_data *side, int nbytes)
|
||||
{
|
||||
enum lc3_dt dt = decoder->dt;
|
||||
enum lc3_srate sr = decoder->sr;
|
||||
enum lc3_srate sr_pcm = decoder->sr_pcm;
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
int nh = LC3_NH(sr_pcm);
|
||||
|
||||
float *xf = decoder->xs;
|
||||
float *xg = decoder->xg;
|
||||
float *xd = decoder->xd;
|
||||
float *xs = xf;
|
||||
|
||||
if (side) {
|
||||
enum lc3_bandwidth bw = side->bw;
|
||||
|
||||
lc3_plc_suspend(&decoder->plc);
|
||||
|
||||
lc3_tns_synthesize(dt, bw, &side->tns, xf);
|
||||
|
||||
lc3_sns_synthesize(dt, sr, &side->sns, xf, xg);
|
||||
|
||||
lc3_mdct_inverse(dt, sr_pcm, sr, xg, xd, xs);
|
||||
|
||||
} else {
|
||||
lc3_plc_synthesize(dt, sr, &decoder->plc, xg, xf);
|
||||
|
||||
memset(xf + ne, 0, (ns - ne) * sizeof(float));
|
||||
|
||||
lc3_mdct_inverse(dt, sr_pcm, sr, xf, xd, xs);
|
||||
}
|
||||
|
||||
lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf,
|
||||
side && side->pitch_present ? &side->ltpf : NULL, xs);
|
||||
|
||||
memmove(xs - nh, xs - nh+ns, nh * sizeof(*xs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size needed for a decoder
|
||||
*/
|
||||
unsigned lc3_decoder_size(int dt_us, int sr_hz)
|
||||
{
|
||||
if (resolve_dt(dt_us) >= LC3_NUM_DT ||
|
||||
resolve_sr(sr_hz) >= LC3_NUM_SRATE)
|
||||
return 0;
|
||||
|
||||
return sizeof(struct lc3_decoder) +
|
||||
LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) * sizeof(float);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup decoder
|
||||
*/
|
||||
struct lc3_decoder *lc3_setup_decoder(
|
||||
int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
|
||||
{
|
||||
if (sr_pcm_hz <= 0)
|
||||
sr_pcm_hz = sr_hz;
|
||||
|
||||
enum lc3_dt dt = resolve_dt(dt_us);
|
||||
enum lc3_srate sr = resolve_sr(sr_hz);
|
||||
enum lc3_srate sr_pcm = resolve_sr(sr_pcm_hz);
|
||||
|
||||
if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
|
||||
return NULL;
|
||||
|
||||
struct lc3_decoder *decoder = mem;
|
||||
int nh = LC3_NH(sr_pcm);
|
||||
int ns = LC3_NS(dt, sr_pcm);
|
||||
int nd = LC3_ND(dt, sr_pcm);
|
||||
|
||||
*decoder = (struct lc3_decoder){
|
||||
.dt = dt, .sr = sr,
|
||||
.sr_pcm = sr_pcm,
|
||||
.xs = decoder->s + nh,
|
||||
.xd = decoder->s + nh+ns,
|
||||
.xg = decoder->s + nh+ns+nd,
|
||||
};
|
||||
|
||||
lc3_plc_reset(&decoder->plc);
|
||||
|
||||
memset(decoder->s, 0,
|
||||
LC3_DECODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float));
|
||||
|
||||
return decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a frame
|
||||
*/
|
||||
int lc3_decode(struct lc3_decoder *decoder, const void *in, int nbytes,
|
||||
enum lc3_pcm_format fmt, void *pcm, int stride)
|
||||
{
|
||||
static void (* const store[])(struct lc3_decoder *, void *, int) = {
|
||||
[LC3_PCM_FORMAT_S16] = store_s16,
|
||||
[LC3_PCM_FORMAT_S24] = store_s24,
|
||||
};
|
||||
|
||||
/* --- Check parameters --- */
|
||||
|
||||
if (!decoder)
|
||||
return -1;
|
||||
|
||||
if (in && (nbytes < LC3_MIN_FRAME_BYTES ||
|
||||
nbytes > LC3_MAX_FRAME_BYTES ))
|
||||
return -1;
|
||||
|
||||
/* --- Processing --- */
|
||||
|
||||
struct side_data side;
|
||||
|
||||
int ret = !in || (decode(decoder, in, nbytes, &side) < 0);
|
||||
|
||||
synthesize(decoder, ret ? NULL : &side, nbytes);
|
||||
|
||||
store[fmt](decoder, pcm, stride);
|
||||
|
||||
return ret;
|
||||
}
|
621
3rd-party/lc3-google/src/ltpf.c
vendored
Normal file
621
3rd-party/lc3-google/src/ltpf.c
vendored
Normal file
@ -0,0 +1,621 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "ltpf.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Resampling
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resample to 12.8 KHz (cf. 3.3.9.3-4) Template
|
||||
* sr Samplerate source of the frame
|
||||
* hp50 State of the High-Pass 50 Hz filter
|
||||
* x [-d..-1] Previous, [0..ns-1] Current samples
|
||||
* y, n [0..n-1] Output `n` processed samples
|
||||
*
|
||||
* The number of previous samples `d` accessed on `x` is :
|
||||
* d: { 10, 20, 30, 40, 60 } - 1 for samplerates from 8KHz to 48KHz
|
||||
*/
|
||||
static inline void resample_12k8_template(const enum lc3_srate sr,
|
||||
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
|
||||
{
|
||||
/* --- Parameters ---
|
||||
* p: Resampling factor, from 4 to 24
|
||||
* w: Half width of polyphase filter
|
||||
*
|
||||
* bn, an: High-Pass Biquad coefficients,
|
||||
* with `bn` support of rescaling resampling factor.
|
||||
* Note that it's an High-Pass filter, so we have `b0 = b2`,
|
||||
* in the following steps we use `b0` as `b2`. */
|
||||
|
||||
const int p = 192 / LC3_SRATE_KHZ(sr);
|
||||
const int w = 5 * LC3_SRATE_KHZ(sr) / 8;
|
||||
|
||||
const int b_scale = p >> (sr == LC3_SRATE_8K);
|
||||
const float a1 = -1.965293373, b1 = -1.965589417 * b_scale;
|
||||
const float a2 = 0.965885461, b2 = 0.982794708 * b_scale;
|
||||
|
||||
/* --- Resampling ---
|
||||
* The value `15*8 * n` is divisible by all resampling factors `p`,
|
||||
* integer and fractionnal position can be determined at compilation
|
||||
* time while unrolling the loops by 8 samples.
|
||||
* The biquad filter implementation chosen in the `Direct Form 2`. */
|
||||
|
||||
const float *h = lc3_ltpf_h12k8 + 119;
|
||||
x -= w;
|
||||
|
||||
for (int i = 0; i < n; i += 8, x += 120/p)
|
||||
for (int j = 0; j < 15*8; j += 15) {
|
||||
float un, yn;
|
||||
int e, f, k;
|
||||
|
||||
e = j / p, f = j % p;
|
||||
for (un = 0, k = 1-w; k <= w; k++)
|
||||
un += x[e+k] * h[k*p - f];
|
||||
|
||||
yn = b2 * un + hp50->s1;
|
||||
hp50->s1 = b1 * un - a1 * yn + hp50->s2;
|
||||
hp50->s2 = b2 * un - a2 * yn;
|
||||
*(y++) = yn;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LTPF Resample to 12.8 KHz implementations for each samplerates
|
||||
*/
|
||||
|
||||
static void resample_8k_12k8(
|
||||
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
|
||||
{
|
||||
resample_12k8_template(LC3_SRATE_8K, hp50, x, y, n);
|
||||
}
|
||||
|
||||
static void resample_16k_12k8(
|
||||
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
|
||||
{
|
||||
resample_12k8_template(LC3_SRATE_16K, hp50, x, y, n);
|
||||
}
|
||||
|
||||
static void resample_24k_12k8(
|
||||
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
|
||||
{
|
||||
resample_12k8_template(LC3_SRATE_24K, hp50, x, y, n);
|
||||
}
|
||||
|
||||
static void resample_32k_12k8(
|
||||
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
|
||||
{
|
||||
resample_12k8_template(LC3_SRATE_32K, hp50, x, y, n);
|
||||
}
|
||||
|
||||
static void resample_48k_12k8(
|
||||
struct lc3_ltpf_hp50_state *hp50, const float *x, float *y, int n)
|
||||
{
|
||||
resample_12k8_template(LC3_SRATE_48K, hp50, x, y, n);
|
||||
}
|
||||
|
||||
static void (* const resample_12k8[])
|
||||
(struct lc3_ltpf_hp50_state *, const float *, float *, int ) =
|
||||
{
|
||||
[LC3_SRATE_8K ] = resample_8k_12k8,
|
||||
[LC3_SRATE_16K] = resample_16k_12k8,
|
||||
[LC3_SRATE_24K] = resample_24k_12k8,
|
||||
[LC3_SRATE_32K] = resample_32k_12k8,
|
||||
[LC3_SRATE_48K] = resample_48k_12k8,
|
||||
};
|
||||
|
||||
/**
|
||||
* Resample to 6.4 KHz (cf. 3.3.9.3-4)
|
||||
* x [-3..-1] Previous, [0..n-1] Current samples
|
||||
* y, n [0..n-1] Output `n` processed samples
|
||||
*/
|
||||
static void resample_6k4(const float *x, float *y, int n)
|
||||
{
|
||||
static const float h[] = { 0.2819382921, 0.2353512128, 0.1236796411 };
|
||||
float xn2 = x[-3], xn1 = x[-2], x0 = x[-1], x1, x2;
|
||||
|
||||
for (const float *ye = y + n; y < ye; xn2 = x0, xn1 = x1, x0 = x2) {
|
||||
x1 = *(x++); x2 = *(x++);
|
||||
|
||||
*(y++) = x0 * h[0] + (xn1 + x1) * h[1] + (xn2 + x2) * h[2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Analysis
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Return dot product of 2 vectors
|
||||
* a, b, n The 2 vectors of size `n`
|
||||
* return sum( a[i] * b[i] ), i = [0..n-1]
|
||||
*/
|
||||
static inline float dot(const float *a, const float *b, int n)
|
||||
{
|
||||
float v = 0;
|
||||
|
||||
while (n--)
|
||||
v += *(a++) * *(b++);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return vector of correlations
|
||||
* a, b, n The 2 vector of size `n` to correlate
|
||||
* y, nc Output the correlation vector of size `nc`
|
||||
*
|
||||
* The size `n` of input vectors must be multiple of 16
|
||||
*/
|
||||
static void correlate(
|
||||
const float *a, const float *b, int n, float *y, int nc)
|
||||
{
|
||||
for (const float *ye = y + nc; y < ye; )
|
||||
*(y++) = dot(a, b--, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the maximum value and returns its argument
|
||||
* x, n The input vector of size `n`
|
||||
* x_max Return the maximum value
|
||||
* return Return the argument of the maximum
|
||||
*/
|
||||
static int argmax(const float *x, int n, float *x_max)
|
||||
{
|
||||
int arg = 0;
|
||||
|
||||
*x_max = x[arg = 0];
|
||||
for (int i = 1; i < n; i++)
|
||||
if (*x_max < x[i])
|
||||
*x_max = x[arg = i];
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the maximum weithed value and returns its argument
|
||||
* x, n The input vector of size `n`
|
||||
* w_incr Increment of the weight
|
||||
* x_max, xw_max Return the maximum not weighted value
|
||||
* return Return the argument of the weigthed maximum
|
||||
*/
|
||||
static int argmax_weighted(
|
||||
const float *x, int n, float w_incr, float *x_max)
|
||||
{
|
||||
int arg;
|
||||
|
||||
float xw_max = (*x_max = x[arg = 0]);
|
||||
float w = 1 + w_incr;
|
||||
|
||||
for (int i = 1; i < n; i++, w += w_incr)
|
||||
if (xw_max < x[i] * w)
|
||||
xw_max = (*x_max = x[arg = i]) * w;
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate from pitch detected value (3.3.9.8)
|
||||
* x, n [-2..-1] Previous, [0..n] Current input
|
||||
* d The phase of interpolation (0 to 3)
|
||||
* return The interpolated vector
|
||||
*
|
||||
* The size `n` of vectors must be multiple of 4
|
||||
*/
|
||||
static void interpolate(const float *x, int n, int d, float *y)
|
||||
{
|
||||
static const float h4[][8] = {
|
||||
{ 2.09880463e-01, 5.83527575e-01, 2.09880463e-01 },
|
||||
{ 1.06999186e-01, 5.50075002e-01, 3.35690625e-01, 6.69885837e-03 },
|
||||
{ 3.96711478e-02, 4.59220930e-01, 4.59220930e-01, 3.96711478e-02 },
|
||||
{ 6.69885837e-03, 3.35690625e-01, 5.50075002e-01, 1.06999186e-01 },
|
||||
};
|
||||
|
||||
const float *h = h4[d];
|
||||
float x3 = x[-2], x2 = x[-1], x1, x0;
|
||||
|
||||
x1 = (*x++);
|
||||
for (const float *ye = y + n; y < ye; ) {
|
||||
*(y++) = (x0 = *(x++)) * h[0] + x1 * h[1] + x2 * h[2] + x3 * h[3];
|
||||
*(y++) = (x3 = *(x++)) * h[0] + x0 * h[1] + x1 * h[2] + x2 * h[3];
|
||||
*(y++) = (x2 = *(x++)) * h[0] + x3 * h[1] + x0 * h[2] + x1 * h[3];
|
||||
*(y++) = (x1 = *(x++)) * h[0] + x2 * h[1] + x3 * h[2] + x0 * h[3];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate autocorrelation (3.3.9.7)
|
||||
* x [-4..-1] Previous, [0..4] Current input
|
||||
* d The phase of interpolation (-3 to 3)
|
||||
* return The interpolated value
|
||||
*/
|
||||
static float interpolate_4(const float *x, int d)
|
||||
{
|
||||
static const float h4[][8] = {
|
||||
{ 1.53572770e-02, -4.72963246e-02, 8.35788573e-02, 8.98638285e-01,
|
||||
8.35788573e-02, -4.72963246e-02, 1.53572770e-02, },
|
||||
{ 2.74547165e-03, 4.59833449e-03, -7.54404636e-02, 8.17488686e-01,
|
||||
3.30182571e-01, -1.05835916e-01, 2.86823405e-02, -2.87456116e-03 },
|
||||
{ -3.00125103e-03, 2.95038503e-02, -1.30305021e-01, 6.03297008e-01,
|
||||
6.03297008e-01, -1.30305021e-01, 2.95038503e-02, -3.00125103e-03 },
|
||||
{ -2.87456116e-03, 2.86823405e-02, -1.05835916e-01, 3.30182571e-01,
|
||||
8.17488686e-01, -7.54404636e-02, 4.59833449e-03, 2.74547165e-03 },
|
||||
};
|
||||
|
||||
const float *h = h4[(4+d) % 4];
|
||||
|
||||
float y = d < 0 ? x[-4] * *(h++) :
|
||||
d > 0 ? x[ 4] * *(h+7) : 0;
|
||||
|
||||
y += x[-3] * h[0] + x[-2] * h[1] + x[-1] * h[2] + x[0] * h[3] +
|
||||
x[ 1] * h[4] + x[ 2] * h[5] + x[ 3] * h[6];
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pitch detection algorithm (3.3.9.5-6)
|
||||
* ltpf Context of analysis
|
||||
* x, n [-114..-17] Previous, [0..n-1] Current 6.4KHz samples
|
||||
* tc Return the pitch-lag estimation
|
||||
* return True when pitch present
|
||||
*/
|
||||
static bool detect_pitch(
|
||||
struct lc3_ltpf_analysis *ltpf, const float *x, int n, int *tc)
|
||||
{
|
||||
float rm1, rm2;
|
||||
float r[98];
|
||||
|
||||
const int r0 = 17, nr = 98;
|
||||
int k0 = LC3_MAX( 0, ltpf->tc-4);
|
||||
int nk = LC3_MIN(nr-1, ltpf->tc+4) - k0 + 1;
|
||||
|
||||
correlate(x, x - r0, n, r, nr);
|
||||
|
||||
int t1 = argmax_weighted(r, nr, -.5/(nr-1), &rm1);
|
||||
int t2 = k0 + argmax(r + k0, nk, &rm2);
|
||||
|
||||
const float *x1 = x - (r0 + t1);
|
||||
const float *x2 = x - (r0 + t2);
|
||||
|
||||
float nc1 = rm1 <= 0 ? 0 :
|
||||
rm1 / sqrtf(dot(x, x, n) * dot(x1, x1, n));
|
||||
|
||||
float nc2 = rm2 <= 0 ? 0 :
|
||||
rm2 / sqrtf(dot(x, x, n) * dot(x2, x2, n));
|
||||
|
||||
int t1sel = nc2 <= 0.85 * nc1;
|
||||
ltpf->tc = (t1sel ? t1 : t2);
|
||||
|
||||
*tc = r0 + ltpf->tc;
|
||||
return (t1sel ? nc1 : nc2) > 0.6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pitch-lag parameter (3.3.9.7)
|
||||
* x, n [-232..-28] Previous, [0..n-1] Current 12.8KHz samples
|
||||
* tc Pitch-lag estimation
|
||||
* pitch The pitch value, in fixed .4
|
||||
* return The bitstream pitch index value
|
||||
*/
|
||||
static int refine_pitch(const float *x, int n, int tc, int *pitch)
|
||||
{
|
||||
float r[17], rm;
|
||||
int e, f;
|
||||
|
||||
int r0 = LC3_MAX( 32, 2*tc - 4);
|
||||
int nr = LC3_MIN(228, 2*tc + 4) - r0 + 1;
|
||||
|
||||
correlate(x, x - (r0 - 4), n, r, nr + 8);
|
||||
|
||||
e = r0 + argmax(r + 4, nr, &rm);
|
||||
const float *re = r + (e - (r0 - 4));
|
||||
|
||||
float dm = interpolate_4(re, f = 0);
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
float d;
|
||||
|
||||
if (e >= 127 && ((i & 1) | (e >= 157)))
|
||||
continue;
|
||||
|
||||
if ((d = interpolate_4(re, i)) > dm)
|
||||
dm = d, f = i;
|
||||
|
||||
if (e > 32 && (d = interpolate_4(re, -i)) > dm)
|
||||
dm = d, f = -i;
|
||||
}
|
||||
|
||||
e -= (f < 0);
|
||||
f += 4*(f < 0);
|
||||
|
||||
*pitch = 4*e + f;
|
||||
return e < 127 ? 4*e + f - 128 :
|
||||
e < 157 ? 2*e + (f >> 1) + 126 : e + 283;
|
||||
}
|
||||
|
||||
/**
|
||||
* LTPF Analysis
|
||||
*/
|
||||
bool lc3_ltpf_analyse(enum lc3_dt dt, enum lc3_srate sr,
|
||||
struct lc3_ltpf_analysis *ltpf, const float *x, struct lc3_ltpf_data *data)
|
||||
{
|
||||
/* --- Resampling to 12.8 KHz --- */
|
||||
|
||||
int z_12k8 = sizeof(ltpf->x_12k8) / sizeof(float);
|
||||
int n_12k8 = dt == LC3_DT_7M5 ? 96 : 128;
|
||||
|
||||
memmove(ltpf->x_12k8, ltpf->x_12k8 + n_12k8,
|
||||
(z_12k8 - n_12k8) * sizeof(float));
|
||||
|
||||
float *x_12k8 = ltpf->x_12k8 + (z_12k8 - n_12k8);
|
||||
resample_12k8[sr](<pf->hp50, x, x_12k8, n_12k8);
|
||||
|
||||
x_12k8 -= (dt == LC3_DT_7M5 ? 44 : 24);
|
||||
|
||||
/* --- Resampling to 6.4 KHz --- */
|
||||
|
||||
int z_6k4 = sizeof(ltpf->x_6k4) / sizeof(float);
|
||||
int n_6k4 = n_12k8 >> 1;
|
||||
|
||||
memmove(ltpf->x_6k4, ltpf->x_6k4 + n_6k4,
|
||||
(z_6k4 - n_6k4) * sizeof(float));
|
||||
|
||||
float *x_6k4 = ltpf->x_6k4 + (z_6k4 - n_6k4);
|
||||
resample_6k4(x_12k8, x_6k4, n_6k4);
|
||||
|
||||
/* --- Pitch detection --- */
|
||||
|
||||
int tc, pitch = 0;
|
||||
float nc = 0;
|
||||
|
||||
bool pitch_present = detect_pitch(ltpf, x_6k4, n_6k4, &tc);
|
||||
|
||||
if (pitch_present) {
|
||||
float u[n_12k8], v[n_12k8];
|
||||
|
||||
data->pitch_index = refine_pitch(x_12k8, n_12k8, tc, &pitch);
|
||||
|
||||
interpolate(x_12k8, n_12k8, 0, u);
|
||||
interpolate(x_12k8 - (pitch >> 2), n_12k8, pitch & 3, v);
|
||||
|
||||
nc = dot(u, v, n_12k8) / sqrtf(dot(u, u, n_12k8) * dot(v, v, n_12k8));
|
||||
}
|
||||
|
||||
/* --- Activation --- */
|
||||
|
||||
if (ltpf->active) {
|
||||
int pitch_diff =
|
||||
LC3_MAX(pitch, ltpf->pitch) - LC3_MIN(pitch, ltpf->pitch);
|
||||
float nc_diff = nc - ltpf->nc[0];
|
||||
|
||||
data->active = pitch_present &&
|
||||
((nc > 0.9) || (nc > 0.84 && pitch_diff < 8 && nc_diff > -0.1));
|
||||
|
||||
} else {
|
||||
data->active = pitch_present &&
|
||||
( (dt == LC3_DT_10M || ltpf->nc[1] > 0.94) &&
|
||||
(ltpf->nc[0] > 0.94 && nc > 0.94) );
|
||||
}
|
||||
|
||||
ltpf->active = data->active;
|
||||
ltpf->pitch = pitch;
|
||||
ltpf->nc[1] = ltpf->nc[0];
|
||||
ltpf->nc[0] = nc;
|
||||
|
||||
return pitch_present;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Synthesis
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Synthesis filter template
|
||||
* ym [-w/2..0] Previous, [0..w-1] Current pitch samples
|
||||
* xm w-1 previous input samples
|
||||
* x, n Current samples as input, filtered as output
|
||||
* c, w Coefficients by pair (num, den), and count of pairs
|
||||
* fade Fading mode of filter -1: Out 1: In 0: None
|
||||
*/
|
||||
static inline void synthesize_template(const float *ym, const float *xm,
|
||||
float *x, int n, const float (*c)[2], const int w, int fade)
|
||||
{
|
||||
float g = (float)(fade <= 0);
|
||||
float g_incr = (float)((fade > 0) - (fade < 0)) / n;
|
||||
float u[w];
|
||||
int i;
|
||||
|
||||
ym -= (w >> 1);
|
||||
|
||||
/* --- Load previous samples --- */
|
||||
|
||||
for (i = 1-w; i < 0; i++) {
|
||||
float xi = *(xm++), yi = *(ym++);
|
||||
|
||||
u[i + w-1] = 0;
|
||||
for (int k = w-1; k+i >= 0; k--)
|
||||
u[i+k] += xi * c[k][0] - yi * c[k][1];
|
||||
}
|
||||
|
||||
u[w-1] = 0;
|
||||
|
||||
/* --- Process --- */
|
||||
|
||||
for (; i < n; i += w) {
|
||||
|
||||
for (int j = 0; j < w; j++, g += g_incr) {
|
||||
float xi = *x, yi = *(ym++);
|
||||
|
||||
for (int k = w-1; k >= 0; k--)
|
||||
u[(j+k)%w] += xi * c[k][0] - yi * c[k][1];
|
||||
|
||||
*(x++) = xi - g * u[j];
|
||||
u[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesis filter for each samplerates (width of filter)
|
||||
*/
|
||||
|
||||
static void synthesize_4(const float *ym, const float *xm,
|
||||
float *x, int n, const float (*c)[2], int fade)
|
||||
{
|
||||
synthesize_template(ym, xm, x, n, c, 4, fade);
|
||||
}
|
||||
|
||||
static void synthesize_6(const float *ym, const float *xm,
|
||||
float *x, int n, const float (*c)[2], int fade)
|
||||
{
|
||||
synthesize_template(ym, xm, x, n, c, 6, fade);
|
||||
}
|
||||
|
||||
static void synthesize_8(const float *ym, const float *xm,
|
||||
float *x, int n, const float (*c)[2], int fade)
|
||||
{
|
||||
synthesize_template(ym, xm, x, n, c, 8, fade);
|
||||
}
|
||||
|
||||
static void synthesize_12(const float *ym, const float *xm,
|
||||
float *x, int n, const float (*c)[2], int fade)
|
||||
{
|
||||
synthesize_template(ym, xm, x, n, c, 12, fade);
|
||||
}
|
||||
|
||||
static void (* const synthesize[])(
|
||||
const float *, const float *, float *, int, const float (*)[2], int) =
|
||||
{
|
||||
[LC3_SRATE_8K ] = synthesize_4,
|
||||
[LC3_SRATE_16K] = synthesize_4,
|
||||
[LC3_SRATE_24K] = synthesize_6,
|
||||
[LC3_SRATE_32K] = synthesize_8,
|
||||
[LC3_SRATE_48K] = synthesize_12,
|
||||
};
|
||||
|
||||
/**
|
||||
* LTPF Synthesis
|
||||
*/
|
||||
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, struct lc3_ltpf_synthesis *ltpf,
|
||||
const struct lc3_ltpf_data *data, float *x)
|
||||
{
|
||||
int dt_us = LC3_DT_US(dt);
|
||||
|
||||
/* --- Filter parameters --- */
|
||||
|
||||
int p_idx = data ? data->pitch_index : 0;
|
||||
int pitch =
|
||||
p_idx >= 440 ? (((p_idx ) - 283) << 2) :
|
||||
p_idx >= 380 ? (((p_idx >> 1) - 63) << 2) + (((p_idx & 1)) << 1) :
|
||||
(((p_idx >> 2) + 32) << 2) + (((p_idx & 3)) << 0) ;
|
||||
|
||||
pitch = (pitch * LC3_SRATE_KHZ(sr) * 10 + 64) / 128;
|
||||
|
||||
int nbits = (nbytes*8 * 10000 + (dt_us/2)) / dt_us;
|
||||
int g_idx = LC3_MAX(nbits / 80, 3 + (int)sr) - (3 + sr);
|
||||
bool active = data && data->active && g_idx < 4;
|
||||
|
||||
int w = LC3_MAX(4, LC3_SRATE_KHZ(sr) / 4);
|
||||
float c[w][2];
|
||||
|
||||
for (int i = 0; i < w; i++) {
|
||||
float g = active ? 0.4f - 0.05f * g_idx : 0;
|
||||
|
||||
c[i][0] = active ? 0.85f * g * lc3_ltpf_cnum[sr][g_idx][i] : 0;
|
||||
c[i][1] = active ? g * lc3_ltpf_cden[sr][pitch & 3][i] : 0;
|
||||
}
|
||||
|
||||
/* --- Transition handling --- */
|
||||
|
||||
int ns = LC3_NS(dt, sr);
|
||||
int nt = ns / (4 - (dt == LC3_DT_7M5));
|
||||
float xm[12];
|
||||
|
||||
if (active)
|
||||
memcpy(xm, x + nt-(w-1), (w-1) * sizeof(float));
|
||||
|
||||
if (!ltpf->active && active)
|
||||
synthesize[sr](x - pitch/4, ltpf->x, x, nt, c, 1);
|
||||
else if (ltpf->active && !active)
|
||||
synthesize[sr](x - ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
|
||||
else if (ltpf->active && active && ltpf->pitch == pitch)
|
||||
synthesize[sr](x - pitch/4, ltpf->x, x, nt, c, 0);
|
||||
else if (ltpf->active && active) {
|
||||
synthesize[sr](x - ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
|
||||
synthesize[sr](x - pitch/4, x - (w-1), x, nt, c, 1);
|
||||
}
|
||||
|
||||
/* --- Remainder --- */
|
||||
|
||||
memcpy(ltpf->x, x + ns-(w-1), (w-1) * sizeof(float));
|
||||
|
||||
if (active)
|
||||
synthesize[sr](x - pitch/4 + nt, xm, x + nt, ns-nt, c, 0);
|
||||
|
||||
/* --- Update state --- */
|
||||
|
||||
ltpf->active = active;
|
||||
ltpf->pitch = pitch;
|
||||
memcpy(ltpf->c, c, w * sizeof(ltpf->c[0]));
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Bitstream data
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* LTPF disable
|
||||
*/
|
||||
void lc3_ltpf_disable(struct lc3_ltpf_data *data)
|
||||
{
|
||||
data->active = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bits coding the bitstream data
|
||||
*/
|
||||
int lc3_ltpf_get_nbits(bool pitch)
|
||||
{
|
||||
return 1 + 10 * pitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put bitstream data
|
||||
*/
|
||||
void lc3_ltpf_put_data(lc3_bits_t *bits,
|
||||
const struct lc3_ltpf_data *data)
|
||||
{
|
||||
lc3_put_bit(bits, data->active);
|
||||
lc3_put_bits(bits, data->pitch_index, 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bitstream data
|
||||
*/
|
||||
void lc3_ltpf_get_data(lc3_bits_t *bits, struct lc3_ltpf_data *data)
|
||||
{
|
||||
data->active = lc3_get_bit(bits);
|
||||
data->pitch_index = lc3_get_bits(bits, 9);
|
||||
}
|
107
3rd-party/lc3-google/src/ltpf.h
vendored
Normal file
107
3rd-party/lc3-google/src/ltpf.h
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Long Term Postfilter
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_LTPF_H
|
||||
#define __LC3_LTPF_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
/**
|
||||
* LTPF data
|
||||
*/
|
||||
|
||||
typedef struct lc3_ltpf_data {
|
||||
bool active;
|
||||
int pitch_index;
|
||||
} lc3_ltpf_data_t;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Encoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* LTPF analysis
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* ltpf Context of analysis
|
||||
* allowed True when activation of LTPF is allowed
|
||||
* x [-d..-1] Previous, [0..ns-1] Current samples
|
||||
* data Return bitstream data
|
||||
* return True when pitch present, False otherwise
|
||||
*
|
||||
* The number of previous samples `d` accessed on `x` is :
|
||||
* d: { 10, 20, 30, 40, 60 } - 1 for samplerates from 8KHz to 48KHz
|
||||
*/
|
||||
bool lc3_ltpf_analyse(enum lc3_dt dt, enum lc3_srate sr,
|
||||
lc3_ltpf_analysis_t *ltpf, const float *x, lc3_ltpf_data_t *data);
|
||||
|
||||
/**
|
||||
* LTPF disable
|
||||
* data LTPF data, disabled activation on return
|
||||
*/
|
||||
void lc3_ltpf_disable(lc3_ltpf_data_t *data);
|
||||
|
||||
/**
|
||||
* Return number of bits coding the bitstream data
|
||||
* pitch True when pitch present, False otherwise
|
||||
* return Bit consumption, including the pitch present flag
|
||||
*/
|
||||
int lc3_ltpf_get_nbits(bool pitch);
|
||||
|
||||
/**
|
||||
* Put bitstream data
|
||||
* bits Bitstream context
|
||||
* data LTPF data
|
||||
*/
|
||||
void lc3_ltpf_put_data(lc3_bits_t *bits, const lc3_ltpf_data_t *data);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Decoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Get bitstream data
|
||||
* bits Bitstream context
|
||||
* data Return bitstream data
|
||||
*/
|
||||
void lc3_ltpf_get_data(lc3_bits_t *bits, lc3_ltpf_data_t *data);
|
||||
|
||||
/**
|
||||
* LTPF synthesis
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* nbytes Size in bytes of the frame
|
||||
* ltpf Context of synthesis
|
||||
* data Bitstream data, NULL when pitch not present
|
||||
* x [-d..-1] Previous, [0..ns-1] Current, filtered as output
|
||||
*
|
||||
* The number of previous samples `d` accessed on `x` is about 18 ms
|
||||
*/
|
||||
void lc3_ltpf_synthesize(enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data, float *x);
|
||||
|
||||
|
||||
#endif /* __LC3_LTPF_H */
|
502
3rd-party/lc3-google/src/mdct.c
vendored
Normal file
502
3rd-party/lc3-google/src/mdct.c
vendored
Normal file
@ -0,0 +1,502 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "tables.h"
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* FFT processing
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* FFT 5 Points template
|
||||
* s -1: Forward 1: Inverse
|
||||
* x, y Input and output coefficients, of size 5xn
|
||||
* n Number of interleaved transform to perform
|
||||
*/
|
||||
static inline void xfft_5(const float s,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
static const float cos1 = 0.3090169944; /* cos(-2Pi 1/5) */
|
||||
static const float cos2 = -0.8090169944; /* cos(-2Pi 2/5) */
|
||||
|
||||
static const float sin1 = -0.9510565163; /* sin(-2Pi 1/5) */
|
||||
static const float sin2 = -0.5877852523; /* sin(-2Pi 2/5) */
|
||||
|
||||
for (int i = 0; i < n; i++, x++, y+= 5) {
|
||||
|
||||
struct lc3_complex s14 =
|
||||
{ x[1*n].re + x[4*n].re, x[1*n].im + x[4*n].im };
|
||||
struct lc3_complex d14 =
|
||||
{ x[1*n].re - x[4*n].re, x[1*n].im - x[4*n].im };
|
||||
|
||||
struct lc3_complex s23 =
|
||||
{ x[2*n].re + x[3*n].re, x[2*n].im + x[3*n].im };
|
||||
struct lc3_complex d23 =
|
||||
{ x[2*n].re - x[3*n].re, x[2*n].im - x[3*n].im };
|
||||
|
||||
y[0].re = x[0].re + s14.re + s23.re;
|
||||
y[0].im = x[0].im + s14.im + s23.im;
|
||||
|
||||
y[1].re = x[0].re + s14.re * cos1 + s * d14.im * sin1
|
||||
+ s23.re * cos2 + s * d23.im * sin2;
|
||||
|
||||
y[1].im = x[0].im + s14.im * cos1 - s * d14.re * sin1
|
||||
+ s23.im * cos2 - s * d23.re * sin2;
|
||||
|
||||
y[2].re = x[0].re + s14.re * cos2 + s * d14.im * sin2
|
||||
+ s23.re * cos1 - s * d23.im * sin1;
|
||||
|
||||
y[2].im = x[0].im + s14.im * cos2 - s * d14.re * sin2
|
||||
+ s23.im * cos1 + s * d23.re * sin1;
|
||||
|
||||
y[3].re = x[0].re + s14.re * cos2 - s * d14.im * sin2
|
||||
+ s23.re * cos1 + s * d23.im * sin1;
|
||||
|
||||
y[3].im = x[0].im + s14.im * cos2 + s * d14.re * sin2
|
||||
+ s23.im * cos1 - s * d23.re * sin1;
|
||||
|
||||
y[4].re = x[0].re + s14.re * cos1 - s * d14.im * sin1
|
||||
+ s23.re * cos2 - s * d23.im * sin2;
|
||||
|
||||
y[4].im = x[0].im + s14.im * cos1 + s * d14.re * sin1
|
||||
+ s23.im * cos2 + s * d23.re * sin2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT Butterfly 3 Points template
|
||||
* s -1: Forward 1: Inverse
|
||||
* x, y Input and output coefficients
|
||||
* twiddles Twiddles factors, determine size of transform
|
||||
* n Number of interleaved transforms
|
||||
*/
|
||||
static inline void xfft_bf3(
|
||||
const float s, const struct lc3_fft_bf3_twiddles *twiddles,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
int n3 = twiddles->n3;
|
||||
const struct lc3_complex (*w0)[2] = twiddles->t;
|
||||
const struct lc3_complex (*w1)[2] = w0 + n3, (*w2)[2] = w1 + n3;
|
||||
|
||||
const struct lc3_complex *x0 = x, *x1 = x0 + n*n3, *x2 = x1 + n*n3;
|
||||
struct lc3_complex *y0 = y, *y1 = y0 + n3, *y2 = y1 + n3;
|
||||
|
||||
for (int i = 0; i < n; i++, y0 += 3*n3, y1 += 3*n3, y2 += 3*n3) {
|
||||
|
||||
for (int j = 0; j < n3; j++, x0++, x1++, x2++) {
|
||||
|
||||
y0[j].re = x0->re + x1->re * w0[j][0].re + s * x1->im * w0[j][0].im
|
||||
+ x2->re * w0[j][1].re + s * x2->im * w0[j][1].im;
|
||||
|
||||
y0[j].im = x0->im + x1->im * w0[j][0].re - s * x1->re * w0[j][0].im
|
||||
+ x2->im * w0[j][1].re - s * x2->re * w0[j][1].im;
|
||||
|
||||
y1[j].re = x0->re + x1->re * w1[j][0].re + s * x1->im * w1[j][0].im
|
||||
+ x2->re * w1[j][1].re + s * x2->im * w1[j][1].im;
|
||||
|
||||
y1[j].im = x0->im + x1->im * w1[j][0].re - s * x1->re * w1[j][0].im
|
||||
+ x2->im * w1[j][1].re - s * x2->re * w1[j][1].im;
|
||||
|
||||
y2[j].re = x0->re + x1->re * w2[j][0].re + s * x1->im * w2[j][0].im
|
||||
+ x2->re * w2[j][1].re + s * x2->im * w2[j][1].im;
|
||||
|
||||
y2[j].im = x0->im + x1->im * w2[j][0].re - s * x1->re * w2[j][0].im
|
||||
+ x2->im * w2[j][1].re - s * x2->re * w2[j][1].im;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT Butterfly 2 Points template
|
||||
* s -1: Forward 1: Inverse
|
||||
* twiddles Twiddles factors, determine size of transform
|
||||
* x, y Input and output coefficients
|
||||
* n Number of interleaved transforms
|
||||
*/
|
||||
static inline void xfft_bf2(
|
||||
const float s, const struct lc3_fft_bf2_twiddles *twiddles,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
int n2 = twiddles->n2;
|
||||
const struct lc3_complex *w = twiddles->t;
|
||||
|
||||
const struct lc3_complex *x0 = x, *x1 = x0 + n*n2;
|
||||
struct lc3_complex *y0 = y, *y1 = y0 + n2;
|
||||
|
||||
for (int i = 0; i < n; i++, y0 += 2*n2, y1 += 2*n2) {
|
||||
|
||||
for (int j = 0; j < n2; j++, x0++, x1++) {
|
||||
|
||||
y0[j].re = x0->re + x1->re * w[j].re + s * x1->im * w[j].im;
|
||||
y0[j].im = x0->im + x1->im * w[j].re - s * x1->re * w[j].im;
|
||||
|
||||
y1[j].re = x0->re - x1->re * w[j].re - s * x1->im * w[j].im;
|
||||
y1[j].im = x0->im - x1->im * w[j].re + s * x1->re * w[j].im;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward FFT 5 Points
|
||||
* x, y Input and output coefficients, of size 5xn
|
||||
* n Number of interleaved transform to perform
|
||||
*/
|
||||
static void ffft_5(const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
xfft_5(-1, x, y, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse FFT 5 Points
|
||||
* x, y Input and output coefficients, of size 5xn
|
||||
* n Number of interleaved transform to perform
|
||||
*/
|
||||
static void ifft_5(const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
xfft_5(1, x, y, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward FFT Butterfly 3 Points
|
||||
* twiddles Twiddles factors, determine size of transform
|
||||
* x, y Input and output coefficients
|
||||
* n Number of interleaved transforms
|
||||
*/
|
||||
static void ffft_bf3(const struct lc3_fft_bf3_twiddles *twiddles,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
xfft_bf3(-1, twiddles, x, y, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse FFT Butterfly 3 Points
|
||||
* twiddles Twiddles factors, determine size of transform
|
||||
* x, y Input and output coefficients
|
||||
* n Number of interleaved transforms
|
||||
*/
|
||||
static void ifft_bf3(const struct lc3_fft_bf3_twiddles *twiddles,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
xfft_bf3(1, twiddles, x, y, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward FFT Butterfly 2 Points
|
||||
* twiddles Twiddles factors, determine size of transform
|
||||
* x, y Input and output coefficients
|
||||
* n Number of interleaved transforms
|
||||
*/
|
||||
static void ffft_bf2(const struct lc3_fft_bf2_twiddles *twiddles,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
xfft_bf2(-1, twiddles, x, y, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* InverseIFFT Butterfly 2 Points
|
||||
* twiddles Twiddles factors, determine size of transform
|
||||
* x, y Input and output coefficients
|
||||
* n Number of interleaved transforms
|
||||
*/
|
||||
static void ifft_bf2(const struct lc3_fft_bf2_twiddles *twiddles,
|
||||
const struct lc3_complex *x, struct lc3_complex *y, int n)
|
||||
{
|
||||
xfft_bf2(1, twiddles, x, y, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform FFT
|
||||
* inverse True on inverse transform else forward
|
||||
* x, y0, y1 Input, and 2 scratch buffers of size `n`
|
||||
* n Number of points 30, 40, 60, 80, 90, 120, 160, 180, 240
|
||||
* return The buffer `y0` or `y1` that hold the result
|
||||
*
|
||||
* Input `x` can be the same as the `y0` second scratch buffer
|
||||
*/
|
||||
static struct lc3_complex *fft(
|
||||
bool inverse, const struct lc3_complex *x, int n,
|
||||
struct lc3_complex *y0, struct lc3_complex *y1)
|
||||
{
|
||||
struct lc3_complex *y[2] = { y1, y0 };
|
||||
int i2, i3, is = 0;
|
||||
|
||||
/* The number of points `n` can be decomposed as :
|
||||
*
|
||||
* n = 5^1 * 3^n3 * 2^n2
|
||||
*
|
||||
* for n = 40, 80, 160 n3 = 0, n2 = [3..5]
|
||||
* n = 30, 60, 120, 240 n3 = 1, n2 = [1..4]
|
||||
* n = 90, 180 n3 = 2, n2 = [1..2]
|
||||
*
|
||||
* Note that the expression `n & (n-1) == 0` is equivalent
|
||||
* to the check that `n` is a power of 2. */
|
||||
|
||||
(inverse ? ifft_5 : ffft_5)(x, y[is], n /= 5);
|
||||
|
||||
for (i3 = 0; n & (n-1); i3++, is ^= 1)
|
||||
(inverse ? ifft_bf3 : ffft_bf3)
|
||||
(lc3_fft_twiddles_bf3[i3], y[is], y[is ^ 1], n /= 3);
|
||||
|
||||
for (i2 = 0; n > 1; i2++, is ^= 1)
|
||||
(inverse ? ifft_bf2 : ffft_bf2)
|
||||
(lc3_fft_twiddles_bf2[i2][i3], y[is], y[is ^ 1], n >>= 1);
|
||||
|
||||
return y[is];
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* MDCT processing
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Windowing of samples before MDCT
|
||||
* dt, sr Duration and samplerate (size of the transform)
|
||||
* x [-nd..-1] Previous, [0..ns-1] Current samples
|
||||
* y Output `ns` windowed samples
|
||||
*
|
||||
* The number of previous samples `nd` accessed on `x` is :
|
||||
* nd: `ns` * 23/30 for 7.5ms frame duration
|
||||
* nd: `ns` * 5/ 8 for 10ms frame duration
|
||||
*/
|
||||
static void mdct_window(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x, float *y)
|
||||
{
|
||||
int ns = LC3_NS(dt, sr), nd = LC3_ND(dt, sr);
|
||||
|
||||
const float *w0 = lc3_mdct_win[dt][sr], *w1 = w0 + ns;
|
||||
const float *w2 = w1, *w3 = w2 + nd;
|
||||
|
||||
const float *x0 = x - nd, *x1 = x0 + ns;
|
||||
const float *x2 = x1, *x3 = x2 + nd;
|
||||
|
||||
float *y0 = y + ns/2, *y1 = y0;
|
||||
|
||||
while (x0 < x1)
|
||||
*(--y0) = *(x0++) * *(w0++) - *(--x1) * *(--w1);
|
||||
|
||||
for (const float *xe = x2 + ns-nd; x2 < xe; )
|
||||
*(y1++) = *(x2++) * *(w2++);
|
||||
|
||||
while (x2 < x3)
|
||||
*(y1++) = *(x2++) * *(w2++) + *(--x3) * *(--w3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-rotate MDCT coefficients of N/2 points, before FFT N/4 points FFT
|
||||
* def Size and twiddles factors
|
||||
* x, y Input and output coefficients
|
||||
*
|
||||
* `x` and y` can be the same buffer
|
||||
*/
|
||||
static void mdct_pre_fft(const struct lc3_mdct_rot_def *def,
|
||||
const float *x, struct lc3_complex *y)
|
||||
{
|
||||
int n4 = def->n4;
|
||||
|
||||
const float *x0 = x, *x1 = x0 + 2*n4;
|
||||
const struct lc3_complex *w0 = def->w, *w1 = w0 + n4;
|
||||
struct lc3_complex *y0 = y, *y1 = y0 + n4;
|
||||
|
||||
while (x0 < x1) {
|
||||
struct lc3_complex u, uw = *(w0++);
|
||||
u.re = - *(--x1) * uw.re + *x0 * uw.im;
|
||||
u.im = *(x0++) * uw.re + *x1 * uw.im;
|
||||
|
||||
struct lc3_complex v, vw = *(--w1);
|
||||
v.re = - *(--x1) * vw.im + *x0 * vw.re;
|
||||
v.im = - *(x0++) * vw.im - *x1 * vw.re;
|
||||
|
||||
*(y0++) = u;
|
||||
*(--y1) = v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-rotate FFT N/4 points coefficients, resulting MDCT N points
|
||||
* def Size and twiddles factors
|
||||
* x, y Input and output coefficients
|
||||
* scale Scale on output coefficients
|
||||
*
|
||||
* `x` and y` can be the same buffer
|
||||
*/
|
||||
static void mdct_post_fft(const struct lc3_mdct_rot_def *def,
|
||||
const struct lc3_complex *x, float *y, float scale)
|
||||
{
|
||||
int n4 = def->n4, n8 = n4 >> 1;
|
||||
|
||||
const struct lc3_complex *w0 = def->w + n8, *w1 = w0 - 1;
|
||||
const struct lc3_complex *x0 = x + n8, *x1 = x0 - 1;
|
||||
|
||||
float *y0 = y + n4, *y1 = y0;
|
||||
|
||||
for ( ; y1 > y; x0++, x1--, w0++, w1--) {
|
||||
|
||||
float u0 = (x0->im * w0->im + x0->re * w0->re) * scale;
|
||||
float u1 = (x1->re * w1->im - x1->im * w1->re) * scale;
|
||||
|
||||
float v0 = (x0->re * w0->im - x0->im * w0->re) * scale;
|
||||
float v1 = (x1->im * w1->im + x1->re * w1->re) * scale;
|
||||
|
||||
*(y0++) = u0; *(y0++) = u1;
|
||||
*(--y1) = v0; *(--y1) = v1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-rotate IMDCT coefficients of N points, before FFT N/4 points FFT
|
||||
* def Size and twiddles factors
|
||||
* x, y Input and output coefficients
|
||||
*
|
||||
* `x` and y` can be the same buffer
|
||||
*/
|
||||
static void imdct_pre_fft(const struct lc3_mdct_rot_def *def,
|
||||
const float *x, struct lc3_complex *y)
|
||||
{
|
||||
int n4 = def->n4;
|
||||
|
||||
const float *x0 = x, *x1 = x0 + 2*n4;
|
||||
|
||||
const struct lc3_complex *w0 = def->w, *w1 = w0 + n4;
|
||||
struct lc3_complex *y0 = y, *y1 = y0 + n4;
|
||||
|
||||
while (x0 < x1) {
|
||||
float u0 = *(x0++), u1 = *(--x1);
|
||||
float v0 = *(x0++), v1 = *(--x1);
|
||||
struct lc3_complex uw = *(w0++), vw = *(--w1);
|
||||
|
||||
(y0 )->re = - u1 * uw.re + u0 * uw.im;
|
||||
(y0++)->im = - u0 * uw.re - u1 * uw.im;
|
||||
|
||||
(--y1)->re = - v0 * vw.re + v1 * vw.im;
|
||||
( y1)->im = - v1 * vw.re - v0 * vw.im;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-rotate FFT N/4 points coefficients, resulting IMDCT N points
|
||||
* def Size and twiddles factors
|
||||
* x, y Input and output coefficients
|
||||
* scale Scale on output coefficients
|
||||
*
|
||||
* `x` and y` can be the same buffer
|
||||
*/
|
||||
static void imdct_post_fft(const struct lc3_mdct_rot_def *def,
|
||||
const struct lc3_complex *x, float *y, float scale)
|
||||
{
|
||||
int n4 = def->n4;
|
||||
|
||||
const struct lc3_complex *w0 = def->w, *w1 = w0 + n4;
|
||||
const struct lc3_complex *x0 = x, *x1 = x0 + n4;
|
||||
|
||||
float *y0 = y, *y1 = y0 + 2*n4;
|
||||
|
||||
while (x0 < x1) {
|
||||
struct lc3_complex uz = *(x0++), vz = *(--x1);
|
||||
struct lc3_complex uw = *(w0++), vw = *(--w1);
|
||||
|
||||
*(y0++) = (uz.im * uw.im - uz.re * uw.re) * scale;
|
||||
*(--y1) = (uz.im * uw.re + uz.re * uw.im) * scale;
|
||||
|
||||
*(--y1) = (vz.im * vw.im - vz.re * vw.re) * scale;
|
||||
*(y0++) = (vz.im * vw.re + vz.re * vw.im) * scale;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply windowing of samples
|
||||
* dt, sr Duration and samplerate
|
||||
* x, d Middle half of IMDCT coefficients and delayed samples
|
||||
* y, d Output samples and delayed ones
|
||||
*/
|
||||
static void imdct_window(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *x, float *d, float *y)
|
||||
{
|
||||
/* The full MDCT coefficients is given by symmetry :
|
||||
* T[ 0 .. n/4-1] = -half[n/4-1 .. 0 ]
|
||||
* T[ n/4 .. n/2-1] = half[0 .. n/4-1]
|
||||
* T[ n/2 .. 3n/4-1] = half[n/4 .. n/2-1]
|
||||
* T[3n/4 .. n-1] = half[n/2-1 .. n/4 ] */
|
||||
|
||||
int n4 = LC3_NS(dt, sr) >> 1, nd = LC3_ND(dt, sr);
|
||||
const float *w2 = lc3_mdct_win[dt][sr], *w0 = w2 + 3*n4, *w1 = w0;
|
||||
|
||||
const float *x0 = d + nd-n4, *x1 = x0;
|
||||
float *y0 = y + nd-n4, *y1 = y0, *y2 = d + nd, *y3 = d;
|
||||
|
||||
while (y0 > y) {
|
||||
*(--y0) = *(--x0) - *(x ) * *(w1++);
|
||||
*(y1++) = *(x1++) + *(x++) * *(--w0);
|
||||
}
|
||||
|
||||
while (y1 < y + nd) {
|
||||
*(y1++) = *(x1++) + *(x++) * *(--w0);
|
||||
}
|
||||
|
||||
while (y1 < y + 2*n4) {
|
||||
*(y1++) = *(x ) * *(--w0);
|
||||
*(--y2) = *(x++) * *(w2++);
|
||||
}
|
||||
|
||||
while (y2 > y3) {
|
||||
*(y3++) = *(x ) * *(--w0);
|
||||
*(--y2) = *(x++) * *(w2++);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward MDCT transformation
|
||||
*/
|
||||
void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_dst, const float *x, float *y)
|
||||
{
|
||||
const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
|
||||
int nf = LC3_NS(dt, sr_dst);
|
||||
int ns = LC3_NS(dt, sr);
|
||||
|
||||
union { float *f; struct lc3_complex *z; } u = { .f = y };
|
||||
struct lc3_complex z[ns/2];
|
||||
|
||||
mdct_window(dt, sr, x, u.f);
|
||||
|
||||
mdct_pre_fft(rot, u.f, u.z);
|
||||
u.z = fft(false, u.z, ns/2, u.z, z);
|
||||
mdct_post_fft(rot, u.z, y, sqrtf( (2.f*nf) / (ns*ns) ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse MDCT transformation
|
||||
*/
|
||||
void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_src, const float *x, float *d, float *y)
|
||||
{
|
||||
const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
|
||||
int nf = LC3_NS(dt, sr_src);
|
||||
int ns = LC3_NS(dt, sr);
|
||||
|
||||
struct lc3_complex buffer[ns/2];
|
||||
struct lc3_complex *z = (struct lc3_complex *)y;
|
||||
union { float *f; struct lc3_complex *z; } u = { .z = buffer };
|
||||
|
||||
imdct_pre_fft(rot, x, z);
|
||||
z = fft(true, z, ns/2, z, u.z);
|
||||
imdct_post_fft(rot, z, u.f, sqrtf(2.f / nf));
|
||||
|
||||
imdct_window(dt, sr, u.f, d, y);
|
||||
}
|
59
3rd-party/lc3-google/src/mdct.h
vendored
Normal file
59
3rd-party/lc3-google/src/mdct.h
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Compute LD-MDCT (Low Delay Modified Discret Cosinus Transform)
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_MDCT_H
|
||||
#define __LC3_MDCT_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Forward MDCT transformation
|
||||
* dt, sr Duration and samplerate (size of the transform)
|
||||
* sr_dst Samplerate destination, scale transforam accordingly
|
||||
* x [-nd..-1] Previous, [0..ns-1] Current samples
|
||||
* y Output `ns` frequency coefficients
|
||||
*
|
||||
* The number of previous samples `nd` accessed on `x` is :
|
||||
* nd: `ns` * 23/30 for 7.5ms frame duration
|
||||
* nd: `ns` * 5/ 8 for 10ms frame duration
|
||||
*/
|
||||
void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_dst, const float *x, float *y);
|
||||
|
||||
/**
|
||||
* Inverse MDCT transformation
|
||||
* dt, sr Duration and samplerate (size of the transform)
|
||||
* sr_src Samplerate source, scale transforam accordingly
|
||||
* x, d Frequency coefficients and delayed buffer
|
||||
* y, d Output `ns` samples and `nd` delayed ones
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_mdct_inverse(enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_srate sr_src, const float *x, float *d, float *y);
|
||||
|
||||
|
||||
#endif /* __LC3_MDCT_H */
|
61
3rd-party/lc3-google/src/plc.c
vendored
Normal file
61
3rd-party/lc3-google/src/plc.c
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "plc.h"
|
||||
|
||||
|
||||
/**
|
||||
* Reset Packet Loss Concealment state
|
||||
*/
|
||||
void lc3_plc_reset(struct lc3_plc_state *plc)
|
||||
{
|
||||
plc->seed = 24607;
|
||||
lc3_plc_suspend(plc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend PLC execution (Good frame received)
|
||||
*/
|
||||
void lc3_plc_suspend(struct lc3_plc_state *plc)
|
||||
{
|
||||
plc->count = 1;
|
||||
plc->alpha = 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesis of a PLC frame
|
||||
*/
|
||||
void lc3_plc_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
struct lc3_plc_state *plc, const float *x, float *y)
|
||||
{
|
||||
uint16_t seed = plc->seed;
|
||||
float alpha = plc->alpha;
|
||||
int ne = LC3_NE(dt, sr);
|
||||
|
||||
alpha *= (plc->count < 4 ? 1.0f :
|
||||
plc->count < 8 ? 0.9f : 0.85f);
|
||||
|
||||
for (int i = 0; i < ne; i++) {
|
||||
seed = (16831 + seed * 12821) & 0xffff;
|
||||
y[i] = alpha * (seed & 0x8000 ? -x[i] : x[i]);
|
||||
}
|
||||
|
||||
plc->seed = seed;
|
||||
plc->alpha = alpha;
|
||||
plc->count++;
|
||||
}
|
57
3rd-party/lc3-google/src/plc.h
vendored
Normal file
57
3rd-party/lc3-google/src/plc.h
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Packet Loss Concealment
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_PLC_H
|
||||
#define __LC3_PLC_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/**
|
||||
* Reset PLC state
|
||||
* plc PLC State to reset
|
||||
*/
|
||||
void lc3_plc_reset(lc3_plc_state_t *plc);
|
||||
|
||||
/**
|
||||
* Suspend PLC synthesis (Error-free frame decoded)
|
||||
* plc PLC State
|
||||
*/
|
||||
void lc3_plc_suspend(lc3_plc_state_t *plc);
|
||||
|
||||
/**
|
||||
* Synthesis of a PLC frame
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* plc PLC State
|
||||
* x Last good spectral coefficients
|
||||
* y Return emulated ones
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_plc_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
lc3_plc_state_t *plc, const float *x, float *y);
|
||||
|
||||
|
||||
#endif /* __LC3_PLC_H */
|
878
3rd-party/lc3-google/src/sns.c
vendored
Normal file
878
3rd-party/lc3-google/src/sns.c
vendored
Normal file
@ -0,0 +1,878 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "sns.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* DCT-16
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Matrix of DCT-16 coefficients
|
||||
*
|
||||
* M[n][k] = 2f cos( Pi k (2n + 1) / 2N )
|
||||
*
|
||||
* k = [0..N-1], n = [0..N-1], N = 16
|
||||
* f = sqrt(1/4N) for k=0, sqrt(1/2N) otherwise
|
||||
*/
|
||||
static const float dct16_m[16][16] = {
|
||||
|
||||
{ 2.50000000e-01, 3.51850934e-01, 3.46759961e-01, 3.38329500e-01,
|
||||
3.26640741e-01, 3.11806253e-01, 2.93968901e-01, 2.73300467e-01,
|
||||
2.50000000e-01, 2.24291897e-01, 1.96423740e-01, 1.66663915e-01,
|
||||
1.35299025e-01, 1.02631132e-01, 6.89748448e-02, 3.46542923e-02 },
|
||||
|
||||
{ 2.50000000e-01, 3.38329500e-01, 2.93968901e-01, 2.24291897e-01,
|
||||
1.35299025e-01, 3.46542923e-02, -6.89748448e-02, -1.66663915e-01,
|
||||
-2.50000000e-01, -3.11806253e-01, -3.46759961e-01, -3.51850934e-01,
|
||||
-3.26640741e-01, -2.73300467e-01, -1.96423740e-01, -1.02631132e-01 },
|
||||
|
||||
{ 2.50000000e-01, 3.11806253e-01, 1.96423740e-01, 3.46542923e-02,
|
||||
-1.35299025e-01, -2.73300467e-01, -3.46759961e-01, -3.38329500e-01,
|
||||
-2.50000000e-01, -1.02631132e-01, 6.89748448e-02, 2.24291897e-01,
|
||||
3.26640741e-01, 3.51850934e-01, 2.93968901e-01, 1.66663915e-01 },
|
||||
|
||||
{ 2.50000000e-01, 2.73300467e-01, 6.89748448e-02, -1.66663915e-01,
|
||||
-3.26640741e-01, -3.38329500e-01, -1.96423740e-01, 3.46542923e-02,
|
||||
2.50000000e-01, 3.51850934e-01, 2.93968901e-01, 1.02631132e-01,
|
||||
-1.35299025e-01, -3.11806253e-01, -3.46759961e-01, -2.24291897e-01 },
|
||||
|
||||
{ 2.50000000e-01, 2.24291897e-01, -6.89748448e-02, -3.11806253e-01,
|
||||
-3.26640741e-01, -1.02631132e-01, 1.96423740e-01, 3.51850934e-01,
|
||||
2.50000000e-01, -3.46542923e-02, -2.93968901e-01, -3.38329500e-01,
|
||||
-1.35299025e-01, 1.66663915e-01, 3.46759961e-01, 2.73300467e-01 },
|
||||
|
||||
{ 2.50000000e-01, 1.66663915e-01, -1.96423740e-01, -3.51850934e-01,
|
||||
-1.35299025e-01, 2.24291897e-01, 3.46759961e-01, 1.02631132e-01,
|
||||
-2.50000000e-01, -3.38329500e-01, -6.89748448e-02, 2.73300467e-01,
|
||||
3.26640741e-01, 3.46542923e-02, -2.93968901e-01, -3.11806253e-01 },
|
||||
|
||||
{ 2.50000000e-01, 1.02631132e-01, -2.93968901e-01, -2.73300467e-01,
|
||||
1.35299025e-01, 3.51850934e-01, 6.89748448e-02, -3.11806253e-01,
|
||||
-2.50000000e-01, 1.66663915e-01, 3.46759961e-01, 3.46542923e-02,
|
||||
-3.26640741e-01, -2.24291897e-01, 1.96423740e-01, 3.38329500e-01 },
|
||||
|
||||
{ 2.50000000e-01, 3.46542923e-02, -3.46759961e-01, -1.02631132e-01,
|
||||
3.26640741e-01, 1.66663915e-01, -2.93968901e-01, -2.24291897e-01,
|
||||
2.50000000e-01, 2.73300467e-01, -1.96423740e-01, -3.11806253e-01,
|
||||
1.35299025e-01, 3.38329500e-01, -6.89748448e-02, -3.51850934e-01 },
|
||||
|
||||
{ 2.50000000e-01, -3.46542923e-02, -3.46759961e-01, 1.02631132e-01,
|
||||
3.26640741e-01, -1.66663915e-01, -2.93968901e-01, 2.24291897e-01,
|
||||
2.50000000e-01, -2.73300467e-01, -1.96423740e-01, 3.11806253e-01,
|
||||
1.35299025e-01, -3.38329500e-01, -6.89748448e-02, 3.51850934e-01 },
|
||||
|
||||
{ 2.50000000e-01, -1.02631132e-01, -2.93968901e-01, 2.73300467e-01,
|
||||
1.35299025e-01, -3.51850934e-01, 6.89748448e-02, 3.11806253e-01,
|
||||
-2.50000000e-01, -1.66663915e-01, 3.46759961e-01, -3.46542923e-02,
|
||||
-3.26640741e-01, 2.24291897e-01, 1.96423740e-01, -3.38329500e-01 },
|
||||
|
||||
{ 2.50000000e-01, -1.66663915e-01, -1.96423740e-01, 3.51850934e-01,
|
||||
-1.35299025e-01, -2.24291897e-01, 3.46759961e-01, -1.02631132e-01,
|
||||
-2.50000000e-01, 3.38329500e-01, -6.89748448e-02, -2.73300467e-01,
|
||||
3.26640741e-01, -3.46542923e-02, -2.93968901e-01, 3.11806253e-01 },
|
||||
|
||||
{ 2.50000000e-01, -2.24291897e-01, -6.89748448e-02, 3.11806253e-01,
|
||||
-3.26640741e-01, 1.02631132e-01, 1.96423740e-01, -3.51850934e-01,
|
||||
2.50000000e-01, 3.46542923e-02, -2.93968901e-01, 3.38329500e-01,
|
||||
-1.35299025e-01, -1.66663915e-01, 3.46759961e-01, -2.73300467e-01 },
|
||||
|
||||
{ 2.50000000e-01, -2.73300467e-01, 6.89748448e-02, 1.66663915e-01,
|
||||
-3.26640741e-01, 3.38329500e-01, -1.96423740e-01, -3.46542923e-02,
|
||||
2.50000000e-01, -3.51850934e-01, 2.93968901e-01, -1.02631132e-01,
|
||||
-1.35299025e-01, 3.11806253e-01, -3.46759961e-01, 2.24291897e-01 },
|
||||
|
||||
{ 2.50000000e-01, -3.11806253e-01, 1.96423740e-01, -3.46542923e-02,
|
||||
-1.35299025e-01, 2.73300467e-01, -3.46759961e-01, 3.38329500e-01,
|
||||
-2.50000000e-01, 1.02631132e-01, 6.89748448e-02, -2.24291897e-01,
|
||||
3.26640741e-01, -3.51850934e-01, 2.93968901e-01, -1.66663915e-01 },
|
||||
|
||||
{ 2.50000000e-01, -3.38329500e-01, 2.93968901e-01, -2.24291897e-01,
|
||||
1.35299025e-01, -3.46542923e-02, -6.89748448e-02, 1.66663915e-01,
|
||||
-2.50000000e-01, 3.11806253e-01, -3.46759961e-01, 3.51850934e-01,
|
||||
-3.26640741e-01, 2.73300467e-01, -1.96423740e-01, 1.02631132e-01 },
|
||||
|
||||
{ 2.50000000e-01, -3.51850934e-01, 3.46759961e-01, -3.38329500e-01,
|
||||
3.26640741e-01, -3.11806253e-01, 2.93968901e-01, -2.73300467e-01,
|
||||
2.50000000e-01, -2.24291897e-01, 1.96423740e-01, -1.66663915e-01,
|
||||
1.35299025e-01, -1.02631132e-01, 6.89748448e-02, -3.46542923e-02 },
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Forward DCT-16 transformation
|
||||
* x, y Input and output 16 values
|
||||
*/
|
||||
static void dct16_forward(const float *x, float *y)
|
||||
{
|
||||
for (int i = 0, j; i < 16; i++)
|
||||
for (y[i] = 0, j = 0; j < 16; j++)
|
||||
y[i] += x[j] * dct16_m[j][i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse DCT-16 transformation
|
||||
* x, y Input and output 16 values
|
||||
*/
|
||||
static void dct16_inverse(const float *x, float *y)
|
||||
{
|
||||
for (int i = 0, j; i < 16; i++)
|
||||
for (y[i] = 0, j = 0; j < 16; j++)
|
||||
y[i] += x[j] * dct16_m[i][j];
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Scale factors
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Scale factors
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* eb Energy estimation per bands
|
||||
* att 1: Attack detected 0: Otherwise
|
||||
* scf Output 16 scale factors
|
||||
*/
|
||||
static void compute_scale_factors(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *eb, bool att, float *scf)
|
||||
{
|
||||
/* Pre-emphasis gain table :
|
||||
* Ge[b] = 10 ^ (b * g_tilt) / 630 , b = [0..63] */
|
||||
|
||||
static const float ge_table[LC3_NUM_SRATE][LC3_NUM_BANDS] = {
|
||||
|
||||
[LC3_SRATE_8K] = { /* g_tilt = 14 */
|
||||
1.00000000e+00, 1.05250029e+00, 1.10775685e+00, 1.16591440e+00,
|
||||
1.22712524e+00, 1.29154967e+00, 1.35935639e+00, 1.43072299e+00,
|
||||
1.50583635e+00, 1.58489319e+00, 1.66810054e+00, 1.75567629e+00,
|
||||
1.84784980e+00, 1.94486244e+00, 2.04696827e+00, 2.15443469e+00,
|
||||
2.26754313e+00, 2.38658979e+00, 2.51188643e+00, 2.64376119e+00,
|
||||
2.78255940e+00, 2.92864456e+00, 3.08239924e+00, 3.24422608e+00,
|
||||
3.41454887e+00, 3.59381366e+00, 3.78248991e+00, 3.98107171e+00,
|
||||
4.19007911e+00, 4.41005945e+00, 4.64158883e+00, 4.88527357e+00,
|
||||
5.14175183e+00, 5.41169527e+00, 5.69581081e+00, 5.99484250e+00,
|
||||
6.30957344e+00, 6.64082785e+00, 6.98947321e+00, 7.35642254e+00,
|
||||
7.74263683e+00, 8.14912747e+00, 8.57695899e+00, 9.02725178e+00,
|
||||
9.50118507e+00, 1.00000000e+01, 1.05250029e+01, 1.10775685e+01,
|
||||
1.16591440e+01, 1.22712524e+01, 1.29154967e+01, 1.35935639e+01,
|
||||
1.43072299e+01, 1.50583635e+01, 1.58489319e+01, 1.66810054e+01,
|
||||
1.75567629e+01, 1.84784980e+01, 1.94486244e+01, 2.04696827e+01,
|
||||
2.15443469e+01, 2.26754313e+01, 2.38658979e+01, 2.51188643e+01 },
|
||||
|
||||
[LC3_SRATE_16K] = { /* g_tilt = 18 */
|
||||
1.00000000e+00, 1.06800043e+00, 1.14062492e+00, 1.21818791e+00,
|
||||
1.30102522e+00, 1.38949549e+00, 1.48398179e+00, 1.58489319e+00,
|
||||
1.69266662e+00, 1.80776868e+00, 1.93069773e+00, 2.06198601e+00,
|
||||
2.20220195e+00, 2.35195264e+00, 2.51188643e+00, 2.68269580e+00,
|
||||
2.86512027e+00, 3.05994969e+00, 3.26802759e+00, 3.49025488e+00,
|
||||
3.72759372e+00, 3.98107171e+00, 4.25178630e+00, 4.54090961e+00,
|
||||
4.84969343e+00, 5.17947468e+00, 5.53168120e+00, 5.90783791e+00,
|
||||
6.30957344e+00, 6.73862717e+00, 7.19685673e+00, 7.68624610e+00,
|
||||
8.20891416e+00, 8.76712387e+00, 9.36329209e+00, 1.00000000e+01,
|
||||
1.06800043e+01, 1.14062492e+01, 1.21818791e+01, 1.30102522e+01,
|
||||
1.38949549e+01, 1.48398179e+01, 1.58489319e+01, 1.69266662e+01,
|
||||
1.80776868e+01, 1.93069773e+01, 2.06198601e+01, 2.20220195e+01,
|
||||
2.35195264e+01, 2.51188643e+01, 2.68269580e+01, 2.86512027e+01,
|
||||
3.05994969e+01, 3.26802759e+01, 3.49025488e+01, 3.72759372e+01,
|
||||
3.98107171e+01, 4.25178630e+01, 4.54090961e+01, 4.84969343e+01,
|
||||
5.17947468e+01, 5.53168120e+01, 5.90783791e+01, 6.30957344e+01 },
|
||||
|
||||
[LC3_SRATE_24K] = { /* g_tilt = 22 */
|
||||
1.00000000e+00, 1.08372885e+00, 1.17446822e+00, 1.27280509e+00,
|
||||
1.37937560e+00, 1.49486913e+00, 1.62003281e+00, 1.75567629e+00,
|
||||
1.90267705e+00, 2.06198601e+00, 2.23463373e+00, 2.42173704e+00,
|
||||
2.62450630e+00, 2.84425319e+00, 3.08239924e+00, 3.34048498e+00,
|
||||
3.62017995e+00, 3.92329345e+00, 4.25178630e+00, 4.60778348e+00,
|
||||
4.99358789e+00, 5.41169527e+00, 5.86481029e+00, 6.35586411e+00,
|
||||
6.88803330e+00, 7.46476041e+00, 8.08977621e+00, 8.76712387e+00,
|
||||
9.50118507e+00, 1.02967084e+01, 1.11588399e+01, 1.20931568e+01,
|
||||
1.31057029e+01, 1.42030283e+01, 1.53922315e+01, 1.66810054e+01,
|
||||
1.80776868e+01, 1.95913107e+01, 2.12316686e+01, 2.30093718e+01,
|
||||
2.49359200e+01, 2.70237760e+01, 2.92864456e+01, 3.17385661e+01,
|
||||
3.43959997e+01, 3.72759372e+01, 4.03970086e+01, 4.37794036e+01,
|
||||
4.74450028e+01, 5.14175183e+01, 5.57226480e+01, 6.03882412e+01,
|
||||
6.54444792e+01, 7.09240702e+01, 7.68624610e+01, 8.32980665e+01,
|
||||
9.02725178e+01, 9.78309319e+01, 1.06022203e+02, 1.14899320e+02,
|
||||
1.24519708e+02, 1.34945600e+02, 1.46244440e+02, 1.58489319e+02 },
|
||||
|
||||
[LC3_SRATE_32K] = { /* g_tilt = 26 */
|
||||
1.00000000e+00, 1.09968890e+00, 1.20931568e+00, 1.32987103e+00,
|
||||
1.46244440e+00, 1.60823388e+00, 1.76855694e+00, 1.94486244e+00,
|
||||
2.13874364e+00, 2.35195264e+00, 2.58641621e+00, 2.84425319e+00,
|
||||
3.12779366e+00, 3.43959997e+00, 3.78248991e+00, 4.15956216e+00,
|
||||
4.57422434e+00, 5.03022373e+00, 5.53168120e+00, 6.08312841e+00,
|
||||
6.68954879e+00, 7.35642254e+00, 8.08977621e+00, 8.89623710e+00,
|
||||
9.78309319e+00, 1.07583590e+01, 1.18308480e+01, 1.30102522e+01,
|
||||
1.43072299e+01, 1.57335019e+01, 1.73019574e+01, 1.90267705e+01,
|
||||
2.09235283e+01, 2.30093718e+01, 2.53031508e+01, 2.78255940e+01,
|
||||
3.05994969e+01, 3.36499270e+01, 3.70044512e+01, 4.06933843e+01,
|
||||
4.47500630e+01, 4.92111475e+01, 5.41169527e+01, 5.95118121e+01,
|
||||
6.54444792e+01, 7.19685673e+01, 7.91430346e+01, 8.70327166e+01,
|
||||
9.57089124e+01, 1.05250029e+02, 1.15742288e+02, 1.27280509e+02,
|
||||
1.39968963e+02, 1.53922315e+02, 1.69266662e+02, 1.86140669e+02,
|
||||
2.04696827e+02, 2.25102829e+02, 2.47543082e+02, 2.72220379e+02,
|
||||
2.99357729e+02, 3.29200372e+02, 3.62017995e+02, 3.98107171e+02 },
|
||||
|
||||
[LC3_SRATE_48K] = { /* g_tilt = 30 */
|
||||
1.00000000e+00, 1.11588399e+00, 1.24519708e+00, 1.38949549e+00,
|
||||
1.55051578e+00, 1.73019574e+00, 1.93069773e+00, 2.15443469e+00,
|
||||
2.40409918e+00, 2.68269580e+00, 2.99357729e+00, 3.34048498e+00,
|
||||
3.72759372e+00, 4.15956216e+00, 4.64158883e+00, 5.17947468e+00,
|
||||
5.77969288e+00, 6.44946677e+00, 7.19685673e+00, 8.03085722e+00,
|
||||
8.96150502e+00, 1.00000000e+01, 1.11588399e+01, 1.24519708e+01,
|
||||
1.38949549e+01, 1.55051578e+01, 1.73019574e+01, 1.93069773e+01,
|
||||
2.15443469e+01, 2.40409918e+01, 2.68269580e+01, 2.99357729e+01,
|
||||
3.34048498e+01, 3.72759372e+01, 4.15956216e+01, 4.64158883e+01,
|
||||
5.17947468e+01, 5.77969288e+01, 6.44946677e+01, 7.19685673e+01,
|
||||
8.03085722e+01, 8.96150502e+01, 1.00000000e+02, 1.11588399e+02,
|
||||
1.24519708e+02, 1.38949549e+02, 1.55051578e+02, 1.73019574e+02,
|
||||
1.93069773e+02, 2.15443469e+02, 2.40409918e+02, 2.68269580e+02,
|
||||
2.99357729e+02, 3.34048498e+02, 3.72759372e+02, 4.15956216e+02,
|
||||
4.64158883e+02, 5.17947468e+02, 5.77969288e+02, 6.44946677e+02,
|
||||
7.19685673e+02, 8.03085722e+02, 8.96150502e+02, 1.00000000e+03 },
|
||||
};
|
||||
|
||||
float e[LC3_NUM_BANDS];
|
||||
|
||||
/* --- Copy and padding --- */
|
||||
|
||||
int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
|
||||
int n2 = LC3_NUM_BANDS - nb;
|
||||
|
||||
for (int i2 = 0; i2 < n2; i2++)
|
||||
e[2*i2 + 0] = e[2*i2 + 1] = eb[i2];
|
||||
|
||||
memcpy(e + 2*n2, eb + n2, (nb - n2) * sizeof(float));
|
||||
|
||||
/* --- Smoothing, pre-emphasis and logarithm --- */
|
||||
|
||||
const float *ge = ge_table[sr];
|
||||
|
||||
float e0 = e[0], e1 = e[0], e2;
|
||||
float e_sum = 0;
|
||||
|
||||
for (int i = 0; i < LC3_NUM_BANDS-1; ) {
|
||||
e[i] = (e0 * 0.25 + e1 * 0.5 + (e2 = e[i+1]) * 0.25) * ge[i];
|
||||
e_sum += e[i++];
|
||||
|
||||
e[i] = (e1 * 0.25 + e2 * 0.5 + (e0 = e[i+1]) * 0.25) * ge[i];
|
||||
e_sum += e[i++];
|
||||
|
||||
e[i] = (e2 * 0.25 + e0 * 0.5 + (e1 = e[i+1]) * 0.25) * ge[i];
|
||||
e_sum += e[i++];
|
||||
}
|
||||
|
||||
e[LC3_NUM_BANDS-1] = (e0 * 0.25 + e1 * 0.75) * ge[LC3_NUM_BANDS-1];
|
||||
e_sum += e[LC3_NUM_BANDS-1];
|
||||
|
||||
float noise_floor = fmaxf(e_sum * (1e-4 / 64), 0x1p-32);
|
||||
|
||||
for (int i = 0; i < LC3_NUM_BANDS; i++)
|
||||
e[i] = log2f(fmaxf(e[i], noise_floor)) * 0.5;
|
||||
|
||||
/* --- Grouping & scaling --- */
|
||||
|
||||
float scf_sum;
|
||||
|
||||
scf[0] = (e[0] + e[4]) * 1./12 +
|
||||
(e[0] + e[3]) * 2./12 +
|
||||
(e[1] + e[2]) * 3./12 ;
|
||||
scf_sum = scf[0];
|
||||
|
||||
for (int i = 1; i < 15; i++) {
|
||||
scf[i] = (e[4*i-1] + e[4*i+4]) * 1./12 +
|
||||
(e[4*i ] + e[4*i+3]) * 2./12 +
|
||||
(e[4*i+1] + e[4*i+2]) * 3./12 ;
|
||||
scf_sum += scf[i];
|
||||
}
|
||||
|
||||
scf[15] = (e[59] + e[63]) * 1./12 +
|
||||
(e[60] + e[63]) * 2./12 +
|
||||
(e[61] + e[62]) * 3./12 ;
|
||||
scf_sum += scf[15];
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
scf[i] = 0.85 * (scf[i] - scf_sum * 1./16);
|
||||
|
||||
/* --- Attack handling --- */
|
||||
|
||||
if (!att)
|
||||
return;
|
||||
|
||||
float s0, s1 = scf[0], s2 = scf[1], s3 = scf[2], s4 = scf[3];
|
||||
float sn = s1 + s2;
|
||||
|
||||
scf[0] = (sn += s3) * 1./3;
|
||||
scf[1] = (sn += s4) * 1./4;
|
||||
scf_sum = scf[0] + scf[1];
|
||||
|
||||
for (int i = 2; i < 14; i++, sn -= s0) {
|
||||
s0 = s1, s1 = s2, s2 = s3, s3 = s4, s4 = scf[i+2];
|
||||
scf[i] = (sn += s4) * 1./5;
|
||||
scf_sum += scf[i];
|
||||
}
|
||||
|
||||
scf[14] = (sn ) * 1./4;
|
||||
scf[15] = (sn -= s1) * 1./3;
|
||||
scf_sum += scf[14] + scf[15];
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
scf[i] = (dt == LC3_DT_7M5 ? 0.3 : 0.5) *
|
||||
(scf[i] - scf_sum * 1./16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Codebooks
|
||||
* scf Input 16 scale factors
|
||||
* lf/hfcb_idx Output the low and high frequency codebooks index
|
||||
*/
|
||||
static void resolve_codebooks(const float *scf, int *lfcb_idx, int *hfcb_idx)
|
||||
{
|
||||
float dlfcb_max = 0, dhfcb_max = 0;
|
||||
*lfcb_idx = *hfcb_idx = 0;
|
||||
|
||||
for (int icb = 0; icb < 32; icb++) {
|
||||
const float *lfcb = lc3_sns_lfcb[icb];
|
||||
const float *hfcb = lc3_sns_hfcb[icb];
|
||||
float dlfcb = 0, dhfcb = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
dlfcb += (scf[ i] - lfcb[i]) * (scf[ i] - lfcb[i]);
|
||||
dhfcb += (scf[8+i] - hfcb[i]) * (scf[8+i] - hfcb[i]);
|
||||
}
|
||||
|
||||
if (icb == 0 || dlfcb < dlfcb_max)
|
||||
*lfcb_idx = icb, dlfcb_max = dlfcb;
|
||||
|
||||
if (icb == 0 || dhfcb < dhfcb_max)
|
||||
*hfcb_idx = icb, dhfcb_max = dhfcb;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit energy normalize pulse configuration
|
||||
* c Pulse configuration
|
||||
* cn Normalized pulse configuration
|
||||
*/
|
||||
static void normalize(const int *c, float *cn)
|
||||
{
|
||||
int c2_sum = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
c2_sum += c[i] * c[i];
|
||||
|
||||
float c_norm = 1.f / sqrtf(c2_sum);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
cn[i] = c[i] * c_norm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-procedure of `quantize()`, add unit pulse
|
||||
* x, y, n Transformed residual, and vector of pulses with length
|
||||
* start, end Current number of pulses, limit to reach
|
||||
* corr, energy Correlation (x,y) and y energy, updated at output
|
||||
*/
|
||||
static void add_pulse(const float *x, int *y, int n,
|
||||
int start, int end, float *corr, float *energy)
|
||||
{
|
||||
for (int k = start; k < end; k++) {
|
||||
float best_c2 = (*corr + x[0]) * (*corr + x[0]);
|
||||
float best_e = *energy + 2*y[0] + 1;
|
||||
int nbest = 0;
|
||||
|
||||
for (int i = 1; i < n; i++) {
|
||||
float c2 = (*corr + x[i]) * (*corr + x[i]);
|
||||
float e = *energy + 2*y[i] + 1;
|
||||
|
||||
if (c2 * best_e > e * best_c2)
|
||||
best_c2 = c2, best_e = e, nbest = i;
|
||||
}
|
||||
|
||||
*corr += x[nbest];
|
||||
*energy += 2*y[nbest] + 1;
|
||||
y[nbest]++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantization of codebooks residual
|
||||
* scf Input 16 scale factors, output quantized version
|
||||
* lf/hfcb_idx Codebooks index
|
||||
* c, cn Output 4 pulse configurations candidates, normalized
|
||||
* shape/gain_idx Output selected shape/gain indexes
|
||||
*/
|
||||
static void quantize(const float *scf, int lfcb_idx, int hfcb_idx,
|
||||
int (*c)[16], float (*cn)[16], int *shape_idx, int *gain_idx)
|
||||
{
|
||||
/* --- Residual --- */
|
||||
|
||||
const float *lfcb = lc3_sns_lfcb[lfcb_idx];
|
||||
const float *hfcb = lc3_sns_hfcb[hfcb_idx];
|
||||
float r[16], x[16];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
r[ i] = scf[ i] - lfcb[i];
|
||||
r[8+i] = scf[8+i] - hfcb[i];
|
||||
}
|
||||
|
||||
dct16_forward(r, x);
|
||||
|
||||
/* --- Shape 3 candidate ---
|
||||
* Project to or below pyramid N = 16, K = 6,
|
||||
* then add unit pulses until you reach K = 6, over N = 16 */
|
||||
|
||||
float xm[16];
|
||||
float xm_sum = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
xm[i] = fabsf(x[i]);
|
||||
xm_sum += xm[i];
|
||||
}
|
||||
|
||||
float proj_factor = (6 - 1) / fmaxf(xm_sum, 1e-31);
|
||||
float corr = 0, energy = 0;
|
||||
int npulses = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
c[3][i] = floorf(xm[i] * proj_factor);
|
||||
npulses += c[3][i];
|
||||
corr += c[3][i] * xm[i];
|
||||
energy += c[3][i] * c[3][i];
|
||||
}
|
||||
|
||||
add_pulse(xm, c[3], 16, npulses, 6, &corr, &energy);
|
||||
npulses = 6;
|
||||
|
||||
/* --- Shape 2 candidate ---
|
||||
* Add unit pulses until you reach K = 8 on shape 3 */
|
||||
|
||||
memcpy(c[2], c[3], sizeof(c[2]));
|
||||
|
||||
add_pulse(xm, c[2], 16, npulses, 8, &corr, &energy);
|
||||
npulses = 8;
|
||||
|
||||
/* --- Shape 1 candidate ---
|
||||
* Remove any unit pulses from shape 2 that are not part of 0 to 9
|
||||
* Update energy and correlation terms accordingly
|
||||
* Add unit pulses until you reach K = 10, over N = 10 */
|
||||
|
||||
memcpy(c[1], c[2], sizeof(c[1]));
|
||||
|
||||
for (int i = 10; i < 16; i++) {
|
||||
c[1][i] = 0;
|
||||
npulses -= c[2][i];
|
||||
corr -= c[2][i] * xm[i];
|
||||
energy -= c[2][i] * c[2][i];
|
||||
}
|
||||
|
||||
add_pulse(xm, c[1], 10, npulses, 10, &corr, &energy);
|
||||
npulses = 10;
|
||||
|
||||
/* --- Shape 0 candidate ---
|
||||
* Add unit pulses until you reach K = 1, on shape 1 */
|
||||
|
||||
memcpy(c[0], c[1], sizeof(c[0]));
|
||||
|
||||
add_pulse(xm + 10, c[0] + 10, 6, 0, 1, &corr, &energy);
|
||||
|
||||
/* --- Add sign and unit energy normalize --- */
|
||||
|
||||
for (int j = 0; j < 16; j++)
|
||||
for (int i = 0; i < 4; i++)
|
||||
c[i][j] = x[j] < 0 ? -c[i][j] : c[i][j];
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
normalize(c[i], cn[i]);
|
||||
|
||||
/* --- Determe shape & gain index ---
|
||||
* Search the Mean Square Error, within (shape, gain) combinations */
|
||||
|
||||
float mse_min = INFINITY;
|
||||
*shape_idx = *gain_idx = 0;
|
||||
|
||||
for (int ic = 0; ic < 4; ic++) {
|
||||
const struct lc3_sns_vq_gains *cgains = lc3_sns_vq_gains + ic;
|
||||
float cmse_min = INFINITY;
|
||||
int cgain_idx = 0;
|
||||
|
||||
for (int ig = 0; ig < cgains->count; ig++) {
|
||||
float g = cgains->v[ig];
|
||||
|
||||
float mse = 0;
|
||||
for (int i = 0; i < 16; i++)
|
||||
mse += (x[i] - g * cn[ic][i]) * (x[i] - g * cn[ic][i]);
|
||||
|
||||
if (mse < cmse_min) {
|
||||
cgain_idx = ig,
|
||||
cmse_min = mse;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmse_min < mse_min) {
|
||||
*shape_idx = ic, *gain_idx = cgain_idx;
|
||||
mse_min = cmse_min;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquantization of codebooks residual
|
||||
* lf/hfcb_idx Low and high frequency codebooks index
|
||||
* c Table of normalized pulse configuration
|
||||
* shape/gain Selected shape/gain indexes
|
||||
* scf Return unquantized scale factors
|
||||
*/
|
||||
static void unquantize(int lfcb_idx, int hfcb_idx,
|
||||
const float *c, int shape, int gain, float *scf)
|
||||
{
|
||||
const float *lfcb = lc3_sns_lfcb[lfcb_idx];
|
||||
const float *hfcb = lc3_sns_hfcb[hfcb_idx];
|
||||
float g = lc3_sns_vq_gains[shape].v[gain];
|
||||
|
||||
dct16_inverse(c, scf);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
scf[i] = lfcb[i] + g * scf[i];
|
||||
|
||||
for (int i = 8; i < 16; i++)
|
||||
scf[i] = hfcb[i-8] + g * scf[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-procedure of `sns_enumerate()`, enumeration of a vector
|
||||
* c, n Table of pulse configuration, and length
|
||||
* idx, ls Return enumeration set
|
||||
*/
|
||||
static void enum_mvpq(const int *c, int n, int *idx, bool *ls)
|
||||
{
|
||||
int ci, i, j;
|
||||
|
||||
/* --- Scan for 1st significant coeff --- */
|
||||
|
||||
for (i = 0, c += n; (ci = *(--c)) == 0 ; i++);
|
||||
|
||||
*idx = 0;
|
||||
*ls = ci < 0;
|
||||
|
||||
/* --- Scan remaining coefficients --- */
|
||||
|
||||
for (i++, j = LC3_ABS(ci); i < n; i++, j += LC3_ABS(ci)) {
|
||||
|
||||
if ((ci = *(--c)) != 0) {
|
||||
*idx = (*idx << 1) | *ls;
|
||||
*ls = ci < 0;
|
||||
}
|
||||
|
||||
*idx += lc3_sns_mpvq_offsets[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-procedure of `sns_deenumerate()`, deenumeration of a vector
|
||||
* idx, ls Enumeration set
|
||||
* npulses Number of pulses in the set
|
||||
* c, n Table of pulses configuration, and length
|
||||
*/
|
||||
static void deenum_mvpq(int idx, bool ls, int npulses, int *c, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* --- Scan for coefficients --- */
|
||||
|
||||
for (i = n-1; i >= 0 && idx; i--) {
|
||||
|
||||
int ci = 0;
|
||||
|
||||
for (ci = 0; idx < lc3_sns_mpvq_offsets[i][npulses - ci]; ci++);
|
||||
idx -= lc3_sns_mpvq_offsets[i][npulses - ci];
|
||||
|
||||
*(c++) = ls ? -ci : ci;
|
||||
npulses -= ci;
|
||||
if (ci > 0) {
|
||||
ls = idx & 1;
|
||||
idx >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Set last significant --- */
|
||||
|
||||
int ci = npulses;
|
||||
|
||||
if (i-- >= 0)
|
||||
*(c++) = ls ? -ci : ci;
|
||||
|
||||
while (i-- >= 0)
|
||||
*(c++) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* SNS Enumeration of PVQ configuration
|
||||
* shape Selected shape index
|
||||
* c Selected pulse configuration
|
||||
* idx_a, ls_a Return enumeration set A
|
||||
* idx_b, ls_b Return enumeration set B (shape = 0)
|
||||
*/
|
||||
static void enumerate(int shape, const int *c,
|
||||
int *idx_a, bool *ls_a, int *idx_b, bool *ls_b)
|
||||
{
|
||||
enum_mvpq(c, shape < 2 ? 10 : 16, idx_a, ls_a);
|
||||
|
||||
if (shape == 0)
|
||||
enum_mvpq(c + 10, 6, idx_b, ls_b);
|
||||
}
|
||||
|
||||
/**
|
||||
* SNS Deenumeration of PVQ configuration
|
||||
* shape Selected shape index
|
||||
* idx_a, ls_a enumeration set A
|
||||
* idx_b, ls_b enumeration set B (shape = 0)
|
||||
* c Return pulse configuration
|
||||
*/
|
||||
static void deenumerate(int shape,
|
||||
int idx_a, bool ls_a, int idx_b, bool ls_b, int *c)
|
||||
{
|
||||
int npulses_a = (const int []){ 10, 10, 8, 6 }[shape];
|
||||
|
||||
deenum_mvpq(idx_a, ls_a, npulses_a, c, shape < 2 ? 10 : 16);
|
||||
|
||||
if (shape == 0)
|
||||
deenum_mvpq(idx_b, ls_b, 1, c + 10, 6);
|
||||
else if (shape == 1)
|
||||
memset(c + 10, 0, 6 * sizeof(*c));
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Filtering
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Spectral shaping
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* scf_q Quantized scale factors
|
||||
* inv True on inverse shaping, False otherwise
|
||||
* x Spectral coefficients
|
||||
* y Return shapped coefficients
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
static void spectral_shaping(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *scf_q, bool inv, const float *x, float *y)
|
||||
{
|
||||
/* --- Interpolate scale factors --- */
|
||||
|
||||
float scf[LC3_NUM_BANDS];
|
||||
float s0, s1 = inv ? -scf_q[0] : scf_q[0];
|
||||
|
||||
scf[0] = scf[1] = s1;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
s0 = s1, s1 = inv ? -scf_q[i+1] : scf_q[i+1];
|
||||
scf[4*i+2] = s0 + 0.125 * (s1 - s0);
|
||||
scf[4*i+3] = s0 + 0.375 * (s1 - s0);
|
||||
scf[4*i+4] = s0 + 0.625 * (s1 - s0);
|
||||
scf[4*i+5] = s0 + 0.875 * (s1 - s0);
|
||||
}
|
||||
scf[62] = s1 + 0.125 * (s1 - s0);
|
||||
scf[63] = s1 + 0.375 * (s1 - s0);
|
||||
|
||||
int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
|
||||
int n2 = LC3_NUM_BANDS - nb;
|
||||
|
||||
for (int i2 = 0; i2 < n2; i2++)
|
||||
scf[i2] = 0.5 * (scf[2*i2] + scf[2*i2+1]);
|
||||
|
||||
if (n2 > 0)
|
||||
memmove(scf + n2, scf + 2*n2, (nb - n2) * sizeof(float));
|
||||
|
||||
/* --- Spectral shaping --- */
|
||||
|
||||
const int *lim = lc3_band_lim[dt][sr];
|
||||
|
||||
for (int i = 0, ib = 0; ib < nb; ib++) {
|
||||
float g_sns = powf(2, -scf[ib]);
|
||||
|
||||
for ( ; i < lim[ib+1]; i++)
|
||||
y[i] = x[i] * g_sns;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Interface
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* SNS analysis
|
||||
*/
|
||||
void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *eb, bool att, struct lc3_sns_data *data,
|
||||
const float *x, float *y)
|
||||
{
|
||||
/* Processing steps :
|
||||
* - Determine 16 scale factors from bands energy estimation
|
||||
* - Get codebooks indexes that match thoses scale factors
|
||||
* - Quantize the residual with the selected codebook
|
||||
* - The pulse configuration `c[]` is enumerated
|
||||
* - Finally shape the spectrum coefficients accordingly */
|
||||
|
||||
float scf[16], cn[4][16];
|
||||
int c[4][16];
|
||||
|
||||
compute_scale_factors(dt, sr, eb, att, scf);
|
||||
|
||||
resolve_codebooks(scf, &data->lfcb, &data->hfcb);
|
||||
|
||||
quantize(scf, data->lfcb, data->hfcb,
|
||||
c, cn, &data->shape, &data->gain);
|
||||
|
||||
unquantize(data->lfcb, data->hfcb,
|
||||
cn[data->shape], data->shape, data->gain, scf);
|
||||
|
||||
enumerate(data->shape, c[data->shape],
|
||||
&data->idx_a, &data->ls_a, &data->idx_b, &data->ls_b);
|
||||
|
||||
spectral_shaping(dt, sr, scf, false, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* SNS synthesis
|
||||
*/
|
||||
void lc3_sns_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const lc3_sns_data_t *data, const float *x, float *y)
|
||||
{
|
||||
float scf[16], cn[16];
|
||||
int c[16];
|
||||
|
||||
deenumerate(data->shape,
|
||||
data->idx_a, data->ls_a, data->idx_b, data->ls_b, c);
|
||||
|
||||
normalize(c, cn);
|
||||
|
||||
unquantize(data->lfcb, data->hfcb, cn, data->shape, data->gain, scf);
|
||||
|
||||
spectral_shaping(dt, sr, scf, true, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of bits coding the bitstream data
|
||||
*/
|
||||
int lc3_sns_get_nbits(void)
|
||||
{
|
||||
return 38;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put bitstream data
|
||||
*/
|
||||
void lc3_sns_put_data(lc3_bits_t *bits, const struct lc3_sns_data *data)
|
||||
{
|
||||
/* --- Codebooks --- */
|
||||
|
||||
lc3_put_bits(bits, data->lfcb, 5);
|
||||
lc3_put_bits(bits, data->hfcb, 5);
|
||||
|
||||
/* --- Shape, gain and vectors --- *
|
||||
* Write MSB bit of shape index, next LSB bits of shape and gain,
|
||||
* and MVPQ vectors indexes are muxed */
|
||||
|
||||
int shape_msb = data->shape >> 1;
|
||||
lc3_put_bit(bits, shape_msb);
|
||||
|
||||
if (shape_msb == 0) {
|
||||
const int size_a = 2390004;
|
||||
int submode = data->shape & 1;
|
||||
|
||||
int mux_high = submode == 0 ?
|
||||
2 * (data->idx_b + 1) + data->ls_b : data->gain & 1;
|
||||
int mux_code = mux_high * size_a + data->idx_a;
|
||||
|
||||
lc3_put_bits(bits, data->gain >> submode, 1);
|
||||
lc3_put_bits(bits, data->ls_a, 1);
|
||||
lc3_put_bits(bits, mux_code, 25);
|
||||
|
||||
} else {
|
||||
const int size_a = 15158272;
|
||||
int submode = data->shape & 1;
|
||||
|
||||
int mux_code = submode == 0 ?
|
||||
data->idx_a : size_a + 2 * data->idx_a + (data->gain & 1);
|
||||
|
||||
lc3_put_bits(bits, data->gain >> submode, 2);
|
||||
lc3_put_bits(bits, data->ls_a, 1);
|
||||
lc3_put_bits(bits, mux_code, 24);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bitstream data
|
||||
*/
|
||||
int lc3_sns_get_data(lc3_bits_t *bits, struct lc3_sns_data *data)
|
||||
{
|
||||
/* --- Codebooks --- */
|
||||
|
||||
*data = (struct lc3_sns_data){
|
||||
.lfcb = lc3_get_bits(bits, 5),
|
||||
.hfcb = lc3_get_bits(bits, 5)
|
||||
};
|
||||
|
||||
/* --- Shape, gain and vectors --- */
|
||||
|
||||
int shape_msb = lc3_get_bit(bits);
|
||||
data->gain = lc3_get_bits(bits, 1 + shape_msb);
|
||||
data->ls_a = lc3_get_bit(bits);
|
||||
|
||||
int mux_code = lc3_get_bits(bits, 25 - shape_msb);
|
||||
|
||||
if (shape_msb == 0) {
|
||||
const int size_a = 2390004;
|
||||
|
||||
if (mux_code >= size_a * 14)
|
||||
return -1;
|
||||
|
||||
data->idx_a = mux_code % size_a;
|
||||
mux_code = mux_code / size_a;
|
||||
|
||||
data->shape = (mux_code < 2);
|
||||
|
||||
if (data->shape == 0) {
|
||||
data->idx_b = (mux_code - 2) / 2;
|
||||
data->ls_b = (mux_code - 2) % 2;
|
||||
} else {
|
||||
data->gain = (data->gain << 1) + (mux_code % 2);
|
||||
}
|
||||
|
||||
} else {
|
||||
const int size_a = 15158272;
|
||||
|
||||
if (mux_code >= size_a + 1549824)
|
||||
return -1;
|
||||
|
||||
data->shape = 2 + (mux_code >= size_a);
|
||||
if (data->shape == 2) {
|
||||
data->idx_a = mux_code;
|
||||
} else {
|
||||
mux_code -= size_a;
|
||||
data->idx_a = mux_code / 2;
|
||||
data->gain = (data->gain << 1) + (mux_code % 2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
103
3rd-party/lc3-google/src/sns.h
vendored
Normal file
103
3rd-party/lc3-google/src/sns.h
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Spectral Noise Shaping
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_SNS_H
|
||||
#define __LC3_SNS_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
/**
|
||||
* Bitstream data
|
||||
*/
|
||||
|
||||
typedef struct lc3_sns_data {
|
||||
int lfcb, hfcb;
|
||||
int shape, gain;
|
||||
int idx_a, idx_b;
|
||||
bool ls_a, ls_b;
|
||||
} lc3_sns_data_t;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Encoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* SNS analysis
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* eb Energy estimation per bands, and count of bands
|
||||
* att 1: Attack detected 0: Otherwise
|
||||
* data Return bitstream data
|
||||
* x Spectral coefficients
|
||||
* y Return shapped coefficients
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_sns_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const float *eb, bool att, lc3_sns_data_t *data,
|
||||
const float *x, float *y);
|
||||
|
||||
/**
|
||||
* Return number of bits coding the bitstream data
|
||||
* return Bit consumption
|
||||
*/
|
||||
int lc3_sns_get_nbits(void);
|
||||
|
||||
/**
|
||||
* Put bitstream data
|
||||
* bits Bitstream context
|
||||
* data Bitstream data
|
||||
*/
|
||||
void lc3_sns_put_data(lc3_bits_t *bits, const lc3_sns_data_t *data);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Decoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get bitstream data
|
||||
* bits Bitstream context
|
||||
* data Return SNS data
|
||||
* return 0: Ok -1: Invalid SNS data
|
||||
*/
|
||||
int lc3_sns_get_data(lc3_bits_t *bits, lc3_sns_data_t *data);
|
||||
|
||||
/**
|
||||
* SNS synthesis
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* data Bitstream data
|
||||
* x Spectral coefficients
|
||||
* y Return shapped coefficients
|
||||
*
|
||||
* `x` and `y` can be the same buffer
|
||||
*/
|
||||
void lc3_sns_synthesize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
const lc3_sns_data_t *data, const float *x, float *y);
|
||||
|
||||
|
||||
#endif /* __LC3_SNS_H */
|
877
3rd-party/lc3-google/src/spec.c
vendored
Normal file
877
3rd-party/lc3-google/src/spec.c
vendored
Normal file
@ -0,0 +1,877 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "spec.h"
|
||||
#include "bits.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Global Gain / Quantization
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resolve quantized gain index offset
|
||||
* sr, nbytes Samplerate and size of the frame
|
||||
* return Gain index offset
|
||||
*/
|
||||
static int resolve_gain_offset(enum lc3_srate sr, int nbytes)
|
||||
{
|
||||
int g_off = (nbytes * 8) / (10 * (1 + sr));
|
||||
return 105 + 5*(1 + sr) + LC3_MIN(g_off, 115);
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Gain Estimation
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* x Spectral coefficients
|
||||
* nbits_budget Number of bits available coding the spectrum
|
||||
* nbits_off Offset on the available bits, temporarily smoothed
|
||||
* g_off Gain index offset
|
||||
* reset_off Return True when the nbits_off must be reset
|
||||
* return The quantized gain value
|
||||
*/
|
||||
static int estimate_gain(
|
||||
enum lc3_dt dt, enum lc3_srate sr, const float *x,
|
||||
int nbits_budget, float nbits_off, int g_off, bool *reset_off)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr) >> 2;
|
||||
float e[ne];
|
||||
|
||||
/* --- Energy (dB) by 4 NDCT blocks ---
|
||||
* For the next steps, add energy offset 28/20 dB,
|
||||
* and compute the maximum magnitude */
|
||||
|
||||
float x_max = 0;
|
||||
|
||||
for (int i = 0; i < ne; i++, x += 4) {
|
||||
float x0 = fabsf(x[0]), x1 = fabsf(x[1]);
|
||||
float x2 = fabsf(x[2]), x3 = fabsf(x[3]);
|
||||
|
||||
x_max = fmaxf(x_max, x0);
|
||||
x_max = fmaxf(x_max, x1);
|
||||
x_max = fmaxf(x_max, x2);
|
||||
x_max = fmaxf(x_max, x3);
|
||||
|
||||
float s2 = x0*x0 + x1*x1 + x2*x2 + x3*x3;
|
||||
e[i] = 28.f/20 * 10 * (s2 > 0 ? log10f(s2) : -10);
|
||||
}
|
||||
|
||||
/* --- Determine gain index --- */
|
||||
|
||||
int nbits = nbits_budget + nbits_off + 0.5f;
|
||||
int g_int = 255 - g_off;
|
||||
|
||||
for (int i = 128; i > 0; i >>= 1) {
|
||||
const float *e_ptr = e + ne-1;
|
||||
float v = 0;
|
||||
|
||||
g_int -= i;
|
||||
|
||||
for ( ; e_ptr >= e && *e_ptr < g_int; e_ptr--);
|
||||
|
||||
while (e_ptr >= e) {
|
||||
float e_diff = *(e_ptr--) - g_int;
|
||||
|
||||
if (e_diff < 0) {
|
||||
v += 2.7f * 28.f/20;
|
||||
} else {
|
||||
v += e_diff + 7 * 28.f/20;
|
||||
if (e_diff > 43 * 28.f/20)
|
||||
v += e_diff - 43 * 28.f/20;
|
||||
}
|
||||
}
|
||||
|
||||
if (v > nbits * 1.4 * 28./20)
|
||||
g_int += i;
|
||||
}
|
||||
|
||||
/* --- Limit gain index --- */
|
||||
|
||||
int g_min = x_max == 0 ? -g_off :
|
||||
ceilf(28 * log10f(x_max / (32768 - 0.375f)));
|
||||
|
||||
*reset_off = g_int < g_min || x_max == 0;
|
||||
if (*reset_off)
|
||||
g_int = g_min;
|
||||
|
||||
return g_int;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Gain Adjustment
|
||||
* sr Samplerate of the frame
|
||||
* g_idx The estimated quantized gain index
|
||||
* nbits Computed number of bits coding the spectrum
|
||||
* nbits_budget Number of bits available for coding the spectrum
|
||||
* return Gain adjust value (-1 to 2)
|
||||
*/
|
||||
static int adjust_gain(enum lc3_srate sr,
|
||||
int g_idx, int nbits, int nbits_budget)
|
||||
{
|
||||
/* --- Compute delta threshold --- */
|
||||
|
||||
const int *t = (const int [LC3_NUM_SRATE][3]){
|
||||
{ 80, 500, 850 }, { 230, 1025, 1700 }, { 380, 1550, 2550 },
|
||||
{ 530, 2075, 3400 }, { 680, 2600, 4250 }
|
||||
}[sr];
|
||||
|
||||
int delta, den = 48;
|
||||
|
||||
if (nbits < t[0]) {
|
||||
delta = 3*(nbits + 48);
|
||||
|
||||
} else if (nbits < t[1]) {
|
||||
int n0 = 3*(t[0] + 48), range = t[1] - t[0];
|
||||
delta = n0 * range + (nbits - t[0]) * (t[1] - n0);
|
||||
den *= range;
|
||||
|
||||
} else {
|
||||
delta = LC3_MIN(nbits, t[2]);
|
||||
}
|
||||
|
||||
delta = (delta + den/2) / den;
|
||||
|
||||
/* --- Adjust gain --- */
|
||||
|
||||
if (nbits < nbits_budget - (delta + 2))
|
||||
return -(g_idx > 0);
|
||||
|
||||
if (nbits > nbits_budget)
|
||||
return (g_idx < 255) + (g_idx < 254 && nbits >= nbits_budget + delta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquantize gain
|
||||
* g_int Quantization gain value
|
||||
* return Unquantized gain value
|
||||
*/
|
||||
static float unquantize_gain(int g_int)
|
||||
{
|
||||
/* Unquantization gain table :
|
||||
* G[i] = 10 ^ (i / 28) , i = [0..64] */
|
||||
|
||||
static const float iq_table[] = {
|
||||
1.00000000e+00, 1.08571112e+00, 1.17876863e+00, 1.27980221e+00,
|
||||
1.38949549e+00, 1.50859071e+00, 1.63789371e+00, 1.77827941e+00,
|
||||
1.93069773e+00, 2.09617999e+00, 2.27584593e+00, 2.47091123e+00,
|
||||
2.68269580e+00, 2.91263265e+00, 3.16227766e+00, 3.43332002e+00,
|
||||
3.72759372e+00, 4.04708995e+00, 4.39397056e+00, 4.77058270e+00,
|
||||
5.17947468e+00, 5.62341325e+00, 6.10540230e+00, 6.62870316e+00,
|
||||
7.19685673e+00, 7.81370738e+00, 8.48342898e+00, 9.21055318e+00,
|
||||
1.00000000e+01, 1.08571112e+01, 1.17876863e+01, 1.27980221e+01,
|
||||
1.38949549e+01, 1.50859071e+01, 1.63789371e+01, 1.77827941e+01,
|
||||
1.93069773e+01, 2.09617999e+01, 2.27584593e+01, 2.47091123e+01,
|
||||
2.68269580e+01, 2.91263265e+01, 3.16227766e+01, 3.43332002e+01,
|
||||
3.72759372e+01, 4.04708995e+01, 4.39397056e+01, 4.77058270e+01,
|
||||
5.17947468e+01, 5.62341325e+01, 6.10540230e+01, 6.62870316e+01,
|
||||
7.19685673e+01, 7.81370738e+01, 8.48342898e+01, 9.21055318e+01,
|
||||
1.00000000e+02, 1.08571112e+02, 1.17876863e+02, 1.27980221e+02,
|
||||
1.38949549e+02, 1.50859071e+02, 1.63789371e+02, 1.77827941e+02,
|
||||
1.93069773e+02
|
||||
};
|
||||
|
||||
float g = iq_table[LC3_ABS(g_int) & 0x3f];
|
||||
for(int n64 = LC3_ABS(g_int) >> 6; n64--; )
|
||||
g *= iq_table[64];
|
||||
|
||||
return g_int >= 0 ? g : 1 / g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spectrum quantization
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* g_int Quantization gain value
|
||||
* x Spectral coefficients, scaled as output
|
||||
* xq, nq Output spectral quantized coefficients, and count
|
||||
*/
|
||||
static void quantize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int g_int, float *x, int16_t *xq, int *nq)
|
||||
{
|
||||
float g_inv = 1 / unquantize_gain(g_int);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
|
||||
*nq = ne;
|
||||
|
||||
for (int i = 0; i < ne; i += 2) {
|
||||
int16_t x0, x1;
|
||||
|
||||
x[i+0] *= g_inv;
|
||||
x0 = fminf(floorf(fabsf(x[i+0]) + 6.f/16), INT16_MAX);
|
||||
xq[i+0] = x[i+0] < 0 ? -x0 : x0;
|
||||
|
||||
x[i+1] *= g_inv;
|
||||
x1 = fminf(floorf(fabsf(x[i+1]) + 6.f/16), INT16_MAX);
|
||||
xq[i+1] = x[i+1] < 0 ? -x1 : x1;
|
||||
|
||||
*nq = x0 || x1 ? ne : *nq - 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Spectrum quantization inverse
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* g_int Quantization gain value
|
||||
* x, nq Spectral quantized, and count of significants
|
||||
* return Unquantized gain value
|
||||
*/
|
||||
static float unquantize(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int g_int, float *x, int nq)
|
||||
{
|
||||
float g = unquantize_gain(g_int);
|
||||
int i, ne = LC3_NE(dt, sr);
|
||||
|
||||
for (i = 0; i < nq; i++)
|
||||
x[i] = x[i] * g;
|
||||
|
||||
for ( ; i < ne; i++)
|
||||
x[i] = 0;
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Spectrum coding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resolve High-bitrate mode according size of the frame
|
||||
* sr, nbytes Samplerate and size of the frame
|
||||
* return True when High-Rate mode enabled
|
||||
*/
|
||||
static int resolve_high_rate(enum lc3_srate sr, int nbytes)
|
||||
{
|
||||
return nbytes > 20 * (1 + (int)sr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bit consumption
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* x Spectral quantized coefficients
|
||||
* n Count of significant coefficients, updated on truncation
|
||||
* nbits_budget Truncate to stay in budget, when not zero
|
||||
* p_lsb_mode Return True when LSB's are not AC coded, or NULL
|
||||
* return The number of bits coding the spectrum
|
||||
*/
|
||||
static int compute_nbits(
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const int16_t *x, int *n, int nbits_budget, bool *p_lsb_mode)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
|
||||
/* --- Mode and rate --- */
|
||||
|
||||
bool lsb_mode = nbytes >= 20 * (3 + (int)sr);
|
||||
bool high_rate = resolve_high_rate(sr, nbytes);
|
||||
|
||||
/* --- Loop on quantized coefficients --- */
|
||||
|
||||
int nbits = 0, nbits_lsb = 0;
|
||||
uint8_t state = 0;
|
||||
|
||||
int nbits_end = 0;
|
||||
int n_end = 0;
|
||||
|
||||
nbits_budget = nbits_budget ? nbits_budget * 2048 : INT_MAX;
|
||||
|
||||
for (int i = 0, h = 0; h < 2; h++) {
|
||||
const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
|
||||
|
||||
for ( ; i < LC3_MIN(*n, (ne + 2) >> (1 - h))
|
||||
&& nbits <= nbits_budget; i += 2) {
|
||||
|
||||
const uint8_t *lut = lut_coeff[state];
|
||||
int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]);
|
||||
|
||||
/* --- Sign values --- */
|
||||
|
||||
int s = (a != 0) + (b != 0);
|
||||
nbits += s * 2048;
|
||||
|
||||
/* --- LSB values Reduce to 2*2 bits MSB values ---
|
||||
* Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
|
||||
* coded with an escape code followed by 1 bit for each values.
|
||||
* The LSB mode does not arthmetic code the first LSB,
|
||||
* add the sign of the LSB when one of pair was at value 1 */
|
||||
|
||||
int k = 0;
|
||||
int m = (a | b) >> 2;
|
||||
|
||||
if (m) {
|
||||
if (lsb_mode) {
|
||||
nbits += lc3_spectrum_bits[lut[k++]][16] - 2*2048;
|
||||
nbits_lsb += 2 + (a == 1) + (b == 1);
|
||||
}
|
||||
|
||||
for (m >>= lsb_mode; m; m >>= 1, k++)
|
||||
nbits += lc3_spectrum_bits[lut[LC3_MIN(k, 3)]][16];
|
||||
|
||||
nbits += k * 2*2048;
|
||||
a >>= k;
|
||||
b >>= k;
|
||||
|
||||
k = LC3_MIN(k, 3);
|
||||
}
|
||||
|
||||
/* --- MSB values --- */
|
||||
|
||||
nbits += lc3_spectrum_bits[lut[k]][a + 4*b];
|
||||
|
||||
/* --- Update state --- */
|
||||
|
||||
if (s && nbits <= nbits_budget) {
|
||||
n_end = i + 2;
|
||||
nbits_end = nbits;
|
||||
}
|
||||
|
||||
state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Return --- */
|
||||
|
||||
*n = n_end;
|
||||
|
||||
if (p_lsb_mode)
|
||||
*p_lsb_mode = lsb_mode &&
|
||||
nbits_end + nbits_lsb * 2048 > nbits_budget;
|
||||
|
||||
if (nbits_budget >= INT_MAX)
|
||||
nbits_end += nbits_lsb * 2048;
|
||||
|
||||
return (nbits_end + 2047) / 2048;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put quantized spectrum
|
||||
* bits Bitstream context
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* x Spectral quantized
|
||||
* nq, lsb_mode Count of significants, and LSB discard indication
|
||||
*/
|
||||
static void put_quantized(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
const int16_t *x, int nq, bool lsb_mode)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
bool high_rate = resolve_high_rate(sr, nbytes);
|
||||
|
||||
/* --- Loop on quantized coefficients --- */
|
||||
|
||||
uint8_t state = 0;
|
||||
|
||||
for (int i = 0, h = 0; h < 2; h++) {
|
||||
const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
|
||||
|
||||
for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
|
||||
|
||||
const uint8_t *lut = lut_coeff[state];
|
||||
bool a_neg = x[i] < 0, b_neg = x[i+1] < 0;
|
||||
int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]);
|
||||
|
||||
/* --- LSB values Reduce to 2*2 bits MSB values ---
|
||||
* Reduce to 2x2 bits MSB values. The LSB's pair are arithmetic
|
||||
* coded with an escape code and 1 bits for each values.
|
||||
* The LSB mode discard the first LSB (at this step) */
|
||||
|
||||
int m = (a | b) >> 2;
|
||||
int k = 0, shr = 0;
|
||||
|
||||
if (m) {
|
||||
|
||||
if (lsb_mode)
|
||||
lc3_put_symbol(bits,
|
||||
lc3_spectrum_models + lut[k++], 16);
|
||||
|
||||
for (m >>= lsb_mode; m; m >>= 1, k++) {
|
||||
lc3_put_bit(bits, (a >> k) & 1);
|
||||
lc3_put_bit(bits, (b >> k) & 1);
|
||||
lc3_put_symbol(bits,
|
||||
lc3_spectrum_models + lut[LC3_MIN(k, 3)], 16);
|
||||
}
|
||||
|
||||
a >>= lsb_mode;
|
||||
b >>= lsb_mode;
|
||||
|
||||
shr = k - lsb_mode;
|
||||
k = LC3_MIN(k, 3);
|
||||
}
|
||||
|
||||
/* --- Sign values --- */
|
||||
|
||||
if (a) lc3_put_bit(bits, a_neg);
|
||||
if (b) lc3_put_bit(bits, b_neg);
|
||||
|
||||
/* --- MSB values --- */
|
||||
|
||||
a >>= shr;
|
||||
b >>= shr;
|
||||
|
||||
lc3_put_symbol(bits, lc3_spectrum_models + lut[k], a + 4*b);
|
||||
|
||||
/* --- Update state --- */
|
||||
|
||||
state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get quantized spectrum
|
||||
* bits Bitstream context
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* nq, lsb_mode Count of significants, and LSB discard indication
|
||||
* xq Return `nq` spectral quantized coefficients
|
||||
* nf_seed Return the noise factor seed associated
|
||||
* return 0: Ok -1: Invalid bitstream data
|
||||
*/
|
||||
static int get_quantized(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, int nbytes,
|
||||
int nq, bool lsb_mode, float *xq, uint16_t *nf_seed)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
bool high_rate = resolve_high_rate(sr, nbytes);
|
||||
|
||||
*nf_seed = 0;
|
||||
|
||||
/* --- Loop on quantized coefficients --- */
|
||||
|
||||
uint8_t state = 0;
|
||||
|
||||
for (int i = 0, h = 0; h < 2; h++) {
|
||||
const uint8_t (*lut_coeff)[4] = lc3_spectrum_lookup[high_rate][h];
|
||||
|
||||
for ( ; i < LC3_MIN(nq, (ne + 2) >> (1 - h)); i += 2) {
|
||||
|
||||
const uint8_t *lut = lut_coeff[state];
|
||||
|
||||
/* --- LSB values ---
|
||||
* Until the symbol read indicates the escape value 16,
|
||||
* read an LSB bit for each values.
|
||||
* The LSB mode discard the first LSB (at this step) */
|
||||
|
||||
int u = 0, v = 0;
|
||||
int k = 0, shl = 0;
|
||||
|
||||
unsigned s = lc3_get_symbol(bits, lc3_spectrum_models + lut[k]);
|
||||
|
||||
if (lsb_mode && s >= 16) {
|
||||
s = lc3_get_symbol(bits, lc3_spectrum_models + lut[++k]);
|
||||
shl++;
|
||||
}
|
||||
|
||||
for ( ; s >= 16 && shl < 14; shl++) {
|
||||
u |= lc3_get_bit(bits) << shl;
|
||||
v |= lc3_get_bit(bits) << shl;
|
||||
|
||||
k += (k < 3);
|
||||
s = lc3_get_symbol(bits, lc3_spectrum_models + lut[k]);
|
||||
}
|
||||
|
||||
if (s >= 16)
|
||||
return -1;
|
||||
|
||||
/* --- MSB & sign values --- */
|
||||
|
||||
int a = s % 4;
|
||||
int b = s / 4;
|
||||
|
||||
u |= a << shl;
|
||||
v |= b << shl;
|
||||
|
||||
xq[i ] = u && lc3_get_bit(bits) ? -u : u;
|
||||
xq[i+1] = v && lc3_get_bit(bits) ? -v : v;
|
||||
|
||||
*nf_seed = (*nf_seed + u * i + v * (i+1)) & 0xffff;
|
||||
|
||||
/* --- Update state --- */
|
||||
|
||||
state = (state << 4) + (k > 1 ? 12 + k : 1 + (a + b) * (k + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put residual bits of quantization
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* xq, n Spectral quantized, and count of significants
|
||||
* xf Scaled spectral coefficients
|
||||
*/
|
||||
static void put_residual(lc3_bits_t *bits, int nbits,
|
||||
const int16_t *xq, int n, const float *xf)
|
||||
{
|
||||
for (int i = 0; i < n && nbits > 0; i++) {
|
||||
|
||||
if (xq[i] == 0)
|
||||
continue;
|
||||
|
||||
lc3_put_bit(bits, xf[i] >= xq[i]);
|
||||
nbits--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get residual bits of quantization
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* x, nq Spectral quantized, and count of significants
|
||||
*/
|
||||
static void get_residual(lc3_bits_t *bits, int nbits, float *x, int nq)
|
||||
{
|
||||
for (int i = 0; i < nq && nbits > 0; i++) {
|
||||
|
||||
if (x[i] == 0)
|
||||
continue;
|
||||
|
||||
if (lc3_get_bit(bits) == 0)
|
||||
x[i] -= x[i] < 0 ? 5.f/16 : 3.f/16;
|
||||
else
|
||||
x[i] += x[i] > 0 ? 5.f/16 : 3.f/16;
|
||||
|
||||
nbits--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put LSB values of quantized spectrum values
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* x, n Spectral quantized, and count of significants
|
||||
*/
|
||||
static void put_lsb(lc3_bits_t *bits, int nbits, const int16_t *x, int n)
|
||||
{
|
||||
for (int i = 0; i < n && nbits > 0; i += 2) {
|
||||
|
||||
bool a_neg = x[i] < 0, b_neg = x[i+1] < 0;
|
||||
int a = LC3_ABS(x[i]), b = LC3_ABS(x[i+1]);
|
||||
|
||||
if ((a | b) >> 2 == 0)
|
||||
continue;
|
||||
|
||||
if (nbits-- > 0)
|
||||
lc3_put_bit(bits, a & 1);
|
||||
|
||||
if (a == 1 && nbits-- > 0)
|
||||
lc3_put_bit(bits, a_neg);
|
||||
|
||||
if (nbits-- > 0)
|
||||
lc3_put_bit(bits, b & 1);
|
||||
|
||||
if (b == 1 && nbits-- > 0)
|
||||
lc3_put_bit(bits, b_neg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LSB values of quantized spectrum values
|
||||
* bits Bitstream context
|
||||
* nbits Maximum number of bits to output
|
||||
* x, nq Spectral quantized, and count of significants
|
||||
* nf_seed Update the noise factor seed according
|
||||
*/
|
||||
static void get_lsb(lc3_bits_t *bits,
|
||||
int nbits, float *x, int nq, uint16_t *nf_seed)
|
||||
{
|
||||
for (int i = 0; i < nq && nbits > 0; i += 2) {
|
||||
|
||||
float a = fabsf(x[i]), b = fabsf(x[i+1]);
|
||||
|
||||
if (fmaxf(a, b) < 4)
|
||||
continue;
|
||||
|
||||
if (nbits-- > 0 && lc3_get_bit(bits)) {
|
||||
if (a) {
|
||||
x[i] += x[i] < 0 ? -1 : 1;
|
||||
*nf_seed = (*nf_seed + i) & 0xffff;
|
||||
} else if (nbits-- > 0) {
|
||||
x[i] = lc3_get_bit(bits) ? -1 : 1;
|
||||
*nf_seed = (*nf_seed + i) & 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
if (nbits-- > 0 && lc3_get_bit(bits)) {
|
||||
if (b) {
|
||||
x[i+1] += x[i+1] < 0 ? -1 : 1;
|
||||
*nf_seed = (*nf_seed + i+1) & 0xffff;
|
||||
} else if (nbits-- > 0) {
|
||||
x[i+1] = lc3_get_bit(bits) ? -1 : 1;
|
||||
*nf_seed = (*nf_seed + i+1) & 0xffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Noise coding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Estimate noise level
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* xq, nq Quantized spectral coefficients
|
||||
* x Quantization scaled spectrum coefficients
|
||||
* return Noise factor (0 to 7)
|
||||
*/
|
||||
static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const int16_t *xq, int nq, const float *x)
|
||||
{
|
||||
int bw_stop = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw);
|
||||
int w = 2 + dt;
|
||||
|
||||
float sum = 0;
|
||||
int i, n = 0, z = 0;
|
||||
|
||||
for (i = 6*(3 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
z = xq[i] ? 0 : z + 1;
|
||||
if (z > 2*w)
|
||||
sum += fabs(x[i - w]), n++;
|
||||
}
|
||||
|
||||
for ( ; i < bw_stop + w; i++)
|
||||
if (++z > 2*w)
|
||||
sum += fabs(x[i - w]), n++;
|
||||
|
||||
int nf = n ? 8 - (int)((16 * sum) / n + 0.5f) : 0;
|
||||
|
||||
return LC3_CLIP(nf, 0, 7);
|
||||
}
|
||||
|
||||
/**
|
||||
* Noise filling
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* nf, nf_seed The noise factor and pseudo-random seed
|
||||
* g Quantization gain
|
||||
* x, nq Spectral quantized, and count of significants
|
||||
*/
|
||||
static void fill_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
int nf, uint16_t nf_seed, float g, float *x, int nq)
|
||||
{
|
||||
int bw_stop = (dt == LC3_DT_7M5 ? 60 : 80) * (1 + bw);
|
||||
int w = 2 + dt;
|
||||
|
||||
float s = g * (float)(8 - nf) / 16;
|
||||
int i, z = 0;
|
||||
|
||||
for (i = 6*(3 + dt) - w; i < LC3_MIN(nq, bw_stop); i++) {
|
||||
z = x[i] ? 0 : z + 1;
|
||||
if (z > 2*w) {
|
||||
nf_seed = (13849 + nf_seed*31821) & 0xffff;
|
||||
x[i - w] = nf_seed & 0x8000 ? -s : s;
|
||||
}
|
||||
}
|
||||
|
||||
for ( ; i < bw_stop + w; i++)
|
||||
if (++z > 2*w) {
|
||||
nf_seed = (13849 + nf_seed*31821) & 0xffff;
|
||||
x[i - w] = nf_seed & 0x8000 ? -s : s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put noise factor
|
||||
* bits Bitstream context
|
||||
* nf Noise factor (0 to 7)
|
||||
*/
|
||||
static void put_noise_factor(lc3_bits_t *bits, int nf)
|
||||
{
|
||||
lc3_put_bits(bits, nf, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get noise factor
|
||||
* bits Bitstream context
|
||||
* return Noise factor (0 to 7)
|
||||
*/
|
||||
static int get_noise_factor(lc3_bits_t *bits)
|
||||
{
|
||||
return lc3_get_bits(bits, 3);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Encoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Bit consumption of the number of coded coefficients
|
||||
* dt, sr Duration, samplerate of the frame
|
||||
* return Bit consumpution of the number of coded coefficients
|
||||
*/
|
||||
static int get_nbits_nq(enum lc3_dt dt, enum lc3_srate sr)
|
||||
{
|
||||
int ne = LC3_NE(dt, sr);
|
||||
return 4 + (ne > 32) + (ne > 64) + (ne > 128) + (ne > 256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bit consumption of the arithmetic coder
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* return Bit consumption of bitstream data
|
||||
*/
|
||||
static int get_nbits_ac(enum lc3_dt dt, enum lc3_srate sr, int nbytes)
|
||||
{
|
||||
return get_nbits_nq(dt, sr) + 3 + LC3_MIN((nbytes-1) / 160, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spectrum analysis
|
||||
*/
|
||||
void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, bool pitch, const lc3_tns_data_t *tns,
|
||||
struct lc3_spec_analysis *spec, float *x,
|
||||
int16_t *xq, struct lc3_spec_side *side)
|
||||
{
|
||||
bool reset_off;
|
||||
|
||||
/* --- Bit budget --- */
|
||||
|
||||
const int nbits_gain = 8;
|
||||
const int nbits_nf = 3;
|
||||
|
||||
int nbits_budget = 8*nbytes - get_nbits_ac(dt, sr, nbytes) -
|
||||
lc3_bwdet_get_nbits(sr) - lc3_ltpf_get_nbits(pitch) -
|
||||
lc3_sns_get_nbits() - lc3_tns_get_nbits(tns) - nbits_gain - nbits_nf;
|
||||
|
||||
/* --- Global gain --- */
|
||||
|
||||
float nbits_off = spec->nbits_off + spec->nbits_spare;
|
||||
nbits_off = fminf(fmaxf(nbits_off, -40), 40);
|
||||
nbits_off = 0.8 * spec->nbits_off + 0.2 * nbits_off;
|
||||
|
||||
int g_off = resolve_gain_offset(sr, nbytes);
|
||||
|
||||
int g_int = estimate_gain(dt, sr,
|
||||
x, nbits_budget, nbits_off, g_off, &reset_off);
|
||||
|
||||
/* --- Quantization --- */
|
||||
|
||||
quantize(dt, sr, g_int, x, xq, &side->nq);
|
||||
|
||||
int nbits = compute_nbits(dt, sr, nbytes, xq, &side->nq, 0, NULL);
|
||||
|
||||
spec->nbits_off = reset_off ? 0 : nbits_off;
|
||||
spec->nbits_spare = reset_off ? 0 : nbits_budget - nbits;
|
||||
|
||||
/* --- Adjust gain and requantize --- */
|
||||
|
||||
int g_adj = adjust_gain(sr, g_int + g_off, nbits, nbits_budget);
|
||||
|
||||
if (g_adj)
|
||||
quantize(dt, sr, g_adj, x, xq, &side->nq);
|
||||
|
||||
side->g_idx = g_int + g_adj + g_off;
|
||||
nbits = compute_nbits(dt, sr, nbytes,
|
||||
xq, &side->nq, nbits_budget, &side->lsb_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put spectral quantization side data
|
||||
*/
|
||||
void lc3_spec_put_side(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, const struct lc3_spec_side *side)
|
||||
{
|
||||
int nbits_nq = get_nbits_nq(dt, sr);
|
||||
|
||||
lc3_put_bits(bits, LC3_MAX(side->nq >> 1, 1) - 1, nbits_nq);
|
||||
lc3_put_bits(bits, side->lsb_mode, 1);
|
||||
lc3_put_bits(bits, side->g_idx, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode spectral coefficients
|
||||
*/
|
||||
void lc3_spec_encode(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
|
||||
const int16_t *xq, const lc3_spec_side_t *side, const float *x)
|
||||
{
|
||||
bool lsb_mode = side->lsb_mode;
|
||||
int nq = side->nq;
|
||||
|
||||
put_noise_factor(bits, estimate_noise(dt, bw, xq, nq, x));
|
||||
|
||||
put_quantized(bits, dt, sr, nbytes, xq, nq, lsb_mode);
|
||||
|
||||
int nbits_left = lc3_get_bits_left(bits);
|
||||
|
||||
if (lsb_mode)
|
||||
put_lsb(bits, nbits_left, xq, nq);
|
||||
else
|
||||
put_residual(bits, nbits_left, xq, nq, x);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Decoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get spectral quantization side data
|
||||
*/
|
||||
int lc3_spec_get_side(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, struct lc3_spec_side *side)
|
||||
{
|
||||
int nbits_nq = get_nbits_nq(dt, sr);
|
||||
int ne = LC3_NE(dt, sr);
|
||||
|
||||
side->nq = (lc3_get_bits(bits, nbits_nq) + 1) << 1;
|
||||
side->lsb_mode = lc3_get_bit(bits);
|
||||
side->g_idx = lc3_get_bits(bits, 8);
|
||||
|
||||
return side->nq > ne ? (side->nq = ne), -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode spectral coefficients
|
||||
*/
|
||||
int lc3_spec_decode(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw,
|
||||
int nbytes, const lc3_spec_side_t *side, float *x)
|
||||
{
|
||||
bool lsb_mode = side->lsb_mode;
|
||||
int nq = side->nq;
|
||||
int ret = 0;
|
||||
|
||||
int nf = get_noise_factor(bits);
|
||||
uint16_t nf_seed;
|
||||
|
||||
if ((ret = get_quantized(bits, dt, sr, nbytes,
|
||||
nq, lsb_mode, x, &nf_seed)) < 0)
|
||||
return ret;
|
||||
|
||||
int nbits_left = lc3_get_bits_left(bits);
|
||||
|
||||
if (lsb_mode)
|
||||
get_lsb(bits, nbits_left, x, nq, &nf_seed);
|
||||
else
|
||||
get_residual(bits, nbits_left, x, nq);
|
||||
|
||||
int g_int = side->g_idx - resolve_gain_offset(sr, nbytes);
|
||||
float g = unquantize(dt, sr, g_int, x, nq);
|
||||
|
||||
if (nq > 2 || x[0] || x[1] || side->g_idx > 0 || nf < 7)
|
||||
fill_noise(dt, bw, nf, nf_seed, g, x, nq);
|
||||
|
||||
return 0;
|
||||
}
|
111
3rd-party/lc3-google/src/spec.h
vendored
Normal file
111
3rd-party/lc3-google/src/spec.h
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Spectral coefficients encoding/decoding
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_SPEC_H
|
||||
#define __LC3_SPEC_H
|
||||
|
||||
#include "common.h"
|
||||
#include "tables.h"
|
||||
#include "bwdet.h"
|
||||
#include "ltpf.h"
|
||||
#include "tns.h"
|
||||
#include "sns.h"
|
||||
|
||||
|
||||
/**
|
||||
* Spectral quantization side data
|
||||
*/
|
||||
typedef struct lc3_spec_side {
|
||||
int g_idx, nq;
|
||||
bool lsb_mode;
|
||||
} lc3_spec_side_t;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Encoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Spectrum analysis
|
||||
* dt, sr, nbytes Duration, samplerate and size of the frame
|
||||
* pitch, tns Pitch present indication and TNS bistream data
|
||||
* spec Context of analysis
|
||||
* x Spectral coefficients, scaled as output
|
||||
* xq, side Return quantization data
|
||||
*/
|
||||
void lc3_spec_analyze(enum lc3_dt dt, enum lc3_srate sr,
|
||||
int nbytes, bool pitch, const lc3_tns_data_t *tns,
|
||||
lc3_spec_analysis_t *spec, float *x, int16_t *xq, lc3_spec_side_t *side);
|
||||
|
||||
/**
|
||||
* Put spectral quantization side data
|
||||
* bits Bitstream context
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* side Spectral quantization side data
|
||||
*/
|
||||
void lc3_spec_put_side(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, const lc3_spec_side_t *side);
|
||||
|
||||
/**
|
||||
* Encode spectral coefficients
|
||||
* bits Bitstream context
|
||||
* dt, sr, bw Duration, samplerate, bandwidth
|
||||
* nbytes and size of the frame
|
||||
* xq, side Quantization data
|
||||
* x Scaled spectral coefficients
|
||||
*/
|
||||
void lc3_spec_encode(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
|
||||
const int16_t *xq, const lc3_spec_side_t *side, const float *x);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Decoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get spectral quantization side data
|
||||
* bits Bitstream context
|
||||
* dt, sr Duration and samplerate of the frame
|
||||
* side Return quantization side data
|
||||
* return 0: Ok -1: Invalid bandwidth indication
|
||||
*/
|
||||
int lc3_spec_get_side(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_srate sr, lc3_spec_side_t *side);
|
||||
|
||||
/**
|
||||
* Decode spectral coefficients
|
||||
* bits Bitstream context
|
||||
* dt, sr, bw Duration, samplerate, bandwidth
|
||||
* nbytes and size of the frame
|
||||
* side Quantization side data
|
||||
* x Spectral coefficients
|
||||
* return 0: Ok -1: Invalid bitstream data
|
||||
*/
|
||||
int lc3_spec_decode(lc3_bits_t *bits, enum lc3_dt dt, enum lc3_srate sr,
|
||||
enum lc3_bandwidth bw, int nbytes, const lc3_spec_side_t *side, float *x);
|
||||
|
||||
|
||||
#endif /* __LC3_SPEC_H */
|
3526
3rd-party/lc3-google/src/tables.c
vendored
Normal file
3526
3rd-party/lc3-google/src/tables.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
96
3rd-party/lc3-google/src/tables.h
vendored
Normal file
96
3rd-party/lc3-google/src/tables.h
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __LC3_TABLES_H
|
||||
#define __LC3_TABLES_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
/**
|
||||
* MDCT Twiddles and window coefficients
|
||||
*/
|
||||
|
||||
struct lc3_fft_bf3_twiddles { int n3; const struct lc3_complex (*t)[2]; };
|
||||
struct lc3_fft_bf2_twiddles { int n2; const struct lc3_complex *t; };
|
||||
struct lc3_mdct_rot_def { int n4; const struct lc3_complex *w; };
|
||||
|
||||
extern const struct lc3_fft_bf3_twiddles *lc3_fft_twiddles_bf3[];
|
||||
extern const struct lc3_fft_bf2_twiddles *lc3_fft_twiddles_bf2[][3];
|
||||
extern const struct lc3_mdct_rot_def *lc3_mdct_rot[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
|
||||
extern const float *lc3_mdct_win[LC3_NUM_DT][LC3_NUM_SRATE];
|
||||
|
||||
|
||||
/**
|
||||
* Limits of bands
|
||||
*/
|
||||
|
||||
#define LC3_NUM_BANDS 64
|
||||
|
||||
extern const int lc3_band_lim[LC3_NUM_DT][LC3_NUM_SRATE][LC3_NUM_BANDS+1];
|
||||
|
||||
|
||||
/**
|
||||
* SNS Quantization
|
||||
*/
|
||||
|
||||
extern const float lc3_sns_lfcb[32][8];
|
||||
extern const float lc3_sns_hfcb[32][8];
|
||||
|
||||
struct lc3_sns_vq_gains {
|
||||
int count; const float *v;
|
||||
};
|
||||
|
||||
extern const struct lc3_sns_vq_gains lc3_sns_vq_gains[4];
|
||||
|
||||
extern const int32_t lc3_sns_mpvq_offsets[][11];
|
||||
|
||||
|
||||
/**
|
||||
* TNS Arithmetic Coding
|
||||
*/
|
||||
|
||||
extern const struct lc3_ac_model lc3_tns_order_models[];
|
||||
extern const uint16_t lc3_tns_order_bits[][8];
|
||||
|
||||
extern const struct lc3_ac_model lc3_tns_coeffs_models[];
|
||||
extern const uint16_t lc3_tns_coeffs_bits[][17];
|
||||
|
||||
|
||||
/**
|
||||
* Long Term Postfilter
|
||||
*/
|
||||
|
||||
extern const float lc3_ltpf_h12k8[240];
|
||||
|
||||
extern const float *lc3_ltpf_cnum[LC3_NUM_SRATE][4];
|
||||
extern const float *lc3_ltpf_cden[LC3_NUM_SRATE][4];
|
||||
|
||||
|
||||
/**
|
||||
* Spectral Data Arithmetic Coding
|
||||
*/
|
||||
|
||||
extern const uint8_t lc3_spectrum_lookup[2][2][256][4];
|
||||
extern const struct lc3_ac_model lc3_spectrum_models[];
|
||||
extern const uint16_t lc3_spectrum_bits[][17];
|
||||
|
||||
|
||||
#endif /* __LC3_TABLES_H */
|
454
3rd-party/lc3-google/src/tns.c
vendored
Normal file
454
3rd-party/lc3-google/src/tns.c
vendored
Normal file
@ -0,0 +1,454 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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 "tns.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Filter Coefficients
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Resolve LPC Weighting indication according bitrate
|
||||
* dt, nbytes Duration and size of the frame
|
||||
* return True when LPC Weighting enabled
|
||||
*/
|
||||
static bool resolve_lpc_weighting(enum lc3_dt dt, int nbytes)
|
||||
{
|
||||
return nbytes < (dt == LC3_DT_7M5 ? 360/8 : 480/8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return dot product of 2 vectors
|
||||
* a, b, n The 2 vectors of size `n`
|
||||
* return sum( a[i] * b[i] ), i = [0..n-1]
|
||||
*/
|
||||
static inline float dot(const float *a, const float *b, int n)
|
||||
{
|
||||
float v = 0;
|
||||
|
||||
while (n--)
|
||||
v += *(a++) * *(b++);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* LPC Coefficients
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* x Spectral coefficients
|
||||
* gain, a Output the prediction gains and LPC coefficients
|
||||
*/
|
||||
static void compute_lpc_coeffs(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const float *x, float *gain, float (*a)[9])
|
||||
{
|
||||
static const int sub_7m5_nb[] = { 9, 26, 43, 60 };
|
||||
static const int sub_7m5_wb[] = { 9, 46, 83, 120 };
|
||||
static const int sub_7m5_sswb[] = { 9, 66, 123, 180 };
|
||||
static const int sub_7m5_swb[] = { 9, 46, 82, 120, 159, 200, 240 };
|
||||
static const int sub_7m5_fb[] = { 9, 56, 103, 150, 200, 250, 300 };
|
||||
|
||||
static const int sub_10m_nb[] = { 12, 34, 57, 80 };
|
||||
static const int sub_10m_wb[] = { 12, 61, 110, 160 };
|
||||
static const int sub_10m_sswb[] = { 12, 88, 164, 240 };
|
||||
static const int sub_10m_swb[] = { 12, 61, 110, 160, 213, 266, 320 };
|
||||
static const int sub_10m_fb[] = { 12, 74, 137, 200, 266, 333, 400 };
|
||||
|
||||
/* --- Normalized autocorrelation --- */
|
||||
|
||||
static const float lag_window[] = {
|
||||
1.00000000e+00, 9.98028026e-01, 9.92135406e-01, 9.82391584e-01,
|
||||
9.68910791e-01, 9.51849807e-01, 9.31404933e-01, 9.07808230e-01,
|
||||
8.81323137e-01
|
||||
};
|
||||
|
||||
const int *sub = (const int * const [LC3_NUM_DT][LC3_NUM_SRATE]){
|
||||
{ sub_7m5_nb, sub_7m5_wb, sub_7m5_sswb, sub_7m5_swb, sub_7m5_fb },
|
||||
{ sub_10m_nb, sub_10m_wb, sub_10m_sswb, sub_10m_swb, sub_10m_fb },
|
||||
}[dt][bw];
|
||||
|
||||
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
|
||||
const float *xs, *xe = x + *sub;
|
||||
float r[2][9];
|
||||
|
||||
for (int f = 0; f < nfilters; f++) {
|
||||
float c[9][3];
|
||||
|
||||
for (int s = 0; s < 3; s++) {
|
||||
xs = xe, xe = x + *(++sub);
|
||||
|
||||
for (int k = 0; k < 9; k++)
|
||||
c[k][s] = dot(xs, xs + k, (xe - xs) - k);
|
||||
}
|
||||
|
||||
float e0 = c[0][0], e1 = c[0][1], e2 = c[0][2];
|
||||
|
||||
r[f][0] = 3;
|
||||
for (int k = 1; k < 9; k++)
|
||||
r[f][k] = e0 == 0 || e1 == 0 || e2 == 0 ? 0 :
|
||||
(c[k][0]/e0 + c[k][1]/e1 + c[k][2]/e2) * lag_window[k];
|
||||
}
|
||||
|
||||
/* --- Levinson-Durbin recursion --- */
|
||||
|
||||
for (int f = 0; f < nfilters; f++) {
|
||||
float *a0 = a[f], a1[9];
|
||||
float err = r[f][0], rc;
|
||||
|
||||
gain[f] = err;
|
||||
|
||||
a0[0] = 1;
|
||||
for (int k = 1; k < 9; ) {
|
||||
|
||||
rc = -r[f][k];
|
||||
for (int i = 1; i < k; i++)
|
||||
rc -= a0[i] * r[f][k-i];
|
||||
|
||||
rc /= err;
|
||||
err *= 1 - rc * rc;
|
||||
|
||||
for (int i = 1; i < k; i++)
|
||||
a1[i] = a0[i] + rc * a0[k-i];
|
||||
a1[k++] = rc;
|
||||
|
||||
rc = -r[f][k];
|
||||
for (int i = 1; i < k; i++)
|
||||
rc -= a1[i] * r[f][k-i];
|
||||
|
||||
rc /= err;
|
||||
err *= 1 - rc * rc;
|
||||
|
||||
for (int i = 1; i < k; i++)
|
||||
a0[i] = a1[i] + rc * a1[k-i];
|
||||
a0[k++] = rc;
|
||||
}
|
||||
|
||||
gain[f] /= err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LPC Weighting
|
||||
* gain, a Prediction gain and LPC coefficients, weighted as output
|
||||
*/
|
||||
static void lpc_weighting(float pred_gain, float *a)
|
||||
{
|
||||
float gamma = 1. - (1. - 0.85) * (2. - pred_gain) / (2. - 1.5), g = 1;
|
||||
for (int i = 1; i < 9; i++)
|
||||
a[i] *= (g *= gamma);
|
||||
}
|
||||
|
||||
/**
|
||||
* LPC reflection
|
||||
* a LPC coefficients
|
||||
* rc Output refelection coefficients
|
||||
*/
|
||||
static void lpc_reflection(const float *a, float *rc)
|
||||
{
|
||||
float e, b[2][7], *b0, *b1;
|
||||
|
||||
rc[7] = a[1+7];
|
||||
e = 1 - rc[7] * rc[7];
|
||||
|
||||
b1 = b[1];
|
||||
for (int i = 0; i < 7; i++)
|
||||
b1[i] = (a[1+i] - rc[7] * a[7-i]) / e;
|
||||
|
||||
for (int k = 6; k > 0; k--) {
|
||||
b0 = b1, b1 = b[k & 1];
|
||||
|
||||
rc[k] = b0[k];
|
||||
e = 1 - rc[k] * rc[k];
|
||||
|
||||
for (int i = 0; i < k; i++)
|
||||
b1[i] = (b0[i] - rc[k] * b0[k-1-i]) / e;
|
||||
}
|
||||
|
||||
rc[0] = b1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Quantization of RC coefficients
|
||||
* rc Refelection coefficients
|
||||
* rc_order Return order of coefficients
|
||||
* rc_i Return quantized coefficients
|
||||
*/
|
||||
static void quantize_rc(const float *rc, int *rc_order, int *rc_q)
|
||||
{
|
||||
/* Quantization table, sin(delta * (i + 0.5)), delta = Pi / 17 */
|
||||
|
||||
static float q_thr[] = {
|
||||
9.22683595e-02, 2.73662990e-01, 4.45738356e-01, 6.02634636e-01,
|
||||
7.39008917e-01, 8.50217136e-01, 9.32472229e-01, 9.82973100e-01
|
||||
};
|
||||
|
||||
*rc_order = 8;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
float rc_m = fabsf(rc[i]);
|
||||
|
||||
rc_q[i] = 4 * (rc_m >= q_thr[4]);
|
||||
for (int j = 0; j < 4 && rc_m >= q_thr[rc_q[i]]; j++, rc_q[i]++);
|
||||
|
||||
if (rc[i] < 0)
|
||||
rc_q[i] = -rc_q[i];
|
||||
|
||||
*rc_order = rc_q[i] != 0 ? 8 : *rc_order - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unquantization of RC coefficients
|
||||
* rc_q Quantized coefficients
|
||||
* rc_order Order of coefficients
|
||||
* rc Return refelection coefficients
|
||||
*/
|
||||
static void unquantize_rc(const int *rc_q, int rc_order, float rc[8])
|
||||
{
|
||||
/* Quantization table, sin(delta * i), delta = Pi / 17 */
|
||||
|
||||
static float q_inv[] = {
|
||||
0.00000000e+00, 1.83749517e-01, 3.61241664e-01, 5.26432173e-01,
|
||||
6.73695641e-01, 7.98017215e-01, 8.95163302e-01, 9.61825645e-01,
|
||||
9.95734176e-01
|
||||
};
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rc_order; i++) {
|
||||
float rc_m = q_inv[LC3_ABS(rc_q[i])];
|
||||
rc[i] = rc_q[i] < 0 ? -rc_m : rc_m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Filtering
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Forward filtering
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* rc_order, rc Order of coefficients, and coefficients
|
||||
* x Spectral coefficients, filtered as output
|
||||
*/
|
||||
static void forward_filtering(
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const int rc_order[2], const float rc[2][8], float *x)
|
||||
{
|
||||
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
|
||||
int i0, ie = 3*(3 + dt);
|
||||
|
||||
float s[8] = { 0 };
|
||||
|
||||
for (int f = 0; f < nfilters; f++) {
|
||||
|
||||
i0 = ie;
|
||||
ie = nf * (1 + f);
|
||||
|
||||
if (!rc_order[f])
|
||||
continue;
|
||||
|
||||
for (int i = i0; i < ie; i++) {
|
||||
float xi = x[i];
|
||||
float s0, s1 = xi;
|
||||
|
||||
for (int k = 0; k < rc_order[f]; k++) {
|
||||
s0 = s[k];
|
||||
s[k] = s1;
|
||||
|
||||
s1 = rc[f][k] * xi + s0;
|
||||
xi += rc[f][k] * s0;
|
||||
}
|
||||
|
||||
x[i] = xi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse filtering
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* rc_order, rc Order of coefficients, and unquantized coefficients
|
||||
* x Spectral coefficients, filtered as output
|
||||
*/
|
||||
static void inverse_filtering(
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const int rc_order[2], const float rc[2][8], float *x)
|
||||
{
|
||||
int nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
int nf = LC3_NE(dt, bw) >> (nfilters - 1);
|
||||
int i0, ie = 3*(3 + dt);
|
||||
|
||||
float s[8] = { 0 };
|
||||
|
||||
for (int f = 0; f < nfilters; f++) {
|
||||
|
||||
i0 = ie;
|
||||
ie = nf * (1 + f);
|
||||
|
||||
if (!rc_order[f])
|
||||
continue;
|
||||
|
||||
for (int i = i0; i < ie; i++) {
|
||||
float xi = x[i];
|
||||
|
||||
xi -= s[7] * rc[f][7];
|
||||
for (int k = 6; k >= 0; k--) {
|
||||
xi -= s[k] * rc[f][k];
|
||||
s[k+1] = s[k] + rc[f][k] * xi;
|
||||
}
|
||||
s[0] = xi;
|
||||
x[i] = xi;
|
||||
}
|
||||
|
||||
for (int k = 7; k >= rc_order[f]; k--)
|
||||
s[k] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Interface
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* TNS analysis
|
||||
*/
|
||||
void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
bool nn_flag, int nbytes, struct lc3_tns_data *data, float *x)
|
||||
{
|
||||
/* Processing steps :
|
||||
* - Determine the LPC (Linear Predictive Coding) Coefficients
|
||||
* - Check is the filtering is disabled
|
||||
* - The coefficients are weighted on low bitrates and predicition gain
|
||||
* - Convert to reflection coefficients and quantize
|
||||
* - Finally filter the spectral coefficients */
|
||||
|
||||
float pred_gain[2], a[2][9];
|
||||
float rc[2][8];
|
||||
|
||||
data->nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
|
||||
|
||||
compute_lpc_coeffs(dt, bw, x, pred_gain, a);
|
||||
|
||||
for (int f = 0; f < data->nfilters; f++) {
|
||||
|
||||
data->rc_order[f] = 0;
|
||||
if (nn_flag || pred_gain[f] <= 1.5)
|
||||
continue;
|
||||
|
||||
if (data->lpc_weighting && pred_gain[f] < 2)
|
||||
lpc_weighting(pred_gain[f], a[f]);
|
||||
|
||||
lpc_reflection(a[f], rc[f]);
|
||||
|
||||
quantize_rc(rc[f], &data->rc_order[f], data->rc[f]);
|
||||
unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
|
||||
}
|
||||
|
||||
forward_filtering(dt, bw, data->rc_order, rc, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* TNS synthesis
|
||||
*/
|
||||
void lc3_tns_synthesize(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const struct lc3_tns_data *data, float *x)
|
||||
{
|
||||
float rc[2][8] = { };
|
||||
|
||||
for (int f = 0; f < data->nfilters; f++)
|
||||
if (data->rc_order[f])
|
||||
unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
|
||||
|
||||
inverse_filtering(dt, bw, data->rc_order, rc, x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bit consumption of bitstream data
|
||||
*/
|
||||
int lc3_tns_get_nbits(const struct lc3_tns_data *data)
|
||||
{
|
||||
int nbits = 0;
|
||||
|
||||
for (int f = 0; f < data->nfilters; f++) {
|
||||
|
||||
int nbits_2048 = 2048;
|
||||
int rc_order = data->rc_order[f];
|
||||
|
||||
nbits_2048 += rc_order > 0 ? lc3_tns_order_bits
|
||||
[data->lpc_weighting][rc_order-1] : 0;
|
||||
|
||||
for (int i = 0; i < rc_order; i++)
|
||||
nbits_2048 += lc3_tns_coeffs_bits[i][8 + data->rc[f][i]];
|
||||
|
||||
nbits += (nbits_2048 + (1 << 11) - 1) >> 11;
|
||||
}
|
||||
|
||||
return nbits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put bitstream data
|
||||
*/
|
||||
void lc3_tns_put_data(lc3_bits_t *bits, const struct lc3_tns_data *data)
|
||||
{
|
||||
for (int f = 0; f < data->nfilters; f++) {
|
||||
int rc_order = data->rc_order[f];
|
||||
|
||||
lc3_put_bits(bits, rc_order > 0, 1);
|
||||
if (rc_order <= 0)
|
||||
continue;
|
||||
|
||||
lc3_put_symbol(bits,
|
||||
lc3_tns_order_models + data->lpc_weighting, rc_order-1);
|
||||
|
||||
for (int i = 0; i < rc_order; i++)
|
||||
lc3_put_symbol(bits,
|
||||
lc3_tns_coeffs_models + i, 8 + data->rc[f][i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bitstream data
|
||||
*/
|
||||
void lc3_tns_get_data(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data)
|
||||
{
|
||||
data->nfilters = 1 + (bw >= LC3_BANDWIDTH_SWB);
|
||||
data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
|
||||
|
||||
for (int f = 0; f < data->nfilters; f++) {
|
||||
|
||||
data->rc_order[f] = lc3_get_bit(bits);
|
||||
if (!data->rc_order[f])
|
||||
continue;
|
||||
|
||||
data->rc_order[f] += lc3_get_symbol(bits,
|
||||
lc3_tns_order_models + data->lpc_weighting);
|
||||
|
||||
for (int i = 0; i < data->rc_order[f]; i++)
|
||||
data->rc[f][i] = (int)lc3_get_symbol(bits,
|
||||
lc3_tns_coeffs_models + i) - 8;
|
||||
}
|
||||
}
|
99
3rd-party/lc3-google/src/tns.h
vendored
Normal file
99
3rd-party/lc3-google/src/tns.h
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright 2021 Google, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LC3 - Temporal Noise Shaping
|
||||
*
|
||||
* Reference : Low Complexity Communication Codec (LC3)
|
||||
* Bluetooth Specification v1.0
|
||||
*/
|
||||
|
||||
#ifndef __LC3_TNS_H
|
||||
#define __LC3_TNS_H
|
||||
|
||||
#include "common.h"
|
||||
#include "bits.h"
|
||||
|
||||
|
||||
/**
|
||||
* Bitstream data
|
||||
*/
|
||||
|
||||
typedef struct lc3_tns_data {
|
||||
int nfilters;
|
||||
bool lpc_weighting;
|
||||
int rc_order[2];
|
||||
int rc[2][8];
|
||||
} lc3_tns_data_t;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Encoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* TNS analysis
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* nn_flag True when high energy detected near Nyquist frequency
|
||||
* nbytes Size in bytes of the frame
|
||||
* data Return bitstream data
|
||||
* x Spectral coefficients, filtered as output
|
||||
*/
|
||||
void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
bool nn_flag, int nbytes, lc3_tns_data_t *data, float *x);
|
||||
|
||||
/**
|
||||
* Return number of bits coding the data
|
||||
* data Bitstream data
|
||||
* return Bit consumption
|
||||
*/
|
||||
int lc3_tns_get_nbits(const lc3_tns_data_t *data);
|
||||
|
||||
/**
|
||||
* Put bitstream data
|
||||
* bits Bitstream context
|
||||
* data Bitstream data
|
||||
*/
|
||||
void lc3_tns_put_data(lc3_bits_t *bits, const lc3_tns_data_t *data);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Decoding
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Get bitstream data
|
||||
* bits Bitstream context
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* nbytes Size in bytes of the frame
|
||||
* data Bitstream data
|
||||
*/
|
||||
void lc3_tns_get_data(lc3_bits_t *bits,
|
||||
enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data);
|
||||
|
||||
/**
|
||||
* TNS synthesis
|
||||
* dt, bw Duration and bandwidth of the frame
|
||||
* data Bitstream data
|
||||
* x Spectral coefficients, filtered as output
|
||||
*/
|
||||
void lc3_tns_synthesize(enum lc3_dt dt, enum lc3_bandwidth bw,
|
||||
const lc3_tns_data_t *data, float *x);
|
||||
|
||||
|
||||
#endif /* __LC3_TNS_H */
|
195
3rd-party/liblc3codec/Api/Lc3Config.hpp
vendored
195
3rd-party/liblc3codec/Api/Lc3Config.hpp
vendored
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Lc3Config.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LC3_CONFIG_HPP_
|
||||
#define __LC3_CONFIG_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/*
|
||||
* The LC3 encoder and decoder have a common set of essential session
|
||||
* configuration parameters - see LC3 specification Sections 2.2 "Encoder interfaces"
|
||||
* and Section 2.4 "Decoder interfaces" (dr09r07).
|
||||
* The set of common session configuration parameters is represented
|
||||
* by an instance of class Lc3Config.
|
||||
*
|
||||
* Lc3Config is designed such that all parameters need to be
|
||||
* providing when constructing an instance. Afterwards, success of creation,
|
||||
* the actual parameter values, and derived parameter values are provided
|
||||
* by corresponding const getter methods or public const fields.
|
||||
*
|
||||
* When parameters need to be changes, a new instance of Lc3Config has to be
|
||||
* created.
|
||||
*
|
||||
* Instances of Lc3Config are provided to instances of Lc3Encoder and Lc3Decoder
|
||||
* when constructing them.
|
||||
*
|
||||
* The main purpose of Lc3Config is to verify and handle common LC3 session
|
||||
* configuration parameters in a consistent way.
|
||||
*
|
||||
*/
|
||||
class Lc3Config
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Enumeration of supported frame durations N_ms = 7.5ms and N_ms = 10ms.
|
||||
*
|
||||
* Note: although the LC3 specification describes frame duration N_ms as
|
||||
* a parameter with floating point values 7.5 and 10.0, we decided
|
||||
* to make this parameter a discrete enumeration of supported
|
||||
* frame durations. There are too many codec parts that need
|
||||
* specifically listed constants dependent on the configured
|
||||
* frame duration, so that it never will be possible to chose from a
|
||||
* larger set of floating point values for N_ms.
|
||||
* Making the data type of N_ms an enumeration supports
|
||||
* straight forwards verification that meaningful parameters are given.
|
||||
*/
|
||||
enum class FrameDuration
|
||||
{
|
||||
d10ms,
|
||||
d7p5ms
|
||||
};
|
||||
|
||||
// configuration error (see "getErrorStatus")
|
||||
static const uint8_t ERROR_FREE = 0x00;
|
||||
static const uint8_t INVALID_SAMPLING_RATE = 0x01;
|
||||
static const uint8_t INVALID_FRAME_DURATION = 0x02;
|
||||
static const uint8_t INVALID_NUMBER_OF_CHANNELS = 0x04;
|
||||
|
||||
/*
|
||||
* Constructor of an instance of Lc3Config
|
||||
* Parameters:
|
||||
* (see also see LC3 specification Sections 2.2 "Encoder interfaces"
|
||||
* and Section 2.4 "Decoder interfaces" (dr09r07) )
|
||||
*
|
||||
* Fs_ : Sampling frequency in Hz -> defines public constant Fs
|
||||
* Supported values are
|
||||
* 8000 Hz
|
||||
* 16000 Hz
|
||||
* 24000 Hz
|
||||
* 32000 Hz
|
||||
* 44100 Hz
|
||||
* 48000 Hz
|
||||
*
|
||||
* N_ms_ : Frame duration given by value from enumeration FrameDuration (see above)
|
||||
* -> defines public constant N_ms
|
||||
* Supported values see enumeration FrameDuration.
|
||||
*
|
||||
* Nc_ : Number of channels -> defines public constant Nc
|
||||
* Supported values are Nc > 0 and Nc < 256 such that device resources are not exhausted.
|
||||
* Notes:
|
||||
* - Exhausting device resources can mean that there is not enough memory
|
||||
* to instantiate the corresponding number of encoders and/or decoders, but
|
||||
* also that computing the encoders and/or decoders in real-time is not possible.
|
||||
* - The parameter N_c_max described in the LC3 specifciation is not given here,
|
||||
* since there is too little knowledge on the target devices where this code
|
||||
* may be used.
|
||||
*
|
||||
*/
|
||||
Lc3Config(uint16_t Fs_, FrameDuration N_ms_, uint8_t Nc_);
|
||||
|
||||
// no default constructor supported
|
||||
Lc3Config() = delete;
|
||||
|
||||
// Destructor
|
||||
virtual ~Lc3Config();
|
||||
|
||||
/*
|
||||
* Getter "isValid" provides a convenience function that returns true when an instance of Lc3Config
|
||||
* could be created without error.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/*
|
||||
* Getter "getErrorStatus" provides details on the success of instantiating Lc3Config.
|
||||
* The possible return values are listed as constants in this class (see configuration error constants above)
|
||||
*/
|
||||
uint8_t getErrorStatus() const;
|
||||
|
||||
/*
|
||||
* Getter "getByteCountFromBitrate" provides the number of bytes available in one encoded frame
|
||||
* of one channel (see "nbytes" as described in Section 3.2.5 "Bit budget and bitrate" (dr09r07) )
|
||||
*
|
||||
* The number of bytes "nbytes" to use for encoding a single channel is a required external input to
|
||||
* each single channel LC3 encoder. The same number of bytes (now to be used for decoding) is also
|
||||
* a required external input to each single channel LC3 decoder. The corresponding number of bits
|
||||
* available in one frame is thus "nbits 8*nbytes".
|
||||
* The codec works on a byte boundary, i.e. the variable "nbytes" shall be an integer number.
|
||||
* A certain "bitrate" can be converted to a number of bytes "nbytes" where the number of bytes is
|
||||
* rounded towards the nearest lower integer.
|
||||
*
|
||||
* The algorithm is verified from the bitrate corresponding to
|
||||
* nbytes = 20 up to the bitrate corresponding to
|
||||
* nbytes = 400 per channel for all sampling rates.
|
||||
* The LC3 specification does not specify or recommend what bitrate to use for encoding a frame of
|
||||
* audio samples. This is specified by the profiles making use of the LC3.
|
||||
*/
|
||||
uint16_t getByteCountFromBitrate(uint32_t bitrate) const; // meant for a single channel
|
||||
|
||||
/*
|
||||
* Getter "getBitrateFromByteCount" provides the bitrate of the codec in bits per second
|
||||
* of one channel (see Section 3.2.5 "Bit budget and bitrate" (dr1.0r03) )
|
||||
*
|
||||
* This is a convenience utility and not directly used by the LC3 implementation.
|
||||
*
|
||||
* The bitrate of the codec in bits per second is
|
||||
* "bitrate = ceil(nbits / frame_duration) = ceil(nbits*Fs/NF) = ceil(8*nbytes*Fs/NF)".
|
||||
*
|
||||
* The LC3 specification does not specify or recommend what bitrate to use for encoding a frame of
|
||||
* audio samples. This is specified by the profiles making use of the LC3.
|
||||
*/
|
||||
uint32_t getBitrateFromByteCount(uint16_t nbytes) const;
|
||||
|
||||
/*
|
||||
* Getter "getFscal" provides a utility used within the LC3 implementation
|
||||
* for easier parameter mapping when Fs == 44100
|
||||
* (see Section 3.2.2 "Sampling rates" (dr1.0r03) )
|
||||
*/
|
||||
double getFscal() const;
|
||||
|
||||
|
||||
/*
|
||||
* Getter "getNmsValue" provides a utility used within the LC3 implementation
|
||||
* that converts FrameDuration N_ms enumeration values to duration values in milliseconds.
|
||||
*/
|
||||
double getNmsValue() const;
|
||||
|
||||
private:
|
||||
// internal utilities used for verifying the given input parameters and computing derived parameters
|
||||
uint8_t getFs_ind(uint16_t Fs);
|
||||
uint16_t getNF(uint16_t Fs, FrameDuration N_ms);
|
||||
uint16_t getNE(uint16_t NF, FrameDuration N_ms);
|
||||
|
||||
// errors status set during construction and returned by getErrorStatus()
|
||||
uint8_t errorStatus;
|
||||
|
||||
public:
|
||||
// configuration details -> see also Section 3.1.2 "Mathematical symbols" (dr09r07)
|
||||
const uint16_t Fs; // Sampling rate (in Hz)
|
||||
const uint8_t Fs_ind; // Sampling rate index (see also Section 3.2.2 "Sampling rates" (dr09r07)
|
||||
const FrameDuration N_ms; // Frame duration -> see Lc3Config constructor documentation
|
||||
// Note: that the actual frame duration is longer by a factor of 480/441
|
||||
// if the sampling rate is 44100 Hz
|
||||
const uint16_t NF; // Number of samples processed in one frame of one channel (also known as frame size)
|
||||
const uint16_t NE; // Number of encoded spectral lines (per frame and channel)
|
||||
const uint16_t Z; // Number of leading zeros in MDCT window
|
||||
const uint8_t Nc; // Number of channels
|
||||
const uint8_t N_b; // Number of bands
|
||||
};
|
||||
|
||||
#endif // __LC3_CONFIG_HPP_
|
329
3rd-party/liblc3codec/Api/Lc3Decoder.hpp
vendored
329
3rd-party/liblc3codec/Api/Lc3Decoder.hpp
vendored
@ -1,329 +0,0 @@
|
||||
/*
|
||||
* Lc3Decoder.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef API_LC3DECODER_HPP_
|
||||
#define API_LC3DECODER_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Lc3Config.hpp"
|
||||
|
||||
/*
|
||||
* Forward declaration of the "internal" class DecoderTop, so
|
||||
* that the private vector of single channel decoders can be declared in Lc3Decoder.
|
||||
*/
|
||||
namespace Lc3Dec
|
||||
{
|
||||
class DecoderTop;
|
||||
}
|
||||
|
||||
/*
|
||||
* The LC3 decoder interface is specified in
|
||||
* LC3 specification Sections 2.4 "Decoder interfaces" (dr09r07).
|
||||
*
|
||||
* Lc3Decoder is designed such that all specified features are provided.
|
||||
*
|
||||
* In contrast to the Lc3Encoder, even 24bit and 32bit decoded audio
|
||||
* data can be provided - however in one fix byte arrangement which will
|
||||
* not meet all meaningful options. Providing 24bit and 32bit decoded audio
|
||||
* data makes the API more complex but does not increase the needed
|
||||
* resources when basic 16bit/sample audio data is desired only.
|
||||
*
|
||||
* Instantiating Lc3Decoder implies providing a Lc3Config instance. A copy of
|
||||
* this instance is available as public const member so that all essential session
|
||||
* parameters can be obtained throughout the lifetime of the Lc3Decoder instance.
|
||||
*
|
||||
* There is no possibility of changing Lc3Config within Lc3Decoder. When session
|
||||
* parameters have to be changed, the calling application has to create a new
|
||||
* instance of Lc3Decoder.
|
||||
*
|
||||
* Lc3 supports operation with variable encoded bitrate. It is possible to change
|
||||
* the bitrate from frame to frame, where for preciseness the parameter is not
|
||||
* given as bitrate directly but in terms of the byte_count per frame. This
|
||||
* parameter has to be in the range of 20 to 400
|
||||
* (see LC3 specification Section 3.2.5 "Bit budget and bitrate").
|
||||
* LC3 specification Sections 2.4 "Decoder interfaces" specifies "byte_count_max"
|
||||
* of the decoder to allow pre-allocation of resources. This parameter is provided
|
||||
* here for completeness and used for verifying the byte_count value of individual
|
||||
* frames only. The needed memory has to be provided by the calling application anyway,
|
||||
* so that it is up to the application whether a pre-allocation of memory is useful.
|
||||
*
|
||||
*/
|
||||
|
||||
class Lc3Decoder
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Convenience constructor of Lc3Decoder with two simple parameter only.
|
||||
* Note that this constructor instantiated Lc3Config implicitly with
|
||||
* Lc3Decoder(Lc3Config(Fs,frameDuration, 1)) that means that this
|
||||
* constructor provides processing of one channel (mono) and 16bit/sample
|
||||
* PCM output only.
|
||||
*
|
||||
* Parameters:
|
||||
* Fs : Sampling frequency in Hz -> see Lc3Config.hpp for supported values
|
||||
*
|
||||
* frameDuration : frame duration of 10ms (default) or 7.5ms
|
||||
* -> see Lc3Config.hpp for more details
|
||||
*/
|
||||
Lc3Decoder(uint16_t Fs, Lc3Config::FrameDuration frameDuration = Lc3Config::FrameDuration::d10ms);
|
||||
|
||||
/*
|
||||
* General constructor of Lc3Decoder.
|
||||
*
|
||||
* Parameters:
|
||||
* lc3Config_ : instance of Lc3Config. See documentation of Lc3Config for more details.
|
||||
* Note: providing an invalid instance of Lc3Config will result
|
||||
* in skipping any processing later.
|
||||
* The provided instance of Lc3Config will be copied to the
|
||||
* public field "lc3Config" (see below).
|
||||
*
|
||||
* bits_per_audio_sample_dec_ : Bits per audio sample for the output PCM signal.
|
||||
* See LC3 specification Section 2.4 "Decoder interfaces"
|
||||
* and Section 3.2.3 "Bits per sample" for the general LC3
|
||||
* requirement to support 16, 24 and 32 bit.
|
||||
* Note: This parameter may differ from the encoder input PCM
|
||||
* setting "bits_per_audio_sample_enc".
|
||||
*
|
||||
* byte_count_max_dec_ : Maximum allowed payload byte_count for a single channel.
|
||||
* When using and allowing external rate control, the maximum byte
|
||||
* count for the session may be used to configure the session buffers
|
||||
* without a need to dynamically reallocate memory during the session.
|
||||
*
|
||||
* datapoints : pointer to an instance of a class allowing to collect internal data.
|
||||
* Note: this feature is used and prepared for testing of the codec
|
||||
* implementation only. See general "Readme.txt"
|
||||
*/
|
||||
Lc3Decoder(Lc3Config lc3Config_, uint8_t bits_per_audio_sample_dec_ = 16, uint16_t byte_count_max_dec_ = 400, void* datapoints=nullptr);
|
||||
|
||||
// no default constructor supported
|
||||
Lc3Decoder() = delete;
|
||||
|
||||
// Destructor
|
||||
virtual ~Lc3Decoder();
|
||||
|
||||
/*
|
||||
* Configuration provided during instantiation accessible as public const fields.
|
||||
* Note: Lc3Config provides a getter to check whether the configuration is valid.
|
||||
*/
|
||||
const Lc3Config lc3Config;
|
||||
const uint8_t bits_per_audio_sample_dec;
|
||||
const uint16_t byte_count_max_dec;
|
||||
|
||||
// encoding error (see return values of "run" methods)
|
||||
static const uint8_t ERROR_FREE = 0x00;
|
||||
static const uint8_t INVALID_CONFIGURATION = 0x01;
|
||||
static const uint8_t INVALID_BYTE_COUNT = 0x02;
|
||||
static const uint8_t INVALID_X_OUT_SIZE = 0x03;
|
||||
static const uint8_t INVALID_BITS_PER_AUDIO_SAMPLE = 0x04;
|
||||
static const uint8_t DECODER_ALLOCATION_ERROR = 0x05;
|
||||
|
||||
/*
|
||||
* Decoding one 16 bit/sample output frame for one channel
|
||||
*
|
||||
* Note that this methods returns the error INVALID_BITS_PER_AUDIO_SAMPLE
|
||||
* when the session has been configured for any bits_per_audio_sample_dec != 16.
|
||||
*
|
||||
* Further, note that this method can be used for multi-channel configurations as well,
|
||||
* particularly when the provided multi-channel "run" (see below) is not supporting
|
||||
* the kind of byte stream concatenation existing in the calling application.
|
||||
*
|
||||
* Parameters:
|
||||
* bytes : pointer to byte array holding the input LC3 encoded byte stream
|
||||
* of the given channel.
|
||||
* The size of this memory is given by the byte_count parameter.
|
||||
*
|
||||
* byte_count : number of encoded bytes; byte count to be used for decoding
|
||||
* the received frame payload.
|
||||
* Supported values are 20 bytes to byte_count_max_dec bytes.
|
||||
*
|
||||
* BFI : Bad Frame Indication flags
|
||||
* "0" signifies that no bit errors where detected in given "bytes"
|
||||
* "1" signifies a corrupt payload packet was detected in given "bytes"
|
||||
*
|
||||
* x_out : pointer to output PCM data (16 bit/sample), where the memory
|
||||
* has to be provided by the calling application.
|
||||
*
|
||||
* x_out_size : number of 16 bit values supported by x_out
|
||||
* Note: this parameter has been introduced for clarity and
|
||||
* verification purpose only. The method will return
|
||||
* the error INVALID_X_OUT_SIZE when x_out_size != lc3Config.NF.
|
||||
*
|
||||
* BEC_detect : flag indication bit errors detected during decoding of input bytes
|
||||
* Note: a basic packet loss concealment (PLC) will be applied when
|
||||
* BEC_detect!=0, so that the returned audio data stays
|
||||
* somewhat acceptable.
|
||||
*
|
||||
* channelNr : index of channel to be processed (default=0), where channelNr < lc3Config.Nc
|
||||
*
|
||||
*
|
||||
* Return value: error code as listed above.
|
||||
*/
|
||||
uint8_t run(const uint8_t* bytes, uint16_t byte_count, uint8_t BFI,
|
||||
int16_t* x_out, uint16_t x_out_size, uint8_t& BEC_detect, uint8_t channelNr=0);
|
||||
|
||||
/*
|
||||
* Decoding one 16, 24, or 32 bit/sample output frame for one channel
|
||||
*
|
||||
* Note that every output PCM sample will need one 32 bit memory place in the
|
||||
* output stream independently from the configured bits_per_audio_sample_dec.
|
||||
*
|
||||
* Further, note that this method can be used for multi-channel configurations as well,
|
||||
* particularly when the provided multi-channel "run" (see below) is not supporting
|
||||
* the kind of byte stream concatenation existing in the calling application.
|
||||
*
|
||||
* Parameters:
|
||||
* bytes : pointer to byte array holding the input LC3 encoded byte stream
|
||||
* of the given channel.
|
||||
* The size of this memory is given by the byte_count parameter.
|
||||
*
|
||||
* byte_count : number of encoded bytes; byte count to be used for decoding
|
||||
* the received frame payload.
|
||||
* Supported values are 20 bytes to byte_count_max_dec bytes.
|
||||
*
|
||||
* BFI : Bad Frame Indication flags
|
||||
* "0" signifies that no bit errors where detected in given "bytes"
|
||||
* "1" signifies a corrupt payload packet was detected in given "bytes"
|
||||
*
|
||||
* x_out : pointer to output PCM data (memory 32 bit/sample, precision 16 bit/sample,
|
||||
* 24 bit/sample or 32 bit/sample), where the memory
|
||||
* has to be provided by the calling application.
|
||||
*
|
||||
* x_out_size : number of 32 bit values supported by x_out
|
||||
* Note: this parameter has been introduced for clarity and
|
||||
* verification purpose only. The method will return
|
||||
* the error INVALID_X_OUT_SIZE when x_out_size != lc3Config.NF.
|
||||
*
|
||||
* BEC_detect : flag indication bit errors detected during decoding of input bytes
|
||||
* Note: a basic packet loss concealment (PLC) will be applied when
|
||||
* BEC_detect!=0, so that the returned audio data stays
|
||||
* somewhat acceptable.
|
||||
*
|
||||
* channelNr : index of channel to be processed (default=0), where channelNr < lc3Config.Nc
|
||||
*
|
||||
*
|
||||
* Return value: error code as listed above.
|
||||
*/
|
||||
uint8_t run(const uint8_t* bytes, uint16_t byte_count, uint8_t BFI,
|
||||
int32_t* x_out, uint16_t x_out_size, uint8_t& BEC_detect, uint8_t channelNr=0);
|
||||
|
||||
/*
|
||||
* Decoding one 16 bit/sample output frame for multiple channels.
|
||||
*
|
||||
* Note that this methods returns the error INVALID_BITS_PER_AUDIO_SAMPLE
|
||||
* when the session has been configured for any bits_per_audio_sample_dec != 16.
|
||||
*
|
||||
* Parameters:
|
||||
* bytes : pointer to byte array holding the input LC3 encoded byte stream
|
||||
* of all given channels.
|
||||
* The size of this memory is given by the sum of all byte_count_per_channel
|
||||
* values (see parameter byte_count_per_channel).
|
||||
* Note that the encoded values of all channels are expected to be
|
||||
* concatenated without any stuffing bytes of meta data in between.
|
||||
*
|
||||
* byte_count_per_channel : number of encoded bytes; byte count to be used for decoding
|
||||
* the received frame payload per channel.
|
||||
* Thus, byte_count_per_channel is an array of byte_count values
|
||||
* with length lc3Conig.Nc
|
||||
* Supported values are 20 bytes to byte_count_max_dec bytes per
|
||||
* channel.
|
||||
*
|
||||
* BFI_per_channel : lc3Conig.Nc length array of Bad Frame Indication flags
|
||||
* "0" signifies that no bit errors where detected in given "bytes"
|
||||
* "1" signifies a corrupt payload packet was detected in given "bytes"
|
||||
*
|
||||
* x_out : pointer to output 16 bit/sample PCM data, where the memory
|
||||
* has to be provided by the calling application.
|
||||
*
|
||||
* x_out_size : number of 16 bit values supported by x_out
|
||||
* Note: this parameter has been introduced for clarity and
|
||||
* verification purpose only. The method will return
|
||||
* the error INVALID_X_OUT_SIZE when x_out_size != lc3Config.NF * lc3Conig.Nc.
|
||||
*
|
||||
* BEC_detect_per_channel : lc3Conig.Nc length array of flags indicating bit errors
|
||||
* detected during decoding of input bytes of a certain channel.
|
||||
* Note: a basic packet loss concealment (PLC) will be applied when
|
||||
* BEC_detect!=0, so that the returned audio data stays
|
||||
* somewhat acceptable.
|
||||
*
|
||||
*
|
||||
* Return value: error code via "or" concatenation of the error codes of processing
|
||||
* the individual channels. Note: this "or" concatenation make specific
|
||||
* error diagnosis impossible. Thus only checking != ERROR_FREE is meaningful.
|
||||
* When more specific information is needed, the single channel call (see above)
|
||||
* need to be called.
|
||||
*/
|
||||
uint8_t run(const uint8_t* bytes, const uint16_t* byte_count_per_channel, const uint8_t* BFI_per_channel,
|
||||
int16_t* x_out, uint32_t x_out_size, uint8_t* BEC_detect_per_channel);
|
||||
|
||||
/*
|
||||
* Decoding one 16, 24, or 32 bit/sample output frame for multiple channels
|
||||
*
|
||||
* Note that every output PCM sample will need one 32 bit memory place in the
|
||||
* output stream independently from the configured bits_per_audio_sample_dec.
|
||||
*
|
||||
* Parameters:
|
||||
* bytes : pointer to byte array holding the input LC3 encoded byte stream
|
||||
* of all given channels.
|
||||
* The size of this memory is given by the sum of all byte_count_per_channel
|
||||
* values (see parameter byte_count_per_channel).
|
||||
* Note that the encoded values of all channels are expected to be
|
||||
* concatenated without any stuffing bytes of meta data in between.
|
||||
*
|
||||
* byte_count_per_channel : number of encoded bytes; byte count to be used for decoding
|
||||
* the received frame payload per channel.
|
||||
* Thus, byte_count_per_channel is an array of byte_count values
|
||||
* with length lc3Conig.Nc
|
||||
* Supported values are 20 bytes to byte_count_max_dec bytes per
|
||||
* channel.
|
||||
*
|
||||
* BFI_per_channel : lc3Conig.Nc length array of Bad Frame Indication flags
|
||||
* "0" signifies that no bit errors where detected in given "bytes"
|
||||
* "1" signifies a corrupt payload packet was detected in given "bytes"
|
||||
*
|
||||
* x_out : pointer to output 16, 24, or 32 bit/sample PCM data, where the memory
|
||||
* has to be provided by the calling application.
|
||||
*
|
||||
* x_out_size : number of 32 bit values supported by x_out
|
||||
* Note: this parameter has been introduced for clarity and
|
||||
* verification purpose only. The method will return
|
||||
* the error INVALID_X_OUT_SIZE when x_out_size != lc3Config.NF * lc3Conig.Nc.
|
||||
*
|
||||
* BEC_detect_per_channel : lc3Conig.Nc length array of flags indicating bit errors
|
||||
* detected during decoding of input bytes of a certain channel.
|
||||
* Note: a basic packet loss concealment (PLC) will be applied when
|
||||
* BEC_detect!=0, so that the returned audio data stays
|
||||
* somewhat acceptable.
|
||||
*
|
||||
*
|
||||
* Return value: error code via "or" concatenation of the error codes of processing
|
||||
* the individual channels. Note: this "or" concatenation make specific
|
||||
* error diagnosis impossible. Thus only checking != ERROR_FREE is meaningful.
|
||||
* When more specific information is needed, the single channel call (see above)
|
||||
* need to be called.
|
||||
*/
|
||||
uint8_t run(const uint8_t* bytes, const uint16_t* byte_count_per_channel, const uint8_t* BFI_per_channel,
|
||||
int32_t* x_out, uint32_t x_out_size, uint8_t* BEC_detect_per_channel);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
std::vector<Lc3Dec::DecoderTop*> decoderList;
|
||||
};
|
||||
|
||||
#endif /* API_LC3DECODER_HPP_ */
|
192
3rd-party/liblc3codec/Api/Lc3Encoder.hpp
vendored
192
3rd-party/liblc3codec/Api/Lc3Encoder.hpp
vendored
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Lc3Encoder.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef API_LC3ENCODER_HPP_
|
||||
#define API_LC3ENCODER_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Lc3Config.hpp"
|
||||
|
||||
/*
|
||||
* Forward declaration of the "internal" class EncoderTop, so
|
||||
* that the private vector of single channel encoders can be declared in Lc3Encoder.
|
||||
*/
|
||||
namespace Lc3Enc
|
||||
{
|
||||
class EncoderTop;
|
||||
}
|
||||
|
||||
/*
|
||||
* The LC3 encoder interface is specified in
|
||||
* LC3 specification Sections 2.2 "Encoder interfaces" (dr09r07).
|
||||
*
|
||||
* Lc3Encoder is designed such that all specified features are provided
|
||||
* with the (current) exception of not providing other input bit depth
|
||||
* than 16 bit/sample. At the time of writing, the main purpose of the
|
||||
* implementation was to handle 16bit audio data provided within android
|
||||
* smartphones. Providing the specified 24bit and 32 bit audio data input,
|
||||
* would make the API more complex. However, the main argument to not support
|
||||
* these sample rates right now, is that internal operations and memory
|
||||
* consumption would have to be increased measurable otherwise.
|
||||
*
|
||||
* Instantiating Lc3Encoder implies providing a Lc3Config instance. A copy of
|
||||
* this instance is available as public const member so that all essential session
|
||||
* parameters can be obtained throughout the lifetime of the Lc3Encoder instance.
|
||||
*
|
||||
* There is no possibility of changing Lc3Config within Lc3Encoder. When session
|
||||
* parameters have to be changed, the calling application has to create a new
|
||||
* instance of Lc3Encoder.
|
||||
*
|
||||
* Lc3 supports operation with variable encoded bitrate. It is possible to change
|
||||
* the bitrate from frame to frame, where for preciseness the parameter is not
|
||||
* given as bit rate directly but in terms of the byte_count per frame. This
|
||||
* parameter has to be in the range of 20 to 400
|
||||
* (see LC3 specification Section 3.2.5 "Bit budget and bitrate")
|
||||
*
|
||||
*/
|
||||
|
||||
class Lc3Encoder
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Convenience constructor of Lc3Encoder with one simple parameter only.
|
||||
* Note that this constructor instantiated Lc3Config implicitly with
|
||||
* Lc3Config(Fs, Lc3Config::FrameDuration::d10ms, 1) that means that this
|
||||
* constructor provides processing of one channel (mono) with 10ms frame duration.
|
||||
*
|
||||
* Parameters:
|
||||
* Fs : Sampling frequency in Hz -> see Lc3Config.hpp for supported values
|
||||
*/
|
||||
Lc3Encoder(uint16_t Fs);
|
||||
|
||||
/*
|
||||
* General constructor of Lc3Encoder.
|
||||
*
|
||||
* Parameters:
|
||||
* lc3Config_ : instance of Lc3Config. See documentation of Lc3Config for more details.
|
||||
* Note: providing an invalid instance of Lc3Config will result
|
||||
* in skipping any processing later.
|
||||
* The provided instance of Lc3Config will be copied to the
|
||||
* public field "lc3Config" (see below).
|
||||
*
|
||||
* bits_per_audio_sample_enc_ : The bits per audio sample for the input PCM signal.
|
||||
* See LC3 specification Section 2.2 "Encoder interfaces"
|
||||
* and Section 3.2.3 "Bits per sample" for the general LC3
|
||||
* requirement to support 16, 24 and 32 bit.
|
||||
* Note: This parameter may differ from the decoder output PCM
|
||||
* setting "bits_per_audio_sample_dec".
|
||||
*
|
||||
* However, the current implementation allows 16 bit only
|
||||
* and will return an error INVALID_BITS_PER_AUDIO_SAMPLE
|
||||
* for run() when configured with any other value.
|
||||
* (see reasoning for this constraint in the general class
|
||||
* descripton above)
|
||||
*
|
||||
* datapoints : pointer to an instance of a class allowing to collect internal data.
|
||||
* Note: this feature is used and prepared for testing of the codec
|
||||
* implementation only. See general "Readme.txt"
|
||||
*/
|
||||
Lc3Encoder(Lc3Config lc3Config_, uint8_t bits_per_audio_sample_enc_ = 16, void* datapoints=nullptr);
|
||||
|
||||
// no default constructor supported
|
||||
Lc3Encoder() = delete;
|
||||
|
||||
// Destructor
|
||||
virtual ~Lc3Encoder();
|
||||
|
||||
/*
|
||||
* Configuration provided during instantiation accessible as public const fields.
|
||||
* Note: Lc3Config provides a getter to check whether the configuration is valid.
|
||||
*/
|
||||
const Lc3Config lc3Config;
|
||||
const uint8_t bits_per_audio_sample_enc;
|
||||
|
||||
// encoding errors (see return values of "run" methods)
|
||||
static const uint8_t ERROR_FREE = 0x00;
|
||||
static const uint8_t INVALID_CONFIGURATION = 0x01;
|
||||
static const uint8_t INVALID_BYTE_COUNT = 0x02;
|
||||
static const uint8_t INVALID_BITS_PER_AUDIO_SAMPLE = 0x03;
|
||||
static const uint8_t ENCODER_ALLOCATION_ERROR = 0x04;
|
||||
|
||||
|
||||
/*
|
||||
* Encoding of one input frame for one channel.
|
||||
*
|
||||
* Note that this method can be used for multi-channel configurations as well,
|
||||
* particularly when the provided multi-channel "run" (see below) is not providing
|
||||
* the kind of byte stream concatenation desired by a specific application.
|
||||
*
|
||||
* Parameters:
|
||||
* x : pointer to input signal array with 16bit/sample.
|
||||
* The length of the signal to be provided depends on the given
|
||||
* session configuration and can be obtained via
|
||||
* lc3Config.NF
|
||||
*
|
||||
* byte_count : determines the compression strength (-> bitrate) to be used
|
||||
* for this specific frame. Supported values are 20 bytes to 400 bytes,
|
||||
* where values well below 40 bytes typically give rather poor audio quality.
|
||||
* Note: in case of having an application targeting a given bitrate, the
|
||||
* helper method "lc3Config.getByteCountFromBitrate(.)" can be used
|
||||
* to compute the proper setting for this byte_count parameter.
|
||||
*
|
||||
* bytes : pointer to byte array (memory) provided by the application, where the
|
||||
* encoded byte stream will be placed. The size of this memory is given by
|
||||
* the byte_count parameter.
|
||||
*
|
||||
* channelNr : index of channel to be processed (default=0), where channelNr < lc3Config.Nc
|
||||
*
|
||||
* Return value: error code as listed above.
|
||||
*/
|
||||
uint8_t run(const int16_t* x, uint16_t byte_count, uint8_t* bytes, uint8_t channelNr=0);
|
||||
|
||||
/*
|
||||
* Encoding of one multi-channel frame.
|
||||
*
|
||||
* Note that this call always processes all channels configured in the given session.
|
||||
*
|
||||
* Parameters:
|
||||
* x : pointer to input signal array with 16bit/sample.
|
||||
* The length of the signal to be provided depends on the given
|
||||
* session configuration and can be obtained via
|
||||
* lc3Config.NF * lc3Config.Nc
|
||||
*
|
||||
* byte_count_per_channel : determines the compression strength (-> bitrate) to be used
|
||||
* for each channel individually of this specific frame.
|
||||
* Thus, byte_count_per_channel is an array of byte_count values
|
||||
* with length lc3Conig.Nc
|
||||
* Supported values per channel are 20 bytes to 400 bytes.
|
||||
* See also the documentation for the single channel "run" above.
|
||||
*
|
||||
* bytes : pointer to byte array (memory) provided by the application, where the
|
||||
* encoded byte stream will be placed. The size of this memory is given by
|
||||
* the byte_count_per_channel parameter, specifically by the sum of all
|
||||
* channel-wise byte_count values
|
||||
* (byte_count_per_channel[0] + ... + byte_count_per_channel[lc3Config.Nc])
|
||||
* This implies that the encoded bytes from the individual channels are
|
||||
* concatenated directly (without any stuffing bytes or meta information).
|
||||
*
|
||||
* Return value: error code as listed above.
|
||||
*/
|
||||
uint8_t run(const int16_t* x, const uint16_t* byte_count_per_channel, uint8_t* bytes);
|
||||
|
||||
private:
|
||||
std::vector<Lc3Enc::EncoderTop*> encoderList;
|
||||
};
|
||||
|
||||
#endif /* API_LC3ENCODER_HPP_ */
|
261
3rd-party/liblc3codec/Common/DctIV.cpp
vendored
261
3rd-party/liblc3codec/Common/DctIV.cpp
vendored
@ -1,261 +0,0 @@
|
||||
/*
|
||||
* DctIV.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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 "DctIV.hpp"
|
||||
#include <cmath>
|
||||
|
||||
/*
|
||||
* Notes on the choice of the applied FFT library:
|
||||
* - Different fast transform implementations for the DCT-IV can be selected via
|
||||
* USE_FFTW
|
||||
* USE_FFTW_FOR_FFT // assume NF being 4 times an integer
|
||||
* USE_KISSFFT // assume NF being 4 times an integer
|
||||
* where only one of them is meaningful to be defined
|
||||
*
|
||||
* - Defining none of the fast transforms will lead to a direct implementation
|
||||
* which is good for testing but usually to slow for practial applications
|
||||
*
|
||||
* - USE_FFTW: The free "fftw" library should be fastest, but may be more complicated to be build
|
||||
* for embedded target devices. It provides dedicated optimization for the DCT-IV
|
||||
* and thus is preferred from a technical perspective. In terms of licences "fftw"
|
||||
* is free in the sense of GPL, which is not liked in some products. There might be the option
|
||||
* to ask the authors for other licences (which they propose). Nevertheless, the "license" issue
|
||||
* has driven us to not bundle "fftw" directly with the LC3 implementation, although the API
|
||||
* for using it is provided and tested.
|
||||
*
|
||||
* - USE_FFTW_FOR_FFT: this is a not fully optimized alternative approach using the complex fft
|
||||
* provided by "fftw" instead of the dedicated optimized DCT-IV implementation. This option
|
||||
* is mainly provided to demonstrate the transition from USE_FFTW to USE_KISSFFT
|
||||
*
|
||||
* - USE_KISSFFT: the free "kissfft" library is sligthly slower than "fftw", but gives a majority
|
||||
* of the possible performance gain over a "stupid" direct DCT-IV implementation.
|
||||
* "kissfft" does not provide a dedicated optimization for DCT-IV so that some additional code
|
||||
* for implementing a DCT-IV by a complex fft has to be added. This also implies additional
|
||||
* memory needed.
|
||||
* The big advantage of the "kissfft" is that it is less restrictive
|
||||
* in terms of its license. Further, the template based C++ implementation reduces its impact
|
||||
* on the build system to a minimum (we just need to include the right header without needing
|
||||
* to compile and link a separate file).
|
||||
*
|
||||
* - USE_KISSFFT is defined below to be the default choice. The other alternatives may be selecting
|
||||
* by providing its define via the compiler switch -D<define>
|
||||
*
|
||||
* - The impact of the defines is restricted to this *.cpp file for clarity reasons.
|
||||
* Ok, to make this work, we needed a few "ugly" pointer casts, but we really wanted to make
|
||||
* sure, that no other code or build impact is generated by the options in this file.
|
||||
*/
|
||||
#define USE_KISSFFT
|
||||
|
||||
|
||||
#if defined USE_FFTW || defined USE_FFTW_FOR_FFT
|
||||
#include <fftw3.h>
|
||||
|
||||
#elif defined USE_KISSFFT
|
||||
#include "kissfft.hh"
|
||||
|
||||
class KissfftConfig
|
||||
{
|
||||
public:
|
||||
KissfftConfig(uint16_t N)
|
||||
: inbuf(nullptr), outbuf(nullptr), fft(nullptr)
|
||||
{
|
||||
inbuf = new std::complex<double>[N];
|
||||
outbuf = new std::complex<double>[N];
|
||||
twiddle = new std::complex<double>[N];
|
||||
fft = new kissfft<double>(N, false);
|
||||
|
||||
const double pi = std::acos(-1);
|
||||
for (uint16_t n=0; n < N; n++)
|
||||
{
|
||||
twiddle[n] = std::complex<double>( std::cos(-pi*(8*n+1)/(8.0*N*2)), std::sin(-pi*(8*n+1)/(8.0*N*2)) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~KissfftConfig()
|
||||
{
|
||||
if (nullptr != fft)
|
||||
{
|
||||
delete fft;
|
||||
}
|
||||
if (nullptr != inbuf)
|
||||
{
|
||||
delete[] inbuf;
|
||||
}
|
||||
if (nullptr != outbuf)
|
||||
{
|
||||
delete[] outbuf;
|
||||
}
|
||||
if (nullptr != twiddle)
|
||||
{
|
||||
delete[] twiddle;
|
||||
}
|
||||
}
|
||||
|
||||
void transform()
|
||||
{
|
||||
if (nullptr != fft)
|
||||
{
|
||||
fft->transform( inbuf, outbuf );
|
||||
}
|
||||
}
|
||||
|
||||
std::complex<double>* inbuf;
|
||||
std::complex<double>* outbuf;
|
||||
std::complex<double>* twiddle;
|
||||
kissfft<double>* fft;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
DctIVDbl::DctIVDbl(uint16_t NF_) :
|
||||
NF(NF_),
|
||||
in(nullptr),
|
||||
out(nullptr),
|
||||
dctIVconfig(nullptr)
|
||||
{
|
||||
in = new double[NF];
|
||||
out = new double[NF];
|
||||
|
||||
#if defined USE_FFTW
|
||||
dctIVconfig = fftw_plan_r2r_1d(NF, in, out, FFTW_REDFT11, FFTW_ESTIMATE);
|
||||
|
||||
#elif defined USE_FFTW_FOR_FFT
|
||||
dctIVconfig = fftw_plan_dft_1d( NF/2,
|
||||
reinterpret_cast<fftw_complex*>(in),
|
||||
reinterpret_cast<fftw_complex*>(out),
|
||||
FFTW_FORWARD, FFTW_ESTIMATE);
|
||||
|
||||
#elif defined USE_KISSFFT
|
||||
dctIVconfig = new KissfftConfig(NF/2);
|
||||
|
||||
#endif
|
||||
|
||||
for (uint16_t n=0; n < NF; n++)
|
||||
{
|
||||
in[n]=0;
|
||||
out[n]=0;
|
||||
}
|
||||
}
|
||||
|
||||
DctIVDbl::~DctIVDbl()
|
||||
{
|
||||
#if defined USE_FFTW || defined USE_FFTW_FOR_FFT
|
||||
if (nullptr != dctIVconfig)
|
||||
{
|
||||
fftw_destroy_plan(reinterpret_cast<fftw_plan>(dctIVconfig));
|
||||
}
|
||||
|
||||
#elif defined USE_KISSFFT
|
||||
if (nullptr != dctIVconfig)
|
||||
{
|
||||
KissfftConfig* kissfftConfig = reinterpret_cast<KissfftConfig*>(dctIVconfig);
|
||||
delete kissfftConfig;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (nullptr != in)
|
||||
{
|
||||
delete[] in;
|
||||
}
|
||||
if (nullptr != out)
|
||||
{
|
||||
delete[] out;
|
||||
}
|
||||
}
|
||||
|
||||
void DctIVDirectDbl(uint16_t N, const double* const tw, double* const X)
|
||||
{
|
||||
const double pi = std::acos(-1);
|
||||
for (uint16_t k=0; k < N; k++)
|
||||
{
|
||||
X[k] = 0;
|
||||
for (uint16_t n=0; n < N; n++)
|
||||
{
|
||||
X[k] += tw[n] * std::cos( pi / N * (n+0.5)*(k+0.5) );
|
||||
}
|
||||
X[k] *= 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DctIVDbl::run()
|
||||
{
|
||||
#ifdef USE_FFTW
|
||||
fftw_execute(reinterpret_cast<fftw_plan>(dctIVconfig));
|
||||
|
||||
#elif defined USE_FFTW_FOR_FFT
|
||||
const double pi = std::acos(-1);
|
||||
// assume NF being 4 times an integer
|
||||
for (uint16_t n=1; n < NF/2; n+=2)
|
||||
{
|
||||
double buffer;
|
||||
buffer = in[n];
|
||||
in[n] = in[NF-n];
|
||||
in[NF-n] = buffer;
|
||||
}
|
||||
for (uint16_t n=0; n < NF; n+=2)
|
||||
{
|
||||
double real = in[n+0];
|
||||
double imag = in[n+1];
|
||||
in[n+0] = real * std::cos( -pi*(4*n+1)/(8.0*NF) )
|
||||
- imag * std::sin( -pi*(4*n+1)/(8.0*NF) );
|
||||
in[n+1] = real * std::sin( -pi*(4*n+1)/(8.0*NF) )
|
||||
+ imag * std::cos( -pi*(4*n+1)/(8.0*NF) );
|
||||
}
|
||||
|
||||
fftw_execute(reinterpret_cast<fftw_plan>(dctIVconfig));
|
||||
|
||||
for (uint16_t n=0; n < NF; n+=2)
|
||||
{
|
||||
double real = out[n+0];
|
||||
double imag = out[n+1];
|
||||
out[n+0] = 2*(real * std::cos( -pi*(4*n+1)/(8.0*NF) )
|
||||
- imag * std::sin( -pi*(4*n+1)/(8.0*NF) ) );
|
||||
out[n+1] = 2*(real * std::sin( -pi*(4*n+1)/(8.0*NF) )
|
||||
+ imag * std::cos( -pi*(4*n+1)/(8.0*NF) ) );
|
||||
}
|
||||
for (uint16_t n=1; n < NF/2; n+=2)
|
||||
{
|
||||
double buffer;
|
||||
buffer = out[n];
|
||||
out[n] = -out[NF-n];
|
||||
out[NF-n] = -buffer;
|
||||
}
|
||||
|
||||
#elif defined USE_KISSFFT
|
||||
// assume NF being 4 times an integer
|
||||
KissfftConfig* kissfftConfig = reinterpret_cast<KissfftConfig*>(dctIVconfig);
|
||||
for (uint16_t n=0; n < NF/2; n++)
|
||||
{
|
||||
kissfftConfig->inbuf[n] = kissfftConfig->twiddle[n] * std::complex<double>( in[2*n], in[NF-2*n-1] );
|
||||
}
|
||||
|
||||
kissfftConfig->transform();
|
||||
|
||||
for (uint16_t n=0; n < NF/2; n++)
|
||||
{
|
||||
std::complex<double> complexOut = kissfftConfig->twiddle[n] * kissfftConfig->outbuf[n];
|
||||
out[2*n] = complexOut.real()*2;
|
||||
out[NF-2*n-1] = -complexOut.imag()*2;
|
||||
}
|
||||
|
||||
#else
|
||||
DctIVDirectDbl(NF, in, out);
|
||||
#endif
|
||||
}
|
38
3rd-party/liblc3codec/Common/DctIV.hpp
vendored
38
3rd-party/liblc3codec/Common/DctIV.hpp
vendored
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* DctIV.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DCT_IV_H_
|
||||
#define DCT_IV_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class DctIVDbl
|
||||
{
|
||||
public:
|
||||
DctIVDbl(uint16_t NF_);
|
||||
virtual ~DctIVDbl();
|
||||
|
||||
void run();
|
||||
|
||||
const uint16_t NF;
|
||||
double* in;
|
||||
double* out;
|
||||
void* dctIVconfig;
|
||||
};
|
||||
|
||||
#endif // DCT_IV_H_
|
157
3rd-party/liblc3codec/Common/Lc3Config.cpp
vendored
157
3rd-party/liblc3codec/Common/Lc3Config.cpp
vendored
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Lc3Config.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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 "Lc3Config.hpp"
|
||||
#include <cmath>
|
||||
|
||||
Lc3Config::Lc3Config(uint16_t Fs_, FrameDuration N_ms_, uint8_t Nc_)
|
||||
:
|
||||
errorStatus(ERROR_FREE),
|
||||
Fs(Fs_),
|
||||
Fs_ind(getFs_ind(Fs)),
|
||||
N_ms(N_ms_),
|
||||
NF(getNF(Fs, N_ms_)),
|
||||
NE(getNE(NF, N_ms_)),
|
||||
Z( (N_ms==FrameDuration::d10ms) ? 3*NF/8 : 7*NF/30 ),
|
||||
Nc(Nc_),
|
||||
N_b( ((N_ms == Lc3Config::FrameDuration::d7p5ms) && (Fs==8000)) ? 60 : 64 )
|
||||
{
|
||||
if (0==Nc) // we do not restrict the maximum yet (naturally limited to 255 because of the chosen datatype)
|
||||
{
|
||||
errorStatus |= INVALID_NUMBER_OF_CHANNELS;
|
||||
}
|
||||
}
|
||||
|
||||
Lc3Config::~Lc3Config()
|
||||
{
|
||||
}
|
||||
|
||||
bool Lc3Config::isValid() const
|
||||
{
|
||||
return ERROR_FREE == errorStatus;
|
||||
}
|
||||
|
||||
uint8_t Lc3Config::getErrorStatus() const
|
||||
{
|
||||
return errorStatus;
|
||||
}
|
||||
|
||||
uint8_t Lc3Config::getFs_ind(uint16_t Fs)
|
||||
{
|
||||
uint8_t fs_ind=0;
|
||||
switch(Fs)
|
||||
{
|
||||
case 8000: fs_ind=0; break;
|
||||
case 16000: fs_ind=1; break;
|
||||
case 24000: fs_ind=2; break;
|
||||
case 32000: fs_ind=3; break;
|
||||
case 44100:;
|
||||
case 48000: fs_ind=4; break;
|
||||
default:
|
||||
errorStatus |= INVALID_SAMPLING_RATE;
|
||||
}
|
||||
return fs_ind;
|
||||
}
|
||||
|
||||
|
||||
uint16_t Lc3Config::getNF(uint16_t Fs, FrameDuration N_ms)
|
||||
{
|
||||
uint16_t NF = 80;
|
||||
if (FrameDuration::d10ms == N_ms)
|
||||
{
|
||||
switch(Fs)
|
||||
{
|
||||
case 8000: NF=80; break;
|
||||
case 16000: NF=160; break;
|
||||
case 24000: NF=240; break;
|
||||
case 32000: NF=320; break;
|
||||
case 44100:;
|
||||
case 48000: NF=480; break;
|
||||
default :
|
||||
errorStatus |= INVALID_SAMPLING_RATE;
|
||||
}
|
||||
}
|
||||
else if (FrameDuration::d7p5ms == N_ms)
|
||||
{
|
||||
switch(Fs)
|
||||
{
|
||||
case 8000: NF=60; break;
|
||||
case 16000: NF=120; break;
|
||||
case 24000: NF=180; break;
|
||||
case 32000: NF=240; break;
|
||||
case 44100:;
|
||||
case 48000: NF=360; break;
|
||||
default :
|
||||
errorStatus |= INVALID_SAMPLING_RATE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We never should reach this line unless
|
||||
// strange things happen. However, we want
|
||||
// to be on the safe side and thus handle
|
||||
// this case explicitly.
|
||||
errorStatus |= INVALID_FRAME_DURATION;
|
||||
}
|
||||
return NF;
|
||||
}
|
||||
|
||||
uint16_t Lc3Config::getNE(uint16_t NF, FrameDuration N_ms)
|
||||
{
|
||||
//3.3.4.3 Time-Frequency Transformation (d09r04_*implementorComments*)
|
||||
if (FrameDuration::d10ms == N_ms)
|
||||
{
|
||||
return (480==NF) ? 400:NF;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (360==NF) ? 300:NF;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Lc3Config::getByteCountFromBitrate(uint32_t bitrate) const
|
||||
{
|
||||
// Section 3.2.5 Bit budget and bitrate (LC3_Specification_d09r06)
|
||||
double f_scal = getFscal();
|
||||
double N_ms_value = getNmsValue();
|
||||
return floor( (bitrate * N_ms_value * f_scal)/8000.0 );
|
||||
}
|
||||
|
||||
uint32_t Lc3Config::getBitrateFromByteCount(uint16_t nbytes) const
|
||||
{
|
||||
// Section 3.2.5 Bit budget and bitrate (LC3_Specification_d1.0r03)
|
||||
// Notes:
|
||||
// - this implementation includes Errata 15051
|
||||
// - this utility function is not used within the LC3 code so far, but
|
||||
// provided here for completeness
|
||||
double f_scal = getFscal();
|
||||
double N_ms_value = getNmsValue();
|
||||
return ceil( (8000.0 * nbytes) / (N_ms_value * f_scal) );
|
||||
}
|
||||
|
||||
double Lc3Config::getFscal() const
|
||||
{
|
||||
// Section 3.2.2 Sampling rates (LC3_Specification_d1.0r03)
|
||||
return (44100==Fs)? 48000.0/44100.0 : 1.0;
|
||||
}
|
||||
|
||||
double Lc3Config::getNmsValue() const
|
||||
{
|
||||
return (FrameDuration::d10ms == N_ms) ? 10.0 : 7.5;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* BandIndexTables.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.1 Band Tables Index I_fs
|
||||
#include "BandIndexTables.hpp"
|
||||
|
||||
// LC3 Specification d09r01.pdf; Page 86 of 177
|
||||
// LC3 Specification Section 3.7.2 (d09r04_*implementorComments*)
|
||||
// Page 115 of 256
|
||||
// Band tables index I_fs for 10 ms frame duration
|
||||
int I_8000[65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,80};
|
||||
int I_16000[65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,30,32,34,36,38,40,42,44,46,48,50,52,55,58,61,64,67,70,73,76,80,84,88,92,96,101,106,111,116,121,127,133,139,146,153,160};
|
||||
int I_24000[65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25,27,29,31,33,35,37,39,41,43,46,49,52,55,58,61,64,68,72,76,80,85,90,95,100,106,112,118,125,132,139,147,155,164,173,183,193,204,215,227,240};
|
||||
int I_32000[65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22,24,26,28,30,32,34,36,38,41,44,47,50,53,56,60,64,68,72,76,81,86,91,97,103,109,116,123,131,139,148,157,166,176,187,199,211,224,238,252,268,284,302,320};
|
||||
int I_48000[65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,24,26,28,30,32,34,36,39,42,45,48,51,55,59,63,67,71,76,81,86,92,98,105,112,119,127,135,144,154,164,175,186,198,211,225,240,256,273,291,310,330,352,375,400};
|
||||
|
||||
|
||||
// LC3 Specification Section 3.7.2 (d09r04_*implementorComments*)
|
||||
// Page 115/116 of 256
|
||||
// Band tables index I_fs for 7.5 ms frame duration
|
||||
int I_8000_7p5ms[61] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60};
|
||||
int I_16000_7p5ms [65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,65,68,71,74,77,80,83,86,90,94,98,102,106,110,115,120};
|
||||
int I_24000_7p5ms [65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,29,31,33,35,37,39,41,43,45,47,49,52,55,58,61,64,67,70,74,78,82,86,90,95,100,105,110,115,121,127,134,141,148,155,163,171,180};
|
||||
int I_32000_7p5ms [65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,28,30,32,34,36,38,40,42,45,48,51,54,57,60,63,67,71,75,79,84,89,94,99,105,111,117,124,131,138,146,154,163,172,182,192,203,215,227,240};
|
||||
int I_48000_7p5ms [65] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,24,26,28,30,32,34,36,38,40,43,46,49,52,55,59,63,67,71,75,80,85,90,96,102,108,115,122,129,137,146,155,165,175,186,197,209,222,236,251,266,283,300};
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* BandIndexTables.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BAND_INDEX_TABLES_H_
|
||||
#define BAND_INDEX_TABLES_H_
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.1 Band Tables Index I_fs
|
||||
|
||||
// LC3 Specification d09r04_*implementorComments*
|
||||
// Section 3.7.1 Band tables index I_fs for 10 ms frame duration
|
||||
|
||||
extern int I_8000[65];
|
||||
extern int I_16000[65];
|
||||
extern int I_24000[65];
|
||||
extern int I_32000[65];
|
||||
extern int I_48000[65];
|
||||
|
||||
// LC3 Specification d09r04_*implementorComments*
|
||||
// Section 3.7.2 Band tables index I_fs for 7.5 ms frame duration
|
||||
|
||||
extern int I_8000_7p5ms[61];
|
||||
extern int I_16000_7p5ms [65];
|
||||
extern int I_24000_7p5ms [65];
|
||||
extern int I_32000_7p5ms [65];
|
||||
extern int I_48000_7p5ms [65];
|
||||
|
||||
#endif // BAND_INDEX_TABLES_H_
|
@ -1,176 +0,0 @@
|
||||
/*
|
||||
* LongTermPostfilterCoefficients.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.5 Long Term Postfiltering
|
||||
#include "LongTermPostfilterCoefficients.hpp"
|
||||
|
||||
// LC3 Specification d09r01.pdf; Page 110 of 177
|
||||
double tab_resamp_filter[239] = {
|
||||
-2.043055832879108e-05, -4.463458936757081e-05, -7.163663994481459e-05,
|
||||
-1.001011132655914e-04, -1.283728480660395e-04, -1.545438297704662e-04,
|
||||
-1.765445671257668e-04, -1.922569599584802e-04, -1.996438192500382e-04,
|
||||
-1.968886856400547e-04, -1.825383318834690e-04, -1.556394266046803e-04,
|
||||
-1.158603651792638e-04, -6.358930335348977e-05, +2.810064795067786e-19,
|
||||
+7.292180213001337e-05, +1.523970757644272e-04, +2.349207769898906e-04,
|
||||
+3.163786496265269e-04, +3.922117380894736e-04, +4.576238491064392e-04,
|
||||
+5.078242936704864e-04, +5.382955231045915e-04, +5.450729176175875e-04,
|
||||
+5.250221548270982e-04, +4.760984242947349e-04, +3.975713799264791e-04,
|
||||
+2.902002172907180e-04, +1.563446669975615e-04, -5.818801416923580e-19,
|
||||
-1.732527127898052e-04, -3.563859653300760e-04, -5.411552308801147e-04,
|
||||
-7.184140229675020e-04, -8.785052315963854e-04, -1.011714513697282e-03,
|
||||
-1.108767055632304e-03, -1.161345220483996e-03, -1.162601694464620e-03,
|
||||
-1.107640974148221e-03, -9.939415631563015e-04, -8.216921898513225e-04,
|
||||
// LC3 Specification d09r01.pdf; Page 111 of 177
|
||||
-5.940177657925908e-04, -3.170746535382728e-04, +9.746950818779534e-19,
|
||||
+3.452937604228947e-04, +7.044808705458705e-04, +1.061334465662964e-03,
|
||||
+1.398374734488549e-03, +1.697630799350524e-03, +1.941486748731660e-03,
|
||||
+2.113575906669355e-03, +2.199682452179964e-03, +2.188606246517629e-03,
|
||||
+2.072945458973295e-03, +1.849752491313908e-03, +1.521021876908738e-03,
|
||||
+1.093974255016849e-03, +5.811080624426164e-04, -1.422482656398999e-18,
|
||||
-6.271537303228204e-04, -1.274251404913447e-03, -1.912238389850182e-03,
|
||||
-2.510269249380764e-03, -3.037038298629825e-03, -3.462226871101535e-03,
|
||||
-3.758006719596473e-03, -3.900532466948409e-03, -3.871352309895838e-03,
|
||||
-3.658665583679722e-03, -3.258358512646846e-03, -2.674755551508349e-03,
|
||||
-1.921033054368456e-03, -1.019254326838640e-03, +1.869623690895593e-18,
|
||||
+1.098415446732263e-03, +2.231131973532823e-03, +3.348309272768835e-03,
|
||||
+4.397022774386510e-03, +5.323426722644900e-03, +6.075105310368700e-03,
|
||||
+6.603520247552113e-03, +6.866453987193027e-03, +6.830342695906946e-03,
|
||||
+6.472392343549424e-03, +5.782375213956374e-03, +4.764012726389739e-03,
|
||||
+3.435863514113467e-03, +1.831652835406657e-03, -2.251898372838663e-18,
|
||||
-1.996476188279370e-03, -4.082668858919100e-03, -6.173080374929424e-03,
|
||||
-8.174448945974208e-03, -9.988823864332691e-03, -1.151698705819990e-02,
|
||||
-1.266210056063963e-02, -1.333344579518481e-02, -1.345011199343934e-02,
|
||||
-1.294448809639154e-02, -1.176541543002924e-02, -9.880867320401294e-03,
|
||||
-7.280036402392082e-03, -3.974730209151807e-03, +2.509617777250391e-18,
|
||||
+4.586044219717467e-03, +9.703248998383679e-03, +1.525124770818010e-02,
|
||||
+2.111205854013017e-02, +2.715337236094137e-02, +3.323242450843114e-02,
|
||||
+3.920032029020130e-02, +4.490666443426786e-02, +5.020433088017846e-02,
|
||||
+5.495420172681558e-02, +5.902970324375908e-02, +6.232097270672976e-02,
|
||||
+6.473850225260731e-02, +6.621612450840858e-02, +6.671322871619612e-02,
|
||||
+6.621612450840858e-02, +6.473850225260731e-02, +6.232097270672976e-02,
|
||||
+5.902970324375908e-02, +5.495420172681558e-02, +5.020433088017846e-02,
|
||||
+4.490666443426786e-02, +3.920032029020130e-02, +3.323242450843114e-02,
|
||||
+2.715337236094137e-02, +2.111205854013017e-02, +1.525124770818010e-02,
|
||||
+9.703248998383679e-03, +4.586044219717467e-03, +2.509617777250391e-18,
|
||||
-3.974730209151807e-03, -7.280036402392082e-03, -9.880867320401294e-03,
|
||||
-1.176541543002924e-02, -1.294448809639154e-02, -1.345011199343934e-02,
|
||||
-1.333344579518481e-02, -1.266210056063963e-02, -1.151698705819990e-02,
|
||||
-9.988823864332691e-03, -8.174448945974208e-03, -6.173080374929424e-03,
|
||||
-4.082668858919100e-03, -1.996476188279370e-03, -2.251898372838663e-18,
|
||||
+1.831652835406657e-03, +3.435863514113467e-03, +4.764012726389739e-03,
|
||||
+5.782375213956374e-03, +6.472392343549424e-03, +6.830342695906946e-03,
|
||||
+6.866453987193027e-03, +6.603520247552113e-03, +6.075105310368700e-03,
|
||||
+5.323426722644900e-03, +4.397022774386510e-03, +3.348309272768835e-03,
|
||||
+2.231131973532823e-03, +1.098415446732263e-03, +1.869623690895593e-18,
|
||||
-1.019254326838640e-03, -1.921033054368456e-03, -2.674755551508349e-03,
|
||||
-3.258358512646846e-03, -3.658665583679722e-03, -3.871352309895838e-03,
|
||||
-3.900532466948409e-03, -3.758006719596473e-03, -3.462226871101535e-03,
|
||||
-3.037038298629825e-03, -2.510269249380764e-03, -1.912238389850182e-03,
|
||||
-1.274251404913447e-03, -6.271537303228204e-04, -1.422482656398999e-18,
|
||||
+5.811080624426164e-04, +1.093974255016849e-03, +1.521021876908738e-03,
|
||||
+1.849752491313908e-03, +2.072945458973295e-03, +2.188606246517629e-03,
|
||||
+2.199682452179964e-03, +2.113575906669355e-03, +1.941486748731660e-03,
|
||||
+1.697630799350524e-03, +1.398374734488549e-03, +1.061334465662964e-03,
|
||||
+7.044808705458705e-04, +3.452937604228947e-04, +9.746950818779534e-19,
|
||||
-3.170746535382728e-04, -5.940177657925908e-04, -8.216921898513225e-04,
|
||||
-9.939415631563015e-04, -1.107640974148221e-03, -1.162601694464620e-03,
|
||||
-1.161345220483996e-03, -1.108767055632304e-03, -1.011714513697282e-03,
|
||||
-8.785052315963854e-04, -7.184140229675020e-04, -5.411552308801147e-04,
|
||||
-3.563859653300760e-04, -1.732527127898052e-04, -5.818801416923580e-19,
|
||||
// LC3 Specification d09r01.pdf; Page 112 of 177
|
||||
+1.563446669975615e-04, +2.902002172907180e-04, +3.975713799264791e-04,
|
||||
+4.760984242947349e-04, +5.250221548270982e-04, +5.450729176175875e-04,
|
||||
+5.382955231045915e-04, +5.078242936704864e-04, +4.576238491064392e-04,
|
||||
+3.922117380894736e-04, +3.163786496265269e-04, +2.349207769898906e-04,
|
||||
+1.523970757644272e-04, +7.292180213001337e-05, +2.810064795067786e-19,
|
||||
-6.358930335348977e-05, -1.158603651792638e-04, -1.556394266046803e-04,
|
||||
-1.825383318834690e-04, -1.968886856400547e-04, -1.996438192500382e-04,
|
||||
-1.922569599584802e-04, -1.765445671257668e-04, -1.545438297704662e-04,
|
||||
-1.283728480660395e-04, -1.001011132655914e-04, -7.163663994481459e-05,
|
||||
-4.463458936757081e-05, -2.043055832879108e-05};
|
||||
double tab_ltpf_interp_R[31] = {
|
||||
-2.874561161519444e-03, -3.001251025861499e-03, +2.745471654059321e-03,
|
||||
+1.535727698935322e-02, +2.868234046665657e-02, +2.950385026557377e-02,
|
||||
+4.598334491135473e-03, -4.729632459043440e-02, -1.058359163062837e-01,
|
||||
-1.303050213607112e-01, -7.544046357555201e-02, +8.357885725250529e-02,
|
||||
+3.301825710764459e-01, +6.032970076366158e-01, +8.174886856243178e-01,
|
||||
+8.986382851273982e-01, +8.174886856243178e-01, +6.032970076366158e-01,
|
||||
+3.301825710764459e-01, +8.357885725250529e-02, -7.544046357555201e-02,
|
||||
-1.303050213607112e-01, -1.058359163062837e-01, -4.729632459043440e-02,
|
||||
+4.598334491135473e-03, +2.950385026557377e-02, +2.868234046665657e-02,
|
||||
+1.535727698935322e-02, +2.745471654059321e-03, -3.001251025861499e-03,
|
||||
-2.874561161519444e-03};
|
||||
double tab_ltpf_interp_x12k8[15] = {
|
||||
+6.698858366939680e-03, +3.967114782344967e-02, +1.069991860896389e-01,
|
||||
+2.098804630681809e-01, +3.356906254147840e-01, +4.592209296082350e-01,
|
||||
+5.500750019177116e-01, +5.835275754221211e-01, +5.500750019177116e-01,
|
||||
+4.592209296082350e-01, +3.356906254147840e-01, +2.098804630681809e-01,
|
||||
+1.069991860896389e-01, +3.967114782344967e-02, +6.698858366939680e-03};
|
||||
double tab_ltpf_num_8000[4][3] = {
|
||||
{6.023618207009578e-01,4.197609261363617e-01,-1.883424527883687e-02},
|
||||
{5.994768582584314e-01,4.197609261363620e-01,-1.594928283631041e-02},
|
||||
{5.967764663733787e-01,4.197609261363617e-01,-1.324889095125780e-02},
|
||||
{5.942410120098895e-01,4.197609261363618e-01,-1.071343658776831e-02}};
|
||||
double tab_ltpf_num_16000[4][3] = {
|
||||
{6.023618207009578e-01,4.197609261363617e-01,-1.883424527883687e-02},
|
||||
{5.994768582584314e-01,4.197609261363620e-01,-1.594928283631041e-02},
|
||||
{5.967764663733787e-01,4.197609261363617e-01,-1.324889095125780e-02},
|
||||
{5.942410120098895e-01,4.197609261363618e-01,-1.071343658776831e-02}};
|
||||
double tab_ltpf_num_24000[4][5] = {
|
||||
{3.989695588963494e-01,5.142508607708275e-01,1.004382966157454e-01,-1.278893956818042e-02,-1.572280075461383e-03},
|
||||
{3.948634911286333e-01,5.123819208048688e-01,1.043194926386267e-01,-1.091999960222166e-02,-1.347408330627317e-03},
|
||||
{3.909844475885914e-01,5.106053522688359e-01,1.079832524685944e-01,-9.143431066188848e-03,-1.132124620551895e-03},
|
||||
{3.873093888199928e-01,5.089122083363975e-01,1.114517380217371e-01,-7.450287133750717e-03,-9.255514050963111e-04}};
|
||||
double tab_ltpf_num_32000[4][7] = {
|
||||
// LC3 Specification d09r01.pdf; Page 113 of 177
|
||||
{2.982379446702096e-01,4.652809203721290e-01,2.105997428614279e-01,3.766780380806063e-02,-1.015696155796564e-02,-2.535880996101096e-03,-3.182946168719958e-04},
|
||||
{2.943834154510240e-01,4.619294002718798e-01,2.129465770091844e-01,4.066175002688857e-02,-8.693272297010050e-03,-2.178307114679820e-03,-2.742888063983188e-04},
|
||||
{2.907439213122688e-01,4.587461910960279e-01,2.151456974108970e-01,4.350104772529774e-02,-7.295495347716925e-03,-1.834395637237086e-03,-2.316920186482416e-04},
|
||||
{2.872975852589158e-01,4.557148886861379e-01,2.172126950911401e-01,4.620088878229615e-02,-5.957463802125952e-03,-1.502934284345198e-03,-1.903851911308866e-04}};
|
||||
double tab_ltpf_num_48000[4][11] = {
|
||||
{1.981363739883217e-01,3.524494903964904e-01,2.513695269649414e-01,1.424146237314458e-01,5.704731023952599e-02,9.293366241586384e-03,-7.226025368953745e-03,-3.172679890356356e-03,-1.121835963567014e-03,-2.902957238400140e-04,-4.270815593769240e-05},
|
||||
{1.950709426598375e-01,3.484660408341632e-01,2.509988459466574e-01,1.441167412482088e-01,5.928947317677285e-02,1.108923827452231e-02,-6.192908108653504e-03,-2.726705509251737e-03,-9.667125826217151e-04,-2.508100923165204e-04,-3.699938766131869e-05},
|
||||
{1.921810055196015e-01,3.446945561091513e-01,2.506220094626024e-01,1.457102447664837e-01,6.141132133664525e-02,1.279941396562798e-02,-5.203721087886321e-03,-2.297324511109085e-03,-8.165608133217555e-04,-2.123855748277408e-04,-3.141271330981649e-05},
|
||||
{1.894485314175868e-01,3.411139251108252e-01,2.502406876894361e-01,1.472065631098081e-01,6.342477229539051e-02,1.443203434150312e-02,-4.254449144657098e-03,-1.883081472613493e-03,-6.709619060722140e-04,-1.749363341966872e-04,-2.593864735284285e-05}};
|
||||
double tab_ltpf_den_8000[4][5] = {
|
||||
{0.000000000000000e+00, 2.098804630681809e-01, 5.835275754221211e-01, 2.098804630681809e-01, 0.000000000000000e+00},
|
||||
{0.000000000000000e+00, 1.069991860896389e-01, 5.500750019177116e-01, 3.356906254147840e-01, 6.698858366939680e-03},
|
||||
{0.000000000000000e+00, 3.967114782344967e-02, 4.592209296082350e-01, 4.592209296082350e-01, 3.967114782344967e-02},
|
||||
{0.000000000000000e+00, 6.698858366939680e-03, 3.356906254147840e-01, 5.500750019177116e-01, 1.069991860896389e-01}};
|
||||
double tab_ltpf_den_16000[4][5] = {
|
||||
{0.000000000000000e+00, 2.098804630681809e-01, 5.835275754221211e-01, 2.098804630681809e-01, 0.000000000000000e+00},
|
||||
{0.000000000000000e+00, 1.069991860896389e-01, 5.500750019177116e-01, 3.356906254147840e-01, 6.698858366939680e-03},
|
||||
{0.000000000000000e+00, 3.967114782344967e-02, 4.592209296082350e-01, 4.592209296082350e-01, 3.967114782344967e-02},
|
||||
{0.000000000000000e+00, 6.698858366939680e-03, 3.356906254147840e-01, 5.500750019177116e-01, 1.069991860896389e-01}};
|
||||
double tab_ltpf_den_24000[4][7] = {
|
||||
{0.000000000000000e+00, 6.322231627323796e-02, 2.507309606013235e-01, 3.713909428901578e-01, 2.507309606013235e-01, 6.322231627323796e-02, 0.000000000000000e+00},
|
||||
// LC3 Specification d09r01.pdf; Page 114 of 177
|
||||
{0.000000000000000e+00, 3.459272174099855e-02, 1.986515602645028e-01, 3.626411726581452e-01, 2.986750548992179e-01, 1.013092873505928e-01, 4.263543712369752e-03},
|
||||
{0.000000000000000e+00, 1.535746784963907e-02, 1.474344878058222e-01, 3.374259553990717e-01, 3.374259553990717e-01, 1.474344878058222e-01, 1.535746784963907e-02},
|
||||
{0.000000000000000e+00, 4.263543712369752e-03, 1.013092873505928e-01, 2.986750548992179e-01, 3.626411726581452e-01, 1.986515602645028e-01, 3.459272174099855e-02}};
|
||||
double tab_ltpf_den_32000[4][9] = {
|
||||
{0.000000000000000e+00, 2.900401878228730e-02, 1.129857420560927e-01, 2.212024028097570e-01, 2.723909472446145e-01, 2.212024028097570e-01, 1.129857420560927e-01, 2.900401878228730e-02, 0.000000000000000e+00},
|
||||
{0.000000000000000e+00, 1.703153418385261e-02, 8.722503785537784e-02, 1.961407762232199e-01, 2.689237982237257e-01, 2.424999102756389e-01, 1.405773364650031e-01, 4.474877169485788e-02, 3.127030243100724e-03},
|
||||
{0.000000000000000e+00, 8.563673748488349e-03, 6.426222944493845e-02, 1.687676705918012e-01, 2.587445937795505e-01, 2.587445937795505e-01, 1.687676705918012e-01, 6.426222944493845e-02, 8.563673748488349e-03},
|
||||
{0.000000000000000e+00, 3.127030243100724e-03, 4.474877169485788e-02, 1.405773364650031e-01, 2.424999102756389e-01, 2.689237982237257e-01, 1.961407762232199e-01, 8.722503785537784e-02, 1.703153418385261e-02}};
|
||||
double tab_ltpf_den_48000[4][13] = {
|
||||
{0.000000000000000e+00, 1.082359386659387e-02, 3.608969221303979e-02, 7.676401468099964e-02, 1.241530577501703e-01, 1.627596438300696e-01, 1.776771417779109e-01, 1.627596438300696e-01, 1.241530577501703e-01, 7.676401468099964e-02, 3.608969221303979e-02, 1.082359386659387e-02, 0.000000000000000e+00},
|
||||
{0.000000000000000e+00, 7.041404930459358e-03, 2.819702319820420e-02, 6.547044935127551e-02, 1.124647986743299e-01, 1.548418956489015e-01, 1.767122381341857e-01, 1.691507213057663e-01, 1.352901577989766e-01, 8.851425011427483e-02, 4.499353848562444e-02, 1.557613714732002e-02, 2.039721956502016e-03},
|
||||
{0.000000000000000e+00, 4.146998467444788e-03, 2.135757310741917e-02, 5.482735584552816e-02, 1.004971444643720e-01, 1.456060342830002e-01, 1.738439838565869e-01, 1.738439838565869e-01, 1.456060342830002e-01, 1.004971444643720e-01, 5.482735584552816e-02, 2.135757310741917e-02, 4.146998467444788e-03},
|
||||
{0.000000000000000e+00, 2.039721956502016e-03, 1.557613714732002e-02, 4.499353848562444e-02, 8.851425011427483e-02, 1.352901577989766e-01, 1.691507213057663e-01, 1.767122381341857e-01, 1.548418956489015e-01, 1.124647986743299e-01, 6.547044935127551e-02, 2.819702319820420e-02, 7.041404930459358e-03}};
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* LongTermPostfilterCoefficients.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.5 Long Term Postfiltering
|
||||
|
||||
#ifndef LONG_TERM_POSTFILTER_COEFFICIENTS_H_
|
||||
#define LONG_TERM_POSTFILTER_COEFFICIENTS_H_
|
||||
|
||||
extern double tab_resamp_filter[239];
|
||||
extern double tab_ltpf_interp_R[31];
|
||||
extern double tab_ltpf_interp_x12k8[15];
|
||||
extern double tab_ltpf_num_8000[4][3];
|
||||
extern double tab_ltpf_num_16000[4][3];
|
||||
extern double tab_ltpf_num_24000[4][5];
|
||||
extern double tab_ltpf_num_32000[4][7];
|
||||
extern double tab_ltpf_num_48000[4][11];
|
||||
extern double tab_ltpf_den_8000[4][5];
|
||||
extern double tab_ltpf_den_16000[4][5];
|
||||
extern double tab_ltpf_den_24000[4][7];
|
||||
extern double tab_ltpf_den_32000[4][9];
|
||||
extern double tab_ltpf_den_48000[4][13];
|
||||
|
||||
#endif // LONG_TERM_POSTFILTER_COEFFICIENTS_H_
|
934
3rd-party/liblc3codec/Common/Tables/MdctWindows.cpp
vendored
934
3rd-party/liblc3codec/Common/Tables/MdctWindows.cpp
vendored
File diff suppressed because one or more lines are too long
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* MdctWindows.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MDCT_WINDOWS_H_
|
||||
#define MDCT_WINDOWS_H_
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.2
|
||||
|
||||
// LC3 Specification d09r04_*implementorComments*
|
||||
// Section 3.7.3 Low delay MDCT windows
|
||||
// Section 3.7.3.1 10 ms Frame Duration
|
||||
|
||||
extern double w_N80[160];
|
||||
extern double w_N160[320];
|
||||
extern double w_N240[480];
|
||||
extern double w_N320[640];
|
||||
extern double w_N480[960];
|
||||
|
||||
// Section 3.7.3.2 7.5 ms Frame Duration
|
||||
|
||||
extern double w_N60_7p5ms[120];
|
||||
extern double w_N120_7p5ms[240];
|
||||
extern double w_N180_7p5ms[360];
|
||||
extern double w_N240_7p5ms[480];
|
||||
extern double w_N360_7p5ms[720];
|
||||
|
||||
|
||||
#endif // MDCT_WINDOWS_H_
|
@ -1,355 +0,0 @@
|
||||
/*
|
||||
* SnsQuantizationTables.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.3 SNS Quantization
|
||||
|
||||
// LC3 Specification d09r04_*implementorComments*
|
||||
// Section 3.7.4 SNS Quantization
|
||||
|
||||
#include "SnsQuantizationTables.hpp"
|
||||
|
||||
// LC3 Specification d09r01.pdf; Page 102 of 177
|
||||
double LFCB[32][8] = {{ +2.262833655926780e+00, +8.133112690613385e-01, -5.301934948714359e-01,
|
||||
-1.356648359034418e+00, -1.599521765631959e+00, -1.440987684300950e+00,
|
||||
-1.143816483058210e+00, -7.552037679090641e-01}, //0
|
||||
{+2.945164791913764e+00, +2.411433179566788e+00, +9.604551064007274e-01,
|
||||
-4.432264880769172e-01, -1.229136124255896e+00, -1.555900391181699e+00,
|
||||
-1.496886559523759e+00, -1.116899865014692e+00}, //1
|
||||
{-2.186107070099790e+00, -1.971521356752276e+00, -1.787186196810059e+00,
|
||||
-1.918658956855768e+00, -1.793991218365963e+00, -1.357384042572884e+00,
|
||||
-7.054442793538694e-01, -4.781729447777114e-02}, //2
|
||||
{+6.936882365289195e-01, +9.556098571582197e-01, +5.752307870387333e-01,
|
||||
-1.146034194628886e-01, -6.460506374360290e-01, -9.523513704496247e-01,
|
||||
-1.074052472261504e+00, -7.580877070949045e-01}, //3
|
||||
{-1.297521323152956e+00, -7.403690571778526e-01, -3.453724836421064e-01,
|
||||
-3.132856962479401e-01, -4.029772428244766e-01, -3.720208534652272e-01,
|
||||
-7.834141773237381e-02, +9.704413039922949e-02}, //4
|
||||
{+9.146520378306716e-01, +1.742930434352573e+00, +1.909066268599861e+00,
|
||||
+1.544084838426651e+00, +1.093449607614550e+00, +6.474795495182776e-01,
|
||||
+3.617907524496421e-02, -2.970928071788889e-01}, //5
|
||||
{-2.514288125789621e+00, -2.891752713843728e+00, -2.004506667594338e+00,
|
||||
-7.509122739031269e-01, +4.412021049046914e-01, +1.201909876010087e+00,
|
||||
+1.327428572572904e+00, +1.220490811409839e+00}, //6
|
||||
{-9.221884048123851e-01, +6.324951414405520e-01, +1.087364312546411e+00,
|
||||
+6.086286245358197e-01, +1.311745675473482e-01, -2.961491577437521e-01,
|
||||
-2.070135165256287e-01, +1.349249166420795e-01}, //7
|
||||
{+7.903222883692664e-01, +6.284012618761988e-01, +3.931179235404499e-01,
|
||||
+4.800077108669007e-01, +4.478151380501427e-01, +2.097342145522343e-01,
|
||||
+6.566919964280205e-03, -8.612423420618573e-02}, //8
|
||||
// LC3 Specification d09r01.pdf; Page 103 of 177
|
||||
{+1.447755801787238e+00, +2.723999516749523e+00, +2.310832687375278e+00,
|
||||
+9.350512695665294e-01, -2.747439113836877e-01, -9.020776968286019e-01,
|
||||
-9.406815119454044e-01, -6.336970389743102e-01}, //9
|
||||
{+7.933545264174744e-01, +1.439311855234535e-02, -5.678348447296789e-01,
|
||||
-6.547604679167449e-01, -4.794589984757430e-01, -1.738946619028885e-01,
|
||||
+6.801627055154381e-02, +2.951259483697938e-01}, //10
|
||||
{+2.724253473850336e+00, +2.959475724048243e+00, +1.849535592684608e+00,
|
||||
+5.632849223223643e-01, +1.399170881250724e-01, +3.596410933662221e-01,
|
||||
+6.894613547745887e-01, +6.397901768331046e-01}, //11
|
||||
{-5.308301983754000e-01, -2.126906828121638e-01, +5.766136283770966e-03,
|
||||
+4.248714843837454e-01, +4.731289521586675e-01, +8.588941993212806e-01,
|
||||
+1.191111608544352e+00, +9.961896696383581e-01}, //12
|
||||
{+1.687284108450062e+00, +2.436145092376558e+00, +2.330194290782250e+00,
|
||||
+1.779837778350905e+00, +1.444112953900818e+00, +1.519951770097301e+00,
|
||||
+1.471993937504249e+00, +9.776824738917613e-01}, //13
|
||||
{-2.951832728018580e+00, -1.593934967733454e+00, -1.099187728780224e-01,
|
||||
+3.886090729192574e-01, +5.129326495175837e-01, +6.281125970634966e-01,
|
||||
+8.226217964306339e-01, +8.758914246550805e-01}, //14
|
||||
{+1.018783427856281e-01, +5.898573242289165e-01, +6.190476467934656e-01,
|
||||
+1.267313138517963e+00, +2.419610477698038e+00, +2.251742525721865e+00,
|
||||
+5.265370309912005e-01, -3.965915132279989e-01}, //15
|
||||
{+2.682545754984259e+00, +1.327380108994199e+00, +1.301852738040482e-01,
|
||||
-3.385330885113471e-01, -3.682192358996665e-01, -1.916899467159607e-01,
|
||||
-1.547823771539079e-01, -2.342071777743923e-01}, //16
|
||||
{+4.826979236804030e+00, +3.119478044924880e+00, +1.395136713851784e+00,
|
||||
+2.502953159187215e-01, -3.936138393797931e-01, -6.434581730547007e-01,
|
||||
-6.425707368569433e-01, -7.231932234440720e-01}, //17
|
||||
{+8.784199364703349e-02, -5.695868402385010e-01, -1.145060156688110e+00,
|
||||
-1.669684881725975e+00, -1.845344176036817e+00, -1.564680273288019e+00,
|
||||
-1.117467590764198e+00, -5.339816633667862e-01}, //18
|
||||
{+1.391023082043259e+00, +1.981464791994655e+00, +1.112657963887701e+00,
|
||||
-2.201075094207434e-01, -7.749656115523655e-01, -5.940638741491173e-01,
|
||||
+1.369376806289231e-01, +8.182428912643381e-01}, //19
|
||||
{+3.845858938891820e-01, -1.605887855365100e-01, -5.393668095577095e-01,
|
||||
-5.293090787898571e-01, +1.904335474379324e-01, +2.560629181065215e+00,
|
||||
+2.818963982452484e+00, +6.566708756961611e-01}, //20
|
||||
{+1.932273994417191e+00, +3.010301804120569e+00, +3.065438938262036e+00,
|
||||
+2.501101608700079e+00, +1.930895929789344e+00, +5.721538109618367e-01,
|
||||
-8.117417940810907e-01, -1.176418108619025e+00}, //21
|
||||
{+1.750804628998837e-01, -7.505228322489846e-01, -1.039438933422309e+00,
|
||||
-1.135775089376484e+00, -1.041979038374938e+00, -1.520600989933816e-02,
|
||||
+2.070483917167066e+00, +3.429489180816891e+00}, //22
|
||||
// LC3 Specification d09r01.pdf; Page 104 of 177
|
||||
{-1.188170202505555e+00, +3.667928736626364e-01, +1.309578304090959e+00,
|
||||
+1.683306872804914e+00, +1.251009242251268e+00, +9.423757516286146e-01,
|
||||
+8.262504833741330e-01, +4.399527411209563e-01}, //23
|
||||
{+2.533222033270612e+00, +2.112746426959081e+00, +1.262884115020644e+00,
|
||||
+7.615135124304274e-01, +5.221179379761699e-01, +1.186800697571213e-01,
|
||||
-4.523468275073703e-01, -7.003524261611032e-01}, //24
|
||||
{+3.998898374856063e+00, +4.079017514519560e+00, +2.822856611024964e+00,
|
||||
+1.726072128495800e+00, +6.471443773486192e-01, -3.311485212172380e-01,
|
||||
-8.840425708487493e-01, -1.126973406454781e+00}, //25
|
||||
{+5.079025931863813e-01, +1.588384497895265e+00, +1.728990238692094e+00,
|
||||
+1.006922302417256e+00, +3.771212318163816e-01, +4.763707668994976e-01,
|
||||
+1.087547403721699e+00, +1.087562660992209e+00}, //26
|
||||
{+3.168568251075689e+00, +3.258534581594065e+00, +2.422305913285988e+00,
|
||||
+1.794460776432612e+00, +1.521779106530886e+00, +1.171967065376021e+00,
|
||||
+4.893945969806952e-01, -6.227957157187685e-02}, //27
|
||||
{+1.894147667317636e+00, +1.251086946092320e+00, +5.904512107206275e-01,
|
||||
+6.083585832937136e-01, +8.781710100110816e-01, +1.119125109509496e+00,
|
||||
+1.018576615503421e+00, +6.204538910117241e-01}, //28
|
||||
{+9.488806045171881e-01, +2.132394392499823e+00, +2.723453503442780e+00,
|
||||
+2.769860768665877e+00, +2.542869732549456e+00, +2.020462638250194e+00,
|
||||
+8.300458594009102e-01, -2.755691738882634e-02}, //29
|
||||
{-1.880267570456275e+00, -1.264310727587049e+00, +3.114249769686986e-01,
|
||||
+1.836702103064300e+00, +2.256341918398738e+00, +2.048189984634735e+00,
|
||||
+2.195268374585677e+00, +2.026596138366193e+00}, //30
|
||||
{+2.463757462771289e-01, +9.556217733930993e-01, +1.520467767417663e+00,
|
||||
+1.976474004194571e+00, +1.940438671774617e+00, +2.233758472826862e+00,
|
||||
+1.988359777584072e+00, +1.272326725547010e+00 }}; //31
|
||||
double HFCB[32][8] = {
|
||||
{+2.320284191244650e-01, -1.008902706044547e+00, -2.142235027894714e+00,
|
||||
-2.375338135706641e+00, -2.230419330496551e+00, -2.175958812236960e+00,
|
||||
-2.290659135409999e+00, -2.532863979798455e+00}, //0
|
||||
{-1.295039366736175e+00, -1.799299653843385e+00, -1.887031475315188e+00,
|
||||
-1.809916596873323e+00, -1.763400384792061e+00, -1.834184284679500e+00,
|
||||
-1.804809806874051e+00, -1.736795453174010e+00}, //1
|
||||
{+1.392857160458027e-01, -2.581851261717519e-01, -6.508045726701103e-01,
|
||||
-1.068157317819692e+00, -1.619287415243023e+00, -2.187625664417564e+00,
|
||||
-2.637575869390537e+00, -2.978977495750963e+00}, //2
|
||||
{-3.165131021857248e-01, -4.777476572098050e-01, -5.511620758797545e-01,
|
||||
-4.847882833811970e-01, -2.383883944558142e-01, -1.430245072855038e-01,
|
||||
+6.831866736490735e-02, +8.830617172880660e-02}, //3
|
||||
{+8.795184052264962e-01, +2.983400960071886e-01, -9.153863964057101e-01,
|
||||
// LC3 Specification d09r01.pdf; Page 105 of 177
|
||||
-2.206459747397620e+00, -2.741421809599509e+00, -2.861390742768913e+00,
|
||||
-2.888415971052714e+00, -2.951826082625207e+00}, //4
|
||||
{-2.967019224553751e-01, -9.750049191745525e-01, -1.358575002469926e+00,
|
||||
-9.837211058374442e-01, -6.529569391008090e-01, -9.899869929218105e-01,
|
||||
-1.614672245988999e+00, -2.407123023851163e+00}, //5
|
||||
{+3.409811004696971e-01, +2.688997889460545e-01, +5.633356848280326e-02,
|
||||
+4.991140468266853e-02, -9.541307274143691e-02, -7.601661460838854e-01,
|
||||
-2.327581201770068e+00, -3.771554853856562e+00}, //6
|
||||
{-1.412297590775968e+00, -1.485221193498518e+00, -1.186035798347001e+00,
|
||||
-6.250016344413516e-01, +1.539024974683036e-01, +5.763864978107553e-01,
|
||||
+7.950926037988714e-01, +5.965646321449126e-01}, //7
|
||||
{-2.288395118273794e-01, -3.337190697846616e-01, -8.093213593246560e-01,
|
||||
-1.635878769237973e+00, -1.884863973309819e+00, -1.644966913163562e+00,
|
||||
-1.405157780466116e+00, -1.466664713261457e+00}, //8
|
||||
{-1.071486285444486e+00, -1.417670154562606e+00, -1.548917622654407e+00,
|
||||
-1.452960624755303e+00, -1.031829700622701e+00, -6.906426402725842e-01,
|
||||
-4.288438045321706e-01, -4.949602154088736e-01}, //9
|
||||
{-5.909885111880511e-01, -7.117377585376282e-02, +3.457195229473127e-01,
|
||||
+3.005494609962507e-01, -1.118652182958568e+00, -2.440891511480490e+00,
|
||||
-2.228547324507349e+00, -1.895092282108533e+00}, //10
|
||||
{-8.484340988361639e-01, -5.832268107088888e-01, +9.004236881428734e-02,
|
||||
+8.450250075568864e-01, +1.065723845017161e+00, +7.375829993777555e-01,
|
||||
+2.565904524599121e-01, -4.919633597623784e-01}, //11
|
||||
{+1.140691455623824e+00, +9.640168923982929e-01, +3.814612059847975e-01,
|
||||
-4.828493406089983e-01, -1.816327212605887e+00, -2.802795127285548e+00,
|
||||
-3.233857248338638e+00, -3.459087144914729e+00}, //12
|
||||
{-3.762832379674643e-01, +4.256754620961052e-02, +5.165476965923055e-01,
|
||||
+2.517168818646298e-01, -2.161799675243032e-01, -5.340740911245042e-01,
|
||||
-6.407860962621957e-01, -8.697450323741350e-01}, //13
|
||||
{+6.650041205984020e-01, +1.097907646907945e+00, +1.383426671120792e+00,
|
||||
+1.343273586282854e+00, +8.229788368559223e-01, +2.158767985156789e-01,
|
||||
-4.049257530802925e-01, -1.070256058705229e+00}, //14
|
||||
{-8.262659539826793e-01, -6.711812327666034e-01, -2.284955927794715e-01,
|
||||
+5.189808525519373e-01, +1.367218963402784e+00, +2.180230382530922e+00,
|
||||
+2.535960927501071e+00, +2.201210988600361e+00}, //15
|
||||
{+1.410083268321729e+00, +7.544419078354684e-01, -1.305505849586310e+00,
|
||||
-1.871337113509707e+00, -1.240086851563054e+00, -1.267129248662737e+00,
|
||||
-2.036708130039070e+00, -2.896851622423807e+00}, //16
|
||||
{+3.613868175743476e-01, -2.199917054278258e-02, -5.793688336338242e-01,
|
||||
-8.794279609410701e-01, -8.506850234081188e-01, -7.793970501558157e-01,
|
||||
-7.321829272918255e-01, -8.883485148212548e-01}, //17
|
||||
{+4.374692393303287e-01, +3.054404196059607e-01, -7.387865664783739e-03,
|
||||
// LC3 Specification d09r01.pdf; Page 106 of 177
|
||||
-4.956498547102520e-01, -8.066512711183929e-01, -1.224318919844005e+00,
|
||||
-1.701577700431810e+00, -2.244919137556108e+00}, //18
|
||||
{+6.481003189965029e-01, +6.822991336406795e-01, +2.532474643329756e-01,
|
||||
+7.358421437884688e-02, +3.142167093890103e-01, +2.347298809236790e-01,
|
||||
+1.446001344798368e-01, -6.821201788801744e-02}, //19
|
||||
{+1.119198330913041e+00, +1.234655325360046e+00, +5.891702380853181e-01,
|
||||
-1.371924596531664e+00, -2.370957072415767e+00, -2.007797826823599e+00,
|
||||
-1.666885402243946e+00, -1.926318462584058e+00}, //20
|
||||
{+1.418474970871759e-01, -1.106600706331509e-01, -2.828245925436287e-01,
|
||||
-6.598134746141936e-03, +2.859292796272158e-01, +4.604455299529710e-02,
|
||||
-6.025964155778858e-01, -2.265687286325748e+00}, //21
|
||||
{+5.040469553902519e-01, +8.269821629590972e-01, +1.119812362918282e+00,
|
||||
+1.179140443327336e+00, +1.079874291972597e+00, +6.975362390675000e-01,
|
||||
-9.125488173710808e-01, -3.576847470627726e+00}, //22
|
||||
{-5.010760504793567e-01, -3.256780060814170e-01, +2.807981949470768e-02,
|
||||
+2.620545547631326e-01, +3.605908060857668e-01, +6.356237220536995e-01,
|
||||
+9.590124671781544e-01, +1.307451566886533e+00}, //23
|
||||
{+3.749709827096420e+00, +1.523426118470452e+00, -4.577156618978547e-01,
|
||||
-7.987110082431923e-01, -3.868193293091003e-01, -3.759010622312032e-01,
|
||||
-6.578368999305377e-01, -1.281639642436027e+00}, //24
|
||||
{-1.152589909805491e+00, -1.108008859062412e+00, -5.626151165124718e-01,
|
||||
-2.205621237656746e-01, -3.498428803366437e-01, -7.534327702504950e-01,
|
||||
-9.885965933963837e-01, -1.287904717914711e+00}, //25
|
||||
{+1.028272464221398e+00, +1.097705193898282e+00, +7.686455457647760e-01,
|
||||
+2.060819777407656e-01, -3.428057350919982e-01, -7.549394046253397e-01,
|
||||
-1.041961776319998e+00, -1.503356529555287e+00}, //26
|
||||
{+1.288319717078174e-01, +6.894393952648783e-01, +1.123469050095749e+00,
|
||||
+1.309345231065936e+00, +1.355119647139345e+00, +1.423113814707990e+00,
|
||||
+1.157064491909045e+00, +4.063194375168383e-01}, //27
|
||||
{+1.340330303347565e+00, +1.389968250677893e+00, +1.044679217088833e+00,
|
||||
+6.358227462443666e-01, -2.747337555184823e-01, -1.549233724306950e+00,
|
||||
-2.442397102780069e+00, -3.024576069445502e+00}, //28
|
||||
{+2.138431054193125e+00, +4.247112673031041e+00, +2.897341098304393e+00,
|
||||
+9.327306580268148e-01, -2.928222497298096e-01, -8.104042968531823e-01,
|
||||
-7.888680987564828e-01, -9.353531487613377e-01}, //29
|
||||
{+5.648304873553961e-01, +1.591849779587432e+00, +2.397716990151462e+00,
|
||||
+3.036973436007040e+00, +2.664243503371508e+00, +1.393044850326060e+00,
|
||||
+4.038340235957454e-01, -6.562709713281135e-01}, //30
|
||||
{-4.224605475860865e-01, +3.261496250498011e-01, +1.391713133422612e+00,
|
||||
+2.231466146364735e+00, +2.611794421696881e+00, +2.665403401965702e+00,
|
||||
+2.401035541057067e+00, +1.759203796708810e+00} //31
|
||||
};
|
||||
// LC3 Specification d09r01.pdf; Page 107 of 177
|
||||
double sns_vq_reg_adj_gains[2] = {8915.0/4096.0, 12054.0/4096.0};
|
||||
double sns_vq_reg_lf_adj_gains[4] = {6245.0/4096.0, 15043.0/4096.0, 17861.0/4096.0, 21014.0/4096.0};
|
||||
double sns_vq_near_adj_gains[4] = {7099.0/4096.0, 9132.0/4096.0, 11253.0/4096.0, 14808.0/4096.0};
|
||||
double sns_vq_far_adj_gains[8] = {4336.0/4096.0, 5067.0/4096.0, 5895.0/4096.0, 8149.0/4096.0,
|
||||
10235.0/4096.0, 12825.0/4096.0, 16868.0/4096.0, 19882.0/4096.0};
|
||||
int sns_gainMSBbits[4]={1,1,2,2};
|
||||
int sns_gainLSBbits[4]={0,1,0,1};
|
||||
unsigned int MPVQ_offsets[16][1+10]= { /* k=0, k=1, k=2,... , k=10 */
|
||||
{0,1,1,1,1,1,1,1,1,1,1}, /* n=0*/
|
||||
{0,1,3,5,7,9,11,13,15,17,19}, /* n=1*/
|
||||
{0,1,5,13,25,41,61,85,113,145,181},
|
||||
{0,1,7,25,63,129,231,377,575,833,1159},
|
||||
{0,1,9,41,129,321,681,1289,2241,3649,5641},
|
||||
{0,1,11,61,231,681,1683,3653,7183,13073,22363},
|
||||
{0,1,13,85,377,1289,3653,8989,19825,40081,75517},
|
||||
{0,1,15,113,575,2241,7183,19825,48639,108545,224143},
|
||||
{0,1,17,145,833,3649,13073,40081,108545,265729,598417},
|
||||
{0,1,19,181,1159,5641,22363,75517,224143,598417,1462563},
|
||||
{0,1,21,221,1561,8361,36365,134245,433905,1256465,3317445},
|
||||
{0,1,23,265,2047,11969,56695,227305,795455,2485825,7059735},
|
||||
{0,1,25,313,2625,16641,85305,369305,1392065,4673345,14218905},
|
||||
{0,1,27,365,3303,22569,124515,579125,2340495,8405905,27298155},
|
||||
{0,1,29,421,4089,29961,177045,880685,3800305,14546705,50250765}, /* n=14*/
|
||||
{0,1,31,481,4991,39041,246047,1303777,5984767,24331777,89129247}, /* n=15*/
|
||||
};
|
||||
double D[16][16] = {
|
||||
/* D consists of the base vectors of the DCT (orthogonalized DCT-II)*/
|
||||
/* (the DCT base vector are stored in column-wise in this table)*/
|
||||
/* first row results in the first coeff in fwd synthesis (dec+(enc))*/
|
||||
/* first column results in the first coeff in the analysis(encoder) */
|
||||
{+2.500000000000000e-01, +3.518509343815957e-01, +3.467599613305369e-01,
|
||||
+3.383295002935882e-01, +3.266407412190941e-01, +3.118062532466678e-01,
|
||||
+2.939689006048397e-01, +2.733004667504394e-01, +2.500000000000001e-01,
|
||||
+2.242918965856591e-01, +1.964237395967756e-01, +1.666639146194367e-01,
|
||||
+1.352990250365493e-01, +1.026311318805893e-01, +6.897484482073578e-02,
|
||||
+3.465429229977293e-02}, // 0 Note: needed a ',' as correction compared to d09r01 (already fixed in d09r02_F2F)
|
||||
{+2.500000000000000e-01, +3.383295002935882e-01, +2.939689006048397e-01,
|
||||
+2.242918965856591e-01, +1.352990250365493e-01, +3.465429229977286e-02,
|
||||
-6.897484482073579e-02, -1.666639146194366e-01, -2.500000000000001e-01,
|
||||
-3.118062532466678e-01, -3.467599613305369e-01, -3.518509343815956e-01,
|
||||
-3.266407412190941e-01, -2.733004667504394e-01, -1.964237395967756e-01,
|
||||
-1.026311318805893e-01}, // 1
|
||||
// LC3 Specification d09r01.pdf; Page 108 of 177
|
||||
{+2.500000000000000e-01, +3.118062532466678e-01, +1.964237395967756e-01,
|
||||
+3.465429229977286e-02, -1.352990250365493e-01, -2.733004667504394e-01,
|
||||
-3.467599613305369e-01, -3.383295002935882e-01, -2.500000000000001e-01,
|
||||
-1.026311318805894e-01, +6.897484482073574e-02, +2.242918965856590e-01,
|
||||
+3.266407412190941e-01, +3.518509343815957e-01, +2.939689006048397e-01,
|
||||
+1.666639146194367e-01}, // 2
|
||||
{+2.500000000000000e-01, +2.733004667504394e-01, +6.897484482073575e-02,
|
||||
-1.666639146194366e-01, -3.266407412190941e-01, -3.383295002935882e-01,
|
||||
-1.964237395967755e-01, +3.465429229977288e-02, +2.500000000000001e-01,
|
||||
+3.518509343815957e-01, +2.939689006048397e-01, +1.026311318805893e-01,
|
||||
-1.352990250365493e-01, -3.118062532466679e-01, -3.467599613305369e-01,
|
||||
-2.242918965856590e-01}, // 3
|
||||
{+2.500000000000000e-01, +2.242918965856591e-01, -6.897484482073575e-02,
|
||||
-3.118062532466678e-01, -3.266407412190941e-01, -1.026311318805894e-01,
|
||||
+1.964237395967755e-01, +3.518509343815957e-01, +2.500000000000001e-01,
|
||||
-3.465429229977282e-02, -2.939689006048397e-01, -3.383295002935882e-01,
|
||||
-1.352990250365493e-01, +1.666639146194367e-01, +3.467599613305369e-01,
|
||||
+2.733004667504394e-01}, // 4
|
||||
{+2.500000000000000e-01, +1.666639146194366e-01, -1.964237395967756e-01,
|
||||
-3.518509343815956e-01, -1.352990250365493e-01, +2.242918965856591e-01,
|
||||
+3.467599613305369e-01, +1.026311318805894e-01, -2.500000000000001e-01,
|
||||
-3.383295002935882e-01, -6.897484482073574e-02, +2.733004667504394e-01,
|
||||
+3.266407412190941e-01, +3.465429229977289e-02, -2.939689006048397e-01,
|
||||
-3.118062532466677e-01}, // 5
|
||||
{+2.500000000000000e-01, +1.026311318805894e-01, -2.939689006048397e-01,
|
||||
-2.733004667504393e-01, +1.352990250365493e-01, +3.518509343815957e-01,
|
||||
+6.897484482073579e-02, -3.118062532466678e-01, -2.500000000000001e-01,
|
||||
+1.666639146194366e-01, +3.467599613305369e-01, +3.465429229977293e-02,
|
||||
-3.266407412190941e-01, -2.242918965856591e-01, +1.964237395967756e-01,
|
||||
+3.383295002935882e-01}, // 6
|
||||
{+2.500000000000000e-01, +3.465429229977287e-02, -3.467599613305369e-01,
|
||||
-1.026311318805893e-01, +3.266407412190941e-01, +1.666639146194366e-01,
|
||||
-2.939689006048397e-01, -2.242918965856591e-01, +2.500000000000001e-01,
|
||||
+2.733004667504393e-01, -1.964237395967756e-01, -3.118062532466678e-01,
|
||||
+1.352990250365493e-01, +3.383295002935882e-01, -6.897484482073578e-02,
|
||||
-3.518509343815956e-01}, // 7
|
||||
{+2.500000000000000e-01, -3.465429229977287e-02, -3.467599613305369e-01,
|
||||
+1.026311318805893e-01, +3.266407412190941e-01, -1.666639146194366e-01,
|
||||
-2.939689006048397e-01, +2.242918965856591e-01, +2.500000000000001e-01,
|
||||
-2.733004667504393e-01, -1.964237395967756e-01, +3.118062532466678e-01,
|
||||
+1.352990250365493e-01, -3.383295002935882e-01, -6.897484482073578e-02,
|
||||
+3.518509343815956e-01}, // 8
|
||||
{+2.500000000000000e-01, -1.026311318805894e-01, -2.939689006048397e-01,
|
||||
+2.733004667504393e-01, +1.352990250365493e-01, -3.518509343815957e-01,
|
||||
+6.897484482073579e-02, +3.118062532466678e-01, -2.500000000000001e-01,
|
||||
-1.666639146194366e-01, +3.467599613305369e-01, -3.465429229977293e-02,
|
||||
-3.266407412190941e-01, +2.242918965856591e-01, +1.964237395967756e-01,
|
||||
-3.383295002935882e-01}, // 9
|
||||
// LC3 Specification d09r01.pdf; Page 109 of 177
|
||||
{+2.500000000000000e-01, -1.666639146194366e-01, -1.964237395967756e-01,
|
||||
+3.518509343815956e-01, -1.352990250365493e-01, -2.242918965856591e-01,
|
||||
+3.467599613305369e-01, -1.026311318805894e-01, -2.500000000000001e-01,
|
||||
+3.383295002935882e-01, -6.897484482073574e-02, -2.733004667504394e-01,
|
||||
+3.266407412190941e-01, -3.465429229977289e-02, -2.939689006048397e-01,
|
||||
+3.118062532466677e-01}, // 10
|
||||
{+2.500000000000000e-01, -2.242918965856591e-01, -6.897484482073575e-02,
|
||||
+3.118062532466678e-01, -3.266407412190941e-01, +1.026311318805894e-01,
|
||||
+1.964237395967755e-01, -3.518509343815957e-01, +2.500000000000001e-01,
|
||||
+3.465429229977282e-02, -2.939689006048397e-01, +3.383295002935882e-01,
|
||||
-1.352990250365493e-01, -1.666639146194367e-01, +3.467599613305369e-01,
|
||||
-2.733004667504394e-01}, // 11
|
||||
{+2.500000000000000e-01, -2.733004667504394e-01, +6.897484482073575e-02,
|
||||
+1.666639146194366e-01, -3.266407412190941e-01, +3.383295002935882e-01,
|
||||
-1.964237395967755e-01, -3.465429229977288e-02, +2.500000000000001e-01,
|
||||
-3.518509343815957e-01, +2.939689006048397e-01, -1.026311318805893e-01,
|
||||
-1.352990250365493e-01, +3.118062532466679e-01, -3.467599613305369e-01,
|
||||
+2.242918965856590e-01}, // 12
|
||||
{+2.500000000000000e-01, -3.118062532466678e-01, +1.964237395967756e-01,
|
||||
-3.465429229977286e-02, -1.352990250365493e-01, +2.733004667504394e-01,
|
||||
-3.467599613305369e-01, +3.383295002935882e-01, -2.500000000000001e-01,
|
||||
+1.026311318805894e-01, +6.897484482073574e-02, -2.242918965856590e-01,
|
||||
+3.266407412190941e-01, -3.518509343815957e-01, +2.939689006048397e-01,
|
||||
-1.666639146194367e-01}, // 13
|
||||
{+2.500000000000000e-01, -3.383295002935882e-01, +2.939689006048397e-01,
|
||||
-2.242918965856591e-01, +1.352990250365493e-01, -3.465429229977286e-02,
|
||||
-6.897484482073579e-02, +1.666639146194366e-01, -2.500000000000001e-01,
|
||||
+3.118062532466678e-01, -3.467599613305369e-01, +3.518509343815956e-01,
|
||||
-3.266407412190941e-01, +2.733004667504394e-01, -1.964237395967756e-01,
|
||||
+1.026311318805893e-01}, // 14
|
||||
{+2.500000000000000e-01, -3.518509343815957e-01, +3.467599613305369e-01,
|
||||
-3.383295002935882e-01, +3.266407412190941e-01, -3.118062532466678e-01,
|
||||
+2.939689006048397e-01, -2.733004667504394e-01, +2.500000000000001e-01,
|
||||
-2.242918965856591e-01, +1.964237395967756e-01, -1.666639146194367e-01,
|
||||
+1.352990250365493e-01, -1.026311318805893e-01, +6.897484482073578e-02,
|
||||
-3.465429229977293e-02} };//15
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* SnsQuantizationTables.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SNS_QUANTIZATION_TABLES_H_
|
||||
#define SNS_QUANTIZATION_TABLES_H_
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.3 SNS Quantization
|
||||
|
||||
// LC3 Specification d09r04_*implementorComments*
|
||||
// Section 3.7.4 SNS Quantization
|
||||
|
||||
extern double LFCB[32][8];
|
||||
extern double HFCB[32][8];
|
||||
extern double sns_vq_reg_adj_gains[2];
|
||||
extern double sns_vq_reg_lf_adj_gains[4];
|
||||
extern double sns_vq_near_adj_gains[4];
|
||||
extern double sns_vq_far_adj_gains[8];
|
||||
extern int sns_gainMSBbits[4];
|
||||
extern int sns_gainLSBbits[4];
|
||||
extern unsigned int MPVQ_offsets[16][1+10];
|
||||
extern double D[16][16];
|
||||
|
||||
|
||||
#endif // SNS_QUANTIZATION_TABLES_H_
|
@ -1,752 +0,0 @@
|
||||
/*
|
||||
* SpectralDataTables.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.6 Spectral data
|
||||
#include "SpectralDataTables.hpp"
|
||||
|
||||
// LC3 Specification d09r01.pdf; Page 114 of 177
|
||||
unsigned char ac_spec_lookup[4096] = {
|
||||
0x01,0x27,0x07,0x19,0x16,0x16,0x1C,0x16,
|
||||
0x16,0x16,0x16,0x1C,0x1C,0x1C,0x22,0x1F,
|
||||
0x1F,0x28,0x2B,0x2E,0x31,0x34,0x0E,0x11,
|
||||
0x24,0x24,0x24,0x26,0x00,0x39,0x26,0x16,
|
||||
0x00,0x08,0x09,0x0B,0x2F,0x0E,0x0E,0x11,
|
||||
// LC3 Specification d09r01.pdf; Page 115 of 177
|
||||
0x24,0x24,0x24,0x26,0x3B,0x3B,0x26,0x16,
|
||||
0x16,0x1A,0x2E,0x1D,0x1E,0x20,0x21,0x23,
|
||||
0x24,0x24,0x24,0x26,0x00,0x3B,0x17,0x16,
|
||||
0x2E,0x2E,0x2D,0x2F,0x30,0x32,0x32,0x12,
|
||||
0x36,0x36,0x36,0x26,0x3B,0x3B,0x3B,0x16,
|
||||
0x00,0x3E,0x3F,0x03,0x21,0x02,0x02,0x3D,
|
||||
0x14,0x14,0x14,0x15,0x3B,0x3B,0x27,0x1C,
|
||||
0x1C,0x3F,0x3F,0x03,0x21,0x02,0x02,0x3D,
|
||||
0x26,0x26,0x26,0x15,0x3B,0x3B,0x27,0x1C,
|
||||
0x1C,0x06,0x06,0x06,0x02,0x12,0x3D,0x14,
|
||||
0x15,0x15,0x15,0x3B,0x27,0x27,0x07,0x22,
|
||||
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
|
||||
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
|
||||
0x22,0x33,0x33,0x33,0x35,0x36,0x14,0x26,
|
||||
0x26,0x39,0x27,0x27,0x27,0x07,0x18,0x22,
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
|
||||
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
|
||||
0x04,0x04,0x04,0x04,0x04,0x38,0x26,0x39,
|
||||
0x39,0x3B,0x07,0x07,0x07,0x2A,0x2A,0x22,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x05,0x04,0x04,0x05,0x15,0x15,0x3B,
|
||||
0x07,0x07,0x07,0x07,0x19,0x19,0x19,0x22,
|
||||
0x04,0x04,0x04,0x04,0x05,0x17,0x17,0x27,
|
||||
0x07,0x07,0x07,0x2A,0x19,0x19,0x16,0x1F,
|
||||
0x1F,0x27,0x27,0x27,0x27,0x07,0x07,0x2A,
|
||||
0x00,0x19,0x16,0x16,0x16,0x1C,0x22,0x1F,
|
||||
0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,
|
||||
0x37,0x37,0x37,0x37,0x37,0x37,0x37,0x37,
|
||||
0x37,0x37,0x28,0x08,0x09,0x31,0x31,0x34,
|
||||
0x11,0x11,0x11,0x04,0x00,0x14,0x11,0x3C,
|
||||
0x28,0x28,0x08,0x2B,0x1B,0x31,0x31,0x0E,
|
||||
0x11,0x11,0x11,0x24,0x2A,0x2A,0x11,0x39,
|
||||
0x39,0x28,0x08,0x1A,0x1B,0x31,0x0C,0x0E,
|
||||
0x11,0x11,0x11,0x24,0x00,0x26,0x24,0x01,
|
||||
0x08,0x08,0x2B,0x09,0x0B,0x31,0x0C,0x0E,
|
||||
0x0E,0x21,0x32,0x32,0x32,0x3D,0x24,0x27,
|
||||
0x08,0x08,0x2B,0x2E,0x31,0x34,0x1E,0x0E,
|
||||
0x0E,0x21,0x32,0x32,0x32,0x32,0x12,0x19,
|
||||
0x08,0x08,0x2B,0x2E,0x31,0x34,0x1E,0x0E,
|
||||
0x0E,0x12,0x05,0x05,0x05,0x3D,0x12,0x17,
|
||||
0x2B,0x2B,0x2B,0x09,0x31,0x34,0x03,0x0E,
|
||||
0x0E,0x32,0x32,0x32,0x32,0x3D,0x11,0x18,
|
||||
0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,
|
||||
0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,0x2B,
|
||||
0x2B,0x2B,0x2B,0x09,0x0B,0x34,0x34,0x0E,
|
||||
0x0E,0x11,0x3D,0x3D,0x3D,0x36,0x11,0x27,
|
||||
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
|
||||
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
|
||||
0x2D,0x2D,0x2C,0x1B,0x1D,0x34,0x30,0x34,
|
||||
0x34,0x11,0x11,0x11,0x11,0x02,0x11,0x07,
|
||||
0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,
|
||||
0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,
|
||||
0x1B,0x1B,0x09,0x1B,0x1B,0x0C,0x34,0x0E,
|
||||
0x0E,0x3A,0x29,0x29,0x29,0x06,0x11,0x25,
|
||||
0x09,0x09,0x09,0x1B,0x0B,0x31,0x0C,0x34,
|
||||
// LC3 Specification d09r01.pdf; Page 116 of 177
|
||||
0x0E,0x0E,0x0E,0x32,0x00,0x35,0x11,0x1C,
|
||||
0x34,0x34,0x31,0x34,0x0C,0x34,0x1E,0x0E,
|
||||
0x0E,0x11,0x02,0x02,0x02,0x26,0x26,0x22,
|
||||
0x1F,0x22,0x22,0x1F,0x1F,0x1F,0x1F,0x13,
|
||||
0x13,0x13,0x13,0x13,0x13,0x13,0x1F,0x13,
|
||||
0x2C,0x2C,0x3E,0x1E,0x20,0x3A,0x23,0x24,
|
||||
0x24,0x26,0x00,0x3B,0x07,0x07,0x27,0x22,
|
||||
0x22,0x2D,0x2F,0x30,0x21,0x23,0x23,0x24,
|
||||
0x26,0x26,0x26,0x3B,0x07,0x07,0x27,0x22,
|
||||
0x22,0x3E,0x1E,0x0F,0x32,0x35,0x35,0x36,
|
||||
0x15,0x15,0x15,0x3B,0x07,0x07,0x07,0x22,
|
||||
0x1E,0x1E,0x30,0x21,0x3A,0x12,0x12,0x38,
|
||||
0x17,0x17,0x17,0x3B,0x07,0x07,0x18,0x22,
|
||||
0x22,0x06,0x06,0x3A,0x35,0x36,0x36,0x15,
|
||||
0x3B,0x3B,0x3B,0x27,0x07,0x07,0x2A,0x22,
|
||||
0x06,0x06,0x21,0x3A,0x35,0x36,0x3D,0x15,
|
||||
0x3B,0x3B,0x3B,0x27,0x07,0x07,0x2A,0x22,
|
||||
0x22,0x33,0x33,0x35,0x36,0x38,0x38,0x39,
|
||||
0x27,0x27,0x27,0x07,0x2A,0x2A,0x19,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x04,0x04,0x04,0x05,0x17,0x17,0x27,
|
||||
0x07,0x07,0x07,0x2A,0x19,0x19,0x16,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x05,0x05,0x05,0x05,0x39,0x39,0x27,
|
||||
0x18,0x18,0x18,0x2A,0x16,0x16,0x1C,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x29,0x29,0x29,0x29,0x27,0x27,0x07,
|
||||
0x2A,0x2A,0x2A,0x19,0x1C,0x1C,0x1C,0x1F,
|
||||
0x1F,0x29,0x29,0x29,0x29,0x27,0x27,0x18,
|
||||
0x19,0x19,0x19,0x16,0x1C,0x1C,0x22,0x1F,
|
||||
0x1F,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x1C,
|
||||
0x22,0x22,0x22,0x22,0x22,0x22,0x1F,0x13,
|
||||
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
|
||||
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
|
||||
0x08,0x08,0x09,0x0B,0x2F,0x20,0x32,0x12,
|
||||
0x12,0x14,0x15,0x15,0x15,0x27,0x3B,0x22,
|
||||
0x1A,0x1A,0x1B,0x1D,0x1E,0x21,0x32,0x12,
|
||||
0x12,0x14,0x39,0x39,0x39,0x3B,0x3B,0x22,
|
||||
0x1B,0x1B,0x0B,0x0C,0x30,0x32,0x3A,0x3D,
|
||||
0x3D,0x38,0x39,0x39,0x39,0x3B,0x27,0x22,
|
||||
0x2D,0x2D,0x0C,0x1E,0x20,0x02,0x02,0x3D,
|
||||
0x26,0x26,0x26,0x39,0x00,0x3B,0x27,0x22,
|
||||
0x3F,0x3F,0x03,0x20,0x3A,0x12,0x12,0x14,
|
||||
0x15,0x15,0x15,0x3B,0x27,0x27,0x07,0x1F,
|
||||
0x1F,0x03,0x03,0x21,0x3A,0x12,0x12,0x14,
|
||||
0x15,0x15,0x15,0x3B,0x07,0x07,0x07,0x1F,
|
||||
0x06,0x06,0x33,0x33,0x35,0x36,0x36,0x26,
|
||||
0x39,0x39,0x39,0x27,0x07,0x07,0x2A,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x33,0x35,0x35,0x36,0x38,0x38,0x39,
|
||||
0x3B,0x3B,0x3B,0x07,0x18,0x18,0x19,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
// LC3 Specification d09r01.pdf; Page 117 of 177
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x04,0x04,0x04,0x36,0x15,0x15,0x39,
|
||||
0x27,0x27,0x27,0x07,0x2A,0x2A,0x16,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
|
||||
0x1F,0x05,0x05,0x05,0x05,0x17,0x17,0x3B,
|
||||
0x07,0x07,0x07,0x2A,0x16,0x16,0x1C,0x1F,
|
||||
0x1F,0x04,0x04,0x04,0x05,0x17,0x17,0x27,
|
||||
0x18,0x18,0x18,0x19,0x1C,0x1C,0x22,0x1F,
|
||||
0x1F,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x1C,
|
||||
0x22,0x22,0x22,0x1F,0x1F,0x1F,0x1F,0x13,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x10,
|
||||
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x0D,0x0D,0x0D,0x00,0x0D,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 118 of 177
|
||||
0x00,0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x00,0x0D,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,
|
||||
0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x25,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x3C,0x10,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x3C,0x10,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x10,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x10,0x10,0x10,0x10,0x10,0x25,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 119 of 177
|
||||
0x00,0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x0D,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x10,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x3C,0x3C,0x3C,0x10,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x10,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x25,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 120 of 177
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x00,0x0D,0x0D,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x00,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x3C,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x00,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x13,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x13,0x0D,0x0D,0x0D,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x3C,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x10,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 121 of 177
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x3C,0x3C,0x3C,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
|
||||
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x3C,0x3C,0x3C,
|
||||
0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,0x3C,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 122 of 177
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x00,0x00,0x00,
|
||||
0x00,0x00,0x0D,0x0D,0x0D,0x0D,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
|
||||
0x0D,0x0D,0x0D,0x0D,0x0D,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x0D,0x0D,0x0D,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x3C,
|
||||
0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 123 of 177
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
// LC3 Specification d09r01.pdf; Page 124 of 177
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
short ac_spec_cumfreq[64][17] = {
|
||||
{ 0, 1, 2, 177, 225, 226, 227, 336, 372, 543, 652, 699, 719, 768, 804, 824, 834 },
|
||||
{ 0, 18, 44, 61, 71, 98, 135, 159, 175, 197, 229, 251, 265, 282, 308, 328, 341 },
|
||||
{ 0, 71, 163, 212, 237, 318, 420, 481, 514, 556, 613, 652, 675, 697, 727, 749, 764 },
|
||||
{ 0, 160, 290, 336, 354, 475, 598, 653, 677, 722, 777, 808, 823, 842, 866, 881, 890 },
|
||||
{ 0, 71, 144, 177, 195, 266, 342, 385, 411, 445, 489, 519, 539, 559, 586, 607, 622 },
|
||||
{ 0, 48, 108, 140, 159, 217, 285, 327, 354, 385, 427, 457, 478, 497, 524, 545, 561 },
|
||||
{ 0, 138, 247, 290, 308, 419, 531, 584, 609, 655, 710, 742, 759, 780, 807, 825, 836 },
|
||||
{ 0, 16, 40, 62, 79, 103, 139, 170, 195, 215, 245, 270, 290, 305, 327, 346, 362 },
|
||||
{ 0, 579, 729, 741, 743, 897, 970, 980, 982, 996, 1007, 1010, 1011, 1014, 1017, 1018, 1019 },
|
||||
{ 0, 398, 582, 607, 612, 788, 902, 925, 931, 956, 979, 987, 990, 996, 1002, 1005, 1007 },
|
||||
{ 0, 13, 34, 52, 63, 83, 112, 134, 149, 163, 183, 199, 211, 221, 235, 247, 257 },
|
||||
{ 0, 281, 464, 501, 510, 681, 820, 857, 867, 902, 938, 953, 959, 968, 978, 984, 987 },
|
||||
{ 0, 198, 362, 408, 421, 575, 722, 773, 789, 832, 881, 905, 915, 928, 944, 954, 959 },
|
||||
{ 0, 1, 2, 95, 139, 140, 141, 213, 251, 337, 407, 450, 475, 515, 551, 576, 592 },
|
||||
{ 0, 133, 274, 338, 366, 483, 605, 664, 691, 730, 778, 807, 822, 837, 857, 870, 878 },
|
||||
{ 0, 128, 253, 302, 320, 443, 577, 636, 659, 708, 767, 799, 814, 833, 857, 872, 881 },
|
||||
{ 0, 1, 2, 25, 42, 43, 44, 67, 85, 105, 126, 144, 159, 174, 191, 205, 217 },
|
||||
{ 0, 70, 166, 229, 267, 356, 468, 533, 569, 606, 653, 685, 705, 722, 745, 762, 774 },
|
||||
{ 0, 55, 130, 175, 200, 268, 358, 416, 449, 488, 542, 581, 606, 628, 659, 683, 699 },
|
||||
{ 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 },
|
||||
{ 0, 34, 85, 123, 147, 196, 265, 317, 352, 386, 433, 470, 497, 518, 549, 574, 593 },
|
||||
{ 0, 30, 73, 105, 127, 170, 229, 274, 305, 335, 377, 411, 436, 455, 483, 506, 524 },
|
||||
{ 0, 9, 24, 38, 51, 65, 87, 108, 126, 139, 159, 177, 193, 204, 221, 236, 250 },
|
||||
{ 0, 30, 74, 105, 125, 166, 224, 266, 294, 322, 361, 391, 413, 431, 457, 478, 494 },
|
||||
{ 0, 15, 38, 58, 73, 95, 128, 156, 178, 196, 222, 245, 263, 276, 296, 314, 329 },
|
||||
// LC3 Specification d09r01.pdf; Page 125 of 177
|
||||
{ 0, 11, 28, 44, 57, 74, 100, 123, 142, 157, 179, 199, 216, 228, 246, 262, 276 },
|
||||
{ 0, 448, 619, 639, 643, 821, 926, 944, 948, 971, 991, 998, 1000, 1005, 1010, 1012, 1013 },
|
||||
{ 0, 332, 520, 549, 555, 741, 874, 903, 910, 940, 970, 981, 985, 991, 998, 1002, 1004 },
|
||||
{ 0, 8, 21, 34, 45, 58, 78, 96, 112, 124, 141, 157, 170, 180, 194, 207, 219 },
|
||||
{ 0, 239, 415, 457, 468, 631, 776, 820, 833, 872, 914, 933, 940, 951, 964, 971, 975 },
|
||||
{ 0, 165, 310, 359, 375, 513, 652, 707, 727, 774, 828, 856, 868, 884, 904, 916, 923 },
|
||||
{ 0, 3, 8, 13, 18, 23, 30, 37, 44, 48, 55, 62, 68, 72, 78, 84, 90 },
|
||||
{ 0, 115, 237, 289, 311, 422, 547, 608, 635, 680, 737, 771, 788, 807, 832, 849, 859 },
|
||||
{ 0, 107, 221, 272, 293, 399, 521, 582, 610, 656, 714, 749, 767, 787, 813, 831, 842 },
|
||||
{ 0, 6, 16, 26, 35, 45, 60, 75, 89, 98, 112, 125, 137, 145, 157, 168, 178 },
|
||||
{ 0, 72, 160, 210, 236, 320, 422, 482, 514, 555, 608, 644, 665, 685, 712, 732, 745 },
|
||||
{ 0, 45, 108, 153, 183, 244, 327, 385, 421, 455, 502, 536, 559, 578, 605, 626, 641 },
|
||||
{ 0, 1, 2, 9, 16, 17, 18, 26, 34, 40, 48, 55, 62, 68, 75, 82, 88 },
|
||||
{ 0, 29, 73, 108, 132, 174, 236, 284, 318, 348, 391, 426, 452, 471, 500, 524, 543 },
|
||||
{ 0, 20, 51, 76, 93, 123, 166, 200, 225, 247, 279, 305, 326, 342, 365, 385, 401 },
|
||||
{ 0, 742, 845, 850, 851, 959, 997, 1001, 1002, 1009, 1014, 1016, 1017, 1019, 1020, 1021, 1022 },
|
||||
{ 0, 42, 94, 121, 137, 186, 244, 280, 303, 330, 366, 392, 410, 427, 451, 470, 484 },
|
||||
{ 0, 13, 33, 51, 66, 85, 114, 140, 161, 178, 203, 225, 243, 256, 275, 292, 307 },
|
||||
{ 0, 501, 670, 689, 693, 848, 936, 952, 956, 975, 991, 997, 999, 1004, 1008, 1010, 1011 },
|
||||
{ 0, 445, 581, 603, 609, 767, 865, 888, 895, 926, 954, 964, 968, 977, 986, 991, 993 },
|
||||
{ 0, 285, 442, 479, 489, 650, 779, 818, 830, 870, 912, 930, 937, 949, 963, 971, 975 },
|
||||
{ 0, 349, 528, 561, 569, 731, 852, 883, 892, 923, 953, 965, 970, 978, 987, 992, 994 },
|
||||
{ 0, 199, 355, 402, 417, 563, 700, 750, 767, 811, 860, 884, 894, 909, 926, 936, 942 },
|
||||
{ 0, 141, 275, 325, 343, 471, 606, 664, 686, 734, 791, 822, 836, 854, 877, 891, 899 },
|
||||
{ 0, 243, 437, 493, 510, 649, 775, 820, 836, 869, 905, 923, 931, 941, 953, 960, 964 },
|
||||
{ 0, 91, 197, 248, 271, 370, 487, 550, 580, 625, 684, 721, 741, 761, 788, 807, 819 },
|
||||
{ 0, 107, 201, 242, 262, 354, 451, 503, 531, 573, 626, 660, 680, 701, 730, 751, 765 },
|
||||
{ 0, 168, 339, 407, 432, 553, 676, 731, 755, 789, 830, 854, 866, 879, 895, 906, 912 },
|
||||
// LC3 Specification d09r01.pdf; Page 126 of 177
|
||||
{ 0, 67, 147, 191, 214, 290, 384, 441, 472, 513, 567, 604, 627, 648, 678, 700, 715 },
|
||||
{ 0, 46, 109, 148, 171, 229, 307, 359, 391, 427, 476, 513, 537, 558, 588, 612, 629 },
|
||||
{ 0, 848, 918, 920, 921, 996, 1012, 1013, 1014, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023 },
|
||||
{ 0, 36, 88, 123, 145, 193, 260, 308, 340, 372, 417, 452, 476, 496, 525, 548, 565 },
|
||||
{ 0, 24, 61, 90, 110, 145, 196, 237, 266, 292, 330, 361, 385, 403, 430, 453, 471 },
|
||||
{ 0, 85, 182, 230, 253, 344, 454, 515, 545, 590, 648, 685, 706, 727, 756, 776, 789 },
|
||||
{ 0, 22, 55, 82, 102, 135, 183, 222, 252, 278, 315, 345, 368, 385, 410, 431, 448 },
|
||||
{ 0, 1, 2, 56, 89, 90, 91, 140, 172, 221, 268, 303, 328, 358, 388, 412, 430 },
|
||||
{ 0, 45, 109, 152, 177, 239, 320, 376, 411, 448, 499, 537, 563, 585, 616, 640, 658 },
|
||||
{ 0, 247, 395, 433, 445, 599, 729, 771, 785, 829, 875, 896, 905, 920, 937, 946, 951 },
|
||||
{ 0, 231, 367, 408, 423, 557, 676, 723, 742, 786, 835, 860, 872, 889, 909, 921, 928 }
|
||||
};
|
||||
short ac_spec_freq[64][17] = {
|
||||
{ 1, 1, 175, 48, 1, 1, 109, 36, 171, 109, 47, 20, 49, 36, 20, 10, 190 },
|
||||
{ 18, 26, 17, 10, 27, 37, 24, 16, 22, 32, 22, 14, 17, 26, 20, 13, 683 },
|
||||
{ 71, 92, 49, 25, 81, 102, 61, 33, 42, 57, 39, 23, 22, 30, 22, 15, 260 },
|
||||
{ 160, 130, 46, 18, 121, 123, 55, 24, 45, 55, 31, 15, 19, 24, 15, 9, 134 },
|
||||
{ 71, 73, 33, 18, 71, 76, 43, 26, 34, 44, 30, 20, 20, 27, 21, 15, 402 },
|
||||
{ 48, 60, 32, 19, 58, 68, 42, 27, 31, 42, 30, 21, 19, 27, 21, 16, 463 },
|
||||
{ 138, 109, 43, 18, 111, 112, 53, 25, 46, 55, 32, 17, 21, 27, 18, 11, 188 },
|
||||
{ 16, 24, 22, 17, 24, 36, 31, 25, 20, 30, 25, 20, 15, 22, 19, 16, 662 },
|
||||
{ 579, 150, 12, 2, 154, 73, 10, 2, 14, 11, 3, 1, 3, 3, 1, 1, 5 },
|
||||
{ 398, 184, 25, 5, 176, 114, 23, 6, 25, 23, 8, 3, 6, 6, 3, 2, 17 },
|
||||
{ 13, 21, 18, 11, 20, 29, 22, 15, 14, 20, 16, 12, 10, 14, 12, 10, 767 },
|
||||
{ 281, 183, 37, 9, 171, 139, 37, 10, 35, 36, 15, 6, 9, 10, 6, 3, 37 },
|
||||
{ 198, 164, 46, 13, 154, 147, 51, 16, 43, 49, 24, 10, 13, 16, 10, 5, 65 },
|
||||
{ 1, 1, 93, 44, 1, 1, 72, 38, 86, 70, 43, 25, 40, 36, 25, 16, 432 },
|
||||
{ 133, 141, 64, 28, 117, 122, 59, 27, 39, 48, 29, 15, 15, 20, 13, 8, 146 },
|
||||
// LC3 Specification d09r01.pdf; Page 127 of 177
|
||||
{ 128, 125, 49, 18, 123, 134, 59, 23, 49, 59, 32, 15, 19, 24, 15, 9, 143 },
|
||||
{ 1, 1, 23, 17, 1, 1, 23, 18, 20, 21, 18, 15, 15, 17, 14, 12, 807 },
|
||||
{ 70, 96, 63, 38, 89, 112, 65, 36, 37, 47, 32, 20, 17, 23, 17, 12, 250 },
|
||||
{ 55, 75, 45, 25, 68, 90, 58, 33, 39, 54, 39, 25, 22, 31, 24, 16, 325 },
|
||||
{ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 993 },
|
||||
{ 34, 51, 38, 24, 49, 69, 52, 35, 34, 47, 37, 27, 21, 31, 25, 19, 431 },
|
||||
{ 30, 43, 32, 22, 43, 59, 45, 31, 30, 42, 34, 25, 19, 28, 23, 18, 500 },
|
||||
{ 9, 15, 14, 13, 14, 22, 21, 18, 13, 20, 18, 16, 11, 17, 15, 14, 774 },
|
||||
{ 30, 44, 31, 20, 41, 58, 42, 28, 28, 39, 30, 22, 18, 26, 21, 16, 530 },
|
||||
{ 15, 23, 20, 15, 22, 33, 28, 22, 18, 26, 23, 18, 13, 20, 18, 15, 695 },
|
||||
{ 11, 17, 16, 13, 17, 26, 23, 19, 15, 22, 20, 17, 12, 18, 16, 14, 748 },
|
||||
{ 448, 171, 20, 4, 178, 105, 18, 4, 23, 20, 7, 2, 5, 5, 2, 1, 11 },
|
||||
{ 332, 188, 29, 6, 186, 133, 29, 7, 30, 30, 11, 4, 6, 7, 4, 2, 20 },
|
||||
{ 8, 13, 13, 11, 13, 20, 18, 16, 12, 17, 16, 13, 10, 14, 13, 12, 805 },
|
||||
{ 239, 176, 42, 11, 163, 145, 44, 13, 39, 42, 19, 7, 11, 13, 7, 4, 49 },
|
||||
{ 165, 145, 49, 16, 138, 139, 55, 20, 47, 54, 28, 12, 16, 20, 12, 7, 101 },
|
||||
{ 3, 5, 5, 5, 5, 7, 7, 7, 4, 7, 7, 6, 4, 6, 6, 6, 934 },
|
||||
{ 115, 122, 52, 22, 111, 125, 61, 27, 45, 57, 34, 17, 19, 25, 17, 10, 165 },
|
||||
{ 107, 114, 51, 21, 106, 122, 61, 28, 46, 58, 35, 18, 20, 26, 18, 11, 182 },
|
||||
{ 6, 10, 10, 9, 10, 15, 15, 14, 9, 14, 13, 12, 8, 12, 11, 10, 846 },
|
||||
{ 72, 88, 50, 26, 84, 102, 60, 32, 41, 53, 36, 21, 20, 27, 20, 13, 279 },
|
||||
{ 45, 63, 45, 30, 61, 83, 58, 36, 34, 47, 34, 23, 19, 27, 21, 15, 383 },
|
||||
{ 1, 1, 7, 7, 1, 1, 8, 8, 6, 8, 7, 7, 6, 7, 7, 6, 936 },
|
||||
{ 29, 44, 35, 24, 42, 62, 48, 34, 30, 43, 35, 26, 19, 29, 24, 19, 481 },
|
||||
{ 20, 31, 25, 17, 30, 43, 34, 25, 22, 32, 26, 21, 16, 23, 20, 16, 623 },
|
||||
{ 742, 103, 5, 1, 108, 38, 4, 1, 7, 5, 2, 1, 2, 1, 1, 1, 2 },
|
||||
{ 42, 52, 27, 16, 49, 58, 36, 23, 27, 36, 26, 18, 17, 24, 19, 14, 540 },
|
||||
{ 13, 20, 18, 15, 19, 29, 26, 21, 17, 25, 22, 18, 13, 19, 17, 15, 717 },
|
||||
// LC3 Specification d09r01.pdf; Page 128 of 177
|
||||
{ 501, 169, 19, 4, 155, 88, 16, 4, 19, 16, 6, 2, 5, 4, 2, 1, 13 },
|
||||
{ 445, 136, 22, 6, 158, 98, 23, 7, 31, 28, 10, 4, 9, 9, 5, 2, 31 },
|
||||
{ 285, 157, 37, 10, 161, 129, 39, 12, 40, 42, 18, 7, 12, 14, 8, 4, 49 },
|
||||
{ 349, 179, 33, 8, 162, 121, 31, 9, 31, 30, 12, 5, 8, 9, 5, 2, 30 },
|
||||
{ 199, 156, 47, 15, 146, 137, 50, 17, 44, 49, 24, 10, 15, 17, 10, 6, 82 },
|
||||
{ 141, 134, 50, 18, 128, 135, 58, 22, 48, 57, 31, 14, 18, 23, 14, 8, 125 },
|
||||
{ 243, 194, 56, 17, 139, 126, 45, 16, 33, 36, 18, 8, 10, 12, 7, 4, 60 },
|
||||
{ 91, 106, 51, 23, 99, 117, 63, 30, 45, 59, 37, 20, 20, 27, 19, 12, 205 },
|
||||
{ 107, 94, 41, 20, 92, 97, 52, 28, 42, 53, 34, 20, 21, 29, 21, 14, 259 },
|
||||
{ 168, 171, 68, 25, 121, 123, 55, 24, 34, 41, 24, 12, 13, 16, 11, 6, 112 },
|
||||
{ 67, 80, 44, 23, 76, 94, 57, 31, 41, 54, 37, 23, 21, 30, 22, 15, 309 },
|
||||
{ 46, 63, 39, 23, 58, 78, 52, 32, 36, 49, 37, 24, 21, 30, 24, 17, 395 },
|
||||
{ 848, 70, 2, 1, 75, 16, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
{ 36, 52, 35, 22, 48, 67, 48, 32, 32, 45, 35, 24, 20, 29, 23, 17, 459 },
|
||||
{ 24, 37, 29, 20, 35, 51, 41, 29, 26, 38, 31, 24, 18, 27, 23, 18, 553 },
|
||||
{ 85, 97, 48, 23, 91, 110, 61, 30, 45, 58, 37, 21, 21, 29, 20, 13, 235 },
|
||||
{ 22, 33, 27, 20, 33, 48, 39, 30, 26, 37, 30, 23, 17, 25, 21, 17, 576 },
|
||||
{ 1, 1, 54, 33, 1, 1, 49, 32, 49, 47, 35, 25, 30, 30, 24, 18, 594 },
|
||||
{ 45, 64, 43, 25, 62, 81, 56, 35, 37, 51, 38, 26, 22, 31, 24, 18, 366 },
|
||||
{ 247, 148, 38, 12, 154, 130, 42, 14, 44, 46, 21, 9, 15, 17, 9, 5, 73 },
|
||||
{ 231, 136, 41, 15, 134, 119, 47, 19, 44, 49, 25, 12, 17, 20, 12, 7, 96 }
|
||||
};
|
||||
short ac_spec_bits[64][17] = {
|
||||
{ 20480,20480, 5220, 9042,20480,20480, 6619, 9892, 5289, 6619, 9105,11629, 8982, 9892,11629,13677, 4977 },
|
||||
{ 11940,10854,12109,13677,10742, 9812,11090,12288,11348,10240,11348,12683,12109,10854,11629,12902, 1197 },
|
||||
{ 7886, 7120, 8982,10970, 7496, 6815, 8334,10150, 9437, 8535, 9656,11216,11348,10431,11348,12479, 4051 },
|
||||
{ 5485, 6099, 9168,11940, 6311, 6262, 8640,11090, 9233, 8640,10334,12479,11781,11090,12479,13988, 6009 },
|
||||
{ 7886, 7804,10150,11940, 7886, 7685, 9368,10854,10061, 9300,10431,11629,11629,10742,11485,12479, 2763 },
|
||||
// LC3 Specification d09r01.pdf; Page 129 of 177
|
||||
{ 9042, 8383,10240,11781, 8483, 8013, 9437,10742,10334, 9437,10431,11485,11781,10742,11485,12288, 2346 },
|
||||
{ 5922, 6619, 9368,11940, 6566, 6539, 8750,10970, 9168, 8640,10240,12109,11485,10742,11940,13396, 5009 },
|
||||
{ 12288,11090,11348,12109,11090, 9892,10334,10970,11629,10431,10970,11629,12479,11348,11781,12288, 1289 },
|
||||
{ 1685, 5676,13138,18432, 5598, 7804,13677,18432,12683,13396,17234,20480,17234,17234,20480,20480,15725 },
|
||||
{ 2793, 5072,10970,15725, 5204, 6487,11216,15186,10970,11216,14336,17234,15186,15186,17234,18432,12109 },
|
||||
{ 12902,11485,11940,13396,11629,10531,11348,12479,12683,11629,12288,13138,13677,12683,13138,13677, 854 },
|
||||
{ 3821, 5088, 9812,13988, 5289, 5901, 9812,13677, 9976, 9892,12479,15186,13988,13677,15186,17234, 9812 },
|
||||
{ 4856, 5412, 9168,12902, 5598, 5736, 8863,12288, 9368, 8982,11090,13677,12902,12288,13677,15725, 8147 },
|
||||
{ 20480,20480, 7088, 9300,20480,20480, 7844, 9733, 7320, 7928, 9368,10970, 9581, 9892,10970,12288, 2550 },
|
||||
{ 6031, 5859, 8192,10635, 6410, 6286, 8433,10742, 9656, 9042,10531,12479,12479,11629,12902,14336, 5756 },
|
||||
{ 6144, 6215, 8982,11940, 6262, 6009, 8433,11216, 8982, 8433,10240,12479,11781,11090,12479,13988, 5817 },
|
||||
{ 20480,20480,11216,12109,20480,20480,11216,11940,11629,11485,11940,12479,12479,12109,12683,13138, 704 },
|
||||
{ 7928, 6994, 8239, 9733, 7218, 6539, 8147, 9892, 9812, 9105,10240,11629,12109,11216,12109,13138, 4167 },
|
||||
{ 8640, 7724, 9233,10970, 8013, 7185, 8483,10150, 9656, 8694, 9656,10970,11348,10334,11090,12288, 3391 },
|
||||
{ 20480,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432,18432, 91 },
|
||||
{ 10061, 8863, 9733,11090, 8982, 7970, 8806, 9976,10061, 9105, 9812,10742,11485,10334,10970,11781, 2557 },
|
||||
{ 10431, 9368,10240,11348, 9368, 8433, 9233,10334,10431, 9437,10061,10970,11781,10635,11216,11940, 2119 },
|
||||
{ 13988,12479,12683,12902,12683,11348,11485,11940,12902,11629,11940,12288,13396,12109,12479,12683, 828 },
|
||||
{ 10431, 9300,10334,11629, 9508, 8483, 9437,10635,10635, 9656,10431,11348,11940,10854,11485,12288, 1946 },
|
||||
{ 12479,11216,11629,12479,11348,10150,10635,11348,11940,10854,11216,11940,12902,11629,11940,12479, 1146 },
|
||||
{ 13396,12109,12288,12902,12109,10854,11216,11781,12479,11348,11629,12109,13138,11940,12288,12683, 928 },
|
||||
{ 2443, 5289,11629,16384, 5170, 6730,11940,16384,11216,11629,14731,18432,15725,15725,18432,20480,13396 },
|
||||
{ 3328, 5009,10531,15186, 5040, 6031,10531,14731,10431,10431,13396,16384,15186,14731,16384,18432,11629 },
|
||||
{ 14336,12902,12902,13396,12902,11629,11940,12288,13138,12109,12288,12902,13677,12683,12902,13138, 711 },
|
||||
// LC3 Specification d09r01.pdf; Page 130 of 177
|
||||
{ 4300, 5204, 9437,13396, 5430, 5776, 9300,12902, 9656, 9437,11781,14731,13396,12902,14731,16384, 8982 },
|
||||
{ 5394, 5776, 8982,12288, 5922, 5901, 8640,11629, 9105, 8694,10635,13138,12288,11629,13138,14731, 6844 },
|
||||
{ 17234,15725,15725,15725,15725,14731,14731,14731,16384,14731,14731,15186,16384,15186,15186,15186, 272 },
|
||||
{ 6461, 6286, 8806,11348, 6566, 6215, 8334,10742, 9233, 8535,10061,12109,11781,10970,12109,13677, 5394 },
|
||||
{ 6674, 6487, 8863,11485, 6702, 6286, 8334,10635, 9168, 8483, 9976,11940,11629,10854,11940,13396, 5105 },
|
||||
{ 15186,13677,13677,13988,13677,12479,12479,12683,13988,12683,12902,13138,14336,13138,13396,13677, 565 },
|
||||
{ 7844, 7252, 8922,10854, 7389, 6815, 8383,10240, 9508, 8750, 9892,11485,11629,10742,11629,12902, 3842 },
|
||||
{ 9233, 8239, 9233,10431, 8334, 7424, 8483, 9892,10061, 9105,10061,11216,11781,10742,11485,12479, 2906 },
|
||||
{ 20480,20480,14731,14731,20480,20480,14336,14336,15186,14336,14731,14731,15186,14731,14731,15186, 266 },
|
||||
{ 10531, 9300, 9976,11090, 9437, 8286, 9042,10061,10431, 9368, 9976,10854,11781,10531,11090,11781, 2233 },
|
||||
{ 11629,10334,10970,12109,10431, 9368,10061,10970,11348,10240,10854,11485,12288,11216,11629,12288, 1469 },
|
||||
{ 952, 6787,15725,20480, 6646, 9733,16384,20480,14731,15725,18432,20480,18432,20480,20480,20480,18432 },
|
||||
{ 9437, 8806,10742,12288, 8982, 8483, 9892,11216,10742, 9892,10854,11940,12109,11090,11781,12683, 1891 },
|
||||
{ 12902,11629,11940,12479,11781,10531,10854,11485,12109,10970,11348,11940,12902,11781,12109,12479, 1054 },
|
||||
{ 2113, 5323,11781,16384, 5579, 7252,12288,16384,11781,12288,15186,18432,15725,16384,18432,20480,12902 },
|
||||
{ 2463, 5965,11348,15186, 5522, 6934,11216,14731,10334,10635,13677,16384,13988,13988,15725,18432,10334 },
|
||||
{ 3779, 5541, 9812,13677, 5467, 6122, 9656,13138, 9581, 9437,11940,14731,13138,12683,14336,16384, 8982 },
|
||||
{ 3181, 5154,10150,14336, 5448, 6311,10334,13988,10334,10431,13138,15725,14336,13988,15725,18432,10431 },
|
||||
{ 4841, 5560, 9105,12479, 5756, 5944, 8922,12109, 9300, 8982,11090,13677,12479,12109,13677,15186, 7460 },
|
||||
{ 5859, 6009, 8922,11940, 6144, 5987, 8483,11348, 9042, 8535,10334,12683,11940,11216,12683,14336, 6215 },
|
||||
{ 4250, 4916, 8587,12109, 5901, 6191, 9233,12288,10150, 9892,11940,14336,13677,13138,14731,16384, 8383 },
|
||||
{ 7153, 6702, 8863,11216, 6904, 6410, 8239,10431, 9233, 8433, 9812,11629,11629,10742,11781,13138, 4753 },
|
||||
{ 6674, 7057, 9508,11629, 7120, 6964, 8806,10635, 9437, 8750,10061,11629,11485,10531,11485,12683, 4062 },
|
||||
{ 5341, 5289, 8013,10970, 6311, 6262, 8640,11090,10061, 9508,11090,13138,12902,12288,13396,15186, 6539 },
|
||||
{ 8057, 7533, 9300,11216, 7685, 7057, 8535,10334, 9508, 8694, 9812,11216,11485,10431,11348,12479, 3541 },
|
||||
{ 9168, 8239, 9656,11216, 8483, 7608, 8806,10240, 9892, 8982, 9812,11090,11485,10431,11090,12109, 2815 },
|
||||
// LC3 Specification d09r01.pdf; Page 131 of 177
|
||||
{ 558, 7928,18432,20480, 7724,12288,20480,20480,18432,20480,20480,20480,20480,20480,20480,20480,20480 },
|
||||
{ 9892, 8806, 9976,11348, 9042, 8057, 9042,10240,10240, 9233, 9976,11090,11629,10531,11216,12109, 2371 },
|
||||
{ 11090, 9812,10531,11629, 9976, 8863, 9508,10531,10854, 9733,10334,11090,11940,10742,11216,11940, 1821 },
|
||||
{ 7354, 6964, 9042,11216, 7153, 6592, 8334,10431, 9233, 8483, 9812,11485,11485,10531,11629,12902, 4349 },
|
||||
{ 11348,10150,10742,11629,10150, 9042, 9656,10431,10854, 9812,10431,11216,12109,10970,11485,12109, 1700 },
|
||||
{ 20480,20480, 8694,10150,20480,20480, 8982,10240, 8982, 9105, 9976,10970,10431,10431,11090,11940, 1610 },
|
||||
{ 9233, 8192, 9368,10970, 8286, 7496, 8587, 9976, 9812, 8863, 9733,10854,11348,10334,11090,11940, 3040 },
|
||||
{ 4202, 5716, 9733,13138, 5598, 6099, 9437,12683, 9300, 9168,11485,13988,12479,12109,13988,15725, 7804 },
|
||||
{ 4400, 5965, 9508,12479, 6009, 6360, 9105,11781, 9300, 8982,10970,13138,12109,11629,13138,14731, 6994 }
|
||||
};
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* SpectralDataTables.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.6 Spectral data
|
||||
|
||||
#ifndef SPECTRAL_DATA_TABLES_H_
|
||||
#define SPECTRAL_DATA_TABLES_H_
|
||||
|
||||
extern unsigned char ac_spec_lookup[4096];
|
||||
extern short ac_spec_cumfreq[64][17];
|
||||
extern short ac_spec_freq[64][17];
|
||||
extern short ac_spec_bits[64][17];
|
||||
|
||||
#endif // SPECTRAL_DATA_TABLES_H_
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* TemporalNoiseShapingTables.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.4 Temporal Noise Shaping
|
||||
#include "TemporalNoiseShapingTables.hpp"
|
||||
|
||||
// LC3 Specification d09r01.pdf; Page 109 of 177
|
||||
short ac_tns_order_bits[2][8] = {{17234,13988,11216,8694,6566,4977,3961,3040}, {12683,9437,6874,5541,5121,5170,5359,5056}};
|
||||
short ac_tns_order_freq[2][8] = {{3,9,23,54,111,190,268,366}, {14,42,100,157,181,178,167,185}};
|
||||
short ac_tns_order_cumfreq[2][8] = {{0,3,12,35,89,200,390,658}, {0,14,56,156,313,494,672,839}};
|
||||
// LC3 Specification d09r01.pdf; Page 110 of 177
|
||||
short ac_tns_coef_bits[8][17] = {{20480,15725,12479,10334,8694,7320,6964,6335,5504,5637,6566,6758,8433,11348,15186,20480,20480},
|
||||
{20480,20480,20480,20480,12902,9368,7057,5901,5254,5485,5598,6076,7608,10742,15186,20480,20480},
|
||||
{20480,20480,20480,20480,13988,9368,6702,4841,4585,4682,5859,7764,12109,20480,20480,20480,20480},
|
||||
{20480,20480,20480,20480,18432,13396,8982,4767,3779,3658,6335,9656,13988,20480,20480,20480,20480},
|
||||
{20480,20480,20480,20480,20480,14731,9437,4275,3249,3493,8483,13988,17234,20480,20480,20480,20480},
|
||||
{20480,20480,20480,20480,20480,20480,12902,4753,3040,2953,9105,15725,20480,20480,20480,20480,20480},
|
||||
{20480,20480,20480,20480,20480,20480,12902,3821,3346,3000,12109,20480,20480,20480,20480,20480,20480},
|
||||
{20480,20480,20480,20480,20480,20480,15725,3658,20480,1201,10854,18432,20480,20480,20480,20480,20480}};
|
||||
short ac_tns_coef_freq[8][17] = {{1,5,15,31,54,86,97,120,159,152,111,104,59,22,6,1,1},
|
||||
{1,1,1,1,13,43,94,139,173,160,154,131,78,27,6,1,1},
|
||||
{1,1,1,1,9,43,106,199,217,210,141,74,17,1,1,1,1},
|
||||
{1,1,1,1,2,11,49,204,285,297,120,39,9,1,1,1,1},
|
||||
{1,1,1,1,1,7,42,241,341,314,58,9,3,1,1,1,1},
|
||||
{1,1,1,1,1,1,13,205,366,377,47,5,1,1,1,1,1},
|
||||
{1,1,1,1,1,1,13,281,330,371,17,1,1,1,1,1,1},
|
||||
{1,1,1,1,1,1,5,297,1,682,26,2,1,1,1,1,1}};
|
||||
short ac_tns_coef_cumfreq[8][17] = {{0,1,6,21,52,106,192,289,409,568,720,831,935,994,1016,1022,1023},
|
||||
{0,1,2,3,4,17,60,154,293,466,626,780,911,989,1016,1022,1023},
|
||||
{0,1,2,3,4,13,56,162,361,578,788,929,1003,1020,1021,1022,1023},
|
||||
{0,1,2,3,4,6,17,66,270,555,852,972,1011,1020,1021,1022,1023},
|
||||
{0,1,2,3,4,5,12,54,295,636,950,1008,1017,1020,1021,1022,1023},
|
||||
{0,1,2,3,4,5,6,19,224,590,967,1014,1019,1020,1021,1022,1023},
|
||||
{0,1,2,3,4,5,6,19,300,630,1001,1018,1019,1020,1021,1022,1023},
|
||||
{0,1,2,3,4,5,6,11,308,309,991,1017,1019,1020,1021,1022,1023}};
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* TemporalNoiseShapingTables.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// LC3 Specification d09r01.pdf
|
||||
// Section 5.7.4 Temporal Noise Shaping
|
||||
|
||||
#ifndef TEMPORAL_NOISE_SHAPING_TABLES_H_
|
||||
#define TEMPORAL_NOISE_SHAPING_TABLES_H_
|
||||
|
||||
// LC3 Specification d09r01.pdf; Page 109 of 177
|
||||
extern short ac_tns_order_bits[2][8];
|
||||
extern short ac_tns_order_freq[2][8];
|
||||
extern short ac_tns_order_cumfreq[2][8];
|
||||
|
||||
extern short ac_tns_coef_bits[8][17];
|
||||
extern short ac_tns_coef_freq[8][17];
|
||||
extern short ac_tns_coef_cumfreq[8][17];
|
||||
|
||||
#endif // TEMPORAL_NOISE_SHAPING_TABLES_H_
|
300
3rd-party/liblc3codec/Decoder/ArithmeticDec.cpp
vendored
300
3rd-party/liblc3codec/Decoder/ArithmeticDec.cpp
vendored
@ -1,300 +0,0 @@
|
||||
/*
|
||||
* ArithmeticDec.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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 "ArithmeticDec.hpp"
|
||||
#include "TemporalNoiseShapingTables.hpp"
|
||||
#include "SpectralDataTables.hpp"
|
||||
|
||||
#include "BitReader.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#include <algorithm> // std::min
|
||||
|
||||
namespace Lc3Dec
|
||||
{
|
||||
|
||||
ArithmeticDec::ArithmeticDec(uint16_t NF_, uint16_t NE_, uint16_t rateFlag_, uint8_t tns_lpc_weighting_)
|
||||
:
|
||||
NF(NF_),
|
||||
NE(NE_),
|
||||
rateFlag(rateFlag_),
|
||||
tns_lpc_weighting(tns_lpc_weighting_),
|
||||
X_hat_q_ari(nullptr),
|
||||
save_lev(nullptr),
|
||||
nf_seed(0),
|
||||
nbits_residual(0)
|
||||
{
|
||||
X_hat_q_ari = new int16_t[NE];
|
||||
save_lev = new uint8_t[NE];
|
||||
}
|
||||
|
||||
ArithmeticDec::~ArithmeticDec()
|
||||
{
|
||||
delete[] X_hat_q_ari;
|
||||
delete[] save_lev;
|
||||
}
|
||||
|
||||
void ac_dec_init(const uint8_t bytes[], uint16_t* bp, struct ac_dec_state* st)
|
||||
{
|
||||
st->low = 0;
|
||||
st->range = 0x00ffffff;
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
{
|
||||
st->low <<= 8;
|
||||
st->low += bytes[(*bp)++];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ac_decode(
|
||||
const uint8_t bytes[],
|
||||
uint16_t* bp,
|
||||
struct ac_dec_state* st,
|
||||
int16_t cum_freq[],
|
||||
int16_t sym_freq[],
|
||||
uint8_t numsym,
|
||||
uint8_t& BEC_detect
|
||||
)
|
||||
{
|
||||
uint32_t tmp = st->range >> 10;
|
||||
if (st->low >= (tmp<<10))
|
||||
{
|
||||
BEC_detect = 1;
|
||||
return 0;
|
||||
}
|
||||
uint8_t val = numsym-1;
|
||||
while (st->low < tmp * cum_freq[val])
|
||||
{
|
||||
val--;
|
||||
}
|
||||
st->low -= tmp * cum_freq[val];
|
||||
st->range = tmp * sym_freq[val];
|
||||
while (st->range < 0x10000)
|
||||
{
|
||||
st->low <<= 8;
|
||||
st->low &= 0x00ffffff;
|
||||
st->low += bytes[(*bp)++];
|
||||
st->range <<= 8;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
double ArithmeticDec::rc_q(uint8_t k, uint8_t f)
|
||||
{
|
||||
// with Δ =π/17
|
||||
const double pi = std::acos(-1);
|
||||
double quantizer_stepsize = pi / 17.0;
|
||||
return sin( quantizer_stepsize * ( rc_i[k + 8*f] -8 ) );
|
||||
}
|
||||
|
||||
void ArithmeticDec::run(
|
||||
const uint8_t* bytes,
|
||||
uint16_t& bp,
|
||||
uint16_t& bp_side,
|
||||
uint8_t& mask_side,
|
||||
int16_t& num_tns_filters,
|
||||
int16_t rc_order[],
|
||||
const uint8_t& lsbMode,
|
||||
const int16_t& lastnz,
|
||||
uint16_t nbits,
|
||||
uint8_t& BEC_detect
|
||||
)
|
||||
{
|
||||
int16_t c = 0;
|
||||
|
||||
// make local copy of rc_order (is this really what we want)
|
||||
rc_order_ari[0] = rc_order[0];
|
||||
rc_order_ari[1] = rc_order[1];
|
||||
|
||||
/* Arithmetic Decoder Initialization */
|
||||
ac_dec_init(bytes, &bp, &st);
|
||||
|
||||
/* TNS data */
|
||||
// Note: some initialization code like that below can be found in d09r02,
|
||||
// but there has been none in d09r01. However, the complete initialization
|
||||
// has been added here, in order to get a proper match to the reference output data
|
||||
for (uint8_t f = 0; f < 2; f++)
|
||||
{
|
||||
for (uint8_t k = 0; k < 8; k++)
|
||||
{
|
||||
rc_i[k + 8*f] = 8;
|
||||
}
|
||||
}
|
||||
for (uint8_t f = 0; f < num_tns_filters; f++)
|
||||
{
|
||||
//if (𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓) > 0)
|
||||
if (rc_order[f] > 0)
|
||||
{
|
||||
//𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓) = ac_decode(bytes, &bp, &st,
|
||||
rc_order_ari[f] = ac_decode(bytes, &bp, &st,
|
||||
ac_tns_order_cumfreq[tns_lpc_weighting],
|
||||
ac_tns_order_freq[tns_lpc_weighting], 8,
|
||||
BEC_detect);
|
||||
if (BEC_detect)
|
||||
{
|
||||
// early exit to avoid unpredictable side-effects
|
||||
return;
|
||||
}
|
||||
|
||||
rc_order_ari[f] = rc_order_ari[f] + 1;
|
||||
// specification (d09r02_F2F) proposes initialization
|
||||
// of rc_i at this place; here implemented above in order
|
||||
// to be performed independet from num_tns_filters
|
||||
for (uint8_t k = 0; k < rc_order_ari[f]; k++)
|
||||
{
|
||||
//𝑟𝑐𝑖(𝑘,𝑓) = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k],
|
||||
//rc_i[k][f] = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k],
|
||||
rc_i[k + 8*f] = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k],
|
||||
ac_tns_coef_freq[k], 17,
|
||||
BEC_detect);
|
||||
if (BEC_detect)
|
||||
{
|
||||
// early exit to avoid unpredictable side-effects
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Spectral data */
|
||||
for (uint16_t k = 0; k < lastnz; k += 2)
|
||||
{
|
||||
uint16_t t = c + rateFlag;
|
||||
//if (k > 𝑁𝐸/2)
|
||||
if (k > NE/2)
|
||||
{
|
||||
t += 256;
|
||||
}
|
||||
//𝑋𝑞̂[k] = 𝑋𝑞̂[k+1] = 0;
|
||||
X_hat_q_ari[k] = X_hat_q_ari[k+1] = 0;
|
||||
uint8_t lev;
|
||||
uint8_t sym;
|
||||
for (lev = 0; lev < 14; lev++)
|
||||
{
|
||||
uint8_t pki = ac_spec_lookup[t+std::min(lev,static_cast<uint8_t>(3U))*1024];
|
||||
sym = ac_decode(bytes, &bp, &st, ac_spec_cumfreq[pki],
|
||||
ac_spec_freq[pki], 17,
|
||||
BEC_detect);
|
||||
if (BEC_detect)
|
||||
{
|
||||
// early exit to avoid unpredictable side-effects
|
||||
return;
|
||||
}
|
||||
if (sym < 16)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (lsbMode == 0 || lev > 0)
|
||||
{
|
||||
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
|
||||
//𝑋𝑞̂[k] += bit << lev;
|
||||
X_hat_q_ari[k] += bit << lev;
|
||||
bit = read_bit(bytes, &bp_side, &mask_side);
|
||||
//𝑋𝑞̂[k+1] += bit << lev;
|
||||
X_hat_q_ari[k+1] += bit << lev;
|
||||
}
|
||||
}
|
||||
if (lev == 14)
|
||||
{
|
||||
BEC_detect = 1;
|
||||
return;
|
||||
}
|
||||
if (lsbMode == 1)
|
||||
{
|
||||
save_lev[k] = lev;
|
||||
}
|
||||
uint8_t a = sym & 0x3;
|
||||
uint8_t b = sym >> 2;
|
||||
//𝑋𝑞̂[k] += a << lev;
|
||||
//𝑋𝑞̂[k+1] += b << lev;
|
||||
//if (𝑋𝑞̂[k] > 0)
|
||||
X_hat_q_ari[k] += a << lev;
|
||||
X_hat_q_ari[k+1] += b << lev;
|
||||
if (X_hat_q_ari[k] > 0)
|
||||
{
|
||||
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
|
||||
if (bit == 1)
|
||||
{
|
||||
//𝑋𝑞̂[k] = -𝑋𝑞̂[k];
|
||||
X_hat_q_ari[k] = -X_hat_q_ari[k];
|
||||
}
|
||||
}
|
||||
//if (𝑋𝑞̂[k+1] > 0)
|
||||
if (X_hat_q_ari[k+1] > 0)
|
||||
{
|
||||
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
|
||||
if (bit == 1)
|
||||
{
|
||||
//𝑋𝑞̂[k+1] = -𝑋𝑞̂[k+1];
|
||||
X_hat_q_ari[k+1] = -X_hat_q_ari[k+1];
|
||||
}
|
||||
}
|
||||
lev = std::min(lev,static_cast<uint8_t>(3));
|
||||
if (lev <= 1)
|
||||
{
|
||||
t = 1 + (a+b)*(lev+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = 12 + lev;
|
||||
}
|
||||
c = (c&15)*16 + t;
|
||||
// Note: specification of the following line hase been changed from d09r01 to d09r02_F2F
|
||||
if (bp - bp_side > 3)
|
||||
{
|
||||
BEC_detect = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// reset remaining fields in array X_hat_q_ari to simplify testing
|
||||
for (int16_t k = lastnz; k < NE; k++)
|
||||
{
|
||||
X_hat_q_ari [k] = 0;
|
||||
}
|
||||
|
||||
|
||||
// 3.4.2.6 Residual data and finalization (d09r02_F2F)
|
||||
/* Number of residual bits */
|
||||
int16_t nbits_side = nbits - (8 * bp_side + 8 - log2(mask_side));
|
||||
int16_t nbits_ari = (bp - 3) * 8;
|
||||
nbits_ari += 25 - floor(log2(st.range));
|
||||
int16_t nbits_residual_tmp = nbits - (nbits_side + nbits_ari);
|
||||
if (nbits_residual_tmp < 0)
|
||||
{
|
||||
BEC_detect = 1;
|
||||
return;
|
||||
}
|
||||
nbits_residual = nbits_residual_tmp;
|
||||
|
||||
}
|
||||
|
||||
void ArithmeticDec::registerDatapoints(DatapointContainer* datapoints)
|
||||
{
|
||||
if (nullptr != datapoints)
|
||||
{
|
||||
datapoints->addDatapoint( "rateFlag", &rateFlag, sizeof(rateFlag) );
|
||||
datapoints->addDatapoint( "tns_lpc_weighting", &tns_lpc_weighting, sizeof(tns_lpc_weighting) );
|
||||
datapoints->addDatapoint( "rc_order_ari", &rc_order_ari[0], sizeof(rc_order_ari) );
|
||||
datapoints->addDatapoint( "rc_i", &rc_i[0], sizeof(rc_i) );
|
||||
datapoints->addDatapoint( "X_hat_q_ari", &X_hat_q_ari[0], sizeof(int16_t)*NE );
|
||||
datapoints->addDatapoint( "nbits_residual", &nbits_residual, sizeof(nbits_residual) );
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace Lc3Dec
|
75
3rd-party/liblc3codec/Decoder/ArithmeticDec.hpp
vendored
75
3rd-party/liblc3codec/Decoder/ArithmeticDec.hpp
vendored
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* ArithmeticDec.hpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ARITHMETIC_DEC_HPP_
|
||||
#define __ARITHMETIC_DEC_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
#include "Datapoints.hpp"
|
||||
|
||||
namespace Lc3Dec
|
||||
{
|
||||
|
||||
struct ac_dec_state {
|
||||
uint32_t low;
|
||||
uint32_t range;
|
||||
};
|
||||
|
||||
class ArithmeticDec
|
||||
{
|
||||
public:
|
||||
ArithmeticDec(uint16_t NF_, uint16_t NE_, uint16_t rateFlag_, uint8_t tns_lpc_weighting_);
|
||||
virtual ~ArithmeticDec();
|
||||
|
||||
void registerDatapoints(DatapointContainer* datapoints);
|
||||
|
||||
double rc_q(uint8_t k, uint8_t f);
|
||||
|
||||
void run(
|
||||
const uint8_t* bytes,
|
||||
uint16_t& bp,
|
||||
uint16_t& bp_side,
|
||||
uint8_t& mask_side,
|
||||
int16_t& num_tns_filters,
|
||||
int16_t rc_order[],
|
||||
const uint8_t& lsbMode,
|
||||
const int16_t& lastnz,
|
||||
uint16_t nbits,
|
||||
uint8_t& BEC_detect
|
||||
);
|
||||
|
||||
const uint16_t NF;
|
||||
const uint16_t NE;
|
||||
const uint16_t rateFlag;
|
||||
const uint8_t tns_lpc_weighting;
|
||||
|
||||
// states & outputs
|
||||
int16_t* X_hat_q_ari;
|
||||
uint8_t* save_lev;
|
||||
int16_t nf_seed;
|
||||
int16_t rc_order_ari[2];
|
||||
int16_t rc_i[2*8]; // [max(rc_order[f])=8][max(num_tns_filters)=2]
|
||||
uint16_t nbits_residual;
|
||||
|
||||
private:
|
||||
struct ac_dec_state st;
|
||||
};
|
||||
|
||||
}//namespace Lc3Dec
|
||||
|
||||
#endif // __ARITHMETIC_DEC_HPP_
|
58
3rd-party/liblc3codec/Decoder/BitReader.cpp
vendored
58
3rd-party/liblc3codec/Decoder/BitReader.cpp
vendored
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* BitReader.cpp
|
||||
*
|
||||
* Copyright 2019 HIMSA II K/S - www.himsa.com. Represented by EHIMA - www.ehima.com
|
||||
*
|
||||
* 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 "BitReader.hpp"
|
||||
|
||||
namespace Lc3Dec
|
||||
{
|
||||
|
||||
uint8_t read_bit(const uint8_t bytes[], uint16_t* bp, uint8_t* mask)
|
||||
{
|
||||
uint8_t bit;
|
||||
if (bytes[*bp] & *mask)
|
||||
{
|
||||
bit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = 0;
|
||||
}
|
||||
if (*mask == 0x80)
|
||||
{
|
||||
*mask = 1;
|
||||
*bp -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*mask <<= 1;
|
||||
}
|
||||
return bit;
|
||||
}
|
||||
|
||||
uint16_t read_uint(const uint8_t bytes[], uint16_t* bp, uint8_t* mask, uint8_t numbits)
|
||||
{
|
||||
uint16_t value = read_bit(bytes, bp, mask);
|
||||
for (uint8_t i = 1; i < numbits; i++)
|
||||
{
|
||||
uint16_t bit = read_bit(bytes, bp, mask);
|
||||
value += bit << i;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}//namespace Lc3Dec
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user