aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Duarte <licorne@google.com>2023-08-16 00:52:36 +0000
committerDavid Duarte <licorne@google.com>2023-08-16 00:52:36 +0000
commit7609a5f5aef68e68f75a0c15f9a2e2b0a08112d3 (patch)
treecd4bc279cbc1c86d8d6da136be5ae737bcae50c9
parentd1c37a2582a7a09d3f69280dbcbc04f1861eaef7 (diff)
parent1a5938ebaca4f13fe79ce074f5dee079783aa29f (diff)
downloadliblc3-7609a5f5aef68e68f75a0c15f9a2e2b0a08112d3.tar.gz
Merge tag 'v1.0.4' into HEAD
Change-Id: I098b3d42976e254209e5fae2aef85f0201a442df
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore6
-rw-r--r--CONTRIBUTING.md28
-rw-r--r--LICENSE202
-rw-r--r--Makefile148
-rw-r--r--README.md132
-rw-r--r--fuzz/dfuzz.cc64
-rw-r--r--fuzz/efuzz.cc117
-rw-r--r--fuzz/makefile.mk52
-rw-r--r--include/lc3.h313
-rw-r--r--include/lc3_cpp.h283
-rw-r--r--include/lc3_private.h163
-rw-r--r--meson.build34
-rw-r--r--meson_options.txt18
-rw-r--r--src/attdet.c92
-rw-r--r--src/attdet.h44
-rw-r--r--src/bits.c375
-rw-r--r--src/bits.h315
-rw-r--r--src/bwdet.c129
-rw-r--r--src/bwdet.h69
-rw-r--r--src/common.h151
-rw-r--r--src/energy.c70
-rw-r--r--src/energy.h43
-rw-r--r--src/fastmath.h158
-rw-r--r--src/lc3.c704
-rw-r--r--src/ltpf.c905
-rw-r--r--src/ltpf.h111
-rw-r--r--src/ltpf_arm.h506
-rw-r--r--src/ltpf_neon.h281
-rw-r--r--src/makefile.mk35
-rw-r--r--src/mdct.c469
-rw-r--r--src/mdct.h57
-rw-r--r--src/mdct_neon.h296
-rw-r--r--src/meson.build61
-rw-r--r--src/plc.c61
-rw-r--r--src/plc.h57
-rw-r--r--src/sns.c880
-rw-r--r--src/sns.h103
-rw-r--r--src/spec.c907
-rw-r--r--src/spec.h119
-rw-r--r--src/tables.c3457
-rw-r--r--src/tables.h94
-rw-r--r--src/tns.c457
-rw-r--r--src/tns.h99
-rwxr-xr-xtables/fastmath.py122
-rwxr-xr-xtables/mktables.py231
-rw-r--r--test/appendix_c.py4083
-rw-r--r--test/arm/ltpf_arm.c114
-rw-r--r--test/arm/makefile.mk31
-rw-r--r--test/arm/simd32.h70
-rw-r--r--test/arm/test_arm.c32
-rw-r--r--test/attdet.py185
-rw-r--r--test/attdet_py.c62
-rw-r--r--test/bitstream.py240
-rw-r--r--test/bwdet.py162
-rw-r--r--test/bwdet_py.c55
-rw-r--r--test/ctypes.h893
-rwxr-xr-xtest/decoder.py197
-rwxr-xr-xtest/encoder.py212
-rw-r--r--test/energy.py92
-rw-r--r--test/energy_py.c62
-rw-r--r--test/lc3_py.c142
-rw-r--r--test/ltpf.py660
-rw-r--r--test/ltpf_py.c138
-rw-r--r--test/makefile.mk30
-rw-r--r--test/mdct.py198
-rw-r--r--test/mdct_py.c93
-rw-r--r--test/module_py.c53
-rw-r--r--test/neon/ltpf_neon.c116
-rw-r--r--test/neon/makefile.mk32
-rw-r--r--test/neon/mdct_neon.c74
-rw-r--r--test/neon/neon.h329
-rw-r--r--test/neon/test_neon.c37
-rwxr-xr-xtest/run.py40
-rwxr-xr-xtest/setup.py49
-rw-r--r--test/sns.py594
-rw-r--r--test/sns_py.c215
-rw-r--r--test/spec.py818
-rw-r--r--test/spec_py.c210
-rw-r--r--test/tables.py2709
-rw-r--r--test/tns.py440
-rw-r--r--test/tns_py.c183
-rw-r--r--tools/dlc3.c257
-rw-r--r--tools/elc3.c260
-rw-r--r--tools/lc3bin.c110
-rw-r--r--tools/lc3bin.h71
-rw-r--r--tools/makefile.mk42
-rw-r--r--tools/meson.build32
-rw-r--r--tools/wave.c182
-rw-r--r--tools/wave.h73
-rw-r--r--zephyr/module.yml4
91 files changed, 27700 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..0a6129d
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+test/* linguist-detectable=false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fa2a190
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.*
+!.gitignore
+bin
+build
+test/build
+*__pycache__
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..6272489
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,28 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution;
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code Reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows [Google's Open Source Community
+Guidelines](https://opensource.google/conduct/).
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e9c2988
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,148 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+V ?= @
+
+BUILD_DIR := build
+BIN_DIR := bin
+
+
+#
+# Set `gcc` as default compiler
+#
+
+CC := $(if $(CC)=cc,gcc,$(CC))
+AS := $(if $(AS)=as,$(CC),$(AS))
+LD := $(if $(LD)=ld,$(CC),$(LD))
+
+CFLAGS := $(if $(DEBUG),-O0 -g,-O3)
+CFLAGS += -std=c11 -Wall -Wextra -Wdouble-promotion -Wvla -pedantic
+
+
+#
+# Declarations
+#
+
+lib_list :=
+bin_list :=
+
+define add-lib
+ $(eval $(1)_bin ?= $(1).a)
+ $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin)))
+
+ lib_list += $(1)
+ LIB += $($(1)_bin)
+endef
+
+define add-bin
+ $(eval $(1)_bin ?= $(1))
+ $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin)))
+
+ $($(1)_bin): LDLIBS += $(if $(filter $(LIBC),bionic),\
+ $(filter-out rt pthread,$($(1)_ldlibs)),$($(1)_ldlibs))
+ $($(1)_bin): LDFLAGS += $($(1)_ldflags)
+
+ bin_list += $(1)
+ BIN += $($(1)_bin)
+endef
+
+define set-target
+ $(eval $(1)_obj ?= $(patsubst %.c,%.o,$(filter %.c,$($(1)_src))) \
+ $(patsubst %.s,%.o,$(filter %.s,$($(1)_src))) \
+ $(patsubst %.cc,%.o,$(filter %.cc,$($(1)_src))))
+ $(eval $(1)_obj := $(addprefix $(BUILD_DIR)/,$($(1)_obj)))
+ $(eval $(1)_lib := $(foreach lib, $($(1)_lib), $($(lib)_bin)))
+
+ $($(1)_obj): INCLUDE += $($(1)_include)
+ $($(1)_obj): DEFINE += $($(1)_define)
+ $($(1)_obj): CFLAGS += $($(1)_cflags)
+ $($(1)_obj): CXXFLAGS += $($(1)_cxxflags)
+
+ -include $($(1)_obj:.o=.d)
+
+ $($(1)_bin): $($(1)_lib)
+ $($(1)_bin): $($(1)_obj)
+ $($(1)_bin): $($(1)_dependencies)
+
+ .PHONY: $(1)
+ $(1): $($(1)_bin)
+endef
+
+.PHONY: default
+default:
+
+
+INCLUDE += include
+
+SRC_DIR = src
+include $(SRC_DIR)/makefile.mk
+
+TOOLS_DIR = tools
+-include $(TOOLS_DIR)/makefile.mk
+
+TEST_DIR := test
+-include $(TEST_DIR)/makefile.mk
+
+FUZZ_DIR := fuzz
+-include $(FUZZ_DIR)/makefile.mk
+
+
+#
+# Rules
+#
+
+MAKEFILE_DEPS := $(MAKEFILE_LIST)
+
+$(foreach lib, $(lib_list), $(eval $(call set-target,$(lib))))
+$(foreach bin, $(bin_list), $(eval $(call set-target,$(bin))))
+
+$(BUILD_DIR)/%.o: %.c $(MAKEFILE_DEPS)
+ @echo " CC $(notdir $<)"
+ $(V)mkdir -p $(dir $@)
+ $(V)$(CC) $< -c $(CFLAGS) \
+ $(addprefix -I,$(INCLUDE)) \
+ $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
+
+$(BUILD_DIR)/%.o: %.s $(MAKEFILE_DEPS)
+ @echo " AS $(notdir $<)"
+ $(V)mkdir -p $(dir $@)
+ $(V)$(AS) $< -c $(CFLAGS) \
+ $(addprefix -I,$(INCLUDE)) \
+ $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
+
+$(BUILD_DIR)/%.o: %.cc $(MAKEFILE_DEPS)
+ @echo " CXX $(notdir $<)"
+ $(V)mkdir -p $(dir $@)
+ $(V)$(CXX) $< -c $(CXXFLAGS) \
+ $(addprefix -I,$(INCLUDE)) \
+ $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@
+
+$(LIB): $(MAKEFILE_DEPS)
+ @echo " AR $(notdir $@)"
+ $(V)mkdir -p $(dir $@)
+ $(V)$(AR) rcs $@ $(filter %.o,$^)
+
+$(BIN): $(MAKEFILE_DEPS)
+ @echo " LD $(notdir $@)"
+ $(V)mkdir -p $(dir $@)
+ $(V)$(LD) $(filter %.o,$^) $(filter %.a,$^) $(LDFLAGS) \
+ $(addprefix -l,$(LDLIBS)) -o $@
+
+clean:
+ $(V)rm -rf $(BUILD_DIR)
+ $(V)rm -rf $(BIN_DIR)
+
+clean-all: clean
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0a97ab7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,132 @@
+# Low Complexity Communication Codec (LC3)
+
+The LC3 is an efficient low latency audio codec.
+
+[_Low Complexity Communication Codec_](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=502107&vId=542963)
+
+## Overview
+
+The directory layout is as follows :
+- include: Library interface
+- src: Source files
+- tools: Standalone encoder/decoder tools
+- test: Python implentation, used as reference for unit testing
+- fuzz: Roundtrip fuzz testing harness
+- build: Building outputs
+- bin: Compilation output
+
+## How to build
+
+The default toolchain used is GCC. Invoke `make` to build the library.
+
+```sh
+$ make -j
+```
+
+Compiled library `liblc3.a` will be found in `bin` directory.
+
+#### Cross compilation
+
+The cc, as, ld and ar can be selected with respective Makefile variables `CC`,
+`AS`, `LD` and `AR`. The `AS` and `LD` selections are optionnal, and fallback
+to `CC` selection when not defined.
+
+The `LIBC` must be set to `bionic` for android cross-compilation. This switch
+prevent link with `pthread` and `rt` libraries, that is included in the
+bionic libc.
+
+Following example build for android, using NDK toolset.
+
+```sh
+$ make -j CC=path_to_android_ndk_prebuilt/toolchain-prefix-clang LIBC=bionic
+```
+
+Compiled library will be found in `bin` directory.
+
+## Tools
+
+Tools can be all compiled, while involking `make` as follows :
+
+```sh
+$ make tools
+```
+
+The standalone encoder `elc3` take a `wave` file as input and encode it
+according given parameter. The LC3 binary file format used is the non
+standard format described by the reference encoder / decoder tools.
+The standalone decoder `dlc3` do the inverse operation.
+
+Refer to `elc3 -h` or `dlc3 -h` for options.
+
+Note that `elc3` output bitstream to standard output when output file is
+omitted. On the other side `dlc3` read from standard input when input output
+file are omitted.
+In such way you can easly test encoding / decoding loop with :
+
+```sh
+$ ./elc3 <in.wav> -b <bitrate> | ./dlc3 > <out.wav>
+```
+
+Adding Linux `aplay` tools, you will be able to instant hear the result :
+
+```sh
+$ ./elc3 <in.wav> -b <bitrate> | ./dlc3 | aplay
+```
+
+## Test
+
+A python implementation of the encoder is provided in `test` diretory.
+The C implementation is unitary validated against this implementation and
+intermediate values given in Appendix C of the specification.
+
+#### Prerequisite
+
+```sh
+# apt install python3 python3-dev python3-pip
+$ pip3 install scipy numpy
+```
+
+#### Running test suite
+
+```sh
+$ make test
+```
+
+## Fuzzing
+
+Roundtrip fuzz testing harness is available in `fuzz` directory.
+LLVM `clang` and `clang++` compilers are needed to run fuzzing.
+
+The encoder and decoder fuzzers can be run, for 1 million iterations, using
+target respectively `dfuzz` and `efuzz`. The `fuzz` target runs both.
+
+```sh
+$ make efuzz # Run encoder fuzzer for 1M iteration
+$ make dfuzz # Run decoder fuzzer for 1M iteration
+$ make fuzz -j # Run encoder and decoder fuzzers in parallel
+```
+
+## Qualification / Conformance
+
+The implementation is qualified under the [_QDID 194161_](https://launchstudio.bluetooth.com/ListingDetails/160904) as part of Google Fluoride 1.5.
+
+For more detail on conformance, refer to [_Bluetooth Conformance
+Documents and scripts_](https://www.bluetooth.com/specifications/specs/low-complexity-communication-codec-1-0/)
+
+## Listening Test
+
+The codec was [_here_](https://hydrogenaud.io/index.php/topic,122575.0.html)
+subjectively evaluated in a blind listening test.
+
+## Meson build system
+
+Meson build system is also available to build and install lc3 codec in Linux
+environment.
+
+```sh
+$ meson build
+$ cd build
+$ ninja
+$ sudo ninja install
+```
+
diff --git a/fuzz/dfuzz.cc b/fuzz/dfuzz.cc
new file mode 100644
index 0000000..c926d61
--- /dev/null
+++ b/fuzz/dfuzz.cc
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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_cpp.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace lc3;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ const int dt_list[] = { 7500, 10000 };
+ const int sr_list[] = { 8000, 16000, 24000, 32000, 48000 };
+
+ FuzzedDataProvider fdp(data, size);
+
+ int dt_us = fdp.PickValueInArray(dt_list);
+ int sr_hz = fdp.PickValueInArray(sr_list);
+ int nchannels =fdp.PickValueInArray({1, 2});
+
+ int sr_pcm_hz = fdp.PickValueInArray(sr_list);
+ if (sr_pcm_hz < sr_hz)
+ sr_pcm_hz = 0;
+
+ Decoder dec(dt_us, sr_hz, sr_pcm_hz, nchannels);
+
+ int frame_size = fdp.ConsumeIntegralInRange(
+ LC3_MIN_FRAME_BYTES, LC3_MAX_FRAME_BYTES);
+
+ PcmFormat fmt = fdp.PickValueInArray(
+ { PcmFormat::kS16, PcmFormat::kS24,
+ PcmFormat::kS24In3Le, PcmFormat::kF32 });
+
+ int frame_samples = dec.GetFrameSamples();
+
+ int sample_bytes =
+ fmt == PcmFormat::kS16 ? sizeof(int16_t) :
+ fmt == PcmFormat::kS24 ? sizeof(int32_t) :
+ fmt == PcmFormat::kS24In3Le ? sizeof(uint8_t) * 3 :
+ fmt == PcmFormat::kF32 ? sizeof(float) : 0;
+
+ if (fdp.remaining_bytes() < frame_size * nchannels)
+ return -1;
+
+ dec.Decode(
+ fdp.ConsumeBytes<uint8_t>(nchannels * frame_size).data(), frame_size,
+ fmt, std::vector<uint8_t>(nchannels * frame_samples * sample_bytes).data());
+
+ return 0;
+}
diff --git a/fuzz/efuzz.cc b/fuzz/efuzz.cc
new file mode 100644
index 0000000..e79ef9c
--- /dev/null
+++ b/fuzz/efuzz.cc
@@ -0,0 +1,117 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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_cpp.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace lc3;
+
+template <typename T>
+T ConsumeInRange(FuzzedDataProvider &fdp, T min, T max) {
+ return fdp.ConsumeIntegralInRange<T>(min, max);
+}
+
+template <>
+float ConsumeInRange(FuzzedDataProvider &fdp, float min, float max) {
+ return fdp.ConsumeFloatingPointInRange<float>(min, max);
+}
+
+template <typename T>
+int encode(Encoder &e, int nchannels, int frame_size, FuzzedDataProvider &fdp,
+ T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
+{
+ int pcm_samples = nchannels * e.GetFrameSamples();
+ if (fdp.remaining_bytes() < pcm_samples * sizeof(T))
+ return -1;
+
+ std::vector<T> pcm(pcm_samples);
+ for (auto &s: pcm)
+ s = ConsumeInRange<T>(fdp, min, max);
+
+ e.Encode(pcm.data(),
+ frame_size, std::vector<uint8_t>(nchannels * frame_size).data());
+
+ return 0;
+}
+
+int encode(Encoder &e, int frame_size, int nchannels,
+ PcmFormat fmt, FuzzedDataProvider &fdp)
+{
+ int sample_bytes =
+ fmt == PcmFormat::kS16 ? sizeof(int16_t) :
+ fmt == PcmFormat::kS24 ? sizeof(int32_t) :
+ fmt == PcmFormat::kS24In3Le ? sizeof(uint8_t) * 3 :
+ fmt == PcmFormat::kF32 ? sizeof(float) : 0;
+
+ int pcm_bytes = nchannels * e.GetFrameSamples() * sample_bytes;
+ if (fdp.remaining_bytes() < pcm_bytes)
+ return -1;
+
+ e.Encode(fmt, fdp.ConsumeBytes<uint8_t>(pcm_bytes).data(),
+ frame_size, std::vector<uint8_t>(nchannels * frame_size).data());
+
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ const int dt_list[] = { 7500, 10000 };
+ const int sr_list[] = { 8000, 16000, 24000, 32000, 48000 };
+
+ FuzzedDataProvider fdp(data, size);
+
+ int dt_us = fdp.PickValueInArray(dt_list);
+ int sr_hz = fdp.PickValueInArray(sr_list);
+ int nchannels = fdp.PickValueInArray({1, 2});
+
+ int sr_pcm_hz = fdp.PickValueInArray(sr_list);
+ if (sr_pcm_hz < sr_hz)
+ sr_pcm_hz = 0;
+
+ Encoder enc(dt_us, sr_hz, sr_pcm_hz, nchannels);
+
+ PcmFormat fmt = fdp.PickValueInArray(
+ { PcmFormat::kS16, PcmFormat::kS24,
+ PcmFormat::kS24In3Le, PcmFormat::kF32 });
+
+ int frame_size = fdp.ConsumeIntegralInRange(
+ LC3_MIN_FRAME_BYTES, LC3_MAX_FRAME_BYTES);
+
+ switch (fmt) {
+
+ case PcmFormat::kS16:
+ return encode<int16_t>(enc, nchannels, frame_size, fdp);
+
+ case PcmFormat::kS24: {
+ const int32_t s24_min = -(1 << 23);
+ const int32_t s24_max = (1 << 23) - 1;
+ return encode<int32_t>(enc, nchannels, frame_size, fdp, s24_min, s24_max);
+ }
+
+ case PcmFormat::kF32: {
+ const float f32_min = -1.0;
+ const float f32_max = 1.0;
+ return encode<float>(enc, nchannels, frame_size, fdp, f32_min, f32_max);
+ }
+
+ case PcmFormat::kS24In3Le:
+ return encode(enc, nchannels, frame_size, fmt, fdp);
+ }
+
+ return 0;
+}
diff --git a/fuzz/makefile.mk b/fuzz/makefile.mk
new file mode 100644
index 0000000..4c83de2
--- /dev/null
+++ b/fuzz/makefile.mk
@@ -0,0 +1,52 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+efuzz_src += \
+ $(FUZZ_DIR)/efuzz.cc
+
+efuzz_lib += liblc3
+efuzz_ldlibs += m
+
+$(eval $(call add-bin,efuzz))
+
+
+dfuzz_src += \
+ $(FUZZ_DIR)/dfuzz.cc
+
+dfuzz_lib += liblc3
+dfuzz_ldlibs += m
+
+$(eval $(call add-bin,dfuzz))
+
+
+.PHONY: fuzz dfuzz efuzz
+
+efuzz dfuzz: CC = clang
+efuzz dfuzz: CXX = clang++
+efuzz dfuzz: LD = clang
+
+FUZZER_SANITIZE := -fsanitize=fuzzer,address
+efuzz dfuzz: CFLAGS += $(FUZZER_SANITIZE)
+efuzz dfuzz: CXXFLAGS += $(FUZZER_SANITIZE)
+efuzz dfuzz: LDFLAGS += $(FUZZER_SANITIZE)
+
+dfuzz:
+ $(V)$(dfuzz_bin) -runs=1000000
+
+efuzz:
+ $(V)$(efuzz_bin) -runs=1000000
+
+fuzz: efuzz dfuzz
diff --git a/include/lc3.h b/include/lc3.h
new file mode 100644
index 0000000..9e84ffb
--- /dev/null
+++ b/include/lc3.h
@@ -0,0 +1,313 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 operates only on fixed frame duration, for
+ * any supported samplerates (8 to 48 KHz). Two frames duration are
+ * available 7.5ms and 10ms.
+ *
+ *
+ * --- About 44.1 KHz samplerate ---
+ *
+ * The Bluetooth specification reference 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 defined base samplerates". Please mind the following items :
+ *
+ * 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 needs to be setup. This context keeps 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
+ * interleaved 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
+ *
+ * ---
+ *
+ * Antoine SOULIER, Tempow / Google LLC
+ *
+ */
+
+#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
+ * - On the number of samples by frames
+ */
+
+#define LC3_MIN_BITRATE 16000
+#define LC3_MAX_BITRATE 320000
+
+#define LC3_MIN_FRAME_BYTES 20
+#define LC3_MAX_FRAME_BYTES 400
+
+#define LC3_MIN_FRAME_SAMPLES __LC3_NS( 7500, 8000)
+#define LC3_MAX_FRAME_SAMPLES __LC3_NS(10000, 48000)
+
+
+/**
+ * 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 (bits 31..24 set to b23).
+ * S24_3LE Signed 24 bits packed in 3 bytes little endian
+ * FLOAT Floating point 32 bits (float type), in range -1 to 1
+ */
+
+enum lc3_pcm_format {
+ LC3_PCM_FORMAT_S16,
+ LC3_PCM_FORMAT_S24,
+ LC3_PCM_FORMAT_S24_3LE,
+ LC3_PCM_FORMAT_FLOAT,
+};
+
+
+/**
+ * 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 second
+ * 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 */
diff --git a/include/lc3_cpp.h b/include/lc3_cpp.h
new file mode 100644
index 0000000..acd3d0b
--- /dev/null
+++ b/include/lc3_cpp.h
@@ -0,0 +1,283 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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) - C++ interface
+ */
+
+#ifndef __LC3_CPP_H
+#define __LC3_CPP_H
+
+#include <cassert>
+#include <memory>
+#include <vector>
+#include <stdlib.h>
+
+#include "lc3.h"
+
+namespace lc3 {
+
+// PCM Sample Format
+// - Signed 16 bits, in 16 bits words (int16_t)
+// - Signed 24 bits, using low three bytes of 32 bits words (int32_t)
+// The high byte sign extends (bits 31..24 set to b23)
+// - Signed 24 bits packed in 3 bytes little endian
+// - Floating point 32 bits (float type), in range -1 to 1
+
+enum class PcmFormat {
+ kS16 = LC3_PCM_FORMAT_S16,
+ kS24 = LC3_PCM_FORMAT_S24,
+ kS24In3Le = LC3_PCM_FORMAT_S24_3LE,
+ kF32 = LC3_PCM_FORMAT_FLOAT
+};
+
+// Base Encoder/Decoder Class
+template <typename T>
+class Base {
+ protected:
+ Base(int dt_us, int sr_hz, int sr_pcm_hz, size_t nchannels)
+ : dt_us_(dt_us),
+ sr_hz_(sr_hz),
+ sr_pcm_hz_(sr_pcm_hz == 0 ? sr_hz : sr_pcm_hz),
+ nchannels_(nchannels) {
+ states.reserve(nchannels_);
+ }
+
+ virtual ~Base() = default;
+
+ int dt_us_, sr_hz_;
+ int sr_pcm_hz_;
+ size_t nchannels_;
+
+ using state_ptr = std::unique_ptr<T, decltype(&free)>;
+ std::vector<state_ptr> states;
+
+ public:
+ // Return the number of PCM samples in a frame
+ int GetFrameSamples() { return lc3_frame_samples(dt_us_, sr_pcm_hz_); }
+
+ // Return the size of frames, from bitrate
+ int GetFrameBytes(int bitrate) { return lc3_frame_bytes(dt_us_, bitrate); }
+
+ // Resolve the bitrate, from the size of frames
+ int ResolveBitrate(int nbytes) { return lc3_resolve_bitrate(dt_us_, nbytes); }
+
+ // Return algorithmic delay, as a number of samples
+ int GetDelaySamples() { return lc3_delay_samples(dt_us_, sr_pcm_hz_); }
+
+}; // class Base
+
+// Encoder Class
+class Encoder : public Base<struct lc3_encoder> {
+ template <typename T>
+ int EncodeImpl(PcmFormat fmt, const T *pcm, int frame_size, uint8_t *out) {
+ if (states.size() != nchannels_) return -1;
+
+ enum lc3_pcm_format cfmt = static_cast<lc3_pcm_format>(fmt);
+ int ret = 0;
+
+ for (size_t ich = 0; ich < nchannels_; ich++)
+ ret |= lc3_encode(states[ich].get(), cfmt, pcm + ich, nchannels_,
+ frame_size, out + ich * frame_size);
+
+ return ret;
+ }
+
+ public:
+ // Encoder construction / destruction
+ //
+ // The frame duration `dt_us` is 7500 or 10000 us.
+ // The samplerate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
+ //
+ // 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`.
+
+ Encoder(int dt_us, int sr_hz, int sr_pcm_hz = 0, size_t nchannels = 1)
+ : Base(dt_us, sr_hz, sr_pcm_hz, nchannels) {
+ for (size_t ich = 0; ich < nchannels_; ich++) {
+ auto s = state_ptr(
+ (lc3_encoder_t)malloc(lc3_encoder_size(dt_us_, sr_pcm_hz_)), free);
+
+ if (lc3_setup_encoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
+ states.push_back(std::move(s));
+ }
+ }
+
+ ~Encoder() override = default;
+
+ // Reset encoder state
+
+ void Reset() {
+ for (auto &s : states)
+ lc3_setup_encoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get());
+ }
+
+ // Encode
+ //
+ // The input PCM samples are given in signed 16 bits, 24 bits, float,
+ // according the type of `pcm` input buffer, or by selecting a format.
+ //
+ // The PCM samples are read in interleaved way, and consecutive
+ // `nchannels` frames of size `frame_size` are output in `out` buffer.
+ //
+ // The value returned is 0 on successs, -1 otherwise.
+
+ int Encode(const int16_t *pcm, int frame_size, uint8_t *out) {
+ return EncodeImpl(PcmFormat::kS16, pcm, frame_size, out);
+ }
+
+ int Encode(const int32_t *pcm, int frame_size, uint8_t *out) {
+ return EncodeImpl(PcmFormat::kS24, pcm, frame_size, out);
+ }
+
+ int Encode(const float *pcm, int frame_size, uint8_t *out) {
+ return EncodeImpl(PcmFormat::kF32, pcm, frame_size, out);
+ }
+
+ int Encode(PcmFormat fmt, const void *pcm, int frame_size, uint8_t *out) {
+ uintptr_t pcm_ptr = reinterpret_cast<uintptr_t>(pcm);
+
+ switch (fmt) {
+ case PcmFormat::kS16:
+ assert(pcm_ptr % alignof(int16_t) == 0);
+ return EncodeImpl(fmt, reinterpret_cast<const int16_t *>(pcm),
+ frame_size, out);
+
+ case PcmFormat::kS24:
+ assert(pcm_ptr % alignof(int32_t) == 0);
+ return EncodeImpl(fmt, reinterpret_cast<const int32_t *>(pcm),
+ frame_size, out);
+
+ case PcmFormat::kS24In3Le:
+ return EncodeImpl(fmt, reinterpret_cast<const int8_t(*)[3]>(pcm),
+ frame_size, out);
+
+ case PcmFormat::kF32:
+ assert(pcm_ptr % alignof(float) == 0);
+ return EncodeImpl(fmt, reinterpret_cast<const float *>(pcm), frame_size,
+ out);
+ }
+
+ return -1;
+ }
+
+}; // class Encoder
+
+// Decoder Class
+class Decoder : public Base<struct lc3_decoder> {
+ template <typename T>
+ int DecodeImpl(const uint8_t *in, int frame_size, PcmFormat fmt, T *pcm) {
+ if (states.size() != nchannels_) return -1;
+
+ enum lc3_pcm_format cfmt = static_cast<enum lc3_pcm_format>(fmt);
+ int ret = 0;
+
+ for (size_t ich = 0; ich < nchannels_; ich++)
+ ret |= lc3_decode(states[ich].get(), in + ich * frame_size, frame_size,
+ cfmt, pcm + ich, nchannels_);
+
+ return ret;
+ }
+
+ public:
+ // Decoder construction / destruction
+ //
+ // The frame duration `dt_us` is 7500 or 10000 us.
+ // The samplerate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
+ //
+ // The `sr_pcm_hz` parameter is an downsampling 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`.
+
+ Decoder(int dt_us, int sr_hz, int sr_pcm_hz = 0, size_t nchannels = 1)
+ : Base(dt_us, sr_hz, sr_pcm_hz, nchannels) {
+ for (size_t i = 0; i < nchannels_; i++) {
+ auto s = state_ptr(
+ (lc3_decoder_t)malloc(lc3_decoder_size(dt_us_, sr_pcm_hz_)), free);
+
+ if (lc3_setup_decoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
+ states.push_back(std::move(s));
+ }
+ }
+
+ ~Decoder() override = default;
+
+ // Reset decoder state
+
+ void Reset() {
+ for (auto &s : states)
+ lc3_setup_decoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get());
+ }
+
+ // Decode
+ //
+ // Consecutive `nchannels` frames of size `frame_size` are decoded
+ // in the `pcm` buffer in interleaved way.
+ //
+ // The PCM samples are output in signed 16 bits, 24 bits, float,
+ // according the type of `pcm` output buffer, or by selecting a format.
+ //
+ // The value returned is 0 on successs, 1 when PLC has been performed,
+ // and -1 otherwise.
+
+ int Decode(const uint8_t *in, int frame_size, int16_t *pcm) {
+ return DecodeImpl(in, frame_size, PcmFormat::kS16, pcm);
+ }
+
+ int Decode(const uint8_t *in, int frame_size, int32_t *pcm) {
+ return DecodeImpl(in, frame_size, PcmFormat::kS24In3Le, pcm);
+ }
+
+ int Decode(const uint8_t *in, int frame_size, float *pcm) {
+ return DecodeImpl(in, frame_size, PcmFormat::kF32, pcm);
+ }
+
+ int Decode(const uint8_t *in, int frame_size, PcmFormat fmt, void *pcm) {
+ uintptr_t pcm_ptr = reinterpret_cast<uintptr_t>(pcm);
+
+ switch (fmt) {
+ case PcmFormat::kS16:
+ assert(pcm_ptr % alignof(int16_t) == 0);
+ return DecodeImpl(in, frame_size, fmt,
+ reinterpret_cast<int16_t *>(pcm));
+
+ case PcmFormat::kS24:
+ assert(pcm_ptr % alignof(int32_t) == 0);
+ return DecodeImpl(in, frame_size, fmt,
+ reinterpret_cast<int32_t *>(pcm));
+
+ case PcmFormat::kS24In3Le:
+ return DecodeImpl(in, frame_size, fmt,
+ reinterpret_cast<int8_t(*)[3]>(pcm));
+
+ case PcmFormat::kF32:
+ assert(pcm_ptr % alignof(float) == 0);
+ return DecodeImpl(in, frame_size, fmt, reinterpret_cast<float *>(pcm));
+ }
+
+ return -1;
+ }
+
+}; // class Decoder
+
+} // namespace lc3
+
+#endif /* __LC3_CPP_H */
diff --git a/include/lc3_private.h b/include/lc3_private.h
new file mode 100644
index 0000000..c4d6703
--- /dev/null
+++ b/include/lc3_private.h
@@ -0,0 +1,163 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 encoding, keep 1.25 ms of temporal winodw
+ * - For decoding, keep 18 ms of history, aligned on frames, and a frame
+ */
+
+#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_NT(sr_hz) \
+ ( (5 * sr_hz) / 4000 )
+
+#define __LC3_NH(dt_us, sr_hz) \
+ ( ((3 - ((dt_us) >= 10000)) + 1) * __LC3_NS(dt_us, sr_hz) )
+
+
+/**
+ * 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 {
+ int32_t en1, an1;
+ int p_att;
+} lc3_attdet_analysis_t;
+
+struct lc3_ltpf_hp50_state {
+ int64_t s1, s2;
+};
+
+typedef struct lc3_ltpf_analysis {
+ bool active;
+ int pitch;
+ float nc[2];
+
+ struct lc3_ltpf_hp50_state hp50;
+ int16_t x_12k8[384];
+ int16_t 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;
+
+ int xt_off, xs_off, xd_off;
+ float x[1];
+};
+
+#define LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz) \
+ ( ( __LC3_NS(dt_us, sr_hz) + __LC3_NT(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 __x[LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz)-1]; \
+ }
+
+
+/**
+ * Decoder state and memory
+ */
+
+typedef struct lc3_ltpf_synthesis {
+ bool active;
+ int pitch;
+ float c[2*12], 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;
+
+ int xh_off, xs_off, xd_off, xg_off;
+ float x[1];
+};
+
+#define LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz) \
+ ( __LC3_NH(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 __x[LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz)-1]; \
+ }
+
+
+#endif /* __LC3_PRIVATE_H */
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..d6eb957
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,34 @@
+# Copyright © 2022 Intel Corporation
+#
+# 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.
+
+project('lc3', 'c',
+ version: '1.0.4',
+ license: 'Apache-2.0',
+ meson_version: '>= 0.47.0',
+ default_options: ['b_lto=true'])
+
+cc = meson.get_compiler('c')
+
+if cc.get_id() != 'msvc'
+ add_project_arguments('-ffast-math', language: 'c')
+endif
+
+
+m_dep = cc.find_library('m', required: false)
+
+subdir('src')
+
+if get_option('tools')
+ subdir('tools')
+endif
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..5249131
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,18 @@
+# Copyright © 2022 Intel Corporation
+#
+# 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.
+
+option('tools',
+ type: 'boolean',
+ value: false,
+ description: 'Build tools')
diff --git a/src/attdet.c b/src/attdet.c
new file mode 100644
index 0000000..3d1528d
--- /dev/null
+++ b/src/attdet.c
@@ -0,0 +1,92 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 int16_t *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);
+ int32_t e[4];
+
+ for (int i = 0; i < nblk; i++) {
+ e[i] = 0;
+
+ if (sr == LC3_SRATE_32K) {
+ int16_t xn2 = (x[-4] + x[-3]) >> 1;
+ int16_t xn1 = (x[-2] + x[-1]) >> 1;
+ int16_t xn, xf;
+
+ for (int j = 0; j < 40; j++, x += 2, xn2 = xn1, xn1 = xn) {
+ xn = (x[0] + x[1]) >> 1;
+ xf = (3 * xn - 4 * xn1 + 1 * xn2) >> 3;
+ e[i] += (xf * xf) >> 5;
+ }
+ }
+
+ else {
+ int16_t xn2 = (x[-6] + x[-5] + x[-4]) >> 2;
+ int16_t xn1 = (x[-3] + x[-2] + x[-1]) >> 2;
+ int16_t xn, xf;
+
+ for (int j = 0; j < 40; j++, x += 3, xn2 = xn1, xn1 = xn) {
+ xn = (x[0] + x[1] + x[2]) >> 2;
+ xf = (3 * xn - 4 * xn1 + 1 * xn2) >> 3;
+ e[i] += (xf * xf) >> 5;
+ }
+ }
+ }
+
+ /* --- 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;
+ int32_t a[4];
+
+ for (int i = 0; i < nblk; i++) {
+ a[i] = LC3_MAX(attdet->an1 >> 2, attdet->en1);
+ attdet->en1 = e[i], attdet->an1 = a[i];
+
+ if ((e[i] >> 3) > a[i] + (a[i] >> 4))
+ p_att = i + 1;
+ }
+
+ int att = attdet->p_att >= 1 + (nblk >> 1) || p_att > 0;
+ attdet->p_att = p_att;
+
+ return att;
+}
diff --git a/src/attdet.h b/src/attdet.h
new file mode 100644
index 0000000..14073bd
--- /dev/null
+++ b/src/attdet.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 int16_t *x);
+
+
+#endif /* __LC3_ATTDET_H */
diff --git a/src/bits.c b/src/bits.c
new file mode 100644
index 0000000..881258b
--- /dev/null
+++ b/src/bits.c
@@ -0,0 +1,375 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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 |= (unsigned)*(--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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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;
+}
diff --git a/src/bits.h b/src/bits.h
new file mode 100644
index 0000000..5dd56cd
--- /dev/null
+++ b/src/bits.h
@@ -0,0 +1,315 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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
+ */
+LC3_HOT static inline void lc3_put_bit(lc3_bits_t *bits, int v)
+{
+ lc3_put_bits(bits, v, 1);
+}
+
+/**
+ * Put from 1 to 32 bits
+ */
+LC3_HOT 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
+ */
+LC3_HOT static inline int lc3_get_bit(lc3_bits_t *bits)
+{
+ return lc3_get_bits(bits, 1);
+}
+
+/**
+ * Get from 1 to 32 bits
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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 */
diff --git a/src/bwdet.c b/src/bwdet.c
new file mode 100644
index 0000000..8dc0f5c
--- /dev/null
+++ b/src/bwdet.c
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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;
+}
diff --git a/src/bwdet.h b/src/bwdet.h
new file mode 100644
index 0000000..19039c7
--- /dev/null
+++ b/src/bwdet.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 */
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..d60ad9e
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 "fastmath.h"
+
+#include <stdalign.h>
+#include <limits.h>
+#include <string.h>
+
+#ifdef __ARM_ARCH
+#include <arm_acle.h>
+#endif
+
+
+/**
+ * Hot Function attribute
+ * Selectively disable sanitizer
+ */
+
+#ifdef __clang__
+
+#define LC3_HOT \
+ __attribute__((no_sanitize("bounds"))) \
+ __attribute__((no_sanitize("integer")))
+
+#else /* __clang__ */
+
+#define LC3_HOT
+
+#endif /* __clang__ */
+
+
+/**
+ * Macros
+ * MIN/MAX Minimum and maximum between 2 values
+ * CLIP Clip a value between low and high limits
+ * SATXX Signed saturation on 'xx' bits
+ * ABS Return 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_SAT16(v) LC3_CLIP(v, -(1 << 15), (1 << 15) - 1)
+#define LC3_SAT24(v) LC3_CLIP(v, -(1 << 23), (1 << 23) - 1)
+
+#define LC3_ABS(v) ( (v) < 0 ? -(v) : (v) )
+
+
+#if defined(__ARM_FEATURE_SAT) && !(__GNUC__ < 10)
+
+#undef LC3_SAT16
+#define LC3_SAT16(v) __ssat(v, 16)
+
+#undef LC3_SAT24
+#define LC3_SAT24(v) __ssat(v, 24)
+
+#endif /* __ARM_FEATURE_SAT */
+
+
+/**
+ * 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 encoding, keep 1.25 ms for temporal window
+ * - For decoding, keep 18 ms of history, aligned on frames, and a frame
+ */
+
+#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_NS \
+ LC3_NS(LC3_DT_10M, LC3_SRATE_48K)
+
+#define LC3_MAX_NE \
+ LC3_NE(LC3_DT_10M, LC3_SRATE_48K)
+
+#define LC3_NT(sr_hz) \
+ ( (5 * LC3_SRATE_KHZ(sr)) / 4 )
+
+#define LC3_NH(dt, sr) \
+ ( ((3 - dt) + 1) * LC3_NS(dt, 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 */
diff --git a/src/energy.c b/src/energy.c
new file mode 100644
index 0000000..bf86db7
--- /dev/null
+++ b/src/energy.c
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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];
+}
diff --git a/src/energy.h b/src/energy.h
new file mode 100644
index 0000000..39f0124
--- /dev/null
+++ b/src/energy.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 */
diff --git a/src/fastmath.h b/src/fastmath.h
new file mode 100644
index 0000000..4210f2e
--- /dev/null
+++ b/src/fastmath.h
@@ -0,0 +1,158 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 - Mathematics function approximation
+ */
+
+#ifndef __LC3_FASTMATH_H
+#define __LC3_FASTMATH_H
+
+#include <stdint.h>
+#include <math.h>
+
+
+/**
+ * Fast 2^n approximation
+ * x Operand, range -8 to 8
+ * return 2^x approximation (max relative error ~ 7e-6)
+ */
+static inline float fast_exp2f(float x)
+{
+ float y;
+
+ /* --- Polynomial approx in range -0.5 to 0.5 --- */
+
+ static const float c[] = { 1.27191277e-09, 1.47415221e-07,
+ 1.35510312e-05, 9.38375815e-04, 4.33216946e-02 };
+
+ y = ( c[0]) * x;
+ y = (y + c[1]) * x;
+ y = (y + c[2]) * x;
+ y = (y + c[3]) * x;
+ y = (y + c[4]) * x;
+ y = (y + 1.f);
+
+ /* --- Raise to the power of 16 --- */
+
+ y = y*y;
+ y = y*y;
+ y = y*y;
+ y = y*y;
+
+ return y;
+}
+
+/**
+ * Fast log2(x) approximation
+ * x Operand, greater than 0
+ * return log2(x) approximation (max absolute error ~ 1e-4)
+ */
+static inline float fast_log2f(float x)
+{
+ float y;
+ int e;
+
+ /* --- Polynomial approx in range 0.5 to 1 --- */
+
+ static const float c[] = {
+ -1.29479677, 5.11769018, -8.42295281, 8.10557963, -3.50567360 };
+
+ x = frexpf(x, &e);
+
+ y = ( c[0]) * x;
+ y = (y + c[1]) * x;
+ y = (y + c[2]) * x;
+ y = (y + c[3]) * x;
+ y = (y + c[4]);
+
+ /* --- Add log2f(2^e) and return --- */
+
+ return e + y;
+}
+
+/**
+ * Fast log10(x) approximation
+ * x Operand, greater than 0
+ * return log10(x) approximation (max absolute error ~ 1e-4)
+ */
+static inline float fast_log10f(float x)
+{
+ return log10f(2) * fast_log2f(x);
+}
+
+/**
+ * Fast `10 * log10(x)` (or dB) approximation in fixed Q16
+ * x Operand, in range 2^-63 to 2^63 (1e-19 to 1e19)
+ * return 10 * log10(x) in fixed Q16 (-190 to 192 dB)
+ *
+ * - The 0 value is accepted and return the minimum value ~ -191dB
+ * - This function assumed that float 32 bits is coded IEEE 754
+ */
+static inline int32_t fast_db_q16(float x)
+{
+ /* --- Table in Q15 --- */
+
+ static const uint16_t t[][2] = {
+
+ /* [n][0] = 10 * log10(2) * log2(1 + n/32), with n = [0..15] */
+ /* [n][1] = [n+1][0] - [n][0] (while defining [16][0]) */
+
+ { 0, 4379 }, { 4379, 4248 }, { 8627, 4125 }, { 12753, 4009 },
+ { 16762, 3899 }, { 20661, 3795 }, { 24456, 3697 }, { 28153, 3603 },
+ { 31755, 3514 }, { 35269, 3429 }, { 38699, 3349 }, { 42047, 3272 },
+ { 45319, 3198 }, { 48517, 3128 }, { 51645, 3061 }, { 54705, 2996 },
+
+ /* [n][0] = 10 * log10(2) * log2(1 + n/32) - 10 * log10(2) / 2, */
+ /* with n = [16..31] */
+ /* [n][1] = [n+1][0] - [n][0] (while defining [32][0]) */
+
+ { 8381, 2934 }, { 11315, 2875 }, { 14190, 2818 }, { 17008, 2763 },
+ { 19772, 2711 }, { 22482, 2660 }, { 25142, 2611 }, { 27754, 2564 },
+ { 30318, 2519 }, { 32837, 2475 }, { 35312, 2433 }, { 37744, 2392 },
+ { 40136, 2352 }, { 42489, 2314 }, { 44803, 2277 }, { 47080, 2241 },
+
+ };
+
+ /* --- Approximation ---
+ *
+ * 10 * log10(x^2) = 10 * log10(2) * log2(x^2)
+ *
+ * And log2(x^2) = 2 * log2( (1 + m) * 2^e )
+ * = 2 * (e + log2(1 + m)) , with m in range [0..1]
+ *
+ * Split the float values in :
+ * e2 Double value of the exponent (2 * e + k)
+ * hi High 5 bits of mantissa, for precalculated result `t[hi][0]`
+ * lo Low 16 bits of mantissa, for linear interpolation `t[hi][1]`
+ *
+ * Two cases, from the range of the mantissa :
+ * 0 to 0.5 `k = 0`, use 1st part of the table
+ * 0.5 to 1 `k = 1`, use 2nd part of the table */
+
+ union { float f; uint32_t u; } x2 = { .f = x*x };
+
+ int e2 = (int)(x2.u >> 22) - 2*127;
+ int hi = (x2.u >> 18) & 0x1f;
+ int lo = (x2.u >> 2) & 0xffff;
+
+ return e2 * 49321 + t[hi][0] + ((t[hi][1] * lo) >> 16);
+}
+
+
+#endif /* __LC3_FASTMATH_H */
diff --git a/src/lc3.c b/src/lc3.c
new file mode 100644
index 0000000..6f54300
--- /dev/null
+++ b/src/lc3.c
@@ -0,0 +1,704 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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;
+
+ int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
+ float *xs = encoder->x + encoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for (int i = 0; i < ns; i++, pcm += stride)
+ xt[i] = *pcm, xs[i] = *pcm;
+}
+
+/**
+ * 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;
+
+ int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
+ float *xs = encoder->x + encoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for (int i = 0; i < ns; i++, pcm += stride) {
+ xt[i] = *pcm >> 8;
+ xs[i] = ldexpf(*pcm, -8);
+ }
+}
+
+/**
+ * Input PCM Samples from signed 24 bits packed
+ * encoder Encoder state
+ * pcm, stride Input PCM samples, and count between two consecutives
+ */
+static void load_s24_3le(
+ struct lc3_encoder *encoder, const void *_pcm, int stride)
+{
+ const uint8_t *pcm = _pcm;
+
+ enum lc3_dt dt = encoder->dt;
+ enum lc3_srate sr = encoder->sr_pcm;
+
+ int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
+ float *xs = encoder->x + encoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for (int i = 0; i < ns; i++, pcm += 3*stride) {
+ int32_t in = ((uint32_t)pcm[0] << 8) |
+ ((uint32_t)pcm[1] << 16) |
+ ((uint32_t)pcm[2] << 24) ;
+
+ xt[i] = in >> 16;
+ xs[i] = ldexpf(in, -16);
+ }
+}
+
+/**
+ * Input PCM Samples from float 32 bits
+ * encoder Encoder state
+ * pcm, stride Input PCM samples, and count between two consecutives
+ */
+static void load_float(
+ struct lc3_encoder *encoder, const void *_pcm, int stride)
+{
+ const float *pcm = _pcm;
+
+ enum lc3_dt dt = encoder->dt;
+ enum lc3_srate sr = encoder->sr_pcm;
+
+ int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
+ float *xs = encoder->x + encoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for (int i = 0; i < ns; i++, pcm += stride) {
+ xs[i] = ldexpf(*pcm, 15);
+ xt[i] = LC3_SAT16((int32_t)xs[i]);
+ }
+}
+
+/**
+ * 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, uint16_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 nt = LC3_NT(sr_pcm);
+
+ int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
+ float *xs = encoder->x + encoder->xs_off;
+ float *xd = encoder->x + encoder->xd_off;
+ float *xf = xs;
+
+ /* --- Temporal --- */
+
+ bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xt);
+
+ side->pitch_present =
+ lc3_ltpf_analyse(dt, sr_pcm, &encoder->ltpf, xt, &side->ltpf);
+
+ memmove(xt - nt, xt + (ns-nt), nt * sizeof(*xt));
+
+ /* --- Spectral --- */
+
+ float e[LC3_NUM_BANDS];
+
+ lc3_mdct_forward(dt, sr_pcm, sr, xs, xd, xf);
+
+ 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, uint16_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->x + encoder->xs_off;
+
+ 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)-1) * 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 nt = LC3_NT(sr_pcm);
+
+ *encoder = (struct lc3_encoder){
+ .dt = dt, .sr = sr,
+ .sr_pcm = sr_pcm,
+
+ .xt_off = nt,
+ .xs_off = (nt + ns) / 2,
+ .xd_off = (nt + ns) / 2 + ns,
+ };
+
+ memset(encoder->x, 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,
+ [LC3_PCM_FORMAT_S24_3LE] = load_s24_3le,
+ [LC3_PCM_FORMAT_FLOAT ] = load_float,
+ };
+
+ /* --- Check parameters --- */
+
+ if (!encoder || nbytes < LC3_MIN_FRAME_BYTES
+ || nbytes > LC3_MAX_FRAME_BYTES)
+ return -1;
+
+ /* --- Processing --- */
+
+ struct side_data side;
+ uint16_t xq[LC3_MAX_NE];
+
+ 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->x + decoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for ( ; ns > 0; ns--, xs++, pcm += stride) {
+ int32_t s = *xs >= 0 ? (int)(*xs + 0.5f) : (int)(*xs - 0.5f);
+ *pcm = LC3_SAT16(s);
+ }
+}
+
+/**
+ * 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;
+
+ enum lc3_dt dt = decoder->dt;
+ enum lc3_srate sr = decoder->sr_pcm;
+
+ float *xs = decoder->x + decoder->xs_off;
+ 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_SAT24(s);
+ }
+}
+
+/**
+ * Output PCM Samples to signed 24 bits packed
+ * decoder Decoder state
+ * pcm, stride Output PCM samples, and count between two consecutives
+ */
+static void store_s24_3le(
+ struct lc3_decoder *decoder, void *_pcm, int stride)
+{
+ uint8_t *pcm = _pcm;
+
+ enum lc3_dt dt = decoder->dt;
+ enum lc3_srate sr = decoder->sr_pcm;
+
+ float *xs = decoder->x + decoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for ( ; ns > 0; ns--, xs++, pcm += 3*stride) {
+ int32_t s = *xs >= 0 ? (int32_t)(ldexpf(*xs, 8) + 0.5f)
+ : (int32_t)(ldexpf(*xs, 8) - 0.5f);
+
+ s = LC3_SAT24(s);
+ pcm[0] = (s >> 0) & 0xff;
+ pcm[1] = (s >> 8) & 0xff;
+ pcm[2] = (s >> 16) & 0xff;
+ }
+}
+
+/**
+ * Output PCM Samples to float 32 bits
+ * decoder Decoder state
+ * pcm, stride Output PCM samples, and count between two consecutives
+ */
+static void store_float(
+ struct lc3_decoder *decoder, void *_pcm, int stride)
+{
+ float *pcm = _pcm;
+
+ enum lc3_dt dt = decoder->dt;
+ enum lc3_srate sr = decoder->sr_pcm;
+
+ float *xs = decoder->x + decoder->xs_off;
+ int ns = LC3_NS(dt, sr);
+
+ for ( ; ns > 0; ns--, xs++, pcm += stride) {
+ float s = ldexpf(*xs, -15);
+ *pcm = fminf(fmaxf(s, -1.f), 1.f);
+ }
+}
+
+/**
+ * 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->x + decoder->xs_off;
+ 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;
+
+ float *xf = decoder->x + decoder->xs_off;
+ int ns = LC3_NS(dt, sr_pcm);
+ int ne = LC3_NE(dt, sr);
+
+ float *xg = decoder->x + decoder->xg_off;
+ float *xs = xf;
+
+ float *xd = decoder->x + decoder->xd_off;
+ float *xh = decoder->x + decoder->xh_off;
+
+ 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, xh, xs);
+}
+
+/**
+ * Update decoder state on decoding completion
+ * decoder Decoder state
+ */
+static void complete(struct lc3_decoder *decoder)
+{
+ enum lc3_dt dt = decoder->dt;
+ enum lc3_srate sr_pcm = decoder->sr_pcm;
+ int nh = LC3_NH(dt, sr_pcm);
+ int ns = LC3_NS(dt, sr_pcm);
+
+ decoder->xs_off = decoder->xs_off - decoder->xh_off < nh - ns ?
+ decoder->xs_off + ns : decoder->xh_off;
+}
+
+/**
+ * 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)-1) * 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(dt, 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,
+
+ .xh_off = 0,
+ .xs_off = nh - ns,
+ .xd_off = nh,
+ .xg_off = nh + nd,
+ };
+
+ lc3_plc_reset(&decoder->plc);
+
+ memset(decoder->x, 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,
+ [LC3_PCM_FORMAT_S24_3LE] = store_s24_3le,
+ [LC3_PCM_FORMAT_FLOAT ] = store_float,
+ };
+
+ /* --- 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);
+
+ complete(decoder);
+
+ return ret;
+}
diff --git a/src/ltpf.c b/src/ltpf.c
new file mode 100644
index 0000000..a0cb7ba
--- /dev/null
+++ b/src/ltpf.c
@@ -0,0 +1,905 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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"
+
+#include "ltpf_neon.h"
+#include "ltpf_arm.h"
+
+
+/* ----------------------------------------------------------------------------
+ * Resampling
+ * -------------------------------------------------------------------------- */
+
+/**
+ * Resampling coefficients
+ * The coefficients, in fixed Q15, are reordered by phase for each source
+ * samplerate (coefficient matrix transposed)
+ */
+
+#ifndef resample_8k_12k8
+static const int16_t h_8k_12k8_q15[8*10] = {
+ 214, 417, -1052, -4529, 26233, -4529, -1052, 417, 214, 0,
+ 180, 0, -1522, -2427, 24506, -5289, 0, 763, 156, -28,
+ 92, -323, -1361, 0, 19741, -3885, 1317, 861, 0, -61,
+ 0, -457, -752, 1873, 13068, 0, 2389, 598, -213, -79,
+ -61, -398, 0, 2686, 5997, 5997, 2686, 0, -398, -61,
+ -79, -213, 598, 2389, 0, 13068, 1873, -752, -457, 0,
+ -61, 0, 861, 1317, -3885, 19741, 0, -1361, -323, 92,
+ -28, 156, 763, 0, -5289, 24506, -2427, -1522, 0, 180,
+};
+#endif /* resample_8k_12k8 */
+
+#ifndef resample_16k_12k8
+static const int16_t h_16k_12k8_q15[4*20] = {
+ -61, 214, -398, 417, 0, -1052, 2686, -4529, 5997, 26233,
+ 5997, -4529, 2686, -1052, 0, 417, -398, 214, -61, 0,
+
+ -79, 180, -213, 0, 598, -1522, 2389, -2427, 0, 24506,
+ 13068, -5289, 1873, 0, -752, 763, -457, 156, 0, -28,
+
+ -61, 92, 0, -323, 861, -1361, 1317, 0, -3885, 19741,
+ 19741, -3885, 0, 1317, -1361, 861, -323, 0, 92, -61,
+
+ -28, 0, 156, -457, 763, -752, 0, 1873, -5289, 13068,
+ 24506, 0, -2427, 2389, -1522, 598, 0, -213, 180, -79,
+};
+#endif /* resample_16k_12k8 */
+
+#ifndef resample_32k_12k8
+static const int16_t h_32k_12k8_q15[2*40] = {
+ -30, -31, 46, 107, 0, -199, -162, 209, 430, 0,
+ -681, -526, 658, 1343, 0, -2264, -1943, 2999, 9871, 13116,
+ 9871, 2999, -1943, -2264, 0, 1343, 658, -526, -681, 0,
+ 430, 209, -162, -199, 0, 107, 46, -31, -30, 0,
+
+ -14, -39, 0, 90, 78, -106, -229, 0, 382, 299,
+ -376, -761, 0, 1194, 937, -1214, -2644, 0, 6534, 12253,
+ 12253, 6534, 0, -2644, -1214, 937, 1194, 0, -761, -376,
+ 299, 382, 0, -229, -106, 78, 90, 0, -39, -14,
+};
+#endif /* resample_32k_12k8 */
+
+#ifndef resample_24k_12k8
+static const int16_t h_24k_12k8_q15[8*30] = {
+ -50, 19, 143, -93, -290, 278, 485, -658, -701, 1396,
+ 901, -3019, -1042, 10276, 17488, 10276, -1042, -3019, 901, 1396,
+ -701, -658, 485, 278, -290, -93, 143, 19, -50, 0,
+
+ -46, 0, 141, -45, -305, 185, 543, -501, -854, 1153,
+ 1249, -2619, -1908, 8712, 17358, 11772, 0, -3319, 480, 1593,
+ -504, -796, 399, 367, -261, -142, 138, 40, -52, -5,
+
+ -41, -17, 133, 0, -304, 91, 574, -334, -959, 878,
+ 1516, -2143, -2590, 7118, 16971, 13161, 1202, -3495, 0, 1731,
+ -267, -908, 287, 445, -215, -188, 125, 62, -52, -12,
+
+ -34, -30, 120, 41, -291, 0, 577, -164, -1015, 585,
+ 1697, -1618, -3084, 5534, 16337, 14406, 2544, -3526, -523, 1800,
+ 0, -985, 152, 509, -156, -230, 104, 83, -48, -19,
+
+ -26, -41, 103, 76, -265, -83, 554, 0, -1023, 288,
+ 1791, -1070, -3393, 3998, 15474, 15474, 3998, -3393, -1070, 1791,
+ 288, -1023, 0, 554, -83, -265, 76, 103, -41, -26,
+
+ -19, -48, 83, 104, -230, -156, 509, 152, -985, 0,
+ 1800, -523, -3526, 2544, 14406, 16337, 5534, -3084, -1618, 1697,
+ 585, -1015, -164, 577, 0, -291, 41, 120, -30, -34,
+
+ -12, -52, 62, 125, -188, -215, 445, 287, -908, -267,
+ 1731, 0, -3495, 1202, 13161, 16971, 7118, -2590, -2143, 1516,
+ 878, -959, -334, 574, 91, -304, 0, 133, -17, -41,
+
+ -5, -52, 40, 138, -142, -261, 367, 399, -796, -504,
+ 1593, 480, -3319, 0, 11772, 17358, 8712, -1908, -2619, 1249,
+ 1153, -854, -501, 543, 185, -305, -45, 141, 0, -46,
+};
+#endif /* resample_24k_12k8 */
+
+#ifndef resample_48k_12k8
+static const int16_t h_48k_12k8_q15[4*60] = {
+ -13, -25, -20, 10, 51, 71, 38, -47, -133, -145,
+ -42, 139, 277, 242, 0, -329, -511, -351, 144, 698,
+ 895, 450, -535, -1510, -1697, -521, 1999, 5138, 7737, 8744,
+ 7737, 5138, 1999, -521, -1697, -1510, -535, 450, 895, 698,
+ 144, -351, -511, -329, 0, 242, 277, 139, -42, -145,
+ -133, -47, 38, 71, 51, 10, -20, -25, -13, 0,
+
+ -9, -23, -24, 0, 41, 71, 52, -23, -115, -152,
+ -78, 92, 254, 272, 76, -251, -493, -427, 0, 576,
+ 900, 624, -262, -1309, -1763, -954, 1272, 4356, 7203, 8679,
+ 8169, 5886, 2767, 0, -1542, -1660, -809, 240, 848, 796,
+ 292, -252, -507, -398, -82, 199, 288, 183, 0, -130,
+ -145, -71, 20, 69, 60, 20, -15, -26, -17, -3,
+
+ -6, -20, -26, -8, 31, 67, 62, 0, -94, -152,
+ -108, 45, 223, 287, 143, -167, -454, -480, -134, 439,
+ 866, 758, 0, -1071, -1748, -1295, 601, 3559, 6580, 8485,
+ 8485, 6580, 3559, 601, -1295, -1748, -1071, 0, 758, 866,
+ 439, -134, -480, -454, -167, 143, 287, 223, 45, -108,
+ -152, -94, 0, 62, 67, 31, -8, -26, -20, -6,
+
+ -3, -17, -26, -15, 20, 60, 69, 20, -71, -145,
+ -130, 0, 183, 288, 199, -82, -398, -507, -252, 292,
+ 796, 848, 240, -809, -1660, -1542, 0, 2767, 5886, 8169,
+ 8679, 7203, 4356, 1272, -954, -1763, -1309, -262, 624, 900,
+ 576, 0, -427, -493, -251, 76, 272, 254, 92, -78,
+ -152, -115, -23, 52, 71, 41, 0, -24, -23, -9,
+};
+#endif /* resample_48k_12k8 */
+
+
+/**
+ * High-pass 50Hz filtering, at 12.8 KHz samplerate
+ * hp50 Biquad filter state
+ * xn Input sample, in fixed Q30
+ * return Filtered sample, in fixed Q30
+ */
+LC3_HOT static inline int32_t filter_hp50(
+ struct lc3_ltpf_hp50_state *hp50, int32_t xn)
+{
+ int32_t yn;
+
+ const int32_t a1 = -2110217691, a2 = 1037111617;
+ const int32_t b1 = -2110535566, b2 = 1055267782;
+
+ yn = (hp50->s1 + (int64_t)xn * b2) >> 30;
+ hp50->s1 = (hp50->s2 + (int64_t)xn * b1 - (int64_t)yn * a1);
+ hp50->s2 = ( (int64_t)xn * b2 - (int64_t)yn * a2);
+
+ return yn;
+}
+
+/**
+ * Resample from 8 / 16 / 32 KHz to 12.8 KHz Template
+ * p Resampling factor with compared to 192 KHz (8, 4 or 2)
+ * h Arrange by phase coefficients table
+ * hp50 High-Pass biquad filter state
+ * x [-d..-1] Previous, [0..ns-1] Current samples, Q15
+ * y, n [0..n-1] Output `n` processed samples, Q14
+ *
+ * The `x` vector is aligned on 32 bits
+ * The number of previous samples `d` accessed on `x` is :
+ * d: { 10, 20, 40 } - 1 for resampling factors 8, 4 and 2.
+ */
+#if !defined(resample_8k_12k8) || !defined(resample_16k_12k8) \
+ || !defined(resample_32k_12k8)
+LC3_HOT static inline void resample_x64k_12k8(const int p, const int16_t *h,
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ const int w = 2*(40 / p);
+
+ x -= w - 1;
+
+ for (int i = 0; i < 5*n; i += 5) {
+ const int16_t *hn = h + (i % p) * w;
+ const int16_t *xn = x + (i / p);
+ int32_t un = 0;
+
+ for (int k = 0; k < w; k += 10) {
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ }
+
+ int32_t yn = filter_hp50(hp50, un);
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+#endif
+
+/**
+ * Resample from 24 / 48 KHz to 12.8 KHz Template
+ * p Resampling factor with compared to 192 KHz (8 or 4)
+ * h Arrange by phase coefficients table
+ * hp50 High-Pass biquad filter state
+ * x [-d..-1] Previous, [0..ns-1] Current samples, Q15
+ * y, n [0..n-1] Output `n` processed samples, Q14
+ *
+ * The `x` vector is aligned on 32 bits
+ * The number of previous samples `d` accessed on `x` is :
+ * d: { 30, 60 } - 1 for resampling factors 8 and 4.
+ */
+#if !defined(resample_24k_12k8) || !defined(resample_48k_12k8)
+LC3_HOT static inline void resample_x192k_12k8(const int p, const int16_t *h,
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ const int w = 2*(120 / p);
+
+ x -= w - 1;
+
+ for (int i = 0; i < 15*n; i += 15) {
+ const int16_t *hn = h + (i % p) * w;
+ const int16_t *xn = x + (i / p);
+ int32_t un = 0;
+
+ for (int k = 0; k < w; k += 15) {
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ un += *(xn++) * *(hn++);
+ }
+
+ int32_t yn = filter_hp50(hp50, un);
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+#endif
+
+/**
+ * Resample from 8 Khz to 12.8 KHz
+ * hp50 High-Pass biquad filter state
+ * x [-10..-1] Previous, [0..ns-1] Current samples, Q15
+ * y, n [0..n-1] Output `n` processed samples, Q14
+ *
+ * The `x` vector is aligned on 32 bits
+ */
+#ifndef resample_8k_12k8
+LC3_HOT static void resample_8k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ resample_x64k_12k8(8, h_8k_12k8_q15, hp50, x, y, n);
+}
+#endif /* resample_8k_12k8 */
+
+/**
+ * Resample from 16 Khz to 12.8 KHz
+ * hp50 High-Pass biquad filter state
+ * x [-20..-1] Previous, [0..ns-1] Current samples, in fixed Q15
+ * y, n [0..n-1] Output `n` processed samples, in fixed Q14
+ *
+ * The `x` vector is aligned on 32 bits
+ */
+#ifndef resample_16k_12k8
+LC3_HOT static void resample_16k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ resample_x64k_12k8(4, h_16k_12k8_q15, hp50, x, y, n);
+}
+#endif /* resample_16k_12k8 */
+
+/**
+ * Resample from 32 Khz to 12.8 KHz
+ * hp50 High-Pass biquad filter state
+ * x [-30..-1] Previous, [0..ns-1] Current samples, in fixed Q15
+ * y, n [0..n-1] Output `n` processed samples, in fixed Q14
+ *
+ * The `x` vector is aligned on 32 bits
+ */
+#ifndef resample_32k_12k8
+LC3_HOT static void resample_32k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ resample_x64k_12k8(2, h_32k_12k8_q15, hp50, x, y, n);
+}
+#endif /* resample_32k_12k8 */
+
+/**
+ * Resample from 24 Khz to 12.8 KHz
+ * hp50 High-Pass biquad filter state
+ * x [-30..-1] Previous, [0..ns-1] Current samples, in fixed Q15
+ * y, n [0..n-1] Output `n` processed samples, in fixed Q14
+ *
+ * The `x` vector is aligned on 32 bits
+ */
+#ifndef resample_24k_12k8
+LC3_HOT static void resample_24k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ resample_x192k_12k8(8, h_24k_12k8_q15, hp50, x, y, n);
+}
+#endif /* resample_24k_12k8 */
+
+/**
+ * Resample from 48 Khz to 12.8 KHz
+ * hp50 High-Pass biquad filter state
+ * x [-60..-1] Previous, [0..ns-1] Current samples, in fixed Q15
+ * y, n [0..n-1] Output `n` processed samples, in fixed Q14
+ *
+* The `x` vector is aligned on 32 bits
+*/
+#ifndef resample_48k_12k8
+LC3_HOT static void resample_48k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ resample_x192k_12k8(4, h_48k_12k8_q15, hp50, x, y, n);
+}
+#endif /* resample_48k_12k8 */
+
+/**
+* Resample to 6.4 KHz
+* x [-3..-1] Previous, [0..n-1] Current samples
+* y, n [0..n-1] Output `n` processed samples
+*
+* The `x` vector is aligned on 32 bits
+ */
+#ifndef resample_6k4
+LC3_HOT static void resample_6k4(const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t h[] = { 18477, 15424, 8105 };
+ const int16_t *ye = y + n;
+
+ for (x--; y < ye; x += 2)
+ *(y++) = (x[0] * h[0] + (x[-1] + x[1]) * h[1]
+ + (x[-2] + x[2]) * h[2]) >> 16;
+}
+#endif /* resample_6k4 */
+
+/**
+ * LTPF Resample to 12.8 KHz implementations for each samplerates
+ */
+
+static void (* const resample_12k8[])
+ (struct lc3_ltpf_hp50_state *, const int16_t *, int16_t *, 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,
+};
+
+
+/* ----------------------------------------------------------------------------
+ * Analysis
+ * -------------------------------------------------------------------------- */
+
+/**
+ * Return dot product of 2 vectors
+ * a, b, n The 2 vectors of size `n` (> 0 and <= 128)
+ * return sum( a[i] * b[i] ), i = [0..n-1]
+ *
+ * The size `n` of vectors must be multiple of 16, and less or equal to 128
+*/
+#ifndef dot
+LC3_HOT static inline float dot(const int16_t *a, const int16_t *b, int n)
+{
+ int64_t v = 0;
+
+ for (int i = 0; i < (n >> 4); i++)
+ for (int j = 0; j < 16; j++)
+ v += *(a++) * *(b++);
+
+ int32_t v32 = (v + (1 << 5)) >> 6;
+ return (float)v32;
+}
+#endif /* dot */
+
+/**
+ * Return vector of correlations
+ * a, b, n The 2 vector of size `n` (> 0 and <= 128)
+ * y, nc Output the correlation vector of size `nc`
+ *
+ * The first vector `a` is aligned of 32 bits
+ * The size `n` of vectors is multiple of 16, and less or equal to 128
+ */
+#ifndef correlate
+LC3_HOT static void correlate(
+ const int16_t *a, const int16_t *b, int n, float *y, int nc)
+{
+ for (const float *ye = y + nc; y < ye; )
+ *(y++) = dot(a, b--, n);
+}
+#endif /* correlate */
+
+/**
+ * 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT static void interpolate(const int16_t *x, int n, int d, int16_t *y)
+{
+ static const int16_t h4_q15[][4] = {
+ { 6877, 19121, 6877, 0 }, { 3506, 18025, 11000, 220 },
+ { 1300, 15048, 15048, 1300 }, { 220, 11000, 18025, 3506 } };
+
+ const int16_t *h = h4_q15[d];
+ int16_t x3 = x[-2], x2 = x[-1], x1, x0;
+
+ x1 = (*x++);
+ for (const int16_t *ye = y + n; y < ye; ) {
+ int32_t yn;
+
+ yn = (x0 = *(x++)) * h[0] + x1 * h[1] + x2 * h[2] + x3 * h[3];
+ *(y++) = yn >> 15;
+
+ yn = (x3 = *(x++)) * h[0] + x0 * h[1] + x1 * h[2] + x2 * h[3];
+ *(y++) = yn >> 15;
+
+ yn = (x2 = *(x++)) * h[0] + x3 * h[1] + x0 * h[2] + x1 * h[3];
+ *(y++) = yn >> 15;
+
+ yn = (x1 = *(x++)) * h[0] + x2 * h[1] + x3 * h[2] + x0 * h[3];
+ *(y++) = yn >> 15;
+ }
+}
+
+/**
+ * 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
+ */
+LC3_HOT static float interpolate_corr(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
+ *
+ * The `x` vector is aligned on 32 bits
+ */
+static bool detect_pitch(
+ struct lc3_ltpf_analysis *ltpf, const int16_t *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, -.5f/(nr-1), &rm1);
+ int t2 = k0 + argmax(r + k0, nk, &rm2);
+
+ const int16_t *x1 = x - (r0 + t1);
+ const int16_t *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.85f * nc1;
+ ltpf->tc = (t1sel ? t1 : t2);
+
+ *tc = r0 + ltpf->tc;
+ return (t1sel ? nc1 : nc2) > 0.6f;
+}
+
+/**
+ * Pitch-lag parameter (3.3.9.7)
+ * x, n [-232..-28] Previous, [0..n-1] Current 12.8KHz samples, Q14
+ * tc Pitch-lag estimation
+ * pitch The pitch value, in fixed .4
+ * return The bitstream pitch index value
+ *
+ * The `x` vector is aligned on 32 bits
+ */
+static int refine_pitch(const int16_t *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_corr(re, f = 0);
+ for (int i = 1; i <= 3; i++) {
+ float d;
+
+ if (e >= 127 && ((i & 1) | (e >= 157)))
+ continue;
+
+ if ((d = interpolate_corr(re, i)) > dm)
+ dm = d, f = i;
+
+ if (e > 32 && (d = interpolate_corr(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 int16_t *x, struct lc3_ltpf_data *data)
+{
+ /* --- Resampling to 12.8 KHz --- */
+
+ int z_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8);
+ int n_12k8 = dt == LC3_DT_7M5 ? 96 : 128;
+
+ memmove(ltpf->x_12k8, ltpf->x_12k8 + n_12k8,
+ (z_12k8 - n_12k8) * sizeof(*ltpf->x_12k8));
+
+ int16_t *x_12k8 = ltpf->x_12k8 + (z_12k8 - n_12k8);
+
+ resample_12k8[sr](&ltpf->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(*ltpf->x_6k4);
+ int n_6k4 = n_12k8 >> 1;
+
+ memmove(ltpf->x_6k4, ltpf->x_6k4 + n_6k4,
+ (z_6k4 - n_6k4) * sizeof(*ltpf->x_6k4));
+
+ int16_t *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) {
+ int16_t u[128], v[128];
+
+ 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.9f) || (nc > 0.84f && pitch_diff < 8 && nc_diff > -0.1f));
+
+ } else {
+ data->active = pitch_present &&
+ ( (dt == LC3_DT_10M || ltpf->nc[1] > 0.94f) &&
+ (ltpf->nc[0] > 0.94f && nc > 0.94f) );
+ }
+
+ ltpf->active = data->active;
+ ltpf->pitch = pitch;
+ ltpf->nc[1] = ltpf->nc[0];
+ ltpf->nc[0] = nc;
+
+ return pitch_present;
+}
+
+
+/* ----------------------------------------------------------------------------
+ * Synthesis
+ * -------------------------------------------------------------------------- */
+
+/**
+ * Width of synthesis filter
+ */
+
+#define FILTER_WIDTH(sr) \
+ LC3_MAX(4, LC3_SRATE_KHZ(sr) / 4)
+
+#define MAX_FILTER_WIDTH \
+ FILTER_WIDTH(LC3_NUM_SRATE)
+
+
+/**
+ * Synthesis filter template
+ * xh, nh History ring buffer of filtered samples
+ * lag Lag parameter in the ring buffer
+ * x0 w-1 previous input samples
+ * x, n Current samples as input, filtered as output
+ * c, w Coefficients `den` then `num`, and width of filter
+ * fade Fading mode of filter -1: Out 1: In 0: None
+ */
+LC3_HOT static inline void synthesize_template(
+ const float *xh, int nh, int lag,
+ const float *x0, float *x, int n,
+ const float *c, const int w, int fade)
+{
+ float g = (float)(fade <= 0);
+ float g_incr = (float)((fade > 0) - (fade < 0)) / n;
+ float u[MAX_FILTER_WIDTH];
+
+ /* --- Load previous samples --- */
+
+ lag += (w >> 1);
+
+ const float *y = x - xh < lag ? x + (nh - lag) : x - lag;
+ const float *y_end = xh + nh - 1;
+
+ for (int j = 0; j < w-1; j++) {
+
+ u[j] = 0;
+
+ float yi = *y, xi = *(x0++);
+ y = y < y_end ? y + 1 : xh;
+
+ for (int k = 0; k <= j; k++)
+ u[j-k] -= yi * c[k];
+
+ for (int k = 0; k <= j; k++)
+ u[j-k] += xi * c[w+k];
+ }
+
+ u[w-1] = 0;
+
+ /* --- Process by filter length --- */
+
+ for (int i = 0; i < n; i += w)
+ for (int j = 0; j < w; j++, g += g_incr) {
+
+ float yi = *y, xi = *x;
+ y = y < y_end ? y + 1 : xh;
+
+ for (int k = 0; k < w; k++)
+ u[(j+(w-1)-k)%w] -= yi * c[k];
+
+ for (int k = 0; k < w; k++)
+ u[(j+(w-1)-k)%w] += xi * c[w+k];
+
+ *(x++) = xi - g * u[j];
+ u[j] = 0;
+ }
+}
+
+/**
+ * Synthesis filter for each samplerates (width of filter)
+ */
+
+
+LC3_HOT static void synthesize_4(const float *xh, int nh, int lag,
+ const float *x0, float *x, int n, const float *c, int fade)
+{
+ synthesize_template(xh, nh, lag, x0, x, n, c, 4, fade);
+}
+
+LC3_HOT static void synthesize_6(const float *xh, int nh, int lag,
+ const float *x0, float *x, int n, const float *c, int fade)
+{
+ synthesize_template(xh, nh, lag, x0, x, n, c, 6, fade);
+}
+
+LC3_HOT static void synthesize_8(const float *xh, int nh, int lag,
+ const float *x0, float *x, int n, const float *c, int fade)
+{
+ synthesize_template(xh, nh, lag, x0, x, n, c, 8, fade);
+}
+
+LC3_HOT static void synthesize_12(const float *xh, int nh, int lag,
+ const float *x0, float *x, int n, const float *c, int fade)
+{
+ synthesize_template(xh, nh, lag, x0, x, n, c, 12, fade);
+}
+
+static void (* const synthesize[])(const float *, int, int,
+ const float *, float *, int, const float *, 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,
+ lc3_ltpf_synthesis_t *ltpf, const lc3_ltpf_data_t *data,
+ const float *xh, float *x)
+{
+ int nh = LC3_NH(dt, sr);
+ 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 = FILTER_WIDTH(sr);
+ float c[2 * MAX_FILTER_WIDTH];
+
+ for (int i = 0; i < w; i++) {
+ float g = active ? 0.4f - 0.05f * g_idx : 0;
+ c[ i] = g * lc3_ltpf_cden[sr][pitch & 3][(w-1)-i];
+ c[w+i] = 0.85f * g * lc3_ltpf_cnum[sr][LC3_MIN(g_idx, 3)][(w-1)-i];
+ }
+
+ /* --- Transition handling --- */
+
+ int ns = LC3_NS(dt, sr);
+ int nt = ns / (3 + dt);
+ float x0[MAX_FILTER_WIDTH];
+
+ if (active)
+ memcpy(x0, x + nt-(w-1), (w-1) * sizeof(float));
+
+ if (!ltpf->active && active)
+ synthesize[sr](xh, nh, pitch/4, ltpf->x, x, nt, c, 1);
+ else if (ltpf->active && !active)
+ synthesize[sr](xh, nh, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
+ else if (ltpf->active && active && ltpf->pitch == pitch)
+ synthesize[sr](xh, nh, pitch/4, ltpf->x, x, nt, c, 0);
+ else if (ltpf->active && active) {
+ synthesize[sr](xh, nh, ltpf->pitch/4, ltpf->x, x, nt, ltpf->c, -1);
+ synthesize[sr](xh, nh, pitch/4,
+ (x <= xh ? x + nh : x) - (w-1), x, nt, c, 1);
+ }
+
+ /* --- Remainder --- */
+
+ memcpy(ltpf->x, x + ns - (w-1), (w-1) * sizeof(float));
+
+ if (active)
+ synthesize[sr](xh, nh, pitch/4, x0, x + nt, ns-nt, c, 0);
+
+ /* --- Update state --- */
+
+ ltpf->active = active;
+ ltpf->pitch = pitch;
+ memcpy(ltpf->c, c, 2*w * sizeof(*ltpf->c));
+}
+
+
+/* ----------------------------------------------------------------------------
+ * 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);
+}
diff --git a/src/ltpf.h b/src/ltpf.h
new file mode 100644
index 0000000..0d5bb3c
--- /dev/null
+++ b/src/ltpf.h
@@ -0,0 +1,111 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 `x` vector is aligned on 32 bits
+ * 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 int16_t *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
+ * xr Base address of ring buffer of decoded samples
+ * x Samples to proceed in the ring buffer, filtered as output
+ *
+ * The size of the ring buffer is `nh + ns`.
+ * The filtering needs an history of at least 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,
+ const float *xr, float *x);
+
+
+#endif /* __LC3_LTPF_H */
diff --git a/src/ltpf_arm.h b/src/ltpf_arm.h
new file mode 100644
index 0000000..c2cc6c0
--- /dev/null
+++ b/src/ltpf_arm.h
@@ -0,0 +1,506 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#if (__ARM_FEATURE_SIMD32 && !(__GNUC__ < 10) || defined(TEST_ARM))
+
+#ifndef TEST_ARM
+
+#include <arm_acle.h>
+
+static inline int16x2_t __pkhbt(int16x2_t a, int16x2_t b)
+{
+ int16x2_t r;
+ __asm("pkhbt %0, %1, %2" : "=r" (r) : "r" (a), "r" (b));
+ return r;
+}
+
+#endif /* TEST_ARM */
+
+
+/**
+ * Import
+ */
+
+static inline int32_t filter_hp50(struct lc3_ltpf_hp50_state *, int32_t);
+static inline float dot(const int16_t *, const int16_t *, int);
+
+
+/**
+ * Resample from 8 / 16 / 32 KHz to 12.8 KHz Template
+ */
+#if !defined(resample_8k_12k8) || !defined(resample_16k_12k8) \
+ || !defined(resample_32k_12k8)
+static inline void arm_resample_x64k_12k8(const int p, const int16x2_t *h,
+ struct lc3_ltpf_hp50_state *hp50, const int16x2_t *x, int16_t *y, int n)
+{
+ const int w = 40 / p;
+
+ x -= w;
+
+ for (int i = 0; i < 5*n; i += 5) {
+ const int16x2_t *hn = h + (i % (2*p)) * (48 / p);
+ const int16x2_t *xn = x + (i / (2*p));
+
+ int32_t un = __smlad(*(xn++), *(hn++), 0);
+
+ for (int k = 0; k < w; k += 5) {
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ }
+
+ int32_t yn = filter_hp50(hp50, un);
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+#endif
+
+/**
+ * Resample from 24 / 48 KHz to 12.8 KHz Template
+ */
+#if !defined(resample_24k_12k8) || !defined(resample_48k_12k8)
+static inline void arm_resample_x192k_12k8(const int p, const int16x2_t *h,
+ struct lc3_ltpf_hp50_state *hp50, const int16x2_t *x, int16_t *y, int n)
+{
+ const int w = 120 / p;
+
+ x -= w;
+
+ for (int i = 0; i < 15*n; i += 15) {
+ const int16x2_t *hn = h + (i % (2*p)) * (128 / p);
+ const int16x2_t *xn = x + (i / (2*p));
+
+ int32_t un = __smlad(*(xn++), *(hn++), 0);
+
+ for (int k = 0; k < w; k += 15) {
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ un = __smlad(*(xn++), *(hn++), un);
+ }
+
+ int32_t yn = filter_hp50(hp50, un);
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+#endif
+
+/**
+ * Resample from 8 Khz to 12.8 KHz
+ */
+#ifndef resample_8k_12k8
+
+static void arm_resample_8k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t alignas(int32_t) h[2*8*12] = {
+ 0, 214, 417, -1052, -4529, 26233, -4529, -1052, 417, 214, 0, 0,
+ 0, 180, 0, -1522, -2427, 24506, -5289, 0, 763, 156, -28, 0,
+ 0, 92, -323, -1361, 0, 19741, -3885, 1317, 861, 0, -61, 0,
+ 0, 0, -457, -752, 1873, 13068, 0, 2389, 598, -213, -79, 0,
+ 0, -61, -398, 0, 2686, 5997, 5997, 2686, 0, -398, -61, 0,
+ 0, -79, -213, 598, 2389, 0, 13068, 1873, -752, -457, 0, 0,
+ 0, -61, 0, 861, 1317, -3885, 19741, 0, -1361, -323, 92, 0,
+ 0, -28, 156, 763, 0, -5289, 24506, -2427, -1522, 0, 180, 0,
+ 0, 0, 214, 417, -1052, -4529, 26233, -4529, -1052, 417, 214, 0,
+ 0, 0, 180, 0, -1522, -2427, 24506, -5289, 0, 763, 156, -28,
+ 0, 0, 92, -323, -1361, 0, 19741, -3885, 1317, 861, 0, -61,
+ 0, 0, 0, -457, -752, 1873, 13068, 0, 2389, 598, -213, -79,
+ 0, 0, -61, -398, 0, 2686, 5997, 5997, 2686, 0, -398, -61,
+ 0, 0, -79, -213, 598, 2389, 0, 13068, 1873, -752, -457, 0,
+ 0, 0, -61, 0, 861, 1317, -3885, 19741, 0, -1361, -323, 92,
+ 0, 0, -28, 156, 763, 0, -5289, 24506, -2427, -1522, 0, 180,
+ };
+
+ arm_resample_x64k_12k8(
+ 8, (const int16x2_t *)h, hp50, (int16x2_t *)x, y, n);
+}
+
+#ifndef TEST_ARM
+#define resample_8k_12k8 arm_resample_8k_12k8
+#endif
+
+#endif /* resample_8k_12k8 */
+
+/**
+ * Resample from 16 Khz to 12.8 KHz
+ */
+#ifndef resample_16k_12k8
+
+static void arm_resample_16k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t alignas(int32_t) h[2*4*24] = {
+
+ 0, -61, 214, -398, 417, 0, -1052, 2686,
+ -4529, 5997, 26233, 5997, -4529, 2686, -1052, 0,
+ 417, -398, 214, -61, 0, 0, 0, 0,
+
+
+ 0, -79, 180, -213, 0, 598, -1522, 2389,
+ -2427, 0, 24506, 13068, -5289, 1873, 0, -752,
+ 763, -457, 156, 0, -28, 0, 0, 0,
+
+
+ 0, -61, 92, 0, -323, 861, -1361, 1317,
+ 0, -3885, 19741, 19741, -3885, 0, 1317, -1361,
+ 861, -323, 0, 92, -61, 0, 0, 0,
+
+ 0, -28, 0, 156, -457, 763, -752, 0,
+ 1873, -5289, 13068, 24506, 0, -2427, 2389, -1522,
+ 598, 0, -213, 180, -79, 0, 0, 0,
+
+
+ 0, 0, -61, 214, -398, 417, 0, -1052,
+ 2686, -4529, 5997, 26233, 5997, -4529, 2686, -1052,
+ 0, 417, -398, 214, -61, 0, 0, 0,
+
+
+ 0, 0, -79, 180, -213, 0, 598, -1522,
+ 2389, -2427, 0, 24506, 13068, -5289, 1873, 0,
+ -752, 763, -457, 156, 0, -28, 0, 0,
+
+
+ 0, 0, -61, 92, 0, -323, 861, -1361,
+ 1317, 0, -3885, 19741, 19741, -3885, 0, 1317,
+ -1361, 861, -323, 0, 92, -61, 0, 0,
+
+ 0, 0, -28, 0, 156, -457, 763, -752,
+ 0, 1873, -5289, 13068, 24506, 0, -2427, 2389,
+ -1522, 598, 0, -213, 180, -79, 0, 0,
+ };
+
+ arm_resample_x64k_12k8(
+ 4, (const int16x2_t *)h, hp50, (int16x2_t *)x, y, n);
+}
+
+#ifndef TEST_ARM
+#define resample_16k_12k8 arm_resample_16k_12k8
+#endif
+
+#endif /* resample_16k_12k8 */
+
+/**
+ * Resample from 32 Khz to 12.8 KHz
+ */
+#ifndef resample_32k_12k8
+
+static void arm_resample_32k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t alignas(int32_t) h[2*2*48] = {
+
+ 0, -30, -31, 46, 107, 0, -199, -162,
+ 209, 430, 0, -681, -526, 658, 1343, 0,
+ -2264, -1943, 2999, 9871, 13116, 9871, 2999, -1943,
+ -2264, 0, 1343, 658, -526, -681, 0, 430,
+ 209, -162, -199, 0, 107, 46, -31, -30,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, -14, -39, 0, 90, 78, -106, -229,
+ 0, 382, 299, -376, -761, 0, 1194, 937,
+ -1214, -2644, 0, 6534, 12253, 12253, 6534, 0,
+ -2644, -1214, 937, 1194, 0, -761, -376, 299,
+ 382, 0, -229, -106, 78, 90, 0, -39,
+ -14, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, -30, -31, 46, 107, 0, -199,
+ -162, 209, 430, 0, -681, -526, 658, 1343,
+ 0, -2264, -1943, 2999, 9871, 13116, 9871, 2999,
+ -1943, -2264, 0, 1343, 658, -526, -681, 0,
+ 430, 209, -162, -199, 0, 107, 46, -31,
+ -30, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, -14, -39, 0, 90, 78, -106,
+ -229, 0, 382, 299, -376, -761, 0, 1194,
+ 937, -1214, -2644, 0, 6534, 12253, 12253, 6534,
+ 0, -2644, -1214, 937, 1194, 0, -761, -376,
+ 299, 382, 0, -229, -106, 78, 90, 0,
+ -39, -14, 0, 0, 0, 0, 0, 0,
+ };
+
+ arm_resample_x64k_12k8(
+ 2, (const int16x2_t *)h, hp50, (int16x2_t *)x, y, n);
+}
+
+#ifndef TEST_ARM
+#define resample_32k_12k8 arm_resample_32k_12k8
+#endif
+
+#endif /* resample_32k_12k8 */
+
+/**
+ * Resample from 24 Khz to 12.8 KHz
+ */
+#ifndef resample_24k_12k8
+
+static void arm_resample_24k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t alignas(int32_t) h[2*8*32] = {
+
+ 0, -50, 19, 143, -93, -290, 278, 485,
+ -658, -701, 1396, 901, -3019, -1042, 10276, 17488,
+ 10276, -1042, -3019, 901, 1396, -701, -658, 485,
+ 278, -290, -93, 143, 19, -50, 0, 0,
+
+ 0, -46, 0, 141, -45, -305, 185, 543,
+ -501, -854, 1153, 1249, -2619, -1908, 8712, 17358,
+ 11772, 0, -3319, 480, 1593, -504, -796, 399,
+ 367, -261, -142, 138, 40, -52, -5, 0,
+
+ 0, -41, -17, 133, 0, -304, 91, 574,
+ -334, -959, 878, 1516, -2143, -2590, 7118, 16971,
+ 13161, 1202, -3495, 0, 1731, -267, -908, 287,
+ 445, -215, -188, 125, 62, -52, -12, 0,
+
+ 0, -34, -30, 120, 41, -291, 0, 577,
+ -164, -1015, 585, 1697, -1618, -3084, 5534, 16337,
+ 14406, 2544, -3526, -523, 1800, 0, -985, 152,
+ 509, -156, -230, 104, 83, -48, -19, 0,
+
+ 0, -26, -41, 103, 76, -265, -83, 554,
+ 0, -1023, 288, 1791, -1070, -3393, 3998, 15474,
+ 15474, 3998, -3393, -1070, 1791, 288, -1023, 0,
+ 554, -83, -265, 76, 103, -41, -26, 0,
+
+ 0, -19, -48, 83, 104, -230, -156, 509,
+ 152, -985, 0, 1800, -523, -3526, 2544, 14406,
+ 16337, 5534, -3084, -1618, 1697, 585, -1015, -164,
+ 577, 0, -291, 41, 120, -30, -34, 0,
+
+ 0, -12, -52, 62, 125, -188, -215, 445,
+ 287, -908, -267, 1731, 0, -3495, 1202, 13161,
+ 16971, 7118, -2590, -2143, 1516, 878, -959, -334,
+ 574, 91, -304, 0, 133, -17, -41, 0,
+
+ 0, -5, -52, 40, 138, -142, -261, 367,
+ 399, -796, -504, 1593, 480, -3319, 0, 11772,
+ 17358, 8712, -1908, -2619, 1249, 1153, -854, -501,
+ 543, 185, -305, -45, 141, 0, -46, 0,
+
+ 0, 0, -50, 19, 143, -93, -290, 278,
+ 485, -658, -701, 1396, 901, -3019, -1042, 10276,
+ 17488, 10276, -1042, -3019, 901, 1396, -701, -658,
+ 485, 278, -290, -93, 143, 19, -50, 0,
+
+ 0, 0, -46, 0, 141, -45, -305, 185,
+ 543, -501, -854, 1153, 1249, -2619, -1908, 8712,
+ 17358, 11772, 0, -3319, 480, 1593, -504, -796,
+ 399, 367, -261, -142, 138, 40, -52, -5,
+
+ 0, 0, -41, -17, 133, 0, -304, 91,
+ 574, -334, -959, 878, 1516, -2143, -2590, 7118,
+ 16971, 13161, 1202, -3495, 0, 1731, -267, -908,
+ 287, 445, -215, -188, 125, 62, -52, -12,
+
+ 0, 0, -34, -30, 120, 41, -291, 0,
+ 577, -164, -1015, 585, 1697, -1618, -3084, 5534,
+ 16337, 14406, 2544, -3526, -523, 1800, 0, -985,
+ 152, 509, -156, -230, 104, 83, -48, -19,
+
+ 0, 0, -26, -41, 103, 76, -265, -83,
+ 554, 0, -1023, 288, 1791, -1070, -3393, 3998,
+ 15474, 15474, 3998, -3393, -1070, 1791, 288, -1023,
+ 0, 554, -83, -265, 76, 103, -41, -26,
+
+ 0, 0, -19, -48, 83, 104, -230, -156,
+ 509, 152, -985, 0, 1800, -523, -3526, 2544,
+ 14406, 16337, 5534, -3084, -1618, 1697, 585, -1015,
+ -164, 577, 0, -291, 41, 120, -30, -34,
+
+ 0, 0, -12, -52, 62, 125, -188, -215,
+ 445, 287, -908, -267, 1731, 0, -3495, 1202,
+ 13161, 16971, 7118, -2590, -2143, 1516, 878, -959,
+ -334, 574, 91, -304, 0, 133, -17, -41,
+
+ 0, 0, -5, -52, 40, 138, -142, -261,
+ 367, 399, -796, -504, 1593, 480, -3319, 0,
+ 11772, 17358, 8712, -1908, -2619, 1249, 1153, -854,
+ -501, 543, 185, -305, -45, 141, 0, -46,
+ };
+
+ arm_resample_x192k_12k8(
+ 8, (const int16x2_t *)h, hp50, (int16x2_t *)x, y, n);
+}
+
+#ifndef TEST_ARM
+#define resample_24k_12k8 arm_resample_24k_12k8
+#endif
+
+#endif /* resample_24k_12k8 */
+
+/**
+ * Resample from 48 Khz to 12.8 KHz
+ */
+#ifndef resample_48k_12k8
+
+static void arm_resample_48k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t alignas(int32_t) h[2*4*64] = {
+
+ 0, -13, -25, -20, 10, 51, 71, 38,
+ -47, -133, -145, -42, 139, 277, 242, 0,
+ -329, -511, -351, 144, 698, 895, 450, -535,
+ -1510, -1697, -521, 1999, 5138, 7737, 8744, 7737,
+ 5138, 1999, -521, -1697, -1510, -535, 450, 895,
+ 698, 144, -351, -511, -329, 0, 242, 277,
+ 139, -42, -145, -133, -47, 38, 71, 51,
+ 10, -20, -25, -13, 0, 0, 0, 0,
+
+ 0, -9, -23, -24, 0, 41, 71, 52,
+ -23, -115, -152, -78, 92, 254, 272, 76,
+ -251, -493, -427, 0, 576, 900, 624, -262,
+ -1309, -1763, -954, 1272, 4356, 7203, 8679, 8169,
+ 5886, 2767, 0, -1542, -1660, -809, 240, 848,
+ 796, 292, -252, -507, -398, -82, 199, 288,
+ 183, 0, -130, -145, -71, 20, 69, 60,
+ 20, -15, -26, -17, -3, 0, 0, 0,
+
+ 0, -6, -20, -26, -8, 31, 67, 62,
+ 0, -94, -152, -108, 45, 223, 287, 143,
+ -167, -454, -480, -134, 439, 866, 758, 0,
+ -1071, -1748, -1295, 601, 3559, 6580, 8485, 8485,
+ 6580, 3559, 601, -1295, -1748, -1071, 0, 758,
+ 866, 439, -134, -480, -454, -167, 143, 287,
+ 223, 45, -108, -152, -94, 0, 62, 67,
+ 31, -8, -26, -20, -6, 0, 0, 0,
+
+ 0, -3, -17, -26, -15, 20, 60, 69,
+ 20, -71, -145, -130, 0, 183, 288, 199,
+ -82, -398, -507, -252, 292, 796, 848, 240,
+ -809, -1660, -1542, 0, 2767, 5886, 8169, 8679,
+ 7203, 4356, 1272, -954, -1763, -1309, -262, 624,
+ 900, 576, 0, -427, -493, -251, 76, 272,
+ 254, 92, -78, -152, -115, -23, 52, 71,
+ 41, 0, -24, -23, -9, 0, 0, 0,
+
+ 0, 0, -13, -25, -20, 10, 51, 71,
+ 38, -47, -133, -145, -42, 139, 277, 242,
+ 0, -329, -511, -351, 144, 698, 895, 450,
+ -535, -1510, -1697, -521, 1999, 5138, 7737, 8744,
+ 7737, 5138, 1999, -521, -1697, -1510, -535, 450,
+ 895, 698, 144, -351, -511, -329, 0, 242,
+ 277, 139, -42, -145, -133, -47, 38, 71,
+ 51, 10, -20, -25, -13, 0, 0, 0,
+
+ 0, 0, -9, -23, -24, 0, 41, 71,
+ 52, -23, -115, -152, -78, 92, 254, 272,
+ 76, -251, -493, -427, 0, 576, 900, 624,
+ -262, -1309, -1763, -954, 1272, 4356, 7203, 8679,
+ 8169, 5886, 2767, 0, -1542, -1660, -809, 240,
+ 848, 796, 292, -252, -507, -398, -82, 199,
+ 288, 183, 0, -130, -145, -71, 20, 69,
+ 60, 20, -15, -26, -17, -3, 0, 0,
+
+ 0, 0, -6, -20, -26, -8, 31, 67,
+ 62, 0, -94, -152, -108, 45, 223, 287,
+ 143, -167, -454, -480, -134, 439, 866, 758,
+ 0, -1071, -1748, -1295, 601, 3559, 6580, 8485,
+ 8485, 6580, 3559, 601, -1295, -1748, -1071, 0,
+ 758, 866, 439, -134, -480, -454, -167, 143,
+ 287, 223, 45, -108, -152, -94, 0, 62,
+ 67, 31, -8, -26, -20, -6, 0, 0,
+
+ 0, 0, -3, -17, -26, -15, 20, 60,
+ 69, 20, -71, -145, -130, 0, 183, 288,
+ 199, -82, -398, -507, -252, 292, 796, 848,
+ 240, -809, -1660, -1542, 0, 2767, 5886, 8169,
+ 8679, 7203, 4356, 1272, -954, -1763, -1309, -262,
+ 624, 900, 576, 0, -427, -493, -251, 76,
+ 272, 254, 92, -78, -152, -115, -23, 52,
+ 71, 41, 0, -24, -23, -9, 0, 0,
+ };
+
+ arm_resample_x192k_12k8(
+ 4, (const int16x2_t *)h, hp50, (int16x2_t *)x, y, n);
+}
+
+#ifndef TEST_ARM
+#define resample_48k_12k8 arm_resample_48k_12k8
+#endif
+
+#endif /* resample_48k_12k8 */
+
+/**
+ * Return vector of correlations
+ */
+#ifndef correlate
+
+static void arm_correlate(
+ const int16_t *a, const int16_t *b, int n, float *y, int nc)
+{
+ /* --- Check alignment of `b` --- */
+
+ if ((uintptr_t)b & 3)
+ *(y++) = dot(a, b--, n), nc--;
+
+ /* --- Processing by pair --- */
+
+ for ( ; nc >= 2; nc -= 2) {
+ const int16x2_t *an = (const int16x2_t *)(a );
+ const int16x2_t *bn = (const int16x2_t *)(b--);
+
+ int16x2_t ax, b0, b1;
+ int64_t v0 = 0, v1 = 0;
+
+ b1 = (int16x2_t)*(b--) << 16;
+
+ for (int i = 0; i < (n >> 4); i++ )
+ for (int j = 0; j < 4; j++) {
+
+ ax = *(an++), b0 = *(bn++);
+ v0 = __smlald (ax, b0, v0);
+ v1 = __smlaldx(ax, __pkhbt(b0, b1), v1);
+
+ ax = *(an++), b1 = *(bn++);
+ v0 = __smlald (ax, b1, v0);
+ v1 = __smlaldx(ax, __pkhbt(b1, b0), v1);
+ }
+
+ *(y++) = (float)((int32_t)((v0 + (1 << 5)) >> 6));
+ *(y++) = (float)((int32_t)((v1 + (1 << 5)) >> 6));
+ }
+
+ /* --- Odd element count --- */
+
+ if (nc > 0)
+ *(y++) = dot(a, b, n);
+}
+
+#ifndef TEST_ARM
+#define correlate arm_correlate
+#endif
+
+#endif /* correlate */
+
+#endif /* __ARM_FEATURE_SIMD32 */
diff --git a/src/ltpf_neon.h b/src/ltpf_neon.h
new file mode 100644
index 0000000..eb1e7d8
--- /dev/null
+++ b/src/ltpf_neon.h
@@ -0,0 +1,281 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#if __ARM_NEON && __ARM_ARCH_ISA_A64 && \
+ !defined(TEST_ARM) || defined(TEST_NEON)
+
+#ifndef TEST_NEON
+#include <arm_neon.h>
+#endif /* TEST_NEON */
+
+
+/**
+ * Import
+ */
+
+static inline int32_t filter_hp50(struct lc3_ltpf_hp50_state *, int32_t);
+
+
+/**
+ * Resample from 16 Khz to 12.8 KHz
+ */
+#ifndef resample_16k_12k8
+
+LC3_HOT static void neon_resample_16k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t h[4][20] = {
+
+ { -61, 214, -398, 417, 0, -1052, 2686, -4529, 5997, 26233,
+ 5997, -4529, 2686, -1052, 0, 417, -398, 214, -61, 0 },
+
+ { -79, 180, -213, 0, 598, -1522, 2389, -2427, 0, 24506,
+ 13068, -5289, 1873, 0, -752, 763, -457, 156, 0, -28 },
+
+ { -61, 92, 0, -323, 861, -1361, 1317, 0, -3885, 19741,
+ 19741, -3885, 0, 1317, -1361, 861, -323, 0, 92, -61 },
+
+ { -28, 0, 156, -457, 763, -752, 0, 1873, -5289, 13068,
+ 24506, 0, -2427, 2389, -1522, 598, 0, -213, 180, -79 },
+
+ };
+
+ x -= 20 - 1;
+
+ for (int i = 0; i < 5*n; i += 5) {
+ const int16_t *hn = h[i & 3];
+ const int16_t *xn = x + (i >> 2);
+ int32x4_t un;
+
+ un = vmull_s16( vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+ un = vmlal_s16(un, vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+ un = vmlal_s16(un, vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+ un = vmlal_s16(un, vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+ un = vmlal_s16(un, vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+
+ int32_t yn = filter_hp50(hp50, vaddvq_s32(un));
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+
+#ifndef TEST_NEON
+#define resample_16k_12k8 neon_resample_16k_12k8
+#endif
+
+#endif /* resample_16k_12k8 */
+
+/**
+ * Resample from 32 Khz to 12.8 KHz
+ */
+#ifndef resample_32k_12k8
+
+LC3_HOT static void neon_resample_32k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ x -= 40 - 1;
+
+ static const int16_t h[2][40] = {
+
+ { -30, -31, 46, 107, 0, -199, -162, 209, 430, 0,
+ -681, -526, 658, 1343, 0, -2264, -1943, 2999, 9871, 13116,
+ 9871, 2999, -1943, -2264, 0, 1343, 658, -526, -681, 0,
+ 430, 209, -162, -199, 0, 107, 46, -31, -30, 0 },
+
+ { -14, -39, 0, 90, 78, -106, -229, 0, 382, 299,
+ -376, -761, 0, 1194, 937, -1214, -2644, 0, 6534, 12253,
+ 12253, 6534, 0, -2644, -1214, 937, 1194, 0, -761, -376,
+ 299, 382, 0, -229, -106, 78, 90, 0, -39, -14 },
+
+ };
+
+ for (int i = 0; i < 5*n; i += 5) {
+ const int16_t *hn = h[i & 1];
+ const int16_t *xn = x + (i >> 1);
+
+ int32x4_t un = vmull_s16(vld1_s16(xn), vld1_s16(hn));
+ xn += 4, hn += 4;
+
+ for (int i = 1; i < 10; i++)
+ un = vmlal_s16(un, vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+
+ int32_t yn = filter_hp50(hp50, vaddvq_s32(un));
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+
+#ifndef TEST_NEON
+#define resample_32k_12k8 neon_resample_32k_12k8
+#endif
+
+#endif /* resample_32k_12k8 */
+
+/**
+ * Resample from 48 Khz to 12.8 KHz
+ */
+#ifndef resample_48k_12k8
+
+LC3_HOT static void neon_resample_48k_12k8(
+ struct lc3_ltpf_hp50_state *hp50, const int16_t *x, int16_t *y, int n)
+{
+ static const int16_t alignas(16) h[4][64] = {
+
+ { -13, -25, -20, 10, 51, 71, 38, -47, -133, -145,
+ -42, 139, 277, 242, 0, -329, -511, -351, 144, 698,
+ 895, 450, -535, -1510, -1697, -521, 1999, 5138, 7737, 8744,
+ 7737, 5138, 1999, -521, -1697, -1510, -535, 450, 895, 698,
+ 144, -351, -511, -329, 0, 242, 277, 139, -42, -145,
+ -133, -47, 38, 71, 51, 10, -20, -25, -13, 0 },
+
+ { -9, -23, -24, 0, 41, 71, 52, -23, -115, -152,
+ -78, 92, 254, 272, 76, -251, -493, -427, 0, 576,
+ 900, 624, -262, -1309, -1763, -954, 1272, 4356, 7203, 8679,
+ 8169, 5886, 2767, 0, -1542, -1660, -809, 240, 848, 796,
+ 292, -252, -507, -398, -82, 199, 288, 183, 0, -130,
+ -145, -71, 20, 69, 60, 20, -15, -26, -17, -3 },
+
+ { -6, -20, -26, -8, 31, 67, 62, 0, -94, -152,
+ -108, 45, 223, 287, 143, -167, -454, -480, -134, 439,
+ 866, 758, 0, -1071, -1748, -1295, 601, 3559, 6580, 8485,
+ 8485, 6580, 3559, 601, -1295, -1748, -1071, 0, 758, 866,
+ 439, -134, -480, -454, -167, 143, 287, 223, 45, -108,
+ -152, -94, 0, 62, 67, 31, -8, -26, -20, -6 },
+
+ { -3, -17, -26, -15, 20, 60, 69, 20, -71, -145,
+ -130, 0, 183, 288, 199, -82, -398, -507, -252, 292,
+ 796, 848, 240, -809, -1660, -1542, 0, 2767, 5886, 8169,
+ 8679, 7203, 4356, 1272, -954, -1763, -1309, -262, 624, 900,
+ 576, 0, -427, -493, -251, 76, 272, 254, 92, -78,
+ -152, -115, -23, 52, 71, 41, 0, -24, -23, -9 },
+
+ };
+
+ x -= 60 - 1;
+
+ for (int i = 0; i < 15*n; i += 15) {
+ const int16_t *hn = h[i & 3];
+ const int16_t *xn = x + (i >> 2);
+
+ int32x4_t un = vmull_s16(vld1_s16(xn), vld1_s16(hn));
+ xn += 4, hn += 4;
+
+ for (int i = 1; i < 15; i++)
+ un = vmlal_s16(un, vld1_s16(xn), vld1_s16(hn)), xn += 4, hn += 4;
+
+ int32_t yn = filter_hp50(hp50, vaddvq_s32(un));
+ *(y++) = (yn + (1 << 15)) >> 16;
+ }
+}
+
+#ifndef TEST_NEON
+#define resample_48k_12k8 neon_resample_48k_12k8
+#endif
+
+#endif /* resample_48k_12k8 */
+
+/**
+ * Return dot product of 2 vectors
+ */
+#ifndef dot
+
+LC3_HOT static inline float neon_dot(const int16_t *a, const int16_t *b, int n)
+{
+ int64x2_t v = vmovq_n_s64(0);
+
+ for (int i = 0; i < (n >> 4); i++) {
+ int32x4_t u;
+
+ u = vmull_s16( vld1_s16(a), vld1_s16(b)), a += 4, b += 4;
+ u = vmlal_s16(u, vld1_s16(a), vld1_s16(b)), a += 4, b += 4;
+ v = vpadalq_s32(v, u);
+
+ u = vmull_s16( vld1_s16(a), vld1_s16(b)), a += 4, b += 4;
+ u = vmlal_s16(u, vld1_s16(a), vld1_s16(b)), a += 4, b += 4;
+ v = vpadalq_s32(v, u);
+ }
+
+ int32_t v32 = (vaddvq_s64(v) + (1 << 5)) >> 6;
+ return (float)v32;
+}
+
+#ifndef TEST_NEON
+#define dot neon_dot
+#endif
+
+#endif /* dot */
+
+/**
+ * Return vector of correlations
+ */
+#ifndef correlate
+
+LC3_HOT static void neon_correlate(
+ const int16_t *a, const int16_t *b, int n, float *y, int nc)
+{
+ for ( ; nc >= 4; nc -= 4, b -= 4) {
+ const int16_t *an = (const int16_t *)a;
+ const int16_t *bn = (const int16_t *)b;
+
+ int64x2_t v0 = vmovq_n_s64(0), v1 = v0, v2 = v0, v3 = v0;
+ int16x4_t ax, b0, b1;
+
+ b0 = vld1_s16(bn-4);
+
+ for (int i=0; i < (n >> 4); i++ )
+ for (int j = 0; j < 2; j++) {
+ int32x4_t u0, u1, u2, u3;
+
+ b1 = b0;
+ b0 = vld1_s16(bn), bn += 4;
+ ax = vld1_s16(an), an += 4;
+
+ u0 = vmull_s16(ax, b0);
+ u1 = vmull_s16(ax, vext_s16(b1, b0, 3));
+ u2 = vmull_s16(ax, vext_s16(b1, b0, 2));
+ u3 = vmull_s16(ax, vext_s16(b1, b0, 1));
+
+ b1 = b0;
+ b0 = vld1_s16(bn), bn += 4;
+ ax = vld1_s16(an), an += 4;
+
+ u0 = vmlal_s16(u0, ax, b0);
+ u1 = vmlal_s16(u1, ax, vext_s16(b1, b0, 3));
+ u2 = vmlal_s16(u2, ax, vext_s16(b1, b0, 2));
+ u3 = vmlal_s16(u3, ax, vext_s16(b1, b0, 1));
+
+ v0 = vpadalq_s32(v0, u0);
+ v1 = vpadalq_s32(v1, u1);
+ v2 = vpadalq_s32(v2, u2);
+ v3 = vpadalq_s32(v3, u3);
+ }
+
+ *(y++) = (float)((int32_t)((vaddvq_s64(v0) + (1 << 5)) >> 6));
+ *(y++) = (float)((int32_t)((vaddvq_s64(v1) + (1 << 5)) >> 6));
+ *(y++) = (float)((int32_t)((vaddvq_s64(v2) + (1 << 5)) >> 6));
+ *(y++) = (float)((int32_t)((vaddvq_s64(v3) + (1 << 5)) >> 6));
+ }
+
+ for ( ; nc > 0; nc--)
+ *(y++) = neon_dot(a, b--, n);
+}
+#endif /* correlate */
+
+#ifndef TEST_NEON
+#define correlate neon_correlate
+#endif
+
+#endif /* __ARM_NEON && __ARM_ARCH_ISA_A64 */
diff --git a/src/makefile.mk b/src/makefile.mk
new file mode 100644
index 0000000..968ec43
--- /dev/null
+++ b/src/makefile.mk
@@ -0,0 +1,35 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+liblc3_src += \
+ $(SRC_DIR)/attdet.c \
+ $(SRC_DIR)/bits.c \
+ $(SRC_DIR)/bwdet.c \
+ $(SRC_DIR)/energy.c \
+ $(SRC_DIR)/lc3.c \
+ $(SRC_DIR)/ltpf.c \
+ $(SRC_DIR)/mdct.c \
+ $(SRC_DIR)/plc.c \
+ $(SRC_DIR)/sns.c \
+ $(SRC_DIR)/spec.c \
+ $(SRC_DIR)/tables.c \
+ $(SRC_DIR)/tns.c
+
+liblc3_cflags += -ffast-math
+
+$(eval $(call add-lib,liblc3))
+
+default: liblc3
diff --git a/src/mdct.c b/src/mdct.c
new file mode 100644
index 0000000..f598221
--- /dev/null
+++ b/src/mdct.c
@@ -0,0 +1,469 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 "mdct.h"
+#include "tables.h"
+
+#include "mdct_neon.h"
+
+
+/* ----------------------------------------------------------------------------
+ * FFT processing
+ * -------------------------------------------------------------------------- */
+
+/**
+ * FFT 5 Points
+ * x, y Input and output coefficients, of size 5xn
+ * n Number of interleaved transform to perform (n % 2 = 0)
+ */
+#ifndef fft_5
+LC3_HOT static inline void fft_5(
+ 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 - d14.im * sin1
+ + s23.re * cos2 - d23.im * sin2;
+
+ y[1].im = x[0].im + s14.im * cos1 + d14.re * sin1
+ + s23.im * cos2 + d23.re * sin2;
+
+ y[2].re = x[0].re + s14.re * cos2 - d14.im * sin2
+ + s23.re * cos1 + d23.im * sin1;
+
+ y[2].im = x[0].im + s14.im * cos2 + d14.re * sin2
+ + s23.im * cos1 - d23.re * sin1;
+
+ y[3].re = x[0].re + s14.re * cos2 + d14.im * sin2
+ + s23.re * cos1 - d23.im * sin1;
+
+ y[3].im = x[0].im + s14.im * cos2 - d14.re * sin2
+ + s23.im * cos1 + d23.re * sin1;
+
+ y[4].re = x[0].re + s14.re * cos1 + d14.im * sin1
+ + s23.re * cos2 + d23.im * sin2;
+
+ y[4].im = x[0].im + s14.im * cos1 - d14.re * sin1
+ + s23.im * cos2 - d23.re * sin2;
+ }
+}
+#endif /* fft_5 */
+
+/**
+ * FFT Butterfly 3 Points
+ * x, y Input and output coefficients
+ * twiddles Twiddles factors, determine size of transform
+ * n Number of interleaved transforms
+ */
+#ifndef fft_bf3
+LC3_HOT static inline void fft_bf3(
+ 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 - x1->im * w0[j][0].im
+ + x2->re * w0[j][1].re - x2->im * w0[j][1].im;
+
+ y0[j].im = x0->im + x1->im * w0[j][0].re + x1->re * w0[j][0].im
+ + x2->im * w0[j][1].re + x2->re * w0[j][1].im;
+
+ y1[j].re = x0->re + x1->re * w1[j][0].re - x1->im * w1[j][0].im
+ + x2->re * w1[j][1].re - x2->im * w1[j][1].im;
+
+ y1[j].im = x0->im + x1->im * w1[j][0].re + x1->re * w1[j][0].im
+ + x2->im * w1[j][1].re + x2->re * w1[j][1].im;
+
+ y2[j].re = x0->re + x1->re * w2[j][0].re - x1->im * w2[j][0].im
+ + x2->re * w2[j][1].re - x2->im * w2[j][1].im;
+
+ y2[j].im = x0->im + x1->im * w2[j][0].re + x1->re * w2[j][0].im
+ + x2->im * w2[j][1].re + x2->re * w2[j][1].im;
+ }
+}
+#endif /* fft_bf3 */
+
+/**
+ * FFT Butterfly 2 Points
+ * twiddles Twiddles factors, determine size of transform
+ * x, y Input and output coefficients
+ * n Number of interleaved transforms
+ */
+#ifndef fft_bf2
+LC3_HOT static inline void fft_bf2(
+ 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 - x1->im * w[j].im;
+ y0[j].im = x0->im + x1->im * w[j].re + x1->re * w[j].im;
+
+ y1[j].re = x0->re - x1->re * w[j].re + x1->im * w[j].im;
+ y1[j].im = x0->im - x1->im * w[j].re - x1->re * w[j].im;
+ }
+ }
+}
+#endif /* fft_bf2 */
+
+/**
+ * Perform FFT
+ * 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(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. */
+
+ fft_5(x, y[is], n /= 5);
+
+ for (i3 = 0; n & (n-1); i3++, is ^= 1)
+ fft_bf3(lc3_fft_twiddles_bf3[i3], y[is], y[is ^ 1], n /= 3);
+
+ for (i2 = 0; n > 1; i2++, is ^= 1)
+ fft_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, y Input current and delayed samples
+ * y, d Output windowed samples, and delayed ones
+ */
+LC3_HOT static void mdct_window(enum lc3_dt dt, enum lc3_srate sr,
+ const float *x, float *d, 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 + ns-nd, *x1 = x0;
+ float *y0 = y + ns/2, *y1 = y0;
+ float *d0 = d, *d1 = d + nd;
+
+ while (x1 > x) {
+ *(--y0) = *d0 * *(w0++) - *(--x1) * *(--w1);
+ *(y1++) = (*(d0++) = *(x0++)) * *(w2++);
+
+ *(--y0) = *d0 * *(w0++) - *(--x1) * *(--w1);
+ *(y1++) = (*(d0++) = *(x0++)) * *(w2++);
+ }
+
+ for (x1 += ns; x0 < x1; ) {
+ *(--y0) = *d0 * *(w0++) - *(--d1) * *(--w1);
+ *(y1++) = (*(d0++) = *(x0++)) * *(w2++) + (*d1 = *(--x1)) * *(--w3);
+
+ *(--y0) = *d0 * *(w0++) - *(--d1) * *(--w1);
+ *(y1++) = (*(d0++) = *(x0++)) * *(w2++) + (*d1 = *(--x1)) * *(--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
+ */
+LC3_HOT 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
+ *
+ * `x` and y` can be the same buffer
+ */
+LC3_HOT static void mdct_post_fft(const struct lc3_mdct_rot_def *def,
+ const struct lc3_complex *x, float *y)
+{
+ 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;
+ float u1 = x1->re * w1->im - x1->im * w1->re;
+
+ float v0 = x0->re * w0->im - x0->im * w0->re;
+ float v1 = x1->im * w1->im + x1->re * w1->re;
+
+ *(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
+ * The real and imaginary parts of `y` are swapped,
+ * to operate on FFT instead of IFFT
+ */
+LC3_HOT 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 = - u0 * uw.re - u1 * uw.im;
+ (y0++)->im = - u1 * uw.re + u0 * uw.im;
+
+ (--y1)->re = - v1 * vw.re - v0 * vw.im;
+ ( y1)->im = - v0 * vw.re + v1 * vw.im;
+ }
+}
+
+/**
+ * Post-rotate FFT N/4 points coefficients, resulting IMDCT N points
+ * def Size and twiddles factors
+ * x, y Input and output coefficients
+ *
+ * `x` and y` can be the same buffer
+ * The real and imaginary parts of `x` are swapped,
+ * to operate on FFT instead of IFFT
+ */
+LC3_HOT static void imdct_post_fft(const struct lc3_mdct_rot_def *def,
+ const struct lc3_complex *x, float *y)
+{
+ 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.re * uw.im - uz.im * uw.re;
+ *(--y1) = uz.re * uw.re + uz.im * uw.im;
+
+ *(--y1) = vz.re * vw.im - vz.im * vw.re;
+ *(y0++) = vz.re * vw.re + vz.im * vw.im;
+ }
+}
+
+/**
+ * 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
+ */
+LC3_HOT 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);
+
+ *(--y0) = *(--x0) - *(x ) * *(w1++);
+ *(y1++) = *(x1++) + *(x++) * *(--w0);
+ }
+
+ while (y1 < y + nd) {
+ *(y1++) = *(x1++) + *(x++) * *(--w0);
+ *(y1++) = *(x1++) + *(x++) * *(--w0);
+ }
+
+ while (y1 < y + 2*n4) {
+ *(y1++) = *(x ) * *(--w0);
+ *(--y2) = *(x++) * *(w2++);
+
+ *(y1++) = *(x ) * *(--w0);
+ *(--y2) = *(x++) * *(w2++);
+ }
+
+ while (y2 > y3) {
+ *(y3++) = *(x ) * *(--w0);
+ *(--y2) = *(x++) * *(w2++);
+
+ *(y3++) = *(x ) * *(--w0);
+ *(--y2) = *(x++) * *(w2++);
+ }
+}
+
+/**
+ * Rescale samples
+ * x, n Input and count of samples, scaled as output
+ * scale Scale factor
+ */
+LC3_HOT static void rescale(float *x, int n, float f)
+{
+ for (int i = 0; i < (n >> 2); i++) {
+ *(x++) *= f; *(x++) *= f;
+ *(x++) *= f; *(x++) *= f;
+ }
+}
+
+/**
+ * Forward MDCT transformation
+ */
+void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
+ enum lc3_srate sr_dst, const float *x, float *d, float *y)
+{
+ const struct lc3_mdct_rot_def *rot = lc3_mdct_rot[dt][sr];
+ int ns_dst = LC3_NS(dt, sr_dst);
+ int ns = LC3_NS(dt, sr);
+
+ struct lc3_complex buffer[LC3_MAX_NS / 2];
+ struct lc3_complex *z = (struct lc3_complex *)y;
+ union { float *f; struct lc3_complex *z; } u = { .z = buffer };
+
+ mdct_window(dt, sr, x, d, u.f);
+
+ mdct_pre_fft(rot, u.f, u.z);
+ u.z = fft(u.z, ns/2, u.z, z);
+ mdct_post_fft(rot, u.z, y);
+
+ if (ns != ns_dst)
+ rescale(y, ns_dst, sqrtf((float)ns_dst / 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 ns_src = LC3_NS(dt, sr_src);
+ int ns = LC3_NS(dt, sr);
+
+ struct lc3_complex buffer[LC3_MAX_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(z, ns/2, z, u.z);
+ imdct_post_fft(rot, z, u.f);
+
+ if (ns != ns_src)
+ rescale(u.f, ns, sqrtf((float)ns / ns_src));
+
+ imdct_window(dt, sr, u.f, d, y);
+}
diff --git a/src/mdct.h b/src/mdct.h
new file mode 100644
index 0000000..03ae801
--- /dev/null
+++ b/src/mdct.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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, d Temporal samples and delayed buffer
+ * y, d Output `ns` coefficients and `nd` delayed samples
+ *
+ * `x` and `y` can be the same buffer
+ */
+void lc3_mdct_forward(enum lc3_dt dt, enum lc3_srate sr,
+ enum lc3_srate sr_dst, const float *x, float *d, 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 */
diff --git a/src/mdct_neon.h b/src/mdct_neon.h
new file mode 100644
index 0000000..a970d4a
--- /dev/null
+++ b/src/mdct_neon.h
@@ -0,0 +1,296 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#if __ARM_NEON && __ARM_ARCH_ISA_A64 && \
+ !defined(TEST_ARM) || defined(TEST_NEON)
+
+#ifndef TEST_NEON
+#include <arm_neon.h>
+#endif /* TEST_NEON */
+
+
+/**
+ * FFT 5 Points
+ * The number of interleaved transform `n` assumed to be even
+ */
+#ifndef fft_5
+
+LC3_HOT static inline void neon_fft_5(
+ const struct lc3_complex *x, struct lc3_complex *y, int n)
+{
+ static const union { float f[2]; uint64_t u64; }
+ __cos1 = { { 0.3090169944, 0.3090169944 } },
+ __cos2 = { { -0.8090169944, -0.8090169944 } },
+ __sin1 = { { 0.9510565163, -0.9510565163 } },
+ __sin2 = { { 0.5877852523, -0.5877852523 } };
+
+ float32x2_t sin1 = vcreate_f32(__sin1.u64);
+ float32x2_t sin2 = vcreate_f32(__sin2.u64);
+ float32x2_t cos1 = vcreate_f32(__cos1.u64);
+ float32x2_t cos2 = vcreate_f32(__cos2.u64);
+
+ float32x4_t sin1q = vcombine_f32(sin1, sin1);
+ float32x4_t sin2q = vcombine_f32(sin2, sin2);
+ float32x4_t cos1q = vcombine_f32(cos1, cos1);
+ float32x4_t cos2q = vcombine_f32(cos2, cos2);
+
+ for (int i = 0; i < n; i += 2, x += 2, y += 10) {
+
+ float32x4_t y0, y1, y2, y3, y4;
+
+ float32x4_t x0 = vld1q_f32( (float *)(x + 0*n) );
+ float32x4_t x1 = vld1q_f32( (float *)(x + 1*n) );
+ float32x4_t x2 = vld1q_f32( (float *)(x + 2*n) );
+ float32x4_t x3 = vld1q_f32( (float *)(x + 3*n) );
+ float32x4_t x4 = vld1q_f32( (float *)(x + 4*n) );
+
+ float32x4_t s14 = vaddq_f32(x1, x4);
+ float32x4_t s23 = vaddq_f32(x2, x3);
+
+ float32x4_t d14 = vrev64q_f32( vsubq_f32(x1, x4) );
+ float32x4_t d23 = vrev64q_f32( vsubq_f32(x2, x3) );
+
+ y0 = vaddq_f32( x0, vaddq_f32(s14, s23) );
+
+ y4 = vfmaq_f32( x0, s14, cos1q );
+ y4 = vfmaq_f32( y4, s23, cos2q );
+
+ y1 = vfmaq_f32( y4, d14, sin1q );
+ y1 = vfmaq_f32( y1, d23, sin2q );
+
+ y4 = vfmsq_f32( y4, d14, sin1q );
+ y4 = vfmsq_f32( y4, d23, sin2q );
+
+ y3 = vfmaq_f32( x0, s14, cos2q );
+ y3 = vfmaq_f32( y3, s23, cos1q );
+
+ y2 = vfmaq_f32( y3, d14, sin2q );
+ y2 = vfmsq_f32( y2, d23, sin1q );
+
+ y3 = vfmsq_f32( y3, d14, sin2q );
+ y3 = vfmaq_f32( y3, d23, sin1q );
+
+ vst1_f32( (float *)(y + 0), vget_low_f32(y0) );
+ vst1_f32( (float *)(y + 1), vget_low_f32(y1) );
+ vst1_f32( (float *)(y + 2), vget_low_f32(y2) );
+ vst1_f32( (float *)(y + 3), vget_low_f32(y3) );
+ vst1_f32( (float *)(y + 4), vget_low_f32(y4) );
+
+ vst1_f32( (float *)(y + 5), vget_high_f32(y0) );
+ vst1_f32( (float *)(y + 6), vget_high_f32(y1) );
+ vst1_f32( (float *)(y + 7), vget_high_f32(y2) );
+ vst1_f32( (float *)(y + 8), vget_high_f32(y3) );
+ vst1_f32( (float *)(y + 9), vget_high_f32(y4) );
+ }
+}
+
+#ifndef TEST_NEON
+#define fft_5 neon_fft_5
+#endif
+
+#endif /* fft_5 */
+
+/**
+ * FFT Butterfly 3 Points
+ */
+#ifndef fft_bf3
+
+LC3_HOT static inline void neon_fft_bf3(
+ 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_ptr)[2] = twiddles->t;
+ const struct lc3_complex (*w1_ptr)[2] = w0_ptr + n3;
+ const struct lc3_complex (*w2_ptr)[2] = w1_ptr + n3;
+
+ const struct lc3_complex *x0_ptr = x;
+ const struct lc3_complex *x1_ptr = x0_ptr + n*n3;
+ const struct lc3_complex *x2_ptr = x1_ptr + n*n3;
+
+ struct lc3_complex *y0_ptr = y;
+ struct lc3_complex *y1_ptr = y0_ptr + n3;
+ struct lc3_complex *y2_ptr = y1_ptr + n3;
+
+ for (int j, i = 0; i < n; i++,
+ y0_ptr += 3*n3, y1_ptr += 3*n3, y2_ptr += 3*n3) {
+
+ /* --- Process by pair --- */
+
+ for (j = 0; j < (n3 >> 1); j++,
+ x0_ptr += 2, x1_ptr += 2, x2_ptr += 2) {
+
+ float32x4_t x0 = vld1q_f32( (float *)x0_ptr );
+ float32x4_t x1 = vld1q_f32( (float *)x1_ptr );
+ float32x4_t x2 = vld1q_f32( (float *)x2_ptr );
+
+ float32x4_t x1r = vtrn1q_f32( vrev64q_f32(vnegq_f32(x1)), x1 );
+ float32x4_t x2r = vtrn1q_f32( vrev64q_f32(vnegq_f32(x2)), x2 );
+
+ float32x4x2_t wn;
+ float32x4_t yn;
+
+ wn = vld2q_f32( (float *)(w0_ptr + 2*j) );
+
+ yn = vfmaq_f32( x0, x1 , vtrn1q_f32(wn.val[0], wn.val[0]) );
+ yn = vfmaq_f32( yn, x1r, vtrn1q_f32(wn.val[1], wn.val[1]) );
+ yn = vfmaq_f32( yn, x2 , vtrn2q_f32(wn.val[0], wn.val[0]) );
+ yn = vfmaq_f32( yn, x2r, vtrn2q_f32(wn.val[1], wn.val[1]) );
+ vst1q_f32( (float *)(y0_ptr + 2*j), yn );
+
+ wn = vld2q_f32( (float *)(w1_ptr + 2*j) );
+
+ yn = vfmaq_f32( x0, x1 , vtrn1q_f32(wn.val[0], wn.val[0]) );
+ yn = vfmaq_f32( yn, x1r, vtrn1q_f32(wn.val[1], wn.val[1]) );
+ yn = vfmaq_f32( yn, x2 , vtrn2q_f32(wn.val[0], wn.val[0]) );
+ yn = vfmaq_f32( yn, x2r, vtrn2q_f32(wn.val[1], wn.val[1]) );
+ vst1q_f32( (float *)(y1_ptr + 2*j), yn );
+
+ wn = vld2q_f32( (float *)(w2_ptr + 2*j) );
+
+ yn = vfmaq_f32( x0, x1 , vtrn1q_f32(wn.val[0], wn.val[0]) );
+ yn = vfmaq_f32( yn, x1r, vtrn1q_f32(wn.val[1], wn.val[1]) );
+ yn = vfmaq_f32( yn, x2 , vtrn2q_f32(wn.val[0], wn.val[0]) );
+ yn = vfmaq_f32( yn, x2r, vtrn2q_f32(wn.val[1], wn.val[1]) );
+ vst1q_f32( (float *)(y2_ptr + 2*j), yn );
+
+ }
+
+ /* --- Last iteration --- */
+
+ if (n3 & 1) {
+
+ float32x2x2_t wn;
+ float32x2_t yn;
+
+ float32x2_t x0 = vld1_f32( (float *)(x0_ptr++) );
+ float32x2_t x1 = vld1_f32( (float *)(x1_ptr++) );
+ float32x2_t x2 = vld1_f32( (float *)(x2_ptr++) );
+
+ float32x2_t x1r = vtrn1_f32( vrev64_f32(vneg_f32(x1)), x1 );
+ float32x2_t x2r = vtrn1_f32( vrev64_f32(vneg_f32(x2)), x2 );
+
+ wn = vld2_f32( (float *)(w0_ptr + 2*j) );
+
+ yn = vfma_f32( x0, x1 , vtrn1_f32(wn.val[0], wn.val[0]) );
+ yn = vfma_f32( yn, x1r, vtrn1_f32(wn.val[1], wn.val[1]) );
+ yn = vfma_f32( yn, x2 , vtrn2_f32(wn.val[0], wn.val[0]) );
+ yn = vfma_f32( yn, x2r, vtrn2_f32(wn.val[1], wn.val[1]) );
+ vst1_f32( (float *)(y0_ptr + 2*j), yn );
+
+ wn = vld2_f32( (float *)(w1_ptr + 2*j) );
+
+ yn = vfma_f32( x0, x1 , vtrn1_f32(wn.val[0], wn.val[0]) );
+ yn = vfma_f32( yn, x1r, vtrn1_f32(wn.val[1], wn.val[1]) );
+ yn = vfma_f32( yn, x2 , vtrn2_f32(wn.val[0], wn.val[0]) );
+ yn = vfma_f32( yn, x2r, vtrn2_f32(wn.val[1], wn.val[1]) );
+ vst1_f32( (float *)(y1_ptr + 2*j), yn );
+
+ wn = vld2_f32( (float *)(w2_ptr + 2*j) );
+
+ yn = vfma_f32( x0, x1 , vtrn1_f32(wn.val[0], wn.val[0]) );
+ yn = vfma_f32( yn, x1r, vtrn1_f32(wn.val[1], wn.val[1]) );
+ yn = vfma_f32( yn, x2 , vtrn2_f32(wn.val[0], wn.val[0]) );
+ yn = vfma_f32( yn, x2r, vtrn2_f32(wn.val[1], wn.val[1]) );
+ vst1_f32( (float *)(y2_ptr + 2*j), yn );
+ }
+
+ }
+}
+
+#ifndef TEST_NEON
+#define fft_bf3 neon_fft_bf3
+#endif
+
+#endif /* fft_bf3 */
+
+/**
+ * FFT Butterfly 2 Points
+ */
+#ifndef fft_bf2
+
+LC3_HOT static inline void neon_fft_bf2(
+ 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_ptr = twiddles->t;
+
+ const struct lc3_complex *x0_ptr = x;
+ const struct lc3_complex *x1_ptr = x0_ptr + n*n2;
+
+ struct lc3_complex *y0_ptr = y;
+ struct lc3_complex *y1_ptr = y0_ptr + n2;
+
+ for (int j, i = 0; i < n; i++, y0_ptr += 2*n2, y1_ptr += 2*n2) {
+
+ /* --- Process by pair --- */
+
+ for (j = 0; j < (n2 >> 1); j++, x0_ptr += 2, x1_ptr += 2) {
+
+ float32x4_t x0 = vld1q_f32( (float *)x0_ptr );
+ float32x4_t x1 = vld1q_f32( (float *)x1_ptr );
+ float32x4_t y0, y1;
+
+ float32x4_t x1r = vtrn1q_f32( vrev64q_f32(vnegq_f32(x1)), x1 );
+
+ float32x4_t w = vld1q_f32( (float *)(w_ptr + 2*j) );
+ float32x4_t w_re = vtrn1q_f32(w, w);
+ float32x4_t w_im = vtrn2q_f32(w, w);
+
+ y0 = vfmaq_f32( x0, x1 , w_re );
+ y0 = vfmaq_f32( y0, x1r, w_im );
+ vst1q_f32( (float *)(y0_ptr + 2*j), y0 );
+
+ y1 = vfmsq_f32( x0, x1 , w_re );
+ y1 = vfmsq_f32( y1, x1r, w_im );
+ vst1q_f32( (float *)(y1_ptr + 2*j), y1 );
+ }
+
+ /* --- Last iteration --- */
+
+ if (n2 & 1) {
+
+ float32x2_t x0 = vld1_f32( (float *)(x0_ptr++) );
+ float32x2_t x1 = vld1_f32( (float *)(x1_ptr++) );
+ float32x2_t y0, y1;
+
+ float32x2_t x1r = vtrn1_f32( vrev64_f32(vneg_f32(x1)), x1 );
+
+ float32x2_t w = vld1_f32( (float *)(w_ptr + 2*j) );
+ float32x2_t w_re = vtrn1_f32(w, w);
+ float32x2_t w_im = vtrn2_f32(w, w);
+
+ y0 = vfma_f32( x0, x1 , w_re );
+ y0 = vfma_f32( y0, x1r, w_im );
+ vst1_f32( (float *)(y0_ptr + 2*j), y0 );
+
+ y1 = vfms_f32( x0, x1 , w_re );
+ y1 = vfms_f32( y1, x1r, w_im );
+ vst1_f32( (float *)(y1_ptr + 2*j), y1 );
+ }
+ }
+}
+
+#ifndef TEST_NEON
+#define fft_bf2 neon_fft_bf2
+#endif
+
+#endif /* fft_bf2 */
+
+#endif /* __ARM_NEON && __ARM_ARCH_ISA_A64 */
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..007573b
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,61 @@
+# Copyright © 2022 Intel Corporation
+#
+# 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.
+
+inc = include_directories('../include')
+
+lc3_sources = [
+ 'attdet.c',
+ 'bits.c',
+ 'bwdet.c',
+ 'energy.c',
+ 'lc3.c',
+ 'ltpf.c',
+ 'mdct.c',
+ 'plc.c',
+ 'sns.c',
+ 'spec.c',
+ 'tables.c',
+ 'tns.c'
+]
+
+lc3lib = library('lc3',
+ lc3_sources,
+ dependencies: m_dep,
+ include_directories: inc,
+ soversion: 1,
+ install: true)
+
+lc3_install_headers = [
+ '../include/lc3_private.h',
+ '../include/lc3.h',
+ '../include/lc3_cpp.h'
+]
+
+install_headers(lc3_install_headers)
+
+pkg_mod = import('pkgconfig')
+
+pkg_mod.generate(libraries : lc3lib,
+ name : 'liblc3',
+ filebase : 'lc3',
+ description : 'LC3 codec library')
+
+#Declare dependency
+liblc3_dep = declare_dependency(
+ link_with : lc3lib,
+ include_directories : inc)
+
+if meson.version().version_compare('>= 0.54.0')
+ meson.override_dependency('liblc3', liblc3_dep)
+endif
diff --git a/src/plc.c b/src/plc.c
new file mode 100644
index 0000000..03911b4
--- /dev/null
+++ b/src/plc.c
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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++;
+}
diff --git a/src/plc.h b/src/plc.h
new file mode 100644
index 0000000..6fda5b5
--- /dev/null
+++ b/src/plc.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 */
diff --git a/src/sns.c b/src/sns.c
new file mode 100644
index 0000000..56a893c
--- /dev/null
+++ b/src/sns.c
@@ -0,0 +1,880 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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.25f + e1 * 0.5f + (e2 = e[i+1]) * 0.25f) * ge[i];
+ e_sum += e[i++];
+
+ e[i] = (e1 * 0.25f + e2 * 0.5f + (e0 = e[i+1]) * 0.25f) * ge[i];
+ e_sum += e[i++];
+
+ e[i] = (e2 * 0.25f + e0 * 0.5f + (e1 = e[i+1]) * 0.25f) * ge[i];
+ e_sum += e[i++];
+ }
+
+ e[LC3_NUM_BANDS-1] = (e0 * 0.25f + e1 * 0.75f) * ge[LC3_NUM_BANDS-1];
+ e_sum += e[LC3_NUM_BANDS-1];
+
+ float noise_floor = fmaxf(e_sum * (1e-4f / 64), 0x1p-32f);
+
+ for (int i = 0; i < LC3_NUM_BANDS; i++)
+ e[i] = fast_log2f(fmaxf(e[i], noise_floor)) * 0.5f;
+
+ /* --- Grouping & scaling --- */
+
+ float scf_sum;
+
+ scf[0] = (e[0] + e[4]) * 1.f/12 +
+ (e[0] + e[3]) * 2.f/12 +
+ (e[1] + e[2]) * 3.f/12 ;
+ scf_sum = scf[0];
+
+ for (int i = 1; i < 15; i++) {
+ scf[i] = (e[4*i-1] + e[4*i+4]) * 1.f/12 +
+ (e[4*i ] + e[4*i+3]) * 2.f/12 +
+ (e[4*i+1] + e[4*i+2]) * 3.f/12 ;
+ scf_sum += scf[i];
+ }
+
+ scf[15] = (e[59] + e[63]) * 1.f/12 +
+ (e[60] + e[63]) * 2.f/12 +
+ (e[61] + e[62]) * 3.f/12 ;
+ scf_sum += scf[15];
+
+ for (int i = 0; i < 16; i++)
+ scf[i] = 0.85f * (scf[i] - scf_sum * 1.f/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.f/3;
+ scf[1] = (sn += s4) * 1.f/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.f/5;
+ scf_sum += scf[i];
+ }
+
+ scf[14] = (sn ) * 1.f/4;
+ scf[15] = (sn -= s1) * 1.f/3;
+ scf_sum += scf[14] + scf[15];
+
+ for (int i = 0; i < 16; i++)
+ scf[i] = (dt == LC3_DT_7M5 ? 0.3f : 0.5f) *
+ (scf[i] - scf_sum * 1.f/16);
+}
+
+/**
+ * Codebooks
+ * scf Input 16 scale factors
+ * lf/hfcb_idx Output the low and high frequency codebooks index
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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-31f);
+ 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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.125f * (s1 - s0);
+ scf[4*i+3] = s0 + 0.375f * (s1 - s0);
+ scf[4*i+4] = s0 + 0.625f * (s1 - s0);
+ scf[4*i+5] = s0 + 0.875f * (s1 - s0);
+ }
+ scf[62] = s1 + 0.125f * (s1 - s0);
+ scf[63] = s1 + 0.375f * (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.5f * (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 = fast_exp2f(-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;
+}
diff --git a/src/sns.h b/src/sns.h
new file mode 100644
index 0000000..432223c
--- /dev/null
+++ b/src/sns.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 */
diff --git a/src/spec.c b/src/spec.c
new file mode 100644
index 0000000..f857f47
--- /dev/null
+++ b/src/spec.c
@@ -0,0 +1,907 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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
+ * g_min Return lower bound of quantized gain value
+ * return The quantized gain value
+ */
+LC3_HOT 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 *g_min)
+{
+ int ne = LC3_NE(dt, sr) >> 2;
+ int e[LC3_MAX_NE];
+
+ /* --- Energy (dB) by 4 MDCT blocks --- */
+
+ float x2_max = 0;
+
+ for (int i = 0; i < ne; i++, x += 4) {
+ float x0 = x[0] * x[0];
+ float x1 = x[1] * x[1];
+ float x2 = x[2] * x[2];
+ float x3 = x[3] * x[3];
+
+ x2_max = fmaxf(x2_max, x0);
+ x2_max = fmaxf(x2_max, x1);
+ x2_max = fmaxf(x2_max, x2);
+ x2_max = fmaxf(x2_max, x3);
+
+ e[i] = fast_db_q16(fmaxf(x0 + x1 + x2 + x3, 1e-10f));
+ }
+
+ /* --- Determine gain index --- */
+
+ int nbits = nbits_budget + nbits_off + 0.5f;
+ int g_int = 255 - g_off;
+
+ const int k_20_28 = 20.f/28 * 0x1p16f + 0.5f;
+ const int k_2u7 = 2.7f * 0x1p16f + 0.5f;
+ const int k_1u4 = 1.4f * 0x1p16f + 0.5f;
+
+ for (int i = 128, j, j0 = ne-1, j1 ; i > 0; i >>= 1) {
+ int gn = (g_int - i) * k_20_28;
+ int v = 0;
+
+ for (j = j0; j >= 0 && e[j] < gn; j--);
+
+ for (j1 = j; j >= 0; j--) {
+ int e_diff = e[j] - gn;
+
+ v += e_diff < 0 ? k_2u7 :
+ e_diff < 43 << 16 ? e_diff + ( 7 << 16)
+ : 2*e_diff - (36 << 16);
+ }
+
+ if (v > nbits * k_1u4)
+ j0 = j1;
+ else
+ g_int = g_int - i;
+ }
+
+ /* --- Limit gain index --- */
+
+ *g_min = x2_max == 0 ? -g_off :
+ ceilf(28 * log10f(sqrtf(x2_max) / (32768 - 0.375f)));
+
+ *reset_off = g_int < *g_min || x2_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
+ * g_idx_min Minimum gain index value
+ * return Gain adjust value (-1 to 2)
+ */
+LC3_HOT static int adjust_gain(enum lc3_srate sr, int g_idx,
+ int nbits, int nbits_budget, int g_idx_min)
+{
+ /* --- 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 > g_idx_min);
+
+ 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
+ *
+ * The spectral coefficients `xq` are stored as :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+LC3_HOT static void quantize(enum lc3_dt dt, enum lc3_srate sr,
+ int g_int, float *x, uint16_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) {
+ uint16_t x0, x1;
+
+ x[i+0] *= g_inv;
+ x[i+1] *= g_inv;
+
+ x0 = fminf(fabsf(x[i+0]) + 6.f/16, INT16_MAX);
+ x1 = fminf(fabsf(x[i+1]) + 6.f/16, INT16_MAX);
+
+ xq[i+0] = (x0 << 1) + ((x0 > 0) & (x[i+0] < 0));
+ xq[i+1] = (x1 << 1) + ((x1 > 0) & (x[i+1] < 0));
+
+ *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
+ */
+LC3_HOT 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
+ *
+ * The spectral coefficients `x` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+LC3_HOT static int compute_nbits(
+ enum lc3_dt dt, enum lc3_srate sr, int nbytes,
+ const uint16_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];
+ uint16_t a = x[i] >> 1, b = x[i+1] >> 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
+ *
+ * The spectral coefficients `x` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+LC3_HOT static void put_quantized(lc3_bits_t *bits,
+ enum lc3_dt dt, enum lc3_srate sr, int nbytes,
+ const uint16_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];
+ uint16_t a = x[i] >> 1, b = x[i+1] >> 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, x[i+0] & 1);
+ if (b) lc3_put_bit(bits, x[i+1] & 1);
+
+ /* --- 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
+ */
+LC3_HOT 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
+ * x, n Spectral quantized, and count of significants
+ * xf Scaled spectral coefficients
+ *
+ * The spectral coefficients `x` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+LC3_HOT static void put_residual(
+ lc3_bits_t *bits, int nbits, const uint16_t *x, int n, const float *xf)
+{
+ for (int i = 0; i < n && nbits > 0; i++) {
+
+ if (x[i] == 0)
+ continue;
+
+ float xq = x[i] & 1 ? -(x[i] >> 1) : (x[i] >> 1);
+
+ lc3_put_bit(bits, xf[i] >= xq);
+ nbits--;
+ }
+}
+
+/**
+ * Get residual bits of quantization
+ * bits Bitstream context
+ * nbits Maximum number of bits to output
+ * x, nq Spectral quantized, and count of significants
+ */
+LC3_HOT 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
+ *
+ * The spectral coefficients `x` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+LC3_HOT static void put_lsb(
+ lc3_bits_t *bits, int nbits, const uint16_t *x, int n)
+{
+ for (int i = 0; i < n && nbits > 0; i += 2) {
+ uint16_t a = x[i] >> 1, b = x[i+1] >> 1;
+ int a_neg = x[i] & 1, b_neg = x[i+1] & 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
+ */
+LC3_HOT 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)
+ *
+ * The spectral coefficients `x` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+LC3_HOT static int estimate_noise(enum lc3_dt dt, enum lc3_bandwidth bw,
+ const uint16_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 += fabsf(x[i - w]), n++;
+ }
+
+ for ( ; i < bw_stop + w; i++)
+ if (++z > 2*w)
+ sum += fabsf(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
+ */
+LC3_HOT 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,
+ uint16_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.8f * spec->nbits_off + 0.2f * nbits_off;
+
+ int g_off = resolve_gain_offset(sr, nbytes);
+
+ int g_min, g_int = estimate_gain(dt, sr,
+ x, nbits_budget, nbits_off, g_off, &reset_off, &g_min);
+
+ /* --- 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_off + g_int,
+ nbits, nbits_budget, g_off + g_min);
+
+ 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 uint16_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;
+}
diff --git a/src/spec.h b/src/spec.h
new file mode 100644
index 0000000..091d25f
--- /dev/null
+++ b/src/spec.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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
+ *
+ * The spectral coefficients `xq` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+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, uint16_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
+ *
+ * The spectral coefficients `xq` storage is :
+ * b0 0:positive or zero 1:negative
+ * b15..b1 Absolute value
+ */
+void lc3_spec_encode(lc3_bits_t *bits,
+ enum lc3_dt dt, enum lc3_srate sr, enum lc3_bandwidth bw, int nbytes,
+ const uint16_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 */
diff --git a/src/tables.c b/src/tables.c
new file mode 100644
index 0000000..c498b5e
--- /dev/null
+++ b/src/tables.c
@@ -0,0 +1,3457 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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"
+
+
+/**
+ * Twiddles FFT 3 points
+ *
+ * T[0..N-1] =
+ * { cos(-2Pi * i/N) + j sin(-2Pi * i/N),
+ * cos(-2Pi * 2i/N) + j sin(-2Pi * 2i/N) } , N=15, 45
+ */
+
+static const struct lc3_fft_bf3_twiddles fft_twiddles_15 = {
+ .n3 = 15/3, .t = (const struct lc3_complex [][2]){
+ { { 1.0000000e+0, -0.0000000e+0 }, { 1.0000000e+0, -0.0000000e+0 } },
+ { { 9.1354546e-1, -4.0673664e-1 }, { 6.6913061e-1, -7.4314483e-1 } },
+ { { 6.6913061e-1, -7.4314483e-1 }, { -1.0452846e-1, -9.9452190e-1 } },
+ { { 3.0901699e-1, -9.5105652e-1 }, { -8.0901699e-1, -5.8778525e-1 } },
+ { { -1.0452846e-1, -9.9452190e-1 }, { -9.7814760e-1, 2.0791169e-1 } },
+ { { -5.0000000e-1, -8.6602540e-1 }, { -5.0000000e-1, 8.6602540e-1 } },
+ { { -8.0901699e-1, -5.8778525e-1 }, { 3.0901699e-1, 9.5105652e-1 } },
+ { { -9.7814760e-1, -2.0791169e-1 }, { 9.1354546e-1, 4.0673664e-1 } },
+ { { -9.7814760e-1, 2.0791169e-1 }, { 9.1354546e-1, -4.0673664e-1 } },
+ { { -8.0901699e-1, 5.8778525e-1 }, { 3.0901699e-1, -9.5105652e-1 } },
+ { { -5.0000000e-1, 8.6602540e-1 }, { -5.0000000e-1, -8.6602540e-1 } },
+ { { -1.0452846e-1, 9.9452190e-1 }, { -9.7814760e-1, -2.0791169e-1 } },
+ { { 3.0901699e-1, 9.5105652e-1 }, { -8.0901699e-1, 5.8778525e-1 } },
+ { { 6.6913061e-1, 7.4314483e-1 }, { -1.0452846e-1, 9.9452190e-1 } },
+ { { 9.1354546e-1, 4.0673664e-1 }, { 6.6913061e-1, 7.4314483e-1 } },
+ }
+};
+
+static const struct lc3_fft_bf3_twiddles fft_twiddles_45 = {
+ .n3 = 45/3, .t = (const struct lc3_complex [][2]){
+ { { 1.0000000e+0, -0.0000000e+0 }, { 1.0000000e+0, -0.0000000e+0 } },
+ { { 9.9026807e-1, -1.3917310e-1 }, { 9.6126170e-1, -2.7563736e-1 } },
+ { { 9.6126170e-1, -2.7563736e-1 }, { 8.4804810e-1, -5.2991926e-1 } },
+ { { 9.1354546e-1, -4.0673664e-1 }, { 6.6913061e-1, -7.4314483e-1 } },
+ { { 8.4804810e-1, -5.2991926e-1 }, { 4.3837115e-1, -8.9879405e-1 } },
+ { { 7.6604444e-1, -6.4278761e-1 }, { 1.7364818e-1, -9.8480775e-1 } },
+ { { 6.6913061e-1, -7.4314483e-1 }, { -1.0452846e-1, -9.9452190e-1 } },
+ { { 5.5919290e-1, -8.2903757e-1 }, { -3.7460659e-1, -9.2718385e-1 } },
+ { { 4.3837115e-1, -8.9879405e-1 }, { -6.1566148e-1, -7.8801075e-1 } },
+ { { 3.0901699e-1, -9.5105652e-1 }, { -8.0901699e-1, -5.8778525e-1 } },
+ { { 1.7364818e-1, -9.8480775e-1 }, { -9.3969262e-1, -3.4202014e-1 } },
+ { { 3.4899497e-2, -9.9939083e-1 }, { -9.9756405e-1, -6.9756474e-2 } },
+ { { -1.0452846e-1, -9.9452190e-1 }, { -9.7814760e-1, 2.0791169e-1 } },
+ { { -2.4192190e-1, -9.7029573e-1 }, { -8.8294759e-1, 4.6947156e-1 } },
+ { { -3.7460659e-1, -9.2718385e-1 }, { -7.1933980e-1, 6.9465837e-1 } },
+ { { -5.0000000e-1, -8.6602540e-1 }, { -5.0000000e-1, 8.6602540e-1 } },
+ { { -6.1566148e-1, -7.8801075e-1 }, { -2.4192190e-1, 9.7029573e-1 } },
+ { { -7.1933980e-1, -6.9465837e-1 }, { 3.4899497e-2, 9.9939083e-1 } },
+ { { -8.0901699e-1, -5.8778525e-1 }, { 3.0901699e-1, 9.5105652e-1 } },
+ { { -8.8294759e-1, -4.6947156e-1 }, { 5.5919290e-1, 8.2903757e-1 } },
+ { { -9.3969262e-1, -3.4202014e-1 }, { 7.6604444e-1, 6.4278761e-1 } },
+ { { -9.7814760e-1, -2.0791169e-1 }, { 9.1354546e-1, 4.0673664e-1 } },
+ { { -9.9756405e-1, -6.9756474e-2 }, { 9.9026807e-1, 1.3917310e-1 } },
+ { { -9.9756405e-1, 6.9756474e-2 }, { 9.9026807e-1, -1.3917310e-1 } },
+ { { -9.7814760e-1, 2.0791169e-1 }, { 9.1354546e-1, -4.0673664e-1 } },
+ { { -9.3969262e-1, 3.4202014e-1 }, { 7.6604444e-1, -6.4278761e-1 } },
+ { { -8.8294759e-1, 4.6947156e-1 }, { 5.5919290e-1, -8.2903757e-1 } },
+ { { -8.0901699e-1, 5.8778525e-1 }, { 3.0901699e-1, -9.5105652e-1 } },
+ { { -7.1933980e-1, 6.9465837e-1 }, { 3.4899497e-2, -9.9939083e-1 } },
+ { { -6.1566148e-1, 7.8801075e-1 }, { -2.4192190e-1, -9.7029573e-1 } },
+ { { -5.0000000e-1, 8.6602540e-1 }, { -5.0000000e-1, -8.6602540e-1 } },
+ { { -3.7460659e-1, 9.2718385e-1 }, { -7.1933980e-1, -6.9465837e-1 } },
+ { { -2.4192190e-1, 9.7029573e-1 }, { -8.8294759e-1, -4.6947156e-1 } },
+ { { -1.0452846e-1, 9.9452190e-1 }, { -9.7814760e-1, -2.0791169e-1 } },
+ { { 3.4899497e-2, 9.9939083e-1 }, { -9.9756405e-1, 6.9756474e-2 } },
+ { { 1.7364818e-1, 9.8480775e-1 }, { -9.3969262e-1, 3.4202014e-1 } },
+ { { 3.0901699e-1, 9.5105652e-1 }, { -8.0901699e-1, 5.8778525e-1 } },
+ { { 4.3837115e-1, 8.9879405e-1 }, { -6.1566148e-1, 7.8801075e-1 } },
+ { { 5.5919290e-1, 8.2903757e-1 }, { -3.7460659e-1, 9.2718385e-1 } },
+ { { 6.6913061e-1, 7.4314483e-1 }, { -1.0452846e-1, 9.9452190e-1 } },
+ { { 7.6604444e-1, 6.4278761e-1 }, { 1.7364818e-1, 9.8480775e-1 } },
+ { { 8.4804810e-1, 5.2991926e-1 }, { 4.3837115e-1, 8.9879405e-1 } },
+ { { 9.1354546e-1, 4.0673664e-1 }, { 6.6913061e-1, 7.4314483e-1 } },
+ { { 9.6126170e-1, 2.7563736e-1 }, { 8.4804810e-1, 5.2991926e-1 } },
+ { { 9.9026807e-1, 1.3917310e-1 }, { 9.6126170e-1, 2.7563736e-1 } },
+ }
+};
+
+const struct lc3_fft_bf3_twiddles *lc3_fft_twiddles_bf3[] =
+ { &fft_twiddles_15, &fft_twiddles_45 };
+
+
+/**
+ * Twiddles FFT 2 points
+ *
+ * T[0..N/2-1] =
+ * cos(-2Pi * i/N) + j sin(-2Pi * i/N) , N=10, 20, ...
+ */
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_10 = {
+ .n2 = 10/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 8.0901699e-01, -5.8778525e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { -3.0901699e-01, -9.5105652e-01 },
+ { -8.0901699e-01, -5.8778525e-01 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_20 = {
+ .n2 = 20/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.5105652e-01, -3.0901699e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 5.8778525e-01, -8.0901699e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 6.1232340e-17, -1.0000000e+00 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -5.8778525e-01, -8.0901699e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -9.5105652e-01, -3.0901699e-01 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_30 = {
+ .n2 = 30/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.7814760e-01, -2.0791169e-01 },
+ { 9.1354546e-01, -4.0673664e-01 }, { 8.0901699e-01, -5.8778525e-01 },
+ { 6.6913061e-01, -7.4314483e-01 }, { 5.0000000e-01, -8.6602540e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 1.0452846e-01, -9.9452190e-01 },
+ { -1.0452846e-01, -9.9452190e-01 }, { -3.0901699e-01, -9.5105652e-01 },
+ { -5.0000000e-01, -8.6602540e-01 }, { -6.6913061e-01, -7.4314483e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -9.1354546e-01, -4.0673664e-01 },
+ { -9.7814760e-01, -2.0791169e-01 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_40 = {
+ .n2 = 40/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.8768834e-01, -1.5643447e-01 },
+ { 9.5105652e-01, -3.0901699e-01 }, { 8.9100652e-01, -4.5399050e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.0710678e-01, -7.0710678e-01 },
+ { 5.8778525e-01, -8.0901699e-01 }, { 4.5399050e-01, -8.9100652e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 1.5643447e-01, -9.8768834e-01 },
+ { 6.1232340e-17, -1.0000000e+00 }, { -1.5643447e-01, -9.8768834e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -4.5399050e-01, -8.9100652e-01 },
+ { -5.8778525e-01, -8.0901699e-01 }, { -7.0710678e-01, -7.0710678e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.9100652e-01, -4.5399050e-01 },
+ { -9.5105652e-01, -3.0901699e-01 }, { -9.8768834e-01, -1.5643447e-01 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_60 = {
+ .n2 = 60/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9452190e-01, -1.0452846e-01 },
+ { 9.7814760e-01, -2.0791169e-01 }, { 9.5105652e-01, -3.0901699e-01 },
+ { 9.1354546e-01, -4.0673664e-01 }, { 8.6602540e-01, -5.0000000e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.4314483e-01, -6.6913061e-01 },
+ { 6.6913061e-01, -7.4314483e-01 }, { 5.8778525e-01, -8.0901699e-01 },
+ { 5.0000000e-01, -8.6602540e-01 }, { 4.0673664e-01, -9.1354546e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.0791169e-01, -9.7814760e-01 },
+ { 1.0452846e-01, -9.9452190e-01 }, { 2.8327694e-16, -1.0000000e+00 },
+ { -1.0452846e-01, -9.9452190e-01 }, { -2.0791169e-01, -9.7814760e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -4.0673664e-01, -9.1354546e-01 },
+ { -5.0000000e-01, -8.6602540e-01 }, { -5.8778525e-01, -8.0901699e-01 },
+ { -6.6913061e-01, -7.4314483e-01 }, { -7.4314483e-01, -6.6913061e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.6602540e-01, -5.0000000e-01 },
+ { -9.1354546e-01, -4.0673664e-01 }, { -9.5105652e-01, -3.0901699e-01 },
+ { -9.7814760e-01, -2.0791169e-01 }, { -9.9452190e-01, -1.0452846e-01 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_80 = {
+ .n2 = 80/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9691733e-01, -7.8459096e-02 },
+ { 9.8768834e-01, -1.5643447e-01 }, { 9.7236992e-01, -2.3344536e-01 },
+ { 9.5105652e-01, -3.0901699e-01 }, { 9.2387953e-01, -3.8268343e-01 },
+ { 8.9100652e-01, -4.5399050e-01 }, { 8.5264016e-01, -5.2249856e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.6040597e-01, -6.4944805e-01 },
+ { 7.0710678e-01, -7.0710678e-01 }, { 6.4944805e-01, -7.6040597e-01 },
+ { 5.8778525e-01, -8.0901699e-01 }, { 5.2249856e-01, -8.5264016e-01 },
+ { 4.5399050e-01, -8.9100652e-01 }, { 3.8268343e-01, -9.2387953e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.3344536e-01, -9.7236992e-01 },
+ { 1.5643447e-01, -9.8768834e-01 }, { 7.8459096e-02, -9.9691733e-01 },
+ { 6.1232340e-17, -1.0000000e+00 }, { -7.8459096e-02, -9.9691733e-01 },
+ { -1.5643447e-01, -9.8768834e-01 }, { -2.3344536e-01, -9.7236992e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -3.8268343e-01, -9.2387953e-01 },
+ { -4.5399050e-01, -8.9100652e-01 }, { -5.2249856e-01, -8.5264016e-01 },
+ { -5.8778525e-01, -8.0901699e-01 }, { -6.4944805e-01, -7.6040597e-01 },
+ { -7.0710678e-01, -7.0710678e-01 }, { -7.6040597e-01, -6.4944805e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.5264016e-01, -5.2249856e-01 },
+ { -8.9100652e-01, -4.5399050e-01 }, { -9.2387953e-01, -3.8268343e-01 },
+ { -9.5105652e-01, -3.0901699e-01 }, { -9.7236992e-01, -2.3344536e-01 },
+ { -9.8768834e-01, -1.5643447e-01 }, { -9.9691733e-01, -7.8459096e-02 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_90 = {
+ .n2 = 90/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9756405e-01, -6.9756474e-02 },
+ { 9.9026807e-01, -1.3917310e-01 }, { 9.7814760e-01, -2.0791169e-01 },
+ { 9.6126170e-01, -2.7563736e-01 }, { 9.3969262e-01, -3.4202014e-01 },
+ { 9.1354546e-01, -4.0673664e-01 }, { 8.8294759e-01, -4.6947156e-01 },
+ { 8.4804810e-01, -5.2991926e-01 }, { 8.0901699e-01, -5.8778525e-01 },
+ { 7.6604444e-01, -6.4278761e-01 }, { 7.1933980e-01, -6.9465837e-01 },
+ { 6.6913061e-01, -7.4314483e-01 }, { 6.1566148e-01, -7.8801075e-01 },
+ { 5.5919290e-01, -8.2903757e-01 }, { 5.0000000e-01, -8.6602540e-01 },
+ { 4.3837115e-01, -8.9879405e-01 }, { 3.7460659e-01, -9.2718385e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.4192190e-01, -9.7029573e-01 },
+ { 1.7364818e-01, -9.8480775e-01 }, { 1.0452846e-01, -9.9452190e-01 },
+ { 3.4899497e-02, -9.9939083e-01 }, { -3.4899497e-02, -9.9939083e-01 },
+ { -1.0452846e-01, -9.9452190e-01 }, { -1.7364818e-01, -9.8480775e-01 },
+ { -2.4192190e-01, -9.7029573e-01 }, { -3.0901699e-01, -9.5105652e-01 },
+ { -3.7460659e-01, -9.2718385e-01 }, { -4.3837115e-01, -8.9879405e-01 },
+ { -5.0000000e-01, -8.6602540e-01 }, { -5.5919290e-01, -8.2903757e-01 },
+ { -6.1566148e-01, -7.8801075e-01 }, { -6.6913061e-01, -7.4314483e-01 },
+ { -7.1933980e-01, -6.9465837e-01 }, { -7.6604444e-01, -6.4278761e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.4804810e-01, -5.2991926e-01 },
+ { -8.8294759e-01, -4.6947156e-01 }, { -9.1354546e-01, -4.0673664e-01 },
+ { -9.3969262e-01, -3.4202014e-01 }, { -9.6126170e-01, -2.7563736e-01 },
+ { -9.7814760e-01, -2.0791169e-01 }, { -9.9026807e-01, -1.3917310e-01 },
+ { -9.9756405e-01, -6.9756474e-02 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_120 = {
+ .n2 = 120/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9862953e-01, -5.2335956e-02 },
+ { 9.9452190e-01, -1.0452846e-01 }, { 9.8768834e-01, -1.5643447e-01 },
+ { 9.7814760e-01, -2.0791169e-01 }, { 9.6592583e-01, -2.5881905e-01 },
+ { 9.5105652e-01, -3.0901699e-01 }, { 9.3358043e-01, -3.5836795e-01 },
+ { 9.1354546e-01, -4.0673664e-01 }, { 8.9100652e-01, -4.5399050e-01 },
+ { 8.6602540e-01, -5.0000000e-01 }, { 8.3867057e-01, -5.4463904e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.7714596e-01, -6.2932039e-01 },
+ { 7.4314483e-01, -6.6913061e-01 }, { 7.0710678e-01, -7.0710678e-01 },
+ { 6.6913061e-01, -7.4314483e-01 }, { 6.2932039e-01, -7.7714596e-01 },
+ { 5.8778525e-01, -8.0901699e-01 }, { 5.4463904e-01, -8.3867057e-01 },
+ { 5.0000000e-01, -8.6602540e-01 }, { 4.5399050e-01, -8.9100652e-01 },
+ { 4.0673664e-01, -9.1354546e-01 }, { 3.5836795e-01, -9.3358043e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.5881905e-01, -9.6592583e-01 },
+ { 2.0791169e-01, -9.7814760e-01 }, { 1.5643447e-01, -9.8768834e-01 },
+ { 1.0452846e-01, -9.9452190e-01 }, { 5.2335956e-02, -9.9862953e-01 },
+ { 2.8327694e-16, -1.0000000e+00 }, { -5.2335956e-02, -9.9862953e-01 },
+ { -1.0452846e-01, -9.9452190e-01 }, { -1.5643447e-01, -9.8768834e-01 },
+ { -2.0791169e-01, -9.7814760e-01 }, { -2.5881905e-01, -9.6592583e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -3.5836795e-01, -9.3358043e-01 },
+ { -4.0673664e-01, -9.1354546e-01 }, { -4.5399050e-01, -8.9100652e-01 },
+ { -5.0000000e-01, -8.6602540e-01 }, { -5.4463904e-01, -8.3867057e-01 },
+ { -5.8778525e-01, -8.0901699e-01 }, { -6.2932039e-01, -7.7714596e-01 },
+ { -6.6913061e-01, -7.4314483e-01 }, { -7.0710678e-01, -7.0710678e-01 },
+ { -7.4314483e-01, -6.6913061e-01 }, { -7.7714596e-01, -6.2932039e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.3867057e-01, -5.4463904e-01 },
+ { -8.6602540e-01, -5.0000000e-01 }, { -8.9100652e-01, -4.5399050e-01 },
+ { -9.1354546e-01, -4.0673664e-01 }, { -9.3358043e-01, -3.5836795e-01 },
+ { -9.5105652e-01, -3.0901699e-01 }, { -9.6592583e-01, -2.5881905e-01 },
+ { -9.7814760e-01, -2.0791169e-01 }, { -9.8768834e-01, -1.5643447e-01 },
+ { -9.9452190e-01, -1.0452846e-01 }, { -9.9862953e-01, -5.2335956e-02 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_160 = {
+ .n2 = 160/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9922904e-01, -3.9259816e-02 },
+ { 9.9691733e-01, -7.8459096e-02 }, { 9.9306846e-01, -1.1753740e-01 },
+ { 9.8768834e-01, -1.5643447e-01 }, { 9.8078528e-01, -1.9509032e-01 },
+ { 9.7236992e-01, -2.3344536e-01 }, { 9.6245524e-01, -2.7144045e-01 },
+ { 9.5105652e-01, -3.0901699e-01 }, { 9.3819134e-01, -3.4611706e-01 },
+ { 9.2387953e-01, -3.8268343e-01 }, { 9.0814317e-01, -4.1865974e-01 },
+ { 8.9100652e-01, -4.5399050e-01 }, { 8.7249601e-01, -4.8862124e-01 },
+ { 8.5264016e-01, -5.2249856e-01 }, { 8.3146961e-01, -5.5557023e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.8531693e-01, -6.1909395e-01 },
+ { 7.6040597e-01, -6.4944805e-01 }, { 7.3432251e-01, -6.7880075e-01 },
+ { 7.0710678e-01, -7.0710678e-01 }, { 6.7880075e-01, -7.3432251e-01 },
+ { 6.4944805e-01, -7.6040597e-01 }, { 6.1909395e-01, -7.8531693e-01 },
+ { 5.8778525e-01, -8.0901699e-01 }, { 5.5557023e-01, -8.3146961e-01 },
+ { 5.2249856e-01, -8.5264016e-01 }, { 4.8862124e-01, -8.7249601e-01 },
+ { 4.5399050e-01, -8.9100652e-01 }, { 4.1865974e-01, -9.0814317e-01 },
+ { 3.8268343e-01, -9.2387953e-01 }, { 3.4611706e-01, -9.3819134e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.7144045e-01, -9.6245524e-01 },
+ { 2.3344536e-01, -9.7236992e-01 }, { 1.9509032e-01, -9.8078528e-01 },
+ { 1.5643447e-01, -9.8768834e-01 }, { 1.1753740e-01, -9.9306846e-01 },
+ { 7.8459096e-02, -9.9691733e-01 }, { 3.9259816e-02, -9.9922904e-01 },
+ { 6.1232340e-17, -1.0000000e+00 }, { -3.9259816e-02, -9.9922904e-01 },
+ { -7.8459096e-02, -9.9691733e-01 }, { -1.1753740e-01, -9.9306846e-01 },
+ { -1.5643447e-01, -9.8768834e-01 }, { -1.9509032e-01, -9.8078528e-01 },
+ { -2.3344536e-01, -9.7236992e-01 }, { -2.7144045e-01, -9.6245524e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -3.4611706e-01, -9.3819134e-01 },
+ { -3.8268343e-01, -9.2387953e-01 }, { -4.1865974e-01, -9.0814317e-01 },
+ { -4.5399050e-01, -8.9100652e-01 }, { -4.8862124e-01, -8.7249601e-01 },
+ { -5.2249856e-01, -8.5264016e-01 }, { -5.5557023e-01, -8.3146961e-01 },
+ { -5.8778525e-01, -8.0901699e-01 }, { -6.1909395e-01, -7.8531693e-01 },
+ { -6.4944805e-01, -7.6040597e-01 }, { -6.7880075e-01, -7.3432251e-01 },
+ { -7.0710678e-01, -7.0710678e-01 }, { -7.3432251e-01, -6.7880075e-01 },
+ { -7.6040597e-01, -6.4944805e-01 }, { -7.8531693e-01, -6.1909395e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.3146961e-01, -5.5557023e-01 },
+ { -8.5264016e-01, -5.2249856e-01 }, { -8.7249601e-01, -4.8862124e-01 },
+ { -8.9100652e-01, -4.5399050e-01 }, { -9.0814317e-01, -4.1865974e-01 },
+ { -9.2387953e-01, -3.8268343e-01 }, { -9.3819134e-01, -3.4611706e-01 },
+ { -9.5105652e-01, -3.0901699e-01 }, { -9.6245524e-01, -2.7144045e-01 },
+ { -9.7236992e-01, -2.3344536e-01 }, { -9.8078528e-01, -1.9509032e-01 },
+ { -9.8768834e-01, -1.5643447e-01 }, { -9.9306846e-01, -1.1753740e-01 },
+ { -9.9691733e-01, -7.8459096e-02 }, { -9.9922904e-01, -3.9259816e-02 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_180 = {
+ .n2 = 180/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9939083e-01, -3.4899497e-02 },
+ { 9.9756405e-01, -6.9756474e-02 }, { 9.9452190e-01, -1.0452846e-01 },
+ { 9.9026807e-01, -1.3917310e-01 }, { 9.8480775e-01, -1.7364818e-01 },
+ { 9.7814760e-01, -2.0791169e-01 }, { 9.7029573e-01, -2.4192190e-01 },
+ { 9.6126170e-01, -2.7563736e-01 }, { 9.5105652e-01, -3.0901699e-01 },
+ { 9.3969262e-01, -3.4202014e-01 }, { 9.2718385e-01, -3.7460659e-01 },
+ { 9.1354546e-01, -4.0673664e-01 }, { 8.9879405e-01, -4.3837115e-01 },
+ { 8.8294759e-01, -4.6947156e-01 }, { 8.6602540e-01, -5.0000000e-01 },
+ { 8.4804810e-01, -5.2991926e-01 }, { 8.2903757e-01, -5.5919290e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.8801075e-01, -6.1566148e-01 },
+ { 7.6604444e-01, -6.4278761e-01 }, { 7.4314483e-01, -6.6913061e-01 },
+ { 7.1933980e-01, -6.9465837e-01 }, { 6.9465837e-01, -7.1933980e-01 },
+ { 6.6913061e-01, -7.4314483e-01 }, { 6.4278761e-01, -7.6604444e-01 },
+ { 6.1566148e-01, -7.8801075e-01 }, { 5.8778525e-01, -8.0901699e-01 },
+ { 5.5919290e-01, -8.2903757e-01 }, { 5.2991926e-01, -8.4804810e-01 },
+ { 5.0000000e-01, -8.6602540e-01 }, { 4.6947156e-01, -8.8294759e-01 },
+ { 4.3837115e-01, -8.9879405e-01 }, { 4.0673664e-01, -9.1354546e-01 },
+ { 3.7460659e-01, -9.2718385e-01 }, { 3.4202014e-01, -9.3969262e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.7563736e-01, -9.6126170e-01 },
+ { 2.4192190e-01, -9.7029573e-01 }, { 2.0791169e-01, -9.7814760e-01 },
+ { 1.7364818e-01, -9.8480775e-01 }, { 1.3917310e-01, -9.9026807e-01 },
+ { 1.0452846e-01, -9.9452190e-01 }, { 6.9756474e-02, -9.9756405e-01 },
+ { 3.4899497e-02, -9.9939083e-01 }, { 6.1232340e-17, -1.0000000e+00 },
+ { -3.4899497e-02, -9.9939083e-01 }, { -6.9756474e-02, -9.9756405e-01 },
+ { -1.0452846e-01, -9.9452190e-01 }, { -1.3917310e-01, -9.9026807e-01 },
+ { -1.7364818e-01, -9.8480775e-01 }, { -2.0791169e-01, -9.7814760e-01 },
+ { -2.4192190e-01, -9.7029573e-01 }, { -2.7563736e-01, -9.6126170e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -3.4202014e-01, -9.3969262e-01 },
+ { -3.7460659e-01, -9.2718385e-01 }, { -4.0673664e-01, -9.1354546e-01 },
+ { -4.3837115e-01, -8.9879405e-01 }, { -4.6947156e-01, -8.8294759e-01 },
+ { -5.0000000e-01, -8.6602540e-01 }, { -5.2991926e-01, -8.4804810e-01 },
+ { -5.5919290e-01, -8.2903757e-01 }, { -5.8778525e-01, -8.0901699e-01 },
+ { -6.1566148e-01, -7.8801075e-01 }, { -6.4278761e-01, -7.6604444e-01 },
+ { -6.6913061e-01, -7.4314483e-01 }, { -6.9465837e-01, -7.1933980e-01 },
+ { -7.1933980e-01, -6.9465837e-01 }, { -7.4314483e-01, -6.6913061e-01 },
+ { -7.6604444e-01, -6.4278761e-01 }, { -7.8801075e-01, -6.1566148e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.2903757e-01, -5.5919290e-01 },
+ { -8.4804810e-01, -5.2991926e-01 }, { -8.6602540e-01, -5.0000000e-01 },
+ { -8.8294759e-01, -4.6947156e-01 }, { -8.9879405e-01, -4.3837115e-01 },
+ { -9.1354546e-01, -4.0673664e-01 }, { -9.2718385e-01, -3.7460659e-01 },
+ { -9.3969262e-01, -3.4202014e-01 }, { -9.5105652e-01, -3.0901699e-01 },
+ { -9.6126170e-01, -2.7563736e-01 }, { -9.7029573e-01, -2.4192190e-01 },
+ { -9.7814760e-01, -2.0791169e-01 }, { -9.8480775e-01, -1.7364818e-01 },
+ { -9.9026807e-01, -1.3917310e-01 }, { -9.9452190e-01, -1.0452846e-01 },
+ { -9.9756405e-01, -6.9756474e-02 }, { -9.9939083e-01, -3.4899497e-02 },
+ }
+};
+
+static const struct lc3_fft_bf2_twiddles fft_twiddles_240 = {
+ .n2 = 240/2, .t = (const struct lc3_complex []){
+ { 1.0000000e+00, -0.0000000e+00 }, { 9.9965732e-01, -2.6176948e-02 },
+ { 9.9862953e-01, -5.2335956e-02 }, { 9.9691733e-01, -7.8459096e-02 },
+ { 9.9452190e-01, -1.0452846e-01 }, { 9.9144486e-01, -1.3052619e-01 },
+ { 9.8768834e-01, -1.5643447e-01 }, { 9.8325491e-01, -1.8223553e-01 },
+ { 9.7814760e-01, -2.0791169e-01 }, { 9.7236992e-01, -2.3344536e-01 },
+ { 9.6592583e-01, -2.5881905e-01 }, { 9.5881973e-01, -2.8401534e-01 },
+ { 9.5105652e-01, -3.0901699e-01 }, { 9.4264149e-01, -3.3380686e-01 },
+ { 9.3358043e-01, -3.5836795e-01 }, { 9.2387953e-01, -3.8268343e-01 },
+ { 9.1354546e-01, -4.0673664e-01 }, { 9.0258528e-01, -4.3051110e-01 },
+ { 8.9100652e-01, -4.5399050e-01 }, { 8.7881711e-01, -4.7715876e-01 },
+ { 8.6602540e-01, -5.0000000e-01 }, { 8.5264016e-01, -5.2249856e-01 },
+ { 8.3867057e-01, -5.4463904e-01 }, { 8.2412619e-01, -5.6640624e-01 },
+ { 8.0901699e-01, -5.8778525e-01 }, { 7.9335334e-01, -6.0876143e-01 },
+ { 7.7714596e-01, -6.2932039e-01 }, { 7.6040597e-01, -6.4944805e-01 },
+ { 7.4314483e-01, -6.6913061e-01 }, { 7.2537437e-01, -6.8835458e-01 },
+ { 7.0710678e-01, -7.0710678e-01 }, { 6.8835458e-01, -7.2537437e-01 },
+ { 6.6913061e-01, -7.4314483e-01 }, { 6.4944805e-01, -7.6040597e-01 },
+ { 6.2932039e-01, -7.7714596e-01 }, { 6.0876143e-01, -7.9335334e-01 },
+ { 5.8778525e-01, -8.0901699e-01 }, { 5.6640624e-01, -8.2412619e-01 },
+ { 5.4463904e-01, -8.3867057e-01 }, { 5.2249856e-01, -8.5264016e-01 },
+ { 5.0000000e-01, -8.6602540e-01 }, { 4.7715876e-01, -8.7881711e-01 },
+ { 4.5399050e-01, -8.9100652e-01 }, { 4.3051110e-01, -9.0258528e-01 },
+ { 4.0673664e-01, -9.1354546e-01 }, { 3.8268343e-01, -9.2387953e-01 },
+ { 3.5836795e-01, -9.3358043e-01 }, { 3.3380686e-01, -9.4264149e-01 },
+ { 3.0901699e-01, -9.5105652e-01 }, { 2.8401534e-01, -9.5881973e-01 },
+ { 2.5881905e-01, -9.6592583e-01 }, { 2.3344536e-01, -9.7236992e-01 },
+ { 2.0791169e-01, -9.7814760e-01 }, { 1.8223553e-01, -9.8325491e-01 },
+ { 1.5643447e-01, -9.8768834e-01 }, { 1.3052619e-01, -9.9144486e-01 },
+ { 1.0452846e-01, -9.9452190e-01 }, { 7.8459096e-02, -9.9691733e-01 },
+ { 5.2335956e-02, -9.9862953e-01 }, { 2.6176948e-02, -9.9965732e-01 },
+ { 2.8327694e-16, -1.0000000e+00 }, { -2.6176948e-02, -9.9965732e-01 },
+ { -5.2335956e-02, -9.9862953e-01 }, { -7.8459096e-02, -9.9691733e-01 },
+ { -1.0452846e-01, -9.9452190e-01 }, { -1.3052619e-01, -9.9144486e-01 },
+ { -1.5643447e-01, -9.8768834e-01 }, { -1.8223553e-01, -9.8325491e-01 },
+ { -2.0791169e-01, -9.7814760e-01 }, { -2.3344536e-01, -9.7236992e-01 },
+ { -2.5881905e-01, -9.6592583e-01 }, { -2.8401534e-01, -9.5881973e-01 },
+ { -3.0901699e-01, -9.5105652e-01 }, { -3.3380686e-01, -9.4264149e-01 },
+ { -3.5836795e-01, -9.3358043e-01 }, { -3.8268343e-01, -9.2387953e-01 },
+ { -4.0673664e-01, -9.1354546e-01 }, { -4.3051110e-01, -9.0258528e-01 },
+ { -4.5399050e-01, -8.9100652e-01 }, { -4.7715876e-01, -8.7881711e-01 },
+ { -5.0000000e-01, -8.6602540e-01 }, { -5.2249856e-01, -8.5264016e-01 },
+ { -5.4463904e-01, -8.3867057e-01 }, { -5.6640624e-01, -8.2412619e-01 },
+ { -5.8778525e-01, -8.0901699e-01 }, { -6.0876143e-01, -7.9335334e-01 },
+ { -6.2932039e-01, -7.7714596e-01 }, { -6.4944805e-01, -7.6040597e-01 },
+ { -6.6913061e-01, -7.4314483e-01 }, { -6.8835458e-01, -7.2537437e-01 },
+ { -7.0710678e-01, -7.0710678e-01 }, { -7.2537437e-01, -6.8835458e-01 },
+ { -7.4314483e-01, -6.6913061e-01 }, { -7.6040597e-01, -6.4944805e-01 },
+ { -7.7714596e-01, -6.2932039e-01 }, { -7.9335334e-01, -6.0876143e-01 },
+ { -8.0901699e-01, -5.8778525e-01 }, { -8.2412619e-01, -5.6640624e-01 },
+ { -8.3867057e-01, -5.4463904e-01 }, { -8.5264016e-01, -5.2249856e-01 },
+ { -8.6602540e-01, -5.0000000e-01 }, { -8.7881711e-01, -4.7715876e-01 },
+ { -8.9100652e-01, -4.5399050e-01 }, { -9.0258528e-01, -4.3051110e-01 },
+ { -9.1354546e-01, -4.0673664e-01 }, { -9.2387953e-01, -3.8268343e-01 },
+ { -9.3358043e-01, -3.5836795e-01 }, { -9.4264149e-01, -3.3380686e-01 },
+ { -9.5105652e-01, -3.0901699e-01 }, { -9.5881973e-01, -2.8401534e-01 },
+ { -9.6592583e-01, -2.5881905e-01 }, { -9.7236992e-01, -2.3344536e-01 },
+ { -9.7814760e-01, -2.0791169e-01 }, { -9.8325491e-01, -1.8223553e-01 },
+ { -9.8768834e-01, -1.5643447e-01 }, { -9.9144486e-01, -1.3052619e-01 },
+ { -9.9452190e-01, -1.0452846e-01 }, { -9.9691733e-01, -7.8459096e-02 },
+ { -9.9862953e-01, -5.2335956e-02 }, { -9.9965732e-01, -2.6176948e-02 },
+ }
+};
+
+const struct lc3_fft_bf2_twiddles *lc3_fft_twiddles_bf2[][3] = {
+ { &fft_twiddles_10 , &fft_twiddles_30 , &fft_twiddles_90 },
+ { &fft_twiddles_20 , &fft_twiddles_60 , &fft_twiddles_180 },
+ { &fft_twiddles_40 , &fft_twiddles_120 },
+ { &fft_twiddles_80 , &fft_twiddles_240 },
+ { &fft_twiddles_160 }
+};
+
+
+/**
+ * MDCT Rotation twiddles
+ *
+ * 2Pi (n + 1/8) / N
+ * W[n] = e * sqrt( sqrt( 4/N ) ), n = [0..N/4-1]
+ */
+
+static const struct lc3_mdct_rot_def mdct_rot_120 = {
+ .n4 = 120/4, .w = (const struct lc3_complex []){
+ { 4.2727785e-01, 2.7965670e-03 }, { 4.2654592e-01, 2.5154729e-02 },
+ { 4.2464486e-01, 4.7443945e-02 }, { 4.2157988e-01, 6.9603119e-02 },
+ { 4.1735937e-01, 9.1571516e-02 }, { 4.1199491e-01, 1.1328892e-01 },
+ { 4.0550120e-01, 1.3469581e-01 }, { 3.9789604e-01, 1.5573351e-01 },
+ { 3.8920028e-01, 1.7634435e-01 }, { 3.7943774e-01, 1.9647185e-01 },
+ { 3.6863519e-01, 2.1606083e-01 }, { 3.5682224e-01, 2.3505760e-01 },
+ { 3.4403126e-01, 2.5341009e-01 }, { 3.3029732e-01, 2.7106801e-01 },
+ { 3.1565806e-01, 2.8798294e-01 }, { 3.0015360e-01, 3.0410854e-01 },
+ { 2.8382644e-01, 3.1940060e-01 }, { 2.6672133e-01, 3.3381720e-01 },
+ { 2.4888515e-01, 3.4731883e-01 }, { 2.3036680e-01, 3.5986848e-01 },
+ { 2.1121703e-01, 3.7143176e-01 }, { 1.9148833e-01, 3.8197697e-01 },
+ { 1.7123477e-01, 3.9147521e-01 }, { 1.5051187e-01, 3.9990044e-01 },
+ { 1.2937643e-01, 4.0722957e-01 }, { 1.0788637e-01, 4.1344252e-01 },
+ { 8.6100606e-02, 4.1852225e-01 }, { 6.4078846e-02, 4.2245483e-01 },
+ { 4.1881450e-02, 4.2522950e-01 }, { 1.9569261e-02, 4.2683865e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_160 = {
+ .n4 = 160/4, .w = (const struct lc3_complex []){
+ { 3.9763057e-01, 1.9518802e-03 }, { 3.9724738e-01, 1.7561278e-02 },
+ { 3.9625167e-01, 3.3143598e-02 }, { 3.9464496e-01, 4.8674813e-02 },
+ { 3.9242974e-01, 6.4130975e-02 }, { 3.8960942e-01, 7.9488252e-02 },
+ { 3.8618835e-01, 9.4722964e-02 }, { 3.8217181e-01, 1.0981162e-01 },
+ { 3.7756598e-01, 1.2473095e-01 }, { 3.7237798e-01, 1.3945796e-01 },
+ { 3.6661580e-01, 1.5396993e-01 }, { 3.6028832e-01, 1.6824450e-01 },
+ { 3.5340530e-01, 1.8225964e-01 }, { 3.4597736e-01, 1.9599375e-01 },
+ { 3.3801594e-01, 2.0942566e-01 }, { 3.2953333e-01, 2.2253464e-01 },
+ { 3.2054261e-01, 2.3530049e-01 }, { 3.1105762e-01, 2.4770353e-01 },
+ { 3.0109302e-01, 2.5972462e-01 }, { 2.9066414e-01, 2.7134524e-01 },
+ { 2.7978709e-01, 2.8254746e-01 }, { 2.6847862e-01, 2.9331402e-01 },
+ { 2.5675618e-01, 3.0362831e-01 }, { 2.4463784e-01, 3.1347442e-01 },
+ { 2.3214228e-01, 3.2283718e-01 }, { 2.1928878e-01, 3.3170215e-01 },
+ { 2.0609715e-01, 3.4005565e-01 }, { 1.9258774e-01, 3.4788482e-01 },
+ { 1.7878136e-01, 3.5517757e-01 }, { 1.6469932e-01, 3.6192266e-01 },
+ { 1.5036333e-01, 3.6810970e-01 }, { 1.3579549e-01, 3.7372914e-01 },
+ { 1.2101826e-01, 3.7877231e-01 }, { 1.0605442e-01, 3.8323145e-01 },
+ { 9.0927064e-02, 3.8709967e-01 }, { 7.5659501e-02, 3.9037101e-01 },
+ { 6.0275277e-02, 3.9304042e-01 }, { 4.4798112e-02, 3.9510380e-01 },
+ { 2.9251872e-02, 3.9655795e-01 }, { 1.3660528e-02, 3.9740065e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_240 = {
+ .n4 = 240/4, .w = (const struct lc3_complex []){
+ { 3.5930219e-01, 1.1758179e-03 }, { 3.5914828e-01, 1.0580850e-02 },
+ { 3.5874824e-01, 1.9978630e-02 }, { 3.5810233e-01, 2.9362718e-02 },
+ { 3.5721099e-01, 3.8726682e-02 }, { 3.5607483e-01, 4.8064105e-02 },
+ { 3.5469464e-01, 5.7368587e-02 }, { 3.5307136e-01, 6.6633752e-02 },
+ { 3.5120611e-01, 7.5853249e-02 }, { 3.4910015e-01, 8.5020760e-02 },
+ { 3.4675494e-01, 9.4130002e-02 }, { 3.4417208e-01, 1.0317473e-01 },
+ { 3.4135334e-01, 1.1214875e-01 }, { 3.3830065e-01, 1.2104591e-01 },
+ { 3.3501611e-01, 1.2986011e-01 }, { 3.3150197e-01, 1.3858531e-01 },
+ { 3.2776063e-01, 1.4721553e-01 }, { 3.2379466e-01, 1.5574485e-01 },
+ { 3.1960678e-01, 1.6416744e-01 }, { 3.1519986e-01, 1.7247752e-01 },
+ { 3.1057691e-01, 1.8066938e-01 }, { 3.0574111e-01, 1.8873743e-01 },
+ { 3.0069577e-01, 1.9667612e-01 }, { 2.9544435e-01, 2.0448002e-01 },
+ { 2.8999045e-01, 2.1214378e-01 }, { 2.8433780e-01, 2.1966215e-01 },
+ { 2.7849028e-01, 2.2702998e-01 }, { 2.7245189e-01, 2.3424220e-01 },
+ { 2.6622679e-01, 2.4129389e-01 }, { 2.5981922e-01, 2.4818021e-01 },
+ { 2.5323358e-01, 2.5489644e-01 }, { 2.4647440e-01, 2.6143798e-01 },
+ { 2.3954629e-01, 2.6780034e-01 }, { 2.3245401e-01, 2.7397916e-01 },
+ { 2.2520241e-01, 2.7997021e-01 }, { 2.1779647e-01, 2.8576938e-01 },
+ { 2.1024127e-01, 2.9137270e-01 }, { 2.0254198e-01, 2.9677633e-01 },
+ { 1.9470387e-01, 3.0197657e-01 }, { 1.8673233e-01, 3.0696984e-01 },
+ { 1.7863281e-01, 3.1175273e-01 }, { 1.7041086e-01, 3.1632196e-01 },
+ { 1.6207212e-01, 3.2067440e-01 }, { 1.5362230e-01, 3.2480707e-01 },
+ { 1.4506720e-01, 3.2871713e-01 }, { 1.3641268e-01, 3.3240190e-01 },
+ { 1.2766467e-01, 3.3585887e-01 }, { 1.1882916e-01, 3.3908565e-01 },
+ { 1.0991221e-01, 3.4208003e-01 }, { 1.0091994e-01, 3.4483998e-01 },
+ { 9.1858496e-02, 3.4736359e-01 }, { 8.2734100e-02, 3.4964913e-01 },
+ { 7.3553002e-02, 3.5169504e-01 }, { 6.4321494e-02, 3.5349992e-01 },
+ { 5.5045904e-02, 3.5506252e-01 }, { 4.5732588e-02, 3.5638178e-01 },
+ { 3.6387929e-02, 3.5745680e-01 }, { 2.7018332e-02, 3.5828683e-01 },
+ { 1.7630217e-02, 3.5887131e-01 }, { 8.2300199e-03, 3.5920984e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_320 = {
+ .n4 = 320/4, .w = (const struct lc3_complex []){
+ { 3.3436915e-01, 8.2066700e-04 }, { 3.3428858e-01, 7.3854098e-03 },
+ { 3.3407914e-01, 1.3947305e-02 }, { 3.3374091e-01, 2.0503824e-02 },
+ { 3.3327401e-01, 2.7052438e-02 }, { 3.3267863e-01, 3.3590623e-02 },
+ { 3.3195499e-01, 4.0115858e-02 }, { 3.3110338e-01, 4.6625627e-02 },
+ { 3.3012413e-01, 5.3117422e-02 }, { 3.2901760e-01, 5.9588738e-02 },
+ { 3.2778423e-01, 6.6037082e-02 }, { 3.2642450e-01, 7.2459968e-02 },
+ { 3.2493892e-01, 7.8854919e-02 }, { 3.2332807e-01, 8.5219469e-02 },
+ { 3.2159257e-01, 9.1551166e-02 }, { 3.1973310e-01, 9.7847569e-02 },
+ { 3.1775035e-01, 1.0410625e-01 }, { 3.1564512e-01, 1.1032479e-01 },
+ { 3.1341819e-01, 1.1650081e-01 }, { 3.1107043e-01, 1.2263191e-01 },
+ { 3.0860275e-01, 1.2871573e-01 }, { 3.0601610e-01, 1.3474993e-01 },
+ { 3.0331148e-01, 1.4073218e-01 }, { 3.0048992e-01, 1.4666018e-01 },
+ { 2.9755251e-01, 1.5253164e-01 }, { 2.9450040e-01, 1.5834429e-01 },
+ { 2.9133475e-01, 1.6409590e-01 }, { 2.8805678e-01, 1.6978424e-01 },
+ { 2.8466777e-01, 1.7540713e-01 }, { 2.8116900e-01, 1.8096240e-01 },
+ { 2.7756185e-01, 1.8644790e-01 }, { 2.7384768e-01, 1.9186153e-01 },
+ { 2.7002795e-01, 1.9720119e-01 }, { 2.6610411e-01, 2.0246482e-01 },
+ { 2.6207768e-01, 2.0765040e-01 }, { 2.5795022e-01, 2.1275592e-01 },
+ { 2.5372331e-01, 2.1777943e-01 }, { 2.4939859e-01, 2.2271898e-01 },
+ { 2.4497772e-01, 2.2757266e-01 }, { 2.4046241e-01, 2.3233861e-01 },
+ { 2.3585439e-01, 2.3701499e-01 }, { 2.3115545e-01, 2.4159999e-01 },
+ { 2.2636739e-01, 2.4609186e-01 }, { 2.2149206e-01, 2.5048885e-01 },
+ { 2.1653135e-01, 2.5478927e-01 }, { 2.1148716e-01, 2.5899147e-01 },
+ { 2.0636143e-01, 2.6309382e-01 }, { 2.0115615e-01, 2.6709474e-01 },
+ { 1.9587332e-01, 2.7099270e-01 }, { 1.9051498e-01, 2.7478618e-01 },
+ { 1.8508318e-01, 2.7847372e-01 }, { 1.7958004e-01, 2.8205391e-01 },
+ { 1.7400766e-01, 2.8552536e-01 }, { 1.6836821e-01, 2.8888674e-01 },
+ { 1.6266384e-01, 2.9213674e-01 }, { 1.5689676e-01, 2.9527412e-01 },
+ { 1.5106920e-01, 2.9829767e-01 }, { 1.4518339e-01, 3.0120621e-01 },
+ { 1.3924162e-01, 3.0399864e-01 }, { 1.3324616e-01, 3.0667387e-01 },
+ { 1.2719933e-01, 3.0923087e-01 }, { 1.2110347e-01, 3.1166865e-01 },
+ { 1.1496092e-01, 3.1398628e-01 }, { 1.0877405e-01, 3.1618287e-01 },
+ { 1.0254525e-01, 3.1825755e-01 }, { 9.6276910e-02, 3.2020955e-01 },
+ { 8.9971456e-02, 3.2203810e-01 }, { 8.3631316e-02, 3.2374249e-01 },
+ { 7.7258935e-02, 3.2532208e-01 }, { 7.0856769e-02, 3.2677625e-01 },
+ { 6.4427286e-02, 3.2810444e-01 }, { 5.7972965e-02, 3.2930614e-01 },
+ { 5.1496295e-02, 3.3038089e-01 }, { 4.4999772e-02, 3.3132827e-01 },
+ { 3.8485901e-02, 3.3214791e-01 }, { 3.1957192e-02, 3.3283951e-01 },
+ { 2.5416164e-02, 3.3340279e-01 }, { 1.8865337e-02, 3.3383753e-01 },
+ { 1.2307237e-02, 3.3414358e-01 }, { 5.7443922e-03, 3.3432081e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_360 = {
+ .n4 = 360/4, .w = (const struct lc3_complex []){
+ { 3.2466714e-01, 7.0831495e-04 }, { 3.2460533e-01, 6.3744300e-03 },
+ { 3.2444464e-01, 1.2038603e-02 }, { 3.2418513e-01, 1.7699110e-02 },
+ { 3.2382686e-01, 2.3354225e-02 }, { 3.2336995e-01, 2.9002226e-02 },
+ { 3.2281454e-01, 3.4641392e-02 }, { 3.2216080e-01, 4.0270007e-02 },
+ { 3.2140893e-01, 4.5886355e-02 }, { 3.2055915e-01, 5.1488725e-02 },
+ { 3.1961172e-01, 5.7075412e-02 }, { 3.1856694e-01, 6.2644713e-02 },
+ { 3.1742512e-01, 6.8194931e-02 }, { 3.1618661e-01, 7.3724377e-02 },
+ { 3.1485178e-01, 7.9231366e-02 }, { 3.1342105e-01, 8.4714220e-02 },
+ { 3.1189485e-01, 9.0171269e-02 }, { 3.1027364e-01, 9.5600851e-02 },
+ { 3.0855792e-01, 1.0100131e-01 }, { 3.0674821e-01, 1.0637101e-01 },
+ { 3.0484506e-01, 1.1170830e-01 }, { 3.0284905e-01, 1.1701157e-01 },
+ { 3.0076079e-01, 1.2227919e-01 }, { 2.9858092e-01, 1.2750957e-01 },
+ { 2.9631010e-01, 1.3270110e-01 }, { 2.9394901e-01, 1.3785221e-01 },
+ { 2.9149839e-01, 1.4296134e-01 }, { 2.8895897e-01, 1.4802691e-01 },
+ { 2.8633154e-01, 1.5304740e-01 }, { 2.8361688e-01, 1.5802126e-01 },
+ { 2.8081584e-01, 1.6294699e-01 }, { 2.7792925e-01, 1.6782308e-01 },
+ { 2.7495800e-01, 1.7264806e-01 }, { 2.7190300e-01, 1.7742044e-01 },
+ { 2.6876518e-01, 1.8213878e-01 }, { 2.6554548e-01, 1.8680164e-01 },
+ { 2.6224490e-01, 1.9140760e-01 }, { 2.5886443e-01, 1.9595525e-01 },
+ { 2.5540512e-01, 2.0044321e-01 }, { 2.5186800e-01, 2.0487012e-01 },
+ { 2.4825416e-01, 2.0923462e-01 }, { 2.4456471e-01, 2.1353538e-01 },
+ { 2.4080075e-01, 2.1777110e-01 }, { 2.3696345e-01, 2.2194049e-01 },
+ { 2.3305396e-01, 2.2604227e-01 }, { 2.2907348e-01, 2.3007519e-01 },
+ { 2.2502323e-01, 2.3403803e-01 }, { 2.2090443e-01, 2.3792959e-01 },
+ { 2.1671834e-01, 2.4174866e-01 }, { 2.1246624e-01, 2.4549410e-01 },
+ { 2.0814942e-01, 2.4916476e-01 }, { 2.0376919e-01, 2.5275952e-01 },
+ { 1.9932689e-01, 2.5627728e-01 }, { 1.9482388e-01, 2.5971698e-01 },
+ { 1.9026152e-01, 2.6307757e-01 }, { 1.8564121e-01, 2.6635803e-01 },
+ { 1.8096434e-01, 2.6955734e-01 }, { 1.7623236e-01, 2.7267455e-01 },
+ { 1.7144669e-01, 2.7570870e-01 }, { 1.6660880e-01, 2.7865887e-01 },
+ { 1.6172015e-01, 2.8152415e-01 }, { 1.5678225e-01, 2.8430368e-01 },
+ { 1.5179659e-01, 2.8699661e-01 }, { 1.4676469e-01, 2.8960211e-01 },
+ { 1.4168808e-01, 2.9211940e-01 }, { 1.3656831e-01, 2.9454771e-01 },
+ { 1.3140695e-01, 2.9688629e-01 }, { 1.2620555e-01, 2.9913444e-01 },
+ { 1.2096571e-01, 3.0129147e-01 }, { 1.1568903e-01, 3.0335673e-01 },
+ { 1.1037710e-01, 3.0532958e-01 }, { 1.0503156e-01, 3.0720942e-01 },
+ { 9.9654017e-02, 3.0899568e-01 }, { 9.4246121e-02, 3.1068782e-01 },
+ { 8.8809517e-02, 3.1228533e-01 }, { 8.3345860e-02, 3.1378770e-01 },
+ { 7.7856816e-02, 3.1519450e-01 }, { 7.2344055e-02, 3.1650528e-01 },
+ { 6.6809258e-02, 3.1771965e-01 }, { 6.1254110e-02, 3.1883725e-01 },
+ { 5.5680304e-02, 3.1985772e-01 }, { 5.0089536e-02, 3.2078076e-01 },
+ { 4.4483511e-02, 3.2160608e-01 }, { 3.8863936e-02, 3.2233345e-01 },
+ { 3.3232523e-02, 3.2296262e-01 }, { 2.7590986e-02, 3.2349342e-01 },
+ { 2.1941045e-02, 3.2392568e-01 }, { 1.6284421e-02, 3.2425927e-01 },
+ { 1.0622836e-02, 3.2449408e-01 }, { 4.9580159e-03, 3.2463006e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_480 = {
+ .n4 = 480/4, .w = (const struct lc3_complex []){
+ { 3.0213714e-01, 4.9437117e-04 }, { 3.0210478e-01, 4.4491817e-03 },
+ { 3.0202066e-01, 8.4032299e-03 }, { 3.0188479e-01, 1.2355838e-02 },
+ { 3.0169719e-01, 1.6306330e-02 }, { 3.0145790e-01, 2.0254027e-02 },
+ { 3.0116696e-01, 2.4198254e-02 }, { 3.0082441e-01, 2.8138334e-02 },
+ { 3.0043032e-01, 3.2073593e-02 }, { 2.9998475e-01, 3.6003357e-02 },
+ { 2.9948778e-01, 3.9926952e-02 }, { 2.9893950e-01, 4.3843705e-02 },
+ { 2.9833999e-01, 4.7752946e-02 }, { 2.9768936e-01, 5.1654004e-02 },
+ { 2.9698773e-01, 5.5546213e-02 }, { 2.9623521e-01, 5.9428903e-02 },
+ { 2.9543193e-01, 6.3301411e-02 }, { 2.9457803e-01, 6.7163072e-02 },
+ { 2.9367365e-01, 7.1013225e-02 }, { 2.9271896e-01, 7.4851211e-02 },
+ { 2.9171411e-01, 7.8676371e-02 }, { 2.9065928e-01, 8.2488050e-02 },
+ { 2.8955464e-01, 8.6285595e-02 }, { 2.8840039e-01, 9.0068356e-02 },
+ { 2.8719672e-01, 9.3835684e-02 }, { 2.8594385e-01, 9.7586934e-02 },
+ { 2.8464198e-01, 1.0132146e-01 }, { 2.8329133e-01, 1.0503863e-01 },
+ { 2.8189215e-01, 1.0873780e-01 }, { 2.8044466e-01, 1.1241834e-01 },
+ { 2.7894913e-01, 1.1607962e-01 }, { 2.7740579e-01, 1.1972100e-01 },
+ { 2.7581493e-01, 1.2334187e-01 }, { 2.7417680e-01, 1.2694161e-01 },
+ { 2.7249170e-01, 1.3051960e-01 }, { 2.7075991e-01, 1.3407523e-01 },
+ { 2.6898172e-01, 1.3760788e-01 }, { 2.6715744e-01, 1.4111695e-01 },
+ { 2.6528739e-01, 1.4460184e-01 }, { 2.6337188e-01, 1.4806196e-01 },
+ { 2.6141125e-01, 1.5149671e-01 }, { 2.5940582e-01, 1.5490549e-01 },
+ { 2.5735595e-01, 1.5828774e-01 }, { 2.5526198e-01, 1.6164286e-01 },
+ { 2.5312427e-01, 1.6497029e-01 }, { 2.5094319e-01, 1.6826945e-01 },
+ { 2.4871911e-01, 1.7153978e-01 }, { 2.4645242e-01, 1.7478072e-01 },
+ { 2.4414349e-01, 1.7799171e-01 }, { 2.4179274e-01, 1.8117220e-01 },
+ { 2.3940055e-01, 1.8432165e-01 }, { 2.3696735e-01, 1.8743951e-01 },
+ { 2.3449354e-01, 1.9052526e-01 }, { 2.3197955e-01, 1.9357836e-01 },
+ { 2.2942581e-01, 1.9659830e-01 }, { 2.2683276e-01, 1.9958454e-01 },
+ { 2.2420085e-01, 2.0253659e-01 }, { 2.2153052e-01, 2.0545394e-01 },
+ { 2.1882223e-01, 2.0833608e-01 }, { 2.1607645e-01, 2.1118253e-01 },
+ { 2.1329364e-01, 2.1399279e-01 }, { 2.1047429e-01, 2.1676638e-01 },
+ { 2.0761888e-01, 2.1950284e-01 }, { 2.0472788e-01, 2.2220168e-01 },
+ { 2.0180182e-01, 2.2486245e-01 }, { 1.9884117e-01, 2.2748469e-01 },
+ { 1.9584645e-01, 2.3006795e-01 }, { 1.9281818e-01, 2.3261179e-01 },
+ { 1.8975686e-01, 2.3511577e-01 }, { 1.8666303e-01, 2.3757947e-01 },
+ { 1.8353722e-01, 2.4000246e-01 }, { 1.8037996e-01, 2.4238433e-01 },
+ { 1.7719180e-01, 2.4472466e-01 }, { 1.7397327e-01, 2.4702306e-01 },
+ { 1.7072493e-01, 2.4927914e-01 }, { 1.6744734e-01, 2.5149250e-01 },
+ { 1.6414106e-01, 2.5366278e-01 }, { 1.6080666e-01, 2.5578958e-01 },
+ { 1.5744470e-01, 2.5787256e-01 }, { 1.5405576e-01, 2.5991136e-01 },
+ { 1.5064043e-01, 2.6190562e-01 }, { 1.4719929e-01, 2.6385500e-01 },
+ { 1.4373292e-01, 2.6575918e-01 }, { 1.4024192e-01, 2.6761782e-01 },
+ { 1.3672690e-01, 2.6943060e-01 }, { 1.3318845e-01, 2.7119722e-01 },
+ { 1.2962718e-01, 2.7291736e-01 }, { 1.2604369e-01, 2.7459075e-01 },
+ { 1.2243861e-01, 2.7621709e-01 }, { 1.1881255e-01, 2.7779609e-01 },
+ { 1.1516614e-01, 2.7932750e-01 }, { 1.1149999e-01, 2.8081105e-01 },
+ { 1.0781473e-01, 2.8224648e-01 }, { 1.0411100e-01, 2.8363355e-01 },
+ { 1.0038943e-01, 2.8497202e-01 }, { 9.6650664e-02, 2.8626167e-01 },
+ { 9.2895335e-02, 2.8750226e-01 }, { 8.9124088e-02, 2.8869359e-01 },
+ { 8.5337570e-02, 2.8983546e-01 }, { 8.1536430e-02, 2.9092766e-01 },
+ { 7.7721319e-02, 2.9197001e-01 }, { 7.3892891e-02, 2.9296234e-01 },
+ { 7.0051802e-02, 2.9390447e-01 }, { 6.6198710e-02, 2.9479624e-01 },
+ { 6.2334275e-02, 2.9563750e-01 }, { 5.8459159e-02, 2.9642810e-01 },
+ { 5.4574027e-02, 2.9716791e-01 }, { 5.0679543e-02, 2.9785681e-01 },
+ { 4.6776376e-02, 2.9849466e-01 }, { 4.2865195e-02, 2.9908137e-01 },
+ { 3.8946668e-02, 2.9961684e-01 }, { 3.5021468e-02, 3.0010097e-01 },
+ { 3.1090267e-02, 3.0053367e-01 }, { 2.7153740e-02, 3.0091488e-01 },
+ { 2.3212559e-02, 3.0124454e-01 }, { 1.9267401e-02, 3.0152257e-01 },
+ { 1.5318942e-02, 3.0174894e-01 }, { 1.1367858e-02, 3.0192361e-01 },
+ { 7.4148264e-03, 3.0204654e-01 }, { 3.4605241e-03, 3.0211772e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_640 = {
+ .n4 = 640/4, .w = (const struct lc3_complex []){
+ { 2.8117045e-01, 3.4504823e-04 }, { 2.8115351e-01, 3.1053717e-03 },
+ { 2.8110948e-01, 5.8653959e-03 }, { 2.8103835e-01, 8.6248547e-03 },
+ { 2.8094013e-01, 1.1383482e-02 }, { 2.8081484e-01, 1.4141013e-02 },
+ { 2.8066248e-01, 1.6897180e-02 }, { 2.8048307e-01, 1.9651719e-02 },
+ { 2.8027662e-01, 2.2404364e-02 }, { 2.8004317e-01, 2.5154849e-02 },
+ { 2.7978272e-01, 2.7902910e-02 }, { 2.7949530e-01, 3.0648282e-02 },
+ { 2.7918095e-01, 3.3390700e-02 }, { 2.7883969e-01, 3.6129899e-02 },
+ { 2.7847155e-01, 3.8865616e-02 }, { 2.7807658e-01, 4.1597587e-02 },
+ { 2.7765480e-01, 4.4325549e-02 }, { 2.7720626e-01, 4.7049239e-02 },
+ { 2.7673100e-01, 4.9768394e-02 }, { 2.7622908e-01, 5.2482752e-02 },
+ { 2.7570052e-01, 5.5192052e-02 }, { 2.7514540e-01, 5.7896032e-02 },
+ { 2.7456376e-01, 6.0594433e-02 }, { 2.7395565e-01, 6.3286992e-02 },
+ { 2.7332114e-01, 6.5973453e-02 }, { 2.7266028e-01, 6.8653554e-02 },
+ { 2.7197315e-01, 7.1327039e-02 }, { 2.7125980e-01, 7.3993649e-02 },
+ { 2.7052031e-01, 7.6653127e-02 }, { 2.6975475e-01, 7.9305217e-02 },
+ { 2.6896318e-01, 8.1949664e-02 }, { 2.6814570e-01, 8.4586212e-02 },
+ { 2.6730236e-01, 8.7214608e-02 }, { 2.6643327e-01, 8.9834598e-02 },
+ { 2.6553849e-01, 9.2445929e-02 }, { 2.6461813e-01, 9.5048350e-02 },
+ { 2.6367225e-01, 9.7641610e-02 }, { 2.6270097e-01, 1.0022546e-01 },
+ { 2.6170436e-01, 1.0279965e-01 }, { 2.6068253e-01, 1.0536393e-01 },
+ { 2.5963558e-01, 1.0791806e-01 }, { 2.5856360e-01, 1.1046178e-01 },
+ { 2.5746670e-01, 1.1299486e-01 }, { 2.5634499e-01, 1.1551705e-01 },
+ { 2.5519857e-01, 1.1802810e-01 }, { 2.5402755e-01, 1.2052778e-01 },
+ { 2.5283205e-01, 1.2301584e-01 }, { 2.5161218e-01, 1.2549204e-01 },
+ { 2.5036806e-01, 1.2795615e-01 }, { 2.4909981e-01, 1.3040793e-01 },
+ { 2.4780754e-01, 1.3284714e-01 }, { 2.4649140e-01, 1.3527354e-01 },
+ { 2.4515150e-01, 1.3768691e-01 }, { 2.4378797e-01, 1.4008700e-01 },
+ { 2.4240094e-01, 1.4247360e-01 }, { 2.4099055e-01, 1.4484646e-01 },
+ { 2.3955693e-01, 1.4720536e-01 }, { 2.3810023e-01, 1.4955007e-01 },
+ { 2.3662057e-01, 1.5188037e-01 }, { 2.3511811e-01, 1.5419603e-01 },
+ { 2.3359299e-01, 1.5649683e-01 }, { 2.3204535e-01, 1.5878255e-01 },
+ { 2.3047535e-01, 1.6105296e-01 }, { 2.2888313e-01, 1.6330785e-01 },
+ { 2.2726886e-01, 1.6554699e-01 }, { 2.2563268e-01, 1.6777019e-01 },
+ { 2.2397475e-01, 1.6997721e-01 }, { 2.2229524e-01, 1.7216785e-01 },
+ { 2.2059430e-01, 1.7434190e-01 }, { 2.1887210e-01, 1.7649914e-01 },
+ { 2.1712880e-01, 1.7863937e-01 }, { 2.1536458e-01, 1.8076239e-01 },
+ { 2.1357960e-01, 1.8286798e-01 }, { 2.1177403e-01, 1.8495594e-01 },
+ { 2.0994805e-01, 1.8702608e-01 }, { 2.0810184e-01, 1.8907820e-01 },
+ { 2.0623557e-01, 1.9111209e-01 }, { 2.0434942e-01, 1.9312756e-01 },
+ { 2.0244358e-01, 1.9512442e-01 }, { 2.0051823e-01, 1.9710247e-01 },
+ { 1.9857355e-01, 1.9906152e-01 }, { 1.9660973e-01, 2.0100139e-01 },
+ { 1.9462696e-01, 2.0292188e-01 }, { 1.9262543e-01, 2.0482282e-01 },
+ { 1.9060533e-01, 2.0670401e-01 }, { 1.8856687e-01, 2.0856528e-01 },
+ { 1.8651023e-01, 2.1040645e-01 }, { 1.8443562e-01, 2.1222734e-01 },
+ { 1.8234322e-01, 2.1402778e-01 }, { 1.8023326e-01, 2.1580759e-01 },
+ { 1.7810592e-01, 2.1756659e-01 }, { 1.7596142e-01, 2.1930463e-01 },
+ { 1.7379995e-01, 2.2102153e-01 }, { 1.7162174e-01, 2.2271713e-01 },
+ { 1.6942698e-01, 2.2439126e-01 }, { 1.6721590e-01, 2.2604377e-01 },
+ { 1.6498869e-01, 2.2767449e-01 }, { 1.6274559e-01, 2.2928326e-01 },
+ { 1.6048680e-01, 2.3086994e-01 }, { 1.5821254e-01, 2.3243436e-01 },
+ { 1.5592304e-01, 2.3397638e-01 }, { 1.5361850e-01, 2.3549585e-01 },
+ { 1.5129916e-01, 2.3699263e-01 }, { 1.4896524e-01, 2.3846656e-01 },
+ { 1.4661696e-01, 2.3991751e-01 }, { 1.4425454e-01, 2.4134533e-01 },
+ { 1.4187823e-01, 2.4274989e-01 }, { 1.3948824e-01, 2.4413106e-01 },
+ { 1.3708480e-01, 2.4548869e-01 }, { 1.3466815e-01, 2.4682267e-01 },
+ { 1.3223853e-01, 2.4813285e-01 }, { 1.2979616e-01, 2.4941912e-01 },
+ { 1.2734127e-01, 2.5068135e-01 }, { 1.2487412e-01, 2.5191942e-01 },
+ { 1.2239493e-01, 2.5313321e-01 }, { 1.1990394e-01, 2.5432260e-01 },
+ { 1.1740139e-01, 2.5548748e-01 }, { 1.1488753e-01, 2.5662774e-01 },
+ { 1.1236260e-01, 2.5774326e-01 }, { 1.0982684e-01, 2.5883394e-01 },
+ { 1.0728049e-01, 2.5989967e-01 }, { 1.0472380e-01, 2.6094035e-01 },
+ { 1.0215702e-01, 2.6195588e-01 }, { 9.9580393e-02, 2.6294617e-01 },
+ { 9.6994168e-02, 2.6391111e-01 }, { 9.4398594e-02, 2.6485061e-01 },
+ { 9.1793922e-02, 2.6576459e-01 }, { 8.9180402e-02, 2.6665295e-01 },
+ { 8.6558287e-02, 2.6751562e-01 }, { 8.3927830e-02, 2.6835249e-01 },
+ { 8.1289283e-02, 2.6916351e-01 }, { 7.8642901e-02, 2.6994858e-01 },
+ { 7.5988940e-02, 2.7070763e-01 }, { 7.3327655e-02, 2.7144059e-01 },
+ { 7.0659302e-02, 2.7214739e-01 }, { 6.7984139e-02, 2.7282796e-01 },
+ { 6.5302424e-02, 2.7348224e-01 }, { 6.2614414e-02, 2.7411015e-01 },
+ { 5.9920370e-02, 2.7471165e-01 }, { 5.7220550e-02, 2.7528667e-01 },
+ { 5.4515216e-02, 2.7583516e-01 }, { 5.1804627e-02, 2.7635706e-01 },
+ { 4.9089045e-02, 2.7685232e-01 }, { 4.6368731e-02, 2.7732090e-01 },
+ { 4.3643949e-02, 2.7776275e-01 }, { 4.0914960e-02, 2.7817783e-01 },
+ { 3.8182028e-02, 2.7856610e-01 }, { 3.5445415e-02, 2.7892752e-01 },
+ { 3.2705387e-02, 2.7926206e-01 }, { 2.9962206e-02, 2.7956968e-01 },
+ { 2.7216137e-02, 2.7985036e-01 }, { 2.4467445e-02, 2.8010406e-01 },
+ { 2.1716395e-02, 2.8033077e-01 }, { 1.8963252e-02, 2.8053046e-01 },
+ { 1.6208281e-02, 2.8070310e-01 }, { 1.3451748e-02, 2.8084870e-01 },
+ { 1.0693918e-02, 2.8096723e-01 }, { 7.9350576e-03, 2.8105867e-01 },
+ { 5.1754324e-03, 2.8112303e-01 }, { 2.4153085e-03, 2.8116029e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_720 = {
+ .n4 = 720/4, .w = (const struct lc3_complex []){
+ { 2.7301192e-01, 2.9780993e-04 }, { 2.7299893e-01, 2.6802468e-03 },
+ { 2.7296515e-01, 5.0624796e-03 }, { 2.7291057e-01, 7.4443269e-03 },
+ { 2.7283522e-01, 9.8256072e-03 }, { 2.7273909e-01, 1.2206139e-02 },
+ { 2.7262218e-01, 1.4585742e-02 }, { 2.7248452e-01, 1.6964234e-02 },
+ { 2.7232611e-01, 1.9341434e-02 }, { 2.7214695e-01, 2.1717161e-02 },
+ { 2.7194708e-01, 2.4091234e-02 }, { 2.7172649e-01, 2.6463472e-02 },
+ { 2.7148521e-01, 2.8833695e-02 }, { 2.7122325e-01, 3.1201723e-02 },
+ { 2.7094064e-01, 3.3567374e-02 }, { 2.7063740e-01, 3.5930469e-02 },
+ { 2.7031354e-01, 3.8290828e-02 }, { 2.6996910e-01, 4.0648270e-02 },
+ { 2.6960411e-01, 4.3002618e-02 }, { 2.6921858e-01, 4.5353690e-02 },
+ { 2.6881255e-01, 4.7701309e-02 }, { 2.6838604e-01, 5.0045294e-02 },
+ { 2.6793910e-01, 5.2385469e-02 }, { 2.6747176e-01, 5.4721655e-02 },
+ { 2.6698404e-01, 5.7053673e-02 }, { 2.6647599e-01, 5.9381346e-02 },
+ { 2.6594765e-01, 6.1704497e-02 }, { 2.6539906e-01, 6.4022949e-02 },
+ { 2.6483026e-01, 6.6336526e-02 }, { 2.6424128e-01, 6.8645051e-02 },
+ { 2.6363219e-01, 7.0948348e-02 }, { 2.6300302e-01, 7.3246242e-02 },
+ { 2.6235382e-01, 7.5538558e-02 }, { 2.6168464e-01, 7.7825122e-02 },
+ { 2.6099553e-01, 8.0105759e-02 }, { 2.6028655e-01, 8.2380295e-02 },
+ { 2.5955774e-01, 8.4648558e-02 }, { 2.5880917e-01, 8.6910375e-02 },
+ { 2.5804089e-01, 8.9165573e-02 }, { 2.5725296e-01, 9.1413981e-02 },
+ { 2.5644543e-01, 9.3655427e-02 }, { 2.5561838e-01, 9.5889741e-02 },
+ { 2.5477186e-01, 9.8116753e-02 }, { 2.5390594e-01, 1.0033629e-01 },
+ { 2.5302069e-01, 1.0254819e-01 }, { 2.5211616e-01, 1.0475228e-01 },
+ { 2.5119244e-01, 1.0694839e-01 }, { 2.5024958e-01, 1.0913636e-01 },
+ { 2.4928767e-01, 1.1131602e-01 }, { 2.4830678e-01, 1.1348720e-01 },
+ { 2.4730697e-01, 1.1564973e-01 }, { 2.4628833e-01, 1.1780346e-01 },
+ { 2.4525094e-01, 1.1994822e-01 }, { 2.4419487e-01, 1.2208384e-01 },
+ { 2.4312020e-01, 1.2421017e-01 }, { 2.4202702e-01, 1.2632704e-01 },
+ { 2.4091541e-01, 1.2843429e-01 }, { 2.3978545e-01, 1.3053175e-01 },
+ { 2.3863723e-01, 1.3261928e-01 }, { 2.3747083e-01, 1.3469670e-01 },
+ { 2.3628636e-01, 1.3676387e-01 }, { 2.3508388e-01, 1.3882063e-01 },
+ { 2.3386351e-01, 1.4086681e-01 }, { 2.3262533e-01, 1.4290226e-01 },
+ { 2.3136943e-01, 1.4492683e-01 }, { 2.3009591e-01, 1.4694037e-01 },
+ { 2.2880487e-01, 1.4894272e-01 }, { 2.2749640e-01, 1.5093372e-01 },
+ { 2.2617061e-01, 1.5291323e-01 }, { 2.2482759e-01, 1.5488109e-01 },
+ { 2.2346746e-01, 1.5683716e-01 }, { 2.2209030e-01, 1.5878128e-01 },
+ { 2.2069624e-01, 1.6071332e-01 }, { 2.1928536e-01, 1.6263311e-01 },
+ { 2.1785779e-01, 1.6454052e-01 }, { 2.1641363e-01, 1.6643540e-01 },
+ { 2.1495298e-01, 1.6831760e-01 }, { 2.1347597e-01, 1.7018699e-01 },
+ { 2.1198270e-01, 1.7204341e-01 }, { 2.1047328e-01, 1.7388674e-01 },
+ { 2.0894784e-01, 1.7571682e-01 }, { 2.0740648e-01, 1.7753352e-01 },
+ { 2.0584933e-01, 1.7933670e-01 }, { 2.0427651e-01, 1.8112622e-01 },
+ { 2.0268812e-01, 1.8290195e-01 }, { 2.0108431e-01, 1.8466375e-01 },
+ { 1.9946518e-01, 1.8641149e-01 }, { 1.9783085e-01, 1.8814503e-01 },
+ { 1.9618147e-01, 1.8986424e-01 }, { 1.9451714e-01, 1.9156900e-01 },
+ { 1.9283800e-01, 1.9325917e-01 }, { 1.9114417e-01, 1.9493462e-01 },
+ { 1.8943579e-01, 1.9659522e-01 }, { 1.8771298e-01, 1.9824085e-01 },
+ { 1.8597588e-01, 1.9987139e-01 }, { 1.8422461e-01, 2.0148670e-01 },
+ { 1.8245932e-01, 2.0308667e-01 }, { 1.8068013e-01, 2.0467118e-01 },
+ { 1.7888718e-01, 2.0624010e-01 }, { 1.7708060e-01, 2.0779331e-01 },
+ { 1.7526055e-01, 2.0933070e-01 }, { 1.7342714e-01, 2.1085214e-01 },
+ { 1.7158053e-01, 2.1235753e-01 }, { 1.6972085e-01, 2.1384675e-01 },
+ { 1.6784825e-01, 2.1531968e-01 }, { 1.6596286e-01, 2.1677622e-01 },
+ { 1.6406484e-01, 2.1821624e-01 }, { 1.6215432e-01, 2.1963965e-01 },
+ { 1.6023145e-01, 2.2104633e-01 }, { 1.5829638e-01, 2.2243618e-01 },
+ { 1.5634925e-01, 2.2380909e-01 }, { 1.5439022e-01, 2.2516496e-01 },
+ { 1.5241943e-01, 2.2650368e-01 }, { 1.5043704e-01, 2.2782514e-01 },
+ { 1.4844319e-01, 2.2912926e-01 }, { 1.4643803e-01, 2.3041593e-01 },
+ { 1.4442172e-01, 2.3168506e-01 }, { 1.4239441e-01, 2.3293654e-01 },
+ { 1.4035626e-01, 2.3417028e-01 }, { 1.3830742e-01, 2.3538618e-01 },
+ { 1.3624805e-01, 2.3658417e-01 }, { 1.3417830e-01, 2.3776413e-01 },
+ { 1.3209834e-01, 2.3892599e-01 }, { 1.3000831e-01, 2.4006965e-01 },
+ { 1.2790838e-01, 2.4119503e-01 }, { 1.2579872e-01, 2.4230205e-01 },
+ { 1.2367947e-01, 2.4339061e-01 }, { 1.2155080e-01, 2.4446063e-01 },
+ { 1.1941288e-01, 2.4551204e-01 }, { 1.1726586e-01, 2.4654476e-01 },
+ { 1.1510992e-01, 2.4755869e-01 }, { 1.1294520e-01, 2.4855378e-01 },
+ { 1.1077189e-01, 2.4952993e-01 }, { 1.0859014e-01, 2.5048709e-01 },
+ { 1.0640012e-01, 2.5142516e-01 }, { 1.0420200e-01, 2.5234410e-01 },
+ { 1.0199594e-01, 2.5324381e-01 }, { 9.9782117e-02, 2.5412424e-01 },
+ { 9.7560694e-02, 2.5498531e-01 }, { 9.5331841e-02, 2.5582697e-01 },
+ { 9.3095728e-02, 2.5664915e-01 }, { 9.0852525e-02, 2.5745178e-01 },
+ { 8.8602403e-02, 2.5823480e-01 }, { 8.6345534e-02, 2.5899816e-01 },
+ { 8.4082090e-02, 2.5974180e-01 }, { 8.1812242e-02, 2.6046565e-01 },
+ { 7.9536165e-02, 2.6116967e-01 }, { 7.7254030e-02, 2.6185380e-01 },
+ { 7.4966012e-02, 2.6251799e-01 }, { 7.2672284e-02, 2.6316219e-01 },
+ { 7.0373023e-02, 2.6378635e-01 }, { 6.8068403e-02, 2.6439042e-01 },
+ { 6.5758598e-02, 2.6497435e-01 }, { 6.3443786e-02, 2.6553810e-01 },
+ { 6.1124143e-02, 2.6608164e-01 }, { 5.8799845e-02, 2.6660491e-01 },
+ { 5.6471069e-02, 2.6710788e-01 }, { 5.4137992e-02, 2.6759050e-01 },
+ { 5.1800793e-02, 2.6805275e-01 }, { 4.9459648e-02, 2.6849459e-01 },
+ { 4.7114738e-02, 2.6891597e-01 }, { 4.4766239e-02, 2.6931688e-01 },
+ { 4.2414331e-02, 2.6969728e-01 }, { 4.0059193e-02, 2.7005714e-01 },
+ { 3.7701004e-02, 2.7039644e-01 }, { 3.5339945e-02, 2.7071514e-01 },
+ { 3.2976194e-02, 2.7101323e-01 }, { 3.0609932e-02, 2.7129068e-01 },
+ { 2.8241338e-02, 2.7154747e-01 }, { 2.5870594e-02, 2.7178357e-01 },
+ { 2.3497880e-02, 2.7199899e-01 }, { 2.1123377e-02, 2.7219369e-01 },
+ { 1.8747265e-02, 2.7236765e-01 }, { 1.6369725e-02, 2.7252088e-01 },
+ { 1.3990938e-02, 2.7265336e-01 }, { 1.1611086e-02, 2.7276507e-01 },
+ { 9.2303502e-03, 2.7285601e-01 }, { 6.8489111e-03, 2.7292617e-01 },
+ { 4.4669505e-03, 2.7297554e-01 }, { 2.0846497e-03, 2.7300413e-01 },
+ }
+};
+
+static const struct lc3_mdct_rot_def mdct_rot_960 = {
+ .n4 = 960/4, .w = (const struct lc3_complex []){
+ { 2.5406629e-01, 2.0785754e-04 }, { 2.5405949e-01, 1.8707012e-03 },
+ { 2.5404180e-01, 3.5334647e-03 }, { 2.5401323e-01, 5.1960769e-03 },
+ { 2.5397379e-01, 6.8584664e-03 }, { 2.5392346e-01, 8.5205622e-03 },
+ { 2.5386225e-01, 1.0182293e-02 }, { 2.5379017e-01, 1.1843588e-02 },
+ { 2.5370722e-01, 1.3504375e-02 }, { 2.5361340e-01, 1.5164584e-02 },
+ { 2.5350872e-01, 1.6824143e-02 }, { 2.5339318e-01, 1.8482981e-02 },
+ { 2.5326678e-01, 2.0141028e-02 }, { 2.5312953e-01, 2.1798212e-02 },
+ { 2.5298144e-01, 2.3454462e-02 }, { 2.5282252e-01, 2.5109708e-02 },
+ { 2.5265276e-01, 2.6763878e-02 }, { 2.5247218e-01, 2.8416901e-02 },
+ { 2.5228079e-01, 3.0068707e-02 }, { 2.5207859e-01, 3.1719225e-02 },
+ { 2.5186559e-01, 3.3368385e-02 }, { 2.5164180e-01, 3.5016115e-02 },
+ { 2.5140723e-01, 3.6662344e-02 }, { 2.5116189e-01, 3.8307004e-02 },
+ { 2.5090580e-01, 3.9950022e-02 }, { 2.5063895e-01, 4.1591330e-02 },
+ { 2.5036137e-01, 4.3230855e-02 }, { 2.5007306e-01, 4.4868529e-02 },
+ { 2.4977405e-01, 4.6504281e-02 }, { 2.4946433e-01, 4.8138040e-02 },
+ { 2.4914393e-01, 4.9769738e-02 }, { 2.4881285e-01, 5.1399303e-02 },
+ { 2.4847112e-01, 5.3026667e-02 }, { 2.4811874e-01, 5.4651759e-02 },
+ { 2.4775573e-01, 5.6274511e-02 }, { 2.4738211e-01, 5.7894851e-02 },
+ { 2.4699789e-01, 5.9512712e-02 }, { 2.4660310e-01, 6.1128023e-02 },
+ { 2.4619774e-01, 6.2740716e-02 }, { 2.4578183e-01, 6.4350721e-02 },
+ { 2.4535539e-01, 6.5957969e-02 }, { 2.4491845e-01, 6.7562392e-02 },
+ { 2.4447101e-01, 6.9163921e-02 }, { 2.4401310e-01, 7.0762488e-02 },
+ { 2.4354474e-01, 7.2358023e-02 }, { 2.4306594e-01, 7.3950458e-02 },
+ { 2.4257673e-01, 7.5539726e-02 }, { 2.4207714e-01, 7.7125757e-02 },
+ { 2.4156717e-01, 7.8708485e-02 }, { 2.4104685e-01, 8.0287842e-02 },
+ { 2.4051621e-01, 8.1863759e-02 }, { 2.3997527e-01, 8.3436169e-02 },
+ { 2.3942404e-01, 8.5005005e-02 }, { 2.3886256e-01, 8.6570200e-02 },
+ { 2.3829085e-01, 8.8131686e-02 }, { 2.3770893e-01, 8.9689398e-02 },
+ { 2.3711683e-01, 9.1243267e-02 }, { 2.3651456e-01, 9.2793227e-02 },
+ { 2.3590217e-01, 9.4339213e-02 }, { 2.3527968e-01, 9.5881158e-02 },
+ { 2.3464710e-01, 9.7418995e-02 }, { 2.3400447e-01, 9.8952659e-02 },
+ { 2.3335182e-01, 1.0048208e-01 }, { 2.3268918e-01, 1.0200721e-01 },
+ { 2.3201656e-01, 1.0352796e-01 }, { 2.3133401e-01, 1.0504427e-01 },
+ { 2.3064154e-01, 1.0655609e-01 }, { 2.2993920e-01, 1.0806334e-01 },
+ { 2.2922701e-01, 1.0956597e-01 }, { 2.2850500e-01, 1.1106390e-01 },
+ { 2.2777320e-01, 1.1255707e-01 }, { 2.2703164e-01, 1.1404542e-01 },
+ { 2.2628036e-01, 1.1552888e-01 }, { 2.2551938e-01, 1.1700740e-01 },
+ { 2.2474874e-01, 1.1848090e-01 }, { 2.2396848e-01, 1.1994933e-01 },
+ { 2.2317862e-01, 1.2141262e-01 }, { 2.2237920e-01, 1.2287071e-01 },
+ { 2.2157026e-01, 1.2432354e-01 }, { 2.2075182e-01, 1.2577104e-01 },
+ { 2.1992393e-01, 1.2721315e-01 }, { 2.1908662e-01, 1.2864982e-01 },
+ { 2.1823992e-01, 1.3008097e-01 }, { 2.1738388e-01, 1.3150655e-01 },
+ { 2.1651852e-01, 1.3292650e-01 }, { 2.1564388e-01, 1.3434075e-01 },
+ { 2.1476001e-01, 1.3574925e-01 }, { 2.1386694e-01, 1.3715193e-01 },
+ { 2.1296471e-01, 1.3854874e-01 }, { 2.1205336e-01, 1.3993962e-01 },
+ { 2.1113292e-01, 1.4132449e-01 }, { 2.1020344e-01, 1.4270332e-01 },
+ { 2.0926495e-01, 1.4407603e-01 }, { 2.0831750e-01, 1.4544257e-01 },
+ { 2.0736113e-01, 1.4680288e-01 }, { 2.0639587e-01, 1.4815690e-01 },
+ { 2.0542177e-01, 1.4950458e-01 }, { 2.0443887e-01, 1.5084585e-01 },
+ { 2.0344722e-01, 1.5218066e-01 }, { 2.0244685e-01, 1.5350895e-01 },
+ { 2.0143780e-01, 1.5483066e-01 }, { 2.0042013e-01, 1.5614574e-01 },
+ { 1.9939388e-01, 1.5745414e-01 }, { 1.9835908e-01, 1.5875578e-01 },
+ { 1.9731578e-01, 1.6005063e-01 }, { 1.9626403e-01, 1.6133862e-01 },
+ { 1.9520388e-01, 1.6261970e-01 }, { 1.9413536e-01, 1.6389382e-01 },
+ { 1.9305853e-01, 1.6516091e-01 }, { 1.9197343e-01, 1.6642093e-01 },
+ { 1.9088010e-01, 1.6767382e-01 }, { 1.8977860e-01, 1.6891953e-01 },
+ { 1.8866896e-01, 1.7015800e-01 }, { 1.8755125e-01, 1.7138918e-01 },
+ { 1.8642550e-01, 1.7261302e-01 }, { 1.8529177e-01, 1.7382947e-01 },
+ { 1.8415009e-01, 1.7503847e-01 }, { 1.8300053e-01, 1.7623997e-01 },
+ { 1.8184314e-01, 1.7743392e-01 }, { 1.8067795e-01, 1.7862027e-01 },
+ { 1.7950502e-01, 1.7979897e-01 }, { 1.7832440e-01, 1.8096997e-01 },
+ { 1.7713614e-01, 1.8213322e-01 }, { 1.7594030e-01, 1.8328866e-01 },
+ { 1.7473692e-01, 1.8443625e-01 }, { 1.7352605e-01, 1.8557595e-01 },
+ { 1.7230775e-01, 1.8670769e-01 }, { 1.7108207e-01, 1.8783143e-01 },
+ { 1.6984906e-01, 1.8894713e-01 }, { 1.6860878e-01, 1.9005474e-01 },
+ { 1.6736127e-01, 1.9115420e-01 }, { 1.6610659e-01, 1.9224547e-01 },
+ { 1.6484480e-01, 1.9332851e-01 }, { 1.6357595e-01, 1.9440327e-01 },
+ { 1.6230008e-01, 1.9546970e-01 }, { 1.6101727e-01, 1.9652776e-01 },
+ { 1.5972756e-01, 1.9757740e-01 }, { 1.5843101e-01, 1.9861857e-01 },
+ { 1.5712767e-01, 1.9965124e-01 }, { 1.5581760e-01, 2.0067536e-01 },
+ { 1.5450085e-01, 2.0169087e-01 }, { 1.5317749e-01, 2.0269775e-01 },
+ { 1.5184756e-01, 2.0369595e-01 }, { 1.5051113e-01, 2.0468542e-01 },
+ { 1.4916826e-01, 2.0566612e-01 }, { 1.4781899e-01, 2.0663801e-01 },
+ { 1.4646339e-01, 2.0760105e-01 }, { 1.4510152e-01, 2.0855520e-01 },
+ { 1.4373343e-01, 2.0950041e-01 }, { 1.4235918e-01, 2.1043665e-01 },
+ { 1.4097884e-01, 2.1136388e-01 }, { 1.3959246e-01, 2.1228205e-01 },
+ { 1.3820009e-01, 2.1319113e-01 }, { 1.3680181e-01, 2.1409107e-01 },
+ { 1.3539767e-01, 2.1498185e-01 }, { 1.3398773e-01, 2.1586341e-01 },
+ { 1.3257204e-01, 2.1673573e-01 }, { 1.3115068e-01, 2.1759876e-01 },
+ { 1.2972370e-01, 2.1845247e-01 }, { 1.2829117e-01, 2.1929683e-01 },
+ { 1.2685313e-01, 2.2013179e-01 }, { 1.2540967e-01, 2.2095732e-01 },
+ { 1.2396083e-01, 2.2177339e-01 }, { 1.2250668e-01, 2.2257995e-01 },
+ { 1.2104729e-01, 2.2337698e-01 }, { 1.1958271e-01, 2.2416445e-01 },
+ { 1.1811300e-01, 2.2494231e-01 }, { 1.1663824e-01, 2.2571053e-01 },
+ { 1.1515848e-01, 2.2646909e-01 }, { 1.1367379e-01, 2.2721794e-01 },
+ { 1.1218422e-01, 2.2795706e-01 }, { 1.1068986e-01, 2.2868642e-01 },
+ { 1.0919075e-01, 2.2940598e-01 }, { 1.0768696e-01, 2.3011571e-01 },
+ { 1.0617856e-01, 2.3081559e-01 }, { 1.0466561e-01, 2.3150558e-01 },
+ { 1.0314818e-01, 2.3218565e-01 }, { 1.0162633e-01, 2.3285577e-01 },
+ { 1.0010013e-01, 2.3351592e-01 }, { 9.8569638e-02, 2.3416607e-01 },
+ { 9.7034924e-02, 2.3480619e-01 }, { 9.5496054e-02, 2.3543625e-01 },
+ { 9.3953093e-02, 2.3605622e-01 }, { 9.2406107e-02, 2.3666608e-01 },
+ { 9.0855163e-02, 2.3726580e-01 }, { 8.9300327e-02, 2.3785536e-01 },
+ { 8.7741666e-02, 2.3843473e-01 }, { 8.6179246e-02, 2.3900389e-01 },
+ { 8.4613135e-02, 2.3956281e-01 }, { 8.3043399e-02, 2.4011147e-01 },
+ { 8.1470106e-02, 2.4064984e-01 }, { 7.9893322e-02, 2.4117790e-01 },
+ { 7.8313117e-02, 2.4169563e-01 }, { 7.6729556e-02, 2.4220301e-01 },
+ { 7.5142709e-02, 2.4270001e-01 }, { 7.3552643e-02, 2.4318662e-01 },
+ { 7.1959427e-02, 2.4366281e-01 }, { 7.0363128e-02, 2.4412856e-01 },
+ { 6.8763814e-02, 2.4458385e-01 }, { 6.7161555e-02, 2.4502867e-01 },
+ { 6.5556419e-02, 2.4546299e-01 }, { 6.3948475e-02, 2.4588679e-01 },
+ { 6.2337792e-02, 2.4630007e-01 }, { 6.0724438e-02, 2.4670279e-01 },
+ { 5.9108483e-02, 2.4709494e-01 }, { 5.7489996e-02, 2.4747651e-01 },
+ { 5.5869046e-02, 2.4784748e-01 }, { 5.4245703e-02, 2.4820783e-01 },
+ { 5.2620036e-02, 2.4855755e-01 }, { 5.0992116e-02, 2.4889662e-01 },
+ { 4.9362011e-02, 2.4922503e-01 }, { 4.7729791e-02, 2.4954276e-01 },
+ { 4.6095527e-02, 2.4984980e-01 }, { 4.4459288e-02, 2.5014615e-01 },
+ { 4.2821145e-02, 2.5043177e-01 }, { 4.1181167e-02, 2.5070667e-01 },
+ { 3.9539426e-02, 2.5097083e-01 }, { 3.7895990e-02, 2.5122424e-01 },
+ { 3.6250931e-02, 2.5146688e-01 }, { 3.4604320e-02, 2.5169876e-01 },
+ { 3.2956226e-02, 2.5191985e-01 }, { 3.1306720e-02, 2.5213015e-01 },
+ { 2.9655874e-02, 2.5232965e-01 }, { 2.8003757e-02, 2.5251834e-01 },
+ { 2.6350440e-02, 2.5269621e-01 }, { 2.4695994e-02, 2.5286326e-01 },
+ { 2.3040491e-02, 2.5301948e-01 }, { 2.1384001e-02, 2.5316486e-01 },
+ { 1.9726595e-02, 2.5329940e-01 }, { 1.8068343e-02, 2.5342308e-01 },
+ { 1.6409318e-02, 2.5353591e-01 }, { 1.4749590e-02, 2.5363788e-01 },
+ { 1.3089230e-02, 2.5372898e-01 }, { 1.1428309e-02, 2.5380921e-01 },
+ { 9.7668984e-03, 2.5387857e-01 }, { 8.1050697e-03, 2.5393706e-01 },
+ { 6.4428938e-03, 2.5398467e-01 }, { 4.7804419e-03, 2.5402140e-01 },
+ { 3.1177852e-03, 2.5404724e-01 }, { 1.4549950e-03, 2.5406221e-01 },
+ }
+};
+
+const struct lc3_mdct_rot_def * lc3_mdct_rot[LC3_NUM_DT][LC3_NUM_SRATE] = {
+ [LC3_DT_7M5] = { &mdct_rot_120, &mdct_rot_240, &mdct_rot_360,
+ &mdct_rot_480, &mdct_rot_720 },
+ [LC3_DT_10M] = { &mdct_rot_160, &mdct_rot_320, &mdct_rot_480,
+ &mdct_rot_640, &mdct_rot_960 }
+};
+
+
+/**
+ * Low delay MDCT windows (cf. 3.7.3)
+ */
+
+static const float mdct_win_10m_80[80+50] = {
+ -7.07854671e-04, -2.09819773e-03, -4.52519808e-03, -8.23397633e-03,
+ -1.33771310e-02, -1.99972156e-02, -2.80090946e-02, -3.72150208e-02,
+ -4.73176826e-02, -5.79465483e-02, -6.86760675e-02, -7.90464744e-02,
+ -8.85970547e-02, -9.68830362e-02, -1.03496124e-01, -1.08076646e-01,
+ -1.10324226e-01, -1.09980985e-01, -1.06817214e-01, -1.00619042e-01,
+ -9.11645251e-02, -7.82061748e-02, -6.14668812e-02, -4.06336286e-02,
+ -1.53632952e-02, 1.47015507e-02, 4.98973651e-02, 9.05036926e-02,
+ 1.36691102e-01, 1.88468639e-01, 2.45645680e-01, 3.07778908e-01,
+ 3.74164237e-01, 4.43811480e-01, 5.15473546e-01, 5.87666172e-01,
+ 6.58761977e-01, 7.27057670e-01, 7.90875299e-01, 8.48664336e-01,
+ 8.99132024e-01, 9.41334815e-01, 9.74763483e-01, 9.99411473e-01,
+ 1.01576037e+00, 1.02473616e+00, 1.02763429e+00, 1.02599149e+00,
+ 1.02142721e+00, 1.01543986e+00, 1.00936693e+00, 1.00350816e+00,
+ 9.98889821e-01, 9.95313390e-01, 9.92594392e-01, 9.90577196e-01,
+ 9.89137162e-01, 9.88179075e-01, 9.87624927e-01, 9.87405628e-01,
+ 9.87452485e-01, 9.87695113e-01, 9.88064062e-01, 9.88492687e-01,
+ 9.88923003e-01, 9.89307497e-01, 9.89614633e-01, 9.89831927e-01,
+ 9.89969310e-01, 9.90060335e-01, 9.90157502e-01, 9.90325529e-01,
+ 9.90630379e-01, 9.91129889e-01, 9.91866549e-01, 9.92861973e-01,
+ 9.94115607e-01, 9.95603378e-01, 9.97279311e-01, 9.99078484e-01,
+ 1.00092237e+00, 1.00272811e+00, 1.00441604e+00, 1.00591922e+00,
+ 1.00718935e+00, 1.00820015e+00, 1.00894949e+00, 1.00945824e+00,
+ 1.00976898e+00, 1.00994034e+00, 1.01003945e+00, 1.01013232e+00,
+ 1.01027252e+00, 1.01049435e+00, 1.01080807e+00, 1.01120107e+00,
+ 1.01164127e+00, 1.01208013e+00, 1.01245818e+00, 1.01270696e+00,
+ 1.01275501e+00, 1.01253013e+00, 1.01196233e+00, 1.01098214e+00,
+ 1.00951244e+00, 1.00746086e+00, 1.00470868e+00, 1.00111141e+00,
+ 9.96504102e-01, 9.90720000e-01, 9.82376587e-01, 9.70882175e-01,
+ 9.54673298e-01, 9.32155386e-01, 9.01800368e-01, 8.62398408e-01,
+ 8.13281737e-01, 7.54455197e-01, 6.86658072e-01, 6.11348804e-01,
+ 5.30618165e-01, 4.47130985e-01, 3.63911468e-01, 2.84164703e-01,
+ 2.11020945e-01, 1.47228797e-01, 9.48266535e-02, 5.48243661e-02,
+ 2.70146141e-02, 9.99674359e-03,
+};
+
+static const float mdct_win_10m_160[160+100] = {
+ -4.61989875e-04, -9.74716672e-04, -1.66447310e-03, -2.59710692e-03,
+ -3.80628516e-03, -5.32460872e-03, -7.17588528e-03, -9.38248086e-03,
+ -1.19527030e-02, -1.48952816e-02, -1.82066640e-02, -2.18757093e-02,
+ -2.58847194e-02, -3.02086274e-02, -3.48159779e-02, -3.96706799e-02,
+ -4.47269805e-02, -4.99422586e-02, -5.52633479e-02, -6.06371724e-02,
+ -6.60096152e-02, -7.13196627e-02, -7.65117823e-02, -8.15296401e-02,
+ -8.63113754e-02, -9.08041129e-02, -9.49537776e-02, -9.87073651e-02,
+ -1.02020268e-01, -1.04843883e-01, -1.07138231e-01, -1.08869014e-01,
+ -1.09996966e-01, -1.10489847e-01, -1.10322584e-01, -1.09462175e-01,
+ -1.07883429e-01, -1.05561251e-01, -1.02465016e-01, -9.85701457e-02,
+ -9.38468492e-02, -8.82630999e-02, -8.17879272e-02, -7.43878560e-02,
+ -6.60218980e-02, -5.66565564e-02, -4.62445689e-02, -3.47458578e-02,
+ -2.21158161e-02, -8.31042570e-03, 6.71769764e-03, 2.30064206e-02,
+ 4.06010646e-02, 5.95323909e-02, 7.98335419e-02, 1.01523314e-01,
+ 1.24617139e-01, 1.49115252e-01, 1.75006740e-01, 2.02269985e-01,
+ 2.30865538e-01, 2.60736512e-01, 2.91814469e-01, 3.24009570e-01,
+ 3.57217518e-01, 3.91314689e-01, 4.26157164e-01, 4.61592545e-01,
+ 4.97447159e-01, 5.33532682e-01, 5.69654673e-01, 6.05608382e-01,
+ 6.41183084e-01, 6.76165350e-01, 7.10340055e-01, 7.43494372e-01,
+ 7.75428189e-01, 8.05943723e-01, 8.34858937e-01, 8.62010834e-01,
+ 8.87259971e-01, 9.10486312e-01, 9.31596250e-01, 9.50522086e-01,
+ 9.67236671e-01, 9.81739750e-01, 9.94055718e-01, 1.00424751e+00,
+ 1.01240743e+00, 1.01865099e+00, 1.02311884e+00, 1.02597245e+00,
+ 1.02739752e+00, 1.02758583e+00, 1.02673867e+00, 1.02506178e+00,
+ 1.02275651e+00, 1.02000914e+00, 1.01699650e+00, 1.01391595e+00,
+ 1.01104487e+00, 1.00777386e+00, 1.00484875e+00, 1.00224501e+00,
+ 9.99939317e-01, 9.97905542e-01, 9.96120338e-01, 9.94559753e-01,
+ 9.93203161e-01, 9.92029727e-01, 9.91023065e-01, 9.90166895e-01,
+ 9.89448837e-01, 9.88855636e-01, 9.88377852e-01, 9.88005163e-01,
+ 9.87729546e-01, 9.87541274e-01, 9.87432981e-01, 9.87394992e-01,
+ 9.87419705e-01, 9.87497321e-01, 9.87620124e-01, 9.87778192e-01,
+ 9.87963798e-01, 9.88167801e-01, 9.88383520e-01, 9.88602222e-01,
+ 9.88818277e-01, 9.89024798e-01, 9.89217866e-01, 9.89392368e-01,
+ 9.89546334e-01, 9.89677201e-01, 9.89785920e-01, 9.89872536e-01,
+ 9.89941079e-01, 9.89994556e-01, 9.90039402e-01, 9.90081472e-01,
+ 9.90129379e-01, 9.90190227e-01, 9.90273445e-01, 9.90386228e-01,
+ 9.90537983e-01, 9.90734883e-01, 9.90984259e-01, 9.91290512e-01,
+ 9.91658694e-01, 9.92090615e-01, 9.92588721e-01, 9.93151653e-01,
+ 9.93779087e-01, 9.94466818e-01, 9.95211663e-01, 9.96006862e-01,
+ 9.96846133e-01, 9.97720337e-01, 9.98621352e-01, 9.99538258e-01,
+ 1.00046196e+00, 1.00138055e+00, 1.00228487e+00, 1.00316385e+00,
+ 1.00400915e+00, 1.00481138e+00, 1.00556397e+00, 1.00625986e+00,
+ 1.00689557e+00, 1.00746662e+00, 1.00797244e+00, 1.00841147e+00,
+ 1.00878601e+00, 1.00909776e+00, 1.00935176e+00, 1.00955240e+00,
+ 1.00970709e+00, 1.00982209e+00, 1.00990696e+00, 1.00996902e+00,
+ 1.01001789e+00, 1.01006081e+00, 1.01010656e+00, 1.01016113e+00,
+ 1.01023108e+00, 1.01031948e+00, 1.01043047e+00, 1.01056410e+00,
+ 1.01072136e+00, 1.01089966e+00, 1.01109699e+00, 1.01130817e+00,
+ 1.01152919e+00, 1.01175301e+00, 1.01197388e+00, 1.01218284e+00,
+ 1.01237303e+00, 1.01253506e+00, 1.01266098e+00, 1.01274058e+00,
+ 1.01276592e+00, 1.01272696e+00, 1.01261590e+00, 1.01242289e+00,
+ 1.01214046e+00, 1.01175881e+00, 1.01126996e+00, 1.01066368e+00,
+ 1.00993075e+00, 1.00905825e+00, 1.00803431e+00, 1.00684335e+00,
+ 1.00547001e+00, 1.00389477e+00, 1.00209885e+00, 1.00006069e+00,
+ 9.97760020e-01, 9.95174643e-01, 9.92286108e-01, 9.89075787e-01,
+ 9.84736245e-01, 9.79861353e-01, 9.74137862e-01, 9.67333198e-01,
+ 9.59253976e-01, 9.49698408e-01, 9.38463416e-01, 9.25356797e-01,
+ 9.10198679e-01, 8.92833832e-01, 8.73143784e-01, 8.51042044e-01,
+ 8.26483991e-01, 7.99468149e-01, 7.70043128e-01, 7.38302860e-01,
+ 7.04381434e-01, 6.68461648e-01, 6.30775533e-01, 5.91579959e-01,
+ 5.51170316e-01, 5.09891542e-01, 4.68101711e-01, 4.26177297e-01,
+ 3.84517234e-01, 3.43522867e-01, 3.03600465e-01, 2.65143468e-01,
+ 2.28528397e-01, 1.94102191e-01, 1.62173542e-01, 1.33001524e-01,
+ 1.06784043e-01, 8.36505724e-02, 6.36518811e-02, 4.67653841e-02,
+ 3.28807275e-02, 2.18305756e-02, 1.33638143e-02, 6.75812489e-03,
+};
+
+static const float mdct_win_10m_240[240+150] = {
+ -3.61349642e-04, -7.07854671e-04, -1.07444364e-03, -1.53347854e-03,
+ -2.09819773e-03, -2.77842087e-03, -3.58412992e-03, -4.52519808e-03,
+ -5.60932724e-03, -6.84323454e-03, -8.23397633e-03, -9.78531476e-03,
+ -1.14988030e-02, -1.33771310e-02, -1.54218168e-02, -1.76297991e-02,
+ -1.99972156e-02, -2.25208056e-02, -2.51940630e-02, -2.80090946e-02,
+ -3.09576509e-02, -3.40299627e-02, -3.72150208e-02, -4.05005325e-02,
+ -4.38721922e-02, -4.73176826e-02, -5.08232534e-02, -5.43716664e-02,
+ -5.79465483e-02, -6.15342620e-02, -6.51170816e-02, -6.86760675e-02,
+ -7.21944781e-02, -7.56569598e-02, -7.90464744e-02, -8.23444256e-02,
+ -8.55332458e-02, -8.85970547e-02, -9.15209110e-02, -9.42884745e-02,
+ -9.68830362e-02, -9.92912326e-02, -1.01500847e-01, -1.03496124e-01,
+ -1.05263700e-01, -1.06793998e-01, -1.08076646e-01, -1.09099730e-01,
+ -1.09852449e-01, -1.10324226e-01, -1.10508462e-01, -1.10397741e-01,
+ -1.09980985e-01, -1.09249277e-01, -1.08197423e-01, -1.06817214e-01,
+ -1.05099580e-01, -1.03036011e-01, -1.00619042e-01, -9.78412002e-02,
+ -9.46930422e-02, -9.11645251e-02, -8.72464453e-02, -8.29304391e-02,
+ -7.82061748e-02, -7.30614243e-02, -6.74846818e-02, -6.14668812e-02,
+ -5.49949726e-02, -4.80544442e-02, -4.06336286e-02, -3.27204559e-02,
+ -2.43012258e-02, -1.53632952e-02, -5.89143427e-03, 4.12659586e-03,
+ 1.47015507e-02, 2.58473819e-02, 3.75765277e-02, 4.98973651e-02,
+ 6.28203403e-02, 7.63539773e-02, 9.05036926e-02, 1.05274712e-01,
+ 1.20670347e-01, 1.36691102e-01, 1.53334389e-01, 1.70595471e-01,
+ 1.88468639e-01, 2.06944996e-01, 2.26009300e-01, 2.45645680e-01,
+ 2.65834602e-01, 2.86554381e-01, 3.07778908e-01, 3.29476944e-01,
+ 3.51617148e-01, 3.74164237e-01, 3.97073959e-01, 4.20304305e-01,
+ 4.43811480e-01, 4.67544229e-01, 4.91449863e-01, 5.15473546e-01,
+ 5.39555764e-01, 5.63639982e-01, 5.87666172e-01, 6.11569531e-01,
+ 6.35289059e-01, 6.58761977e-01, 6.81923097e-01, 7.04709282e-01,
+ 7.27057670e-01, 7.48906896e-01, 7.70199019e-01, 7.90875299e-01,
+ 8.10878869e-01, 8.30157914e-01, 8.48664336e-01, 8.66354816e-01,
+ 8.83189685e-01, 8.99132024e-01, 9.14154056e-01, 9.28228255e-01,
+ 9.41334815e-01, 9.53461939e-01, 9.64604825e-01, 9.74763483e-01,
+ 9.83943539e-01, 9.92152910e-01, 9.99411473e-01, 1.00574608e+00,
+ 1.01118397e+00, 1.01576037e+00, 1.01951507e+00, 1.02249094e+00,
+ 1.02473616e+00, 1.02630410e+00, 1.02725098e+00, 1.02763429e+00,
+ 1.02751106e+00, 1.02694280e+00, 1.02599149e+00, 1.02471615e+00,
+ 1.02317598e+00, 1.02142721e+00, 1.01952157e+00, 1.01751012e+00,
+ 1.01543986e+00, 1.01346092e+00, 1.01165490e+00, 1.00936693e+00,
+ 1.00726318e+00, 1.00531319e+00, 1.00350816e+00, 1.00184079e+00,
+ 1.00030393e+00, 9.98889821e-01, 9.97591528e-01, 9.96401528e-01,
+ 9.95313390e-01, 9.94320108e-01, 9.93415896e-01, 9.92594392e-01,
+ 9.91851028e-01, 9.91179799e-01, 9.90577196e-01, 9.90038105e-01,
+ 9.89559439e-01, 9.89137162e-01, 9.88768437e-01, 9.88449792e-01,
+ 9.88179075e-01, 9.87952836e-01, 9.87769137e-01, 9.87624927e-01,
+ 9.87517995e-01, 9.87445813e-01, 9.87405628e-01, 9.87395112e-01,
+ 9.87411537e-01, 9.87452485e-01, 9.87514989e-01, 9.87596889e-01,
+ 9.87695113e-01, 9.87807582e-01, 9.87931200e-01, 9.88064062e-01,
+ 9.88203257e-01, 9.88347108e-01, 9.88492687e-01, 9.88638659e-01,
+ 9.88782558e-01, 9.88923003e-01, 9.89058172e-01, 9.89186767e-01,
+ 9.89307497e-01, 9.89419640e-01, 9.89522076e-01, 9.89614633e-01,
+ 9.89697035e-01, 9.89769260e-01, 9.89831927e-01, 9.89885257e-01,
+ 9.89930764e-01, 9.89969310e-01, 9.90002569e-01, 9.90032156e-01,
+ 9.90060335e-01, 9.90088981e-01, 9.90120659e-01, 9.90157502e-01,
+ 9.90202395e-01, 9.90257541e-01, 9.90325529e-01, 9.90408791e-01,
+ 9.90509649e-01, 9.90630379e-01, 9.90772711e-01, 9.90938744e-01,
+ 9.91129889e-01, 9.91347632e-01, 9.91592856e-01, 9.91866549e-01,
+ 9.92169132e-01, 9.92501085e-01, 9.92861973e-01, 9.93251918e-01,
+ 9.93670021e-01, 9.94115607e-01, 9.94587315e-01, 9.95083740e-01,
+ 9.95603378e-01, 9.96143992e-01, 9.96703453e-01, 9.97279311e-01,
+ 9.97869086e-01, 9.98469709e-01, 9.99078484e-01, 9.99691901e-01,
+ 1.00030819e+00, 1.00092237e+00, 1.00153264e+00, 1.00213546e+00,
+ 1.00272811e+00, 1.00330745e+00, 1.00387093e+00, 1.00441604e+00,
+ 1.00494055e+00, 1.00544214e+00, 1.00591922e+00, 1.00637030e+00,
+ 1.00679393e+00, 1.00718935e+00, 1.00755557e+00, 1.00789267e+00,
+ 1.00820015e+00, 1.00847842e+00, 1.00872788e+00, 1.00894949e+00,
+ 1.00914411e+00, 1.00931322e+00, 1.00945824e+00, 1.00958128e+00,
+ 1.00968409e+00, 1.00976898e+00, 1.00983831e+00, 1.00989455e+00,
+ 1.00994034e+00, 1.00997792e+00, 1.01001023e+00, 1.01003945e+00,
+ 1.01006820e+00, 1.01009839e+00, 1.01013232e+00, 1.01017166e+00,
+ 1.01021810e+00, 1.01027252e+00, 1.01033649e+00, 1.01041022e+00,
+ 1.01049435e+00, 1.01058887e+00, 1.01069350e+00, 1.01080807e+00,
+ 1.01093144e+00, 1.01106288e+00, 1.01120107e+00, 1.01134470e+00,
+ 1.01149190e+00, 1.01164127e+00, 1.01179028e+00, 1.01193757e+00,
+ 1.01208013e+00, 1.01221624e+00, 1.01234291e+00, 1.01245818e+00,
+ 1.01255888e+00, 1.01264286e+00, 1.01270696e+00, 1.01274895e+00,
+ 1.01276580e+00, 1.01275501e+00, 1.01271380e+00, 1.01263978e+00,
+ 1.01253013e+00, 1.01238231e+00, 1.01219407e+00, 1.01196233e+00,
+ 1.01168517e+00, 1.01135914e+00, 1.01098214e+00, 1.01055072e+00,
+ 1.01006213e+00, 1.00951244e+00, 1.00889869e+00, 1.00821592e+00,
+ 1.00746086e+00, 1.00662774e+00, 1.00571234e+00, 1.00470868e+00,
+ 1.00361147e+00, 1.00241429e+00, 1.00111141e+00, 9.99696165e-01,
+ 9.98162595e-01, 9.96504102e-01, 9.94714888e-01, 9.92789191e-01,
+ 9.90720000e-01, 9.88479371e-01, 9.85534766e-01, 9.82376587e-01,
+ 9.78974733e-01, 9.75162381e-01, 9.70882175e-01, 9.66080552e-01,
+ 9.60697640e-01, 9.54673298e-01, 9.47947935e-01, 9.40460905e-01,
+ 9.32155386e-01, 9.22977548e-01, 9.12874535e-01, 9.01800368e-01,
+ 8.89716328e-01, 8.76590897e-01, 8.62398408e-01, 8.47120080e-01,
+ 8.30747973e-01, 8.13281737e-01, 7.94729145e-01, 7.75110884e-01,
+ 7.54455197e-01, 7.32796355e-01, 7.10179084e-01, 6.86658072e-01,
+ 6.62296243e-01, 6.37168412e-01, 6.11348804e-01, 5.84920660e-01,
+ 5.57974743e-01, 5.30618165e-01, 5.02952396e-01, 4.75086883e-01,
+ 4.47130985e-01, 4.19204992e-01, 3.91425291e-01, 3.63911468e-01,
+ 3.36783777e-01, 3.10162784e-01, 2.84164703e-01, 2.58903371e-01,
+ 2.34488060e-01, 2.11020945e-01, 1.88599764e-01, 1.67310081e-01,
+ 1.47228797e-01, 1.28422307e-01, 1.10942255e-01, 9.48266535e-02,
+ 8.00991437e-02, 6.67676585e-02, 5.48243661e-02, 4.42458885e-02,
+ 3.49936100e-02, 2.70146141e-02, 2.02437018e-02, 1.46079676e-02,
+ 9.99674359e-03, 5.30523510e-03,
+};
+
+static const float mdct_win_10m_320[320+200] = {
+ -3.02115349e-04, -5.86773749e-04, -8.36650400e-04, -1.12663536e-03,
+ -1.47049294e-03, -1.87347339e-03, -2.33929236e-03, -2.87200807e-03,
+ -3.47625639e-03, -4.15596382e-03, -4.91456379e-03, -5.75517250e-03,
+ -6.68062338e-03, -7.69381692e-03, -8.79676075e-03, -9.99050307e-03,
+ -1.12757412e-02, -1.26533415e-02, -1.41243899e-02, -1.56888962e-02,
+ -1.73451209e-02, -1.90909737e-02, -2.09254671e-02, -2.28468479e-02,
+ -2.48520772e-02, -2.69374670e-02, -2.90995249e-02, -3.13350463e-02,
+ -3.36396073e-02, -3.60082097e-02, -3.84360174e-02, -4.09174603e-02,
+ -4.34465489e-02, -4.60178672e-02, -4.86259851e-02, -5.12647420e-02,
+ -5.39264475e-02, -5.66038431e-02, -5.92911675e-02, -6.19826820e-02,
+ -6.46702555e-02, -6.73454222e-02, -7.00009902e-02, -7.26305701e-02,
+ -7.52278496e-02, -7.77852594e-02, -8.02948025e-02, -8.27492454e-02,
+ -8.51412546e-02, -8.74637912e-02, -8.97106934e-02, -9.18756408e-02,
+ -9.39517698e-02, -9.59313774e-02, -9.78084326e-02, -9.95785130e-02,
+ -1.01236117e-01, -1.02774104e-01, -1.04186122e-01, -1.05468025e-01,
+ -1.06616088e-01, -1.07625538e-01, -1.08491230e-01, -1.09208742e-01,
+ -1.09773615e-01, -1.10180886e-01, -1.10427188e-01, -1.10510836e-01,
+ -1.10428147e-01, -1.10173922e-01, -1.09743736e-01, -1.09135313e-01,
+ -1.08346734e-01, -1.07373994e-01, -1.06213016e-01, -1.04860615e-01,
+ -1.03313240e-01, -1.01567316e-01, -9.96200551e-02, -9.74680323e-02,
+ -9.51072362e-02, -9.25330338e-02, -8.97412522e-02, -8.67287769e-02,
+ -8.34921384e-02, -8.00263990e-02, -7.63267954e-02, -7.23880616e-02,
+ -6.82057680e-02, -6.37761143e-02, -5.90938600e-02, -5.41531632e-02,
+ -4.89481272e-02, -4.34734711e-02, -3.77246130e-02, -3.16958761e-02,
+ -2.53817983e-02, -1.87768910e-02, -1.18746138e-02, -4.66909925e-03,
+ 2.84409675e-03, 1.06697612e-02, 1.88135595e-02, 2.72815601e-02,
+ 3.60781047e-02, 4.52070276e-02, 5.46723880e-02, 6.44786605e-02,
+ 7.46286220e-02, 8.51249057e-02, 9.59698399e-02, 1.07165078e-01,
+ 1.18711585e-01, 1.30610107e-01, 1.42859645e-01, 1.55458473e-01,
+ 1.68404161e-01, 1.81694789e-01, 1.95327388e-01, 2.09296321e-01,
+ 2.23594564e-01, 2.38216022e-01, 2.53152972e-01, 2.68396157e-01,
+ 2.83936139e-01, 2.99762426e-01, 3.15861908e-01, 3.32221055e-01,
+ 3.48826468e-01, 3.65664038e-01, 3.82715297e-01, 3.99961186e-01,
+ 4.17384327e-01, 4.34966962e-01, 4.52687640e-01, 4.70524201e-01,
+ 4.88453925e-01, 5.06454555e-01, 5.24500675e-01, 5.42567437e-01,
+ 5.60631204e-01, 5.78667265e-01, 5.96647704e-01, 6.14545890e-01,
+ 6.32336194e-01, 6.49992632e-01, 6.67487403e-01, 6.84793267e-01,
+ 7.01883546e-01, 7.18732254e-01, 7.35312821e-01, 7.51600199e-01,
+ 7.67569925e-01, 7.83197457e-01, 7.98458386e-01, 8.13329535e-01,
+ 8.27789227e-01, 8.41817856e-01, 8.55396130e-01, 8.68506898e-01,
+ 8.81133444e-01, 8.93259678e-01, 9.04874884e-01, 9.15965761e-01,
+ 9.26521530e-01, 9.36533999e-01, 9.45997703e-01, 9.54908841e-01,
+ 9.63265812e-01, 9.71068890e-01, 9.78320416e-01, 9.85022676e-01,
+ 9.91179208e-01, 9.96798994e-01, 1.00189402e+00, 1.00647434e+00,
+ 1.01055206e+00, 1.01414254e+00, 1.01726259e+00, 1.01992884e+00,
+ 1.02215987e+00, 1.02397632e+00, 1.02540073e+00, 1.02645534e+00,
+ 1.02716451e+00, 1.02755273e+00, 1.02764446e+00, 1.02746325e+00,
+ 1.02703590e+00, 1.02638907e+00, 1.02554820e+00, 1.02453713e+00,
+ 1.02338080e+00, 1.02210370e+00, 1.02072836e+00, 1.01927533e+00,
+ 1.01776518e+00, 1.01621736e+00, 1.01466531e+00, 1.01324907e+00,
+ 1.01194801e+00, 1.01018909e+00, 1.00855796e+00, 1.00701129e+00,
+ 1.00554876e+00, 1.00416842e+00, 1.00286727e+00, 1.00164177e+00,
+ 1.00048907e+00, 9.99406080e-01, 9.98389887e-01, 9.97437085e-01,
+ 9.96544484e-01, 9.95709855e-01, 9.94930241e-01, 9.94202405e-01,
+ 9.93524160e-01, 9.92893043e-01, 9.92306810e-01, 9.91763378e-01,
+ 9.91259764e-01, 9.90795450e-01, 9.90367789e-01, 9.89975161e-01,
+ 9.89616034e-01, 9.89289016e-01, 9.88992851e-01, 9.88726033e-01,
+ 9.88486872e-01, 9.88275104e-01, 9.88089217e-01, 9.87927711e-01,
+ 9.87789826e-01, 9.87674344e-01, 9.87580750e-01, 9.87507202e-01,
+ 9.87452945e-01, 9.87416974e-01, 9.87398469e-01, 9.87395830e-01,
+ 9.87408003e-01, 9.87434340e-01, 9.87473624e-01, 9.87524314e-01,
+ 9.87585620e-01, 9.87656379e-01, 9.87735892e-01, 9.87822558e-01,
+ 9.87915097e-01, 9.88013273e-01, 9.88115695e-01, 9.88221131e-01,
+ 9.88328903e-01, 9.88437831e-01, 9.88547679e-01, 9.88656841e-01,
+ 9.88764587e-01, 9.88870854e-01, 9.88974432e-01, 9.89074727e-01,
+ 9.89171004e-01, 9.89263102e-01, 9.89350722e-01, 9.89433065e-01,
+ 9.89509692e-01, 9.89581081e-01, 9.89646747e-01, 9.89706737e-01,
+ 9.89760693e-01, 9.89809448e-01, 9.89853013e-01, 9.89891471e-01,
+ 9.89925419e-01, 9.89955420e-01, 9.89982449e-01, 9.90006512e-01,
+ 9.90028481e-01, 9.90049748e-01, 9.90070956e-01, 9.90092836e-01,
+ 9.90116392e-01, 9.90142748e-01, 9.90173428e-01, 9.90208733e-01,
+ 9.90249864e-01, 9.90298369e-01, 9.90354850e-01, 9.90420508e-01,
+ 9.90495930e-01, 9.90582515e-01, 9.90681257e-01, 9.90792209e-01,
+ 9.90916546e-01, 9.91055074e-01, 9.91208461e-01, 9.91376861e-01,
+ 9.91560583e-01, 9.91760421e-01, 9.91976718e-01, 9.92209110e-01,
+ 9.92457914e-01, 9.92723123e-01, 9.93004954e-01, 9.93302728e-01,
+ 9.93616108e-01, 9.93945371e-01, 9.94289515e-01, 9.94648168e-01,
+ 9.95020303e-01, 9.95405817e-01, 9.95803871e-01, 9.96213027e-01,
+ 9.96632469e-01, 9.97061531e-01, 9.97499058e-01, 9.97943743e-01,
+ 9.98394057e-01, 9.98849312e-01, 9.99308343e-01, 9.99768922e-01,
+ 1.00023113e+00, 1.00069214e+00, 1.00115201e+00, 1.00160853e+00,
+ 1.00206049e+00, 1.00250721e+00, 1.00294713e+00, 1.00337891e+00,
+ 1.00380137e+00, 1.00421381e+00, 1.00461539e+00, 1.00500462e+00,
+ 1.00538063e+00, 1.00574328e+00, 1.00609151e+00, 1.00642491e+00,
+ 1.00674243e+00, 1.00704432e+00, 1.00733022e+00, 1.00759940e+00,
+ 1.00785206e+00, 1.00808818e+00, 1.00830803e+00, 1.00851125e+00,
+ 1.00869814e+00, 1.00886952e+00, 1.00902566e+00, 1.00916672e+00,
+ 1.00929336e+00, 1.00940640e+00, 1.00950702e+00, 1.00959526e+00,
+ 1.00967215e+00, 1.00973908e+00, 1.00979668e+00, 1.00984614e+00,
+ 1.00988808e+00, 1.00992409e+00, 1.00995538e+00, 1.00998227e+00,
+ 1.01000630e+00, 1.01002862e+00, 1.01005025e+00, 1.01007195e+00,
+ 1.01009437e+00, 1.01011892e+00, 1.01014650e+00, 1.01017711e+00,
+ 1.01021176e+00, 1.01025100e+00, 1.01029547e+00, 1.01034523e+00,
+ 1.01040032e+00, 1.01046156e+00, 1.01052862e+00, 1.01060152e+00,
+ 1.01067979e+00, 1.01076391e+00, 1.01085343e+00, 1.01094755e+00,
+ 1.01104595e+00, 1.01114849e+00, 1.01125440e+00, 1.01136308e+00,
+ 1.01147330e+00, 1.01158500e+00, 1.01169742e+00, 1.01180892e+00,
+ 1.01191926e+00, 1.01202724e+00, 1.01213215e+00, 1.01223273e+00,
+ 1.01232756e+00, 1.01241638e+00, 1.01249789e+00, 1.01257043e+00,
+ 1.01263330e+00, 1.01268528e+00, 1.01272556e+00, 1.01275258e+00,
+ 1.01276506e+00, 1.01276236e+00, 1.01274338e+00, 1.01270648e+00,
+ 1.01265084e+00, 1.01257543e+00, 1.01247947e+00, 1.01236111e+00,
+ 1.01221981e+00, 1.01205436e+00, 1.01186400e+00, 1.01164722e+00,
+ 1.01140252e+00, 1.01112965e+00, 1.01082695e+00, 1.01049292e+00,
+ 1.01012635e+00, 1.00972589e+00, 1.00929006e+00, 1.00881730e+00,
+ 1.00830503e+00, 1.00775283e+00, 1.00715783e+00, 1.00651805e+00,
+ 1.00583140e+00, 1.00509559e+00, 1.00430863e+00, 1.00346750e+00,
+ 1.00256950e+00, 1.00161271e+00, 1.00059427e+00, 9.99511170e-01,
+ 9.98360922e-01, 9.97140929e-01, 9.95848886e-01, 9.94481854e-01,
+ 9.93037528e-01, 9.91514656e-01, 9.89913680e-01, 9.88193062e-01,
+ 9.85942259e-01, 9.83566790e-01, 9.81142303e-01, 9.78521444e-01,
+ 9.75663604e-01, 9.72545344e-01, 9.69145663e-01, 9.65440618e-01,
+ 9.61404362e-01, 9.57011307e-01, 9.52236767e-01, 9.47054884e-01,
+ 9.41440374e-01, 9.35369161e-01, 9.28819009e-01, 9.21766289e-01,
+ 9.14189628e-01, 9.06069468e-01, 8.97389168e-01, 8.88133200e-01,
+ 8.78289389e-01, 8.67846957e-01, 8.56797064e-01, 8.45133465e-01,
+ 8.32854281e-01, 8.19959478e-01, 8.06451101e-01, 7.92334648e-01,
+ 7.77620449e-01, 7.62320618e-01, 7.46448649e-01, 7.30020573e-01,
+ 7.13056738e-01, 6.95580544e-01, 6.77617323e-01, 6.59195531e-01,
+ 6.40348643e-01, 6.21107220e-01, 6.01504928e-01, 5.81578761e-01,
+ 5.61367451e-01, 5.40918863e-01, 5.20273683e-01, 4.99478073e-01,
+ 4.78577418e-01, 4.57617260e-01, 4.36649021e-01, 4.15722146e-01,
+ 3.94885659e-01, 3.74190319e-01, 3.53686890e-01, 3.33426002e-01,
+ 3.13458647e-01, 2.93833790e-01, 2.74599264e-01, 2.55803064e-01,
+ 2.37490219e-01, 2.19703603e-01, 2.02485542e-01, 1.85874992e-01,
+ 1.69906780e-01, 1.54613227e-01, 1.40023821e-01, 1.26163740e-01,
+ 1.13053443e-01, 1.00708497e-01, 8.91402439e-02, 7.83561210e-02,
+ 6.83582123e-02, 5.91421154e-02, 5.06989301e-02, 4.30171776e-02,
+ 3.60802073e-02, 2.98631634e-02, 2.43372266e-02, 1.94767524e-02,
+ 1.52571017e-02, 1.16378749e-02, 8.43308778e-03, 4.44966900e-03,
+};
+
+static const float mdct_win_10m_480[480+300] = {
+ -2.35303215e-04, -4.61989875e-04, -6.26293154e-04, -7.92918043e-04,
+ -9.74716672e-04, -1.18025689e-03, -1.40920904e-03, -1.66447310e-03,
+ -1.94659161e-03, -2.25708173e-03, -2.59710692e-03, -2.96760762e-03,
+ -3.37045488e-03, -3.80628516e-03, -4.27687377e-03, -4.78246990e-03,
+ -5.32460872e-03, -5.90340381e-03, -6.52041973e-03, -7.17588528e-03,
+ -7.87142282e-03, -8.60658604e-03, -9.38248086e-03, -1.01982718e-02,
+ -1.10552055e-02, -1.19527030e-02, -1.28920591e-02, -1.38726348e-02,
+ -1.48952816e-02, -1.59585662e-02, -1.70628856e-02, -1.82066640e-02,
+ -1.93906598e-02, -2.06135542e-02, -2.18757093e-02, -2.31752632e-02,
+ -2.45122745e-02, -2.58847194e-02, -2.72926374e-02, -2.87339090e-02,
+ -3.02086274e-02, -3.17144037e-02, -3.32509886e-02, -3.48159779e-02,
+ -3.64089241e-02, -3.80274232e-02, -3.96706799e-02, -4.13357542e-02,
+ -4.30220337e-02, -4.47269805e-02, -4.64502229e-02, -4.81889149e-02,
+ -4.99422586e-02, -5.17069080e-02, -5.34816204e-02, -5.52633479e-02,
+ -5.70512315e-02, -5.88427175e-02, -6.06371724e-02, -6.24310403e-02,
+ -6.42230355e-02, -6.60096152e-02, -6.77896227e-02, -6.95599687e-02,
+ -7.13196627e-02, -7.30658127e-02, -7.47975891e-02, -7.65117823e-02,
+ -7.82071142e-02, -7.98801069e-02, -8.15296401e-02, -8.31523735e-02,
+ -8.47472895e-02, -8.63113754e-02, -8.78437445e-02, -8.93416436e-02,
+ -9.08041129e-02, -9.22279576e-02, -9.36123287e-02, -9.49537776e-02,
+ -9.62515531e-02, -9.75028462e-02, -9.87073651e-02, -9.98627129e-02,
+ -1.00968022e-01, -1.02020268e-01, -1.03018380e-01, -1.03959636e-01,
+ -1.04843883e-01, -1.05668684e-01, -1.06434282e-01, -1.07138231e-01,
+ -1.07779996e-01, -1.08357063e-01, -1.08869014e-01, -1.09313559e-01,
+ -1.09690356e-01, -1.09996966e-01, -1.10233226e-01, -1.10397281e-01,
+ -1.10489847e-01, -1.10508642e-01, -1.10453743e-01, -1.10322584e-01,
+ -1.10114583e-01, -1.09827693e-01, -1.09462175e-01, -1.09016396e-01,
+ -1.08490885e-01, -1.07883429e-01, -1.07193718e-01, -1.06419636e-01,
+ -1.05561251e-01, -1.04616281e-01, -1.03584904e-01, -1.02465016e-01,
+ -1.01256900e-01, -9.99586457e-02, -9.85701457e-02, -9.70891114e-02,
+ -9.55154582e-02, -9.38468492e-02, -9.20830006e-02, -9.02217102e-02,
+ -8.82630999e-02, -8.62049382e-02, -8.40474215e-02, -8.17879272e-02,
+ -7.94262503e-02, -7.69598078e-02, -7.43878560e-02, -7.17079700e-02,
+ -6.89199478e-02, -6.60218980e-02, -6.30134942e-02, -5.98919191e-02,
+ -5.66565564e-02, -5.33040616e-02, -4.98342724e-02, -4.62445689e-02,
+ -4.25345569e-02, -3.87019577e-02, -3.47458578e-02, -3.06634152e-02,
+ -2.64542508e-02, -2.21158161e-02, -1.76474054e-02, -1.30458136e-02,
+ -8.31042570e-03, -3.43826866e-03, 1.57031548e-03, 6.71769764e-03,
+ 1.20047702e-02, 1.74339832e-02, 2.30064206e-02, 2.87248142e-02,
+ 3.45889635e-02, 4.06010646e-02, 4.67610292e-02, 5.30713391e-02,
+ 5.95323909e-02, 6.61464781e-02, 7.29129318e-02, 7.98335419e-02,
+ 8.69080741e-02, 9.41381377e-02, 1.01523314e-01, 1.09065152e-01,
+ 1.16762655e-01, 1.24617139e-01, 1.32627295e-01, 1.40793819e-01,
+ 1.49115252e-01, 1.57592141e-01, 1.66222480e-01, 1.75006740e-01,
+ 1.83943194e-01, 1.93031818e-01, 2.02269985e-01, 2.11656743e-01,
+ 2.21188852e-01, 2.30865538e-01, 2.40683799e-01, 2.50642064e-01,
+ 2.60736512e-01, 2.70965907e-01, 2.81325902e-01, 2.91814469e-01,
+ 3.02427028e-01, 3.13160350e-01, 3.24009570e-01, 3.34971959e-01,
+ 3.46042294e-01, 3.57217518e-01, 3.68491565e-01, 3.79859512e-01,
+ 3.91314689e-01, 4.02853287e-01, 4.14468833e-01, 4.26157164e-01,
+ 4.37911390e-01, 4.49725632e-01, 4.61592545e-01, 4.73506703e-01,
+ 4.85460018e-01, 4.97447159e-01, 5.09459723e-01, 5.21490984e-01,
+ 5.33532682e-01, 5.45578981e-01, 5.57621716e-01, 5.69654673e-01,
+ 5.81668558e-01, 5.93656062e-01, 6.05608382e-01, 6.17519206e-01,
+ 6.29379661e-01, 6.41183084e-01, 6.52920354e-01, 6.64584079e-01,
+ 6.76165350e-01, 6.87657395e-01, 6.99051154e-01, 7.10340055e-01,
+ 7.21514933e-01, 7.32569177e-01, 7.43494372e-01, 7.54284633e-01,
+ 7.64931365e-01, 7.75428189e-01, 7.85767017e-01, 7.95941465e-01,
+ 8.05943723e-01, 8.15768707e-01, 8.25408622e-01, 8.34858937e-01,
+ 8.44112583e-01, 8.53165119e-01, 8.62010834e-01, 8.70645634e-01,
+ 8.79063156e-01, 8.87259971e-01, 8.95231329e-01, 9.02975168e-01,
+ 9.10486312e-01, 9.17762555e-01, 9.24799743e-01, 9.31596250e-01,
+ 9.38149486e-01, 9.44458839e-01, 9.50522086e-01, 9.56340292e-01,
+ 9.61911452e-01, 9.67236671e-01, 9.72315664e-01, 9.77150119e-01,
+ 9.81739750e-01, 9.86086587e-01, 9.90190638e-01, 9.94055718e-01,
+ 9.97684240e-01, 1.00108096e+00, 1.00424751e+00, 1.00718858e+00,
+ 1.00990665e+00, 1.01240743e+00, 1.01469470e+00, 1.01677466e+00,
+ 1.01865099e+00, 1.02033046e+00, 1.02181733e+00, 1.02311884e+00,
+ 1.02424026e+00, 1.02518972e+00, 1.02597245e+00, 1.02659694e+00,
+ 1.02706918e+00, 1.02739752e+00, 1.02758790e+00, 1.02764895e+00,
+ 1.02758583e+00, 1.02740852e+00, 1.02712299e+00, 1.02673867e+00,
+ 1.02626166e+00, 1.02570100e+00, 1.02506178e+00, 1.02435398e+00,
+ 1.02358239e+00, 1.02275651e+00, 1.02188060e+00, 1.02096387e+00,
+ 1.02000914e+00, 1.01902729e+00, 1.01801944e+00, 1.01699650e+00,
+ 1.01595743e+00, 1.01492344e+00, 1.01391595e+00, 1.01304757e+00,
+ 1.01221613e+00, 1.01104487e+00, 1.00991459e+00, 1.00882489e+00,
+ 1.00777386e+00, 1.00676170e+00, 1.00578665e+00, 1.00484875e+00,
+ 1.00394608e+00, 1.00307885e+00, 1.00224501e+00, 1.00144473e+00,
+ 1.00067619e+00, 9.99939317e-01, 9.99232085e-01, 9.98554813e-01,
+ 9.97905542e-01, 9.97284268e-01, 9.96689095e-01, 9.96120338e-01,
+ 9.95576126e-01, 9.95056572e-01, 9.94559753e-01, 9.94086038e-01,
+ 9.93633779e-01, 9.93203161e-01, 9.92792187e-01, 9.92401518e-01,
+ 9.92029727e-01, 9.91676778e-01, 9.91340877e-01, 9.91023065e-01,
+ 9.90721643e-01, 9.90436680e-01, 9.90166895e-01, 9.89913101e-01,
+ 9.89673564e-01, 9.89448837e-01, 9.89237484e-01, 9.89040193e-01,
+ 9.88855636e-01, 9.88684347e-01, 9.88524761e-01, 9.88377852e-01,
+ 9.88242327e-01, 9.88118564e-01, 9.88005163e-01, 9.87903202e-01,
+ 9.87811174e-01, 9.87729546e-01, 9.87657198e-01, 9.87594984e-01,
+ 9.87541274e-01, 9.87496906e-01, 9.87460625e-01, 9.87432981e-01,
+ 9.87412641e-01, 9.87400475e-01, 9.87394992e-01, 9.87396916e-01,
+ 9.87404906e-01, 9.87419705e-01, 9.87439972e-01, 9.87466328e-01,
+ 9.87497321e-01, 9.87533893e-01, 9.87574654e-01, 9.87620124e-01,
+ 9.87668980e-01, 9.87722156e-01, 9.87778192e-01, 9.87837649e-01,
+ 9.87899199e-01, 9.87963798e-01, 9.88030030e-01, 9.88098468e-01,
+ 9.88167801e-01, 9.88239030e-01, 9.88310769e-01, 9.88383520e-01,
+ 9.88456016e-01, 9.88529420e-01, 9.88602222e-01, 9.88674940e-01,
+ 9.88746626e-01, 9.88818277e-01, 9.88888248e-01, 9.88957438e-01,
+ 9.89024798e-01, 9.89091125e-01, 9.89155170e-01, 9.89217866e-01,
+ 9.89277956e-01, 9.89336519e-01, 9.89392368e-01, 9.89446283e-01,
+ 9.89497212e-01, 9.89546334e-01, 9.89592362e-01, 9.89636265e-01,
+ 9.89677201e-01, 9.89716220e-01, 9.89752029e-01, 9.89785920e-01,
+ 9.89817027e-01, 9.89846207e-01, 9.89872536e-01, 9.89897514e-01,
+ 9.89920005e-01, 9.89941079e-01, 9.89960061e-01, 9.89978226e-01,
+ 9.89994556e-01, 9.90010350e-01, 9.90024832e-01, 9.90039402e-01,
+ 9.90053211e-01, 9.90067475e-01, 9.90081472e-01, 9.90096693e-01,
+ 9.90112245e-01, 9.90129379e-01, 9.90147465e-01, 9.90168060e-01,
+ 9.90190227e-01, 9.90215190e-01, 9.90242442e-01, 9.90273445e-01,
+ 9.90307127e-01, 9.90344891e-01, 9.90386228e-01, 9.90432448e-01,
+ 9.90482565e-01, 9.90537983e-01, 9.90598060e-01, 9.90664037e-01,
+ 9.90734883e-01, 9.90812038e-01, 9.90894786e-01, 9.90984259e-01,
+ 9.91079525e-01, 9.91181924e-01, 9.91290512e-01, 9.91406471e-01,
+ 9.91528801e-01, 9.91658694e-01, 9.91795272e-01, 9.91939622e-01,
+ 9.92090615e-01, 9.92249503e-01, 9.92415240e-01, 9.92588721e-01,
+ 9.92768871e-01, 9.92956911e-01, 9.93151653e-01, 9.93353924e-01,
+ 9.93562689e-01, 9.93779087e-01, 9.94001643e-01, 9.94231202e-01,
+ 9.94466818e-01, 9.94709344e-01, 9.94957285e-01, 9.95211663e-01,
+ 9.95471264e-01, 9.95736795e-01, 9.96006862e-01, 9.96282303e-01,
+ 9.96561799e-01, 9.96846133e-01, 9.97133827e-01, 9.97425669e-01,
+ 9.97720337e-01, 9.98018509e-01, 9.98318587e-01, 9.98621352e-01,
+ 9.98925543e-01, 9.99231731e-01, 9.99538258e-01, 9.99846116e-01,
+ 1.00015391e+00, 1.00046196e+00, 1.00076886e+00, 1.00107561e+00,
+ 1.00138055e+00, 1.00168424e+00, 1.00198543e+00, 1.00228487e+00,
+ 1.00258098e+00, 1.00287441e+00, 1.00316385e+00, 1.00345006e+00,
+ 1.00373157e+00, 1.00400915e+00, 1.00428146e+00, 1.00454934e+00,
+ 1.00481138e+00, 1.00506827e+00, 1.00531880e+00, 1.00556397e+00,
+ 1.00580227e+00, 1.00603455e+00, 1.00625986e+00, 1.00647902e+00,
+ 1.00669054e+00, 1.00689557e+00, 1.00709305e+00, 1.00728380e+00,
+ 1.00746662e+00, 1.00764273e+00, 1.00781104e+00, 1.00797244e+00,
+ 1.00812588e+00, 1.00827260e+00, 1.00841147e+00, 1.00854357e+00,
+ 1.00866802e+00, 1.00878601e+00, 1.00889653e+00, 1.00900077e+00,
+ 1.00909776e+00, 1.00918888e+00, 1.00927316e+00, 1.00935176e+00,
+ 1.00942394e+00, 1.00949118e+00, 1.00955240e+00, 1.00960889e+00,
+ 1.00965997e+00, 1.00970709e+00, 1.00974924e+00, 1.00978774e+00,
+ 1.00982209e+00, 1.00985371e+00, 1.00988150e+00, 1.00990696e+00,
+ 1.00992957e+00, 1.00995057e+00, 1.00996902e+00, 1.00998650e+00,
+ 1.01000236e+00, 1.01001789e+00, 1.01003217e+00, 1.01004672e+00,
+ 1.01006081e+00, 1.01007567e+00, 1.01009045e+00, 1.01010656e+00,
+ 1.01012323e+00, 1.01014176e+00, 1.01016113e+00, 1.01018264e+00,
+ 1.01020559e+00, 1.01023108e+00, 1.01025795e+00, 1.01028773e+00,
+ 1.01031948e+00, 1.01035408e+00, 1.01039064e+00, 1.01043047e+00,
+ 1.01047227e+00, 1.01051710e+00, 1.01056410e+00, 1.01061427e+00,
+ 1.01066629e+00, 1.01072136e+00, 1.01077842e+00, 1.01083825e+00,
+ 1.01089966e+00, 1.01096373e+00, 1.01102919e+00, 1.01109699e+00,
+ 1.01116586e+00, 1.01123661e+00, 1.01130817e+00, 1.01138145e+00,
+ 1.01145479e+00, 1.01152919e+00, 1.01160368e+00, 1.01167880e+00,
+ 1.01175301e+00, 1.01182748e+00, 1.01190094e+00, 1.01197388e+00,
+ 1.01204489e+00, 1.01211499e+00, 1.01218284e+00, 1.01224902e+00,
+ 1.01231210e+00, 1.01237303e+00, 1.01243046e+00, 1.01248497e+00,
+ 1.01253506e+00, 1.01258168e+00, 1.01262347e+00, 1.01266098e+00,
+ 1.01269276e+00, 1.01271979e+00, 1.01274058e+00, 1.01275575e+00,
+ 1.01276395e+00, 1.01276592e+00, 1.01276030e+00, 1.01274782e+00,
+ 1.01272696e+00, 1.01269861e+00, 1.01266140e+00, 1.01261590e+00,
+ 1.01256083e+00, 1.01249705e+00, 1.01242289e+00, 1.01233923e+00,
+ 1.01224492e+00, 1.01214046e+00, 1.01202430e+00, 1.01189756e+00,
+ 1.01175881e+00, 1.01160845e+00, 1.01144516e+00, 1.01126996e+00,
+ 1.01108126e+00, 1.01087961e+00, 1.01066368e+00, 1.01043418e+00,
+ 1.01018968e+00, 1.00993075e+00, 1.00965566e+00, 1.00936525e+00,
+ 1.00905825e+00, 1.00873476e+00, 1.00839308e+00, 1.00803431e+00,
+ 1.00765666e+00, 1.00726014e+00, 1.00684335e+00, 1.00640701e+00,
+ 1.00594915e+00, 1.00547001e+00, 1.00496799e+00, 1.00444353e+00,
+ 1.00389477e+00, 1.00332190e+00, 1.00272313e+00, 1.00209885e+00,
+ 1.00144728e+00, 1.00076851e+00, 1.00006069e+00, 9.99324268e-01,
+ 9.98557350e-01, 9.97760020e-01, 9.96930604e-01, 9.96069427e-01,
+ 9.95174643e-01, 9.94246644e-01, 9.93283713e-01, 9.92286108e-01,
+ 9.91252309e-01, 9.90182742e-01, 9.89075787e-01, 9.87931302e-01,
+ 9.86355322e-01, 9.84736245e-01, 9.83175095e-01, 9.81558334e-01,
+ 9.79861353e-01, 9.78061749e-01, 9.76157432e-01, 9.74137862e-01,
+ 9.71999011e-01, 9.69732741e-01, 9.67333198e-01, 9.64791512e-01,
+ 9.62101150e-01, 9.59253976e-01, 9.56242718e-01, 9.53060091e-01,
+ 9.49698408e-01, 9.46149812e-01, 9.42407161e-01, 9.38463416e-01,
+ 9.34311297e-01, 9.29944987e-01, 9.25356797e-01, 9.20540463e-01,
+ 9.15489628e-01, 9.10198679e-01, 9.04662060e-01, 8.98875519e-01,
+ 8.92833832e-01, 8.86533719e-01, 8.79971272e-01, 8.73143784e-01,
+ 8.66047653e-01, 8.58681252e-01, 8.51042044e-01, 8.43129723e-01,
+ 8.34943514e-01, 8.26483991e-01, 8.17750537e-01, 8.08744982e-01,
+ 7.99468149e-01, 7.89923516e-01, 7.80113773e-01, 7.70043128e-01,
+ 7.59714574e-01, 7.49133097e-01, 7.38302860e-01, 7.27229876e-01,
+ 7.15920192e-01, 7.04381434e-01, 6.92619693e-01, 6.80643883e-01,
+ 6.68461648e-01, 6.56083014e-01, 6.43517927e-01, 6.30775533e-01,
+ 6.17864165e-01, 6.04795463e-01, 5.91579959e-01, 5.78228937e-01,
+ 5.64753589e-01, 5.51170316e-01, 5.37490509e-01, 5.23726350e-01,
+ 5.09891542e-01, 4.96000807e-01, 4.82066294e-01, 4.68101711e-01,
+ 4.54121700e-01, 4.40142182e-01, 4.26177297e-01, 4.12241789e-01,
+ 3.98349961e-01, 3.84517234e-01, 3.70758372e-01, 3.57088679e-01,
+ 3.43522867e-01, 3.30076376e-01, 3.16764033e-01, 3.03600465e-01,
+ 2.90599616e-01, 2.77775850e-01, 2.65143468e-01, 2.52716188e-01,
+ 2.40506985e-01, 2.28528397e-01, 2.16793343e-01, 2.05313990e-01,
+ 1.94102191e-01, 1.83168087e-01, 1.72522195e-01, 1.62173542e-01,
+ 1.52132068e-01, 1.42405280e-01, 1.33001524e-01, 1.23926066e-01,
+ 1.15185830e-01, 1.06784043e-01, 9.87263751e-02, 9.10137900e-02,
+ 8.36505724e-02, 7.66350831e-02, 6.99703341e-02, 6.36518811e-02,
+ 5.76817602e-02, 5.20524422e-02, 4.67653841e-02, 4.18095054e-02,
+ 3.71864025e-02, 3.28807275e-02, 2.88954850e-02, 2.52098057e-02,
+ 2.18305756e-02, 1.87289619e-02, 1.59212782e-02, 1.33638143e-02,
+ 1.10855888e-02, 8.94347419e-03, 6.75812489e-03, 3.50443813e-03,
+};
+
+static const float mdct_win_7m5_60[60+46] = {
+ 2.95060859e-03, 7.17541132e-03, 1.37695374e-02, 2.30953556e-02,
+ 3.54036230e-02, 5.08289304e-02, 6.94696293e-02, 9.13884278e-02,
+ 1.16604575e-01, 1.45073546e-01, 1.76711174e-01, 2.11342953e-01,
+ 2.48768614e-01, 2.88701102e-01, 3.30823871e-01, 3.74814544e-01,
+ 4.20308013e-01, 4.66904918e-01, 5.14185341e-01, 5.61710041e-01,
+ 6.09026346e-01, 6.55671016e-01, 7.01218384e-01, 7.45240679e-01,
+ 7.87369206e-01, 8.27223833e-01, 8.64513675e-01, 8.98977415e-01,
+ 9.30407518e-01, 9.58599937e-01, 9.83447719e-01, 1.00488283e+00,
+ 1.02285381e+00, 1.03740495e+00, 1.04859791e+00, 1.05656184e+00,
+ 1.06149371e+00, 1.06362578e+00, 1.06325973e+00, 1.06074505e+00,
+ 1.05643590e+00, 1.05069500e+00, 1.04392435e+00, 1.03647725e+00,
+ 1.02872867e+00, 1.02106486e+00, 1.01400658e+00, 1.00727455e+00,
+ 1.00172250e+00, 9.97309592e-01, 9.93985158e-01, 9.91683335e-01,
+ 9.90325325e-01, 9.89822613e-01, 9.90074734e-01, 9.90975314e-01,
+ 9.92412851e-01, 9.94273149e-01, 9.96439157e-01, 9.98791616e-01,
+ 1.00120985e+00, 1.00357357e+00, 1.00575984e+00, 1.00764515e+00,
+ 1.00910687e+00, 1.01002476e+00, 1.01028203e+00, 1.00976919e+00,
+ 1.00838641e+00, 1.00605124e+00, 1.00269767e+00, 9.98280464e-01,
+ 9.92777987e-01, 9.86186892e-01, 9.77634164e-01, 9.67447270e-01,
+ 9.55129725e-01, 9.40389877e-01, 9.22959280e-01, 9.02607350e-01,
+ 8.79202689e-01, 8.52641750e-01, 8.22881272e-01, 7.89971715e-01,
+ 7.54030328e-01, 7.15255742e-01, 6.73936911e-01, 6.30414716e-01,
+ 5.85078858e-01, 5.38398518e-01, 4.90833753e-01, 4.42885823e-01,
+ 3.95091024e-01, 3.48004343e-01, 3.02196710e-01, 2.58227431e-01,
+ 2.16641416e-01, 1.77922122e-01, 1.42480547e-01, 1.10652194e-01,
+ 8.26995967e-02, 5.88334516e-02, 3.92030848e-02, 2.38629107e-02,
+ 1.26976223e-02, 5.35665361e-03,
+};
+
+static const float mdct_win_7m5_120[120+92] = {
+ 2.20824874e-03, 3.81014420e-03, 5.91552473e-03, 8.58361457e-03,
+ 1.18759723e-02, 1.58335301e-02, 2.04918652e-02, 2.58883593e-02,
+ 3.20415894e-02, 3.89616721e-02, 4.66742169e-02, 5.51849337e-02,
+ 6.45038384e-02, 7.46411071e-02, 8.56000162e-02, 9.73846703e-02,
+ 1.09993603e-01, 1.23419277e-01, 1.37655457e-01, 1.52690437e-01,
+ 1.68513363e-01, 1.85093105e-01, 2.02410419e-01, 2.20450365e-01,
+ 2.39167941e-01, 2.58526168e-01, 2.78498539e-01, 2.99038432e-01,
+ 3.20104862e-01, 3.41658622e-01, 3.63660034e-01, 3.86062695e-01,
+ 4.08815272e-01, 4.31871046e-01, 4.55176988e-01, 4.78676593e-01,
+ 5.02324813e-01, 5.26060916e-01, 5.49831283e-01, 5.73576883e-01,
+ 5.97241338e-01, 6.20770242e-01, 6.44099662e-01, 6.67176382e-01,
+ 6.89958854e-01, 7.12379980e-01, 7.34396372e-01, 7.55966688e-01,
+ 7.77036981e-01, 7.97558114e-01, 8.17490856e-01, 8.36796950e-01,
+ 8.55447310e-01, 8.73400798e-01, 8.90635719e-01, 9.07128770e-01,
+ 9.22848784e-01, 9.37763323e-01, 9.51860206e-01, 9.65130600e-01,
+ 9.77556541e-01, 9.89126209e-01, 9.99846919e-01, 1.00970073e+00,
+ 1.01868229e+00, 1.02681455e+00, 1.03408981e+00, 1.04051196e+00,
+ 1.04610837e+00, 1.05088565e+00, 1.05486289e+00, 1.05807221e+00,
+ 1.06053414e+00, 1.06227662e+00, 1.06333815e+00, 1.06375557e+00,
+ 1.06356632e+00, 1.06282156e+00, 1.06155996e+00, 1.05981709e+00,
+ 1.05765876e+00, 1.05512006e+00, 1.05223985e+00, 1.04908779e+00,
+ 1.04569860e+00, 1.04210831e+00, 1.03838099e+00, 1.03455276e+00,
+ 1.03067200e+00, 1.02679167e+00, 1.02295558e+00, 1.01920733e+00,
+ 1.01587289e+00, 1.01221017e+00, 1.00884559e+00, 1.00577851e+00,
+ 1.00300262e+00, 1.00051460e+00, 9.98309229e-01, 9.96378601e-01,
+ 9.94718132e-01, 9.93316216e-01, 9.92166957e-01, 9.91258603e-01,
+ 9.90581104e-01, 9.90123118e-01, 9.89873712e-01, 9.89818707e-01,
+ 9.89946800e-01, 9.90243175e-01, 9.90695564e-01, 9.91288540e-01,
+ 9.92009469e-01, 9.92842693e-01, 9.93775067e-01, 9.94790398e-01,
+ 9.95875534e-01, 9.97014367e-01, 9.98192871e-01, 9.99394506e-01,
+ 1.00060586e+00, 1.00181040e+00, 1.00299457e+00, 1.00414155e+00,
+ 1.00523688e+00, 1.00626393e+00, 1.00720890e+00, 1.00805489e+00,
+ 1.00878802e+00, 1.00939182e+00, 1.00985296e+00, 1.01015529e+00,
+ 1.01028602e+00, 1.01022988e+00, 1.00997541e+00, 1.00950846e+00,
+ 1.00881848e+00, 1.00789488e+00, 1.00672876e+00, 1.00530991e+00,
+ 1.00363456e+00, 1.00169363e+00, 9.99485663e-01, 9.97006370e-01,
+ 9.94254687e-01, 9.91231967e-01, 9.87937115e-01, 9.84375125e-01,
+ 9.79890963e-01, 9.75269879e-01, 9.70180498e-01, 9.64580027e-01,
+ 9.58425534e-01, 9.51684014e-01, 9.44320232e-01, 9.36290624e-01,
+ 9.27580507e-01, 9.18153414e-01, 9.07976524e-01, 8.97050058e-01,
+ 8.85351360e-01, 8.72857927e-01, 8.59579819e-01, 8.45502615e-01,
+ 8.30619943e-01, 8.14946648e-01, 7.98489378e-01, 7.81262450e-01,
+ 7.63291769e-01, 7.44590843e-01, 7.25199287e-01, 7.05153668e-01,
+ 6.84490545e-01, 6.63245210e-01, 6.41477162e-01, 6.19235334e-01,
+ 5.96559133e-01, 5.73519989e-01, 5.50173851e-01, 5.26568538e-01,
+ 5.02781159e-01, 4.78860889e-01, 4.54877894e-01, 4.30898123e-01,
+ 4.06993964e-01, 3.83234031e-01, 3.59680098e-01, 3.36408100e-01,
+ 3.13496418e-01, 2.91010565e-01, 2.69019585e-01, 2.47584348e-01,
+ 2.26788433e-01, 2.06677771e-01, 1.87310343e-01, 1.68739644e-01,
+ 1.51012382e-01, 1.34171842e-01, 1.18254662e-01, 1.03290734e-01,
+ 8.93117360e-02, 7.63429787e-02, 6.44077291e-02, 5.35243715e-02,
+ 4.37084453e-02, 3.49667099e-02, 2.72984629e-02, 2.06895808e-02,
+ 1.51125125e-02, 1.05228754e-02, 6.85547314e-03, 4.02351119e-03,
+};
+
+static const float mdct_win_7m5_180[180+138] = {
+ 1.97084908e-03, 2.95060859e-03, 4.12447721e-03, 5.52688664e-03,
+ 7.17541132e-03, 9.08757730e-03, 1.12819105e-02, 1.37695374e-02,
+ 1.65600266e-02, 1.96650895e-02, 2.30953556e-02, 2.68612894e-02,
+ 3.09632560e-02, 3.54036230e-02, 4.01915610e-02, 4.53331403e-02,
+ 5.08289304e-02, 5.66815448e-02, 6.28935304e-02, 6.94696293e-02,
+ 7.64106314e-02, 8.37160016e-02, 9.13884278e-02, 9.94294008e-02,
+ 1.07834725e-01, 1.16604575e-01, 1.25736503e-01, 1.35226811e-01,
+ 1.45073546e-01, 1.55273819e-01, 1.65822194e-01, 1.76711174e-01,
+ 1.87928776e-01, 1.99473180e-01, 2.11342953e-01, 2.23524554e-01,
+ 2.36003100e-01, 2.48768614e-01, 2.61813811e-01, 2.75129161e-01,
+ 2.88701102e-01, 3.02514034e-01, 3.16558805e-01, 3.30823871e-01,
+ 3.45295567e-01, 3.59963992e-01, 3.74814544e-01, 3.89831817e-01,
+ 4.05001010e-01, 4.20308013e-01, 4.35739515e-01, 4.51277817e-01,
+ 4.66904918e-01, 4.82609041e-01, 4.98375466e-01, 5.14185341e-01,
+ 5.30021478e-01, 5.45869352e-01, 5.61710041e-01, 5.77528151e-01,
+ 5.93304696e-01, 6.09026346e-01, 6.24674189e-01, 6.40227555e-01,
+ 6.55671016e-01, 6.70995935e-01, 6.86184559e-01, 7.01218384e-01,
+ 7.16078449e-01, 7.30756084e-01, 7.45240679e-01, 7.59515122e-01,
+ 7.73561955e-01, 7.87369206e-01, 8.00923138e-01, 8.14211386e-01,
+ 8.27223833e-01, 8.39952374e-01, 8.52386102e-01, 8.64513675e-01,
+ 8.76324079e-01, 8.87814288e-01, 8.98977415e-01, 9.09803319e-01,
+ 9.20284312e-01, 9.30407518e-01, 9.40169652e-01, 9.49567795e-01,
+ 9.58599937e-01, 9.67260260e-01, 9.75545166e-01, 9.83447719e-01,
+ 9.90971957e-01, 9.98119269e-01, 1.00488283e+00, 1.01125773e+00,
+ 1.01724436e+00, 1.02285381e+00, 1.02808734e+00, 1.03293706e+00,
+ 1.03740495e+00, 1.04150164e+00, 1.04523236e+00, 1.04859791e+00,
+ 1.05160340e+00, 1.05425505e+00, 1.05656184e+00, 1.05853400e+00,
+ 1.06017414e+00, 1.06149371e+00, 1.06249943e+00, 1.06320577e+00,
+ 1.06362578e+00, 1.06376487e+00, 1.06363778e+00, 1.06325973e+00,
+ 1.06264695e+00, 1.06180496e+00, 1.06074505e+00, 1.05948492e+00,
+ 1.05804533e+00, 1.05643590e+00, 1.05466218e+00, 1.05274047e+00,
+ 1.05069500e+00, 1.04853894e+00, 1.04627898e+00, 1.04392435e+00,
+ 1.04149540e+00, 1.03901003e+00, 1.03647725e+00, 1.03390793e+00,
+ 1.03131989e+00, 1.02872867e+00, 1.02614832e+00, 1.02358988e+00,
+ 1.02106486e+00, 1.01856262e+00, 1.01655770e+00, 1.01400658e+00,
+ 1.01162953e+00, 1.00938590e+00, 1.00727455e+00, 1.00529616e+00,
+ 1.00344526e+00, 1.00172250e+00, 1.00012792e+00, 9.98657533e-01,
+ 9.97309592e-01, 9.96083571e-01, 9.94976569e-01, 9.93985158e-01,
+ 9.93107530e-01, 9.92341305e-01, 9.91683335e-01, 9.91130070e-01,
+ 9.90678325e-01, 9.90325325e-01, 9.90067562e-01, 9.89901282e-01,
+ 9.89822613e-01, 9.89827845e-01, 9.89913241e-01, 9.90074734e-01,
+ 9.90308256e-01, 9.90609852e-01, 9.90975314e-01, 9.91400330e-01,
+ 9.91880966e-01, 9.92412851e-01, 9.92991779e-01, 9.93613381e-01,
+ 9.94273149e-01, 9.94966958e-01, 9.95690370e-01, 9.96439157e-01,
+ 9.97208572e-01, 9.97994275e-01, 9.98791616e-01, 9.99596062e-01,
+ 1.00040410e+00, 1.00120985e+00, 1.00200976e+00, 1.00279924e+00,
+ 1.00357357e+00, 1.00432828e+00, 1.00505850e+00, 1.00575984e+00,
+ 1.00642767e+00, 1.00705768e+00, 1.00764515e+00, 1.00818549e+00,
+ 1.00867427e+00, 1.00910687e+00, 1.00947916e+00, 1.00978659e+00,
+ 1.01002476e+00, 1.01018954e+00, 1.01027669e+00, 1.01028203e+00,
+ 1.01020174e+00, 1.01003208e+00, 1.00976919e+00, 1.00940939e+00,
+ 1.00894931e+00, 1.00838641e+00, 1.00771780e+00, 1.00694031e+00,
+ 1.00605124e+00, 1.00504879e+00, 1.00393183e+00, 1.00269767e+00,
+ 1.00134427e+00, 9.99872092e-01, 9.98280464e-01, 9.96566569e-01,
+ 9.94731737e-01, 9.92777987e-01, 9.90701374e-01, 9.88504165e-01,
+ 9.86186892e-01, 9.83711989e-01, 9.80584643e-01, 9.77634164e-01,
+ 9.74455033e-01, 9.71062916e-01, 9.67447270e-01, 9.63593926e-01,
+ 9.59491398e-01, 9.55129725e-01, 9.50501326e-01, 9.45592810e-01,
+ 9.40389877e-01, 9.34886760e-01, 9.29080559e-01, 9.22959280e-01,
+ 9.16509579e-01, 9.09724456e-01, 9.02607350e-01, 8.95155084e-01,
+ 8.87356154e-01, 8.79202689e-01, 8.70699698e-01, 8.61847424e-01,
+ 8.52641750e-01, 8.43077833e-01, 8.33154905e-01, 8.22881272e-01,
+ 8.12257597e-01, 8.01285439e-01, 7.89971715e-01, 7.78318177e-01,
+ 7.66337710e-01, 7.54030328e-01, 7.41407991e-01, 7.28477501e-01,
+ 7.15255742e-01, 7.01751739e-01, 6.87975632e-01, 6.73936911e-01,
+ 6.59652573e-01, 6.45139489e-01, 6.30414716e-01, 6.15483622e-01,
+ 6.00365852e-01, 5.85078858e-01, 5.69649536e-01, 5.54084810e-01,
+ 5.38398518e-01, 5.22614738e-01, 5.06756805e-01, 4.90833753e-01,
+ 4.74866033e-01, 4.58876566e-01, 4.42885823e-01, 4.26906539e-01,
+ 4.10970973e-01, 3.95091024e-01, 3.79291327e-01, 3.63587417e-01,
+ 3.48004343e-01, 3.32563201e-01, 3.17287485e-01, 3.02196710e-01,
+ 2.87309403e-01, 2.72643992e-01, 2.58227431e-01, 2.44072856e-01,
+ 2.30208977e-01, 2.16641416e-01, 2.03398481e-01, 1.90486162e-01,
+ 1.77922122e-01, 1.65726674e-01, 1.53906397e-01, 1.42480547e-01,
+ 1.31453980e-01, 1.20841778e-01, 1.10652194e-01, 1.00891734e-01,
+ 9.15718851e-02, 8.26995967e-02, 7.42815529e-02, 6.63242382e-02,
+ 5.88334516e-02, 5.18140676e-02, 4.52698346e-02, 3.92030848e-02,
+ 3.36144159e-02, 2.85023308e-02, 2.38629107e-02, 1.96894227e-02,
+ 1.59720527e-02, 1.26976223e-02, 9.84937739e-03, 7.40724463e-03,
+ 5.35665361e-03, 3.83226552e-03,
+};
+
+static const float mdct_win_7m5_240[240+184] = {
+ 1.84833037e-03, 2.56481839e-03, 3.36762118e-03, 4.28736617e-03,
+ 5.33830143e-03, 6.52679223e-03, 7.86112587e-03, 9.34628179e-03,
+ 1.09916868e-02, 1.28011172e-02, 1.47805911e-02, 1.69307043e-02,
+ 1.92592307e-02, 2.17696937e-02, 2.44685983e-02, 2.73556543e-02,
+ 3.04319230e-02, 3.36980464e-02, 3.71583577e-02, 4.08148180e-02,
+ 4.46708068e-02, 4.87262995e-02, 5.29820633e-02, 5.74382470e-02,
+ 6.20968580e-02, 6.69609767e-02, 7.20298364e-02, 7.73039146e-02,
+ 8.27825574e-02, 8.84682102e-02, 9.43607566e-02, 1.00460272e-01,
+ 1.06763824e-01, 1.13273679e-01, 1.19986420e-01, 1.26903521e-01,
+ 1.34020853e-01, 1.41339557e-01, 1.48857211e-01, 1.56573685e-01,
+ 1.64484622e-01, 1.72589077e-01, 1.80879090e-01, 1.89354320e-01,
+ 1.98012244e-01, 2.06854141e-01, 2.15875319e-01, 2.25068672e-01,
+ 2.34427407e-01, 2.43948314e-01, 2.53627993e-01, 2.63464061e-01,
+ 2.73450494e-01, 2.83582189e-01, 2.93853469e-01, 3.04257373e-01,
+ 3.14790914e-01, 3.25449123e-01, 3.36227410e-01, 3.47118760e-01,
+ 3.58120177e-01, 3.69224663e-01, 3.80427793e-01, 3.91720023e-01,
+ 4.03097022e-01, 4.14551955e-01, 4.26081719e-01, 4.37676318e-01,
+ 4.49330196e-01, 4.61034855e-01, 4.72786043e-01, 4.84576777e-01,
+ 4.96401707e-01, 5.08252458e-01, 5.20122078e-01, 5.32002077e-01,
+ 5.43888090e-01, 5.55771601e-01, 5.67645739e-01, 5.79502786e-01,
+ 5.91335035e-01, 6.03138367e-01, 6.14904172e-01, 6.26623941e-01,
+ 6.38288834e-01, 6.49893375e-01, 6.61432360e-01, 6.72902514e-01,
+ 6.84293750e-01, 6.95600460e-01, 7.06811784e-01, 7.17923425e-01,
+ 7.28931386e-01, 7.39832773e-01, 7.50618982e-01, 7.61284053e-01,
+ 7.71818919e-01, 7.82220992e-01, 7.92481330e-01, 8.02599448e-01,
+ 8.12565230e-01, 8.22377129e-01, 8.32030518e-01, 8.41523208e-01,
+ 8.50848313e-01, 8.60002412e-01, 8.68979881e-01, 8.77778347e-01,
+ 8.86395904e-01, 8.94829421e-01, 9.03077626e-01, 9.11132652e-01,
+ 9.18993585e-01, 9.26652937e-01, 9.34111420e-01, 9.41364344e-01,
+ 9.48412967e-01, 9.55255630e-01, 9.61892013e-01, 9.68316363e-01,
+ 9.74530156e-01, 9.80528338e-01, 9.86313928e-01, 9.91886049e-01,
+ 9.97246345e-01, 1.00239190e+00, 1.00731946e+00, 1.01202707e+00,
+ 1.01651654e+00, 1.02079430e+00, 1.02486082e+00, 1.02871471e+00,
+ 1.03235170e+00, 1.03577375e+00, 1.03898432e+00, 1.04198786e+00,
+ 1.04478564e+00, 1.04737818e+00, 1.04976743e+00, 1.05195405e+00,
+ 1.05394290e+00, 1.05573463e+00, 1.05734177e+00, 1.05875726e+00,
+ 1.05998674e+00, 1.06103672e+00, 1.06190651e+00, 1.06260369e+00,
+ 1.06313289e+00, 1.06350237e+00, 1.06370981e+00, 1.06376322e+00,
+ 1.06366765e+00, 1.06343012e+00, 1.06305656e+00, 1.06255421e+00,
+ 1.06192235e+00, 1.06116702e+00, 1.06029469e+00, 1.05931469e+00,
+ 1.05823465e+00, 1.05705891e+00, 1.05578948e+00, 1.05442979e+00,
+ 1.05298793e+00, 1.05147505e+00, 1.04989930e+00, 1.04826213e+00,
+ 1.04656691e+00, 1.04481699e+00, 1.04302125e+00, 1.04118768e+00,
+ 1.03932339e+00, 1.03743168e+00, 1.03551757e+00, 1.03358511e+00,
+ 1.03164371e+00, 1.02969955e+00, 1.02775944e+00, 1.02582719e+00,
+ 1.02390791e+00, 1.02200805e+00, 1.02013910e+00, 1.01826310e+00,
+ 1.01687901e+00, 1.01492195e+00, 1.01309662e+00, 1.01134205e+00,
+ 1.00965912e+00, 1.00805036e+00, 1.00651754e+00, 1.00505799e+00,
+ 1.00366956e+00, 1.00235327e+00, 1.00110981e+00, 9.99937523e-01,
+ 9.98834524e-01, 9.97800606e-01, 9.96835756e-01, 9.95938881e-01,
+ 9.95108459e-01, 9.94343411e-01, 9.93642921e-01, 9.93005832e-01,
+ 9.92430984e-01, 9.91917493e-01, 9.91463898e-01, 9.91068214e-01,
+ 9.90729218e-01, 9.90446225e-01, 9.90217819e-01, 9.90041963e-01,
+ 9.89917085e-01, 9.89841975e-01, 9.89815048e-01, 9.89834329e-01,
+ 9.89898211e-01, 9.90005403e-01, 9.90154189e-01, 9.90342427e-01,
+ 9.90568459e-01, 9.90830953e-01, 9.91128038e-01, 9.91457566e-01,
+ 9.91817881e-01, 9.92207559e-01, 9.92624757e-01, 9.93067358e-01,
+ 9.93533398e-01, 9.94021410e-01, 9.94529685e-01, 9.95055964e-01,
+ 9.95598351e-01, 9.96155580e-01, 9.96725627e-01, 9.97306092e-01,
+ 9.97895214e-01, 9.98491441e-01, 9.99092890e-01, 9.99697063e-01,
+ 1.00030303e+00, 1.00090793e+00, 1.00151084e+00, 1.00210923e+00,
+ 1.00270118e+00, 1.00328513e+00, 1.00385926e+00, 1.00442111e+00,
+ 1.00496860e+00, 1.00550040e+00, 1.00601455e+00, 1.00650869e+00,
+ 1.00698104e+00, 1.00743004e+00, 1.00785364e+00, 1.00824962e+00,
+ 1.00861604e+00, 1.00895138e+00, 1.00925390e+00, 1.00952134e+00,
+ 1.00975175e+00, 1.00994371e+00, 1.01009550e+00, 1.01020488e+00,
+ 1.01027007e+00, 1.01028975e+00, 1.01026227e+00, 1.01018562e+00,
+ 1.01005820e+00, 1.00987882e+00, 1.00964593e+00, 1.00935753e+00,
+ 1.00901228e+00, 1.00860959e+00, 1.00814837e+00, 1.00762674e+00,
+ 1.00704343e+00, 1.00639775e+00, 1.00568877e+00, 1.00491559e+00,
+ 1.00407768e+00, 1.00317429e+00, 1.00220424e+00, 1.00116684e+00,
+ 1.00006248e+00, 9.98891422e-01, 9.97652252e-01, 9.96343856e-01,
+ 9.94967462e-01, 9.93524663e-01, 9.92013927e-01, 9.90433283e-01,
+ 9.88785147e-01, 9.87072681e-01, 9.85297443e-01, 9.83401161e-01,
+ 9.80949418e-01, 9.78782729e-01, 9.76468238e-01, 9.74042850e-01,
+ 9.71498848e-01, 9.68829968e-01, 9.66030974e-01, 9.63095104e-01,
+ 9.60018198e-01, 9.56795738e-01, 9.53426267e-01, 9.49903482e-01,
+ 9.46222115e-01, 9.42375820e-01, 9.38361702e-01, 9.34177798e-01,
+ 9.29823124e-01, 9.25292320e-01, 9.20580120e-01, 9.15679793e-01,
+ 9.10590604e-01, 9.05315030e-01, 8.99852756e-01, 8.94199497e-01,
+ 8.88350152e-01, 8.82301631e-01, 8.76054874e-01, 8.69612385e-01,
+ 8.62972799e-01, 8.56135198e-01, 8.49098179e-01, 8.41857024e-01,
+ 8.34414055e-01, 8.26774617e-01, 8.18939244e-01, 8.10904891e-01,
+ 8.02675318e-01, 7.94253751e-01, 7.85641662e-01, 7.76838609e-01,
+ 7.67853193e-01, 7.58685181e-01, 7.49330658e-01, 7.39809171e-01,
+ 7.30109944e-01, 7.20247781e-01, 7.10224161e-01, 7.00044326e-01,
+ 6.89711890e-01, 6.79231154e-01, 6.68608179e-01, 6.57850997e-01,
+ 6.46965718e-01, 6.35959617e-01, 6.24840336e-01, 6.13603503e-01,
+ 6.02265091e-01, 5.90829083e-01, 5.79309408e-01, 5.67711124e-01,
+ 5.56037416e-01, 5.44293664e-01, 5.32489768e-01, 5.20636084e-01,
+ 5.08743273e-01, 4.96811166e-01, 4.84849881e-01, 4.72868107e-01,
+ 4.60875918e-01, 4.48881081e-01, 4.36891039e-01, 4.24912022e-01,
+ 4.12960603e-01, 4.01035896e-01, 3.89157867e-01, 3.77322199e-01,
+ 3.65543767e-01, 3.53832356e-01, 3.42196115e-01, 3.30644820e-01,
+ 3.19187559e-01, 3.07833309e-01, 2.96588182e-01, 2.85463717e-01,
+ 2.74462409e-01, 2.63609584e-01, 2.52883101e-01, 2.42323489e-01,
+ 2.31925746e-01, 2.21690837e-01, 2.11638058e-01, 2.01766920e-01,
+ 1.92082236e-01, 1.82589160e-01, 1.73305997e-01, 1.64229200e-01,
+ 1.55362654e-01, 1.46717079e-01, 1.38299391e-01, 1.30105078e-01,
+ 1.22145310e-01, 1.14423458e-01, 1.06941076e-01, 9.97025893e-02,
+ 9.27124283e-02, 8.59737427e-02, 7.94893311e-02, 7.32616579e-02,
+ 6.72934102e-02, 6.15874081e-02, 5.61458003e-02, 5.09700747e-02,
+ 4.60617047e-02, 4.14220117e-02, 3.70514189e-02, 3.29494666e-02,
+ 2.91153327e-02, 2.55476401e-02, 2.22437711e-02, 1.92000659e-02,
+ 1.64122205e-02, 1.38747611e-02, 1.15806353e-02, 9.52213664e-03,
+ 7.69137380e-03, 6.07207833e-03, 4.62581217e-03, 3.60685164e-03,
+};
+
+static const float mdct_win_7m5_360[360+276] = {
+ 1.72152668e-03, 2.20824874e-03, 2.68901752e-03, 3.22613342e-03,
+ 3.81014420e-03, 4.45371932e-03, 5.15369240e-03, 5.91552473e-03,
+ 6.73869158e-03, 7.62861841e-03, 8.58361457e-03, 9.60938437e-03,
+ 1.07060753e-02, 1.18759723e-02, 1.31190130e-02, 1.44390108e-02,
+ 1.58335301e-02, 1.73063081e-02, 1.88584711e-02, 2.04918652e-02,
+ 2.22061476e-02, 2.40057166e-02, 2.58883593e-02, 2.78552326e-02,
+ 2.99059145e-02, 3.20415894e-02, 3.42610013e-02, 3.65680973e-02,
+ 3.89616721e-02, 4.14435824e-02, 4.40140796e-02, 4.66742169e-02,
+ 4.94214625e-02, 5.22588489e-02, 5.51849337e-02, 5.82005143e-02,
+ 6.13059845e-02, 6.45038384e-02, 6.77913923e-02, 7.11707833e-02,
+ 7.46411071e-02, 7.82028053e-02, 8.18549521e-02, 8.56000162e-02,
+ 8.94357617e-02, 9.33642589e-02, 9.73846703e-02, 1.01496718e-01,
+ 1.05698760e-01, 1.09993603e-01, 1.14378287e-01, 1.18853508e-01,
+ 1.23419277e-01, 1.28075997e-01, 1.32820581e-01, 1.37655457e-01,
+ 1.42578648e-01, 1.47590522e-01, 1.52690437e-01, 1.57878853e-01,
+ 1.63152529e-01, 1.68513363e-01, 1.73957969e-01, 1.79484737e-01,
+ 1.85093105e-01, 1.90784835e-01, 1.96556497e-01, 2.02410419e-01,
+ 2.08345433e-01, 2.14359825e-01, 2.20450365e-01, 2.26617296e-01,
+ 2.32856279e-01, 2.39167941e-01, 2.45550642e-01, 2.52003951e-01,
+ 2.58526168e-01, 2.65118408e-01, 2.71775911e-01, 2.78498539e-01,
+ 2.85284606e-01, 2.92132459e-01, 2.99038432e-01, 3.06004256e-01,
+ 3.13026529e-01, 3.20104862e-01, 3.27237324e-01, 3.34423210e-01,
+ 3.41658622e-01, 3.48944976e-01, 3.56279252e-01, 3.63660034e-01,
+ 3.71085146e-01, 3.78554327e-01, 3.86062695e-01, 3.93610554e-01,
+ 4.01195225e-01, 4.08815272e-01, 4.16468460e-01, 4.24155411e-01,
+ 4.31871046e-01, 4.39614744e-01, 4.47384019e-01, 4.55176988e-01,
+ 4.62990138e-01, 4.70824619e-01, 4.78676593e-01, 4.86545433e-01,
+ 4.94428714e-01, 5.02324813e-01, 5.10229471e-01, 5.18142927e-01,
+ 5.26060916e-01, 5.33982818e-01, 5.41906817e-01, 5.49831283e-01,
+ 5.57751234e-01, 5.65667636e-01, 5.73576883e-01, 5.81476666e-01,
+ 5.89364661e-01, 5.97241338e-01, 6.05102013e-01, 6.12946170e-01,
+ 6.20770242e-01, 6.28572094e-01, 6.36348526e-01, 6.44099662e-01,
+ 6.51820973e-01, 6.59513822e-01, 6.67176382e-01, 6.74806795e-01,
+ 6.82400711e-01, 6.89958854e-01, 6.97475722e-01, 7.04950145e-01,
+ 7.12379980e-01, 7.19765434e-01, 7.27103833e-01, 7.34396372e-01,
+ 7.41638561e-01, 7.48829639e-01, 7.55966688e-01, 7.63049259e-01,
+ 7.70072273e-01, 7.77036981e-01, 7.83941108e-01, 7.90781257e-01,
+ 7.97558114e-01, 8.04271381e-01, 8.10914901e-01, 8.17490856e-01,
+ 8.23997094e-01, 8.30432785e-01, 8.36796950e-01, 8.43089298e-01,
+ 8.49305847e-01, 8.55447310e-01, 8.61511037e-01, 8.67496281e-01,
+ 8.73400798e-01, 8.79227518e-01, 8.84972438e-01, 8.90635719e-01,
+ 8.96217173e-01, 9.01716414e-01, 9.07128770e-01, 9.12456578e-01,
+ 9.17697261e-01, 9.22848784e-01, 9.27909917e-01, 9.32882596e-01,
+ 9.37763323e-01, 9.42553356e-01, 9.47252428e-01, 9.51860206e-01,
+ 9.56376060e-01, 9.60800602e-01, 9.65130600e-01, 9.69366689e-01,
+ 9.73508812e-01, 9.77556541e-01, 9.81507226e-01, 9.85364580e-01,
+ 9.89126209e-01, 9.92794201e-01, 9.96367545e-01, 9.99846919e-01,
+ 1.00322812e+00, 1.00651341e+00, 1.00970073e+00, 1.01279029e+00,
+ 1.01578293e+00, 1.01868229e+00, 1.02148657e+00, 1.02419772e+00,
+ 1.02681455e+00, 1.02933598e+00, 1.03176043e+00, 1.03408981e+00,
+ 1.03632326e+00, 1.03846361e+00, 1.04051196e+00, 1.04246831e+00,
+ 1.04433331e+00, 1.04610837e+00, 1.04779018e+00, 1.04938334e+00,
+ 1.05088565e+00, 1.05229923e+00, 1.05362522e+00, 1.05486289e+00,
+ 1.05601521e+00, 1.05708746e+00, 1.05807221e+00, 1.05897524e+00,
+ 1.05979447e+00, 1.06053414e+00, 1.06119412e+00, 1.06177366e+00,
+ 1.06227662e+00, 1.06270324e+00, 1.06305569e+00, 1.06333815e+00,
+ 1.06354800e+00, 1.06368607e+00, 1.06375557e+00, 1.06375743e+00,
+ 1.06369358e+00, 1.06356632e+00, 1.06337707e+00, 1.06312782e+00,
+ 1.06282156e+00, 1.06245782e+00, 1.06203634e+00, 1.06155996e+00,
+ 1.06102951e+00, 1.06044797e+00, 1.05981709e+00, 1.05914163e+00,
+ 1.05842136e+00, 1.05765876e+00, 1.05685377e+00, 1.05600761e+00,
+ 1.05512006e+00, 1.05419505e+00, 1.05323346e+00, 1.05223985e+00,
+ 1.05121668e+00, 1.05016637e+00, 1.04908779e+00, 1.04798366e+00,
+ 1.04685334e+00, 1.04569860e+00, 1.04452056e+00, 1.04332348e+00,
+ 1.04210831e+00, 1.04087907e+00, 1.03963603e+00, 1.03838099e+00,
+ 1.03711403e+00, 1.03583813e+00, 1.03455276e+00, 1.03326200e+00,
+ 1.03196750e+00, 1.03067200e+00, 1.02937564e+00, 1.02808244e+00,
+ 1.02679167e+00, 1.02550635e+00, 1.02422655e+00, 1.02295558e+00,
+ 1.02169299e+00, 1.02044475e+00, 1.01920733e+00, 1.01799992e+00,
+ 1.01716022e+00, 1.01587289e+00, 1.01461783e+00, 1.01339738e+00,
+ 1.01221017e+00, 1.01105652e+00, 1.00993444e+00, 1.00884559e+00,
+ 1.00778956e+00, 1.00676790e+00, 1.00577851e+00, 1.00482173e+00,
+ 1.00389592e+00, 1.00300262e+00, 1.00214091e+00, 1.00131213e+00,
+ 1.00051460e+00, 9.99748988e-01, 9.99013486e-01, 9.98309229e-01,
+ 9.97634934e-01, 9.96991885e-01, 9.96378601e-01, 9.95795982e-01,
+ 9.95242217e-01, 9.94718132e-01, 9.94222122e-01, 9.93755313e-01,
+ 9.93316216e-01, 9.92905809e-01, 9.92522422e-01, 9.92166957e-01,
+ 9.91837704e-01, 9.91535508e-01, 9.91258603e-01, 9.91007878e-01,
+ 9.90781723e-01, 9.90581104e-01, 9.90404336e-01, 9.90252267e-01,
+ 9.90123118e-01, 9.90017726e-01, 9.89934325e-01, 9.89873712e-01,
+ 9.89834110e-01, 9.89816359e-01, 9.89818707e-01, 9.89841998e-01,
+ 9.89884438e-01, 9.89946800e-01, 9.90027287e-01, 9.90126680e-01,
+ 9.90243175e-01, 9.90377594e-01, 9.90528134e-01, 9.90695564e-01,
+ 9.90878043e-01, 9.91076302e-01, 9.91288540e-01, 9.91515602e-01,
+ 9.91755666e-01, 9.92009469e-01, 9.92275155e-01, 9.92553486e-01,
+ 9.92842693e-01, 9.93143533e-01, 9.93454080e-01, 9.93775067e-01,
+ 9.94104689e-01, 9.94443742e-01, 9.94790398e-01, 9.95145361e-01,
+ 9.95506800e-01, 9.95875534e-01, 9.96249681e-01, 9.96629919e-01,
+ 9.97014367e-01, 9.97403799e-01, 9.97796404e-01, 9.98192871e-01,
+ 9.98591286e-01, 9.98992436e-01, 9.99394506e-01, 9.99798247e-01,
+ 1.00020179e+00, 1.00060586e+00, 1.00100858e+00, 1.00141070e+00,
+ 1.00181040e+00, 1.00220846e+00, 1.00260296e+00, 1.00299457e+00,
+ 1.00338148e+00, 1.00376444e+00, 1.00414155e+00, 1.00451348e+00,
+ 1.00487832e+00, 1.00523688e+00, 1.00558730e+00, 1.00593027e+00,
+ 1.00626393e+00, 1.00658905e+00, 1.00690380e+00, 1.00720890e+00,
+ 1.00750238e+00, 1.00778498e+00, 1.00805489e+00, 1.00831287e+00,
+ 1.00855700e+00, 1.00878802e+00, 1.00900405e+00, 1.00920593e+00,
+ 1.00939182e+00, 1.00956244e+00, 1.00971590e+00, 1.00985296e+00,
+ 1.00997177e+00, 1.01007317e+00, 1.01015529e+00, 1.01021893e+00,
+ 1.01026225e+00, 1.01028602e+00, 1.01028842e+00, 1.01027030e+00,
+ 1.01022988e+00, 1.01016802e+00, 1.01008292e+00, 1.00997541e+00,
+ 1.00984369e+00, 1.00968863e+00, 1.00950846e+00, 1.00930404e+00,
+ 1.00907371e+00, 1.00881848e+00, 1.00853675e+00, 1.00822947e+00,
+ 1.00789488e+00, 1.00753391e+00, 1.00714488e+00, 1.00672876e+00,
+ 1.00628393e+00, 1.00581146e+00, 1.00530991e+00, 1.00478053e+00,
+ 1.00422177e+00, 1.00363456e+00, 1.00301719e+00, 1.00237067e+00,
+ 1.00169363e+00, 1.00098749e+00, 1.00025108e+00, 9.99485663e-01,
+ 9.98689592e-01, 9.97863666e-01, 9.97006370e-01, 9.96119199e-01,
+ 9.95201404e-01, 9.94254687e-01, 9.93277595e-01, 9.92270651e-01,
+ 9.91231967e-01, 9.90163286e-01, 9.89064394e-01, 9.87937115e-01,
+ 9.86779736e-01, 9.85592773e-01, 9.84375125e-01, 9.83129288e-01,
+ 9.81348463e-01, 9.79890963e-01, 9.78400459e-01, 9.76860435e-01,
+ 9.75269879e-01, 9.73627353e-01, 9.71931341e-01, 9.70180498e-01,
+ 9.68372652e-01, 9.66506952e-01, 9.64580027e-01, 9.62592318e-01,
+ 9.60540986e-01, 9.58425534e-01, 9.56244393e-01, 9.53998416e-01,
+ 9.51684014e-01, 9.49301185e-01, 9.46846884e-01, 9.44320232e-01,
+ 9.41718404e-01, 9.39042580e-01, 9.36290624e-01, 9.33464050e-01,
+ 9.30560854e-01, 9.27580507e-01, 9.24519592e-01, 9.21378471e-01,
+ 9.18153414e-01, 9.14844696e-01, 9.11451652e-01, 9.07976524e-01,
+ 9.04417545e-01, 9.00776308e-01, 8.97050058e-01, 8.93238398e-01,
+ 8.89338681e-01, 8.85351360e-01, 8.81274023e-01, 8.77109638e-01,
+ 8.72857927e-01, 8.68519505e-01, 8.64092796e-01, 8.59579819e-01,
+ 8.54976007e-01, 8.50285220e-01, 8.45502615e-01, 8.40630470e-01,
+ 8.35667925e-01, 8.30619943e-01, 8.25482007e-01, 8.20258909e-01,
+ 8.14946648e-01, 8.09546696e-01, 8.04059978e-01, 7.98489378e-01,
+ 7.92831417e-01, 7.87090668e-01, 7.81262450e-01, 7.75353947e-01,
+ 7.69363613e-01, 7.63291769e-01, 7.57139016e-01, 7.50901711e-01,
+ 7.44590843e-01, 7.38205136e-01, 7.31738075e-01, 7.25199287e-01,
+ 7.18588225e-01, 7.11905687e-01, 7.05153668e-01, 6.98332634e-01,
+ 6.91444101e-01, 6.84490545e-01, 6.77470119e-01, 6.70388375e-01,
+ 6.63245210e-01, 6.56045780e-01, 6.48788627e-01, 6.41477162e-01,
+ 6.34114323e-01, 6.26702000e-01, 6.19235334e-01, 6.11720596e-01,
+ 6.04161612e-01, 5.96559133e-01, 5.88914401e-01, 5.81234783e-01,
+ 5.73519989e-01, 5.65770616e-01, 5.57988067e-01, 5.50173851e-01,
+ 5.42330194e-01, 5.34460798e-01, 5.26568538e-01, 5.18656324e-01,
+ 5.10728813e-01, 5.02781159e-01, 4.94819491e-01, 4.86845139e-01,
+ 4.78860889e-01, 4.70869928e-01, 4.62875144e-01, 4.54877894e-01,
+ 4.46882512e-01, 4.38889325e-01, 4.30898123e-01, 4.22918322e-01,
+ 4.14950878e-01, 4.06993964e-01, 3.99052648e-01, 3.91134614e-01,
+ 3.83234031e-01, 3.75354653e-01, 3.67502060e-01, 3.59680098e-01,
+ 3.51887312e-01, 3.44130166e-01, 3.36408100e-01, 3.28728966e-01,
+ 3.21090505e-01, 3.13496418e-01, 3.05951565e-01, 2.98454319e-01,
+ 2.91010565e-01, 2.83621109e-01, 2.76285415e-01, 2.69019585e-01,
+ 2.61812445e-01, 2.54659232e-01, 2.47584348e-01, 2.40578694e-01,
+ 2.33647009e-01, 2.26788433e-01, 2.20001992e-01, 2.13301325e-01,
+ 2.06677771e-01, 2.00140409e-01, 1.93683630e-01, 1.87310343e-01,
+ 1.81027384e-01, 1.74839476e-01, 1.68739644e-01, 1.62737273e-01,
+ 1.56825277e-01, 1.51012382e-01, 1.45298230e-01, 1.39687469e-01,
+ 1.34171842e-01, 1.28762544e-01, 1.23455562e-01, 1.18254662e-01,
+ 1.13159677e-01, 1.08171439e-01, 1.03290734e-01, 9.85202978e-02,
+ 9.38600023e-02, 8.93117360e-02, 8.48752103e-02, 8.05523737e-02,
+ 7.63429787e-02, 7.22489246e-02, 6.82699120e-02, 6.44077291e-02,
+ 6.06620003e-02, 5.70343711e-02, 5.35243715e-02, 5.01334690e-02,
+ 4.68610790e-02, 4.37084453e-02, 4.06748365e-02, 3.77612269e-02,
+ 3.49667099e-02, 3.22919275e-02, 2.97357669e-02, 2.72984629e-02,
+ 2.49787186e-02, 2.27762542e-02, 2.06895808e-02, 1.87178169e-02,
+ 1.68593418e-02, 1.51125125e-02, 1.34757094e-02, 1.19462709e-02,
+ 1.05228754e-02, 9.20130941e-03, 7.98124316e-03, 6.85547314e-03,
+ 5.82657334e-03, 4.87838525e-03, 4.02351119e-03, 3.15418663e-03,
+};
+
+const float *lc3_mdct_win[LC3_NUM_DT][LC3_NUM_SRATE] = {
+
+ [LC3_DT_7M5] = {
+ [LC3_SRATE_8K ] = mdct_win_7m5_60,
+ [LC3_SRATE_16K] = mdct_win_7m5_120,
+ [LC3_SRATE_24K] = mdct_win_7m5_180,
+ [LC3_SRATE_32K] = mdct_win_7m5_240,
+ [LC3_SRATE_48K] = mdct_win_7m5_360,
+ },
+
+ [LC3_DT_10M] = {
+ [LC3_SRATE_8K ] = mdct_win_10m_80,
+ [LC3_SRATE_16K] = mdct_win_10m_160,
+ [LC3_SRATE_24K] = mdct_win_10m_240,
+ [LC3_SRATE_32K] = mdct_win_10m_320,
+ [LC3_SRATE_48K] = mdct_win_10m_480,
+ },
+};
+
+
+/**
+ * Bands limits (cf. 3.7.1-2)
+ */
+
+const int lc3_band_lim[LC3_NUM_DT][LC3_NUM_SRATE][LC3_NUM_BANDS+1] = {
+
+ [LC3_DT_7M5] = {
+
+ [LC3_SRATE_8K ] = {
+ 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, 60, 60, 60, 60 },
+
+ [LC3_SRATE_16K] = {
+ 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 },
+
+ [LC3_SRATE_24K] = {
+ 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 },
+
+ [LC3_SRATE_32K] = {
+ 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 },
+
+ [LC3_SRATE_48K] = {
+ 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 },
+ },
+
+ [LC3_DT_10M] = {
+
+ [LC3_SRATE_8K ] = {
+ 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 },
+
+ [LC3_SRATE_16K] = {
+ 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 },
+
+ [LC3_SRATE_24K] = {
+ 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 },
+
+ [LC3_SRATE_32K] = {
+ 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 },
+
+ [LC3_SRATE_48K] = {
+ 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 },
+ }
+};
+
+
+/**
+ * SNS Quantization (cf. 3.7.4)
+ */
+
+const float lc3_sns_lfcb[32][8] = {
+
+ { 2.26283366e+00, 8.13311269e-01, -5.30193495e-01, -1.35664836e+00,
+ -1.59952177e+00, -1.44098768e+00, -1.14381648e+00, -7.55203768e-01 },
+
+ { 2.94516479e+00, 2.41143318e+00, 9.60455106e-01, -4.43226488e-01,
+ -1.22913612e+00, -1.55590039e+00, -1.49688656e+00, -1.11689987e+00 },
+
+ { -2.18610707e+00, -1.97152136e+00, -1.78718620e+00, -1.91865896e+00,
+ -1.79399122e+00, -1.35738404e+00, -7.05444279e-01, -4.78172945e-02 },
+
+ { 6.93688237e-01, 9.55609857e-01, 5.75230787e-01, -1.14603419e-01,
+ -6.46050637e-01, -9.52351370e-01, -1.07405247e+00, -7.58087707e-01 },
+
+ { -1.29752132e+00, -7.40369057e-01, -3.45372484e-01, -3.13285696e-01,
+ -4.02977243e-01, -3.72020853e-01, -7.83414177e-02, 9.70441304e-02 },
+
+ { 9.14652038e-01, 1.74293043e+00, 1.90906627e+00, 1.54408484e+00,
+ 1.09344961e+00, 6.47479550e-01, 3.61790752e-02, -2.97092807e-01 },
+
+ { -2.51428813e+00, -2.89175271e+00, -2.00450667e+00, -7.50912274e-01,
+ 4.41202105e-01, 1.20190988e+00, 1.32742857e+00, 1.22049081e+00 },
+
+ { -9.22188405e-01, 6.32495141e-01, 1.08736431e+00, 6.08628625e-01,
+ 1.31174568e-01, -2.96149158e-01, -2.07013517e-01, 1.34924917e-01 },
+
+ { 7.90322288e-01, 6.28401262e-01, 3.93117924e-01, 4.80007711e-01,
+ 4.47815138e-01, 2.09734215e-01, 6.56691996e-03, -8.61242342e-02 },
+
+ { 1.44775580e+00, 2.72399952e+00, 2.31083269e+00, 9.35051270e-01,
+ -2.74743911e-01, -9.02077697e-01, -9.40681512e-01, -6.33697039e-01 },
+
+ { 7.93354526e-01, 1.43931186e-02, -5.67834845e-01, -6.54760468e-01,
+ -4.79458998e-01, -1.73894662e-01, 6.80162706e-02, 2.95125948e-01 },
+
+ { 2.72425347e+00, 2.95947572e+00, 1.84953559e+00, 5.63284922e-01,
+ 1.39917088e-01, 3.59641093e-01, 6.89461355e-01, 6.39790177e-01 },
+
+ { -5.30830198e-01, -2.12690683e-01, 5.76613628e-03, 4.24871484e-01,
+ 4.73128952e-01, 8.58894199e-01, 1.19111161e+00, 9.96189670e-01 },
+
+ { 1.68728411e+00, 2.43614509e+00, 2.33019429e+00, 1.77983778e+00,
+ 1.44411295e+00, 1.51995177e+00, 1.47199394e+00, 9.77682474e-01 },
+
+ { -2.95183273e+00, -1.59393497e+00, -1.09918773e-01, 3.88609073e-01,
+ 5.12932650e-01, 6.28112597e-01, 8.22621796e-01, 8.75891425e-01 },
+
+ { 1.01878343e-01, 5.89857324e-01, 6.19047647e-01, 1.26731314e+00,
+ 2.41961048e+00, 2.25174253e+00, 5.26537031e-01, -3.96591513e-01 },
+
+ { 2.68254575e+00, 1.32738011e+00, 1.30185274e-01, -3.38533089e-01,
+ -3.68219236e-01, -1.91689947e-01, -1.54782377e-01, -2.34207178e-01 },
+
+ { 4.82697924e+00, 3.11947804e+00, 1.39513671e+00, 2.50295316e-01,
+ -3.93613839e-01, -6.43458173e-01, -6.42570737e-01, -7.23193223e-01 },
+
+ { 8.78419936e-02, -5.69586840e-01, -1.14506016e+00, -1.66968488e+00,
+ -1.84534418e+00, -1.56468027e+00, -1.11746759e+00, -5.33981663e-01 },
+
+ { 1.39102308e+00, 1.98146479e+00, 1.11265796e+00, -2.20107509e-01,
+ -7.74965612e-01, -5.94063874e-01, 1.36937681e-01, 8.18242891e-01 },
+
+ { 3.84585894e-01, -1.60588786e-01, -5.39366810e-01, -5.29309079e-01,
+ 1.90433547e-01, 2.56062918e+00, 2.81896398e+00, 6.56670876e-01 },
+
+ { 1.93227399e+00, 3.01030180e+00, 3.06543894e+00, 2.50110161e+00,
+ 1.93089593e+00, 5.72153811e-01, -8.11741794e-01, -1.17641811e+00 },
+
+ { 1.75080463e-01, -7.50522832e-01, -1.03943893e+00, -1.13577509e+00,
+ -1.04197904e+00, -1.52060099e-02, 2.07048392e+00, 3.42948918e+00 },
+
+ { -1.18817020e+00, 3.66792874e-01, 1.30957830e+00, 1.68330687e+00,
+ 1.25100924e+00, 9.42375752e-01, 8.26250483e-01, 4.39952741e-01 },
+
+ { 2.53322203e+00, 2.11274643e+00, 1.26288412e+00, 7.61513512e-01,
+ 5.22117938e-01, 1.18680070e-01, -4.52346828e-01, -7.00352426e-01 },
+
+ { 3.99889837e+00, 4.07901751e+00, 2.82285661e+00, 1.72607213e+00,
+ 6.47144377e-01, -3.31148521e-01, -8.84042571e-01, -1.12697341e+00 },
+
+ { 5.07902593e-01, 1.58838450e+00, 1.72899024e+00, 1.00692230e+00,
+ 3.77121232e-01, 4.76370767e-01, 1.08754740e+00, 1.08756266e+00 },
+
+ { 3.16856825e+00, 3.25853458e+00, 2.42230591e+00, 1.79446078e+00,
+ 1.52177911e+00, 1.17196707e+00, 4.89394597e-01, -6.22795716e-02 },
+
+ { 1.89414767e+00, 1.25108695e+00, 5.90451211e-01, 6.08358583e-01,
+ 8.78171010e-01, 1.11912511e+00, 1.01857662e+00, 6.20453891e-01 },
+
+ { 9.48880605e-01, 2.13239439e+00, 2.72345350e+00, 2.76986077e+00,
+ 2.54286973e+00, 2.02046264e+00, 8.30045859e-01, -2.75569174e-02 },
+
+ { -1.88026757e+00, -1.26431073e+00, 3.11424977e-01, 1.83670210e+00,
+ 2.25634192e+00, 2.04818998e+00, 2.19526837e+00, 2.02659614e+00 },
+
+ { 2.46375746e-01, 9.55621773e-01, 1.52046777e+00, 1.97647400e+00,
+ 1.94043867e+00, 2.23375847e+00, 1.98835978e+00, 1.27232673e+00 },
+
+};
+
+const float lc3_sns_hfcb[32][8] = {
+
+ { 2.32028419e-01, -1.00890271e+00, -2.14223503e+00, -2.37533814e+00,
+ -2.23041933e+00, -2.17595881e+00, -2.29065914e+00, -2.53286398e+00 },
+
+ { -1.29503937e+00, -1.79929965e+00, -1.88703148e+00, -1.80991660e+00,
+ -1.76340038e+00, -1.83418428e+00, -1.80480981e+00, -1.73679545e+00 },
+
+ { 1.39285716e-01, -2.58185126e-01, -6.50804573e-01, -1.06815732e+00,
+ -1.61928742e+00, -2.18762566e+00, -2.63757587e+00, -2.97897750e+00 },
+
+ { -3.16513102e-01, -4.77747657e-01, -5.51162076e-01, -4.84788283e-01,
+ -2.38388394e-01, -1.43024507e-01, 6.83186674e-02, 8.83061717e-02 },
+
+ { 8.79518405e-01, 2.98340096e-01, -9.15386396e-01, -2.20645975e+00,
+ -2.74142181e+00, -2.86139074e+00, -2.88841597e+00, -2.95182608e+00 },
+
+ { -2.96701922e-01, -9.75004919e-01, -1.35857500e+00, -9.83721106e-01,
+ -6.52956939e-01, -9.89986993e-01, -1.61467225e+00, -2.40712302e+00 },
+
+ { 3.40981100e-01, 2.68899789e-01, 5.63335685e-02, 4.99114047e-02,
+ -9.54130727e-02, -7.60166146e-01, -2.32758120e+00, -3.77155485e+00 },
+
+ { -1.41229759e+00, -1.48522119e+00, -1.18603580e+00, -6.25001634e-01,
+ 1.53902497e-01, 5.76386498e-01, 7.95092604e-01, 5.96564632e-01 },
+
+ { -2.28839512e-01, -3.33719070e-01, -8.09321359e-01, -1.63587877e+00,
+ -1.88486397e+00, -1.64496691e+00, -1.40515778e+00, -1.46666471e+00 },
+
+ { -1.07148629e+00, -1.41767015e+00, -1.54891762e+00, -1.45296062e+00,
+ -1.03182970e+00, -6.90642640e-01, -4.28843805e-01, -4.94960215e-01 },
+
+ { -5.90988511e-01, -7.11737759e-02, 3.45719523e-01, 3.00549461e-01,
+ -1.11865218e+00, -2.44089151e+00, -2.22854732e+00, -1.89509228e+00 },
+
+ { -8.48434099e-01, -5.83226811e-01, 9.00423688e-02, 8.45025008e-01,
+ 1.06572385e+00, 7.37582999e-01, 2.56590452e-01, -4.91963360e-01 },
+
+ { 1.14069146e+00, 9.64016892e-01, 3.81461206e-01, -4.82849341e-01,
+ -1.81632721e+00, -2.80279513e+00, -3.23385725e+00, -3.45908714e+00 },
+
+ { -3.76283238e-01, 4.25675462e-02, 5.16547697e-01, 2.51716882e-01,
+ -2.16179968e-01, -5.34074091e-01, -6.40786096e-01, -8.69745032e-01 },
+
+ { 6.65004121e-01, 1.09790765e+00, 1.38342667e+00, 1.34327359e+00,
+ 8.22978837e-01, 2.15876799e-01, -4.04925753e-01, -1.07025606e+00 },
+
+ { -8.26265954e-01, -6.71181233e-01, -2.28495593e-01, 5.18980853e-01,
+ 1.36721896e+00, 2.18023038e+00, 2.53596093e+00, 2.20121099e+00 },
+
+ { 1.41008327e+00, 7.54441908e-01, -1.30550585e+00, -1.87133711e+00,
+ -1.24008685e+00, -1.26712925e+00, -2.03670813e+00, -2.89685162e+00 },
+
+ { 3.61386818e-01, -2.19991705e-02, -5.79368834e-01, -8.79427961e-01,
+ -8.50685023e-01, -7.79397050e-01, -7.32182927e-01, -8.88348515e-01 },
+
+ { 4.37469239e-01, 3.05440420e-01, -7.38786566e-03, -4.95649855e-01,
+ -8.06651271e-01, -1.22431892e+00, -1.70157770e+00, -2.24491914e+00 },
+
+ { 6.48100319e-01, 6.82299134e-01, 2.53247464e-01, 7.35842144e-02,
+ 3.14216709e-01, 2.34729881e-01, 1.44600134e-01, -6.82120179e-02 },
+
+ { 1.11919833e+00, 1.23465533e+00, 5.89170238e-01, -1.37192460e+00,
+ -2.37095707e+00, -2.00779783e+00, -1.66688540e+00, -1.92631846e+00 },
+
+ { 1.41847497e-01, -1.10660071e-01, -2.82824593e-01, -6.59813475e-03,
+ 2.85929280e-01, 4.60445530e-02, -6.02596416e-01, -2.26568729e+00 },
+
+ { 5.04046955e-01, 8.26982163e-01, 1.11981236e+00, 1.17914044e+00,
+ 1.07987429e+00, 6.97536239e-01, -9.12548817e-01, -3.57684747e+00 },
+
+ { -5.01076050e-01, -3.25678006e-01, 2.80798195e-02, 2.62054555e-01,
+ 3.60590806e-01, 6.35623722e-01, 9.59012467e-01, 1.30745157e+00 },
+
+ { 3.74970983e+00, 1.52342612e+00, -4.57715662e-01, -7.98711008e-01,
+ -3.86819329e-01, -3.75901062e-01, -6.57836900e-01, -1.28163964e+00 },
+
+ { -1.15258991e+00, -1.10800886e+00, -5.62615117e-01, -2.20562124e-01,
+ -3.49842880e-01, -7.53432770e-01, -9.88596593e-01, -1.28790472e+00 },
+
+ { 1.02827246e+00, 1.09770519e+00, 7.68645546e-01, 2.06081978e-01,
+ -3.42805735e-01, -7.54939405e-01, -1.04196178e+00, -1.50335653e+00 },
+
+ { 1.28831972e-01, 6.89439395e-01, 1.12346905e+00, 1.30934523e+00,
+ 1.35511965e+00, 1.42311381e+00, 1.15706449e+00, 4.06319438e-01 },
+
+ { 1.34033030e+00, 1.38996825e+00, 1.04467922e+00, 6.35822746e-01,
+ -2.74733756e-01, -1.54923372e+00, -2.44239710e+00, -3.02457607e+00 },
+
+ { 2.13843105e+00, 4.24711267e+00, 2.89734110e+00, 9.32730658e-01,
+ -2.92822250e-01, -8.10404297e-01, -7.88868099e-01, -9.35353149e-01 },
+
+ { 5.64830487e-01, 1.59184978e+00, 2.39771699e+00, 3.03697344e+00,
+ 2.66424350e+00, 1.39304485e+00, 4.03834024e-01, -6.56270971e-01 },
+
+ { -4.22460548e-01, 3.26149625e-01, 1.39171313e+00, 2.23146615e+00,
+ 2.61179442e+00, 2.66540340e+00, 2.40103554e+00, 1.75920380e+00 },
+
+};
+
+const struct lc3_sns_vq_gains lc3_sns_vq_gains[4] = {
+
+ { 2, (const float []){
+ 8915.f / 4096, 12054.f / 4096 } },
+
+ { 4, (const float []){
+ 6245.f / 4096, 15043.f / 4096, 17861.f / 4096, 21014.f / 4096 } },
+
+ { 4, (const float []){
+ 7099.f / 4096, 9132.f / 4096, 11253.f / 4096, 14808.f / 4096 } },
+
+ { 8, (const float []){
+ 4336.f / 4096, 5067.f / 4096, 5895.f / 4096, 8149.f / 4096,
+ 10235.f / 4096, 12825.f / 4096, 16868.f / 4096, 19882.f / 4096 } }
+};
+
+const int32_t lc3_sns_mpvq_offsets[][11] = {
+ { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ { 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 },
+ { 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 },
+ { 0, 1, 31, 481, 4991, 39041, 246047,1303777,5984767,24331777,89129247 },
+};
+
+
+/**
+ * TNS Arithmetic Coding (cf. 3.7.5)
+ * The number of bits are given at 2048th of bits
+ */
+
+const struct lc3_ac_model lc3_tns_order_models[] = {
+
+ { { { 0, 3 }, { 3, 9 }, { 12, 23 }, { 35, 54 },
+ { 89, 111 }, { 200, 190 }, { 390, 268 }, { 658, 366 },
+ { 1024, 0 }, { 1024, 0 }, { 1024, 0 }, { 1024, 0 },
+ { 1024, 0 }, { 1024, 0 }, { 1024, 0 }, { 1024, 0 },
+ { 1024, 0 } } },
+
+ { { { 0, 14 }, { 14, 42 }, { 56, 100 }, { 156, 157 },
+ { 313, 181 }, { 494, 178 }, { 672, 167 }, { 839, 185 },
+ { 1024, 0 }, { 1024, 0 }, { 1024, 0 }, { 1024, 0 },
+ { 1024, 0 }, { 1024, 0 }, { 1024, 0 }, { 1024, 0 },
+ { 1024, 0 } } },
+};
+
+const uint16_t lc3_tns_order_bits[][8] = {
+ { 17234, 13988, 11216, 8694, 6566, 4977, 3961, 3040 },
+ { 12683, 9437, 6874, 5541, 5121, 5170, 5359, 5056 }
+};
+
+const struct lc3_ac_model lc3_tns_coeffs_models[] = {
+
+ { { { 0, 1 }, { 1, 5 }, { 6, 15 }, { 21, 31 },
+ { 52, 54 }, { 106, 86 }, { 192, 97 }, { 289, 120 },
+ { 409, 159 }, { 568, 152 }, { 720, 111 }, { 831, 104 },
+ { 935, 59 }, { 994, 22 }, { 1016, 6 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 13 }, { 17, 43 }, { 60, 94 }, { 154, 139 },
+ { 293, 173 }, { 466, 160 }, { 626, 154 }, { 780, 131 },
+ { 911, 78 }, { 989, 27 }, { 1016, 6 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 9 }, { 13, 43 }, { 56, 106 }, { 162, 199 },
+ { 361, 217 }, { 578, 210 }, { 788, 141 }, { 929, 74 },
+ { 1003, 17 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 2 }, { 6, 11 }, { 17, 49 }, { 66, 204 },
+ { 270, 285 }, { 555, 297 }, { 852, 120 }, { 972, 39 },
+ { 1011, 9 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 1 }, { 5, 7 }, { 12, 42 }, { 54, 241 },
+ { 295, 341 }, { 636, 314 }, { 950, 58 }, { 1008, 9 },
+ { 1017, 3 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 1 }, { 5, 1 }, { 6, 13 }, { 19, 205 },
+ { 224, 366 }, { 590, 377 }, { 967, 47 }, { 1014, 5 },
+ { 1019, 1 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 1 }, { 5, 1 }, { 6, 13 }, { 19, 281 },
+ { 300, 330 }, { 630, 371 }, { 1001, 17 }, { 1018, 1 },
+ { 1019, 1 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 },
+ { 4, 1 }, { 5, 1 }, { 6, 5 }, { 11, 297 },
+ { 308, 1 }, { 309, 682 }, { 991, 26 }, { 1017, 2 },
+ { 1019, 1 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+};
+
+const uint16_t lc3_tns_coeffs_bits[][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 }
+
+};
+
+
+/**
+ * Long Term Postfilter Synthesis (cf. 3.7.6)
+ * with - addition of a 0 for num coefficients
+ * - remove of first 0 den coefficients
+ */
+
+const float *lc3_ltpf_cnum[LC3_NUM_SRATE][4] = {
+
+ [LC3_SRATE_8K] = {
+ (const float []){
+ 6.02361821e-01, 4.19760926e-01, -1.88342453e-02, 0. },
+ (const float []){
+ 5.99476858e-01, 4.19760926e-01, -1.59492828e-02, 0. },
+ (const float []){
+ 5.96776466e-01, 4.19760926e-01, -1.32488910e-02, 0. },
+ (const float []){
+ 5.94241012e-01, 4.19760926e-01, -1.07134366e-02, 0. },
+ },
+
+ [LC3_SRATE_16K] = {
+ (const float []){
+ 6.02361821e-01, 4.19760926e-01, -1.88342453e-02, 0. },
+ (const float []){
+ 5.99476858e-01, 4.19760926e-01, -1.59492828e-02, 0. },
+ (const float []){
+ 5.96776466e-01, 4.19760926e-01, -1.32488910e-02, 0. },
+ (const float []){
+ 5.94241012e-01, 4.19760926e-01, -1.07134366e-02, 0. },
+ },
+
+ [LC3_SRATE_24K] = {
+ (const float []){
+ 3.98969559e-01, 5.14250861e-01, 1.00438297e-01, -1.27889396e-02,
+ -1.57228008e-03, 0. },
+ (const float []){
+ 3.94863491e-01, 5.12381921e-01, 1.04319493e-01, -1.09199996e-02,
+ -1.34740833e-03, 0. },
+ (const float []){
+ 3.90984448e-01, 5.10605352e-01, 1.07983252e-01, -9.14343107e-03,
+ -1.13212462e-03, 0. },
+ (const float []){
+ 3.87309389e-01, 5.08912208e-01, 1.11451738e-01, -7.45028713e-03,
+ -9.25551405e-04, 0. },
+ },
+
+ [LC3_SRATE_32K] = {
+ (const float []){
+ 2.98237945e-01, 4.65280920e-01, 2.10599743e-01, 3.76678038e-02,
+ -1.01569616e-02, -2.53588100e-03, -3.18294617e-04, 0. },
+ (const float []){
+ 2.94383415e-01, 4.61929400e-01, 2.12946577e-01, 4.06617500e-02,
+ -8.69327230e-03, -2.17830711e-03, -2.74288806e-04, 0. },
+ (const float []){
+ 2.90743921e-01, 4.58746191e-01, 2.15145697e-01, 4.35010477e-02,
+ -7.29549535e-03, -1.83439564e-03, -2.31692019e-04, 0. },
+ (const float []){
+ 2.87297585e-01, 4.55714889e-01, 2.17212695e-01, 4.62008888e-02,
+ -5.95746380e-03, -1.50293428e-03, -1.90385191e-04, 0. },
+ },
+
+ [LC3_SRATE_48K] = {
+ (const float []){
+ 1.98136374e-01, 3.52449490e-01, 2.51369527e-01, 1.42414624e-01,
+ 5.70473102e-02, 9.29336624e-03, -7.22602537e-03, -3.17267989e-03,
+ -1.12183596e-03, -2.90295724e-04, -4.27081559e-05, 0. },
+ (const float []){
+ 1.95070943e-01, 3.48466041e-01, 2.50998846e-01, 1.44116741e-01,
+ 5.92894732e-02, 1.10892383e-02, -6.19290811e-03, -2.72670551e-03,
+ -9.66712583e-04, -2.50810092e-04, -3.69993877e-05, 0. },
+ (const float []){
+ 1.92181006e-01, 3.44694556e-01, 2.50622009e-01, 1.45710245e-01,
+ 6.14113213e-02, 1.27994140e-02, -5.20372109e-03, -2.29732451e-03,
+ -8.16560813e-04, -2.12385575e-04, -3.14127133e-05, 0. },
+ (const float []){
+ 1.89448531e-01, 3.41113925e-01, 2.50240688e-01, 1.47206563e-01,
+ 6.34247723e-02, 1.44320343e-02, -4.25444914e-03, -1.88308147e-03,
+ -6.70961906e-04, -1.74936334e-04, -2.59386474e-05, 0. },
+ }
+};
+
+const float *lc3_ltpf_cden[LC3_NUM_SRATE][4] = {
+
+ [LC3_SRATE_8K] = {
+ (const float []){
+ 2.09880463e-01, 5.83527575e-01, 2.09880463e-01, 0.00000000e+00 },
+ (const float []){
+ 1.06999186e-01, 5.50075002e-01, 3.35690625e-01, 6.69885837e-03 },
+ (const float []){
+ 3.96711478e-02, 4.59220930e-01, 4.59220930e-01, 3.96711478e-02 },
+ (const float []){
+ 6.69885837e-03, 3.35690625e-01, 5.50075002e-01, 1.06999186e-01 },
+ },
+
+ [LC3_SRATE_16K] = {
+ (const float []){
+ 2.09880463e-01, 5.83527575e-01, 2.09880463e-01, 0.00000000e+00 },
+ (const float []){
+ 1.06999186e-01, 5.50075002e-01, 3.35690625e-01, 6.69885837e-03 },
+ (const float []){
+ 3.96711478e-02, 4.59220930e-01, 4.59220930e-01, 3.96711478e-02 },
+ (const float []){
+ 6.69885837e-03, 3.35690625e-01, 5.50075002e-01, 1.06999186e-01 },
+ },
+
+ [LC3_SRATE_24K] = {
+ (const float []){
+ 6.32223163e-02, 2.50730961e-01, 3.71390943e-01, 2.50730961e-01,
+ 6.32223163e-02, 0.00000000e+00 },
+ (const float []){
+ 3.45927217e-02, 1.98651560e-01, 3.62641173e-01, 2.98675055e-01,
+ 1.01309287e-01, 4.26354371e-03 },
+ (const float []){
+ 1.53574678e-02, 1.47434488e-01, 3.37425955e-01, 3.37425955e-01,
+ 1.47434488e-01, 1.53574678e-02 },
+ (const float []){
+ 4.26354371e-03, 1.01309287e-01, 2.98675055e-01, 3.62641173e-01,
+ 1.98651560e-01, 3.45927217e-02 },
+ },
+
+ [LC3_SRATE_32K] = {
+ (const float []){
+ 2.90040188e-02, 1.12985742e-01, 2.21202403e-01, 2.72390947e-01,
+ 2.21202403e-01, 1.12985742e-01, 2.90040188e-02, 0.00000000e+00 },
+ (const float []){
+ 1.70315342e-02, 8.72250379e-02, 1.96140776e-01, 2.68923798e-01,
+ 2.42499910e-01, 1.40577336e-01, 4.47487717e-02, 3.12703024e-03 },
+ (const float []){
+ 8.56367375e-03, 6.42622294e-02, 1.68767671e-01, 2.58744594e-01,
+ 2.58744594e-01, 1.68767671e-01, 6.42622294e-02, 8.56367375e-03 },
+ (const float []){
+ 3.12703024e-03, 4.47487717e-02, 1.40577336e-01, 2.42499910e-01,
+ 2.68923798e-01, 1.96140776e-01, 8.72250379e-02, 1.70315342e-02 },
+ },
+
+ [LC3_SRATE_48K] = {
+ (const float []){
+ 1.08235939e-02, 3.60896922e-02, 7.67640147e-02, 1.24153058e-01,
+ 1.62759644e-01, 1.77677142e-01, 1.62759644e-01, 1.24153058e-01,
+ 7.67640147e-02, 3.60896922e-02, 1.08235939e-02, 0.00000000e+00 },
+ (const float []){
+ 7.04140493e-03, 2.81970232e-02, 6.54704494e-02, 1.12464799e-01,
+ 1.54841896e-01, 1.76712238e-01, 1.69150721e-01, 1.35290158e-01,
+ 8.85142501e-02, 4.49935385e-02, 1.55761371e-02, 2.03972196e-03 },
+ (const float []){
+ 4.14699847e-03, 2.13575731e-02, 5.48273558e-02, 1.00497144e-01,
+ 1.45606034e-01, 1.73843984e-01, 1.73843984e-01, 1.45606034e-01,
+ 1.00497144e-01, 5.48273558e-02, 2.13575731e-02, 4.14699847e-03 },
+ (const float []){
+ 2.03972196e-03, 1.55761371e-02, 4.49935385e-02, 8.85142501e-02,
+ 1.35290158e-01, 1.69150721e-01, 1.76712238e-01, 1.54841896e-01,
+ 1.12464799e-01, 6.54704494e-02, 2.81970232e-02, 7.04140493e-03 },
+ }
+};
+
+
+/**
+ * Spectral Data Arithmetic Coding (cf. 3.7.7)
+ * The number of bits are given at 2048th of bits
+ *
+ * The dimensions of the lookup table are set as following :
+ * 1: Rate selection
+ * 2: Half spectrum selection (1st half / 2nd half)
+ * 3: State of the arithmetic coder
+ * 4: Number of msb bits (significant - 2), limited to 3
+ *
+ * table[r][h][s][k] = table(normative)[s + h*256 + r*512 + k*1024]
+ */
+
+const uint8_t lc3_spectrum_lookup[2][2][256][4] = {
+
+ { { { 1,13, 0, 0 }, { 39,13, 0, 0 }, { 7,13, 0, 0 }, { 25,13, 0, 0 },
+ { 22,13, 0, 0 }, { 22,13, 0, 0 }, { 28,13, 0, 0 }, { 22,13, 0, 0 },
+ { 22,60, 0, 0 }, { 22,60, 0, 0 }, { 22,60, 0, 0 }, { 28,60, 0, 0 },
+ { 28,60, 0, 0 }, { 28,60,13, 0 }, { 34,60,13, 0 }, { 31,16,13, 0 },
+ { 31,16,13, 0 }, { 40, 0, 0, 0 }, { 43, 0, 0, 0 }, { 46, 0, 0, 0 },
+ { 49, 0, 0, 0 }, { 52, 0, 0, 0 }, { 14, 0, 0, 0 }, { 17, 0, 0, 0 },
+ { 36, 0, 0, 0 }, { 36, 0, 0, 0 }, { 36, 0, 0, 0 }, { 38, 0, 0, 0 },
+ { 0, 0, 0, 0 }, { 57, 0, 0, 0 }, { 38,13, 0, 0 }, { 22,60, 0, 0 },
+ { 0, 0, 0, 0 }, { 8, 0, 0, 0 }, { 9, 0, 0, 0 }, { 11, 0, 0, 0 },
+ { 47, 0, 0, 0 }, { 14, 0, 0, 0 }, { 14, 0, 0, 0 }, { 17, 0, 0, 0 },
+ { 36, 0, 0, 0 }, { 36, 0, 0, 0 }, { 36, 0, 0, 0 }, { 38, 0, 0, 0 },
+ { 59, 0, 0, 0 }, { 59, 0, 0, 0 }, { 38,13, 0, 0 }, { 22,60, 0, 0 },
+ { 22,60, 0, 0 }, { 26, 0, 0, 0 }, { 46, 0, 0, 0 }, { 29, 0, 0, 0 },
+ { 30, 0, 0, 0 }, { 32, 0, 0, 0 }, { 33, 0, 0, 0 }, { 35, 0, 0, 0 },
+ { 36, 0, 0, 0 }, { 36, 0, 0, 0 }, { 36, 0, 0, 0 }, { 38, 0, 0, 0 },
+ { 0,13, 0, 0 }, { 59,13, 0, 0 }, { 23,13, 0, 0 }, { 22,60, 0, 0 },
+ { 46,60, 0, 0 }, { 46, 0, 0, 0 }, { 45, 0, 0, 0 }, { 47, 0, 0, 0 },
+ { 48, 0, 0, 0 }, { 50, 0, 0, 0 }, { 50, 0, 0, 0 }, { 18, 0, 0, 0 },
+ { 54, 0, 0, 0 }, { 54, 0, 0, 0 }, { 54, 0, 0, 0 }, { 38, 0, 0, 0 },
+ { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 22,60, 0, 0 },
+ { 0,60, 0, 0 }, { 62, 0, 0, 0 }, { 63, 0, 0, 0 }, { 3, 0, 0, 0 },
+ { 33, 0, 0, 0 }, { 2, 0, 0, 0 }, { 2, 0, 0, 0 }, { 61, 0, 0, 0 },
+ { 20, 0, 0, 0 }, { 20, 0, 0, 0 }, { 20,13, 0, 0 }, { 21,13, 0, 0 },
+ { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 39,13, 0, 0 }, { 28,60, 0, 0 },
+ { 28,60, 0, 0 }, { 63, 0, 0, 0 }, { 63, 0, 0, 0 }, { 3, 0, 0, 0 },
+ { 33, 0, 0, 0 }, { 2, 0, 0, 0 }, { 2, 0, 0, 0 }, { 61, 0, 0, 0 },
+ { 38, 0, 0, 0 }, { 38, 0, 0, 0 }, { 38,13, 0, 0 }, { 21,13, 0, 0 },
+ { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 39,13, 0, 0 }, { 28,60, 0, 0 },
+ { 28,60, 0, 0 }, { 6, 0, 0, 0 }, { 6, 0, 0, 0 }, { 6, 0, 0, 0 },
+ { 2, 0, 0, 0 }, { 18, 0, 0, 0 }, { 61, 0, 0, 0 }, { 20, 0, 0, 0 },
+ { 21, 0, 0, 0 }, { 21, 0, 0, 0 }, { 21,13, 0, 0 }, { 59,13, 0, 0 },
+ { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 7,13, 0, 0 }, { 34,60,13, 0 },
+ { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 },
+ { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 },
+ { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 },
+ { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,60,13, 0 },
+ { 34,60,13, 0 }, { 51, 0, 0, 0 }, { 51, 0, 0, 0 }, { 51, 0, 0, 0 },
+ { 53, 0, 0, 0 }, { 54, 0, 0, 0 }, { 20, 0, 0, 0 }, { 38, 0, 0, 0 },
+ { 38, 0, 0, 0 }, { 57, 0, 0, 0 }, { 39,13, 0, 0 }, { 39,13, 0, 0 },
+ { 39,13, 0, 0 }, { 7,13, 0, 0 }, { 24,13, 0, 0 }, { 34,60,13, 0 },
+ { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 },
+ { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 },
+ { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 },
+ { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 }, { 4,60, 0, 0 },
+ { 4,60, 0, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 },
+ { 4, 0, 0, 0 }, { 56, 0, 0, 0 }, { 38, 0, 0, 0 }, { 57, 0, 0, 0 },
+ { 57,13, 0, 0 }, { 59,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13, 0, 0 },
+ { 7,13, 0, 0 }, { 42,13, 0, 0 }, { 42,13, 0, 0 }, { 34,60,13, 0 },
+ { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 },
+ { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 },
+ { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 },
+ { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 }, { 0,60,13, 0 },
+ { 0,60,13, 0 }, { 5, 0, 0, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 },
+ { 5, 0, 0, 0 }, { 21, 0, 0, 0 }, { 21, 0, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13, 0, 0 },
+ { 25,13, 0, 0 }, { 25,13, 0, 0 }, { 25,13, 0, 0 }, { 34,60,13, 0 },
+ { 4,13, 0, 0 }, { 4,13, 0, 0 }, { 4,13, 0, 0 }, { 4,13, 0, 0 },
+ { 5,13, 0, 0 }, { 23,13, 0, 0 }, { 23,13, 0, 0 }, { 39,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 42,13, 0, 0 },
+ { 25,13, 0, 0 }, { 25,13, 0, 0 }, { 22,13, 0, 0 }, { 31,60,13, 0 },
+ { 31,60,13, 0 }, { 39,60, 0, 0 }, { 39,60, 0, 0 }, { 39,60, 0, 0 },
+ { 39,60, 0, 0 }, { 7,60, 0, 0 }, { 7,60, 0, 0 }, { 42,60, 0, 0 },
+ { 0,60, 0, 0 }, { 25,60, 0, 0 }, { 22,60, 0, 0 }, { 22,60, 0, 0 },
+ { 22,60, 0, 0 }, { 28,60, 0, 0 }, { 34,60, 0, 0 }, { 31,16,13, 0 } },
+
+ { { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 },
+ { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 },
+ { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 },
+ { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 }, { 55, 0,13, 0 },
+ { 55, 0,13, 0 }, { 55, 0, 0, 0 }, { 40, 0, 0, 0 }, { 8, 0, 0, 0 },
+ { 9, 0, 0, 0 }, { 49, 0, 0, 0 }, { 49, 0, 0, 0 }, { 52, 0, 0, 0 },
+ { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 4,13, 0, 0 },
+ { 0,13, 0, 0 }, { 20,13, 0, 0 }, { 17, 0, 0, 0 }, { 60,13,60,13 },
+ { 40, 0, 0,13 }, { 40, 0, 0, 0 }, { 8, 0, 0, 0 }, { 43, 0, 0, 0 },
+ { 27, 0, 0, 0 }, { 49, 0, 0, 0 }, { 49, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 36, 0, 0, 0 },
+ { 42,13, 0, 0 }, { 42,13, 0, 0 }, { 17, 0, 0, 0 }, { 57,60,13, 0 },
+ { 57, 0,13, 0 }, { 40, 0, 0, 0 }, { 8, 0, 0, 0 }, { 26, 0, 0, 0 },
+ { 27, 0, 0, 0 }, { 49, 0, 0, 0 }, { 12, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 36, 0, 0, 0 },
+ { 0, 0,13, 0 }, { 38, 0,13, 0 }, { 36,13, 0, 0 }, { 1,60, 0, 0 },
+ { 8,60, 0, 0 }, { 8, 0, 0, 0 }, { 43, 0, 0, 0 }, { 9, 0, 0, 0 },
+ { 11, 0, 0, 0 }, { 49, 0, 0, 0 }, { 12, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 14, 0,13, 0 }, { 33, 0,13, 0 }, { 50, 0,13, 0 }, { 50, 0, 0, 0 },
+ { 50, 0,13, 0 }, { 61, 0,13, 0 }, { 36,13, 0, 0 }, { 39,60, 0, 0 },
+ { 8,60, 0, 0 }, { 8, 0, 0, 0 }, { 43, 0, 0, 0 }, { 46, 0, 0, 0 },
+ { 49, 0, 0, 0 }, { 52, 0, 0, 0 }, { 30, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 14, 0,13, 0 }, { 33, 0,13, 0 }, { 50, 0,13, 0 }, { 50, 0,13, 0 },
+ { 50,13,13, 0 }, { 50,13, 0, 0 }, { 18,13,13, 0 }, { 25,60,13, 0 },
+ { 8,60,13,13 }, { 8, 0, 0,13 }, { 43, 0, 0,13 }, { 46, 0, 0,13 },
+ { 49, 0, 0,13 }, { 52, 0, 0, 0 }, { 30, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 14, 0, 0, 0 }, { 18, 0,60, 0 }, { 5, 0, 0,13 }, { 5, 0, 0,13 },
+ { 5, 0, 0,13 }, { 61,13, 0,13 }, { 18,13,13, 0 }, { 23,13,60, 0 },
+ { 43,13, 0,13 }, { 43, 0, 0,13 }, { 43, 0, 0,13 }, { 9, 0, 0,13 },
+ { 49, 0, 0,13 }, { 52, 0, 0, 0 }, { 3, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 14, 0, 0, 0 }, { 50, 0, 0, 0 }, { 50,13,13, 0 }, { 50,13,13, 0 },
+ { 50,13,13, 0 }, { 61, 0, 0, 0 }, { 17,13,13, 0 }, { 24,60,13, 0 },
+ { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 },
+ { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 },
+ { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 },
+ { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 }, { 43,60,13, 0 },
+ { 43,60,13, 0 }, { 43, 0, 0, 0 }, { 43, 0,19, 0 }, { 9, 0, 0, 0 },
+ { 11, 0, 0, 0 }, { 52, 0, 0, 0 }, { 52, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 14, 0, 0, 0 }, { 17, 0, 0, 0 }, { 61,13, 0, 0 }, { 61,13, 0, 0 },
+ { 61,13, 0, 0 }, { 54, 0, 0, 0 }, { 17, 0,13,13 }, { 39,13,13, 0 },
+ { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 },
+ { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 },
+ { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 },
+ { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 }, { 45,13,13, 0 },
+ { 45,13,13, 0 }, { 45, 0,13, 0 }, { 44, 0,13, 0 }, { 27, 0, 0, 0 },
+ { 29, 0, 0, 0 }, { 52, 0, 0, 0 }, { 48, 0, 0, 0 }, { 52, 0, 0, 0 },
+ { 52, 0, 0, 0 }, { 17, 0, 0, 0 }, { 17, 0, 0, 0 }, { 17, 0,19, 0 },
+ { 17, 0,13, 0 }, { 2, 0,13, 0 }, { 17, 0,13, 0 }, { 7,13, 0, 0 },
+ { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 },
+ { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 },
+ { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 },
+ { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 27, 0, 0,13 },
+ { 27, 0, 0,13 }, { 27, 0, 0,13 }, { 9, 0, 0,13 }, { 27, 0, 0,13 },
+ { 27, 0, 0,13 }, { 12, 0, 0,13 }, { 52, 0, 0,13 }, { 14, 0, 0,13 },
+ { 14, 0, 0,13 }, { 58, 0, 0,13 }, { 41, 0, 0,13 }, { 41, 0, 0,13 },
+ { 41, 0, 0,13 }, { 6, 0, 0,13 }, { 17,60, 0,13 }, { 37, 0,19,13 },
+ { 9, 0, 0,13 }, { 9,16, 0,13 }, { 9, 0, 0,13 }, { 27, 0, 0,13 },
+ { 11, 0, 0,13 }, { 49, 0, 0, 0 }, { 12, 0, 0, 0 }, { 52, 0, 0, 0 },
+ { 14, 0, 0, 0 }, { 14, 0, 0, 0 }, { 14, 0, 0, 0 }, { 50, 0, 0, 0 },
+ { 0, 0, 0,13 }, { 53, 0, 0,13 }, { 17, 0, 0,13 }, { 28, 0,13, 0 },
+ { 52, 0,13, 0 }, { 52, 0,13, 0 }, { 49, 0,13, 0 }, { 52, 0, 0, 0 },
+ { 12, 0, 0, 0 }, { 52, 0, 0, 0 }, { 30, 0, 0, 0 }, { 14, 0, 0, 0 },
+ { 14, 0, 0, 0 }, { 17, 0, 0, 0 }, { 2, 0, 0, 0 }, { 2, 0, 0, 0 },
+ { 2, 0, 0, 0 }, { 38, 0, 0, 0 }, { 38, 0, 0, 0 }, { 34, 0, 0, 0 } } },
+
+ { { { 31,16,60,13 }, { 34,16,13, 0 }, { 34,16,13, 0 }, { 31,16,13, 0 },
+ { 31,16,13, 0 }, { 31,16,13, 0 }, { 31,16,13, 0 }, { 19,16,60, 0 },
+ { 19,16,60, 0 }, { 19,16,60, 0 }, { 19,16,60, 0 }, { 19,16,60, 0 },
+ { 19,16,60, 0 }, { 19,16,60, 0 }, { 31,16,60,13 }, { 19,37,16,60 },
+ { 44, 0, 0,60 }, { 44, 0, 0, 0 }, { 62, 0, 0, 0 }, { 30, 0, 0, 0 },
+ { 32, 0, 0, 0 }, { 58, 0, 0, 0 }, { 35, 0, 0, 0 }, { 36, 0, 0, 0 },
+ { 36, 0, 0, 0 }, { 38,13, 0, 0 }, { 0,13, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 39,13, 0, 0 }, { 34,60,13, 0 },
+ { 34, 0,13, 0 }, { 45, 0, 0, 0 }, { 47, 0, 0, 0 }, { 48, 0, 0, 0 },
+ { 33, 0, 0, 0 }, { 35, 0, 0, 0 }, { 35, 0, 0, 0 }, { 36, 0, 0, 0 },
+ { 38,13, 0, 0 }, { 38,13, 0, 0 }, { 38,13, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 39,13, 0, 0 }, { 34,60,13, 0 },
+ { 34, 0,13, 0 }, { 62, 0, 0, 0 }, { 30, 0, 0, 0 }, { 15, 0, 0, 0 },
+ { 50, 0, 0, 0 }, { 53, 0, 0, 0 }, { 53, 0, 0, 0 }, { 54,13, 0, 0 },
+ { 21,13, 0, 0 }, { 21,13, 0, 0 }, { 21,13, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 34,60,13, 0 },
+ { 30, 0,13, 0 }, { 30, 0, 0, 0 }, { 48, 0, 0, 0 }, { 33, 0, 0, 0 },
+ { 58, 0, 0, 0 }, { 18, 0, 0, 0 }, { 18, 0, 0, 0 }, { 56,13, 0, 0 },
+ { 23,13, 0, 0 }, { 23,13, 0, 0 }, { 23,13, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 24,13, 0, 0 }, { 34,60,13, 0 },
+ { 34, 0,13, 0 }, { 6, 0, 0, 0 }, { 6, 0, 0, 0 }, { 58, 0, 0, 0 },
+ { 53, 0, 0, 0 }, { 54, 0, 0, 0 }, { 54, 0, 0, 0 }, { 21,13, 0, 0 },
+ { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 39,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 42,60, 0, 0 }, { 34,16,13, 0 },
+ { 6, 0,13, 0 }, { 6, 0, 0, 0 }, { 33, 0, 0, 0 }, { 58, 0, 0, 0 },
+ { 53, 0, 0, 0 }, { 54, 0, 0, 0 }, { 61, 0, 0, 0 }, { 21,13, 0, 0 },
+ { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 39,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 42,60, 0, 0 }, { 34,16,13, 0 },
+ { 34, 0,13, 0 }, { 51, 0, 0, 0 }, { 51, 0, 0, 0 }, { 53, 0, 0, 0 },
+ { 54, 0, 0, 0 }, { 56,13, 0, 0 }, { 56,13, 0, 0 }, { 57,13, 0, 0 },
+ { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 7,13, 0, 0 },
+ { 42,13, 0, 0 }, { 42,13, 0, 0 }, { 25,60, 0, 0 }, { 31,16,13, 0 },
+ { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 },
+ { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 },
+ { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 },
+ { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 }, { 31, 0,13, 0 },
+ { 31, 0,13, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 },
+ { 5,13, 0, 0 }, { 23,13, 0, 0 }, { 23,13, 0, 0 }, { 39,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 42,13, 0, 0 },
+ { 25,13, 0, 0 }, { 25,13, 0, 0 }, { 22,60, 0, 0 }, { 31,16,60, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 5,13, 0, 0 }, { 5,13, 0, 0 }, { 5,13, 0, 0 },
+ { 5,13, 0, 0 }, { 57,13, 0, 0 }, { 57,13, 0, 0 }, { 39,13, 0, 0 },
+ { 24,13, 0, 0 }, { 24,13, 0, 0 }, { 24,13, 0, 0 }, { 42,13, 0, 0 },
+ { 22,13, 0, 0 }, { 22,60, 0, 0 }, { 28,60,13, 0 }, { 31,16,60, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 }, { 31,13, 0, 0 },
+ { 31,13, 0, 0 }, { 41,13, 0, 0 }, { 41,13, 0, 0 }, { 41,13, 0, 0 },
+ { 41,13, 0, 0 }, { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 7,13, 0, 0 },
+ { 42,13, 0, 0 }, { 42,13, 0, 0 }, { 42,13, 0, 0 }, { 25,13, 0, 0 },
+ { 28,13, 0, 0 }, { 28,60, 0, 0 }, { 28,60,13, 0 }, { 31,16,60,13 },
+ { 31,13, 0, 0 }, { 41,13, 0, 0 }, { 41,13, 0, 0 }, { 41,13, 0, 0 },
+ { 41,13, 0, 0 }, { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 24,13, 0, 0 },
+ { 25,60, 0, 0 }, { 25,60, 0, 0 }, { 25,60, 0, 0 }, { 22,60, 0, 0 },
+ { 28,60, 0, 0 }, { 28,60, 0, 0 }, { 34,60,13, 0 }, { 31,16,60,13 },
+ { 31,60,13,13 }, { 10,60,13, 0 }, { 10,60,13, 0 }, { 10,60,13, 0 },
+ { 10,60,13, 0 }, { 10,60,13, 0 }, { 10,60,13, 0 }, { 28,60,13, 0 },
+ { 34,60,13, 0 }, { 34,60,13, 0 }, { 34,16,13, 0 }, { 34,16,13, 0 },
+ { 34,16,60, 0 }, { 34,16,60, 0 }, { 31,16,60, 0 }, { 19,37,16,13 } },
+
+ { { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 },
+ { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 },
+ { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 },
+ { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 }, { 8, 0,16, 0 },
+ { 8, 0,16, 0 }, { 8, 0, 0, 0 }, { 9, 0, 0, 0 }, { 11, 0, 0, 0 },
+ { 47, 0, 0, 0 }, { 32, 0, 0, 0 }, { 50, 0, 0, 0 }, { 18, 0, 0, 0 },
+ { 18, 0, 0, 0 }, { 20, 0, 0, 0 }, { 21, 0, 0, 0 }, { 21, 0, 0, 0 },
+ { 21,13, 0, 0 }, { 39,13, 0, 0 }, { 59,13, 0, 0 }, { 34,16,60, 0 },
+ { 26, 0, 0, 0 }, { 26, 0, 0, 0 }, { 27, 0, 0, 0 }, { 29, 0, 0, 0 },
+ { 30, 0, 0, 0 }, { 33, 0, 0, 0 }, { 50, 0, 0, 0 }, { 18, 0, 0, 0 },
+ { 18, 0, 0, 0 }, { 20, 0, 0, 0 }, { 57, 0, 0, 0 }, { 57,13, 0, 0 },
+ { 57,13, 0, 0 }, { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 34,16,60, 0 },
+ { 27, 0, 0, 0 }, { 27, 0, 0, 0 }, { 11, 0, 0, 0 }, { 12, 0, 0, 0 },
+ { 48, 0, 0, 0 }, { 50, 0, 0, 0 }, { 58, 0, 0, 0 }, { 61, 0, 0, 0 },
+ { 61, 0, 0, 0 }, { 56, 0, 0, 0 }, { 57,13, 0, 0 }, { 57,13, 0, 0 },
+ { 57,13, 0, 0 }, { 59,13, 0, 0 }, { 39,13, 0, 0 }, { 34,16,60, 0 },
+ { 45, 0, 0, 0 }, { 45, 0, 0, 0 }, { 12, 0, 0, 0 }, { 30, 0, 0, 0 },
+ { 32, 0, 0, 0 }, { 2, 0, 0, 0 }, { 2, 0, 0, 0 }, { 61, 0, 0, 0 },
+ { 38, 0, 0, 0 }, { 38, 0, 0, 0 }, { 38,13, 0, 0 }, { 57,13, 0, 0 },
+ { 0,13, 0, 0 }, { 59,13, 0, 0 }, { 39,13, 0, 0 }, { 34,16,60, 0 },
+ { 63, 0, 0, 0 }, { 63, 0, 0, 0 }, { 3, 0, 0, 0 }, { 32, 0, 0, 0 },
+ { 58, 0, 0, 0 }, { 18, 0, 0, 0 }, { 18, 0, 0, 0 }, { 20, 0, 0, 0 },
+ { 21, 0, 0, 0 }, { 21, 0, 0, 0 }, { 21,13, 0, 0 }, { 59,13, 0, 0 },
+ { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 7,13,13, 0 }, { 31,16,60, 0 },
+ { 31, 0, 0, 0 }, { 3, 0, 0, 0 }, { 3, 0, 0, 0 }, { 33, 0, 0, 0 },
+ { 58, 0, 0, 0 }, { 18, 0, 0, 0 }, { 18, 0, 0, 0 }, { 20, 0, 0, 0 },
+ { 21, 0, 0, 0 }, { 21, 0, 0, 0 }, { 21,13, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13,13, 0 }, { 31,16,60, 0 },
+ { 6, 0, 0, 0 }, { 6, 0, 0, 0 }, { 51, 0, 0, 0 }, { 51, 0, 0, 0 },
+ { 53, 0, 0, 0 }, { 54, 0, 0, 0 }, { 54, 0, 0, 0 }, { 38, 0, 0, 0 },
+ { 57,13, 0, 0 }, { 57,13, 0, 0 }, { 57,13, 0, 0 }, { 39,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 42,60,13, 0 }, { 31,16,60, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 51, 0, 0, 0 }, { 53, 0, 0, 0 }, { 53, 0, 0, 0 },
+ { 54, 0, 0, 0 }, { 56, 0, 0, 0 }, { 56, 0, 0, 0 }, { 57,13, 0, 0 },
+ { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 59,13, 0, 0 }, { 7,13, 0, 0 },
+ { 24,13, 0, 0 }, { 24,13, 0, 0 }, { 25,60,13, 0 }, { 31,16,60, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 }, { 31, 0, 0, 0 },
+ { 31, 0, 0, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 }, { 4, 0, 0, 0 },
+ { 54, 0, 0, 0 }, { 21,13, 0, 0 }, { 21, 0, 0, 0 }, { 57,13, 0, 0 },
+ { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 39,13, 0, 0 }, { 7,13, 0, 0 },
+ { 42,13,13, 0 }, { 42,13,13, 0 }, { 22,60,13, 0 }, { 31,16,60, 0 },
+ { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 },
+ { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 },
+ { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 },
+ { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 }, { 31,16, 0, 0 },
+ { 31,16, 0, 0 }, { 5, 0, 0, 0 }, { 5, 0, 0, 0 }, { 5, 0, 0, 0 },
+ { 5,13, 0, 0 }, { 23,13, 0, 0 }, { 23,13, 0, 0 }, { 59,13, 0, 0 },
+ { 7,13, 0, 0 }, { 7,13, 0, 0 }, { 7,13,13, 0 }, { 42,13,13, 0 },
+ { 22,60,13, 0 }, { 22,60,13, 0 }, { 28,60,13, 0 }, { 31,16,60, 0 },
+ { 31,13, 0, 0 }, { 4,13, 0, 0 }, { 4,13, 0, 0 }, { 4,13, 0, 0 },
+ { 5,13, 0, 0 }, { 23,13, 0, 0 }, { 23,13, 0, 0 }, { 39,13,13, 0 },
+ { 24,60,13, 0 }, { 24,60,13, 0 }, { 24,60,13, 0 }, { 25,60,13, 0 },
+ { 28,60,13, 0 }, { 28,60,13, 0 }, { 34,16,13, 0 }, { 31,16,60, 0 },
+ { 31,16,13, 0 }, { 10,16,13, 0 }, { 10,16,13, 0 }, { 10,16,13, 0 },
+ { 10,16,13, 0 }, { 10,16,60, 0 }, { 10,16,60, 0 }, { 28,16,60, 0 },
+ { 34,16,60, 0 }, { 34,16,60, 0 }, { 34,16,60, 0 }, { 31,16,60, 0 },
+ { 31,16,60, 0 }, { 31,16,60, 0 }, { 31,16,60, 0 }, { 19,37,60, 0 } } }
+};
+
+const struct lc3_ac_model lc3_spectrum_models[] = {
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 175 }, { 177, 48 },
+ { 225, 1 }, { 226, 1 }, { 227, 109 }, { 336, 36 },
+ { 372, 171 }, { 543, 109 }, { 652, 47 }, { 699, 20 },
+ { 719, 49 }, { 768, 36 }, { 804, 20 }, { 824, 10 },
+ { 834, 190 } } },
+
+ { { { 0, 18 }, { 18, 26 }, { 44, 17 }, { 61, 10 },
+ { 71, 27 }, { 98, 37 }, { 135, 24 }, { 159, 16 },
+ { 175, 22 }, { 197, 32 }, { 229, 22 }, { 251, 14 },
+ { 265, 17 }, { 282, 26 }, { 308, 20 }, { 328, 13 },
+ { 341, 683 } } },
+
+ { { { 0, 71 }, { 71, 92 }, { 163, 49 }, { 212, 25 },
+ { 237, 81 }, { 318, 102 }, { 420, 61 }, { 481, 33 },
+ { 514, 42 }, { 556, 57 }, { 613, 39 }, { 652, 23 },
+ { 675, 22 }, { 697, 30 }, { 727, 22 }, { 749, 15 },
+ { 764, 260 } } },
+
+ { { { 0, 160 }, { 160, 130 }, { 290, 46 }, { 336, 18 },
+ { 354, 121 }, { 475, 123 }, { 598, 55 }, { 653, 24 },
+ { 677, 45 }, { 722, 55 }, { 777, 31 }, { 808, 15 },
+ { 823, 19 }, { 842, 24 }, { 866, 15 }, { 881, 9 },
+ { 890, 134 } } },
+
+ { { { 0, 71 }, { 71, 73 }, { 144, 33 }, { 177, 18 },
+ { 195, 71 }, { 266, 76 }, { 342, 43 }, { 385, 26 },
+ { 411, 34 }, { 445, 44 }, { 489, 30 }, { 519, 20 },
+ { 539, 20 }, { 559, 27 }, { 586, 21 }, { 607, 15 },
+ { 622, 402 } } },
+
+ { { { 0, 48 }, { 48, 60 }, { 108, 32 }, { 140, 19 },
+ { 159, 58 }, { 217, 68 }, { 285, 42 }, { 327, 27 },
+ { 354, 31 }, { 385, 42 }, { 427, 30 }, { 457, 21 },
+ { 478, 19 }, { 497, 27 }, { 524, 21 }, { 545, 16 },
+ { 561, 463 } } },
+
+ { { { 0, 138 }, { 138, 109 }, { 247, 43 }, { 290, 18 },
+ { 308, 111 }, { 419, 112 }, { 531, 53 }, { 584, 25 },
+ { 609, 46 }, { 655, 55 }, { 710, 32 }, { 742, 17 },
+ { 759, 21 }, { 780, 27 }, { 807, 18 }, { 825, 11 },
+ { 836, 188 } } },
+
+ { { { 0, 16 }, { 16, 24 }, { 40, 22 }, { 62, 17 },
+ { 79, 24 }, { 103, 36 }, { 139, 31 }, { 170, 25 },
+ { 195, 20 }, { 215, 30 }, { 245, 25 }, { 270, 20 },
+ { 290, 15 }, { 305, 22 }, { 327, 19 }, { 346, 16 },
+ { 362, 662 } } },
+
+ { { { 0, 579 }, { 579, 150 }, { 729, 12 }, { 741, 2 },
+ { 743, 154 }, { 897, 73 }, { 970, 10 }, { 980, 2 },
+ { 982, 14 }, { 996, 11 }, { 1007, 3 }, { 1010, 1 },
+ { 1011, 3 }, { 1014, 3 }, { 1017, 1 }, { 1018, 1 },
+ { 1019, 5 } } },
+
+ { { { 0, 398 }, { 398, 184 }, { 582, 25 }, { 607, 5 },
+ { 612, 176 }, { 788, 114 }, { 902, 23 }, { 925, 6 },
+ { 931, 25 }, { 956, 23 }, { 979, 8 }, { 987, 3 },
+ { 990, 6 }, { 996, 6 }, { 1002, 3 }, { 1005, 2 },
+ { 1007, 17 } } },
+
+ { { { 0, 13 }, { 13, 21 }, { 34, 18 }, { 52, 11 },
+ { 63, 20 }, { 83, 29 }, { 112, 22 }, { 134, 15 },
+ { 149, 14 }, { 163, 20 }, { 183, 16 }, { 199, 12 },
+ { 211, 10 }, { 221, 14 }, { 235, 12 }, { 247, 10 },
+ { 257, 767 } } },
+
+ { { { 0, 281 }, { 281, 183 }, { 464, 37 }, { 501, 9 },
+ { 510, 171 }, { 681, 139 }, { 820, 37 }, { 857, 10 },
+ { 867, 35 }, { 902, 36 }, { 938, 15 }, { 953, 6 },
+ { 959, 9 }, { 968, 10 }, { 978, 6 }, { 984, 3 },
+ { 987, 37 } } },
+
+ { { { 0, 198 }, { 198, 164 }, { 362, 46 }, { 408, 13 },
+ { 421, 154 }, { 575, 147 }, { 722, 51 }, { 773, 16 },
+ { 789, 43 }, { 832, 49 }, { 881, 24 }, { 905, 10 },
+ { 915, 13 }, { 928, 16 }, { 944, 10 }, { 954, 5 },
+ { 959, 65 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 93 }, { 95, 44 },
+ { 139, 1 }, { 140, 1 }, { 141, 72 }, { 213, 38 },
+ { 251, 86 }, { 337, 70 }, { 407, 43 }, { 450, 25 },
+ { 475, 40 }, { 515, 36 }, { 551, 25 }, { 576, 16 },
+ { 592, 432 } } },
+
+ { { { 0, 133 }, { 133, 141 }, { 274, 64 }, { 338, 28 },
+ { 366, 117 }, { 483, 122 }, { 605, 59 }, { 664, 27 },
+ { 691, 39 }, { 730, 48 }, { 778, 29 }, { 807, 15 },
+ { 822, 15 }, { 837, 20 }, { 857, 13 }, { 870, 8 },
+ { 878, 146 } } },
+
+ { { { 0, 128 }, { 128, 125 }, { 253, 49 }, { 302, 18 },
+ { 320, 123 }, { 443, 134 }, { 577, 59 }, { 636, 23 },
+ { 659, 49 }, { 708, 59 }, { 767, 32 }, { 799, 15 },
+ { 814, 19 }, { 833, 24 }, { 857, 15 }, { 872, 9 },
+ { 881, 143 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 23 }, { 25, 17 },
+ { 42, 1 }, { 43, 1 }, { 44, 23 }, { 67, 18 },
+ { 85, 20 }, { 105, 21 }, { 126, 18 }, { 144, 15 },
+ { 159, 15 }, { 174, 17 }, { 191, 14 }, { 205, 12 },
+ { 217, 807 } } },
+
+ { { { 0, 70 }, { 70, 96 }, { 166, 63 }, { 229, 38 },
+ { 267, 89 }, { 356, 112 }, { 468, 65 }, { 533, 36 },
+ { 569, 37 }, { 606, 47 }, { 653, 32 }, { 685, 20 },
+ { 705, 17 }, { 722, 23 }, { 745, 17 }, { 762, 12 },
+ { 774, 250 } } },
+
+ { { { 0, 55 }, { 55, 75 }, { 130, 45 }, { 175, 25 },
+ { 200, 68 }, { 268, 90 }, { 358, 58 }, { 416, 33 },
+ { 449, 39 }, { 488, 54 }, { 542, 39 }, { 581, 25 },
+ { 606, 22 }, { 628, 31 }, { 659, 24 }, { 683, 16 },
+ { 699, 325 } } },
+
+ { { { 0, 1 }, { 1, 2 }, { 3, 2 }, { 5, 2 },
+ { 7, 2 }, { 9, 2 }, { 11, 2 }, { 13, 2 },
+ { 15, 2 }, { 17, 2 }, { 19, 2 }, { 21, 2 },
+ { 23, 2 }, { 25, 2 }, { 27, 2 }, { 29, 2 },
+ { 31, 993 } } },
+
+ { { { 0, 34 }, { 34, 51 }, { 85, 38 }, { 123, 24 },
+ { 147, 49 }, { 196, 69 }, { 265, 52 }, { 317, 35 },
+ { 352, 34 }, { 386, 47 }, { 433, 37 }, { 470, 27 },
+ { 497, 21 }, { 518, 31 }, { 549, 25 }, { 574, 19 },
+ { 593, 431 } } },
+
+ { { { 0, 30 }, { 30, 43 }, { 73, 32 }, { 105, 22 },
+ { 127, 43 }, { 170, 59 }, { 229, 45 }, { 274, 31 },
+ { 305, 30 }, { 335, 42 }, { 377, 34 }, { 411, 25 },
+ { 436, 19 }, { 455, 28 }, { 483, 23 }, { 506, 18 },
+ { 524, 500 } } },
+
+ { { { 0, 9 }, { 9, 15 }, { 24, 14 }, { 38, 13 },
+ { 51, 14 }, { 65, 22 }, { 87, 21 }, { 108, 18 },
+ { 126, 13 }, { 139, 20 }, { 159, 18 }, { 177, 16 },
+ { 193, 11 }, { 204, 17 }, { 221, 15 }, { 236, 14 },
+ { 250, 774 } } },
+
+ { { { 0, 30 }, { 30, 44 }, { 74, 31 }, { 105, 20 },
+ { 125, 41 }, { 166, 58 }, { 224, 42 }, { 266, 28 },
+ { 294, 28 }, { 322, 39 }, { 361, 30 }, { 391, 22 },
+ { 413, 18 }, { 431, 26 }, { 457, 21 }, { 478, 16 },
+ { 494, 530 } } },
+
+ { { { 0, 15 }, { 15, 23 }, { 38, 20 }, { 58, 15 },
+ { 73, 22 }, { 95, 33 }, { 128, 28 }, { 156, 22 },
+ { 178, 18 }, { 196, 26 }, { 222, 23 }, { 245, 18 },
+ { 263, 13 }, { 276, 20 }, { 296, 18 }, { 314, 15 },
+ { 329, 695 } } },
+
+ { { { 0, 11 }, { 11, 17 }, { 28, 16 }, { 44, 13 },
+ { 57, 17 }, { 74, 26 }, { 100, 23 }, { 123, 19 },
+ { 142, 15 }, { 157, 22 }, { 179, 20 }, { 199, 17 },
+ { 216, 12 }, { 228, 18 }, { 246, 16 }, { 262, 14 },
+ { 276, 748 } } },
+
+ { { { 0, 448 }, { 448, 171 }, { 619, 20 }, { 639, 4 },
+ { 643, 178 }, { 821, 105 }, { 926, 18 }, { 944, 4 },
+ { 948, 23 }, { 971, 20 }, { 991, 7 }, { 998, 2 },
+ { 1000, 5 }, { 1005, 5 }, { 1010, 2 }, { 1012, 1 },
+ { 1013, 11 } } },
+
+ { { { 0, 332 }, { 332, 188 }, { 520, 29 }, { 549, 6 },
+ { 555, 186 }, { 741, 133 }, { 874, 29 }, { 903, 7 },
+ { 910, 30 }, { 940, 30 }, { 970, 11 }, { 981, 4 },
+ { 985, 6 }, { 991, 7 }, { 998, 4 }, { 1002, 2 },
+ { 1004, 20 } } },
+
+ { { { 0, 8 }, { 8, 13 }, { 21, 13 }, { 34, 11 },
+ { 45, 13 }, { 58, 20 }, { 78, 18 }, { 96, 16 },
+ { 112, 12 }, { 124, 17 }, { 141, 16 }, { 157, 13 },
+ { 170, 10 }, { 180, 14 }, { 194, 13 }, { 207, 12 },
+ { 219, 805 } } },
+
+ { { { 0, 239 }, { 239, 176 }, { 415, 42 }, { 457, 11 },
+ { 468, 163 }, { 631, 145 }, { 776, 44 }, { 820, 13 },
+ { 833, 39 }, { 872, 42 }, { 914, 19 }, { 933, 7 },
+ { 940, 11 }, { 951, 13 }, { 964, 7 }, { 971, 4 },
+ { 975, 49 } } },
+
+ { { { 0, 165 }, { 165, 145 }, { 310, 49 }, { 359, 16 },
+ { 375, 138 }, { 513, 139 }, { 652, 55 }, { 707, 20 },
+ { 727, 47 }, { 774, 54 }, { 828, 28 }, { 856, 12 },
+ { 868, 16 }, { 884, 20 }, { 904, 12 }, { 916, 7 },
+ { 923, 101 } } },
+
+ { { { 0, 3 }, { 3, 5 }, { 8, 5 }, { 13, 5 },
+ { 18, 5 }, { 23, 7 }, { 30, 7 }, { 37, 7 },
+ { 44, 4 }, { 48, 7 }, { 55, 7 }, { 62, 6 },
+ { 68, 4 }, { 72, 6 }, { 78, 6 }, { 84, 6 },
+ { 90, 934 } } },
+
+ { { { 0, 115 }, { 115, 122 }, { 237, 52 }, { 289, 22 },
+ { 311, 111 }, { 422, 125 }, { 547, 61 }, { 608, 27 },
+ { 635, 45 }, { 680, 57 }, { 737, 34 }, { 771, 17 },
+ { 788, 19 }, { 807, 25 }, { 832, 17 }, { 849, 10 },
+ { 859, 165 } } },
+
+ { { { 0, 107 }, { 107, 114 }, { 221, 51 }, { 272, 21 },
+ { 293, 106 }, { 399, 122 }, { 521, 61 }, { 582, 28 },
+ { 610, 46 }, { 656, 58 }, { 714, 35 }, { 749, 18 },
+ { 767, 20 }, { 787, 26 }, { 813, 18 }, { 831, 11 },
+ { 842, 182 } } },
+
+ { { { 0, 6 }, { 6, 10 }, { 16, 10 }, { 26, 9 },
+ { 35, 10 }, { 45, 15 }, { 60, 15 }, { 75, 14 },
+ { 89, 9 }, { 98, 14 }, { 112, 13 }, { 125, 12 },
+ { 137, 8 }, { 145, 12 }, { 157, 11 }, { 168, 10 },
+ { 178, 846 } } },
+
+ { { { 0, 72 }, { 72, 88 }, { 160, 50 }, { 210, 26 },
+ { 236, 84 }, { 320, 102 }, { 422, 60 }, { 482, 32 },
+ { 514, 41 }, { 555, 53 }, { 608, 36 }, { 644, 21 },
+ { 665, 20 }, { 685, 27 }, { 712, 20 }, { 732, 13 },
+ { 745, 279 } } },
+
+ { { { 0, 45 }, { 45, 63 }, { 108, 45 }, { 153, 30 },
+ { 183, 61 }, { 244, 83 }, { 327, 58 }, { 385, 36 },
+ { 421, 34 }, { 455, 47 }, { 502, 34 }, { 536, 23 },
+ { 559, 19 }, { 578, 27 }, { 605, 21 }, { 626, 15 },
+ { 641, 383 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 7 }, { 9, 7 },
+ { 16, 1 }, { 17, 1 }, { 18, 8 }, { 26, 8 },
+ { 34, 6 }, { 40, 8 }, { 48, 7 }, { 55, 7 },
+ { 62, 6 }, { 68, 7 }, { 75, 7 }, { 82, 6 },
+ { 88, 936 } } },
+
+ { { { 0, 29 }, { 29, 44 }, { 73, 35 }, { 108, 24 },
+ { 132, 42 }, { 174, 62 }, { 236, 48 }, { 284, 34 },
+ { 318, 30 }, { 348, 43 }, { 391, 35 }, { 426, 26 },
+ { 452, 19 }, { 471, 29 }, { 500, 24 }, { 524, 19 },
+ { 543, 481 } } },
+
+ { { { 0, 20 }, { 20, 31 }, { 51, 25 }, { 76, 17 },
+ { 93, 30 }, { 123, 43 }, { 166, 34 }, { 200, 25 },
+ { 225, 22 }, { 247, 32 }, { 279, 26 }, { 305, 21 },
+ { 326, 16 }, { 342, 23 }, { 365, 20 }, { 385, 16 },
+ { 401, 623 } } },
+
+ { { { 0, 742 }, { 742, 103 }, { 845, 5 }, { 850, 1 },
+ { 851, 108 }, { 959, 38 }, { 997, 4 }, { 1001, 1 },
+ { 1002, 7 }, { 1009, 5 }, { 1014, 2 }, { 1016, 1 },
+ { 1017, 2 }, { 1019, 1 }, { 1020, 1 }, { 1021, 1 },
+ { 1022, 2 } } },
+
+ { { { 0, 42 }, { 42, 52 }, { 94, 27 }, { 121, 16 },
+ { 137, 49 }, { 186, 58 }, { 244, 36 }, { 280, 23 },
+ { 303, 27 }, { 330, 36 }, { 366, 26 }, { 392, 18 },
+ { 410, 17 }, { 427, 24 }, { 451, 19 }, { 470, 14 },
+ { 484, 540 } } },
+
+ { { { 0, 13 }, { 13, 20 }, { 33, 18 }, { 51, 15 },
+ { 66, 19 }, { 85, 29 }, { 114, 26 }, { 140, 21 },
+ { 161, 17 }, { 178, 25 }, { 203, 22 }, { 225, 18 },
+ { 243, 13 }, { 256, 19 }, { 275, 17 }, { 292, 15 },
+ { 307, 717 } } },
+
+ { { { 0, 501 }, { 501, 169 }, { 670, 19 }, { 689, 4 },
+ { 693, 155 }, { 848, 88 }, { 936, 16 }, { 952, 4 },
+ { 956, 19 }, { 975, 16 }, { 991, 6 }, { 997, 2 },
+ { 999, 5 }, { 1004, 4 }, { 1008, 2 }, { 1010, 1 },
+ { 1011, 13 } } },
+
+ { { { 0, 445 }, { 445, 136 }, { 581, 22 }, { 603, 6 },
+ { 609, 158 }, { 767, 98 }, { 865, 23 }, { 888, 7 },
+ { 895, 31 }, { 926, 28 }, { 954, 10 }, { 964, 4 },
+ { 968, 9 }, { 977, 9 }, { 986, 5 }, { 991, 2 },
+ { 993, 31 } } },
+
+ { { { 0, 285 }, { 285, 157 }, { 442, 37 }, { 479, 10 },
+ { 489, 161 }, { 650, 129 }, { 779, 39 }, { 818, 12 },
+ { 830, 40 }, { 870, 42 }, { 912, 18 }, { 930, 7 },
+ { 937, 12 }, { 949, 14 }, { 963, 8 }, { 971, 4 },
+ { 975, 49 } } },
+
+ { { { 0, 349 }, { 349, 179 }, { 528, 33 }, { 561, 8 },
+ { 569, 162 }, { 731, 121 }, { 852, 31 }, { 883, 9 },
+ { 892, 31 }, { 923, 30 }, { 953, 12 }, { 965, 5 },
+ { 970, 8 }, { 978, 9 }, { 987, 5 }, { 992, 2 },
+ { 994, 30 } } },
+
+ { { { 0, 199 }, { 199, 156 }, { 355, 47 }, { 402, 15 },
+ { 417, 146 }, { 563, 137 }, { 700, 50 }, { 750, 17 },
+ { 767, 44 }, { 811, 49 }, { 860, 24 }, { 884, 10 },
+ { 894, 15 }, { 909, 17 }, { 926, 10 }, { 936, 6 },
+ { 942, 82 } } },
+
+ { { { 0, 141 }, { 141, 134 }, { 275, 50 }, { 325, 18 },
+ { 343, 128 }, { 471, 135 }, { 606, 58 }, { 664, 22 },
+ { 686, 48 }, { 734, 57 }, { 791, 31 }, { 822, 14 },
+ { 836, 18 }, { 854, 23 }, { 877, 14 }, { 891, 8 },
+ { 899, 125 } } },
+
+ { { { 0, 243 }, { 243, 194 }, { 437, 56 }, { 493, 17 },
+ { 510, 139 }, { 649, 126 }, { 775, 45 }, { 820, 16 },
+ { 836, 33 }, { 869, 36 }, { 905, 18 }, { 923, 8 },
+ { 931, 10 }, { 941, 12 }, { 953, 7 }, { 960, 4 },
+ { 964, 60 } } },
+
+ { { { 0, 91 }, { 91, 106 }, { 197, 51 }, { 248, 23 },
+ { 271, 99 }, { 370, 117 }, { 487, 63 }, { 550, 30 },
+ { 580, 45 }, { 625, 59 }, { 684, 37 }, { 721, 20 },
+ { 741, 20 }, { 761, 27 }, { 788, 19 }, { 807, 12 },
+ { 819, 205 } } },
+
+ { { { 0, 107 }, { 107, 94 }, { 201, 41 }, { 242, 20 },
+ { 262, 92 }, { 354, 97 }, { 451, 52 }, { 503, 28 },
+ { 531, 42 }, { 573, 53 }, { 626, 34 }, { 660, 20 },
+ { 680, 21 }, { 701, 29 }, { 730, 21 }, { 751, 14 },
+ { 765, 259 } } },
+
+ { { { 0, 168 }, { 168, 171 }, { 339, 68 }, { 407, 25 },
+ { 432, 121 }, { 553, 123 }, { 676, 55 }, { 731, 24 },
+ { 755, 34 }, { 789, 41 }, { 830, 24 }, { 854, 12 },
+ { 866, 13 }, { 879, 16 }, { 895, 11 }, { 906, 6 },
+ { 912, 112 } } },
+
+ { { { 0, 67 }, { 67, 80 }, { 147, 44 }, { 191, 23 },
+ { 214, 76 }, { 290, 94 }, { 384, 57 }, { 441, 31 },
+ { 472, 41 }, { 513, 54 }, { 567, 37 }, { 604, 23 },
+ { 627, 21 }, { 648, 30 }, { 678, 22 }, { 700, 15 },
+ { 715, 309 } } },
+
+ { { { 0, 46 }, { 46, 63 }, { 109, 39 }, { 148, 23 },
+ { 171, 58 }, { 229, 78 }, { 307, 52 }, { 359, 32 },
+ { 391, 36 }, { 427, 49 }, { 476, 37 }, { 513, 24 },
+ { 537, 21 }, { 558, 30 }, { 588, 24 }, { 612, 17 },
+ { 629, 395 } } },
+
+ { { { 0, 848 }, { 848, 70 }, { 918, 2 }, { 920, 1 },
+ { 921, 75 }, { 996, 16 }, { 1012, 1 }, { 1013, 1 },
+ { 1014, 2 }, { 1016, 1 }, { 1017, 1 }, { 1018, 1 },
+ { 1019, 1 }, { 1020, 1 }, { 1021, 1 }, { 1022, 1 },
+ { 1023, 1 } } },
+
+ { { { 0, 36 }, { 36, 52 }, { 88, 35 }, { 123, 22 },
+ { 145, 48 }, { 193, 67 }, { 260, 48 }, { 308, 32 },
+ { 340, 32 }, { 372, 45 }, { 417, 35 }, { 452, 24 },
+ { 476, 20 }, { 496, 29 }, { 525, 23 }, { 548, 17 },
+ { 565, 459 } } },
+
+ { { { 0, 24 }, { 24, 37 }, { 61, 29 }, { 90, 20 },
+ { 110, 35 }, { 145, 51 }, { 196, 41 }, { 237, 29 },
+ { 266, 26 }, { 292, 38 }, { 330, 31 }, { 361, 24 },
+ { 385, 18 }, { 403, 27 }, { 430, 23 }, { 453, 18 },
+ { 471, 553 } } },
+
+ { { { 0, 85 }, { 85, 97 }, { 182, 48 }, { 230, 23 },
+ { 253, 91 }, { 344, 110 }, { 454, 61 }, { 515, 30 },
+ { 545, 45 }, { 590, 58 }, { 648, 37 }, { 685, 21 },
+ { 706, 21 }, { 727, 29 }, { 756, 20 }, { 776, 13 },
+ { 789, 235 } } },
+
+ { { { 0, 22 }, { 22, 33 }, { 55, 27 }, { 82, 20 },
+ { 102, 33 }, { 135, 48 }, { 183, 39 }, { 222, 30 },
+ { 252, 26 }, { 278, 37 }, { 315, 30 }, { 345, 23 },
+ { 368, 17 }, { 385, 25 }, { 410, 21 }, { 431, 17 },
+ { 448, 576 } } },
+
+ { { { 0, 1 }, { 1, 1 }, { 2, 54 }, { 56, 33 },
+ { 89, 1 }, { 90, 1 }, { 91, 49 }, { 140, 32 },
+ { 172, 49 }, { 221, 47 }, { 268, 35 }, { 303, 25 },
+ { 328, 30 }, { 358, 30 }, { 388, 24 }, { 412, 18 },
+ { 430, 594 } } },
+
+ { { { 0, 45 }, { 45, 64 }, { 109, 43 }, { 152, 25 },
+ { 177, 62 }, { 239, 81 }, { 320, 56 }, { 376, 35 },
+ { 411, 37 }, { 448, 51 }, { 499, 38 }, { 537, 26 },
+ { 563, 22 }, { 585, 31 }, { 616, 24 }, { 640, 18 },
+ { 658, 366 } } },
+
+ { { { 0, 247 }, { 247, 148 }, { 395, 38 }, { 433, 12 },
+ { 445, 154 }, { 599, 130 }, { 729, 42 }, { 771, 14 },
+ { 785, 44 }, { 829, 46 }, { 875, 21 }, { 896, 9 },
+ { 905, 15 }, { 920, 17 }, { 937, 9 }, { 946, 5 },
+ { 951, 73 } } },
+
+ { { { 0, 231 }, { 231, 136 }, { 367, 41 }, { 408, 15 },
+ { 423, 134 }, { 557, 119 }, { 676, 47 }, { 723, 19 },
+ { 742, 44 }, { 786, 49 }, { 835, 25 }, { 860, 12 },
+ { 872, 17 }, { 889, 20 }, { 909, 12 }, { 921, 7 },
+ { 928, 96 } } }
+
+};
+
+const uint16_t lc3_spectrum_bits[][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 },
+
+ { 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 },
+
+ { 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 },
+
+ { 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 }
+
+};
diff --git a/src/tables.h b/src/tables.h
new file mode 100644
index 0000000..26bd48e
--- /dev/null
+++ b/src/tables.h
@@ -0,0 +1,94 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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_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 */
diff --git a/src/tns.c b/src/tns.c
new file mode 100644
index 0000000..19bf149
--- /dev/null
+++ b/src/tns.c
@@ -0,0 +1,457 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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]
+ */
+LC3_HOT 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
+ */
+LC3_HOT 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
+ */
+LC3_HOT static void lpc_weighting(float pred_gain, float *a)
+{
+ float gamma = 1.f - (1.f - 0.85f) * (2.f - pred_gain) / (2.f - 1.5f);
+ float g = 1.f;
+
+ for (int i = 1; i < 9; i++)
+ a[i] *= (g *= gamma);
+}
+
+/**
+ * LPC reflection
+ * a LPC coefficients
+ * rc Output refelection coefficients
+ */
+LC3_HOT 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
+ */
+LC3_HOT static void forward_filtering(
+ enum lc3_dt dt, enum lc3_bandwidth bw,
+ const int rc_order[2], float (* const rc)[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
+ */
+LC3_HOT static void inverse_filtering(
+ enum lc3_dt dt, enum lc3_bandwidth bw,
+ const int rc_order[2], float (* const rc)[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.5f)
+ continue;
+
+ if (data->lpc_weighting && pred_gain[f] < 2.f)
+ 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] = { 0 };
+
+ 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;
+ }
+}
diff --git a/src/tns.h b/src/tns.h
new file mode 100644
index 0000000..534f191
--- /dev/null
+++ b/src/tns.h
@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 */
diff --git a/tables/fastmath.py b/tables/fastmath.py
new file mode 100755
index 0000000..202561a
--- /dev/null
+++ b/tables/fastmath.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+
+def fast_exp2(x, p):
+
+ p = p.astype(np.float32)
+ x = x.astype(np.float32)
+
+ y = (((((p[0]*x) + p[1])*x + p[2])*x + p[3])*x + p[4])*x + 1
+
+ return np.power(y.astype(np.float32), 16)
+
+def approx_exp2():
+
+ x = np.arange(-8, 8, step=1e-3)
+
+ p = np.polyfit(x, ((2 ** (x/16)) - 1) / x, 4)
+ y = [ fast_exp2(x[i], p) for i in range(len(x)) ]
+ e = np.abs(y - 2**x) / (2 ** x)
+
+ print('{{ {:14.8e}, {:14.8e}, {:14.8e}, {:14.8e}, {:14.8e} }}'
+ .format(p[0], p[1], p[2], p[3], p[4]))
+ print('Max relative error: ', np.max(e))
+ print('Max RMS error: ', np.sqrt(np.mean(e ** 2)))
+
+ if False:
+ fig, (ax1, ax2) = plt.subplots(2)
+
+ ax1.plot(x, 2**x, label='Reference')
+ ax1.plot(x, y, label='Approximation')
+ ax1.legend()
+
+ ax2.plot(x, e, label='Relative Error')
+ ax2.legend()
+
+ plt.show()
+
+
+def fast_log2(x, p):
+
+ p = p.astype(np.float32)
+ x = x.astype(np.float32)
+
+ (x, e) = np.frexp(x)
+
+ y = ((((p[0]*x) + p[1])*x + p[2])*x + p[3])*x + p[4]
+
+ return (e ) + y.astype(np.float32)
+
+def approx_log2():
+
+ x = np.logspace(-1, 0, base=2, num=100)
+ p = np.polyfit(x, np.log2(x), 4)
+
+ x = np.logspace(-2, 5, num=10000)
+ y = [ fast_log2(x[i], p) for i in range(len(x)) ]
+ e = np.abs(y - np.log2(x))
+
+ print('{{ {:14.8e}, {:14.8e}, {:14.8e}, {:14.8e}, {:14.8e} }}'
+ .format(p[0], p[1], p[2], p[3], p[4]))
+ print('Max absolute error: ', np.max(e))
+ print('Max RMS error: ', np.sqrt(np.mean(e ** 2)))
+
+ if False:
+ fig, (ax1, ax2) = plt.subplots(2)
+
+ ax1.plot(x, np.log2(x), label='Reference')
+ ax1.plot(x, y, label='Approximation')
+ ax1.legend()
+
+ ax2.plot(x, e, label = 'Absolute error')
+ ax2.legend()
+
+ plt.show()
+
+
+def table_db_q16():
+
+ k = 10 * np.log10(2);
+
+ for i in range(32):
+ a = k * np.log2(np.ldexp(32 + i , -5)) - (i // 16) * (k/2);
+ b = k * np.log2(np.ldexp(32 + i+1, -5)) - (i // 16) * (k/2);
+
+ an = np.ldexp(a, 15) + 0.5
+ bn = np.ldexp(b - a, 15) + 0.5
+ print('{{ {:5d}, {:4d} }},'
+ .format(int(np.ldexp(a, 15) + 0.5),
+ int(np.ldexp(b - a, 15) + 0.5)),
+ end = ' ' if i % 4 < 3 else '\n')
+
+
+if __name__ == '__main__':
+
+ print('\n--- Approximation of 2^n ---')
+ approx_exp2()
+
+ print('\n--- Approximation of log2(n) ---')
+ approx_log2()
+
+ print('\n--- Table of fixed Q16 dB ---')
+ table_db_q16()
+
+ print('')
diff --git a/tables/mktables.py b/tables/mktables.py
new file mode 100755
index 0000000..4f6f855
--- /dev/null
+++ b/tables/mktables.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+LTPF_H12K8 = np.array([
+ -2.04305583e-05, -4.46345894e-05, -7.16366399e-05, -1.00101113e-04,
+ -1.28372848e-04, -1.54543830e-04, -1.76544567e-04, -1.92256960e-04,
+ -1.99643819e-04, -1.96888686e-04, -1.82538332e-04, -1.55639427e-04,
+ -1.15860365e-04, -6.35893034e-05, 2.81006480e-19, 7.29218021e-05,
+ 1.52397076e-04, 2.34920777e-04, 3.16378650e-04, 3.92211738e-04,
+ 4.57623849e-04, 5.07824294e-04, 5.38295523e-04, 5.45072918e-04,
+ 5.25022155e-04, 4.76098424e-04, 3.97571380e-04, 2.90200217e-04,
+ 1.56344667e-04, -5.81880142e-19, -1.73252713e-04, -3.56385965e-04,
+ -5.41155231e-04, -7.18414023e-04, -8.78505232e-04, -1.01171451e-03,
+ -1.10876706e-03, -1.16134522e-03, -1.16260169e-03, -1.10764097e-03,
+ -9.93941563e-04, -8.21692190e-04, -5.94017766e-04, -3.17074654e-04,
+ 9.74695082e-19, 3.45293760e-04, 7.04480871e-04, 1.06133447e-03,
+ 1.39837473e-03, 1.69763080e-03, 1.94148675e-03, 2.11357591e-03,
+ 2.19968245e-03, 2.18860625e-03, 2.07294546e-03, 1.84975249e-03,
+ 1.52102188e-03, 1.09397426e-03, 5.81108062e-04, -1.42248266e-18,
+ -6.27153730e-04, -1.27425140e-03, -1.91223839e-03, -2.51026925e-03,
+ -3.03703830e-03, -3.46222687e-03, -3.75800672e-03, -3.90053247e-03,
+ -3.87135231e-03, -3.65866558e-03, -3.25835851e-03, -2.67475555e-03,
+ -1.92103305e-03, -1.01925433e-03, 1.86962369e-18, 1.09841545e-03,
+ 2.23113197e-03, 3.34830927e-03, 4.39702277e-03, 5.32342672e-03,
+ 6.07510531e-03, 6.60352025e-03, 6.86645399e-03, 6.83034270e-03,
+ 6.47239234e-03, 5.78237521e-03, 4.76401273e-03, 3.43586351e-03,
+ 1.83165284e-03, -2.25189837e-18, -1.99647619e-03, -4.08266886e-03,
+ -6.17308037e-03, -8.17444895e-03, -9.98882386e-03, -1.15169871e-02,
+ -1.26621006e-02, -1.33334458e-02, -1.34501120e-02, -1.29444881e-02,
+ -1.17654154e-02, -9.88086732e-03, -7.28003640e-03, -3.97473021e-03,
+ 2.50961778e-18, 4.58604422e-03, 9.70324900e-03, 1.52512477e-02,
+ 2.11120585e-02, 2.71533724e-02, 3.32324245e-02, 3.92003203e-02,
+ 4.49066644e-02, 5.02043309e-02, 5.49542017e-02, 5.90297032e-02,
+ 6.23209727e-02, 6.47385023e-02, 6.62161245e-02, 6.67132287e-02,
+ 6.62161245e-02, 6.47385023e-02, 6.23209727e-02, 5.90297032e-02,
+ 5.49542017e-02, 5.02043309e-02, 4.49066644e-02, 3.92003203e-02,
+ 3.32324245e-02, 2.71533724e-02, 2.11120585e-02, 1.52512477e-02,
+ 9.70324900e-03, 4.58604422e-03, 2.50961778e-18, -3.97473021e-03,
+ -7.28003640e-03, -9.88086732e-03, -1.17654154e-02, -1.29444881e-02,
+ -1.34501120e-02, -1.33334458e-02, -1.26621006e-02, -1.15169871e-02,
+ -9.98882386e-03, -8.17444895e-03, -6.17308037e-03, -4.08266886e-03,
+ -1.99647619e-03, -2.25189837e-18, 1.83165284e-03, 3.43586351e-03,
+ 4.76401273e-03, 5.78237521e-03, 6.47239234e-03, 6.83034270e-03,
+ 6.86645399e-03, 6.60352025e-03, 6.07510531e-03, 5.32342672e-03,
+ 4.39702277e-03, 3.34830927e-03, 2.23113197e-03, 1.09841545e-03,
+ 1.86962369e-18, -1.01925433e-03, -1.92103305e-03, -2.67475555e-03,
+ -3.25835851e-03, -3.65866558e-03, -3.87135231e-03, -3.90053247e-03,
+ -3.75800672e-03, -3.46222687e-03, -3.03703830e-03, -2.51026925e-03,
+ -1.91223839e-03, -1.27425140e-03, -6.27153730e-04, -1.42248266e-18,
+ 5.81108062e-04, 1.09397426e-03, 1.52102188e-03, 1.84975249e-03,
+ 2.07294546e-03, 2.18860625e-03, 2.19968245e-03, 2.11357591e-03,
+ 1.94148675e-03, 1.69763080e-03, 1.39837473e-03, 1.06133447e-03,
+ 7.04480871e-04, 3.45293760e-04, 9.74695082e-19, -3.17074654e-04,
+ -5.94017766e-04, -8.21692190e-04, -9.93941563e-04, -1.10764097e-03,
+ -1.16260169e-03, -1.16134522e-03, -1.10876706e-03, -1.01171451e-03,
+ -8.78505232e-04, -7.18414023e-04, -5.41155231e-04, -3.56385965e-04,
+ -1.73252713e-04, -5.81880142e-19, 1.56344667e-04, 2.90200217e-04,
+ 3.97571380e-04, 4.76098424e-04, 5.25022155e-04, 5.45072918e-04,
+ 5.38295523e-04, 5.07824294e-04, 4.57623849e-04, 3.92211738e-04,
+ 3.16378650e-04, 2.34920777e-04, 1.52397076e-04, 7.29218021e-05,
+ 2.81006480e-19, -6.35893034e-05, -1.15860365e-04, -1.55639427e-04,
+ -1.82538332e-04, -1.96888686e-04, -1.99643819e-04, -1.92256960e-04,
+ -1.76544567e-04, -1.54543830e-04, -1.28372848e-04, -1.00101113e-04,
+ -7.16366399e-05, -4.46345894e-05, -2.04305583e-05
+])
+
+LTPF_HI = np.array([
+ 6.69885837e-03, 3.96711478e-02, 1.06999186e-01, 2.09880463e-01,
+ 3.35690625e-01, 4.59220930e-01, 5.50075002e-01, 5.83527575e-01,
+ 5.50075002e-01, 4.59220930e-01, 3.35690625e-01, 2.09880463e-01,
+ 1.06999186e-01, 3.96711478e-02, 6.69885837e-03
+])
+
+def print_table(t, m=4):
+
+ for (i, v) in enumerate(t):
+ print('{:14.8e},'.format(v), end = '\n' if i%m == m-1 else ' ')
+
+ if len(t) % 4:
+ print('')
+
+
+def mdct_fft_twiddles():
+
+ for n in (10, 20, 30, 40, 60, 80, 90, 120, 160, 180, 240):
+
+ print('\n--- fft bf2 twiddles {:3d} ---'.format(n))
+
+ kv = -2 * np.pi * np.arange(n // 2) / n
+ for (i, k) in enumerate(kv):
+ print('{{ {:14.7e}, {:14.7e} }},'.format(np.cos(k), np.sin(k)),
+ end = '\n' if i%2 == 1 else ' ')
+
+ for n in (15, 45):
+
+ print('\n--- fft bf3 twiddles {:3d} ---'.format(n))
+
+ kv = -2 * np.pi * np.arange(n) / n
+ for k in kv:
+ print(('{{ {{ {:14.7e}, {:14.7e} }},' +
+ ' {{ {:14.7e}, {:14.7e} }} }},').format(
+ np.cos(k), np.sin(k), np.cos(2*k), np.sin(2*k)))
+
+
+def mdct_rot_twiddles():
+
+ for n in (120, 160, 240, 320, 360, 480, 640, 720, 960):
+
+ print('\n--- mdct rot twiddles {:3d} ---'.format(n))
+
+ kv = 2 * np.pi * (np.arange(n // 4) + 1/8) / n
+ scale = np.sqrt( np.sqrt( 4 / n ) )
+ for (i, k) in enumerate(kv):
+ print('{{ {:14.7e}, {:14.7e} }},'.format(
+ np.cos(k) * scale, np.sin(k) * scale),
+ end = '\n' if i%2 == 1 else ' ')
+
+
+def mdct_scaling():
+
+ print('\n--- mdct scaling ---')
+ ns = np.array([ [ 60, 120, 180, 240, 360], [ 80, 160, 240, 320, 480] ])
+ print_table(np.sqrt(2 / ns[0]))
+ print_table(np.sqrt(2 / ns[1]))
+
+
+def tns_lag_window():
+
+ print('\n--- tns lag window ---')
+ print_table(np.exp(-0.5 * (0.02 * np.pi * np.arange(9)) ** 2))
+
+
+def tns_quantization_table():
+
+ print('\n--- tns quantization table ---')
+ print_table(np.sin((np.arange(8) + 0.5) * (np.pi / 17)))
+ print_table(np.sin((np.arange(8)) * (np.pi / 17)))
+
+
+def quant_iq_table():
+
+ print('\n--- quantization iq table ---')
+ print_table(10 ** (np.arange(65) / 28))
+
+
+def sns_ge_table():
+
+ g_tilt_table = [ 14, 18, 22, 26, 30 ]
+
+ for (sr, g_tilt) in enumerate(g_tilt_table):
+ print('\n--- sns ge table, sr:{} ---'.format(sr))
+ print_table(10 ** ((np.arange(64) * g_tilt) / 630))
+
+
+def inv_table():
+
+ print('\n--- inv table ---')
+ print_table(np.append(np.zeros(1), 1 / np.arange(1, 28)))
+
+def ltpf_resampler_table():
+
+ for sr in [ 8, 16, 32, 24, 48 ]:
+
+ r = 192 // sr
+ k = 64 if r & (r-1) else 192
+
+ p = (192 // k) * (k // sr)
+ q = p * (0.5 if sr == 8 else 1)
+
+ print('\n--- LTPF resampler {:d} KHz to 12.8 KHz ---'.format(sr))
+
+ h = np.rint(np.append(LTPF_H12K8, 0.) * q * 2**15).astype(int)
+ h = h.reshape((len(h) // p, p)).T
+ h = np.flip(h, axis=0)
+ print('... Gain:', np.max(np.sum(np.abs(h), axis=1)) / 32768.)
+
+ for i in range(0, len(h), 192 // k):
+ for j in range(0, len(h[i]), 10):
+ print('{:5d}, {:5d}, {:5d}, {:5d}, {:5d}, '
+ '{:5d}, {:5d}, {:5d}, {:5d}, {:5d},'.format(
+ h[i][j+0], h[i][j+1], h[i][j+2], h[i][j+3], h[i][j+4],
+ h[i][j+5], h[i][j+6], h[i][j+7], h[i][j+8], h[i][j+9]))
+
+
+def ltpf_interpolate_table():
+
+ print('\n--- LTPF interpolation ---')
+
+ h = np.rint(np.append(LTPF_HI, 0.) * 2**15).astype(int)
+
+ h = h.reshape(len(h) // 4, 4).T
+ h = np.flip(h, axis=0)
+ print('... Gain:', np.max(np.sum(np.abs(h), axis=1)) / 32768.)
+
+ for i in range(len(h)):
+ print('{:5d}, {:5d}, {:5d}, {:5d}'.format(
+ h[i][0], h[i][1], h[i][2], h[i][3]))
+
+
+if __name__ == '__main__':
+
+ mdct_fft_twiddles()
+ mdct_rot_twiddles()
+ mdct_scaling()
+
+ inv_table()
+ sns_ge_table()
+ tns_lag_window()
+ tns_quantization_table()
+ quant_iq_table()
+
+ ltpf_resampler_table()
+ ltpf_interpolate_table()
+
+ print('')
diff --git a/test/appendix_c.py b/test/appendix_c.py
new file mode 100644
index 0000000..66b6e04
--- /dev/null
+++ b/test/appendix_c.py
@@ -0,0 +1,4083 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+#
+# Appendix C - Intermediate verification of input and output
+#
+
+import numpy as np
+
+
+NBYTES = (32e3 * np.array([ 7.5e-3, 10e-3 ]) / 8).astype(int)
+
+
+### C.3.1.1 PCM Input
+
+X_PCM_10M = np.array([
+
+ [ 0, 3212, 6392, 9512, 12539, 15446, 18205, 20788,
+ 23170, 25328, 27244, 28898, 30272, 31357, 32137, 32609,
+ 32767, 32609, 32138, 31356, 30272, 28898, 27245, 25330,
+ 23169, 20787, 18205, 15446, 12539, 9511, 6393, 3212,
+ 0, -3212, -6393, -9512, -12540, -15446, -18204, -20787,
+ -23170, -25329, -27245, -28898, -30273, -31356, -32137, -32610,
+ -32766, -32609, -32137, -31356, -30272, -28898, -27244, -25329,
+ -23171, -20787, -18204, -15446, -12539, -9511, -6393, -3212,
+ -1, 3212, 6393, 9512, 12540, 15446, 18204, 20788,
+ 23169, 25329, 27245, 28898, 30273, 31356, 32137, 32609,
+ 32767, 32609, 32137, 31356, 30273, 28898, 27245, 25330,
+ 23170, 20787, 18204, 15446, 12540, 9512, 6393, 3212,
+ 0, -3212, -6393, -9512, -12539, -15447, -18204, -20787,
+ -23170, -25330, -27244, -28898, -30272, -31356, -32137, -32609,
+ -32767, -32609, -32137, -31356, -30273, -28898, -27244, -25330,
+ -23169, -20787, -18204, -15446, -12540, -9511, -6393, -3212,
+ 0, 3212, 6392, 9511, 12539, 15446, 18205, 20787,
+ 23169, 25329, 27245, 28898, 30273, 31356, 32137, 32609,
+ 32767, 32610, 32137, 31356, 30273, 28898, 27244, 25329,
+ 23170, 20787, 18204, 15446, 12540, 9511, 6392, 3211 ],
+
+ [ 0, -3211, -6393, -9512, -12539, -15446, -18204, -20788,
+ -23170, -25329, -27245, -28898, -30273, -31356, -32137, -32609,
+ -32767, -32609, -32138, -31356, -30273, -28898, -27245, -25329,
+ -23170, -20788, -18205, -15447, -12539, -9512, -6392, -3211,
+ 0, 3211, 6393, 9512, 12539, 15446, 18204, 20787,
+ 23170, 25329, 27244, 28897, 30273, 31356, 32137, 32609,
+ 32767, 32609, 32137, 31356, 30273, 28897, 27244, 25330,
+ 23170, 20787, 18205, 15446, 12539, 9512, 6393, 3213,
+ 0, -3212, -6393, -9512, -12540, -15447, -18205, -20787,
+ -23169, -25329, -27245, -28897, -30273, -31356, -32138, -32609,
+ -32767, -32609, -32138, -31356, -30273, -28898, -27244, -25330,
+ -23170, -20787, -18205, -15446, -12540, -9513, -6392, -3212,
+ 0, 3212, 6393, 9512, 12540, 15446, 18204, 20788,
+ 23170, 25329, 27245, 28898, 30272, 31356, 32138, 32609,
+ 32767, 32609, 32138, 31356, 30273, 28898, 27244, 25330,
+ 23170, 20787, 18204, 15446, 12540, 9512, 6392, 3211,
+ 0, -3211, -6393, -9512, -12539, -15446, -18205, -20786,
+ -23170, -25329, -27245, -28898, -30272, -31356, -32137, -32609,
+ -32766, -32609, -32137, -31356, -30273, -28898, -27245, -25329,
+ -23170, -20787, -18204, -15446, -12539, -9511, -6393, -3212 ]
+
+])
+
+X_PCM_7M5 = np.array([
+
+ [ 0, 3212, 6392, 9512, 12539, 15446, 18205, 20788,
+ 23170, 25328, 27244, 28898, 30272, 31357, 32137, 32609,
+ 32767, 32609, 32138, 31356, 30272, 28898, 27245, 25330,
+ 23169, 20787, 18205, 15446, 12539, 9511, 6393, 3212,
+ 0, -3212, -6393, -9512, -12540, -15446, -18204, -20787,
+ -23170, -25329, -27245, -28898, -30273, -31356, -32137, -32610,
+ -32766, -32609, -32137, -31356, -30272, -28898, -27244, -25329,
+ -23171, -20787, -18204, -15446, -12539, -9511, -6393, -3212,
+ -1, 3212, 6393, 9512, 12540, 15446, 18204, 20788,
+ 23169, 25329, 27245, 28898, 30273, 31356, 32137, 32609,
+ 32767, 32609, 32137, 31356, 30273, 28898, 27245, 25330,
+ 23170, 20787, 18204, 15446, 12540, 9512, 6393, 3212,
+ 0, -3212, -6393, -9512, -12539, -15447, -18204, -20787,
+ -23170, -25330, -27244, -28898, -30272, -31356, -32137, -32609,
+ -32767, -32609, -32137, -31356, -30273, -28898, -27244, -25330 ],
+
+ [ -23169, -20787, -18204, -15446, -12540, -9511, -6393, -3212,
+ 0, 3212, 6392, 9511, 12539, 15446, 18205, 20787,
+ 23169, 25329, 27245, 28898, 30273, 31356, 32137, 32609,
+ 32767, 32610, 32137, 31356, 30273, 28898, 27244, 25329,
+ 23170, 20787, 18204, 15446, 12540, 9511, 6392, 3211,
+ 0, -3211, -6393, -9512, -12539, -15446, -18204, -20788,
+ -23170, -25329, -27245, -28898, -30273, -31356, -32137, -32609,
+ -32767, -32609, -32138, -31356, -30273, -28898, -27245, -25329,
+ -23170, -20788, -18205, -15447, -12539, -9512, -6392, -3211,
+ 0, 3211, 6393, 9512, 12539, 15446, 18204, 20787,
+ 23170, 25329, 27244, 28897, 30273, 31356, 32137, 32609,
+ 32767, 32609, 32137, 31356, 30273, 28897, 27244, 25330,
+ 23170, 20787, 18205, 15446, 12539, 9512, 6393, 3213,
+ 0, -3212, -6393, -9512, -12540, -15447, -18205, -20787,
+ -23169, -25329, -27245, -28897, -30273, -31356, -32138, -32609 ]
+
+])
+
+X_PCM = [ X_PCM_7M5, X_PCM_10M ]
+
+
+### C.3.1.2 MDCT
+
+X_10M = np.array([
+
+ [ -5.8990646e+02, 3.2262618e+04, -2.7619007e+04, 9.5178147e+04,
+ -1.1418053e+05, -2.2419557e+05, -2.2347007e+03, -1.9867627e+04,
+ -1.6067159e+04, 5.8154816e+02, -1.5722676e+04, 4.0158688e+03,
+ -1.0088102e+04, 1.9017417e+03, -4.1954471e+03, -9.7496049e+02,
+ 4.7235950e+02, -2.7499647e+03, 2.4705648e+03, -2.7529252e+03,
+ 2.2309610e+03, -1.4814949e+03, 8.0924574e+02, 1.0419403e+02,
+ -6.3151413e+02, 1.1597939e+03, -1.3202428e+03, 1.3143498e+03,
+ -1.1022736e+03, 7.2762067e+02, -3.2778511e+02, -1.1134462e+02,
+ 4.5185190e+02, -7.0065111e+02, 8.1286568e+02, -7.8143265e+02,
+ 6.4645208e+02, -4.1055413e+02, 1.5009894e+02, 1.1832095e+02,
+ -3.4137778e+02, 4.8690132e+02, -5.5346349e+02, 5.1921969e+02,
+ -4.1808273e+02, 2.5332159e+02, -6.4719513e+01, -1.1746306e+02,
+ 2.7072573e+02, -3.6623733e+02, 4.0439184e+02, -3.7097974e+02,
+ 2.8704947e+02, -1.6297022e+02, 2.0395888e+01, 1.1218314e+02,
+ -2.2577273e+02, 2.8951685e+02, -3.1083971e+02, 2.7771234e+02,
+ -2.0730346e+02, 1.0688285e+02, 6.1320766e+00, -1.0817459e+02,
+ 1.9320762e+02, -2.3845257e+02, 2.4826403e+02, -2.1609003e+02,
+ 1.5207388e+02, -6.9546445e+01, -2.4211219e+01, 1.0403883e+02,
+ -1.6888652e+02, 2.0050394e+02, -2.0326028e+02, 1.7179995e+02,
+ -1.1399655e+02, 4.4242025e+01, 3.4454794e+01, -1.0009362e+02,
+ 1.5218958e+02, -1.7342213e+02, 1.7018985e+02, -1.3794243e+02,
+ 8.6156013e+01, -2.4921223e+01, -4.2552602e+01, 9.5559562e+01,
+ -1.3740945e+02, 1.5218075e+02, -1.4462762e+02, 1.1451272e+02,
+ -6.4959967e+01, 1.0627359e+01, 4.7836856e+01, -9.2854453e+01,
+ 1.2654514e+02, -1.3593370e+02, 1.2459754e+02, -9.4075815e+01,
+ 4.9816314e+01, 2.1529924e-01, -5.2425581e+01, 9.0995703e+01,
+ -1.1737069e+02, 1.2263969e+02, -1.0917602e+02, 7.9712422e+01,
+ -3.5722986e+01, -9.6955535e+00, 5.6602292e+01, -8.9431609e+01,
+ 1.0953959e+02, -1.1249540e+02, 9.6333120e+01, -6.6446434e+01,
+ 2.3693799e+01, 1.7708430e+01, -5.8794346e+01, 8.8078076e+01,
+ -1.0478463e+02, 1.0227969e+02, -8.4957399e+01, 5.5726976e+01,
+ -1.4768315e+01, -2.3981122e+01, 6.1741642e+01, -8.6508895e+01,
+ 9.9868691e+01, -9.6459597e+01, 7.6331011e+01, -4.6588689e+01,
+ 6.4212746e+00, 3.0432190e+01, -6.6116496e+01, 8.6861568e+01,
+ -9.6320778e+01, 8.9835533e+01, -6.7287784e+01, 3.7477990e+01,
+ 1.3842189e+00, -3.5731585e+01, 6.8605400e+01, -8.7530923e+01,
+ 9.3616286e+01, -8.3728496e+01, 6.0230516e+01, -2.9414119e+01,
+ -7.6609110e+00, 4.2149725e+01, -7.1968501e+01, 8.7743888e+01,
+ -9.0802890e+01, 7.8923198e+01, -5.4973827e+01, 2.2745574e+01,
+ 1.5766746e+01, -4.7673661e+01, 7.5778794e+01, -8.9162686e+01 ],
+
+ [ -6.2843560e+03, -1.4627418e+04, 4.9801516e+03, -7.0344966e+04,
+ 8.5564327e+04, 2.5840606e+05, -3.5208419e+04, 5.4644134e+04,
+ -1.1212441e+04, 1.8683629e+04, 1.8049757e+03, 7.0569176e+03,
+ 1.2829514e+03, 4.0930299e+03, 1.1947052e+03, 1.5425662e+03,
+ 6.0325642e+02, 6.4703789e+02, 1.5715070e+02, 1.0644751e+02,
+ -7.5883978e+00, -5.2773353e+01, -6.0996565e+01, -8.3409817e+01,
+ -4.3996776e+01, -3.3763658e+01, -1.2075849e+01, -2.9293481e+00,
+ 5.2907677e+00, 1.4501256e+01, 1.0866309e+01, 9.1905374e+00,
+ 3.0606323e+00, 1.6027594e+00, -1.1174900e+00, -5.4280671e+00,
+ -4.5919914e+00, -4.4199737e+00, -2.0085059e+00, -4.2065884e-01,
+ 6.3446132e-01, 2.7718649e+00, 3.5654183e+00, 2.6588468e+00,
+ 1.3730777e+00, 1.3705866e+00, 6.3801955e-02, -1.1191414e+00,
+ -2.1495458e+00, -2.1211746e+00, -1.1188698e+00, -1.3646427e+00,
+ -1.2245570e+00, 1.5630676e-01, 1.0243080e+00, 2.0104419e+00,
+ 1.8985278e+00, 1.2447591e+00, 1.7309919e+00, 9.4234385e-01,
+ -3.3619810e-01, -1.6030368e+00, -7.1471558e-01, -2.0710920e+00,
+ -2.9423847e+00, -1.7873501e+00, -8.0633559e-01, -1.6093125e-03,
+ 7.9415802e-01, 8.7937487e-01, 1.7154607e+00, 1.0383457e+00,
+ 2.3742697e+00, 9.7376296e-01, 1.5290469e+00, 1.1078186e-01,
+ -1.3382843e+00, -8.0183060e-01, -1.1937948e+00, -1.6144857e+00,
+ -2.4688787e+00, 2.7158214e-01, -2.8802354e-01, 1.5704268e-01,
+ -2.7983134e-01, 7.3794617e-01, 1.0364997e+00, 6.9563470e-01,
+ 9.9846216e-02, 7.4018952e-01, -1.6599106e-02, -6.7106650e-01,
+ 9.4477394e-02, -1.1325310e+00, -1.2183007e+00, -1.1326694e+00,
+ -7.0637699e-01, -1.1096511e+00, 1.4381563e-01, 4.6121573e-01,
+ 7.9281879e-01, 1.4577665e+00, 1.9515924e+00, 1.5493961e+00,
+ 7.6923395e-01, 1.0666962e-01, -5.8376568e-01, -1.7768814e-01,
+ -7.8840041e-01, -8.4273142e-01, -1.1227955e-01, 1.7007988e-01,
+ -1.2788265e+00, -8.2037634e-01, 2.9027089e-02, 1.1299878e+00,
+ 1.5466537e+00, 5.7106120e-01, 1.0054291e+00, 7.7078972e-01,
+ -1.2498850e-01, 1.4337381e-01, -9.1649732e-03, 1.5189923e-01,
+ -1.8656702e+00, -1.3065376e+00, -1.0474639e+00, -6.1982978e-01,
+ -4.0826276e-01, -2.5749212e-01, 7.5196564e-01, 5.9204803e-01,
+ 3.8971675e-01, 4.7356386e-01, 9.6497659e-01, 1.0654369e+00,
+ 1.0179577e-01, -8.7312829e-01, -1.0535862e+00, -5.5302243e-01,
+ -1.4681184e+00, -9.4220508e-01, -7.2255455e-01, -5.3132915e-01,
+ -1.4926868e-01, 3.6245889e-01, 1.6544183e-01, 7.2654545e-01,
+ -7.6464228e-02, 1.9158155e-02, 8.5964508e-01, 5.0113123e-02,
+ -3.5523428e-02, -1.0719814e+00, -1.0268355e+00, -3.9656991e-01,
+ -3.7302065e-01, -7.6860159e-01, -3.9431418e-01, -8.4906570e-02 ]
+
+])
+
+X_7M5 = np.array([
+
+ [ -2.7808220e+04, 3.1171944e+04, -1.0484449e+05, -1.6109747e+05,
+ 7.1020534e+03, 6.1529776e+04, -4.3352596e+03, 1.6872730e+03,
+ 8.3021669e+03, -8.0904023e+03, 2.8986710e+03, 1.6300470e+03,
+ -3.9442485e+03, 3.3369609e+03, -7.5314157e+02, -1.5665608e+03,
+ 2.3627282e+03, -1.5968140e+03, -2.9454372e+01, 1.3170795e+03,
+ -1.5221502e+03, 7.5501127e+02, 3.4796318e+02, -1.0725998e+03,
+ 9.9368163e+02, -2.9346750e+02, -4.7457374e+02, 8.5309969e+02,
+ -6.3326698e+02, 2.2874568e+01, 5.0703180e+02, -6.5956792e+02,
+ 3.7615149e+02, 1.3645752e+02, -4.8970087e+02, 4.9257049e+02,
+ -1.8802536e+02, -2.2788339e+02, 4.4305145e+02, -3.4924777e+02,
+ 5.0697164e+01, 2.7264213e+02, -3.8309643e+02, 2.2685761e+02,
+ 4.8724694e+01, -2.8629820e+02, 3.1493179e+02, -1.2493286e+02,
+ -1.1855917e+02, 2.7825778e+02, -2.4421869e+02, 3.9752437e+01,
+ 1.6382158e+02, -2.5263703e+02, 1.7444462e+02, 2.6833647e+01,
+ -1.8770774e+02, 2.1765469e+02, -1.1027623e+02, -7.8965164e+01,
+ 1.9573957e+02, -1.7599945e+02, 4.9679803e+01, 1.1484006e+02,
+ -1.8898112e+02, 1.3092016e+02, 7.2222470e-01, -1.3789235e+02,
+ 1.7321190e+02, -8.5147249e+01, -4.3896934e+01, 1.4839226e+02,
+ -1.4915199e+02, 4.1079567e+01, 7.7806126e+01, -1.4826509e+02,
+ 1.1954125e+02, -9.5155767e-01, -1.0279192e+02, 1.3980505e+02,
+ -8.5889140e+01, -3.4465766e+01, 1.1923625e+02, -1.2267683e+02,
+ 5.1023135e+01, 6.4082513e+01, -1.2613323e+02, 9.9909559e+01,
+ -1.6509945e+01, -8.6980952e+01, 1.2384580e+02, -7.3451876e+01,
+ -1.5354773e+01, 1.0245575e+02, -1.1445423e+02, 4.5501562e+01,
+ 4.3867941e+01, -1.1121715e+02, 1.0028146e+02, -1.5168901e+01,
+ -6.9443433e+01, 1.1170827e+02, -7.9410276e+01, -1.4798645e+01,
+ 8.7563510e+01, -1.0510000e+02, 5.5384253e+01, 4.1531846e+01,
+ -1.0069765e+02, 9.2428209e+01, -2.7848167e+01, -6.4462037e+01,
+ 1.0628096e+02, -7.4978815e+01, 1.6316106e-01, 8.3599643e+01,
+ -1.0561445e+02, 5.2787841e+01, 2.7101412e+01, -9.7922081e+01 ],
+
+ [ 3.8121925e+03, -2.2031854e+04, 6.2134301e+04, -2.5584480e+05,
+ -4.0289726e+04, -1.1591648e+04, 9.9946415e+03, -5.6931570e+03,
+ -1.4027155e+03, -8.4816729e+01, -1.6692931e+02, 3.7467791e+01,
+ 1.5876357e+02, 1.0909061e+02, -1.2446699e+01, -7.8016012e+01,
+ -5.9665224e+01, 1.7150538e+01, 4.1435247e+01, 1.4446691e+01,
+ -3.8364171e+00, -9.0141422e+00, -1.1905776e+01, -1.1758083e+01,
+ 2.4695821e+00, 1.6421675e+01, 1.7958775e+01, -1.0112627e+00,
+ -1.7276148e+01, -1.4579197e+01, -3.0796621e-01, 3.4903800e+00,
+ 8.9247274e+00, 1.0542251e+01, 5.1085251e+00, -6.3561781e+00,
+ -1.5196238e+01, -8.5814612e+00, 5.9801475e+00, 8.8788786e+00,
+ 6.6693886e+00, 4.0520010e+00, -2.5648927e+00, -7.3376816e+00,
+ -9.4020988e+00, -3.7886737e+00, 9.8324354e+00, 1.0369412e+01,
+ 2.7236309e+00, -1.1806094e+00, -5.4027659e+00, -7.1662503e+00,
+ -5.2723002e+00, 2.2261048e+00, 1.0161892e+01, 7.6651861e+00,
+ -2.2518007e+00, -5.1245529e+00, -5.3667831e+00, -4.6532034e+00,
+ -9.0748070e-01, 2.8558608e+00, 8.7396007e+00, 5.8069435e+00,
+ -4.9824625e+00, -6.3131200e+00, -4.2366242e+00, -1.2878986e+00,
+ 1.9593460e+00, 4.4854081e+00, 6.1847341e+00, 1.9350643e+00,
+ -6.7952522e+00, -7.6836416e+00, -1.1341833e+00, 8.9242434e-01,
+ 4.4208241e+00, 4.7103946e+00, 3.3250393e+00, -5.6553445e-01,
+ -6.6710206e+00, -5.9125999e+00, 8.2386239e-01, 4.8587135e+00,
+ 4.1530321e+00, 3.6100791e+00, 3.4896727e-01, -3.5268730e+00,
+ -6.6259985e+00, -4.6374540e+00, 4.0614812e+00, 4.8600515e+00,
+ 3.4816753e+00, 7.5221655e-01, -1.5176717e+00, -3.5752094e+00,
+ -5.3492120e+00, -1.8813288e+00, 4.5633890e+00, 5.8660550e+00,
+ 2.6127035e+00, -1.4095531e+00, -3.2585158e+00, -4.0492745e+00,
+ -3.0513819e+00, 1.0864826e+00, 6.1166169e+00, 5.3791204e+00,
+ -2.6627677e-01, -3.3401114e+00, -4.3742918e+00, -3.7773803e+00,
+ -3.2386710e-01, 2.3283535e+00, 6.5557289e+00, 4.4470718e+00,
+ -2.5793855e+00, -4.6626375e+00, -3.9104033e+00, -1.1065239e+00 ]
+
+])
+
+X = [ X_7M5, X_10M ]
+
+
+### C.3.1.3 12.8 kHz resampler
+
+X_TILDE_12K8D_10M = np.array([
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, -2.7136560e+00, -2.6569981e+00, -8.2098309e+00,
+ 2.5435023e+00, -1.2692479e+01, 3.2383771e+00, -4.3038498e+01,
+ 1.6475668e+02, 3.9002834e+03, 7.6897871e+03, 1.1168030e+04,
+ 1.4388464e+04, 1.7228860e+04, 1.9693442e+04, 2.1734211e+04,
+ 2.3341435e+04, 2.4458687e+04, 2.5091505e+04, 2.5237788e+04,
+ 2.4898746e+04, 2.4056493e+04, 2.2750447e+04, 2.1002836e+04,
+ 1.8837538e+04, 1.6271528e+04, 1.3371876e+04, 1.0177959e+04,
+ 6.7345474e+03, 3.0859120e+03, -6.8926189e+02, -4.5387403e+03,
+ -8.4127977e+03, -1.2248756e+04, -1.5972309e+04, -1.9535642e+04,
+ -2.2893718e+04, -2.5977602e+04, -2.8736936e+04, -3.1140674e+04,
+ -3.3157374e+04, -3.4729421e+04, -3.5844044e+04, -3.6489767e+04,
+ -3.6657691e+04, -3.6317413e+04, -3.5493490e+04, -3.4198956e+04,
+ -3.2451848e+04, -3.0250170e+04, -2.7655246e+04, -2.4700058e+04,
+ -2.1422013e+04, -1.7854871e+04, -1.4073383e+04, -1.0130011e+04,
+ -6.0696279e+03, -1.9523115e+03, 2.1432690e+03, 6.1682081e+03,
+ 1.0075311e+04, 1.3793150e+04, 1.7261182e+04, 2.0439154e+04,
+ 2.3290746e+04, 2.5752435e+04, 2.7792879e+04, 2.9395551e+04,
+ 3.0539419e+04, 3.1182642e+04, 3.1334658e+04, 3.1000121e+04,
+ 3.0185153e+04, 2.8876238e+04, 2.7121382e+04, 2.4947537e+04,
+ 2.2382237e+04, 1.9447889e+04, 1.6216333e+04, 1.2730773e+04,
+ 9.0366635e+03, 5.1844000e+03, 1.2542494e+03, -2.7040631e+03,
+ -6.6402694e+03, -1.0487968e+04, -1.4176374e+04, -1.7659977e+04,
+ -2.0896015e+04, -2.3817756e+04, -2.6379477e+04, -2.8555427e+04,
+ -3.0316787e+04, -3.1610147e+04, -3.2431837e+04, -3.2774372e+04,
+ -3.2634728e+04, -3.1986767e+04, -3.0864057e+04, -2.9283835e+04,
+ -2.7267471e+04, -2.4822384e+04, -2.2011114e+04, -1.8874753e+04,
+ -1.5449273e+04 ],
+
+ [ -1.5449273e+04, -1.1776342e+04, -7.9350741e+03, -3.9753420e+03,
+ 5.6212790e+01, 4.0948091e+03, 8.0660721e+03, 1.1920829e+04,
+ 1.5610547e+04, 1.9067628e+04, 2.2236206e+04, 2.5079838e+04,
+ 2.7562773e+04, 2.9625190e+04, 3.1247708e+04, 3.2411870e+04,
+ 3.3105731e+04, 3.3290869e+04, 3.2986189e+04, 3.2200486e+04,
+ 3.0944512e+04, 2.9210715e+04, 2.7055339e+04, 2.4507368e+04,
+ 2.1598895e+04, 1.8359789e+04, 1.4864140e+04, 1.1157303e+04,
+ 7.2876208e+03, 3.3081055e+03, -7.0156289e+02, -4.6891569e+03,
+ -8.6058356e+03, -1.2384088e+04, -1.5958973e+04, -1.9284607e+04,
+ -2.2323146e+04, -2.5008095e+04, -2.7303120e+04, -2.9181339e+04,
+ -3.0623681e+04, -3.1579731e+04, -3.2052556e+04, -3.2039965e+04,
+ -3.1544863e+04, -3.0546815e+04, -2.9086911e+04, -2.7186800e+04,
+ -2.4871192e+04, -2.2155336e+04, -1.9106913e+04, -1.5768099e+04,
+ -1.2180718e+04, -8.3886907e+03, -4.4727275e+03, -4.8397983e+02,
+ 3.5287168e+03, 7.5007937e+03, 1.1356312e+04, 1.5052293e+04,
+ 1.8540697e+04, 2.1752202e+04, 2.4638955e+04, 2.7166972e+04,
+ 2.9306556e+04, 3.0998943e+04, 3.2231603e+04, 3.2995051e+04,
+ 3.3278595e+04, 3.3050597e+04, 3.2338337e+04, 3.1153755e+04,
+ 2.9512841e+04, 2.7417674e+04, 2.4925451e+04, 2.2071406e+04,
+ 1.8894430e+04, 1.5423055e+04, 1.1739349e+04, 7.8892265e+03,
+ 3.9209702e+03, -1.0578292e+02, -4.1130091e+03, -8.0523247e+03,
+ -1.1874762e+04, -1.5509335e+04, -1.8896353e+04, -2.1995901e+04,
+ -2.4770068e+04, -2.7154380e+04, -2.9121926e+04, -3.0652080e+04,
+ -3.1724909e+04, -3.2299883e+04, -3.2385523e+04, -3.1985436e+04,
+ -3.1105919e+04, -2.9735628e+04, -2.7920239e+04, -2.5686848e+04,
+ -2.3064137e+04, -2.0073280e+04, -1.6788431e+04, -1.3249779e+04,
+ -9.5054623e+03, -5.6021829e+03, -1.6246392e+03, 2.3816986e+03,
+ 6.3633660e+03, 1.0254738e+04, 1.3986117e+04, 1.7511038e+04,
+ 2.0787917e+04, 2.3746769e+04, 2.6347708e+04, 2.8559387e+04,
+ 3.0354770e+04, 3.1683451e+04, 3.2536757e+04, 3.2910967e+04,
+ 3.2802210e+04, 3.2182725e+04, 3.1087832e+04, 2.9535420e+04,
+ 2.7544339e+04, 2.5123821e+04, 2.2336463e+04, 1.9222835e+04,
+ 1.5819986e+04 ]
+
+])
+
+X_TILDE_12K8D_7M5 = np.array([
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, -2.7136560e+00, -2.6569981e+00, -8.2098309e+00,
+ 2.5435023e+00, -1.2692479e+01, 3.2383771e+00, -4.3038498e+01,
+ 1.6475668e+02, 3.9002834e+03, 7.6897871e+03, 1.1168030e+04,
+ 1.4388464e+04, 1.7228860e+04, 1.9693442e+04, 2.1734211e+04,
+ 2.3341435e+04, 2.4458687e+04, 2.5091505e+04, 2.5237788e+04,
+ 2.4898746e+04, 2.4056493e+04, 2.2750447e+04, 2.1002836e+04,
+ 1.8837538e+04, 1.6271528e+04, 1.3371876e+04, 1.0177959e+04,
+ 6.7345474e+03, 3.0859120e+03, -6.8926189e+02, -4.5387403e+03,
+ -8.4127977e+03, -1.2248756e+04, -1.5972309e+04, -1.9535642e+04,
+ -2.2893718e+04, -2.5977602e+04, -2.8736936e+04, -3.1140674e+04,
+ -3.3157374e+04, -3.4729421e+04, -3.5844044e+04, -3.6489767e+04,
+ -3.6657691e+04, -3.6317413e+04, -3.5493490e+04, -3.4198956e+04,
+ -3.2451848e+04, -3.0250170e+04, -2.7655246e+04, -2.4700058e+04,
+ -2.1422013e+04 ],
+
+ [ -2.1422013e+04, -1.7854871e+04, -1.4073383e+04, -1.0130011e+04,
+ -6.0696279e+03, -1.9523115e+03, 2.1432690e+03, 6.1682081e+03,
+ 1.0075311e+04, 1.3793150e+04, 1.7261182e+04, 2.0439154e+04,
+ 2.3290746e+04, 2.5752435e+04, 2.7792879e+04, 2.9395551e+04,
+ 3.0539419e+04, 3.1182642e+04, 3.1334658e+04, 3.1000121e+04,
+ 3.0185153e+04, 2.8876238e+04, 2.7121382e+04, 2.4947537e+04,
+ 2.2382237e+04, 1.9447889e+04, 1.6216333e+04, 1.2730773e+04,
+ 9.0366635e+03, 5.1844000e+03, 1.2542494e+03, -2.7040631e+03,
+ -6.6402694e+03, -1.0487968e+04, -1.4176374e+04, -1.7659977e+04,
+ -2.0896015e+04, -2.3817756e+04, -2.6379477e+04, -2.8555427e+04,
+ -3.0316787e+04, -3.1610147e+04, -3.2431837e+04, -3.2774372e+04,
+ -3.2634728e+04, -3.1986767e+04, -3.0864057e+04, -2.9283835e+04,
+ -2.7267471e+04, -2.4822384e+04, -2.2011114e+04, -1.8874753e+04,
+ -1.5449273e+04, -1.1776342e+04, -7.9350741e+03, -3.9753420e+03,
+ 5.6212790e+01, 4.0948091e+03, 8.0660721e+03, 1.1920829e+04,
+ 1.5610547e+04, 1.9067628e+04, 2.2236206e+04, 2.5079838e+04,
+ 2.7562773e+04, 2.9625190e+04, 3.1247708e+04, 3.2411870e+04,
+ 3.3105731e+04, 3.3290869e+04, 3.2986189e+04, 3.2200486e+04,
+ 3.0944512e+04, 2.9210715e+04, 2.7055339e+04, 2.4507368e+04,
+ 2.1598895e+04, 1.8359789e+04, 1.4864140e+04, 1.1157303e+04,
+ 7.2876208e+03, 3.3081055e+03, -7.0156289e+02, -4.6891569e+03,
+ -8.6058356e+03, -1.2384088e+04, -1.5958973e+04, -1.9284607e+04,
+ -2.2323146e+04, -2.5008095e+04, -2.7303120e+04, -2.9181339e+04,
+ -3.0623681e+04, -3.1579731e+04, -3.2052556e+04, -3.2039965e+04,
+ -3.1544863e+04 ]
+
+])
+
+X_TILDE_12K8D = [ X_TILDE_12K8D_7M5, X_TILDE_12K8D_10M ]
+
+
+### C.3.1.4 Pitch analysis
+
+T_CURR_10M = np.array([ 25, 26 ])
+T_CURR_7M5 = np.array([ 22, 25 ])
+T_CURR = [ T_CURR_7M5, T_CURR_10M ]
+
+NORMCORR_10M = np.array([ 0.677220, 0.992748 ])
+NORMCORR_7M5 = np.array([ 0.473429, 0.952099 ])
+NORMCORR = [ NORMCORR_7M5, NORMCORR_10M ]
+
+T1_10M = np.array([ 25, 26 ])
+T1_7M5 = np.array([ 22, 25 ])
+T1 = [ T1_7M5, T1_10M ]
+
+T2_10M = np.array([ 21, 26 ])
+T2_7M5 = np.array([ 21, 25 ])
+T2 = [ T2_7M5, T2_10M ]
+
+NORMCORR1_10M = np.array([ 0.677220, 0.992748 ])
+NORMCORR1_7M5 = np.array([ 0.473429, 0.952099 ])
+NORMCORR1 = [ NORMCORR1_7M5, NORMCORR1_10M ]
+
+NORMCORR2_10M = np.array([ 0.276293, 0.992748 ])
+NORMCORR2_7M5 = np.array([ 0.000000, 0.952099 ])
+NORMCORR2 = [ NORMCORR2_7M5, NORMCORR2_10M ]
+
+
+### C.3.1.5 LTPF encoder
+
+PITCH_PRESENT_10M = np.array([ 1, 1 ])
+PITCH_PRESENT_7M5 = np.array([ 0, 1 ])
+PITCH_PRESENT = [ PITCH_PRESENT_7M5, PITCH_PRESENT_10M ]
+
+PITCH_INDEX_10M = np.array([ 76, 76 ])
+PITCH_INDEX_7M5 = np.array([ 0, 72 ])
+PITCH_INDEX = [ PITCH_INDEX_7M5, PITCH_INDEX_10M ]
+
+LTPF_ACTIVE_10M = np.array([ 0, 0 ])
+LTPF_ACTIVE_7M5 = np.array([ 0, 0 ])
+LTPF_ACTIVE = [ LTPF_ACTIVE_7M5, LTPF_ACTIVE_10M ]
+
+NC_LTPF_10M = np.array([ 0.690317, 0.998707 ])
+NC_LTPF_7M5 = np.array([ 0.000000, 0.963121 ])
+NC_LTPF = [ NC_LTPF_7M5, NC_LTPF_10M ]
+
+
+### C.3.1.6 Per-band energy
+
+E_B_10M = np.array([
+
+ [ 3.4798963e+05, 1.0408765e+09, 7.6280953e+08, 9.0588797e+09,
+ 1.3037195e+10, 5.0263652e+10, 4.9938874e+06, 3.9472260e+08,
+ 2.5815358e+08, 3.3819826e+05, 2.4720253e+08, 1.6127203e+07,
+ 1.0176981e+08, 3.6166214e+06, 1.7601776e+07, 9.5054796e+05,
+ 2.2312350e+05, 7.5623058e+06, 6.1036902e+06, 7.5785971e+06,
+ 4.9771870e+06, 2.1948272e+06, 6.5487867e+05, 1.0856397e+04,
+ 3.9881009e+05, 1.3451218e+06, 1.7430411e+06, 1.7275154e+06,
+ 8.7221944e+05, 5.9920352e+04, 3.4754106e+05, 6.3569381e+05,
+ 2.9322749e+05, 1.8264770e+04, 1.7680584e+05, 2.8795546e+05,
+ 1.1948250e+05, 8.9930924e+03, 1.0371110e+05, 1.5057936e+05,
+ 3.6457561e+04, 4.9126130e+04, 7.2240065e+04, 7.7210962e+03,
+ 5.1941280e+04, 2.4886024e+04, 1.3310972e+04, 3.7010599e+04,
+ 6.5396090e+03, 2.5307401e+04, 4.7465699e+03, 1.9017662e+04,
+ 3.8107631e+03, 1.2269623e+04, 7.9690160e+03, 4.5694858e+03,
+ 9.2694695e+03, 4.6138651e+03, 4.2316029e+03, 5.8000267e+03,
+ 5.7863671e+03, 4.4037279e+03, 3.9216878e+03, 3.7117332e+03 ],
+
+ [ 3.9493130e+07, 2.1396136e+08, 2.4801910e+07, 4.9484143e+09,
+ 7.3212541e+09, 6.6773691e+10, 1.2396327e+09, 2.9859813e+09,
+ 1.2571883e+08, 3.4907798e+08, 3.2579374e+06, 4.9800086e+07,
+ 1.6459643e+06, 1.6752894e+07, 1.4273206e+06, 2.3795106e+06,
+ 3.6391831e+05, 4.1865804e+05, 2.4696343e+04, 1.1331072e+04,
+ 5.7583781e+01, 2.7850268e+03, 3.7205810e+03, 6.9571975e+03,
+ 1.9357163e+03, 1.1399846e+03, 1.4582614e+02, 8.5810802e+00,
+ 1.1913932e+02, 1.0127132e+02, 5.9681539e+00, 1.5356348e+01,
+ 2.0311276e+01, 2.1055250e+00, 4.0428882e+00, 9.8908370e+00,
+ 1.8819250e+00, 6.2827408e-01, 4.5599643e+00, 1.5570596e+00,
+ 8.5772617e-01, 3.0652366e+00, 1.3324581e+00, 2.4566558e+00,
+ 4.1674750e+00, 4.6799657e-01, 3.2193746e+00, 1.0994905e+00,
+ 1.6164118e+00, 1.5691847e+00, 5.4527735e-01, 2.5211389e-01,
+ 1.0146872e+00, 5.1845169e-01, 1.7875047e+00, 3.4334672e-01,
+ 7.2301137e-01, 8.6777500e-01, 1.0547766e+00, 2.8083700e-01,
+ 6.9555959e-01, 6.1528702e-01, 1.8631657e-01, 4.6476980e-01 ]
+
+])
+
+E_B_7M5 = np.array([
+
+ [ 7.7329708e+08, 9.7169006e+08, 1.0992368e+10, 2.5952396e+10,
+ 5.0439162e+07, 3.7859133e+09, 1.8794475e+07, 2.8468901e+06,
+ 6.8925976e+07, 6.5454609e+07, 8.4022938e+06, 2.6570531e+06,
+ 1.5557097e+07, 1.1135308e+07, 5.6722222e+05, 2.4541127e+06,
+ 5.5824847e+06, 2.5498151e+06, 8.6756001e+02, 1.7346984e+06,
+ 2.3169412e+06, 5.7004201e+05, 1.2107837e+05, 1.1504704e+06,
+ 9.8740319e+05, 8.6123175e+04, 2.2522023e+05, 7.2777908e+05,
+ 4.0102706e+05, 5.2324588e+02, 2.5708125e+05, 4.3502984e+05,
+ 1.4148995e+05, 1.8620654e+04, 2.4121631e+05, 4.3642188e+04,
+ 1.5913430e+05, 3.8451966e+04, 9.9113627e+04, 4.2170377e+04,
+ 5.7395127e+04, 4.5741834e+04, 3.0611513e+04, 4.5331490e+04,
+ 1.5575486e+04, 4.1303881e+04, 9.1981721e+03, 3.4644893e+04,
+ 1.7123395e+04, 1.2051636e+04, 1.3059786e+04, 1.5318037e+04,
+ 1.4108814e+04, 1.0037512e+04, 7.5940392e+03, 7.2531779e+03,
+ 8.4324439e+03, 7.8664771e+03, 7.3659535e+03, 6.8968988e+03,
+ 6.3095928e+03, 5.8688253e+03, 4.3696732e+03, 6.2506180e+03 ],
+
+ [ 1.4532812e+07, 4.8540259e+08, 3.8606713e+09, 6.5456561e+10,
+ 1.6232620e+09, 1.3436631e+08, 9.9892859e+07, 3.2412037e+07,
+ 1.9676109e+06, 7.1938775e+03, 2.7865394e+04, 1.4038353e+03,
+ 2.5205872e+04, 1.1900762e+04, 1.5492031e+02, 6.0864981e+03,
+ 3.5599390e+03, 2.9414095e+02, 1.7168797e+03, 2.0870689e+02,
+ 1.4718096e+01, 8.1254760e+01, 1.4174751e+02, 1.3825251e+02,
+ 6.0988360e+00, 2.6967143e+02, 3.2251759e+02, 1.0226523e+00,
+ 2.9846530e+02, 2.1255299e+02, 9.4843183e-02, 1.2182752e+01,
+ 7.9650760e+01, 1.1113906e+02, 3.3249014e+01, 1.5228356e+02,
+ 5.7298325e+01, 3.0449728e+01, 3.0210123e+01, 5.1376755e+01,
+ 1.0210074e+02, 4.4060019e+00, 4.0272511e+01, 1.6376346e+01,
+ 8.1009561e+01, 1.5665824e+01, 2.5227331e+01, 4.4897310e+00,
+ 4.4975382e+01, 1.9821051e+01, 2.0736286e+01, 3.6319425e+01,
+ 7.2088263e+00, 1.1187844e+01, 2.6713368e+01, 1.7962481e+01,
+ 1.9492612e+01, 1.3200905e+01, 1.1809729e+01, 1.6012045e+01,
+ 9.3764812e+00, 1.9393796e+01, 1.6381346e+01, 1.2937103e+01 ]
+
+])
+
+E_B = [ E_B_7M5, E_B_10M ]
+
+
+### C.3.1.7 Bandwidth detector
+
+P_BW_10M = np.array([ 1, 1 ])
+P_BW_7M5 = np.array([ 1, 1 ])
+P_BW = [ P_BW_7M5, P_BW_10M ]
+
+
+### C.3.1.8 SNS gains
+
+SCF_10M = np.array([
+
+ [ 3.5009846e+00, 4.4942639e+00, 2.3071956e+00, 1.2022551e+00,
+ 6.2362294e-01, 9.4722039e-03, -3.2828840e-02, -3.3840570e-01,
+ -7.2946152e-01, -1.0018093e+00, -1.2127892e+00, -1.4678244e+00,
+ -1.6640459e+00, -1.8392946e+00, -1.9307510e+00, -1.9205837e+00 ],
+
+ [ 3.7432369e+00, 5.6927098e+00, 3.2662471e+00, 1.4474935e+00,
+ -4.4505556e-01, -1.2458756e+00, -1.2458756e+00, -1.2458756e+00,
+ -1.2458756e+00, -1.2458756e+00, -1.2458756e+00, -1.2458756e+00,
+ -1.2458756e+00, -1.2458756e+00, -1.2458756e+00, -1.2458756e+00 ],
+
+ [ -1.5649514e+00, -1.1656014e+00, -1.5624815e+00, -1.1411195e+00,
+ -7.4976482e-01, -2.4654068e-01, 1.3534391e-01, -1.1293867e-01,
+ -1.6932960e-01, 5.7623565e-02, 6.7159547e-01, 9.3859612e-01,
+ 1.0824257e+00, 1.2057632e+00, 1.4053510e+00, 1.2160286e+00 ]
+
+])
+
+SCF_7M5 = np.array([
+
+ [ 4.4048340e+00, 3.5389298e+00, 1.5267043e+00, 7.9358598e-01,
+ 3.0615231e-01, -3.2867352e-02, -2.7847443e-01, -4.6371063e-01,
+ -6.8557046e-01, -8.7944953e-01, -1.0976367e+00, -1.2286102e+00,
+ -1.3879732e+00, -1.5027094e+00, -1.5071962e+00, -1.5060084e+00 ],
+
+ [ 5.4182466e+00, 4.3372862e+00, 3.1487482e-01, -7.7464674e-01,
+ -7.7464674e-01, -7.7464674e-01, -7.7464674e-01, -7.7464674e-01,
+ -7.7464674e-01, -7.7464674e-01, -7.7464674e-01, -7.7464674e-01,
+ -7.7464674e-01, -7.7464674e-01, -7.7464674e-01, -7.7464674e-01 ]
+
+])
+
+SCF = [ SCF_7M5, SCF_10M ]
+
+
+### C.3.1.9 SNS quantization: stage 2
+
+T2ROT_10M = np.array([
+
+ [ -3.8060310e-01, 2.8077898e-01, -6.7415911e-01, -4.4050504e-01,
+ -5.0680535e-02, 1.2946234e+00, -3.1905543e-02, -8.3983883e-01,
+ -3.0573474e-02, -1.7180800e-01, -3.1795511e-01, -5.6801435e-01,
+ -3.4459445e-01, -5.3266246e-02, -6.2922325e-02, -2.0856957e-01 ],
+
+ [ -6.9862836e-01, 7.4316023e-01, 1.6797292e-01, 1.7318569e+00,
+ 2.0540381e-01, -3.3073095e-01, -5.2816094e-01, -1.0380535e+00,
+ -6.4017558e-01, -3.8876809e-01, -3.3239735e-01, -4.8437565e-01,
+ -4.2394514e-01, -3.6228481e-01, -2.3217161e-01, -2.2684893e-01 ],
+
+ [ -1.0349648e+00, -8.7888573e-01, 1.9107834e-01, -9.0835649e-01,
+ 7.6273219e-01, 5.4107875e-01, 7.5161773e-01, -7.8846551e-02,
+ 1.4299991e-01, -1.5545871e-01, -6.6321266e-02, -7.2264622e-02,
+ -1.3018946e-01, -2.4094909e-01, -1.6785267e-01, 7.1244633e-02 ]
+
+])
+
+T2ROT_7M5 = np.array([
+
+ [ 5.5508969e-01, 3.8471081e-01, 4.0948426e-02, -7.5029612e-01,
+ -9.7881975e-01, 4.9702346e-01, -8.2168015e-02, -4.3546804e-01,
+ 1.8914981e-01, -1.9792621e-01, -2.4794744e-01, -2.9000112e-01,
+ -2.2928306e-01, -8.1890752e-02, -1.0731157e-01, -2.2349961e-01 ],
+
+ [ -1.9137509e-01, -1.3751444e-01, 4.4707625e-01, 4.0374158e-01,
+ 1.6628366e+00, 3.1663673e-01, 5.0786462e-01, 5.0214496e-01,
+ -2.8554914e-01, -6.2625497e-01, -4.7743904e-01, -5.5803079e-01,
+ -4.8903072e-01, -4.6108945e-01, -2.3248007e-01, -1.2652277e-01 ],
+
+])
+
+T2ROT = [ T2ROT_7M5, T2ROT_10M ]
+
+SNS_Y0_10M = np.array([
+ [ -1, 1,-2,-1, 0, 3, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0 ],
+ [ -1, 1, 0, 3, 0, 0,-1,-2,-1,-1, 0,-1, 0, 0, 0, 0 ],
+ [ -2,-2, 0,-2, 2, 1, 1, 0, 0, 0, 0, 0, 0,-1, 0, 0 ]
+])
+
+SNS_Y1_10M = np.array([
+ [ -1, 1,-2,-1, 0, 3, 0,-2, 0, 0 ],
+ [ -1, 1, 0, 3, 0, 0,-1,-2,-1,-1 ],
+ [ -2,-2, 0,-2, 2, 1, 1, 0, 0, 0 ]
+])
+
+SNS_Y2_10M = np.array([
+ [ -1, 0,-1,-1, 0, 2, 0,-1, 0, 0, 0,-1,-1, 0, 0, 0 ],
+ [ -1, 1, 0, 2, 0, 0,-1,-1,-1, 0, 0,-1, 0, 0, 0, 0 ],
+ [ -2,-1, 0,-2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+])
+
+SNS_Y3_10M = np.array([
+ [ 0, 0,-1,-1, 0, 2, 0,-1, 0, 0, 0,-1, 0, 0, 0, 0 ],
+ [ -1, 1, 0, 2, 0, 0, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0 ],
+ [ -1,-1, 0,-1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+])
+
+SNS_Y0_7M5 = np.array([
+ [ 1, 1, 0,-2,-3, 1, 0,-1, 0,-1, 0,-1, 0, 0, 0, 0 ],
+ [ 0, 0, 1, 1, 3, 1, 1, 1,-1,-1, 0,-1, 0, 0, 0, 0 ]
+])
+
+SNS_Y1_7M5 = np.array([
+ [ 1, 1, 0,-2,-3, 1, 0,-1, 0,-1 ],
+ [ 0, 0, 1, 1, 3, 1, 1, 1,-1,-1 ]
+])
+
+SNS_Y2_7M5 = np.array([
+ [ 1, 1, 0,-1,-2, 1, 0,-1, 0, 0, 0,-1, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 2, 0, 1, 1, 0,-1,-1,-1,-1, 0, 0, 0 ]
+])
+
+SNS_Y3_7M5 = np.array([
+ [ 1, 0, 0,-1,-2, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 2, 0, 1, 1, 0,-1, 0,-1, 0, 0, 0, 0 ]
+])
+
+SNS_Y0 = [ SNS_Y0_7M5, SNS_Y0_10M ]
+SNS_Y1 = [ SNS_Y1_7M5, SNS_Y1_10M ]
+SNS_Y2 = [ SNS_Y2_7M5, SNS_Y2_10M ]
+SNS_Y3 = [ SNS_Y3_7M5, SNS_Y3_10M ]
+
+SNS_XQ0_10M = np.array([
+
+ [ -2.1821789e-01, 2.1821789e-01, -4.3643578e-01, -2.1821789e-01,
+ -0.0000000e+00, 6.5465367e-01, -0.0000000e+00, -4.3643578e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -2.1821789e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -2.2941573e-01, 2.2941573e-01, 0.0000000e+00, 6.8824720e-01,
+ 0.0000000e+00, -0.0000000e+00, -2.2941573e-01, -4.5883147e-01,
+ -2.2941573e-01, -2.2941573e-01, -0.0000000e+00, -2.2941573e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -4.5883147e-01, -4.5883147e-01, 0.0000000e+00, -4.5883147e-01,
+ 4.5883147e-01, 2.2941573e-01, 2.2941573e-01, -0.0000000e+00,
+ 0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -2.2941573e-01, -0.0000000e+00, 0.0000000e+00 ]
+
+])
+
+SNS_XQ1_10M = np.array([
+
+ [ -2.2360680e-01, 2.2360680e-01, -4.4721360e-01, -2.2360680e-01,
+ -0.0000000e+00, 6.7082039e-01, -0.0000000e+00, -4.4721360e-01,
+ -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -2.3570226e-01, 2.3570226e-01, 0.0000000e+00, 7.0710678e-01,
+ 0.0000000e+00, -0.0000000e+00, -2.3570226e-01, -4.7140452e-01,
+ -2.3570226e-01, -2.3570226e-01 ],
+
+ [ -4.7140452e-01, -4.7140452e-01, 0.0000000e+00, -4.7140452e-01,
+ 4.7140452e-01, 2.3570226e-01, 2.3570226e-01, -0.0000000e+00,
+ 0.0000000e+00, -0.0000000e+00 ],
+
+])
+
+SNS_XQ2_10M = np.array([
+
+ [ -3.1622777e-01, 0.0000000e+00, -3.1622777e-01, -3.1622777e-01,
+ -0.0000000e+00, 6.3245553e-01, -0.0000000e+00, -3.1622777e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -3.1622777e-01,
+ -3.1622777e-01, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -3.1622777e-01, 3.1622777e-01, 0.0000000e+00, 6.3245553e-01,
+ 0.0000000e+00, -0.0000000e+00, -3.1622777e-01, -3.1622777e-01,
+ -3.1622777e-01, -0.0000000e+00, -0.0000000e+00, -3.1622777e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -5.7735027e-01, -2.8867513e-01, 0.0000000e+00, -5.7735027e-01,
+ 2.8867513e-01, 2.8867513e-01, 2.8867513e-01, -0.0000000e+00,
+ 0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, 0.0000000e+00 ]
+
+])
+
+SNS_XQ3_10M = np.array([
+
+ [ -0.0000000e+00, 0.0000000e+00, -3.5355339e-01, -3.5355339e-01,
+ -0.0000000e+00, 7.0710678e-01, -0.0000000e+00, -3.5355339e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -3.5355339e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -3.5355339e-01, 3.5355339e-01, 0.0000000e+00, 7.0710678e-01,
+ 0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -3.5355339e-01,
+ -3.5355339e-01, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -4.0824829e-01, -4.0824829e-01, 0.0000000e+00, -4.0824829e-01,
+ 4.0824829e-01, 4.0824829e-01, 4.0824829e-01, -0.0000000e+00,
+ 0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, 0.0000000e+00 ]
+
+])
+
+SNS_XQ0_7M5 = np.array([
+
+ [ 2.2941573e-01, 2.2941573e-01, 0.0000000e+00, -4.5883147e-01,
+ -6.8824720e-01, 2.2941573e-01, -0.0000000e+00, -2.2941573e-01,
+ 0.0000000e+00, -2.2941573e-01, -0.0000000e+00, -2.2941573e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -0.0000000e+00, -0.0000000e+00, 2.4253563e-01, 2.4253563e-01,
+ 7.2760688e-01, 2.4253563e-01, 2.4253563e-01, 2.4253563e-01,
+ -2.4253563e-01, -2.4253563e-01, -0.0000000e+00, -2.4253563e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ]
+
+])
+
+SNS_XQ1_7M5 = np.array([
+
+ [ 2.3570226e-01, 2.3570226e-01, 0.0000000e+00, -4.7140452e-01,
+ -7.0710678e-01, 2.3570226e-01, -0.0000000e+00, -2.3570226e-01,
+ 0.0000000e+00, -2.3570226e-01 ],
+
+ [ -0.0000000e+00, -0.0000000e+00, 2.5000000e-01, 2.5000000e-01,
+ 7.5000000e-01, 2.5000000e-01, 2.5000000e-01, 2.5000000e-01,
+ -2.5000000e-01, -2.5000000e-01 ]
+
+])
+
+SNS_XQ2_7M5 = np.array([
+
+ [ 3.1622777e-01, 3.1622777e-01, 0.0000000e+00, -3.1622777e-01,
+ -6.3245553e-01, 3.1622777e-01, -0.0000000e+00, -3.1622777e-01,
+ 0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -3.1622777e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -0.0000000e+00, -0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 6.3245553e-01, 0.0000000e+00, 3.1622777e-01, 3.1622777e-01,
+ -0.0000000e+00, -3.1622777e-01, -3.1622777e-01, -3.1622777e-01,
+ -3.1622777e-01, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ]
+
+])
+
+SNS_XQ3_7M5 = np.array([
+
+ [ 3.5355339e-01, 0.0000000e+00, 0.0000000e+00, -3.5355339e-01,
+ -7.0710678e-01, 3.5355339e-01, -0.0000000e+00, -3.5355339e-01,
+ 0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ],
+
+ [ -0.0000000e+00, -0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 7.0710678e-01, 0.0000000e+00, 3.5355339e-01, 3.5355339e-01,
+ -0.0000000e+00, -3.5355339e-01, -0.0000000e+00, -3.5355339e-01,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00 ]
+
+])
+
+SNS_XQ0 = [ SNS_XQ0_7M5, SNS_XQ0_10M ]
+SNS_XQ1 = [ SNS_XQ1_7M5, SNS_XQ1_10M ]
+SNS_XQ2 = [ SNS_XQ2_7M5, SNS_XQ2_10M ]
+SNS_XQ3 = [ SNS_XQ3_7M5, SNS_XQ3_10M ]
+
+
+### C.3.1.10/12 SNS quantization gains
+
+IND_LF_10M = np.array([ 25, 25, 4 ])
+IND_LF_7M5 = np.array([ 17, 17 ])
+IND_LF = [ IND_LF_7M5, IND_LF_10M ]
+
+IND_HF_10M = np.array([ 8, 9, 27 ])
+IND_HF_7M5 = np.array([ 8, 25 ])
+IND_HF = [ IND_HF_7M5, IND_HF_10M ]
+
+SUBMODE_MSB_10M = np.array([ 0, 0, 1 ])
+SUBMODE_MSB_7M5 = np.array([ 0, 0 ])
+SUBMODE_MSB = [ SUBMODE_MSB_7M5, SUBMODE_MSB_10M ]
+
+SUBMODE_LSB_10M = np.array([ 0, 0, 1 ])
+SUBMODE_LSB_7M5 = np.array([ 1, 0 ])
+SUBMODE_LSB = [ SUBMODE_LSB_7M5, SUBMODE_LSB_10M ]
+
+G_IND_10M = np.array([ 0, 0, 3 ])
+G_IND_7M5 = np.array([ 0, 0 ])
+G_IND = [ G_IND_7M5, G_IND_10M ]
+
+LS_IND_A_10M = np.array([ 1, 1, 1 ])
+LS_IND_A_7M5 = np.array([ 0, 0 ])
+LS_IND_A = [ LS_IND_A_7M5, LS_IND_A_10M ]
+
+LS_IND_B_10M = np.array([ True, True, None ])
+LS_IND_B_7M5 = np.array([ None, 1 ])
+LS_IND_B = [ LS_IND_B_7M5, LS_IND_B_10M ]
+
+IDX_A_10M = np.array([ 865837, 1023911, 61886 ])
+IDX_A_7M5 = np.array([ 1025681, 2213651 ])
+IDX_A = [ IDX_A_7M5, IDX_A_10M ]
+
+IDX_B_10M = np.array([ 1, 1, None ])
+IDX_B_7M5 = np.array([ None, 1 ])
+IDX_B = [ IDX_B_7M5, IDX_B_10M ]
+
+SCF_Q_10M = np.array([
+
+ [ 3.6627046e+00, 4.1100042e+00, 2.4746060e+00, 1.1870402e+00,
+ 5.2877727e-01, 7.5258069e-02, 2.3608016e-01, -2.5249380e-01,
+ -6.8201580e-01, -1.1328318e+00, -1.0800359e+00, -1.6239492e+00,
+ -1.7143487e+00, -1.9073626e+00, -2.2321087e+00, -2.0267285e+00 ],
+
+ [ 3.8168009e+00, 5.1162010e+00, 3.4807329e+00, 1.1997530e+00,
+ -2.2081921e-01, -1.0181629e+00, -1.0657728e+00, -1.1230690e+00,
+ -1.2811443e+00, -1.3048218e+00, -1.2081961e+00, -1.2804827e+00,
+ -8.0867787e-01, -1.0022261e+00, -1.3971454e+00, -1.1057621e+00 ],
+
+ [ -1.3038278e+00, -1.3183731e+00, -1.4433352e+00, -1.3025832e+00,
+ -7.2407159e-01, -7.0739510e-02, 3.0891592e-01, 1.1110561e-01,
+ -2.3826205e-01, 2.2790355e-01, 7.5958402e-01, 1.0128069e+00,
+ 1.0886346e+00, 1.3319042e+00, 1.4367016e+00, 1.0146522e+00 ]
+
+])
+
+
+SCF_Q_7M5 = np.array([
+
+ [ 4.3811806e+00, 3.2082316e+00, 1.7782399e+00, 6.4980749e-01,
+ 2.0221356e-01, 7.0332445e-02, -2.8668104e-01, -8.5700304e-01,
+ -6.1964726e-01, -8.0165679e-01, -1.0516986e+00, -1.3477232e+00,
+ -1.4003932e+00, -1.5566567e+00, -1.6059594e+00, -1.5454836e+00 ],
+
+ [ 5.8316083e+00, 3.9835316e+00, 8.6468396e-01, -9.5443316e-01,
+ -8.1173658e-01, -6.2522498e-01, -6.4450858e-01, -7.4038105e-01,
+ -1.0412349e+00, -6.5113903e-01, -5.8671926e-01, -9.6639127e-01,
+ -5.7817825e-01, -5.4629017e-01, -9.2263684e-01, -8.4544942e-01 ],
+
+])
+
+SCF_Q = [ SCF_Q_7M5, SCF_Q_10M ]
+
+
+### C.3.1.11 SNS interpolation
+
+G_SNS_10M = np.array([
+
+ [ 7.8961620e-02, 7.8961620e-02, 7.5959959e-02, 7.0294618e-02,
+ 6.5051816e-02, 6.0200039e-02, 6.6727283e-02, 8.8588922e-02,
+ 1.1761302e-01, 1.5614618e-01, 2.0114945e-01, 2.5143043e-01,
+ 3.1428006e-01, 3.9284010e-01, 4.6498069e-01, 5.2116367e-01,
+ 5.8413517e-01, 6.5471542e-01, 7.2092077e-01, 7.7986290e-01,
+ 8.4362411e-01, 9.1259840e-01, 9.3603811e-01, 9.1031240e-01,
+ 8.8529374e-01, 8.6096267e-01, 8.8576235e-01, 9.6402006e-01,
+ 1.0491919e+00, 1.1418887e+00, 1.2364330e+00, 1.3319727e+00,
+ 1.4348949e+00, 1.5457699e+00, 1.6682873e+00, 1.8038405e+00,
+ 1.9504078e+00, 2.1088841e+00, 2.1828793e+00, 2.1629996e+00,
+ 2.1433009e+00, 2.1237816e+00, 2.2161032e+00, 2.4351378e+00,
+ 2.6758212e+00, 2.9402932e+00, 3.1064119e+00, 3.1554571e+00,
+ 3.2052766e+00, 3.2558828e+00, 3.3368236e+00, 3.4503169e+00,
+ 3.5676705e+00, 3.6890154e+00, 3.8582746e+00, 4.0816214e+00,
+ 4.3178972e+00, 4.5678504e+00, 4.6153375e+00, 4.4539677e+00,
+ 4.2982400e+00, 4.1479572e+00, 4.0029288e+00, 3.8629712e+00 ],
+
+ [ 7.0962424e-02, 7.0962424e-02, 6.3406480e-02, 5.0622552e-02,
+ 4.0416103e-02, 3.2267464e-02, 3.3220843e-02, 4.4105412e-02,
+ 5.8556233e-02, 7.7741760e-02, 1.0915042e-01, 1.6206389e-01,
+ 2.4062852e-01, 3.5727938e-01, 4.9237129e-01, 6.2979823e-01,
+ 8.0558272e-01, 1.0304308e+00, 1.2487522e+00, 1.4337794e+00,
+ 1.6462221e+00, 1.8901424e+00, 2.0337102e+00, 2.0505581e+00,
+ 2.0675455e+00, 2.0846737e+00, 2.1037086e+00, 2.1246996e+00,
+ 2.1459001e+00, 2.1673122e+00, 2.2081350e+00, 2.2694571e+00,
+ 2.3324822e+00, 2.3972575e+00, 2.4353075e+00, 2.4453201e+00,
+ 2.4553739e+00, 2.4654690e+00, 2.4499352e+00, 2.4092551e+00,
+ 2.3692505e+00, 2.3299102e+00, 2.3250020e+00, 2.3543088e+00,
+ 2.3839851e+00, 2.4140354e+00, 2.3319019e+00, 2.1488367e+00,
+ 1.9801431e+00, 1.8246926e+00, 1.7812270e+00, 1.8419813e+00,
+ 1.9048079e+00, 1.9697773e+00, 2.0728144e+00, 2.2196325e+00,
+ 2.3768496e+00, 2.5452025e+00, 2.5681376e+00, 2.4416843e+00,
+ 2.3214575e+00, 2.2071505e+00, 2.0984720e+00, 1.9951447e+00 ]
+
+])
+
+G_SNS_7M5 = np.array([
+
+ [ 4.7988064e-02, 4.7988064e-02, 5.3121439e-02, 6.5094311e-02,
+ 7.9765711e-02, 9.7743851e-02, 1.2247145e-01, 1.5691066e-01,
+ 2.0103424e-01, 2.5756547e-01, 3.2148295e-01, 3.9091375e-01,
+ 4.7533955e-01, 5.7799882e-01, 6.6256861e-01, 7.1600434e-01,
+ 7.7374963e-01, 8.3615204e-01, 8.7920505e-01, 8.9952910e-01,
+ 9.2032297e-01, 9.4159751e-01, 9.8233993e-01, 1.0450324e+00,
+ 1.1117258e+00, 1.1826756e+00, 1.2816224e+00, 1.4147546e+00,
+ 1.5617162e+00, 1.7239439e+00, 1.7744028e+00, 1.7029011e+00,
+ 1.6342806e+00, 1.5684252e+00, 1.5609220e+00, 1.6109378e+00,
+ 1.6625563e+00, 1.7158288e+00, 1.7812772e+00, 1.8601545e+00,
+ 1.9425246e+00, 2.0285422e+00, 2.1268255e+00, 2.2387723e+00,
+ 2.3566116e+00, 2.4806533e+00, 2.5567427e+00, 2.5801849e+00,
+ 2.6038421e+00, 2.6277162e+00, 2.6757181e+00, 2.7491622e+00,
+ 2.8246222e+00, 2.9021534e+00, 2.9543066e+00, 2.9796549e+00,
+ 3.0052206e+00, 3.0310057e+00, 3.0280729e+00, 2.9965054e+00,
+ 2.9652670e+00, 2.9343543e+00, 2.9037639e+00, 2.8734924e+00 ],
+
+ [ 1.7559453e-02, 1.7559453e-02, 2.0608757e-02, 2.8387910e-02,
+ 3.9103448e-02, 5.3863762e-02, 8.2831558e-02, 1.4220423e-01,
+ 2.4413451e-01, 4.1912721e-01, 6.4291757e-01, 8.8116553e-01,
+ 1.2077018e+00, 1.6552436e+00, 1.9140070e+00, 1.8672589e+00,
+ 1.8216525e+00, 1.7771601e+00, 1.7271850e+00, 1.6722548e+00,
+ 1.6190716e+00, 1.5675798e+00, 1.5450306e+00, 1.5502021e+00,
+ 1.5553909e+00, 1.5605971e+00, 1.5762459e+00, 1.6026515e+00,
+ 1.6294995e+00, 1.6567972e+00, 1.7147376e+00, 1.8065050e+00,
+ 1.9031836e+00, 2.0050361e+00, 1.9895925e+00, 1.8595441e+00,
+ 1.7379963e+00, 1.6243933e+00, 1.5616667e+00, 1.5443306e+00,
+ 1.5271869e+00, 1.5102336e+00, 1.5520535e+00, 1.6576004e+00,
+ 1.7703250e+00, 1.8907155e+00, 1.8893168e+00, 1.7663992e+00,
+ 1.6514784e+00, 1.5440344e+00, 1.4888436e+00, 1.4806393e+00,
+ 1.4724802e+00, 1.4643660e+00, 1.5087288e+00, 1.6104012e+00,
+ 1.7189253e+00, 1.8347627e+00, 1.8829418e+00, 1.8579241e+00,
+ 1.8332388e+00, 1.8088814e+00, 1.7848477e+00, 1.7611333e+00 ],
+
+])
+
+G_SNS = [ G_SNS_7M5, G_SNS_10M ]
+
+
+### C.3.1.13 Spectral shaping
+
+X_S_10M = np.array([
+
+ [ -4.6579970e+01, 2.5475086e+03, -2.0979386e+03, 6.6905115e+03,
+ -7.4276511e+03, -1.3496582e+04, -1.4911551e+02, -1.7600517e+03,
+ -1.8897070e+03, 9.0806525e+01, -3.1626076e+03, 1.0097116e+03,
+ -3.1704894e+03, 7.4708040e+02, -1.9508019e+03, -5.0811399e+02,
+ 2.7592179e+02, -1.8004443e+03, 1.7810815e+03, -2.1469042e+03,
+ 1.8820925e+03, -1.3520099e+03, 7.5748485e+02, 9.4849121e+01,
+ -5.5907550e+02, 9.9853924e+02, -1.1694214e+03, 1.2670596e+03,
+ -1.1564965e+03, 7.6341371e+02, -3.7429412e+02, -1.2714316e+02,
+ 5.5868459e+02, -8.6630814e+02, 1.0827149e+03, -1.0408470e+03,
+ 9.2759078e+02, -5.8910202e+02, 2.3201842e+02, 1.8289697e+02,
+ -5.6951623e+02, 8.1229132e+02, -9.9835988e+02, 9.3658953e+02,
+ -8.1543182e+02, 4.9408042e+02, -1.3648595e+02, -2.4771597e+02,
+ 5.9096160e+02, -7.9945187e+02, 8.7469937e+02, -8.0242901e+02,
+ 6.1523337e+02, -3.4929423e+02, 4.3714524e+01, 2.3825249e+02,
+ -4.7949197e+02, 6.1487056e+02, -6.8885288e+02, 6.1543922e+02,
+ -4.5940587e+02, 2.6027447e+02, 1.4932451e+01, -2.6342003e+02,
+ 5.1698905e+02, -6.3805644e+02, 6.6431016e+02, -6.3536804e+02,
+ 4.4714179e+02, -2.0448694e+02, -7.5210020e+01, 3.2318745e+02,
+ -5.2463109e+02, 6.3268159e+02, -6.4137909e+02, 5.4210738e+02,
+ -3.6539049e+02, 1.4180793e+02, 1.1043715e+02, -3.2082774e+02,
+ 4.9551143e+02, -5.6464214e+02, 5.5411819e+02, -4.4912438e+02,
+ 2.8748742e+02, -8.3157725e+01, -1.4199053e+02, 3.1886540e+02,
+ -4.7410616e+02, 5.2507181e+02, -4.9901112e+02, 3.9510519e+02,
+ -2.3175576e+02, 3.7914915e+01, 1.7066614e+02, -3.3127409e+02,
+ 4.6682698e+02, -5.0146152e+02, 4.5964223e+02, -3.4704713e+02,
+ 1.8377315e+02, 8.3068359e-01, -2.0227229e+02, 3.5108641e+02,
+ -4.5284836e+02, 4.7317762e+02, -4.4561519e+02, 3.2535592e+02,
+ -1.4580770e+02, -3.9573578e+01, 2.3102912e+02, -3.8615649e+02,
+ 4.7298066e+02, -4.8574358e+02, 4.1595651e+02, -2.8690887e+02,
+ 1.0822973e+02, 8.0889458e+01, -2.6856378e+02, 4.0232748e+02,
+ -4.7864051e+02, 4.7205528e+02, -3.9210707e+02, 2.5719880e+02,
+ -6.8160760e+01, -1.1068097e+02, 2.8495852e+02, -3.8530783e+02,
+ 4.4481193e+02, -4.2962793e+02, 3.3997586e+02, -2.0750452e+02,
+ 2.8600150e+01, 1.3080486e+02, -2.8418457e+02, 3.7335187e+02,
+ -4.1400983e+02, 3.8613469e+02, -2.8921905e+02, 1.5545710e+02,
+ 5.7416806e+00, -1.4821308e+02, 2.8457226e+02, -3.6307452e+02,
+ 3.8831635e+02, -3.4730222e+02, 2.4109847e+02, -1.1774263e+02,
+ -3.0666081e+01, 1.6872235e+02, -2.8808479e+02, 3.5123254e+02,
+ -3.6347751e+02, 3.0487804e+02, -2.1236231e+02, 8.7865496e+01,
+ 6.0906484e+01, -1.8416198e+02, 2.9273130e+02, -3.4443289e+02 ],
+
+ [ -4.4595314e+02, -1.0379970e+03, 3.1577388e+02, -3.5610417e+03,
+ 3.4581766e+03, 8.3381081e+03, -1.1696533e+03, 2.4101021e+03,
+ -6.5655829e+02, 1.4524982e+03, 1.9701386e+02, 1.1436715e+03,
+ 3.0871470e+02, 1.4623552e+03, 5.8823857e+02, 9.7150548e+02,
+ 4.8597295e+02, 6.6672780e+02, 1.9624228e+02, 1.5262224e+02,
+ -1.2492188e+01, -9.9749152e+01, -1.2404934e+02, -1.7103668e+02,
+ -9.0965339e+01, -7.0386211e+01, -2.5404068e+01, -6.2239848e+00,
+ 1.1353459e+01, 3.1118246e+01, 2.3550684e+01, 1.9918764e+01,
+ 6.7582893e+00, 3.5391093e+00, -2.5360957e+00, -1.2318765e+01,
+ -1.0710738e+01, -1.0309510e+01, -4.8149059e+00, -1.0084275e+00,
+ 1.5451084e+00, 6.7503435e+00, 8.7185892e+00, 6.5017316e+00,
+ 3.3714192e+00, 3.3653026e+00, 1.5730174e-01, -2.7592084e+00,
+ -5.2662479e+00, -5.1967404e+00, -2.6956428e+00, -3.2877724e+00,
+ -2.9012824e+00, 3.7032988e-01, 2.4268422e+00, 4.6841491e+00,
+ 4.4233993e+00, 2.9001769e+00, 4.0245597e+00, 2.1909513e+00,
+ -7.8166125e-01, -3.7740437e+00, -1.6826612e+00, -4.8759902e+00,
+ -7.0146012e+00, -4.2610160e+00, -1.9222920e+00, -3.8849374e-03,
+ 1.9171256e+00, 2.1228421e+00, 4.0002861e+00, 2.4213202e+00,
+ 5.5365640e+00, 2.0924576e+00, 3.2856722e+00, 2.3805212e-01,
+ -2.6499944e+00, -1.5877393e+00, -2.3638844e+00, -3.1969127e+00,
+ -4.5049447e+00, 4.9555393e-01, -5.2555443e-01, 2.8655462e-01,
+ -4.9844313e-01, 1.3144496e+00, 1.8462413e+00, 1.2390833e+00,
+ 1.8391487e-01, 1.3634153e+00, -3.0575242e-02, -1.2360920e+00,
+ 1.7996128e-01, -2.1572539e+00, -2.3206289e+00, -2.1575175e+00,
+ -1.3914054e+00, -2.1857655e+00, 2.8328476e-01, 9.0849227e-01,
+ 1.5616765e+00, 3.0216795e+00, 4.0452889e+00, 3.2116107e+00,
+ 1.5944792e+00, 2.2110634e-01, -1.2957452e+00, -3.9440236e-01,
+ -1.7499591e+00, -1.8705540e+00, -2.4921933e-01, 4.0425431e-01,
+ -3.0395784e+00, -1.9499112e+00, 6.8993026e-02, 2.6858112e+00,
+ 3.9365468e+00, 1.4534664e+00, 2.5590207e+00, 1.9618160e+00,
+ -3.1812104e-01, 3.6820368e-01, -2.3536912e-02, 3.9009812e-01,
+ -4.7912977e+00, -3.3553682e+00, -2.6900314e+00, -1.5134286e+00,
+ -9.9684877e-01, -6.2871446e-01, 1.8360627e+00, 1.4455944e+00,
+ 9.5156525e-01, 1.0993584e+00, 2.2401521e+00, 2.4733664e+00,
+ 2.3631456e-01, -2.0269302e+00, -2.4458555e+00, -1.2206038e+00,
+ -3.2403583e+00, -2.0795885e+00, -1.5947867e+00, -1.1727234e+00,
+ -3.2945845e-01, 8.0000134e-01, 3.4717506e-01, 1.5246353e+00,
+ -1.6045804e-01, 4.0202852e-02, 1.8039411e+00, 1.0516099e-01,
+ -7.4544919e-02, -2.1387580e+00, -2.0486855e+00, -7.9121437e-01,
+ -7.4423018e-01, -1.5334714e+00, -7.8671386e-01, -1.6940090e-01 ]
+
+])
+
+X_S_7M5 = np.array([
+
+ [ -1.3344626e+03, 1.4958812e+03, -5.5694903e+03, -1.0486529e+04,
+ 5.6650034e+02, 6.0141573e+03, -5.3094551e+02, 2.6475111e+02,
+ 1.6690199e+03, -2.0838083e+03, 9.3187330e+02, 6.3720777e+02,
+ -1.8748573e+03, 1.9287595e+03, -4.9900796e+02, -1.1216643e+03,
+ 1.8281601e+03, -1.3351793e+03, -2.5896432e+01, 1.1847513e+03,
+ -1.4008698e+03, 7.1091673e+02, 3.4181812e+02, -1.1209015e+03,
+ 1.1047015e+03, -3.4707684e+02, -6.0822434e+02, 1.2069267e+03,
+ -9.8898328e+02, 3.9434472e+01, 8.9967867e+02, -1.1231789e+03,
+ 6.1473708e+02, 2.1402341e+02, -7.6438486e+02, 7.6886411e+02,
+ -3.0289717e+02, -3.6710597e+02, 7.3659799e+02, -5.8064409e+02,
+ 8.6987653e+01, 4.6780721e+02, -6.8240093e+02, 4.0409628e+02,
+ 9.0635459e+01, -5.3255888e+02, 6.1176277e+02, -2.4268516e+02,
+ -2.4050228e+02, 5.6445766e+02, -5.1941054e+02, 8.4546495e+01,
+ 3.6675922e+02, -5.6559679e+02, 4.1109821e+02, 6.3236483e+01,
+ -4.6563784e+02, 5.3992584e+02, -2.8194795e+02, -2.0189361e+02,
+ 5.0504429e+02, -4.5411112e+02, 1.2935836e+02, 2.9902539e+02,
+ -4.9207698e+02, 3.4402101e+02, 1.8978015e+00, -3.6234196e+02,
+ 4.6346622e+02, -2.2783004e+02, -1.1745582e+02, 4.0795439e+02,
+ -4.1004303e+02, 1.1293439e+02, 2.1977291e+02, -4.1879288e+02,
+ 3.3765885e+02, -2.7615664e+00, -2.9831792e+02, 4.0573572e+02,
+ -2.5374285e+02, -1.0182244e+02, 3.5226045e+02, -3.6553462e+02,
+ 1.5203133e+02, 1.9094377e+02, -3.7905818e+02, 3.0025026e+02,
+ -4.9616026e+01, -2.6139695e+02, 3.7537731e+02, -2.2263305e+02,
+ -4.6540403e+01, 3.1054395e+02, -3.4657574e+02, 1.3778205e+02,
+ 1.3283532e+02, -3.3677365e+02, 3.0049394e+02, -4.5453695e+01,
+ -2.0808762e+02, 3.3473443e+02, -2.3547267e+02, -4.3881934e+01,
+ 2.5964919e+02, -3.1164958e+02, 1.6251702e+02, 1.2186915e+02,
+ -2.9548260e+02, 2.7121711e+02, -8.0864501e+01, -1.8718254e+02,
+ 3.0861481e+02, -2.1772078e+02, 4.7378118e-01, 2.4022293e+02,
+ -3.0348233e+02, 1.5168546e+02, 7.7875700e+01, -2.8137835e+02 ],
+
+ [ 6.6940015e+01, -3.8686730e+02, 1.2805107e+03, -7.2628992e+03,
+ -1.5754672e+03, -6.2436979e+02, 8.2787173e+02, -8.0959099e+02,
+ -3.4245127e+02, -3.5548999e+01, -1.0732178e+02, 3.3015325e+01,
+ 1.9173905e+02, 1.8057154e+02, -2.3823068e+01, -1.4567609e+02,
+ -1.0868931e+02, 3.0479251e+01, 7.1566338e+01, 2.4158550e+01,
+ -6.2114342e+00, -1.4130388e+01, -1.8394789e+01, -1.8227404e+01,
+ 3.8411657e+00, 2.5627619e+01, 2.8307446e+01, -1.6207017e+00,
+ -2.8151474e+01, -2.4154773e+01, -5.2808122e-01, 6.3053889e+00,
+ 1.6985395e+01, 2.1137594e+01, 1.0163883e+01, -1.2646204e+01,
+ -2.8258074e+01, -1.5957606e+01, 1.0393474e+01, 1.5431458e+01,
+ 1.0833710e+01, 6.5820435e+00, -4.0055074e+00, -1.1459013e+01,
+ -1.4519949e+01, -5.8509646e+00, 1.5015967e+01, 1.5836030e+01,
+ 4.1133189e+00, -1.7829961e+00, -8.3853815e+00, -1.1122404e+01,
+ -8.7393669e+00, 3.6899921e+00, 1.7989851e+01, 1.3569871e+01,
+ -4.2575144e+00, -9.6890713e+00, -1.0139553e+01, -8.7913755e+00,
+ -1.6029731e+00, 5.0445901e+00, 1.4433262e+01, 9.5900419e+00,
+ -8.2284294e+00, -9.7476743e+00, -6.5414935e+00, -1.9885597e+00,
+ 2.9171599e+00, 6.6780713e+00, 9.2081019e+00, 2.8651322e+00,
+ -1.0061317e+01, -1.1376702e+01, -1.6700624e+00, 1.3140771e+00,
+ 6.5095758e+00, 6.8977417e+00, 4.8690746e+00, -8.2814942e-01,
+ -1.0064761e+01, -8.9205098e+00, 1.2429849e+00, 7.8244782e+00,
+ 6.6880480e+00, 5.8136759e+00, 5.9984867e-01, -6.0624312e+00,
+ -1.1389596e+01, -7.9714369e+00, 7.4518543e+00, 8.9170413e+00,
+ 6.3880481e+00, 1.3801389e+00, -2.8576875e+00, -6.7319113e+00,
+ -1.0072255e+01, -3.5424326e+00, 8.4784304e+00, 1.0898685e+01,
+ 4.8542048e+00, -2.6188427e+00, -5.9736376e+00, -7.4232870e+00,
+ -5.5939115e+00, 1.9917820e+00, 1.1064235e+01, 9.7301910e+00,
+ -4.8166311e-01, -6.0418655e+00, -7.8074447e+00, -6.7420485e+00,
+ -5.7805346e-01, 4.1557564e+00, 1.1700978e+01, 7.8318863e+00,
+ -4.5426418e+00, -8.2115262e+00, -6.8867416e+00, -1.9487360e+00 ]
+
+])
+
+X_S = [ X_S_7M5, X_S_10M ]
+
+
+### C.3.1.14 TNS coder
+
+X_F_10M = np.array([
+
+ [ -4.6579970e+01, 2.5475086e+03, -2.0979386e+03, 6.6905115e+03,
+ -7.4276511e+03, -1.3496582e+04, -1.4911551e+02, -1.7600517e+03,
+ -1.8897070e+03, 9.0806525e+01, -3.1626076e+03, 1.0097116e+03,
+ -3.1704894e+03, -1.4629727e+03, 1.6177531e+02, -2.8070849e+02,
+ 1.6836280e+02, -4.8794939e+02, 4.8735463e+01, -3.2812648e+02,
+ 2.0567762e+02, -2.7612607e+02, 1.7089464e+02, -1.4903447e+02,
+ 1.7634897e+02, -1.7636863e+02, -1.4114282e+01, 1.5326904e+02,
+ -2.0051680e+02, 7.5885344e+01, -1.2030117e+02, 8.6222257e+01,
+ 3.4247381e+01, -3.1564007e+01, 1.3038568e+02, -1.1547149e+02,
+ 1.5722828e+02, -1.1575179e+02, 8.3918034e+01, -4.2997589e+01,
+ -4.9151429e+01, 5.7178185e+01, -1.4462317e+02, 1.2240116e+02,
+ -1.4658879e+02, 1.0329710e+02, -4.8119513e+01, 1.5046477e+01,
+ 4.7974194e+01, -6.8870459e+01, 7.5850716e+01, -1.0491255e+02,
+ 1.0512982e+02, -9.6951573e+01, 6.8788954e+01, -3.9997908e+01,
+ -8.7506165e+00, 3.5520535e+01, -9.4932383e+01, 8.5065288e+01,
+ -6.7462450e+01, 9.2204890e+01, -2.2005176e+01, -2.2102766e+01,
+ 7.7845918e+01, -7.8223738e+01, 7.3211489e+01, -1.4466156e+02,
+ 7.8730279e+01, -2.1569349e+01, 2.0934594e+01, 1.0330210e+01,
+ -5.6199662e+01, 7.4347857e+01, -8.7431560e+01, 8.2441742e+01,
+ -7.4246878e+01, 5.8052214e+01, -1.2858317e+01, -8.5491490e+00,
+ 4.9073587e+01, -6.1606297e+01, 7.0756502e+01, -7.3226896e+01,
+ 6.7149964e+01, -4.3873945e+01, -3.2798184e-01, 1.2618393e+01,
+ -6.0263717e+01, 6.9581326e+01, -6.2258677e+01, 7.0807773e+01,
+ -5.6473108e+01, 2.9499750e+01, 6.4843952e+00, -2.1637431e+01,
+ 6.5900289e+01, -6.9209851e+01, 5.7574118e+01, -6.3239986e+01,
+ 5.0201888e+01, -2.5161732e+01, -1.8407647e+01, 3.3057952e+01,
+ -5.1394596e+01, 6.6274453e+01, -8.9093497e+01, 6.1636186e+01,
+ -1.8970991e+01, 1.8110690e+01, 1.4664315e+01, -5.7379639e+01,
+ 5.9659304e+01, -6.7425126e+01, 6.6740221e+01, -5.6441736e+01,
+ 3.3370764e+01, -8.8727172e+00, -2.8768291e+01, 4.7072609e+01,
+ -6.4504039e+01, 7.0679425e+01, -6.4413968e+01, 5.7895311e+01,
+ -2.2822099e+01, 8.2462832e+00, 2.1908355e+01, -3.0461871e+01,
+ 5.6741507e+01, -7.3393219e+01, 5.3252893e+01, -4.6826469e+01,
+ 2.0122779e+01, -5.9699302e+00, -2.3230042e+01, 3.8784526e+01,
+ -5.3705628e+01, 6.2675409e+01, -4.5504385e+01, 3.5709340e+01,
+ -1.9387569e+01, 5.2553786e+00, 3.0873151e+01, -4.6681999e+01,
+ 5.1345152e+01, -5.3802726e+01, 3.5105259e+01, -3.7404776e+01,
+ 2.0074043e+01, 1.0637688e+01, -3.4769882e+01, 4.1709646e+01,
+ -5.1828676e+01, 4.2299294e+01, -4.3335588e+01, 3.5793638e+01,
+ 1.1265725e+00, -1.0395933e+01, 3.3544261e+01, -4.9299157e+01 ],
+
+ [ -4.4595314e+02, -1.0379970e+03, 3.1577388e+02, -3.5610417e+03,
+ 3.4581766e+03, 8.3381081e+03, -1.1696533e+03, 2.4101021e+03,
+ -6.5655829e+02, 1.4524982e+03, 1.9701386e+02, 1.1436715e+03,
+ 3.0871470e+02, 1.3134384e+03, -2.1221169e+02, 2.4285486e+02,
+ -1.3136018e+02, 2.0492262e+02, -5.7778142e+01, 2.0474887e+02,
+ 7.0763142e+01, 9.9953062e+01, 8.3698665e+01, 6.2817480e+01,
+ 7.7348745e+01, 4.8618716e+01, 1.9547983e+01, -7.2171464e+00,
+ -1.9159653e+01, -1.4038329e+01, -1.8628426e+01, -1.6163696e+01,
+ -1.4520857e+01, -4.8554891e+00, -5.7820395e-01, -3.7918076e+00,
+ 2.3294407e+00, 2.9495405e+00, 4.7407475e+00, 4.4409321e+00,
+ 1.5250457e+00, 2.7760466e+00, 1.9722269e+00, -2.1015209e+00,
+ -3.2710967e+00, -2.8401413e-03, -1.3044069e+00, -1.6457901e+00,
+ -1.6669278e+00, -2.3124530e-01, 2.3073051e+00, 8.9693576e-02,
+ -9.1429477e-01, 1.6390903e+00, 1.5921541e+00, 2.0781925e+00,
+ 5.6774613e-01, -1.4873030e+00, 9.0090862e-01, -1.7392411e-01,
+ -2.0619629e+00, -2.6804981e+00, 1.5808344e+00, -1.9739969e+00,
+ -3.2934549e+00, 8.3984861e-01, 1.6902572e+00, 1.1574818e+00,
+ 1.5309696e+00, -4.5293583e-01, 6.7334155e-01, -1.0828159e+00,
+ 2.8647595e+00, -1.0355011e+00, 1.2478700e+00, -1.0934505e+00,
+ -2.6607804e+00, 6.5988107e-01, 5.0203258e-01, -9.3129652e-01,
+ -1.6993602e+00, 3.3832184e+00, -1.1600967e-01, -2.6664726e-01,
+ -1.2900776e+00, 4.8121635e-01, 5.7458524e-01, -1.3748852e-02,
+ -1.0422755e+00, 9.6404835e-01, -6.5515813e-01, -1.2033320e+00,
+ 1.2628304e+00, -1.5881764e+00, -1.2024205e+00, -1.5188743e-01,
+ 2.1530142e-01, -1.1518121e+00, 1.5159517e+00, 7.6772612e-01,
+ 3.4785413e-01, 1.4223757e+00, 1.6791664e+00, 1.6342604e-03,
+ -9.7881678e-01, -1.0907888e+00, -1.1879306e+00, 1.1798907e+00,
+ -9.0898948e-02, -1.9025707e-01, 1.4674577e+00, 9.8643104e-01,
+ -3.5040854e+00, -8.8416089e-01, 1.4586672e+00, 2.8440488e+00,
+ 2.5053395e+00, -1.5126041e+00, -3.8048891e-02, 5.8273982e-02,
+ -1.6839084e+00, 8.3919618e-01, 8.4288521e-01, 8.2299662e-01,
+ -4.3286655e+00, -8.2387031e-01, 3.8407497e-01, 8.0932325e-01,
+ 4.2209188e-01, -1.6088979e-01, 1.1786569e+00, -1.5473109e-01,
+ -9.7397503e-01, -1.5447399e-01, 1.2455806e+00, 1.1521613e+00,
+ -1.1394046e+00, -2.4879158e+00, -1.1733733e+00, 1.0462318e+00,
+ -1.2964334e+00, 2.4531392e-01, 1.9106251e-01, -4.3741350e-01,
+ 5.7814855e-02, 7.3157372e-01, -7.7503310e-01, 5.5390581e-01,
+ -1.3940056e+00, -5.7191178e-01, 1.8789088e+00, -5.6670606e-01,
+ -4.8435902e-01, -1.8372728e+00, -9.7604008e-01, 1.0244293e+00,
+ 5.7039949e-01, -1.0034018e+00, -8.3178864e-02, 7.5770740e-02 ]
+
+])
+
+X_F_7M5 = np.array([
+
+ [ -1.3344626e+03, 1.4958812e+03, -5.5694903e+03, -1.0486529e+04,
+ 5.6650034e+02, 6.0141573e+03, -5.3094551e+02, 2.6475111e+02,
+ 1.6690199e+03, -2.0838083e+03, -5.7181477e+02, 3.0979708e+02,
+ -2.1393724e+02, 1.2521746e+02, 3.2684730e+02, -1.7994574e+02,
+ -2.0020361e+02, 8.6111917e+00, -2.4832990e+02, 1.7213677e+02,
+ 1.4131656e+00, -8.5287997e+01, 1.7851510e+02, -2.3922723e+02,
+ 9.9313025e+01, 8.9492487e+01, -2.1678225e+02, 2.8445423e+02,
+ -1.0586008e+02, -1.7011189e+02, 2.0924470e+02, -4.3658588e+01,
+ -5.3305585e+01, 9.5065494e+01, -2.4959448e+01, -1.9882483e+01,
+ 6.3950343e+01, -1.8254423e+02, 1.4871147e+02, -2.9924201e+01,
+ -3.8358507e+01, 1.3662271e+02, -9.1506608e+01, -3.6536786e+01,
+ 6.1379812e+01, -1.2146687e+02, 7.5261109e+01, 6.3261448e+01,
+ -7.4977224e+01, 9.6981001e+01, -5.2501206e+01, -8.8542526e+01,
+ 8.7236325e+01, -7.1242762e+01, 3.4918529e+01, 1.0382986e+02,
+ -9.4414359e+01, 4.3111460e+01, -6.8550987e+00, -1.1139641e+02,
+ 6.8058914e+01, -6.1872729e+00, -2.3074735e+01, 1.0246797e+02,
+ -5.7063670e+01, -1.0528237e+01, 3.4668643e+01, -9.7928146e+01,
+ 5.4841513e+01, 3.8537271e+01, -4.1668071e+01, 9.3225595e+01,
+ -3.6482817e+01, -5.6719701e+01, 4.9322737e+01, -7.0376756e+01,
+ 2.4449679e+01, 7.1939467e+01, -5.4394295e+01, 5.0564463e+01,
+ -1.2276169e+01, -8.5637045e+01, 5.2333982e+01, -2.5308579e+01,
+ -5.5784300e+00, 8.7058263e+01, -5.1715921e+01, -7.2178424e-01,
+ 1.4946171e+01, -8.5511725e+01, 4.3784053e+01, 1.9685956e+01,
+ -2.5023328e+01, 8.0537198e+01, -3.0868111e+01, -3.4548956e+01,
+ 3.4272902e+01, -7.1390131e+01, 1.8631772e+01, 5.2295899e+01,
+ -3.9080597e+01, 5.2223213e+01, -9.1791474e+00, -6.4321817e+01,
+ 3.7530035e+01, -3.6279190e+01, 1.3252369e+00, 7.2448665e+01,
+ -3.9490622e+01, 1.4609831e+01, 9.3290814e+00, -7.2230799e+01,
+ 3.7265287e+01, 3.1414748e+00, -1.8859243e+01, 7.1138748e+01,
+ -3.1848909e+01, -2.1851571e+01, 2.6573367e+01, -6.9966757e+01 ],
+
+ [ 6.6940015e+01, -3.8686730e+02, 1.2805107e+03, -7.2628992e+03,
+ -1.5754672e+03, -6.2436979e+02, 8.2787173e+02, -8.0959099e+02,
+ -3.4245127e+02, -3.5548999e+01, -7.4832843e+01, 9.1419785e+01,
+ 5.1342258e+01, 5.3971888e+01, -2.7664071e+01, 4.6162382e+01,
+ -1.0556418e+01, 6.7202580e+01, -1.7808740e+01, -6.8463927e+00,
+ -1.7273295e+01, 1.1657273e+00, -3.0473621e+00, 7.6704533e+00,
+ 3.2019440e+00, -4.9821490e+00, 9.7767521e+00, -5.6595863e+00,
+ -2.2488613e+00, -2.3116498e+00, 3.6060424e+00, -1.0509700e+01,
+ 1.0880662e+01, 1.3223251e+00, 3.8299992e+00, -3.2105583e+00,
+ -1.3455890e+00, -1.3800967e+00, 3.9392807e+00, -5.9971359e+00,
+ 3.0005141e+00, 3.1693816e+00, -2.4580934e+00, 7.4517245e-01,
+ -2.5522465e+00, -1.7665735e+00, 6.2439566e+00, -2.5566772e+00,
+ 1.0487489e+00, 4.9010207e+00, -2.4551119e+00, -2.3895763e+00,
+ -1.5405507e+00, 1.9495530e+00, 3.6880545e+00, 5.9918442e-01,
+ -2.4705668e+00, 4.8115098e+00, -4.1881444e+00, -3.6102608e+00,
+ -5.5087057e-01, -2.6206962e+00, 3.9639713e+00, -7.7640910e-01,
+ -3.9510665e+00, 4.4026144e+00, -3.2255765e+00, -1.5538782e+00,
+ -3.1853054e-01, 1.6928250e+00, 8.0901945e-01, 9.8517710e-01,
+ -3.9968911e+00, 5.2957448e-01, 7.5228614e-01, -5.5755012e+00,
+ 4.1839400e+00, -8.6149818e-01, 2.4716293e+00, -3.9843760e-01,
+ -1.6905671e+00, -8.5829267e-01, 1.9447429e+00, -3.4134235e-01,
+ 7.0851852e-02, 5.1275041e+00, -1.0122600e+00, 1.4475050e-01,
+ -3.3223224e+00, -1.0374444e+00, 3.7779787e+00, -4.5459512e+00,
+ 4.0726493e+00, -2.5433866e-01, 2.0525115e+00, -3.0465923e+00,
+ -1.7020097e+00, -1.0852672e+00, 2.3054607e+00, -5.4698297e-01,
+ 1.0938816e+00, 9.5295631e-01, 1.8110373e-01, -2.4274422e+00,
+ -9.0034207e-01, 3.4598368e-01, 3.0697391e+00, -3.3366935e-03,
+ -3.4637690e-02, 2.0742294e+00, -2.0643727e+00, -2.3004709e+00,
+ 3.4207323e-01, -1.8133178e+00, 5.0366054e+00, -8.8976033e-01,
+ -7.4204267e-01, 1.6508374e+00, -1.2431019e+00, -1.1825352e+00 ]
+
+])
+
+X_F = [ X_F_7M5, X_F_10M ]
+
+RC_ORDER_10M = np.array([ [ 6, 0 ], [ 6, 0 ] ])
+RC_ORDER_7M5 = np.array([ [ 8, 0 ], [ 8, 0 ] ])
+RC_ORDER = [ RC_ORDER_7M5, RC_ORDER_10M ]
+
+RC_I_1_10M = np.array([ [ 13, 9, 4, 9, 8, 9, 8, 8 ],
+ [ 4, 7, 9, 9, 9, 9, 8, 8 ] ])
+
+RC_I_1_7M5 = np.array([ [ 12, 13, 6, 9, 7, 9, 7, 9 ],
+ [ 5, 13, 8, 10, 9, 9, 7, 9 ] ])
+
+RC_I_1 = [ RC_I_1_7M5, RC_I_1_10M ]
+
+RC_I_2_10M = np.array([ [ 8, 8, 8, 8, 8, 8, 8, 8 ],
+ [ 8, 8, 8, 8, 8, 8, 8, 8 ] ])
+
+RC_I_2_7M5 = np.array([ [ 8, 8, 8, 8, 8, 8, 8, 8 ],
+ [ 8, 8, 8, 8, 8, 8, 8, 8 ] ])
+
+RC_I_2 = [ RC_I_2_7M5, RC_I_2_10M ]
+
+RC_Q_1_10M = np.array([
+
+ [ 7.9801723e-01, 1.8374952e-01, -6.7369564e-01, 1.8374952e-01,
+ 0.0000000e+00, 1.8374952e-01, 0.0000000e+00, 0.0000000e+00 ],
+
+ [ -6.7369564e-01, -1.8374952e-01, 1.8374952e-01, 1.8374952e-01,
+ 1.8374952e-01, 1.8374952e-01, 0.0000000e+00, 0.0000000e+00 ]
+
+])
+
+RC_Q_1_7M5 = np.array([
+
+ [ 6.7369564e-01, 7.9801723e-01, -3.6124167e-01, 1.8374952e-01,
+ -1.8374952e-01, 1.8374952e-01, -1.8374952e-01, 1.8374952e-01 ],
+
+ [ -5.2643216e-01, 7.9801723e-01, 0.0000000e+00, 3.6124167e-01,
+ 1.8374952e-01, 1.8374952e-01, -1.8374952e-01, 1.8374952e-01 ]
+
+])
+
+RC_Q_1 = [ RC_Q_1_7M5, RC_Q_1_10M ]
+
+RC_Q_2_10M = np.array([
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ],
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ]
+
+])
+
+RC_Q_2_7M5 = np.array([
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ],
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00 ]
+
+])
+
+RC_Q_2 = [ RC_Q_2_7M5, RC_Q_2_10M ]
+
+NUM_TNS_FILTERS_10M = [ 1, 1 ]
+NUM_TNS_FILTERS_7M5 = [ 1, 1 ]
+NUM_TNS_FILTERS = [ NUM_TNS_FILTERS_7M5, NUM_TNS_FILTERS_10M ]
+
+TNS_LEV_A_10M = np.array([
+
+ [ 1.0000000e+00, 7.2228594e-01, -5.9139666e-01, -5.8613895e-01,
+ 1.1856746e-01, 2.9269254e-02, 8.0280074e-02, 3.8446982e-02,
+ 4.3781506e-02 ],
+
+ [ 1.0000000e+00, -5.6089086e-01, -2.3332924e-01, 1.3258672e-01,
+ -7.2233128e-02, 1.1753190e-01, 1.9802609e-01, -6.1275417e-02,
+ 2.2455104e-02 ]
+
+])
+
+TNS_LEV_A_7M5 = np.array([
+
+ [ 1.0000000e+00, 5.2890099e-01, 5.4205760e-01, -4.4859180e-01,
+ 3.5954391e-01, -1.9179061e-01, 1.8237136e-01, -1.1968822e-01,
+ 1.6649226e-01 ],
+
+ [ 1.0000000e+00, -9.0587790e-01, 9.8849245e-01, -1.4294859e-01,
+ 2.5680120e-01, -5.8559598e-03, 3.0914531e-01, -2.2365546e-01,
+ 1.0115038e-01 ]
+
+])
+
+TNS_LEV_A = [ TNS_LEV_A_7M5, TNS_LEV_A_10M ]
+
+TNS_LEV_E_10M = [ 0.412635, 1.396833 ]
+TNS_LEV_E_7M5 = [ 0.397854, 0.665554 ]
+TNS_LEV_E = [ TNS_LEV_E_7M5, TNS_LEV_E_10M ]
+
+TNS_LEV_RC_10M = np.array([
+
+ [ 8.3775274e-01, 1.7149527e-01, -7.0757376e-01, 1.9028627e-01,
+ -1.4202392e-02, 1.0144450e-01, 6.8373224e-03, 4.3781506e-02 ],
+
+ [ -6.7692801e-01, -9.9895702e-02, 2.2652538e-01, 1.0193040e-01,
+ 2.0702019e-01, 1.7652182e-01, -4.8705113e-02, 2.2455104e-02 ]
+
+])
+
+TNS_LEV_RC_7M5 = np.array([
+
+ [ 6.0637394e-01, 8.3208082e-01, -4.0823140e-01, 2.1979501e-01,
+ -1.5450397e-01, 2.2566273e-01, -2.1366897e-01, 1.6649226e-01 ],
+
+ [ -5.4911119e-01, 7.7810682e-01, -2.2286927e-03, 3.4649135e-01,
+ 2.2484419e-01, 9.3957220e-02, -1.3339034e-01, 1.0115038e-01 ]
+
+])
+
+TNS_LEV_RC = [ TNS_LEV_RC_7M5, TNS_LEV_RC_10M ]
+
+NBITS_TNS_10M = np.array([ 24, 18 ])
+NBITS_TNS_7M5 = np.array([ 24, 24 ])
+NBITS_TNS = [ NBITS_TNS_7M5, NBITS_TNS_10M ]
+
+
+### C.3.1.15 Global gain estimation
+
+GG_OFF_10M = np.array([ -131, -131 ])
+GG_OFF_7M5 = np.array([ -127, -127 ])
+GG_OFF = [ GG_OFF_7M5, GG_OFF_10M ]
+
+GG_IND_10M = np.array([ 191, 166 ])
+GG_IND_7M5 = np.array([ 189, 162 ])
+GG_IND = [ GG_IND_7M5, GG_IND_10M ]
+
+GG_MIN_10M = np.array([ 121, 115 ])
+GG_MIN_7M5 = np.array([ 114, 109 ])
+GG_MIN = [ GG_MIN_7M5, GG_MIN_10M ]
+
+GG_10M = np.array([ 138.949549, 17.782794 ])
+GG_7M5 = np.array([ 163.789371, 17.782794 ])
+GG = [ GG_7M5, GG_10M ]
+
+NBITS_OFFSET_10M = np.array([ 0.000000, -1.200000 ])
+NBITS_OFFSET_7M5 = np.array([ 0.000000, -1.600000 ])
+NBITS_OFFSET = [ NBITS_OFFSET_7M5, NBITS_OFFSET_10M ]
+
+
+### C.3.1.16 Quantization
+
+X_Q_10M = np.array([
+
+ [ 0, 18, -15, 48, -53, -97, -1, -13, -13, 1,
+ -23, 7, -23, -10, 1, -2, 1, -3, 0, -2,
+ 1, -2, 1, -1, 1, -1, 0, 1, -1, 0,
+ -1, 0, 0, 0, 1, -1, 1, -1, 0, 0,
+ 0, 0, -1, 1, -1, 1, 0, 0, 0, 0,
+ 0, -1, 1, -1, 0, 0, 0, 0, -1, 0,
+ 0, 1, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+ [ -25, -58, 18, -200, 194, 469, -66, 135, -37, 82,
+ 11, 64, 17, 74, -12, 14, -7, 11, -3, 11,
+ 4, 5, 5, 3, 4, 3, 1, 0, -1, -1,
+ -1, -1, -1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+
+])
+
+X_Q_7M5 = np.array([
+
+ [ -8, 9, -34, -64, 3, 37, -3, 1, 10, -13,
+ -3, 2, -1, 1, 2, -1, -1, 0, -1, 1,
+ 0, 0, 1, -1, 0, 0, -1, 2, -1, -1,
+ 1, 0, 0, 0, 0, 0, 0, -1, 1, 0,
+ 0, 1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, -1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+ [ 4, -22, 72, -408, -88, -35, 46, -45, -19, -2,
+ -4, 5, 3, 3, -1, 2, 0, 4, -1, 0,
+ -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+
+])
+
+X_Q = [ X_Q_7M5, X_Q_10M ]
+
+LASTNZ_10M = np.array([ 108, 34 ])
+LASTNZ_7M5 = np.array([ 64, 22 ])
+LASTNZ = [ LASTNZ_7M5, LASTNZ_10M ]
+
+NBITS_EST_10M = np.array([ 231, 250 ])
+NBITS_EST_7M5 = np.array([ 164, 140 ])
+NBITS_EST = [ NBITS_EST_7M5, NBITS_EST_10M ]
+
+LSB_MODE_10M = np.array([ 0, 0 ])
+LSB_MODE_7M5 = np.array([ 0, 0 ])
+LSB_MODE = [ LSB_MODE_7M5, LSB_MODE_10M ]
+
+NBITS_SPEC_10M = np.array([ 225, 231 ])
+NBITS_SPEC_7M5 = np.array([ 156, 146 ])
+NBITS_SPEC = [ NBITS_SPEC_7M5, NBITS_SPEC_10M ]
+
+
+### C.3.1.17 Global Gain adjustement
+
+GG_IND_ADJ_10M = np.array([ 192, 168 ])
+GG_IND_ADJ_7M5 = np.array([ 190, 162 ])
+GG_IND_ADJ = [ GG_IND_ADJ_7M5, GG_IND_ADJ_10M ]
+
+GG_ADJ_10M = np.array([ 1.508591e+02, 2.096180e+01 ])
+GG_ADJ_7M5 = np.array([ 1.778279e+02, 1.778279e+01 ])
+GG_ADJ = [ GG_ADJ_7M5, GG_ADJ_10M ]
+
+
+### C.3.1.18 Requantization
+
+X_Q_REQ_10M = np.array([
+
+ [ 0, 17, -14, 44, -49, -89, -1, -12, -12, 0,
+ -21, 7, -21, -10, 1, -2, 1, -3, 0, -2,
+ 1, -2, 1, -1, 1, -1, 0, 1, -1, 0,
+ -1, 0, 0, 0, 1, -1, 1, -1, 0, 0,
+ 0, 0, -1, 1, -1, 1, 0, 0, 0, 0,
+ 0, -1, 1, -1, 0, 0, 0, 0, -1, 0,
+ 0, 0, 0, 0, 0, 0, 0, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+ [ -21, -49, 15, -170, 165, 398, -56, 115, -31, 69,
+ 9, 54, 15, 63, -10, 11, -6, 10, -3, 10,
+ 3, 5, 4, 3, 4, 2, 1, 0, -1, -1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+
+])
+
+X_Q_REQ_7M5 = np.array([
+
+ [ -7, 8, -31, -59, 3, 34, -3, 1, 9, -12,
+ -3, 2, -1, 1, 2, -1, -1, 0, -1, 1,
+ 0, 0, 1, -1, 0, 0, -1, 1, 0, -1,
+ 1, 0, 0, 0, 0, 0, 0, -1, 1, 0,
+ 0, 1, 0, 0, 0, -1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+])
+
+X_Q_REQ = [ X_Q_REQ_7M5, X_Q_REQ_10M ]
+
+LASTNZ_REQ_10M = np.array([ 68, 30 ])
+LASTNZ_REQ_7M5 = np.array([ 60, None ])
+LASTNZ_REQ = [ LASTNZ_REQ_7M5, LASTNZ_REQ_10M ]
+
+NBITS_EST_REQ_10M = np.array([ 206, 237 ])
+NBITS_EST_REQ_7M5 = np.array([ 147, None ])
+NBITS_EST_REQ = [ NBITS_EST_REQ_7M5, NBITS_EST_REQ_10M ]
+
+NBITS_TRUNC_REQ_10M = np.array([ 206, 229 ])
+NBITS_TRUNC_REQ_7M5 = np.array([ 147, None ])
+NBITS_TRUNC_REQ = [ NBITS_TRUNC_REQ_7M5, NBITS_TRUNC_REQ_10M ]
+
+LSB_MODE_REQ_10M = np.array([ 0, 0 ])
+LSB_MODE_REQ_7M5 = np.array([ 0, None ])
+LSB_MODE_REQ = [ LSB_MODE_REQ_7M5, LSB_MODE_REQ_10M ]
+
+
+### C.3.1.19 Residual Coding
+
+RES_BITS_10M = np.array([
+ [ 0, 1 ,1 ,0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0,
+ 0, 1, 1, 1, 1, 1, 0 ],
+ [ 0, 0, 1, 1, 0, 0 ]
+], dtype=object)
+
+RES_BITS_7M5 = np.array([
+ [ 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0 ],
+ [ 0, 1, 1, 0, 0, 0, 1, 0, 0, 1 ]
+], dtype=object)
+
+RES_BITS = [ RES_BITS_7M5, RES_BITS_10M ]
+
+
+### C.3.1.20 Noise factor
+
+F_NF_10M = np.array([ 3, 7 ])
+F_NF_7M5 = np.array([ 4, 6 ])
+F_NF = [ F_NF_7M5, F_NF_10M ]
+
+
+### C.3.1.21 Side information encoding
+
+BYTES_SIDE_10M = [
+
+ bytearray([
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x19, 0x30, 0xc3, 0x8d, 0xf1, 0x88, 0xcf, 0x80, 0x43 ]),
+
+ bytearray([
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x39, 0x30, 0xc5, 0xf7, 0x6b, 0x89, 0xcf, 0x50, 0x1d ])
+
+]
+
+BYTES_SIDE_7M5 = [
+
+ bytearray([
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x07, 0xd3, 0x48, 0x84, 0x45, 0xbe, 0x3b ]),
+
+ bytearray([
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x18, 0x90, 0x6c, 0x0f, 0x6b, 0x8c, 0xc7, 0xa2, 0x15 ])
+
+]
+
+BYTES_SIDE = [ BYTES_SIDE_7M5, BYTES_SIDE_10M ]
+
+
+### C.3.1.22 Arithmetic encoding
+
+BYTES_AC_10M = [
+
+ bytearray([
+ 0xa7, 0x1c, 0x2a, 0x35, 0xaf, 0x69, 0x0e, 0xf9, 0xbe, 0xf1,
+ 0xcb, 0x2e, 0x87, 0x5f, 0x05, 0x13, 0xd7, 0x8e, 0x3c, 0xf2,
+ 0xcd, 0xd5, 0xad, 0x56, 0xb6, 0x5e, 0xe1, 0x8f, 0xc1, 0xbe,
+ 0x80, 0x99, 0x30, 0xc3, 0x8d, 0xf1, 0x88, 0xcf, 0x80, 0x43 ]),
+
+ bytearray([
+ 0x7e, 0x55, 0xff, 0x85, 0x35, 0x86, 0xf7, 0x01, 0xf8, 0x8c,
+ 0xaa, 0x1a, 0x1e, 0x42, 0x43, 0xd6, 0x26, 0x02, 0x37, 0x5c,
+ 0x78, 0xff, 0x1a, 0x55, 0xdd, 0xd2, 0x81, 0x2e, 0x68, 0xdd,
+ 0xc4, 0xf9, 0x30, 0xc5, 0xf7, 0x6b, 0x89, 0xcf, 0x50, 0x1d ])
+
+]
+
+BYTES_AC_7M5 = [
+
+ bytearray([
+ 0xfe, 0x86, 0xdb, 0xa2, 0x90, 0x78, 0x54, 0xb1, 0x5d, 0x1b,
+ 0x1f, 0x3b, 0x24, 0x62, 0xaf, 0xb5, 0x95, 0x9c, 0xb0, 0xa0,
+ 0x6f, 0xbe, 0xac, 0x07, 0xd3, 0x48, 0x84, 0x45, 0xbe, 0x3b ]),
+
+ bytearray([
+ 0xda, 0x52, 0x63, 0x57, 0xf8, 0x66, 0x37, 0xcf, 0x85, 0xe1,
+ 0xd4, 0x32, 0x46, 0xc2, 0x36, 0x6d, 0xed, 0xa9, 0x52, 0x58,
+ 0x17, 0x18, 0x90, 0x6c, 0x0f, 0x6b, 0x8c, 0xc7, 0xa2, 0x15 ])
+
+]
+
+BYTES_AC = [ BYTES_AC_7M5, BYTES_AC_10M ]
+
+
+### C.3.1.23 Attack detector intermediate data
+
+NBYTES_ATT = (88e3 * np.array([ 7.5e-3, 10e-3 ]) / 8).astype(int)
+
+X_PCM_ATT_10M = np.array([
+
+ [ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 27852, 29491, 27852, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+ [ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 ]
+
+])
+
+X_PCM_ATT_7M5 = np.array([
+
+ [ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 27852, 29491, 27852, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+ [ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 ],
+
+])
+
+X_PCM_ATT = [ X_PCM_ATT_7M5, X_PCM_ATT_10M ]
+
+F_ATT_7M5 = np.array([ 1, 1 ])
+F_ATT_10M = np.array([ 1, 1 ])
+F_ATT = [ F_ATT_7M5, F_ATT_10M ]
+
+
+### C.4.1.1-4 Spectrum Decoding
+
+X_HAT_Q_10M = np.array([
+
+ [ 0.0000, 16.8125, -13.8125, 44.3125, -49.3125, -89.3125,
+ -0.8125, -11.8125, -12.3125, 0.0000, -20.8125, 6.8125,
+ -21.3125, -9.8125, 1.3125, -1.8125, 1.3125, -3.3125,
+ 0.0000, -2.3125, 1.3125, -1.8125, 1.3125, -0.8125,
+ 1.0000, -1.0000, 0.0000, 1.0000, -1.0000, 0.0000,
+ -1.0000, 0.0000, 0.0000, 0.0000, 1.0000, -1.0000,
+ 1.0000, -1.0000, 0.0000, 0.0000, 0.0000, 0.0000,
+ -1.0000, 1.0000, -1.0000, 1.0000, 0.0000, 0.0000,
+ 0.0000, 0.0000, 0.0000, -1.0000, 1.0000, -1.0000,
+ 0.0000, 0.0000, 0.0000, 0.0000, -1.0000, 0.0000,
+ 0.0000, 0.0000, -0.3125, -0.3125, 0.0000, 0.0000,
+ 0.0000, -1.0000, 0.0000, 0.0000, 0.0000, 0.3125,
+ -0.3125, -0.3125, -0.3125, -0.3125, 0.3125, -0.3125,
+ -0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125,
+ -0.3125, 0.3125, 0.3125, 0.3125, 0.3125, 0.3125,
+ 0.3125, 0.3125, 0.3125, -0.3125, -0.3125, -0.3125,
+ -0.3125, -0.3125, -0.3125, -0.3125, -0.3125, -0.3125,
+ 0.3125, -0.3125, -0.3125, 0.3125, -0.3125, -0.3125,
+ -0.3125, -0.3125, -0.3125, -0.3125, 0.3125, 0.3125,
+ -0.3125, 0.3125, 0.3125, 0.3125, -0.3125, 0.3125,
+ 0.3125, -0.3125, 0.3125, -0.3125, 0.3125, 0.3125,
+ -0.3125, 0.3125, 0.3125, 0.3125, -0.3125, -0.3125,
+ 0.3125, -0.3125, 0.3125, 0.3125, -0.3125, -0.3125,
+ -0.3125, -0.3125, 0.3125, 0.3125, 0.3125, -0.3125,
+ -0.3125, 0.3125, 0.3125, 0.3125, -0.3125, -0.3125,
+ 0.3125, 0.3125, -0.3125, -0.3125, -0.3125, -0.3125,
+ -0.3125, 0.3125, -0.3125, -0.3125 ],
+
+ [ -21.3125, -49.3125, 15.3125, -170.0000, 165.0000, 398.0000,
+ -56.0000, 115.0000, -31.0000, 69.0000, 9.0000, 54.0000,
+ 15.0000, 63.0000, -10.0000, 11.0000, -6.0000, 10.0000,
+ -3.0000, 10.0000, 3.0000, 5.0000, 4.0000, 3.0000,
+ 4.0000, 2.0000, 1.0000, 0.0000, -1.0000, -1.0000,
+ 0.0000, 0.0000, 0.0000, 0.0625, 0.0625, -0.0625,
+ -0.0625, -0.0625, 0.0625, 0.0625, -0.0625, 0.0625,
+ -0.0625, 0.0625, -0.0625, -0.0625, 0.0625, -0.0625,
+ -0.0625, -0.0625, 0.0625, 0.0625, 0.0625, -0.0625,
+ -0.0625, -0.0625, -0.0625, 0.0625, -0.0625, 0.0625,
+ -0.0625, 0.0625, 0.0625, 0.0625, 0.0625, -0.0625,
+ 0.0625, 0.0625, 0.0625, -0.0625, -0.0625, -0.0625,
+ -0.0625, 0.0625, -0.0625, 0.0625, 0.0625, -0.0625,
+ 0.0625, 0.0625, 0.0625, -0.0625, 0.0625, -0.0625,
+ -0.0625, 0.0625, -0.0625, -0.0625, -0.0625, -0.0625,
+ -0.0625, 0.0625, -0.0625, 0.0625, -0.0625, -0.0625,
+ -0.0625, -0.0625, 0.0625, 0.0625, -0.0625, 0.0625,
+ -0.0625, -0.0625, 0.0625, -0.0625, -0.0625, -0.0625,
+ 0.0625, 0.0625, -0.0625, -0.0625, 0.0625, -0.0625,
+ -0.0625, 0.0625, 0.0625, 0.0625, 0.0625, 0.0625,
+ -0.0625, -0.0625, -0.0625, 0.0625, -0.0625, 0.0625,
+ 0.0625, 0.0625, -0.0625, 0.0625, -0.0625, -0.0625,
+ -0.0625, 0.0625, -0.0625, -0.0625, -0.0625, 0.0625,
+ -0.0625, -0.0625, -0.0625, 0.0625, 0.0625, 0.0625,
+ -0.0625, -0.0625, 0.0625, -0.0625, 0.0625, 0.0625,
+ 0.0625, 0.0625, 0.0625, -0.0625, 0.0625, 0.0625,
+ 0.0625, -0.0625, 0.0625, 0.0625 ]
+
+])
+
+X_HAT_Q_7M5 = np.array([
+
+ [ -7.3125, 8.3125, -31.3125, -58.8125, 3.3125, 33.8125,
+ -2.8125, 1.3125, 9.3125, -11.8125, -3.0000, 2.0000,
+ -1.0000, 1.0000, 2.0000, -1.0000, -1.0000, 0.0000,
+ -1.0000, 1.0000, 0.0000, 0.0000, 1.0000, -1.0000,
+ 0.0000, 0.0000, -1.0000, 1.0000, 0.0000, -1.0000,
+ 1.0000, 0.0000, 0.0000, 0.2500, -0.2500, 0.0000,
+ 0.0000, -1.0000, 1.0000, 0.0000, 0.0000, 1.0000,
+ 0.0000, 0.0000, 0.0000, -1.0000, 0.0000, 0.0000,
+ -0.2500, 0.2500, 0.2500, 0.2500, -0.2500, 0.2500,
+ 0.2500, 0.2500, -0.2500, 0.0000, 0.0000, -1.0000,
+ 0.0000, 0.0000, 0.2500, 0.2500, -0.2500, -0.2500,
+ 0.2500, 0.2500, 0.2500, -0.2500, -0.2500, 0.2500,
+ -0.2500, 0.2500, -0.2500, 0.2500, -0.2500, -0.2500,
+ -0.2500, -0.2500, -0.2500, -0.2500, 0.2500, -0.2500,
+ 0.2500, 0.2500, -0.2500, -0.2500, 0.2500, -0.2500,
+ 0.2500, 0.2500, -0.2500, -0.2500, 0.2500, -0.2500,
+ 0.2500, -0.2500, 0.2500, 0.2500, 0.2500, 0.2500,
+ 0.2500, -0.2500, -0.2500, -0.2500, 0.2500, 0.2500,
+ 0.2500, 0.2500, 0.2500, -0.2500, -0.2500, -0.2500,
+ 0.2500, 0.2500, 0.2500, -0.2500, 0.2500, 0.2500 ],
+
+ [ 3.8125, -21.8125, 72.3125, -408.3125, -88.3125, -35.3125,
+ 46.3125, -45.0000, -19.0000, -2.0000, -4.0000, 5.0000,
+ 3.0000, 3.0000, -1.0000, 2.0000, 0.0000, 4.0000,
+ -1.0000, 0.0000, -1.0000, 0.0000, 0.0000, -0.1250,
+ -0.1250, 0.1250, -0.1250, -0.1250, 0.1250, -0.1250,
+ -0.1250, -0.1250, -0.1250, -0.1250, 0.1250, 0.1250,
+ -0.1250, -0.1250, 0.1250, -0.1250, 0.1250, -0.1250,
+ -0.1250, 0.1250, 0.1250, -0.1250, -0.1250, 0.1250,
+ -0.1250, -0.1250, -0.1250, 0.1250, -0.1250, 0.1250,
+ -0.1250, -0.1250, 0.1250, -0.1250, 0.1250, -0.1250,
+ -0.1250, 0.1250, -0.1250, -0.1250, -0.1250, -0.1250,
+ -0.1250, -0.1250, -0.1250, 0.1250, -0.1250, 0.1250,
+ 0.1250, 0.1250, -0.1250, -0.1250, -0.1250, -0.1250,
+ 0.1250, 0.1250, 0.1250, 0.1250, 0.1250, 0.1250,
+ -0.1250, -0.1250, -0.1250, 0.1250, 0.1250, -0.1250,
+ -0.1250, -0.1250, -0.1250, -0.1250, -0.1250, 0.1250,
+ 0.1250, -0.1250, 0.1250, 0.1250, 0.1250, -0.1250,
+ -0.1250, -0.1250, -0.1250, 0.1250, -0.1250, 0.1250,
+ -0.1250, -0.1250, -0.1250, -0.1250, 0.1250, 0.1250,
+ -0.1250, 0.1250, 0.1250, 0.1250, -0.1250, -0.1250 ]
+
+])
+
+X_HAT_Q = [ X_HAT_Q_7M5, X_HAT_Q_10M ]
+
+### C.4.1.6 TNS
+
+X_HAT_TNS_10M = np.array([
+
+ [ 0.0000000e+00, 2.5363181e+03, -2.0837409e+03, 6.6849426e+03,
+ -7.4392379e+03, -1.3473601e+04, -1.2257300e+02, -1.7820228e+03,
+ -1.8574523e+03, 0.0000000e+00, -3.1397544e+03, 1.0277274e+03,
+ -3.2151839e+03, 7.6090367e+02, -1.9466503e+03, -5.2445445e+02,
+ 3.3140414e+02, -1.8519794e+03, 1.7920998e+03, -2.1685321e+03,
+ 1.8597265e+03, -1.3374728e+03, 7.4531009e+02, 1.3315563e+02,
+ -6.0572955e+02, 1.0738661e+03, -1.2042433e+03, 1.2934874e+03,
+ -1.0948115e+03, 6.2875792e+02, -2.6176578e+02, -3.3286816e+02,
+ 6.3874781e+02, -9.2546646e+02, 1.0536075e+03, -1.0082162e+03,
+ 8.4609116e+02, -5.3643862e+02, 8.6016577e+01, 3.1548104e+02,
+ -6.4537299e+02, 7.8414243e+02, -9.2031551e+02, 8.4727748e+02,
+ -7.1936859e+02, 4.6589807e+02, -6.4881797e+01, -2.6457448e+02,
+ 5.6215195e+02, -6.6813432e+02, 6.6226333e+02, -6.5474860e+02,
+ 5.2409793e+02, -4.0142502e+02, 6.3505532e+01, 1.7235901e+02,
+ -4.1924611e+02, 5.0550392e+02, -6.5734435e+02, 5.0345309e+02,
+ -3.6608788e+02, 8.0016434e+01, 9.3237184e+01, -3.5017721e+02,
+ 4.2795992e+02, -4.6886670e+02, 3.7402812e+02, -3.7888490e+02,
+ 1.5291801e+02, -1.5802320e+01, -1.9719846e+02, 3.4187888e+02,
+ -4.2748515e+02, 3.5181826e+02, -3.0466662e+02, 7.6284275e+01,
+ 8.7663093e+01, -2.9659233e+02, 3.1030268e+02, -2.9594060e+02,
+ 2.6439080e+02, -9.3629481e+01, 5.7399177e+01, 1.6375927e+02,
+ -2.3208956e+02, 3.5517121e+02, -2.5708880e+02, 2.5690950e+02,
+ -5.2915469e+01, 2.3237996e+01, 1.8246977e+02, -1.5537990e+02,
+ 2.8029628e+02, -2.5001493e+02, 1.6287623e+02, -1.2710806e+02,
+ -6.9041960e+01, 5.1949460e+01, -2.3006446e+02, 1.3249613e+02,
+ -2.3061667e+02, 6.5507752e+01, -6.6442896e+00, -1.4373816e+02,
+ 1.3523410e+02, -1.2379774e+02, 5.2635973e+01, -6.1214557e+01,
+ -4.6571211e+01, 6.8132465e+00, -1.2664460e+02, 3.6959535e+01,
+ -3.5846511e+01, 2.8934234e+01, -4.3948154e+01, 8.1935863e+01,
+ 7.4660900e+00, 5.1207805e+01, -2.1748068e+01, 8.5958555e+01,
+ 4.9435547e+00, -4.1272410e+01, 1.2552229e+02, -1.6625839e+02,
+ 1.9307762e+02, -1.0613596e+02, 1.4547859e+01, 1.0890433e+02,
+ -1.0539493e+02, 1.9916467e+02, -1.9460994e+02, 1.3162563e+02,
+ -2.6679242e+01, -1.0641065e+02, 1.9984677e+02, -1.8499813e+02,
+ 1.3746427e+02, -1.2384807e+02, -4.8113073e+00, -1.1154394e+01,
+ -4.8901484e+01, 9.9602073e+01, -6.2727442e+01, 4.0646873e+01,
+ -3.8839607e+01, 5.5618701e+01, 1.5609019e+01, 2.6413984e+01,
+ -1.3661998e+01, -2.1935131e+01, 7.0604596e+01, -3.6013874e+01,
+ -5.2534512e+00, -1.9095831e+01, -5.9462211e+01, -2.0474437e+01,
+ -8.2457334e+01, 6.6458037e+01, -1.3905842e+02, 4.4992015e+01 ],
+
+ [ -4.4674836e+02, -1.0336788e+03, 3.2097756e+02, -3.5635060e+03,
+ 3.4586970e+03, 8.3427964e+03, -1.1738608e+03, 2.4106070e+03,
+ -6.4981580e+02, 1.4463642e+03, 1.8865620e+02, 1.1319372e+03,
+ 3.1442700e+02, 1.4722656e+03, 5.9737149e+02, 9.6658866e+02,
+ 4.9169825e+02, 6.7177464e+02, 1.9327293e+02, 1.5499589e+02,
+ -2.1600722e+01, -9.8228391e+01, -1.2744379e+02, -1.7269979e+02,
+ -8.5793205e+01, -7.4701778e+01, -2.2833266e+01, 8.7668786e-01,
+ 1.4493209e+01, 2.7797597e+01, 4.0794920e+01, 4.3722928e+01,
+ 3.6950947e+01, 2.9794074e+01, 2.0218141e+01, 7.2233914e+00,
+ -4.3603335e+00, -1.3552659e+01, -1.6604838e+01, -1.8237845e+01,
+ -1.9241801e+01, -1.3923796e+01, -1.1242668e+01, -3.6760056e+00,
+ -1.1829705e+00, 2.5681718e+00, 7.2841081e+00, 6.6584846e+00,
+ 6.5203815e+00, 4.4803237e+00, 5.1830531e+00, 3.8023813e+00,
+ 2.5801707e+00, -8.9194181e-01, -2.7289508e+00, -4.3183797e+00,
+ -5.5686696e+00, -3.5658387e+00, -5.0013288e+00, -1.5969716e+00,
+ -2.5434186e+00, 1.0495670e+00, 2.5178803e+00, 4.0287891e+00,
+ 5.1309495e+00, 2.8569829e+00, 4.5137803e+00, 3.7678816e+00,
+ 3.5274736e+00, 2.1055313e-01, -1.4896329e+00, -3.0388583e+00,
+ -4.4849681e+00, -2.7741285e+00, -4.6088456e+00, -1.5252078e+00,
+ -1.4816216e-01, -7.4985193e-01, 2.1073955e+00, 3.0534784e+00,
+ 4.4307001e+00, 2.0418555e+00, 3.6512371e+00, 8.8259920e-01,
+ -5.5756792e-01, 2.4731249e-01, -2.4585823e+00, -3.1307473e+00,
+ -4.3178686e+00, -4.4328370e+00, -4.5859669e+00, -1.9461803e+00,
+ -2.7535202e+00, 5.2435412e-01, -5.7680820e-01, -1.1178729e-01,
+ -4.7067976e-01, -9.7145273e-01, 1.1713253e+00, 1.5417023e+00,
+ -6.2164141e-02, 1.8196547e+00, -3.3253562e-01, -8.7085257e-01,
+ 4.0545492e-01, -1.6971448e+00, -2.1315433e+00, -3.1522747e+00,
+ -7.0840626e-01, 1.9820684e-01, -1.2521487e+00, -1.2659519e+00,
+ 9.9900232e-01, -5.5880815e-01, -1.1085204e+00, 6.9059170e-01,
+ 1.6309021e+00, 2.4853740e+00, 2.8911996e+00, 3.6269550e+00,
+ 1.3909661e+00, 9.7770819e-02, -1.4853328e+00, -1.9863830e-01,
+ -2.7510985e+00, -8.4492066e-01, -1.7063127e-01, 1.1338053e+00,
+ -4.4636302e-01, 1.7476214e+00, -3.9440033e-02, -6.3944530e-01,
+ -1.7198507e+00, 7.4867347e-02, -1.8649133e+00, -2.4597157e+00,
+ -2.9678215e+00, -5.7798031e-01, -2.1073509e+00, -2.2439980e+00,
+ -2.4007588e+00, 2.2681540e-01, 1.3649713e+00, 2.4256778e+00,
+ 9.1907814e-01, 4.7699713e-01, 2.1704836e+00, -3.5175645e-01,
+ 1.3125148e+00, 1.2589840e+00, 2.0656111e+00, 2.3990940e+00,
+ 2.6834440e+00, 6.0589675e-01, 1.9858819e+00, 1.9373749e+00,
+ 2.1901227e+00, -3.8495770e-01, 1.1720109e+00, 1.3860966e+00 ]
+
+])
+
+X_HAT_TNS_7M5 = np.array([
+
+ [ -1.3003668e+03, 1.4781948e+03, -5.5682374e+03, -1.0458506e+04,
+ 5.8905505e+02, 6.0128073e+03, -5.0014108e+02, 2.3339917e+02,
+ 1.6560227e+03, -2.1005926e+03, 9.8231590e+02, 6.5472037e+02,
+ -1.8816616e+03, 1.9995050e+03, -5.2483056e+02, -1.1296152e+03,
+ 1.8917056e+03, -1.4074840e+03, 7.3771850e+01, 1.1607281e+03,
+ -1.4654795e+03, 9.0328961e+02, 1.8790564e+02, -1.0278688e+03,
+ 1.0629204e+03, -5.3634594e+02, -3.2451913e+02, 9.0207993e+02,
+ -8.0267777e+02, 1.2277267e+02, 5.5484886e+02, -6.8584739e+02,
+ 4.1901310e+02, 7.2779950e+01, -4.3460765e+02, 4.5133152e+02,
+ -2.1578787e+02, -2.4628376e+02, 5.3756691e+02, -3.8146878e+02,
+ 3.4097661e+01, 4.5169871e+02, -5.0575362e+02, 2.7278971e+02,
+ 9.4493294e+01, -5.2727129e+02, 4.9704432e+02, -2.0290693e+02,
+ -2.1943755e+02, 4.6316564e+02, -3.5988557e+02, 1.5354987e+02,
+ 8.8971222e+01, -2.1177185e+02, 2.9338708e+02, -1.6015893e+02,
+ -3.0076244e+01, 1.4282354e+02, -1.8203323e+02, -3.8237583e+01,
+ 8.0989223e+01, -6.7911301e+01, 4.5876843e+01, 5.8160967e+01,
+ -1.2140603e+02, 3.0523591e+01, 1.0177828e+02, -7.1769925e+01,
+ 6.9697281e+01, -4.4342614e+01, -7.7392269e+01, 1.5965917e+02,
+ -1.5467801e+02, 8.0965471e+01, 5.9745822e+00, -7.8890418e+01,
+ 9.3802490e+01, -1.3176806e+02, 3.1336676e+01, 5.8640239e-01,
+ -1.0941547e+02, 8.4322101e+01, -1.0231229e+01, -7.6312076e+01,
+ 1.2996536e+02, -2.7610121e+01, -8.9190623e+01, 7.8060953e+01,
+ 6.1715955e+00, -9.5954760e+01, 1.3405798e+02, -1.2502304e+01,
+ -1.3552601e+02, 1.1952233e+02, -6.4806966e+00, -1.2142849e+02,
+ 1.8115437e+02, -1.4257871e+02, 3.1225251e+01, 1.6033227e+02,
+ -1.6511810e+02, 1.5240738e+02, 1.2638046e+01, -1.6469393e+02,
+ 1.4205406e+02, -1.1641621e+02, 4.7933541e+01, 9.6516025e+01,
+ -1.1306054e+02, 1.3942714e+02, -2.5241905e+01, -9.3530513e+01,
+ 8.8433097e+01, -1.0959238e+02, 8.7282861e+01, 3.9977748e+01,
+ -7.0411977e+01, 4.1780370e+01, 1.4511943e+01, 3.1125577e+01 ],
+
+ [ 6.7796903e+01, -3.8788720e+02, 1.2859183e+03, -7.2609371e+03,
+ -1.5704430e+03, -6.2795492e+02, 8.2356565e+02, -8.0022573e+02,
+ -3.3787309e+02, -3.5565588e+01, -1.0363528e+02, 3.3897199e+01,
+ 1.9043187e+02, 1.7876914e+02, -1.5669449e+01, -1.4678018e+02,
+ -1.0987901e+02, 3.8138527e+01, 7.5635735e+01, 2.8493842e+01,
+ -9.6336587e+00, -2.2372156e+01, -1.9441869e+01, -2.6295536e+01,
+ -6.7279947e+00, 3.2810187e+01, 3.3795132e+01, 2.0377831e+00,
+ -2.2847912e+01, -2.2110999e+01, -7.4749335e+00, 8.1844245e-01,
+ 6.9094406e+00, 1.1427591e+01, 1.0664575e+01, 2.5808397e+00,
+ -1.1296056e+01, -1.5517110e+01, -3.3427801e+00, 6.2108447e+00,
+ 1.0440121e+01, 4.7195530e+00, -4.6830353e+00, -4.3321706e+00,
+ -4.2308894e-01, -6.6286888e-01, -3.0541198e+00, 1.0803641e+00,
+ 3.4706447e+00, -1.0277278e+00, -5.8300676e+00, -1.2004259e+00,
+ 2.9511818e+00, 4.4258015e+00, -1.2798751e-01, -5.6192448e+00,
+ -1.1434112e+00, 2.9285732e-01, 2.3558315e+00, 8.5236355e-01,
+ -3.6033829e+00, 3.6155080e-01, -1.9369648e-02, -3.0335453e+00,
+ -3.9032015e+00, -3.0556779e+00, 3.9409059e-01, 3.5833234e-01,
+ -1.1380321e+00, 3.0590734e+00, 2.1256269e+00, 1.1948865e+00,
+ 1.8418728e+00, 1.9339640e+00, -1.8934727e+00, -7.8211470e+00,
+ -7.2315006e+00, -1.6085474e+00, 7.0887341e+00, 1.1289772e+01,
+ 7.3233713e+00, 5.9236776e-01, -4.6290981e+00, -4.8012930e+00,
+ -5.3731448e+00, -4.9951949e+00, -1.0331793e+00, 6.8575568e+00,
+ 1.1172332e+01, 2.1481470e+00, -9.4111289e+00, -1.2048567e+01,
+ -6.2321457e+00, 1.2834480e+00, 4.2595916e+00, 8.2235361e+00,
+ 9.4292179e+00, -8.2653408e-01, -7.7277654e+00, -5.0381286e+00,
+ 2.5809009e+00, 2.9671834e+00, -3.1758077e+00, -4.8014638e+00,
+ -2.4972384e+00, 3.7424503e+00, 3.1651108e+00, 2.1258770e+00,
+ -3.9826224e-01, -5.5310115e+00, -6.7195904e+00, -4.6113744e+00,
+ 4.7359889e+00, 1.1737180e+01, 4.3792994e+00, -2.4150647e+00,
+ -3.2444202e+00, -3.3837188e-01, -2.0142283e+00, -6.2230109e+00 ]
+
+])
+
+X_HAT_TNS = [ X_HAT_TNS_7M5, X_HAT_TNS_10M ]
+
+X_HAT_F_48K_10M = np.array([
+
+ 9.4517170e+02, 6.1123091e+02, 2.6864344e+03, -9.2131878e+02,
+ 3.9506388e+03, -1.6369062e+03, 2.4082498e+04, -3.0114303e+02,
+ -7.0038117e+03, -5.0717257e+03, -4.3561383e+03, -4.8809024e+03,
+ -2.4479052e+03, -6.2613898e+01, 2.0513506e+03, -1.4311748e+02,
+ 1.4311748e+02, -9.0641071e+02, 9.5411654e+01, -1.2880573e+03,
+ 5.2476410e+02, -1.1926457e+03, 4.7705827e+01, -9.5411654e+01,
+ 3.8164662e+02, 9.5411654e+01, 2.3852913e+02, 9.5411654e+01,
+ 9.5411654e+01, -9.5411654e+01, -1.9082331e+02, -1.9082331e+02,
+ 0.0000000e+00, 0.0000000e+00, -4.7705827e+02, 5.7246992e+02,
+ 2.8623496e+02, 3.3394079e+02, -4.7705827e+01, -9.5411654e+01,
+ -9.5411654e+01, -9.5411654e+01, -9.5411654e+01, 0.0000000e+00,
+ 0.0000000e+00, 2.3852913e+02, 4.7705827e+01, 8.1099906e+02,
+ -5.2476410e+02, 0.0000000e+00, -9.5411654e+01, 9.5411654e+01,
+ -1.9082331e+02, -4.7705827e+01, -9.5411654e+01, 1.4311748e+02,
+ 4.7705827e+01, 9.5411654e+01, 0.0000000e+00, 0.0000000e+00,
+ -2.3852913e+02, -9.5411654e+01, -2.8623496e+02, -3.3394079e+02,
+ -1.4311748e+02, -4.7705827e+01, 4.7705827e+01, 4.7705827e+01,
+ 1.9082331e+02, 2.3852913e+02, 9.5411654e+01, 0.0000000e+00,
+ -9.5411654e+01, -1.9082331e+02, -1.9082331e+02, -9.5411654e+01,
+ -1.4311748e+02, 4.7705827e+01, 4.7705827e+01, 2.8623496e+02,
+ 1.4311748e+02, 2.3852913e+02, 1.9082331e+02, 1.4311748e+02,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, -4.7705827e+01,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, -4.7705827e+01,
+ 4.7705827e+01, -2.3852913e+02, 0.0000000e+00, -9.5411654e+01,
+ -2.8623496e+02, -2.3852913e+02, -4.7705827e+01, -4.7705827e+01,
+ 0.0000000e+00, 0.0000000e+00, -4.7705827e+01, 4.7705827e+01,
+ -4.7705827e+01, -9.5411654e+01, -4.7705827e+01, -4.7705827e+01,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 4.7705827e+01,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, -4.7705827e+01, -4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, 4.7705827e+01, 0.0000000e+00, -4.7705827e+01,
+ 0.0000000e+00, -4.7705827e+01, 1.4311748e+02, -9.5411654e+01,
+ -4.7705827e+01, 4.7705827e+01, -4.7705827e+01, -4.7705827e+01,
+ 4.7705827e+01, 4.7705827e+01, 0.0000000e+00, 9.5411654e+01,
+ -1.9082331e+02, 9.5411654e+01, 1.9082331e+02, -9.5411654e+01,
+ -9.5411654e+01, 1.9082331e+02, -1.9082331e+02, 9.5411654e+01,
+ 4.7705827e+01, 0.0000000e+00, -4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, 4.7705827e+01, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 4.7705827e+01,
+ -4.7705827e+01, -4.7705827e+01, 0.0000000e+00, 0.0000000e+00,
+ -4.7705827e+01, 0.0000000e+00, 4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, -4.7705827e+01, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 4.7705827e+01, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 4.7705827e+01, 0.0000000e+00, -4.7705827e+01,
+ -4.7705827e+01, -4.7705827e+01, -4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 4.7705827e+01, 4.7705827e+01,
+ 4.7705827e+01, 0.0000000e+00, 0.0000000e+00, -4.7705827e+01,
+ -9.5411654e+01, -9.5411654e+01, -9.5411654e+01, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 9.5411654e+01,
+ 4.7705827e+01, 4.7705827e+01, 4.7705827e+01, 4.7705827e+01,
+ 0.0000000e+00, 0.0000000e+00, -4.7705827e+01, -4.7705827e+01,
+ -4.7705827e+01, 0.0000000e+00, -4.7705827e+01, -4.7705827e+01,
+ -4.7705827e+01, 0.0000000e+00, -4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 4.7705827e+01, 4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, 4.7705827e+01, -4.7705827e+01, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, -4.7705827e+01,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 4.7705827e+01, 0.0000000e+00,
+ 4.7705827e+01, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, 5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 4.7705827e+01, -4.7705827e+01, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, -5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ -5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, -5.9632284e+00, 5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, -5.9632284e+00, -5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, -5.9632284e+00, 5.9632284e+00,
+ 5.9632284e+00, 5.9632284e+00, 5.9632284e+00, -5.9632284e+00
+
+])
+
+RC_ORDER_48K_10M = np.array([ 4, 5 ])
+
+RC_I_1_48K_10M = np.array([ 3, 10, 10, 9, 8, 8, 8, 8 ])
+RC_I_2_48K_10M = np.array([ 4, 9, 11, 9, 9, 8, 8, 8 ])
+
+X_HAT_TNS_48K_10M = np.array([
+
+ 9.4517170e+02, 6.1123091e+02, 2.6864344e+03, -9.2131878e+02,
+ 3.9506388e+03, -1.6369062e+03, 2.4082498e+04, -3.0114303e+02,
+ -7.0038117e+03, -5.0717257e+03, -4.3561383e+03, -4.8809024e+03,
+ -2.4479052e+03, -2.2398317e+03, -3.1132766e+01, 2.0090579e+02,
+ 1.1862042e+03, 5.7338427e+02, 6.1759350e+02, -9.7469088e+02,
+ -6.4374897e+02, -2.0211697e+03, -1.7062857e+03, -1.3890132e+03,
+ -4.2328832e+02, 3.5577372e+02, 1.1106915e+03, 1.4302110e+03,
+ 1.4201992e+03, 9.4898618e+02, 2.3607533e+02, -4.7224392e+02,
+ -8.4841824e+02, -9.9022181e+02, -1.3448133e+03, -4.1592231e+02,
+ 2.0637545e+02, 9.3371650e+02, 1.1146864e+03, 9.6858809e+02,
+ 5.9597157e+02, 9.1928376e+01, -3.7626331e+02, -6.1986247e+02,
+ -6.9177579e+02, -3.4667628e+02, -1.0196915e+02, 9.4981560e+02,
+ 5.0772033e+02, 5.6925480e+02, 2.7206846e+02, 8.9632931e+01,
+ -3.0001737e+02, -4.6633999e+02, -5.8788470e+02, -3.5775041e+02,
+ -1.5049111e+02, 1.4316978e+02, 2.9621193e+02, 3.6240991e+02,
+ 9.5814668e+01, -7.8107250e+01, -4.7386669e+02, -8.4266712e+02,
+ -9.1319744e+02, -7.8870946e+02, -4.4400310e+02, -5.1962032e+01,
+ 4.4241817e+02, 8.5744581e+02, 9.6559775e+02, 8.1789237e+02,
+ 4.2722231e+02, -1.1744557e+02, -6.0875733e+02, -8.7077276e+02,
+ -9.9676704e+02, -7.3639748e+02, -3.7055666e+02, 2.7449836e+02,
+ 6.9342929e+02, 1.0695021e+03, 1.1847878e+03, 1.0572091e+03,
+ 6.5809175e+02, 2.0789887e+02, -2.0474320e+02, -5.3854975e+02,
+ -6.4606559e+02, -5.9469535e+02, -4.1519106e+02, -2.2005318e+02,
+ 6.5763023e+01, -1.8180468e+00, 1.1794585e+02, 3.7652871e+01,
+ -2.6013985e+02, -4.9007184e+02, -5.2184675e+02, -4.8856445e+02,
+ -3.1503130e+02, -1.1131138e+02, 2.8240046e+01, 2.1696333e+02,
+ 2.2485577e+02, 1.2779759e+02, 2.8796892e+01, -9.8980705e+01,
+ -1.5201103e+02, -1.6768213e+02, -1.4166855e+02, -3.8081735e+01,
+ 1.9957705e+01, 7.3452728e+01, 9.9166879e+01, 9.4204641e+01,
+ 7.0145854e+01, -1.3744063e+01, -9.3049197e+01, -1.1359718e+02,
+ -1.1480749e+02, -3.8801493e+01, -5.6439787e-01, -7.4563180e+00,
+ 2.1645294e+01, -2.1494684e+01, 1.2628610e+02, 1.3469076e+01,
+ -3.1053646e+01, 1.0922488e+00, -7.3585334e+01, -1.0982479e+02,
+ -4.7186648e+01, 1.5142158e+01, 4.5632808e+01, 1.6549594e+02,
+ -3.6083949e+01, 5.8172372e+01, 2.0212810e+02, 6.2799792e+01,
+ -3.6264662e+01, 1.1267918e+02, -1.4073978e+02, -3.0415441e+01,
+ 1.2090131e+00, 5.3715012e+00, -1.1377286e+01, -4.5565675e+00,
+ -5.6917226e+00, 4.3600122e+01, 4.1505158e+01, 4.0418175e+01,
+ 3.0433405e+01, 1.8807364e+01, 8.6851800e+00, 1.3063317e+00,
+ -1.6374357e+00, -5.1287186e-01, -8.3181817e+00, -1.3316624e+01,
+ -1.1754958e+01, -9.3082910e+00, -4.7125436e+00, 4.7799716e+01,
+ -1.4779469e+00, -4.4671371e+01, -4.7792557e+01, -5.2664965e+01,
+ -8.7747532e+01, -6.2908560e+01, 7.0728829e+00, 2.9933713e+01,
+ 5.4684947e+01, 1.2283279e+01, 6.0871825e+00, -9.7832692e+00,
+ -2.0805101e+01, 2.5453410e+01, 2.2568456e+01, 2.6671505e+01,
+ 2.3653407e+01, 6.0861792e+01, 4.5907030e+01, -1.3920574e+01,
+ -7.4036162e+01, -1.3377313e+02, -1.7526999e+02, -1.4452509e+02,
+ -9.6576994e+01, -3.4117396e+01, 7.2828977e+01, 1.5570493e+02,
+ 2.1295914e+02, 1.8790695e+02, 1.3270346e+02, 9.1184381e+00,
+ -1.5641394e+02, -2.9335242e+02, -3.8817395e+02, -3.2871789e+02,
+ -2.0655338e+02, -4.3550786e+01, 1.0968391e+02, 3.0824064e+02,
+ 3.3663279e+02, 3.0642586e+02, 1.8519446e+02, 5.7390329e+01,
+ -1.1630607e+02, -2.0276872e+02, -2.7699576e+02, -2.4543885e+02,
+ -1.7669630e+02, -1.9362678e+01, 4.7199101e+01, 1.0516333e+02,
+ 8.6666990e+01, 8.8657037e+01, -1.5558419e+01, -3.6914314e+01,
+ -8.0595009e+01, -7.0566026e+01, -5.9248668e+01, -1.4894165e+01,
+ 1.6364229e+01, 9.4426516e+01, 1.2736629e+02, 9.8422987e+01,
+ 5.1256905e+01, 4.3261239e+01, -7.3161150e+01, -8.1108665e+01,
+ -9.8148881e+01, -5.9938566e+01, -2.8972996e+01, -2.3262373e+01,
+ 2.3557895e+01, 4.1063112e+01, 4.9456507e+01, 2.9572229e+01,
+ 2.1373324e+01, -1.2116045e+01, -1.7920284e+01, -2.5397799e+01,
+ -1.5011495e+01, -1.6604903e+01, 5.7220095e+00, 4.2124559e+00,
+ 9.1295553e+00, 2.0972476e+00, 1.0219314e+01, 1.7408319e+00,
+ 9.3716408e-01, -4.4755970e+00, 4.3615172e+01, 2.1619284e+01,
+ 7.0197660e+01, 2.9541340e+01, 2.1495384e+01, -1.5543427e+01,
+ -2.9701692e+01, -4.8601263e+01, -4.1417636e+01, -2.0218456e+01,
+ -4.1919983e+00, 1.0811220e+01, 1.8282903e+01, 2.9153799e+01,
+ 2.6637698e+01, 2.0822319e+01, -2.0049692e+00, -1.7515145e+01,
+ -1.8945085e+01, -2.6096971e+01, -1.0443081e+01, 2.8259408e+00,
+ 1.9054250e+01, 2.6408940e+01, 2.9532072e+01, 1.1442436e+01,
+ 7.5316255e+00, -3.0305702e+00, -5.1747435e+00, -1.8407036e+01,
+ -7.2025275e+00, -1.3142410e+00, -8.9104503e-01, -1.9580507e+00,
+ 9.0242278e+00, 5.0649445e-01, 9.0989185e+00, 8.4374358e+00,
+ 1.2180369e+01, 9.8043365e+00, 1.0390873e+01, -4.5184465e+00,
+ -3.0104815e-01, -1.3617490e+01, -2.8571680e+00, 4.7226441e-02,
+ 1.0968668e+01, 1.4263590e+01, 1.9054635e+01, 4.5694855e+00,
+ -5.1714614e+00, -5.6951038e+00, -1.5868058e+01, -6.3038212e+00,
+ 6.0252467e-01, 5.9026641e+00, 7.8745777e+00, 8.8744978e+00,
+ 5.3462027e+01, -1.8654382e+01, -4.3353244e+00, -2.6929767e+01,
+ -1.5311914e+01, -2.7217677e+01, 3.5149041e-01, -3.3211226e+00,
+ 7.7038597e+00, 2.4167585e+00, 3.1307056e+00, -6.1700798e+00,
+ -9.6229135e+00, -1.5399820e+01, -1.5266153e+01, -2.7143843e+00,
+ 8.4318705e+00, 1.8387062e+01, 1.1142869e+01, 1.6194808e+01,
+ -9.1085598e-01, -9.8865640e+00, -9.6606173e+00, -4.4966142e+00,
+ -1.0006828e+01, -8.3653492e+00, 3.2044245e+00, -2.9444546e-01,
+ 1.0908085e+01, 1.3460563e+01, 1.7296403e+01, 2.3331346e+00,
+ -6.4643323e+00, -1.8141900e+01, -2.2182809e+01, -1.1540102e+01,
+ 1.1288138e+00, 2.4890144e+00, 1.6559739e+01, 8.5186198e+00,
+ 1.5415016e+01, -1.5380758e+00, -8.2713929e+00, -8.0722274e+00,
+ -2.5013191e+00, -8.9116220e+00, -7.8813678e+00, -9.3233771e+00,
+ 3.7714591e+00, -1.8991746e+00, -8.2806999e-01, 5.9195021e+00,
+ 1.1264459e+01, 1.3340521e+01, 1.4254734e+01, 7.3923870e-01,
+ 2.7992830e+00, -1.2191542e+01, -4.1559084e+00, -1.4491802e+01,
+ -1.1202358e+01, -1.3530333e+01, -8.4296049e+00, -7.8650114e+00,
+ -4.0242598e+00, -3.9190447e+00, -3.2052868e+00, 6.8414475e+00,
+ 1.2298364e+01, 4.5966329e+00, -2.2198027e+00, 1.4780361e+00,
+ 2.6041179e+00, -5.9986780e+00, 1.8848742e+00, 5.1985761e+00,
+ 1.0933162e+01, 1.2576045e+01, 2.6295117e+00, -6.3792422e+00,
+ -3.2379866e+00, -1.0344676e+00, -7.5143096e+00, 2.5669904e+00,
+ 7.6423118e+00, 1.4123706e+01, 1.5442459e+01, 4.3051286e+00
+
+])
+
+### C.4.1.7 Spectral shaping
+
+X_HAT_SNS_10M = np.array([
+
+ [ 0.0000000e+00, 3.2120898e+04, -2.7432096e+04, 9.5098925e+04,
+ -1.1435865e+05, -2.2381382e+05, -1.8369247e+03, -2.0115639e+04,
+ -1.5792914e+04, 0.0000000e+00, -1.5609063e+04, 4.0875220e+03,
+ -1.0230315e+04, 1.9369297e+03, -4.1865185e+03, -1.0063143e+03,
+ 5.6734153e+02, -2.8286784e+03, 2.4858485e+03, -2.7806581e+03,
+ 2.2044492e+03, -1.4655656e+03, 7.9623905e+02, 1.4627465e+02,
+ -6.8421307e+02, 1.2472853e+03, -1.3595558e+03, 1.3417640e+03,
+ -1.0434807e+03, 5.9927829e+02, -2.2923931e+02, -2.9150665e+02,
+ 5.1660528e+02, -7.4849706e+02, 7.9101280e+02, -7.5693454e+02,
+ 5.8965376e+02, -3.7385221e+02, 5.5646432e+01, 2.0409315e+02,
+ -3.8684762e+02, 4.7002840e+02, -5.1019782e+02, 4.6970753e+02,
+ -3.6882983e+02, 2.3887213e+02, -3.0765937e+01, -1.2545710e+02,
+ 2.5752773e+02, -3.0607937e+02, 3.0617821e+02, -3.0270399e+02,
+ 2.4452840e+02, -1.8729289e+02, 2.9629779e+01, 8.1156654e+01,
+ -1.9740547e+02, 2.3802067e+02, -2.9662172e+02, 2.2717944e+02,
+ -1.6519442e+02, 3.2859099e+01, 3.8288258e+01, -1.4380181e+02,
+ 1.5993592e+02, -1.7522348e+02, 1.3978068e+02, -1.2885956e+02,
+ 5.2007743e+01, -5.3744028e+00, -6.3481105e+01, 1.1005588e+02,
+ -1.3761380e+02, 1.1149518e+02, -9.6552293e+01, 2.4175349e+01,
+ 2.7349618e+01, -9.2532521e+01, 9.6809951e+01, -9.2329191e+01,
+ 8.1204030e+01, -2.8757018e+01, 1.7629374e+01, 5.0296426e+01,
+ -6.9554039e+01, 1.0643991e+02, -7.7045965e+01, 7.6992232e+01,
+ -1.5336408e+01, 6.7350324e+00, 5.2884931e+01, -4.5033515e+01,
+ 7.8565630e+01, -7.0077921e+01, 4.5653385e+01, -3.5627746e+01,
+ -1.8715552e+01, 1.4082202e+01, -6.2364732e+01, 3.5916392e+01,
+ -6.2514422e+01, 1.6978510e+01, -1.7220883e+00, -3.7254517e+01,
+ 3.5050409e+01, -3.2086295e+01, 1.2895849e+01, -1.4997608e+01,
+ -1.1409978e+01, 1.6692500e+00, -3.1028013e+01, 8.5596145e+00,
+ -8.3018444e+00, 6.7010013e+00, -1.0178138e+01, 1.8975872e+01,
+ 1.6344865e+00, 1.1210482e+01, -4.7611165e+00, 1.8818163e+01,
+ 1.0822497e+00, -8.9424468e+00, 2.7196773e+01, -3.6023020e+01,
+ 4.1833912e+01, -2.2996359e+01, 3.1520683e+00, 2.4451081e+01,
+ -2.3663155e+01, 4.4716235e+01, -4.3693613e+01, 2.9552445e+01,
+ -5.9899945e+00, -2.4756795e+01, 4.6495022e+01, -4.3040437e+01,
+ 3.1981524e+01, -2.8813669e+01, -1.1193668e+00, -2.6891294e+00,
+ -1.1789293e+01, 2.4012319e+01, -1.5122490e+01, 9.7992507e+00,
+ -9.3635505e+00, 1.3408697e+01, 3.8993996e+00, 6.5986643e+00,
+ -3.4130004e+00, -5.4797703e+00, 1.7638234e+01, -8.9968811e+00,
+ -1.3124018e+00, -4.9433015e+00, -1.5392870e+01, -5.3001786e+00,
+ -2.1345573e+01, 1.7203866e+01, -3.5997789e+01, 1.1646997e+01 ],
+
+ [ -6.2955623e+03, -1.4566565e+04, 5.0622202e+03, -7.0393645e+04,
+ 8.5577202e+04, 2.5855135e+05, -3.5335070e+04, 5.4655582e+04,
+ -1.1097295e+04, 1.8604727e+04, 1.7284056e+03, 6.9845121e+03,
+ 1.3066905e+03, 4.1207686e+03, 1.2132541e+03, 1.5347593e+03,
+ 6.1036346e+02, 6.5193569e+02, 1.5477285e+02, 1.0810302e+02,
+ -1.3121390e+01, -5.1968778e+01, -6.2665661e+01, -8.4220873e+01,
+ -4.1495195e+01, -3.5833798e+01, -1.0853816e+01, 4.1261732e-01,
+ 6.7539065e+00, 1.2953817e+01, 1.8822817e+01, 2.0173803e+01,
+ 1.6734007e+01, 1.3492868e+01, 8.9088009e+00, 3.1828720e+00,
+ -1.8693963e+00, -5.8104021e+00, -6.9265975e+00, -7.6077959e+00,
+ -7.9011791e+00, -5.7174692e+00, -4.5976263e+00, -1.5032819e+00,
+ -4.8178832e-01, 1.0459392e+00, 2.9544513e+00, 2.7006970e+00,
+ 2.6614506e+00, 1.8287519e+00, 2.1513094e+00, 1.5782394e+00,
+ 1.0890240e+00, -3.7646581e-01, -1.1518203e+00, -1.8534533e+00,
+ -2.3900791e+00, -1.5304619e+00, -2.1511073e+00, -6.8686891e-01,
+ -1.0939425e+00, 4.4580685e-01, 1.0694775e+00, 1.7112407e+00,
+ 2.1522574e+00, 1.1984063e+00, 1.8933761e+00, 1.5608228e+00,
+ 1.4612352e+00, 8.7220397e-02, -6.3880600e-01, -1.3031673e+00,
+ -1.9233091e+00, -1.2909908e+00, -2.1448096e+00, -7.0978302e-01,
+ -7.4823965e-02, -3.7868573e-01, 1.0642643e+00, 1.5420494e+00,
+ 2.4281898e+00, 1.1190134e+00, 2.0010149e+00, 4.8369747e-01,
+ -3.1302463e-01, 1.3884389e-01, -1.3802746e+00, -1.7576352e+00,
+ -2.3441435e+00, -2.4065591e+00, -2.4896924e+00, -1.0565690e+00,
+ -1.4455632e+00, 2.7527927e-01, -3.0281700e-01, -5.8686912e-02,
+ -2.3895075e-01, -4.9317896e-01, 5.9464861e-01, 7.8267846e-01,
+ -3.1558969e-02, 8.7786664e-01, -1.6042710e-01, -4.2013050e-01,
+ 1.9560599e-01, -8.1876351e-01, -9.6031363e-01, -1.4201787e+00,
+ -3.1915476e-01, 8.9297143e-02, -5.6412436e-01, -5.3261760e-01,
+ 4.2030523e-01, -2.3510454e-01, -4.6638224e-01, 2.9054917e-01,
+ 6.4077498e-01, 9.7649360e-01, 1.1359409e+00, 1.4250163e+00,
+ 5.4650505e-01, 3.8070710e-02, -5.7836964e-01, -7.7347222e-02,
+ -1.0712427e+00, -3.2900133e-01, -6.6441638e-02, 4.6435375e-01,
+ -1.8280947e-01, 7.1574422e-01, -1.6152798e-02, -2.6188697e-01,
+ -7.0437063e-01, 3.2250148e-02, -8.0333729e-01, -1.0595566e+00,
+ -1.2784303e+00, -2.4897303e-01, -9.0777061e-01, -1.0166946e+00,
+ -1.0877187e+00, 1.0276390e-01, 6.1843142e-01, 1.0990088e+00,
+ 4.1640936e-01, 2.1611445e-01, 1.0343162e+00, -1.6762504e-01,
+ 6.2546212e-01, 5.9995270e-01, 9.8434057e-01, 1.1432576e+00,
+ 1.2787609e+00, 3.0368561e-01, 9.9535729e-01, 9.7104477e-01,
+ 1.0977262e+00, -1.9294725e-01, 5.8743153e-01, 6.9473485e-01 ]
+])
+
+X_HAT_SNS_7M5 = np.array([
+
+ [ -2.7097714e+04, 3.0803384e+04, -1.0482091e+05, -1.6066697e+05,
+ 7.3848155e+03, 6.1515964e+04, -4.0837362e+03, 1.4874654e+03,
+ 8.2375155e+03, -8.1555674e+03, 3.0555770e+03, 1.6748461e+03,
+ -3.9585632e+03, 3.4593583e+03, -7.9211504e+02, -1.5776652e+03,
+ 2.4448549e+03, -1.6832871e+03, 8.3907446e+01, 1.2903730e+03,
+ -1.5923535e+03, 9.5931605e+02, 1.9128372e+02, -9.8357603e+02,
+ 9.5609940e+02, -4.5350218e+02, -2.5320962e+02, 6.3762292e+02,
+ -5.1397160e+02, 7.1216163e+01, 3.1269611e+02, -4.0275234e+02,
+ 2.5638994e+02, 4.6403201e+01, -2.7843009e+02, 2.8914418e+02,
+ -1.3395170e+02, -1.5288222e+02, 3.2333756e+02, -2.2944713e+02,
+ 1.9872415e+01, 2.6325395e+02, -2.8392752e+02, 1.5314277e+02,
+ 5.0798626e+01, -2.8345564e+02, 2.5587542e+02, -1.0445526e+02,
+ -1.0817500e+02, 2.2832437e+02, -1.6921255e+02, 7.2196740e+01,
+ 3.9741076e+01, -9.4592848e+01, 1.2449531e+02, -6.7961530e+01,
+ -1.2124324e+01, 5.7574971e+01, -7.1197322e+01, -1.4955585e+01,
+ 3.1388922e+01, -2.6320323e+01, 1.7618904e+01, 2.2336595e+01,
+ -4.6625728e+01, 1.1616015e+01, 3.8732599e+01, -2.7312663e+01,
+ 2.6048066e+01, -1.6572229e+01, -2.8923924e+01, 5.8075573e+01,
+ -5.6263689e+01, 2.9450962e+01, 2.1151792e+00, -2.7929547e+01,
+ 3.3208863e+01, -4.5403546e+01, 1.0797732e+01, 2.0205768e-01,
+ -3.7035922e+01, 2.8542095e+01, -3.4631575e+00, -2.5611045e+01,
+ 4.3617589e+01, -9.2662146e+00, -2.9678561e+01, 2.5975116e+01,
+ 2.0536248e+00, -3.1929357e+01, 4.4228879e+01, -4.1248038e+00,
+ -4.4713214e+01, 3.9433226e+01, -2.1402050e+00, -4.0100915e+01,
+ 5.9824970e+01, -4.7085628e+01, 1.0420556e+01, 5.3506419e+01,
+ -5.5103555e+01, 5.0861706e+01, 4.2620261e+00, -5.5541010e+01,
+ 4.7905991e+01, -3.9259942e+01, 1.6335294e+01, 3.2891742e+01,
+ -3.8529956e+01, 4.7515440e+01, -8.6928230e+00, -3.2210096e+01,
+ 3.0454645e+01, -3.7741492e+01, 3.0058525e+01, 1.3912599e+01,
+ -2.4503972e+01, 1.4539927e+01, 5.0502807e+00, 1.0831968e+01 ],
+
+ [ 3.8609917e+03, -2.2089936e+04, 6.2396694e+04, -2.5577568e+05,
+ -4.0161241e+04, -1.1658208e+04, 9.9426556e+03, -5.6272992e+03,
+ -1.3839628e+03, -8.4856310e+01, -1.6119528e+02, 3.8468595e+01,
+ 1.5768120e+02, 1.0800171e+02, -8.1867250e+00, -7.8607304e+01,
+ -6.0318312e+01, 2.1460378e+01, 4.3791334e+01, 1.7039175e+01,
+ -5.9501127e+00, -1.4271781e+01, -1.2583485e+01, -1.6962650e+01,
+ -4.3255972e+00, 2.1024124e+01, 2.1440266e+01, 1.2715073e+00,
+ -1.4021429e+01, -1.3345628e+01, -4.3592289e+00, 4.5305297e-01,
+ 3.6304646e+00, 5.6994442e+00, 5.3601809e+00, 1.2971700e+00,
+ -6.0746373e+00, -8.3445774e+00, -1.9233529e+00, 3.5735662e+00,
+ 6.4270894e+00, 2.9054250e+00, -2.9987419e+00, -2.7740687e+00,
+ -2.7396267e-01, -4.2922732e-01, -1.9998336e+00, 7.0742100e-01,
+ 2.2980847e+00, -6.8050918e-01, -3.7563574e+00, -7.7344365e-01,
+ 1.7803940e+00, 2.6700051e+00, -7.2296053e-02, -3.1741317e+00,
+ -6.0475055e-01, 1.5489233e-01, 1.2469224e+00, 4.5114909e-01,
+ -2.0399596e+00, 2.0468239e-01, -1.1728671e-02, -1.8368664e+00,
+ -2.3634589e+00, -1.9790219e+00, 2.5523434e-01, 2.3207537e-01,
+ -7.6437315e-01, 2.0546640e+00, 1.4277033e+00, 8.0700716e-01,
+ 1.2439713e+00, 1.3061682e+00, -1.2859071e+00, -5.3115466e+00,
+ -4.9111022e+00, -1.0984600e+00, 4.8408213e+00, 7.7096653e+00,
+ 4.8540011e+00, 3.9262706e-01, -3.0682108e+00, -2.9814266e+00,
+ -3.3365255e+00, -3.1018325e+00, -6.0106119e-01, 3.9894443e+00,
+ 6.4996032e+00, 1.2497035e+00, -5.1293438e+00, -6.5668257e+00,
+ -3.3967039e+00, 6.9951716e-01, 2.2622003e+00, 4.3673873e+00,
+ 5.0077054e+00, -4.3895891e-01, -4.1593548e+00, -2.7116978e+00,
+ 1.3891315e+00, 1.5970423e+00, -1.7323481e+00, -2.6191154e+00,
+ -1.3622003e+00, 2.0414418e+00, 1.7497613e+00, 1.1752440e+00,
+ -2.2017045e-01, -3.0576971e+00, -3.7647976e+00, -2.5836234e+00,
+ 2.6534415e+00, 6.5760121e+00, 2.4535983e+00, -1.3713128e+00,
+ -1.8422343e+00, -1.9213303e-01, -1.1437114e+00, -3.5335263e+00 ],
+])
+
+X_HAT_SNS = [ X_HAT_SNS_7M5, X_HAT_SNS_10M ]
+
+### C.4.1.8 MDCT
+
+T_HAT_MDCT_10M = np.array([
+
+ [ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ 6.1525095e-01, 1.7117620e+00, -1.6200436e-01, -2.1107548e+00,
+ 9.1636911e-01, 8.7583398e+00, 1.4291828e+01, 1.4615904e+01,
+ 1.9312730e+01, 2.2178311e+01, 2.1178760e+01, 1.9939021e+01,
+ 3.2745193e+01, 3.1385007e+01, 4.5642888e+01, 3.8185668e+01,
+ 4.3452271e+01, 3.0174130e+01, 2.7510416e+01, 3.9048290e+00,
+ -4.1911157e+00, -3.4032526e+01, -4.3089457e+01, -7.1817465e+01,
+ -7.3319439e+01, -1.0231340e+02, -8.2645833e+01, -1.0207070e+02,
+ -7.4253115e+01, -9.5269932e+01, -1.2210097e+02, -1.3216707e+02,
+ -1.2665681e+02, -1.6033791e+02, -1.3067613e+02, -1.8796611e+01,
+ 6.2097263e+01, 7.2290617e+00, -1.2550979e+02, -8.9649115e+01,
+ 7.6135408e+02, 2.7072170e+03, 6.1558256e+03, 9.6522574e+03,
+ 1.2566221e+04, 1.5421574e+04, 1.8329565e+04, 2.1102710e+04,
+ 2.3323039e+04, 2.5451924e+04, 2.7365468e+04, 2.8891223e+04,
+ 3.0341813e+04, 3.1380038e+04, 3.2134454e+04, 3.2606958e+04,
+ 3.2683895e+04, 3.2518324e+04, 3.2036626e+04, 3.1278795e+04,
+ 3.0136453e+04, 2.8694957e+04, 2.7009676e+04, 2.5075921e+04,
+ 2.2940269e+04, 2.0564299e+04, 1.7956441e+04, 1.5202722e+04,
+ 1.2352834e+04, 9.3639445e+03, 6.2714619e+03, 3.1112267e+03,
+ -1.0075267e+02, -3.3115389e+03, -6.4954073e+03, -9.6110111e+03,
+ -1.2594144e+04, -1.5477538e+04, -1.8214406e+04, -2.0797170e+04,
+ -2.3195615e+04, -2.5355124e+04, -2.7302557e+04, -2.8919494e+04,
+ -3.0273227e+04, -3.1357707e+04, -3.2152224e+04, -3.2625545e+04,
+ -3.2802109e+04, -3.2640407e+04, -3.2172861e+04, -3.1393517e+04,
+ -3.0316009e+04, -2.8922986e+04, -2.7290775e+04, -2.5351571e+04,
+ -2.3183937e+04, -2.0795771e+04, -1.8212609e+04, -1.5453610e+04,
+ -1.2543978e+04, -9.4923186e+03, -6.3663932e+03, -3.1740539e+03,
+ 4.2407582e+01, 3.2479359e+03, 6.4369448e+03, 9.5564107e+03,
+ 1.2589389e+04, 1.5494437e+04, 1.8238168e+04, 2.0814647e+04,
+ 2.3183440e+04, 2.5340307e+04, 2.7236643e+04, 2.8879098e+04,
+ 3.0219987e+04, 3.1304367e+04, 3.2073455e+04, 3.2541098e+04,
+ 3.2660415e+04, 3.2490788e+04, 3.2004309e+04, 3.1215306e+04,
+ 3.0131477e+04, 2.8751611e+04, 2.7114762e+04, 2.5198099e+04,
+ 2.3044166e+04, 2.0655799e+04, 1.8068458e+04, 1.5312555e+04,
+ 1.2400688e+04, 9.3834439e+03, 6.2670869e+03, 3.1043555e+03,
+ -9.0364008e+01, -3.2949280e+03, -6.4558716e+03, -9.5736656e+03,
+ -1.2593429e+04, -1.5487321e+04, -1.8231003e+04, -2.0808229e+04,
+ -2.3191386e+04, -2.5327915e+04, -2.7226934e+04, -2.8860268e+04,
+ -3.0235350e+04, -3.1313467e+04, -3.2092397e+04, -3.2585580e+04,
+ -3.2777259e+04, -3.2606534e+04, -3.2146234e+04, -3.1383325e+04,
+ -3.0295384e+04, -2.8926934e+04, -2.7297985e+04, -2.5343669e+04,
+ -2.3152305e+04, -2.0670493e+04, -1.7934304e+04, -1.4904360e+04,
+ -1.1690361e+04, -8.2034060e+03, -4.4966301e+03, -5.9716414e+02,
+ 3.3525737e+03, 7.3668269e+03, 1.1354417e+04, 1.5112467e+04,
+ 1.8623854e+04, 2.1896001e+04, 2.4687380e+04, 2.6938007e+04,
+ 2.8626837e+04, 2.9696113e+04, 3.0136274e+04, 2.9938040e+04,
+ 2.9086081e+04, 2.7633076e+04, 2.5690739e+04, 2.3353541e+04,
+ 2.0706676e+04, 1.7862611e+04, 1.4893850e+04, 1.1890794e+04,
+ 9.0400724e+03, 6.3496693e+03, 3.8416289e+03, 1.6255098e+03,
+ -2.6829587e+02, -1.8648283e+03, -3.1265144e+03, -4.0739027e+03,
+ -4.7217057e+03, -5.1308259e+03, -5.2994797e+03, -5.2717085e+03,
+ -5.0702632e+03, -4.7404796e+03, -4.2926332e+03, -3.7668674e+03,
+ -3.1863326e+03, -2.5717341e+03, -1.9487052e+03, -1.3380710e+03,
+ -7.5480786e+02, -2.1731911e+02, 2.6258546e+02, 6.7531993e+02,
+ 1.0134680e+03, 1.2732878e+03, 1.4518662e+03, 1.5497281e+03,
+ 1.5671087e+03, 1.5098872e+03, 1.3843562e+03, 1.1969411e+03,
+ 9.5570061e+02, 6.6987624e+02, 3.5217663e+02, 9.8694010e+00,
+ -3.4394935e+02, -6.9967997e+02, -1.0489605e+03, -1.3797643e+03,
+ -1.6859141e+03, -1.9573045e+03, -2.1892388e+03, -2.3761776e+03,
+ -2.5135134e+03, -2.6015039e+03, -2.6377063e+03, -2.6272971e+03,
+ -2.5708325e+03, -2.4734547e+03, -2.3405452e+03, -2.1774990e+03,
+ -1.9928710e+03, -1.7900465e+03, -1.5787667e+03, -1.3647693e+03,
+ -1.1565972e+03, -9.5713834e+02, -7.7246019e+02, -6.0536929e+02,
+ -4.5916520e+02, -3.3470350e+02, -2.3251725e+02, -1.5151486e+02,
+ -9.0224117e+01, -4.6447782e+01, -1.7377196e+01, -1.6206249e-01,
+ 8.2694380e+00, 1.0620902e+01, 9.2650945e+00, 5.7978679e+00 ],
+
+ [ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -5.8307275e+01, -1.5961611e+02, -3.2822433e+02, -5.8684193e+02,
+ -9.5063064e+02, -1.4274461e+03, -2.0154696e+03, -2.7009630e+03,
+ -3.4569464e+03, -4.2430564e+03, -5.0068652e+03, -5.6873576e+03,
+ -6.2169269e+03, -6.5268185e+03, -6.5539697e+03, -6.2419962e+03,
+ -5.5512117e+03, -4.4569448e+03, -2.9581517e+03, -1.0742654e+03,
+ 1.1530263e+03, 3.6594640e+03, 6.3646353e+03, 9.1749853e+03,
+ 1.1985116e+04, 1.4691422e+04, 1.7187008e+04, 1.9378907e+04,
+ 2.1179777e+04, 2.2522740e+04, 2.3359818e+04, 2.3657684e+04,
+ 2.3405693e+04, 2.2611255e+04, 2.1297773e+04, 1.9499385e+04,
+ 1.7264572e+04, 1.4646235e+04, 1.1703370e+04, 8.4960382e+03,
+ 5.0883571e+03, 1.5400010e+03, -2.0852434e+03, -5.7317898e+03,
+ -9.3443119e+03, -1.2867162e+04, -1.6250847e+04, -1.9448892e+04,
+ -2.2417993e+04, -2.5119550e+04, -2.7519523e+04, -2.9589531e+04,
+ -3.1306279e+04, -3.2653256e+04, -3.3615026e+04, -3.4186391e+04,
+ -3.4364519e+04, -3.4152077e+04, -3.3554064e+04, -3.2586709e+04,
+ -3.1263292e+04, -2.9603089e+04, -2.7630063e+04, -2.5371579e+04,
+ -2.2853607e+04, -2.0109903e+04, -1.7174483e+04, -1.4079475e+04,
+ -1.0861936e+04, -7.5574424e+03, -4.2020683e+03, -8.2997756e+02,
+ 2.5249878e+03, 5.8295399e+03, 9.0523976e+03, 1.2164914e+04,
+ 1.5141205e+04, 1.7954597e+04, 2.0583186e+04, 2.3005366e+04,
+ 2.5205897e+04, 2.7165327e+04, 2.8871803e+04, 3.0312108e+04,
+ 3.1479927e+04, 3.2363955e+04, 3.2960351e+04, 3.3265900e+04,
+ 3.3277052e+04, 3.2993786e+04, 3.2419707e+04, 3.1554084e+04,
+ 3.0408074e+04, 2.8986068e+04, 2.7298583e+04, 2.5360460e+04,
+ 2.3186540e+04, 2.0794689e+04, 1.8206602e+04, 1.5444741e+04,
+ 1.2535402e+04, 9.5045150e+03, 6.3825434e+03, 3.1961404e+03,
+ -1.9030604e+01, -3.2350097e+03, -6.4178539e+03, -9.5376996e+03,
+ -1.2564818e+04, -1.5468879e+04, -1.8222757e+04, -2.0799617e+04,
+ -2.3177492e+04, -2.5329860e+04, -2.7239548e+04, -2.8887388e+04,
+ -3.0257022e+04, -3.1336972e+04, -3.2115659e+04, -3.2585521e+04,
+ -3.2741691e+04, -3.2583544e+04, -3.2112334e+04, -3.1332786e+04,
+ -3.0253039e+04, -2.8881031e+04, -2.7231757e+04, -2.5321143e+04,
+ -2.3168095e+04, -2.0790131e+04, -1.8212051e+04, -1.5458479e+04,
+ -1.2554090e+04, -9.5278709e+03, -6.4088050e+03, -3.2282766e+03,
+ -1.5127187e+01, 3.1974595e+03, 6.3806758e+03, 9.5013370e+03,
+ 1.2533377e+04, 1.5443257e+04, 1.8203988e+04, 2.0793445e+04,
+ 2.3180292e+04, 2.5344634e+04, 2.7265053e+04, 2.8919963e+04,
+ 3.0294320e+04, 3.1376795e+04, 3.2154178e+04, 3.2622959e+04,
+ 3.2776568e+04, 3.2617286e+04, 3.2145842e+04, 3.1360660e+04,
+ 3.0278348e+04, 2.8901877e+04, 2.7241369e+04, 2.5301056e+04,
+ 2.3077170e+04, 2.0602593e+04, 1.7860920e+04, 1.4845935e+04,
+ 1.1575770e+04, 8.0714330e+03, 4.3590833e+03, 4.8619425e+02,
+ -3.4812252e+03, -7.4811451e+03, -1.1420224e+04, -1.5218969e+04,
+ -1.8767216e+04, -2.1982348e+04, -2.4766842e+04, -2.7038512e+04,
+ -2.8729372e+04, -2.9797530e+04, -3.0215913e+04, -2.9983529e+04,
+ -2.9130275e+04, -2.7706100e+04, -2.5778477e+04, -2.3437188e+04,
+ -2.0783932e+04, -1.7920105e+04, -1.4952584e+04, -1.1982327e+04,
+ -9.1037807e+03, -6.3864700e+03, -3.9012432e+03, -1.6878870e+03,
+ 2.1843895e+02, 1.8077853e+03, 3.0762163e+03, 4.0339692e+03,
+ 4.7031968e+03, 5.1098317e+03, 5.2820716e+03, 5.2546005e+03,
+ 5.0617380e+03, 4.7306477e+03, 4.2889148e+03, 3.7647491e+03,
+ 3.1840313e+03, 2.5717028e+03, 1.9493478e+03, 1.3380429e+03,
+ 7.5567371e+02, 2.1773747e+02, -2.6311651e+02, -6.7663706e+02,
+ -1.0155643e+03, -1.2750705e+03, -1.4528246e+03, -1.5489867e+03,
+ -1.5659952e+03, -1.5076498e+03, -1.3804175e+03, -1.1912334e+03,
+ -9.4848033e+02, -6.6207374e+02, -3.4175876e+02, 1.6521653e+00,
+ 3.5767927e+02, 7.1550189e+02, 1.0651058e+03, 1.3968326e+03,
+ 1.7019804e+03, 1.9728594e+03, 2.2034762e+03, 2.3889564e+03,
+ 2.5257870e+03, 2.6127289e+03, 2.6495795e+03, 2.6378966e+03,
+ 2.5805079e+03, 2.4818035e+03, 2.3472272e+03, 2.1829178e+03,
+ 1.9955916e+03, 1.7924019e+03, 1.5804111e+03, 1.3664419e+03,
+ 1.1569292e+03, 9.5724044e+02, 7.7214172e+02, 6.0521399e+02,
+ 4.5883364e+02, 3.3442067e+02, 2.3213371e+02, 1.5121914e+02,
+ 9.0047461e+01, 4.6310025e+01, 1.7308037e+01, 7.2726310e-02,
+ -8.3269806e+00, -1.0647845e+01, -9.2769990e+00, -5.7939041e+00 ],
+
+])
+
+T_HAT_MDCT_7M5 = np.array([
+
+ [ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ 9.0382948e-01, 2.8563300e+00, 2.0863167e+00, 3.2605273e+00,
+ 1.8231017e+00, -2.6473031e+00, -7.7420704e+00, -1.6971743e+01,
+ -4.4169569e+00, 4.7473387e+00, 7.9882732e+00, 2.1090757e+00,
+ 6.9477046e+00, 7.6294361e+00, 4.5069158e+00, 1.1288109e+00,
+ 5.5301798e-01, -1.2320805e+00, 1.2696965e+01, 1.7998129e+01,
+ 1.9997378e+01, 2.3310802e+01, 3.4116671e+01, 3.1619222e+01,
+ 2.3643252e+01, 2.2595989e+01, 2.4150879e+01, 1.7561939e+01,
+ 2.4167995e+01, 2.1868269e+01, 1.2021561e+01, 1.0810360e+01,
+ -1.1321816e+01, -1.3811836e+01, -2.7571991e+01, -3.3459505e+01,
+ -2.6720233e+01, -4.0425004e+01, -4.1666697e+01, -4.8106995e+01,
+ -7.1121739e+01, -8.5018856e+01, -6.4519501e+01, -6.1651047e+01,
+ -6.2001672e+01, -4.9054098e+01, 5.3605147e+00, -2.7222279e+00,
+ -6.3200946e+00, -2.8873822e+01, -5.6314175e+01, -5.9551902e+01,
+ -2.1183627e+01, -9.5007617e+01, -6.7674879e+01, 7.6546124e+01,
+ 3.6355638e+02, 2.0908440e+02, 9.2290767e+01, -8.4453487e+01,
+ -2.0810832e+02, -1.9235273e+02, -4.0634578e+02, -2.2011977e+02,
+ 6.2920459e+02, 3.1481663e+03, 6.2343351e+03, 9.4022080e+03,
+ 1.2520451e+04, 1.5313131e+04, 1.8128985e+04, 2.0762454e+04,
+ 2.3084787e+04, 2.5275848e+04, 2.7095495e+04, 2.8665301e+04,
+ 3.0094623e+04, 3.1202047e+04, 3.2006678e+04, 3.2461623e+04,
+ 3.2568832e+04, 3.2408327e+04, 3.1961953e+04, 3.1146555e+04,
+ 3.0073949e+04, 2.8725124e+04, 2.7099832e+04, 2.5196695e+04,
+ 2.3022972e+04, 2.0643354e+04, 1.8079103e+04, 1.5352852e+04,
+ 1.2476728e+04, 9.4135962e+03, 6.2948219e+03, 3.1010477e+03,
+ -9.0897787e+01, -3.3383673e+03, -6.5093586e+03, -9.6214110e+03,
+ -1.2638625e+04, -1.5564780e+04, -1.8289238e+04, -2.0877731e+04,
+ -2.3274493e+04, -2.5456613e+04, -2.7372293e+04, -2.9018289e+04,
+ -3.0399516e+04, -3.1474248e+04, -3.2213279e+04, -3.2686770e+04,
+ -3.2836146e+04, -3.2655386e+04, -3.2161995e+04, -3.1363572e+04,
+ -3.0296725e+04, -2.8893704e+04, -2.7226660e+04, -2.5303018e+04,
+ -2.3185989e+04, -2.0860640e+04, -1.8388180e+04, -1.5768019e+04,
+ -1.3017648e+04, -1.0256225e+04, -7.4288937e+03, -4.6404303e+03,
+ -1.8479563e+03, 8.9695589e+02, 3.6050165e+03, 6.1774761e+03,
+ 8.5802409e+03, 1.0843314e+04, 1.2957357e+04, 1.4915752e+04,
+ 1.6688121e+04, 1.8234848e+04, 1.9622853e+04, 2.0843143e+04,
+ 2.1874370e+04, 2.2730604e+04, 2.3433492e+04, 2.3972978e+04,
+ 2.4361621e+04, 2.4632443e+04, 2.4789213e+04, 2.4834368e+04,
+ 2.4817473e+04, 2.4691904e+04, 2.4506825e+04, 2.4260930e+04,
+ 2.3952544e+04, 2.3583514e+04, 2.3158707e+04, 2.2682736e+04,
+ 2.2114814e+04, 2.1501602e+04, 2.0804765e+04, 2.0028682e+04,
+ 1.9176325e+04, 1.8229068e+04, 1.7186098e+04, 1.6064305e+04,
+ 1.4857345e+04, 1.3566101e+04, 1.2216378e+04, 1.0824025e+04,
+ 9.3566686e+03, 7.8525218e+03, 6.3408636e+03, 4.8352443e+03,
+ 3.3500951e+03, 1.8786022e+03, 4.4842764e+02, -8.8483949e+02,
+ -2.1241927e+03, -3.2448273e+03, -4.2656467e+03, -5.1440714e+03,
+ -5.9062863e+03, -6.5125637e+03, -6.9672797e+03, -7.2820785e+03,
+ -7.4483481e+03, -7.4911171e+03, -7.4042834e+03, -7.2043747e+03,
+ -6.8934126e+03, -6.5065747e+03, -6.0545237e+03, -5.5534407e+03,
+ -5.0174587e+03, -4.4641711e+03, -3.9151968e+03, -3.3732391e+03,
+ -2.8528068e+03, -2.3664418e+03, -1.9195477e+03, -1.5167365e+03,
+ -1.1638365e+03, -8.6204669e+02, -6.1212532e+02, -4.0852043e+02,
+ -2.5108888e+02, -1.3435049e+02, -5.3189240e+01, -1.0851528e+00,
+ 2.6728439e+01, 3.7348684e+01, 3.5932093e+01, 2.7568411e+01 ],
+
+ [ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, -0.0000000e+00, -0.0000000e+00, -0.0000000e+00,
+ -0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 0.0000000e+00, 0.0000000e+00, 0.0000000e+00, 0.0000000e+00,
+ 7.4140637e+01, 1.4259396e+02, 2.4292388e+02, 3.8197729e+02,
+ 5.6596483e+02, 8.0010169e+02, 1.0881546e+03, 1.4325879e+03,
+ 1.8337245e+03, 2.2902305e+03, 2.7978462e+03, 3.3513844e+03,
+ 3.9420820e+03, 4.5597592e+03, 5.1914056e+03, 5.8224872e+03,
+ 6.4359174e+03, 7.0133507e+03, 7.5344894e+03, 7.9783768e+03,
+ 8.3235628e+03, 8.5499202e+03, 8.6355016e+03, 8.5623082e+03,
+ 8.3125769e+03, 7.8732452e+03, 7.2322659e+03, 6.3830254e+03,
+ 5.3220070e+03, 4.0508083e+03, 2.5743934e+03, 9.0382380e+02,
+ -9.4658515e+02, -2.9577774e+03, -5.1073476e+03, -7.3680800e+03,
+ -9.7116793e+03, -1.2105745e+04, -1.4518157e+04, -1.6913624e+04,
+ -1.9259368e+04, -2.1519698e+04, -2.3664419e+04, -2.5661182e+04,
+ -2.7484674e+04, -2.9109128e+04, -3.0513566e+04, -3.1680767e+04,
+ -3.2599500e+04, -3.3259046e+04, -3.3656364e+04, -3.3789359e+04,
+ -3.3661417e+04, -3.3275865e+04, -3.2647991e+04, -3.1778553e+04,
+ -3.0687860e+04, -2.9386993e+04, -2.7893292e+04, -2.6217793e+04,
+ -2.4380305e+04, -2.2396921e+04, -2.0285631e+04, -1.8056304e+04,
+ -1.5731396e+04, -1.3310749e+04, -1.0817930e+04, -8.2632546e+03,
+ -5.6584950e+03, -3.0169039e+03, -3.5049466e+02, 2.3300294e+03,
+ 5.0072558e+03, 7.6692538e+03, 1.0296341e+04, 1.2873294e+04,
+ 1.5379430e+04, 1.7799709e+04, 2.0110518e+04, 2.2292425e+04,
+ 2.4321243e+04, 2.6179470e+04, 2.7838772e+04, 2.9288536e+04,
+ 3.0502052e+04, 3.1467674e+04, 3.2161346e+04, 3.2580900e+04,
+ 3.2712443e+04, 3.2548152e+04, 3.2079638e+04, 3.1315042e+04,
+ 3.0239307e+04, 2.8881574e+04, 2.7232557e+04, 2.5325302e+04,
+ 2.3165560e+04, 2.0776212e+04, 1.8202819e+04, 1.5452512e+04,
+ 1.2552870e+04, 9.5323059e+03, 6.4141989e+03, 3.2353808e+03,
+ 3.2008805e+01, -3.1778835e+03, -6.3568255e+03, -9.4682388e+03,
+ -1.2490842e+04, -1.5403926e+04, -1.8154186e+04, -2.0745346e+04,
+ -2.3121161e+04, -2.5285375e+04, -2.7200767e+04, -2.8855100e+04,
+ -3.0236188e+04, -3.1303814e+04, -3.2106304e+04, -3.2610143e+04,
+ -3.2801911e+04, -3.2722047e+04, -3.2333816e+04, -3.1622380e+04,
+ -3.0637858e+04, -2.9319050e+04, -2.7722782e+04, -2.5854268e+04,
+ -2.3707550e+04, -2.1309710e+04, -1.8683478e+04, -1.5843106e+04,
+ -1.2810610e+04, -9.6245078e+03, -6.3128385e+03, -2.9018457e+03,
+ 5.6021860e+02, 4.0355321e+03, 7.4888401e+03, 1.0869459e+04,
+ 1.4146120e+04, 1.7266962e+04, 2.0195488e+04, 2.2894666e+04,
+ 2.5327458e+04, 2.7459548e+04, 2.9268259e+04, 3.0729712e+04,
+ 3.1824168e+04, 3.2542974e+04, 3.2879994e+04, 3.2838377e+04,
+ 3.2420961e+04, 3.1641217e+04, 3.0522280e+04, 2.9086732e+04,
+ 2.7364573e+04, 2.5386626e+04, 2.3192561e+04, 2.0822736e+04,
+ 1.8313768e+04, 1.5710203e+04, 1.3055162e+04, 1.0388760e+04,
+ 7.7479346e+03, 5.1773492e+03, 2.7035918e+03, 3.6336147e+02,
+ -1.8203312e+03, -3.8257571e+03, -5.6281400e+03, -7.2191945e+03,
+ -8.5918440e+03, -9.7361057e+03, -1.0653660e+04, -1.1351662e+04,
+ -1.1834991e+04, -1.2108888e+04, -1.2194030e+04, -1.2106898e+04,
+ -1.1844914e+04, -1.1451706e+04, -1.0928890e+04, -1.0302174e+04,
+ -9.5993172e+03, -8.8336978e+03, -8.0218966e+03, -7.1899794e+03,
+ -6.3420744e+03, -5.5028868e+03, -4.6880751e+03, -3.9103856e+03,
+ -3.1844358e+03, -2.5158381e+03, -1.9161507e+03, -1.3860285e+03,
+ -9.3082869e+02, -5.4957243e+02, -2.3962727e+02, 2.0859282e+00,
+ 1.8035744e+02, 3.0232747e+02, 3.7488265e+02, 4.0574857e+02,
+ 4.0326247e+02, 3.7569870e+02, 3.3102137e+02, 2.7655429e+02,
+ 2.1828293e+02, 1.6157727e+02, 1.1024218e+02, 6.6816369e+01 ]
+
+])
+
+T_HAT_MDCT = [ T_HAT_MDCT_7M5, T_HAT_MDCT_10M ]
+
+### C.4.1.9 LTPF
+
+X_HAT_LTPF_10M = np.array([
+
+ [ 6.1525095e-01, 1.7117620e+00, -1.6200436e-01, -2.1107548e+00,
+ 9.1636911e-01, 8.7583398e+00, 1.4291828e+01, 1.4615904e+01,
+ 1.9312730e+01, 2.2178311e+01, 2.1178760e+01, 1.9939021e+01,
+ 3.2745193e+01, 3.1385007e+01, 4.5642888e+01, 3.8185668e+01,
+ 4.3452271e+01, 3.0174130e+01, 2.7510416e+01, 3.9048290e+00,
+ -4.1911157e+00, -3.4032526e+01, -4.3089457e+01, -7.1817465e+01,
+ -7.3319439e+01, -1.0231340e+02, -8.2645833e+01, -1.0207070e+02,
+ -7.4253115e+01, -9.5269932e+01, -1.2210097e+02, -1.3216707e+02,
+ -1.2665681e+02, -1.6033791e+02, -1.3067613e+02, -1.8796611e+01,
+ 6.2097263e+01, 7.2290617e+00, -1.2550979e+02, -8.9649115e+01,
+ 7.6135408e+02, 2.7072170e+03, 6.1558256e+03, 9.6522574e+03,
+ 1.2566221e+04, 1.5421574e+04, 1.8329565e+04, 2.1102710e+04,
+ 2.3323039e+04, 2.5451924e+04, 2.7365468e+04, 2.8891223e+04,
+ 3.0341813e+04, 3.1380038e+04, 3.2134454e+04, 3.2606958e+04,
+ 3.2683895e+04, 3.2518324e+04, 3.2036626e+04, 3.1278795e+04,
+ 3.0136453e+04, 2.8694957e+04, 2.7009676e+04, 2.5075921e+04,
+ 2.2940269e+04, 2.0564299e+04, 1.7956441e+04, 1.5202722e+04,
+ 1.2352834e+04, 9.3639445e+03, 6.2714619e+03, 3.1112267e+03,
+ -1.0075267e+02, -3.3115389e+03, -6.4954073e+03, -9.6110111e+03,
+ -1.2594144e+04, -1.5477538e+04, -1.8214406e+04, -2.0797170e+04,
+ -2.3195615e+04, -2.5355124e+04, -2.7302557e+04, -2.8919494e+04,
+ -3.0273227e+04, -3.1357707e+04, -3.2152224e+04, -3.2625545e+04,
+ -3.2802109e+04, -3.2640407e+04, -3.2172861e+04, -3.1393517e+04,
+ -3.0316009e+04, -2.8922986e+04, -2.7290775e+04, -2.5351571e+04,
+ -2.3183937e+04, -2.0795771e+04, -1.8212609e+04, -1.5453610e+04,
+ -1.2543978e+04, -9.4923186e+03, -6.3663932e+03, -3.1740539e+03,
+ 4.2407582e+01, 3.2479359e+03, 6.4369448e+03, 9.5564107e+03,
+ 1.2589389e+04, 1.5494437e+04, 1.8238168e+04, 2.0814647e+04,
+ 2.3183440e+04, 2.5340307e+04, 2.7236643e+04, 2.8879098e+04,
+ 3.0219987e+04, 3.1304367e+04, 3.2073455e+04, 3.2541098e+04,
+ 3.2660415e+04, 3.2490788e+04, 3.2004309e+04, 3.1215306e+04,
+ 3.0131477e+04, 2.8751611e+04, 2.7114762e+04, 2.5198099e+04,
+ 2.3044166e+04, 2.0655799e+04, 1.8068458e+04, 1.5312555e+04,
+ 1.2400688e+04, 9.3834439e+03, 6.2670869e+03, 3.1043555e+03,
+ -9.0364008e+01, -3.2949280e+03, -6.4558716e+03, -9.5736656e+03,
+ -1.2593429e+04, -1.5487321e+04, -1.8231003e+04, -2.0808229e+04,
+ -2.3191386e+04, -2.5327915e+04, -2.7226934e+04, -2.8860268e+04,
+ -3.0235350e+04, -3.1313467e+04, -3.2092397e+04, -3.2585580e+04,
+ -3.2777259e+04, -3.2606534e+04, -3.2146234e+04, -3.1383325e+04,
+ -3.0295384e+04, -2.8926934e+04, -2.7297985e+04, -2.5343669e+04 ],
+
+ [ -2.3210612e+04, -2.0830109e+04, -1.8262528e+04, -1.5491202e+04,
+ -1.2640992e+04, -9.6308521e+03, -6.5120997e+03, -3.2981272e+03,
+ -1.0437273e+02, 3.1237705e+03, 6.3475523e+03, 9.4251090e+03,
+ 1.2406927e+04, 1.5369182e+04, 1.8133410e+04, 2.0696011e+04,
+ 2.3075625e+04, 2.5239168e+04, 2.7178122e+04, 2.8863775e+04,
+ 3.0239107e+04, 3.1292540e+04, 3.2055374e+04, 3.2528526e+04,
+ 3.2691792e+04, 3.2554032e+04, 3.2080858e+04, 3.1269701e+04,
+ 3.0219849e+04, 2.8872409e+04, 2.7201446e+04, 2.5283194e+04,
+ 2.3137397e+04, 2.0746427e+04, 1.8171258e+04, 1.5425482e+04,
+ 1.2542866e+04, 9.5154094e+03, 6.4038902e+03, 3.2243297e+03,
+ 1.8093877e+01, -3.2004786e+03, -6.3778766e+03, -9.4986572e+03,
+ -1.2530644e+04, -1.5438896e+04, -1.8199553e+04, -2.0786963e+04,
+ -2.3172801e+04, -2.5336869e+04, -2.7256938e+04, -2.8914212e+04,
+ -3.0292811e+04, -3.1379968e+04, -3.2163160e+04, -3.2636663e+04,
+ -3.2797410e+04, -3.2642190e+04, -3.2169708e+04, -3.1389768e+04,
+ -3.0307591e+04, -2.8933213e+04, -2.7277887e+04, -2.5361709e+04,
+ -2.3197556e+04, -2.0809583e+04, -1.8223444e+04, -1.5459240e+04,
+ -1.2547850e+04, -9.5147469e+03, -6.3913071e+03, -3.2061552e+03,
+ 1.1474435e+01, 3.2280361e+03, 6.4146913e+03, 9.5376172e+03,
+ 1.2570372e+04, 1.5481142e+04, 1.8242641e+04, 2.0827867e+04,
+ 2.3213026e+04, 2.5375280e+04, 2.7293037e+04, 2.8947339e+04,
+ 3.0323330e+04, 3.1406817e+04, 3.2187891e+04, 3.2660531e+04,
+ 3.2817886e+04, 3.2659083e+04, 3.2187190e+04, 3.1402569e+04,
+ 3.0317849e+04, 2.8939620e+04, 2.7281206e+04, 2.5360297e+04,
+ 2.3194809e+04, 2.0805310e+04, 1.8215867e+04, 1.5450539e+04,
+ 1.2535402e+04, 9.5045150e+03, 6.3825434e+03, 3.1961404e+03,
+ -1.9030604e+01, -3.2350097e+03, -6.4178539e+03, -9.5376996e+03,
+ -1.2564818e+04, -1.5468879e+04, -1.8222757e+04, -2.0799617e+04,
+ -2.3177492e+04, -2.5329860e+04, -2.7239548e+04, -2.8887388e+04,
+ -3.0257022e+04, -3.1336972e+04, -3.2115659e+04, -3.2585521e+04,
+ -3.2741691e+04, -3.2583544e+04, -3.2112334e+04, -3.1332786e+04,
+ -3.0253039e+04, -2.8881031e+04, -2.7231757e+04, -2.5321143e+04,
+ -2.3168095e+04, -2.0790131e+04, -1.8212051e+04, -1.5458479e+04,
+ -1.2554090e+04, -9.5278709e+03, -6.4088050e+03, -3.2282766e+03,
+ -1.5127187e+01, 3.1974595e+03, 6.3806758e+03, 9.5013370e+03,
+ 1.2533377e+04, 1.5443257e+04, 1.8203988e+04, 2.0793445e+04,
+ 2.3180292e+04, 2.5344634e+04, 2.7265053e+04, 2.8919963e+04,
+ 3.0294320e+04, 3.1376795e+04, 3.2154178e+04, 3.2622959e+04,
+ 3.2776568e+04, 3.2617286e+04, 3.2145842e+04, 3.1360660e+04,
+ 3.0278348e+04, 2.8901877e+04, 2.7241369e+04, 2.5301056e+04 ],
+
+])
+
+X_HAT_LTPF_7M5 = np.array([
+
+ [ 9.0382948e-01, 2.8563300e+00, 2.0863167e+00, 3.2605273e+00,
+ 1.8231017e+00, -2.6473031e+00, -7.7420704e+00, -1.6971743e+01,
+ -4.4169569e+00, 4.7473387e+00, 7.9882732e+00, 2.1090757e+00,
+ 6.9477046e+00, 7.6294361e+00, 4.5069158e+00, 1.1288109e+00,
+ 5.5301798e-01, -1.2320805e+00, 1.2696965e+01, 1.7998129e+01,
+ 1.9997378e+01, 2.3310802e+01, 3.4116671e+01, 3.1619222e+01,
+ 2.3643252e+01, 2.2595989e+01, 2.4150879e+01, 1.7561939e+01,
+ 2.4167995e+01, 2.1868269e+01, 1.2021561e+01, 1.0810360e+01,
+ -1.1321816e+01, -1.3811836e+01, -2.7571991e+01, -3.3459505e+01,
+ -2.6720233e+01, -4.0425004e+01, -4.1666697e+01, -4.8106995e+01,
+ -7.1121739e+01, -8.5018856e+01, -6.4519501e+01, -6.1651047e+01,
+ -6.2001672e+01, -4.9054098e+01, 5.3605147e+00, -2.7222279e+00,
+ -6.3200946e+00, -2.8873822e+01, -5.6314175e+01, -5.9551902e+01,
+ -2.1183627e+01, -9.5007617e+01, -6.7674879e+01, 7.6546124e+01,
+ 3.6355638e+02, 2.0908440e+02, 9.2290767e+01, -8.4453487e+01,
+ -2.0810832e+02, -1.9235273e+02, -4.0634578e+02, -2.2011977e+02,
+ 6.2920459e+02, 3.1481663e+03, 6.2343351e+03, 9.4022080e+03,
+ 1.2520451e+04, 1.5313131e+04, 1.8128985e+04, 2.0762454e+04,
+ 2.3084787e+04, 2.5275848e+04, 2.7095495e+04, 2.8665301e+04,
+ 3.0094623e+04, 3.1202047e+04, 3.2006678e+04, 3.2461623e+04,
+ 3.2568832e+04, 3.2408327e+04, 3.1961953e+04, 3.1146555e+04,
+ 3.0073949e+04, 2.8725124e+04, 2.7099832e+04, 2.5196695e+04,
+ 2.3022972e+04, 2.0643354e+04, 1.8079103e+04, 1.5352852e+04,
+ 1.2476728e+04, 9.4135962e+03, 6.2948219e+03, 3.1010477e+03,
+ -9.0897787e+01, -3.3383673e+03, -6.5093586e+03, -9.6214110e+03,
+ -1.2638625e+04, -1.5564780e+04, -1.8289238e+04, -2.0877731e+04,
+ -2.3274493e+04, -2.5456613e+04, -2.7372293e+04, -2.9018289e+04,
+ -3.0399516e+04, -3.1474248e+04, -3.2213279e+04, -3.2686770e+04,
+ -3.2836146e+04, -3.2655386e+04, -3.2161995e+04, -3.1363572e+04,
+ -3.0296725e+04, -2.8893704e+04, -2.7226660e+04, -2.5303018e+04 ],
+
+ [ -2.3111848e+04, -2.0718046e+04, -1.8145256e+04, -1.5386042e+04,
+ -1.2451683e+04, -9.4561229e+03, -6.3407390e+03, -3.2078423e+03,
+ -1.4231827e+01, 3.1871864e+03, 6.4028626e+03, 9.5288605e+03,
+ 1.2522323e+04, 1.5403074e+04, 1.8148763e+04, 2.0738239e+04,
+ 2.3124038e+04, 2.5248199e+04, 2.7157343e+04, 2.8821520e+04,
+ 3.0197933e+04, 3.1280524e+04, 3.2068994e+04, 3.2535286e+04,
+ 3.2674198e+04, 3.2505688e+04, 3.2021479e+04, 3.1217393e+04,
+ 3.0139480e+04, 2.8742712e+04, 2.7081219e+04, 2.5164753e+04,
+ 2.3005958e+04, 2.0625737e+04, 1.8051360e+04, 1.5314656e+04,
+ 1.2403135e+04, 9.3958576e+03, 6.2866076e+03, 3.1150574e+03,
+ -8.3043055e+01, -3.2906309e+03, -6.4783209e+03, -9.5968770e+03,
+ -1.2627329e+04, -1.5543027e+04, -1.8297188e+04, -2.0856742e+04,
+ -2.3242831e+04, -2.5406524e+04, -2.7315500e+04, -2.8954115e+04,
+ -3.0311322e+04, -3.1397263e+04, -3.2199564e+04, -3.2663393e+04,
+ -3.2812053e+04, -3.2631820e+04, -3.2158938e+04, -3.1361864e+04,
+ -3.0286591e+04, -2.8909485e+04, -2.7252911e+04, -2.5338382e+04,
+ -2.3179744e+04, -2.0801866e+04, -1.8222214e+04, -1.5467629e+04,
+ -1.2551908e+04, -9.5234786e+03, -6.4050183e+03, -3.2234113e+03,
+ -1.0202956e+01, 3.2050827e+03, 6.3811438e+03, 9.5000550e+03,
+ 1.2526624e+04, 1.5433267e+04, 1.8190970e+04, 2.0775689e+04,
+ 2.3157406e+04, 2.5317424e+04, 2.7226647e+04, 2.8880016e+04,
+ 3.0250964e+04, 3.1333324e+04, 3.2108157e+04, 3.2579815e+04,
+ 3.2739171e+04, 3.2585501e+04, 3.2115570e+04, 3.1342610e+04,
+ 3.0239307e+04, 2.8881574e+04, 2.7232557e+04, 2.5325302e+04,
+ 2.3165560e+04, 2.0776212e+04, 1.8202819e+04, 1.5452512e+04,
+ 1.2552870e+04, 9.5323059e+03, 6.4141989e+03, 3.2353808e+03,
+ 3.2008805e+01, -3.1778835e+03, -6.3568255e+03, -9.4682388e+03,
+ -1.2490842e+04, -1.5403926e+04, -1.8154186e+04, -2.0745346e+04,
+ -2.3121161e+04, -2.5285375e+04, -2.7200767e+04, -2.8855100e+04,
+ -3.0236188e+04, -3.1303814e+04, -3.2106304e+04, -3.2610143e+04 ]
+
+])
+
+X_HAT_LTPF = [ X_HAT_LTPF_7M5, X_HAT_LTPF_10M ]
+
+LTPF_C2_NBITS = 320
+
+LTPF_C2_ACTIVE = np.array([ False, True ])
+LTPF_C2_PITCH_INDEX = np.array([ 60, 56 ])
+
+LTPF_C2_C_N = np.array([
+ [ 0. , 0. , 0. ],
+ [ 2.0480302e-01, 1.4271871e-01, -6.4036434e-03 ],
+])
+
+LTPF_C2_C_D = np.array([
+ [ 0. , 0. , 0. , 0. ],
+ [ 1.5868459e-02, 1.8368837e-01, 1.8368837e-01, 1.5868459e-02 ],
+])
+
+LTPF_C2_X = np.array([
+
+ [ 2.1004800e+03, 2.0660438e+03, 2.0070810e+03, 1.9335150e+03,
+ 1.8437505e+03, 1.7474564e+03, 1.6433626e+03, 1.5341100e+03,
+ 1.4257583e+03, 1.3211557e+03, 1.2062000e+03, 1.0819606e+03,
+ 9.5194047e+02, 8.1893657e+02, 6.7789896e+02, 5.3732954e+02,
+ 4.0506079e+02, 2.7179124e+02, 1.3998655e+02, 1.9709326e+00,
+ -1.3683087e+02, -2.7783589e+02, -4.1717230e+02, -5.5239764e+02,
+ -6.7544678e+02, -7.8374115e+02, -8.8533384e+02, -9.8169275e+02,
+ -1.0740844e+03, -1.1619601e+03, -1.2468187e+03, -1.3276334e+03,
+ -1.3976625e+03, -1.4581676e+03, -1.5080701e+03, -1.5565703e+03,
+ -1.6009886e+03, -1.6442955e+03, -1.6843665e+03, -1.7151734e+03,
+ -1.7459758e+03, -1.7579559e+03, -1.7383847e+03, -1.6558090e+03,
+ -1.4937678e+03, -1.2402230e+03, -9.0680789e+02, -5.2126546e+02,
+ -1.0907639e+02, 2.9396419e+02, 6.6844988e+02, 9.9743497e+02,
+ 1.2728461e+03, 1.5005211e+03, 1.6749621e+03, 1.8070876e+03,
+ 1.9030819e+03, 1.9644916e+03, 1.9851832e+03, 1.9771133e+03,
+ 1.9382403e+03, 1.8819654e+03, 1.8027215e+03, 1.7116504e+03,
+ 1.6036716e+03, 1.4931560e+03, 1.3786289e+03, 1.2583587e+03,
+ 1.1369652e+03, 1.0121811e+03, 8.8292297e+02, 7.5232872e+02,
+ 6.2279997e+02, 4.8668604e+02, 3.4937590e+02, 2.1277380e+02,
+ 7.7335654e+01, -5.2960798e+01, -1.8097039e+02, -3.0070120e+02,
+ -4.1472118e+02, -5.2643886e+02, -6.3396297e+02, -7.3691168e+02,
+ -8.3480847e+02, -9.2600159e+02, -1.0147685e+03, -1.0954793e+03,
+ -1.1736112e+03, -1.2509220e+03, -1.3222525e+03, -1.3883874e+03,
+ -1.4496560e+03, -1.5064726e+03, -1.5576614e+03, -1.6028926e+03,
+ -1.6434987e+03, -1.6803495e+03, -1.7069786e+03, -1.7018749e+03,
+ -1.6517403e+03, -1.5416168e+03, -1.3607723e+03, -1.1195564e+03,
+ -8.2569063e+02, -4.9652560e+02, -1.5319529e+02, 1.8519693e+02,
+ 5.0070752e+02, 7.8614834e+02, 1.0314193e+03, 1.2402508e+03,
+ 1.4166554e+03, 1.5555207e+03, 1.6600606e+03, 1.7324994e+03,
+ 1.7753655e+03, 1.7931195e+03, 1.7839794e+03, 1.7543157e+03,
+ 1.7049335e+03, 1.6342871e+03, 1.5549646e+03, 1.4629383e+03,
+ 1.3581758e+03, 1.2457595e+03, 1.1299878e+03, 1.0119864e+03,
+ 8.9090477e+02, 7.6719677e+02, 6.4285660e+02, 5.1408928e+02,
+ 3.8508372e+02, 2.5534679e+02, 1.2497756e+02, -3.9966107e+00,
+ -1.2599628e+02, -2.4595825e+02, -3.6034285e+02, -4.7095724e+02,
+ -5.7730810e+02, -6.8592514e+02, -7.8960041e+02, -8.9182726e+02,
+ -9.8741569e+02, -1.0733871e+03, -1.1555560e+03, -1.2285264e+03,
+ -1.2950383e+03, -1.3587508e+03, -1.4190449e+03, -1.4731166e+03,
+ -1.5244161e+03, -1.5700435e+03, -1.6143711e+03, -1.6442522e+03,
+ -1.6504480e+03, -1.6200592e+03, -1.5385467e+03, -1.4018632e+03 ],
+
+ [ -1.2097642e+03, -9.7471997e+02, -7.0651192e+02, -4.1925510e+02,
+ -1.2278127e+02, 1.6308666e+02, 4.3389868e+02, 6.8416589e+02,
+ 9.0871878e+02, 1.1028177e+03, 1.2670447e+03, 1.4015901e+03,
+ 1.5108776e+03, 1.5894427e+03, 1.6428125e+03, 1.6684610e+03,
+ 1.6687068e+03, 1.6467684e+03, 1.6069401e+03, 1.5504379e+03,
+ 1.4802355e+03, 1.3985477e+03, 1.3037872e+03, 1.1957600e+03,
+ 1.0853732e+03, 9.7233331e+02, 8.4944729e+02, 7.2549848e+02,
+ 5.9937450e+02, 4.8205790e+02, 3.5945231e+02, 2.3181221e+02,
+ 1.0289577e+02, -2.2787734e+01, -1.4227469e+02, -2.5954609e+02,
+ -3.7614640e+02, -4.8391910e+02, -5.8341913e+02, -6.8123214e+02,
+ -7.7747871e+02, -8.6932601e+02, -9.5415487e+02, -1.0385138e+03,
+ -1.1184902e+03, -1.1867290e+03, -1.2499404e+03, -1.3128700e+03,
+ -1.3730047e+03, -1.4324194e+03, -1.4841659e+03, -1.5297608e+03,
+ -1.5601321e+03, -1.5603639e+03, -1.5252096e+03, -1.4567924e+03,
+ -1.3535284e+03, -1.2050129e+03, -1.0232675e+03, -8.1556031e+02,
+ -5.8338838e+02, -3.4263538e+02, -9.1284066e+01, 1.4792883e+02,
+ 3.7724977e+02, 5.9063752e+02, 7.8210956e+02, 9.5337152e+02,
+ 1.1069618e+03, 1.2346417e+03, 1.3304957e+03, 1.4081378e+03,
+ 1.4660754e+03, 1.5064930e+03, 1.5231194e+03, 1.5173564e+03,
+ 1.4891356e+03, 1.4460229e+03, 1.3890302e+03, 1.3171848e+03,
+ 1.2329448e+03, 1.1400293e+03, 1.0376506e+03, 9.3324803e+02,
+ 8.2426407e+02, 7.1443513e+02, 6.0252527e+02, 4.9088960e+02,
+ 3.7646014e+02, 2.6184052e+02, 1.4340035e+02, 3.0422051e+01,
+ -8.5724331e+01, -1.9809318e+02, -3.0918985e+02, -4.1384220e+02,
+ -5.0992503e+02, -6.0275760e+02, -6.9829113e+02, -7.9525188e+02,
+ -8.9453019e+02, -9.7802721e+02, -1.0526954e+03, -1.1251736e+03,
+ -1.1955435e+03, -1.2637584e+03, -1.3263901e+03, -1.3794649e+03,
+ -1.4229086e+03, -1.4542303e+03, -1.4659972e+03, -1.4469638e+03,
+ -1.3956114e+03, -1.3075606e+03, -1.1938217e+03, -1.0487411e+03,
+ -8.7590742e+02, -6.8650630e+02, -4.8348960e+02, -2.7915529e+02,
+ -7.3951415e+01, 1.2639053e+02, 3.2037647e+02, 5.0816397e+02,
+ 6.7805869e+02, 8.2207151e+02, 9.5456310e+02, 1.0705573e+03,
+ 1.1629335e+03, 1.2429314e+03, 1.3063791e+03, 1.3382875e+03,
+ 1.3364949e+03, 1.3197603e+03, 1.3011283e+03, 1.2904738e+03,
+ 1.2841453e+03, 1.2735627e+03, 1.2483109e+03, 1.1982190e+03,
+ 1.1236072e+03, 1.0353182e+03, 9.4811986e+02, 8.4791470e+02,
+ 7.4977805e+02, 6.0946439e+02, 4.1686370e+02, 1.5206161e+02,
+ -7.9210822e+01, -2.2784261e+02, -3.2684361e+02, -3.9056312e+02,
+ -4.6716161e+02, -5.4206330e+02, -6.2230545e+02, -7.0009951e+02,
+ -7.7171489e+02, -8.3103588e+02, -8.8858361e+02, -9.5353054e+02 ]
+
+])
+
+LTPF_C2_PREV = np.array([
+
+ [ 3.6075890e+02, 2.5558573e+02, 1.5676072e+02, 6.2869832e+01,
+ -2.7464215e+01, -1.0807999e+02, -1.8538536e+02, -2.5213341e+02,
+ -3.1737297e+02, -3.7675903e+02, -4.3291912e+02, -4.8396843e+02,
+ -5.3257774e+02, -5.7812590e+02, -6.2166743e+02, -6.6533460e+02,
+ -7.0685062e+02, -7.4579194e+02, -7.7729679e+02, -8.0489134e+02,
+ -8.3252315e+02, -8.5569655e+02, -8.7998412e+02, -9.0742496e+02,
+ -9.3370927e+02, -9.5471476e+02, -9.7276449e+02, -9.9514771e+02,
+ -1.0136386e+03, -1.0163600e+03, -9.9100449e+02, -9.3570452e+02,
+ -8.4068970e+02, -7.0878785e+02, -5.4236585e+02, -3.4883259e+02,
+ -1.3544369e+02, 7.6143761e+01, 2.8313432e+02, 4.7371481e+02,
+ 6.3854542e+02, 7.8591376e+02, 9.1647781e+02, 1.0326049e+03,
+ 1.1226394e+03, 1.1855486e+03, 1.2110267e+03, 1.2072759e+03,
+ 1.1810221e+03, 1.1433488e+03, 1.0943565e+03, 1.0414966e+03,
+ 9.8463390e+02, 9.1048007e+02, 8.1752062e+02, 7.2333732e+02,
+ 6.4850080e+02, 5.9874218e+02, 5.6539980e+02, 5.5634736e+02,
+ 5.3800637e+02, 4.9467989e+02, 4.1631880e+02, 2.8517505e+02,
+ 1.1305724e+02, -8.8498535e+01, -2.9818901e+02, -4.9635689e+02,
+ -6.7273562e+02, -8.1632731e+02, -9.2538304e+02, -1.0146932e+03,
+ -1.0962177e+03, -1.1660919e+03, -1.2306080e+03, -1.2853503e+03,
+ -1.3346346e+03, -1.3883886e+03, -1.4496624e+03, -1.5155564e+03,
+ -1.5793268e+03, -1.6396210e+03, -1.6937295e+03, -1.7314870e+03,
+ -1.7610564e+03, -1.7775059e+03, -1.7806815e+03, -1.7684558e+03,
+ -1.6949960e+03, -1.4776266e+03, -1.0700242e+03, -5.1121101e+02,
+ 1.0329967e+02, 6.7165782e+02, 1.1381176e+03, 1.4974226e+03,
+ 1.7689436e+03, 1.9620604e+03, 2.0875907e+03, 2.1420343e+03,
+ 2.1555856e+03, 2.1497779e+03, 2.1345923e+03, 2.1141460e+03,
+ 2.0831857e+03, 2.0328927e+03, 1.9628672e+03, 1.8762276e+03,
+ 1.7788061e+03, 1.6631901e+03, 1.5303905e+03, 1.3855681e+03,
+ 1.2298992e+03, 1.0770934e+03, 9.1998634e+02, 7.6869655e+02,
+ 6.1555385e+02, 4.7278828e+02, 3.3511742e+02, 2.0334643e+02,
+ 8.1069660e+01, -4.1916116e+01, -1.7411361e+02, -3.0622256e+02,
+ -4.3179154e+02, -5.5570746e+02, -6.8069811e+02, -7.9809071e+02,
+ -9.0053455e+02, -9.9388321e+02, -1.0834733e+03, -1.1654917e+03,
+ -1.2466250e+03, -1.3184789e+03, -1.3814537e+03, -1.4386054e+03,
+ -1.5024822e+03, -1.5617271e+03, -1.6148868e+03, -1.6639722e+03,
+ -1.7108728e+03, -1.7519590e+03, -1.7805217e+03, -1.8036393e+03,
+ -1.8080682e+03, -1.7690236e+03, -1.6458189e+03, -1.4003994e+03,
+ -1.0280788e+03, -5.6864419e+02, -7.5505097e+01, 3.9987715e+02,
+ 8.1589313e+02, 1.1654034e+03, 1.4482132e+03, 1.6762780e+03,
+ 1.8458377e+03, 1.9698779e+03, 2.0528472e+03, 2.0941040e+03 ],
+
+ [ 2.1004800e+03, 2.0660438e+03, 2.0070810e+03, 1.9335150e+03,
+ 1.8437505e+03, 1.7474564e+03, 1.6433626e+03, 1.5341100e+03,
+ 1.4257583e+03, 1.3211557e+03, 1.2062000e+03, 1.0819606e+03,
+ 9.5194047e+02, 8.1893657e+02, 6.7789896e+02, 5.3732954e+02,
+ 4.0506079e+02, 2.7179124e+02, 1.3998655e+02, 1.9709326e+00,
+ -1.3683087e+02, -2.7783589e+02, -4.1717230e+02, -5.5239764e+02,
+ -6.7544678e+02, -7.8374115e+02, -8.8533384e+02, -9.8169275e+02,
+ -1.0740844e+03, -1.1619601e+03, -1.2468187e+03, -1.3276334e+03,
+ -1.3976625e+03, -1.4581676e+03, -1.5080701e+03, -1.5565703e+03,
+ -1.6009886e+03, -1.6442955e+03, -1.6843665e+03, -1.7151734e+03,
+ -1.7459758e+03, -1.7579559e+03, -1.7383847e+03, -1.6558090e+03,
+ -1.4937678e+03, -1.2402230e+03, -9.0680789e+02, -5.2126546e+02,
+ -1.0907639e+02, 2.9396419e+02, 6.6844988e+02, 9.9743497e+02,
+ 1.2728461e+03, 1.5005211e+03, 1.6749621e+03, 1.8070876e+03,
+ 1.9030819e+03, 1.9644916e+03, 1.9851832e+03, 1.9771133e+03,
+ 1.9382403e+03, 1.8819654e+03, 1.8027215e+03, 1.7116504e+03,
+ 1.6036716e+03, 1.4931560e+03, 1.3786289e+03, 1.2583587e+03,
+ 1.1369652e+03, 1.0121811e+03, 8.8292297e+02, 7.5232872e+02,
+ 6.2279997e+02, 4.8668604e+02, 3.4937590e+02, 2.1277380e+02,
+ 7.7335654e+01, -5.2960798e+01, -1.8097039e+02, -3.0070120e+02,
+ -4.1472118e+02, -5.2643886e+02, -6.3396297e+02, -7.3691168e+02,
+ -8.3480847e+02, -9.2600159e+02, -1.0147685e+03, -1.0954793e+03,
+ -1.1736112e+03, -1.2509220e+03, -1.3222525e+03, -1.3883874e+03,
+ -1.4496560e+03, -1.5064726e+03, -1.5576614e+03, -1.6028926e+03,
+ -1.6434987e+03, -1.6803495e+03, -1.7069786e+03, -1.7018749e+03,
+ -1.6517403e+03, -1.5416168e+03, -1.3607723e+03, -1.1195564e+03,
+ -8.2569063e+02, -4.9652560e+02, -1.5319529e+02, 1.8519693e+02,
+ 5.0070752e+02, 7.8614834e+02, 1.0314193e+03, 1.2402508e+03,
+ 1.4166554e+03, 1.5555207e+03, 1.6600606e+03, 1.7324994e+03,
+ 1.7753655e+03, 1.7931195e+03, 1.7839794e+03, 1.7543157e+03,
+ 1.7049335e+03, 1.6342871e+03, 1.5549646e+03, 1.4629383e+03,
+ 1.3581758e+03, 1.2457595e+03, 1.1299878e+03, 1.0119864e+03,
+ 8.9090477e+02, 7.6719677e+02, 6.4285660e+02, 5.1408928e+02,
+ 3.8508372e+02, 2.5534679e+02, 1.2497756e+02, -3.9966107e+00,
+ -1.2599628e+02, -2.4595825e+02, -3.6034285e+02, -4.7095724e+02,
+ -5.7730810e+02, -6.8592514e+02, -7.8960041e+02, -8.9182726e+02,
+ -9.8741569e+02, -1.0733871e+03, -1.1555560e+03, -1.2285264e+03,
+ -1.2950383e+03, -1.3587508e+03, -1.4190449e+03, -1.4731166e+03,
+ -1.5244161e+03, -1.5700435e+03, -1.6143711e+03, -1.6442522e+03,
+ -1.6504480e+03, -1.6200592e+03, -1.5385467e+03, -1.4018632e+03 ],
+
+])
+
+LTPF_C2_TRANS = np.array([
+
+ -1.2097642e+03, -9.7530715e+02, -7.0586256e+02, -4.1543418e+02,
+ -1.1414107e+02, 1.7777097e+02, 4.5531279e+02, 7.1225199e+02,
+ 9.4297106e+02, 1.1428504e+03, 1.3122721e+03, 1.4510401e+03,
+ 1.5632810e+03, 1.6437088e+03, 1.6979967e+03, 1.7236213e+03,
+ 1.7231450e+03, 1.6998644e+03, 1.6575399e+03, 1.5978279e+03,
+ 1.5240838e+03, 1.4378667e+03, 1.3380626e+03, 1.2256564e+03,
+ 1.1110323e+03, 9.9312189e+02, 8.6572627e+02, 7.3745656e+02,
+ 6.0633674e+02, 4.8191123e+02, 3.5135472e+02, 2.1648189e+02,
+ 8.0831679e+01, -5.1111363e+01, -1.7717212e+02, -3.0113312e+02,
+ -4.2348388e+02, -5.3759466e+02, -6.4602675e+02, -7.5403092e+02,
+ -8.6017221e+02, -9.5944484e+02, -1.0506850e+03, -1.1398086e+03,
+ -1.2228263e+03, -1.2941518e+03, -1.3612258e+03, -1.4273749e+03,
+ -1.4894501e+03, -1.5495534e+03, -1.6019734e+03, -1.6490374e+03,
+ -1.6814663e+03, -1.6844562e+03, -1.6513997e+03, -1.5793876e+03,
+ -1.4632011e+03, -1.2939942e+03, -1.0852074e+03, -8.4480887e+02,
+ -5.7732264e+02, -3.0008156e+02, -1.5103259e+01, 2.5424761e+02,
+ 5.1054364e+02, 7.4618547e+02, 9.5531914e+02, 1.1392454e+03,
+ 1.2997276e+03, 1.4305069e+03, 1.5279454e+03, 1.6037570e+03,
+ 1.6553093e+03, 1.6847892e+03, 1.6879843e+03, 1.6682815e+03,
+ 1.6264868e+03, 1.5696403e+03, 1.4983779e+03, 1.4119806e+03,
+ 1.3127144e+03, 1.2052332e+03, 1.0900241e+03, 9.7210566e+02,
+ 8.4877207e+02, 7.2467907e+02, 5.9961756e+02, 4.7505541e+02,
+ 3.4639404e+02, 2.1700781e+02, 8.5155762e+01, -4.0026523e+01,
+ -1.6698145e+02, -2.8953979e+02, -4.0971310e+02, -5.2233024e+02,
+ -6.2776248e+02, -7.3117198e+02, -8.3540014e+02, -9.3755661e+02,
+ -1.0392995e+03, -1.1263481e+03, -1.2052728e+03, -1.2805748e+03,
+ -1.3532553e+03, -1.4234920e+03, -1.4883360e+03, -1.5444401e+03,
+ -1.5915550e+03, -1.6260829e+03, -1.6379761e+03, -1.6152110e+03,
+ -1.5560714e+03, -1.4554812e+03, -1.3203947e+03, -1.1456045e+03,
+ -9.3870522e+02, -7.1082654e+02, -4.6691560e+02, -2.2039906e+02,
+ 2.5206392e+01, 2.6135641e+02, 4.8629103e+02, 6.9790232e+02,
+ 8.8592993e+02, 1.0460616e+03, 1.1899193e+03, 1.3098413e+03,
+ 1.4023098e+03, 1.4788921e+03, 1.5346583e+03, 1.5579963e+03,
+ 1.5491955e+03, 1.5242006e+03, 1.4921986e+03, 1.4607118e+03,
+ 1.4256432e+03, 1.3811223e+03, 1.3213357e+03, 1.2406869e+03,
+ 1.1418577e+03, 1.0338657e+03, 9.2734345e+02, 8.0983956e+02,
+ 6.9568058e+02, 5.4691592e+02, 3.6168815e+02, 1.2569299e+02,
+ -7.2937241e+01, -2.1016935e+02, -3.1888920e+02, -4.0476988e+02,
+ -5.0359952e+02, -5.9623817e+02, -6.9164993e+02, -7.8397385e+02,
+ -8.7149927e+02, -9.4943765e+02, -1.0247441e+03, -1.1018532e+03,
+
+])
+
+LTPF_C3_NBITS = 320
+
+LTPF_C3_ACTIVE = np.array([ True, False ])
+LTPF_C3_PITCH_INDEX = np.array([ 56, 0 ])
+
+LTPF_C3_C_N = np.array([
+ [ 2.0480302e-01, 1.4271871e-01, -6.4036434e-03 ],
+ [ 0. , 0. , 0. ],
+])
+
+LTPF_C3_C_D = np.array([
+ [ 1.5868459e-02, 1.8368837e-01, 1.8368837e-01, 1.5868459e-02 ],
+ [ 0. , 0. , 0. , 0. ],
+])
+
+LTPF_C3_X = np.array([
+
+ [ -3.4872147e+02, -3.2869651e+02, -3.0368708e+02, -2.7206929e+02,
+ -2.3135299e+02, -1.8746149e+02, -1.4271272e+02, -9.8455678e+01,
+ -4.8137684e+01, 2.0589588e-01, 4.5670854e+01, 8.5887062e+01,
+ 1.2485726e+02, 1.6126194e+02, 1.9191268e+02, 2.2387152e+02,
+ 2.4650629e+02, 2.6665533e+02, 2.8210563e+02, 2.9385531e+02,
+ 3.0042345e+02, 2.9898320e+02, 2.9792092e+02, 2.9201085e+02,
+ 2.8341711e+02, 2.7006923e+02, 2.5925000e+02, 2.4396424e+02,
+ 2.2871379e+02, 2.1604489e+02, 2.0086440e+02, 1.8158468e+02,
+ 1.6604772e+02, 1.4881816e+02, 1.3450578e+02, 1.1691585e+02,
+ 1.0011405e+02, 8.1066153e+01, 5.7608036e+01, 3.3232973e+01,
+ 8.7252186e+00, -1.9268859e+01, -5.0019465e+01, -7.8718920e+01,
+ -1.1264618e+02, -1.4558774e+02, -1.7907091e+02, -2.1353821e+02,
+ -2.4860083e+02, -2.7968268e+02, -3.0845126e+02, -3.3166214e+02,
+ -3.4854139e+02, -3.6210272e+02, -3.6311551e+02, -3.6538831e+02,
+ -3.5698782e+02, -3.4320560e+02, -3.2228293e+02, -2.9431070e+02,
+ -2.6126653e+02, -2.2161989e+02, -1.7770590e+02, -1.3258934e+02,
+ -8.8768668e+01, -4.1250510e+01, 4.8812815e+00, 4.8960277e+01,
+ 9.1265856e+01, 1.2722198e+02, 1.5854814e+02, 1.8841450e+02,
+ 2.1263776e+02, 2.3530944e+02, 2.5135346e+02, 2.6817644e+02,
+ 2.7730158e+02, 2.7972049e+02, 2.7893036e+02, 2.7638406e+02,
+ 2.6804826e+02, 2.6051672e+02, 2.4861891e+02, 2.3713159e+02,
+ 2.2260424e+02, 2.0911457e+02, 1.9338336e+02, 1.8071811e+02,
+ 1.6387353e+02, 1.5139501e+02, 1.3594276e+02, 1.2442513e+02,
+ 1.1022492e+02, 9.7036956e+01, 7.4818560e+01, 5.7999575e+01,
+ 3.1360863e+01, 8.7303630e+00, -1.6051537e+01, -4.5294499e+01,
+ -7.3824309e+01, -1.0455773e+02, -1.3439723e+02, -1.6704153e+02,
+ -1.9839956e+02, -2.3387826e+02, -2.6412575e+02, -2.9170423e+02,
+ -3.1531207e+02, -3.3274995e+02, -3.4693113e+02, -3.5369132e+02,
+ -3.5301724e+02, -3.4943527e+02, -3.3608402e+02, -3.1755446e+02,
+ -2.9205556e+02, -2.6071672e+02, -2.2432542e+02, -1.8738248e+02,
+ -1.4392604e+02, -1.0106545e+02, -5.5577429e+01, -9.8667562e+00,
+ 3.7353443e+01, 7.5303068e+01, 1.1105079e+02, 1.4264083e+02,
+ 1.7184174e+02, 1.9822361e+02, 2.2081903e+02, 2.4084291e+02,
+ 2.5643437e+02, 2.6758684e+02, 2.7445589e+02, 2.7569331e+02,
+ 2.7159104e+02, 2.6648908e+02, 2.5914969e+02, 2.4863883e+02,
+ 2.3470167e+02, 2.2613959e+02, 2.1126267e+02, 2.0090440e+02,
+ 1.8404815e+02, 1.6736836e+02, 1.5327263e+02, 1.3857671e+02,
+ 1.2564592e+02, 1.1183479e+02, 9.8674586e+01, 7.9462699e+01,
+ 6.1566145e+01, 3.4757509e+01, 9.1597341e+00, -1.6506764e+01,
+ -4.4310986e+01, -7.7716465e+01, -1.1113407e+02, -1.4150980e+02 ],
+
+ [ -1.6775203e+02, -2.0410277e+02, -2.4176001e+02, -2.7386652e+02,
+ -2.9629852e+02, -3.0908748e+02, -3.0195831e+02, -2.8578850e+02,
+ -2.6686979e+02, -2.6140403e+02, -2.6601879e+02, -2.7595293e+02,
+ -2.8053255e+02, -2.9088609e+02, -2.8340082e+02, -2.8587804e+02,
+ -2.5164112e+02, -2.1308294e+02, -1.5229837e+02, -8.7968057e+01,
+ -3.9965246e+01, 1.9682469e+01, 8.3439201e+01, 1.3071313e+02,
+ 2.0278676e+02, 2.2530998e+02, 2.4917273e+02, 2.2837462e+02,
+ 2.0851337e+02, 1.8379204e+02, 1.0597931e+02, 5.0251896e+01,
+ 5.3816342e+01, 1.9418724e+02, 3.6073746e+02, 4.9001894e+02,
+ 5.6206313e+02, 5.4551465e+02, 5.0418915e+02, 3.9875911e+02,
+ 2.9036149e+02, 2.1569487e+02, 1.2216776e+02, 5.6342202e+01,
+ 1.9881173e+01, -1.0527142e+01, -2.8641229e+01, -6.5396380e+01,
+ -2.2087227e+01, -1.9320385e+00, 9.9837180e+00, -1.2901176e+01,
+ -4.8912099e+01, -1.0229260e+02, -1.3236180e+02, -1.1357973e+02,
+ -1.6394336e+02, -2.0430337e+02, -2.3625105e+02, -2.7025726e+02,
+ -2.1302135e+02, -2.2632729e+02, -2.0952571e+02, -2.1427507e+02,
+ -2.5180218e+02, -2.9681097e+02, -3.2929367e+02, -3.2993365e+02,
+ -3.3630273e+02, -3.0716107e+02, -2.2776881e+02, -2.2007043e+02,
+ -1.7036950e+02, -1.6356561e+02, -1.0711820e+02, 3.8723772e+01,
+ 9.2665406e+01, 1.2719129e+02, 2.3419328e+02, 2.4827798e+02,
+ 2.2061102e+02, 1.4474493e+02, 1.0064081e+02, 9.5343023e+01,
+ 5.5501524e+01, 3.6218435e+00, -6.9277352e+01, -1.2309115e+01,
+ -2.9683737e+01, -1.1059060e+01, 1.2650129e+02, 2.8907139e+02,
+ 5.9646998e+02, 7.2219690e+02, 6.4274592e+02, 2.5572095e+02,
+ 8.9009716e+00, -1.6887796e+02, -5.4165018e+02, -8.8289542e+02,
+ -9.0816906e+02, 2.8400805e+02, 1.3941683e+03, 1.4288425e+03,
+ 1.0428507e+03, 6.0910516e+02, 4.9505488e+02, 5.1165385e+02,
+ -4.9324168e+01, -5.0538446e+02, -6.1278936e+02, -6.0237215e+02,
+ -1.0190721e+03, -1.3790932e+03, -1.3541381e+03, 7.7933615e+01,
+ 1.3253623e+03, 1.3970218e+03, 1.1115023e+03, 7.7044387e+02,
+ 5.1675398e+02, 2.7357534e+02, -1.1882263e+02, -3.6893899e+02,
+ -5.9907798e+02, -6.8538645e+02, -1.0290340e+03, -1.2093927e+03,
+ -1.3183905e+03, -6.4097534e+02, 7.8577340e+02, 1.3858651e+03,
+ 1.2575136e+03, 1.0978140e+03, 7.7239776e+02, 3.5047643e+02,
+ 1.3677282e+02, -2.9932975e+01, -3.3626785e+02, -6.8938845e+02,
+ -8.0039496e+02, -8.8267000e+02, -8.9787173e+02, -8.6951038e+02,
+ 4.6805939e+02, 1.7552178e+03, 1.5546574e+03, 1.1148179e+03,
+ 7.4606055e+02, 5.7001670e+02, 3.6944970e+02, 9.7838518e+01,
+ -1.1941272e+02, -4.1377871e+02, -7.6382784e+02, -8.4434380e+02,
+ -7.9151095e+02, -8.6493987e+02, -2.8343467e+02, 1.2284377e+03 ],
+
+])
+
+LTPF_C3_PREV = np.array([
+
+ [ 6.4066155e+01, 9.8702625e+01, 1.3788395e+02, 1.7357908e+02,
+ 2.0965843e+02, 2.3764314e+02, 2.6644923e+02, 2.9043075e+02,
+ 3.1194822e+02, 3.2482869e+02, 3.3339160e+02, 3.4071606e+02,
+ 3.4077768e+02, 3.3516446e+02, 3.2705459e+02, 3.1766371e+02,
+ 3.0450863e+02, 2.8884502e+02, 2.7626398e+02, 2.5687540e+02,
+ 2.3783751e+02, 2.1914457e+02, 1.9792827e+02, 1.7491941e+02,
+ 1.5135385e+02, 1.2210867e+02, 9.3873907e+01, 6.1133113e+01,
+ 2.5655472e+01, -9.0068272e+00, -4.6864087e+01, -8.5961652e+01,
+ -1.2549724e+02, -1.6396142e+02, -2.0212479e+02, -2.3817055e+02,
+ -2.7665292e+02, -3.0851152e+02, -3.4115267e+02, -3.6978674e+02,
+ -3.9095963e+02, -4.0758998e+02, -4.1787548e+02, -4.2041787e+02,
+ -4.1483578e+02, -4.0572811e+02, -3.8202738e+02, -3.5555284e+02,
+ -3.2171184e+02, -2.8408934e+02, -2.3936543e+02, -1.8996836e+02,
+ -1.4140617e+02, -9.0899975e+01, -4.2131433e+01, 5.1447212e+00,
+ 5.1259588e+01, 9.2032590e+01, 1.3108193e+02, 1.6957969e+02,
+ 2.0599062e+02, 2.3735997e+02, 2.6672423e+02, 2.9065678e+02,
+ 3.1149055e+02, 3.2543573e+02, 3.3604446e+02, 3.4053351e+02,
+ 3.4068048e+02, 3.3756977e+02, 3.3026320e+02, 3.2068706e+02,
+ 3.0912932e+02, 2.9328335e+02, 2.7625928e+02, 2.6245063e+02,
+ 2.4670232e+02, 2.2666582e+02, 2.0533576e+02, 1.8873190e+02,
+ 1.6715637e+02, 1.4420637e+02, 1.1629663e+02, 8.8561616e+01,
+ 5.8962789e+01, 2.5166894e+01, -1.1130553e+01, -4.5737395e+01,
+ -8.2162714e+01, -1.2346999e+02, -1.6150200e+02, -2.0028107e+02,
+ -2.3669696e+02, -2.7393564e+02, -3.0977094e+02, -3.4398480e+02,
+ -3.6896668e+02, -3.9241987e+02, -4.0955117e+02, -4.2052014e+02,
+ -4.2287410e+02, -4.1573504e+02, -4.0403021e+02, -3.8178373e+02,
+ -3.5516185e+02, -3.2075205e+02, -2.8058887e+02, -2.3403076e+02,
+ -1.8587624e+02, -1.3565255e+02, -8.4981034e+01, -3.4327765e+01,
+ 1.6122604e+01, 6.2803153e+01, 1.0703665e+02, 1.4333420e+02,
+ 1.8149169e+02, 2.1834576e+02, 2.4733100e+02, 2.7545243e+02,
+ 2.9756989e+02, 3.1498586e+02, 3.2836159e+02, 3.3505102e+02,
+ 3.3656005e+02, 3.3923920e+02, 3.3129967e+02, 3.2145289e+02,
+ 3.1074707e+02, 2.9901767e+02, 2.8311559e+02, 2.6682498e+02,
+ 2.4940742e+02, 2.3261497e+02, 2.1196627e+02, 1.9333406e+02,
+ 1.7509963e+02, 1.5279050e+02, 1.3109055e+02, 1.0449469e+02,
+ 7.8409595e+01, 4.9363873e+01, 1.7554459e+01, -1.5539732e+01,
+ -4.8805768e+01, -8.5198692e+01, -1.2189071e+02, -1.5886754e+02,
+ -1.9634205e+02, -2.3335312e+02, -2.7073502e+02, -3.0557489e+02,
+ -3.3663951e+02, -3.6449227e+02, -3.8546603e+02, -4.0164063e+02,
+ -4.1170176e+02, -4.1157567e+02, -4.0619410e+02, -3.9613725e+02 ],
+
+ [ -3.7147766e+02, -3.4548841e+02, -3.1333857e+02, -2.7463625e+02,
+ -2.2842732e+02, -1.8027124e+02, -1.3148070e+02, -8.3137241e+01,
+ -3.0054878e+01, 1.9883532e+01, 6.6714609e+01, 1.0807815e+02,
+ 1.4822202e+02, 1.8586131e+02, 2.1800420e+02, 2.5060047e+02,
+ 2.7401990e+02, 2.9513896e+02, 3.1106912e+02, 3.2286594e+02,
+ 3.2918272e+02, 3.2833211e+02, 3.2739842e+02, 3.2088124e+02,
+ 3.1147526e+02, 2.9799117e+02, 2.8657122e+02, 2.7043218e+02,
+ 2.5431668e+02, 2.3996550e+02, 2.2300791e+02, 2.0270053e+02,
+ 1.8568534e+02, 1.6689279e+02, 1.5012389e+02, 1.2962033e+02,
+ 1.0942755e+02, 8.6477433e+01, 5.9720239e+01, 3.1778371e+01,
+ 2.9431398e+00, -2.9247908e+01, -6.3765298e+01, -9.6917096e+01,
+ -1.3470119e+02, -1.7108334e+02, -2.0808704e+02, -2.4574024e+02,
+ -2.8326377e+02, -3.1633765e+02, -3.4671102e+02, -3.7097994e+02,
+ -3.8869922e+02, -4.0237282e+02, -4.0334704e+02, -4.0408504e+02,
+ -3.9385794e+02, -3.7723701e+02, -3.5253919e+02, -3.2150862e+02,
+ -2.8492979e+02, -2.4106826e+02, -1.9287257e+02, -1.4370111e+02,
+ -9.5563935e+01, -4.3545337e+01, 7.0713976e+00, 5.5117442e+01,
+ 1.0039302e+02, 1.3954207e+02, 1.7504613e+02, 2.0852764e+02,
+ 2.3658875e+02, 2.6248596e+02, 2.8111481e+02, 2.9971212e+02,
+ 3.1019868e+02, 3.1449414e+02, 3.1475549e+02, 3.1252800e+02,
+ 3.0472635e+02, 2.9675698e+02, 2.8382811e+02, 2.7136329e+02,
+ 2.5584249e+02, 2.4078158e+02, 2.2398280e+02, 2.0974116e+02,
+ 1.9071035e+02, 1.7568738e+02, 1.5790704e+02, 1.4374608e+02,
+ 1.2653380e+02, 1.0989392e+02, 8.5342354e+01, 6.5160001e+01,
+ 3.5365747e+01, 9.6994716e+00, -1.9148759e+01, -5.2247954e+01,
+ -8.4460390e+01, -1.1917021e+02, -1.5343168e+02, -1.9000568e+02,
+ -2.2535999e+02, -2.6422733e+02, -2.9746477e+02, -3.2794048e+02,
+ -3.5381425e+02, -3.7289983e+02, -3.8800620e+02, -3.9445315e+02,
+ -3.9341234e+02, -3.8871213e+02, -3.7329028e+02, -3.5219370e+02,
+ -3.2339521e+02, -2.8848818e+02, -2.4782613e+02, -2.0517168e+02,
+ -1.5630958e+02, -1.0872773e+02, -5.8413582e+01, -7.9029246e+00,
+ 4.3081069e+01, 8.5378547e+01, 1.2552492e+02, 1.6074903e+02,
+ 1.9342830e+02, 2.2272087e+02, 2.4784891e+02, 2.6963531e+02,
+ 2.8673587e+02, 2.9921346e+02, 3.0619842e+02, 3.0724158e+02,
+ 3.0343005e+02, 2.9800183e+02, 2.8972999e+02, 2.7822622e+02,
+ 2.6355926e+02, 2.5308771e+02, 2.3630848e+02, 2.2381546e+02,
+ 2.0555172e+02, 1.8801065e+02, 1.7231093e+02, 1.5597740e+02,
+ 1.4132322e+02, 1.2578292e+02, 1.1037371e+02, 8.8726457e+01,
+ 6.8198855e+01, 3.9334854e+01, 1.1725578e+01, -1.6214439e+01,
+ -4.7122569e+01, -8.2888237e+01, -1.1823402e+02, -1.5159407e+02 ],
+
+])
+
+LTPF_C3_TRANS = np.array([
+
+ -1.8246409e+02, -2.2173994e+02, -2.6085374e+02, -2.9483717e+02,
+ -3.2011835e+02, -3.3711584e+02, -3.3663215e+02, -3.2868626e+02,
+ -3.1677331e+02, -3.1352548e+02, -3.1534653e+02, -3.1872408e+02,
+ -3.1513281e+02, -3.1569554e+02, -2.9910316e+02, -2.9198409e+02,
+ -2.5148901e+02, -2.0982533e+02, -1.4838034e+02, -8.5301198e+01,
+ -3.6694674e+01, 2.3482066e+01, 8.5828448e+01, 1.3216759e+02,
+ 2.0172964e+02, 2.2393590e+02, 2.4953564e+02, 2.3256572e+02,
+ 2.1734484e+02, 1.9615122e+02, 1.2352168e+02, 7.1940230e+01,
+ 7.4762310e+01, 2.0724785e+02, 3.6354237e+02, 4.8584290e+02,
+ 5.5511323e+02, 5.3946449e+02, 5.0046673e+02, 3.9744659e+02,
+ 2.9036149e+02, 2.1569487e+02, 1.2216776e+02, 5.6342202e+01,
+ 1.9881173e+01, -1.0527142e+01, -2.8641229e+01, -6.5396380e+01,
+ -2.2087227e+01, -1.9320385e+00, 9.9837180e+00, -1.2901176e+01,
+ -4.8912099e+01, -1.0229260e+02, -1.3236180e+02, -1.1357973e+02,
+ -1.6394336e+02, -2.0430337e+02, -2.3625105e+02, -2.7025726e+02,
+ -2.1302135e+02, -2.2632729e+02, -2.0952571e+02, -2.1427507e+02,
+ -2.5180218e+02, -2.9681097e+02, -3.2929367e+02, -3.2993365e+02,
+ -3.3630273e+02, -3.0716107e+02, -2.2776881e+02, -2.2007043e+02,
+ -1.7036950e+02, -1.6356561e+02, -1.0711820e+02, 3.8723772e+01,
+ 9.2665406e+01, 1.2719129e+02, 2.3419328e+02, 2.4827798e+02,
+ 2.2061102e+02, 1.4474493e+02, 1.0064081e+02, 9.5343023e+01,
+ 5.5501524e+01, 3.6218435e+00, -6.9277352e+01, -1.2309115e+01,
+ -2.9683737e+01, -1.1059060e+01, 1.2650129e+02, 2.8907139e+02,
+ 5.9646998e+02, 7.2219690e+02, 6.4274592e+02, 2.5572095e+02,
+ 8.9009716e+00, -1.6887796e+02, -5.4165018e+02, -8.8289542e+02,
+ -9.0816906e+02, 2.8400805e+02, 1.3941683e+03, 1.4288425e+03,
+ 1.0428507e+03, 6.0910516e+02, 4.9505488e+02, 5.1165385e+02,
+ -4.9324168e+01, -5.0538446e+02, -6.1278936e+02, -6.0237215e+02,
+ -1.0190721e+03, -1.3790932e+03, -1.3541381e+03, 7.7933615e+01,
+ 1.3253623e+03, 1.3970218e+03, 1.1115023e+03, 7.7044387e+02,
+ 5.1675398e+02, 2.7357534e+02, -1.1882263e+02, -3.6893899e+02,
+ -5.9907798e+02, -6.8538645e+02, -1.0290340e+03, -1.2093927e+03,
+ -1.3183905e+03, -6.4097534e+02, 7.8577340e+02, 1.3858651e+03,
+ 1.2575136e+03, 1.0978140e+03, 7.7239776e+02, 3.5047643e+02,
+ 1.3677282e+02, -2.9932975e+01, -3.3626785e+02, -6.8938845e+02,
+ -8.0039496e+02, -8.8267000e+02, -8.9787173e+02, -8.6951038e+02,
+ 4.6805939e+02, 1.7552178e+03, 1.5546574e+03, 1.1148179e+03,
+ 7.4606055e+02, 5.7001670e+02, 3.6944970e+02, 9.7838518e+01,
+ -1.1941272e+02, -4.1377871e+02, -7.6382784e+02, -8.4434380e+02,
+ -7.9151095e+02, -8.6493987e+02, -2.8343467e+02, 1.2284377e+03,
+
+])
+
+LTPF_C4_NBITS = 320
+
+LTPF_C4_ACTIVE = np.array([ True, True ])
+LTPF_C4_PITCH_INDEX = np.array([ 56, 56 ])
+
+LTPF_C4_C_N = np.array([
+ [ 2.0480302e-01, 1.4271871e-01, -6.4036434e-03 ],
+ [ 2.0480302e-01, 1.4271871e-01, -6.4036434e-03 ],
+])
+
+LTPF_C4_C_D = np.array([
+ [ 1.5868459e-02, 1.8368837e-01, 1.8368837e-01, 1.5868459e-02 ],
+ [ 1.5868459e-02, 1.8368837e-01, 1.8368837e-01, 1.5868459e-02 ],
+])
+
+LTPF_C4_X = np.array([
+
+ [ -1.3212378e+02, 4.5530263e+00, 1.4615982e+02, 2.9071151e+02,
+ 4.2471908e+02, 5.4825306e+02, 6.6032559e+02, 7.5740827e+02,
+ 8.3891172e+02, 9.0995714e+02, 9.6747077e+02, 1.0121710e+03,
+ 1.0274871e+03, 1.0037721e+03, 9.3793010e+02, 8.2480912e+02,
+ 6.6687812e+02, 5.0610704e+02, 3.7535508e+02, 2.8417912e+02,
+ 2.3507950e+02, 2.2431573e+02, 2.3503665e+02, 2.5100781e+02,
+ 2.5591188e+02, 2.4573096e+02, 2.3732458e+02, 2.2379033e+02,
+ 2.0393082e+02, 1.7940329e+02, 1.5349002e+02, 1.2421970e+02,
+ 8.2607174e+01, 3.3890085e+01, -1.4919514e+01, -6.7050562e+01,
+ -1.2022717e+02, -1.7802094e+02, -2.3045847e+02, -2.7788664e+02,
+ -3.3683640e+02, -4.1806874e+02, -5.2071432e+02, -6.3745995e+02,
+ -7.6831195e+02, -8.9933303e+02, -1.0058396e+03, -1.0704297e+03,
+ -1.0883680e+03, -1.0715794e+03, -1.0235340e+03, -9.4781945e+02,
+ -8.5584778e+02, -7.4716794e+02, -6.2920874e+02, -5.0223965e+02,
+ -3.6316475e+02, -2.2074077e+02, -7.5442666e+01, 6.7658245e+01,
+ 2.0420074e+02, 3.3396592e+02, 4.4656898e+02, 5.4596637e+02,
+ 6.3808859e+02, 7.2787698e+02, 8.1472882e+02, 8.9279612e+02,
+ 9.5178350e+02, 9.7288475e+02, 9.4735790e+02, 8.8244167e+02,
+ 7.9508887e+02, 7.0282080e+02, 6.0598321e+02, 5.1640859e+02,
+ 4.3937674e+02, 3.7245496e+02, 3.2160255e+02, 2.8003421e+02,
+ 2.5119199e+02, 2.3495839e+02, 2.2200688e+02, 2.0973737e+02,
+ 1.9073208e+02, 1.6793312e+02, 1.4320783e+02, 1.1276855e+02,
+ 8.0839691e+01, 4.8429863e+01, 1.1662609e+01, -3.3424450e+01,
+ -7.9726479e+01, -1.2393767e+02, -1.7110449e+02, -2.1662821e+02,
+ -2.6310613e+02, -3.1774127e+02, -3.9885548e+02, -5.1583270e+02,
+ -6.4243905e+02, -7.6184139e+02, -8.6566023e+02, -9.4822201e+02,
+ -1.0112142e+03, -1.0437627e+03, -1.0457937e+03, -1.0207768e+03,
+ -9.6819885e+02, -8.9378058e+02, -7.9861844e+02, -6.8734848e+02,
+ -5.6329990e+02, -4.2840844e+02, -2.8589443e+02, -1.4101586e+02,
+ -5.6273423e-01, 1.3949815e+02, 2.7417238e+02, 4.0010557e+02,
+ 5.2193759e+02, 6.3439172e+02, 7.3810702e+02, 8.2658657e+02,
+ 8.9885978e+02, 9.5846967e+02, 9.8349123e+02, 9.6474177e+02,
+ 9.0987618e+02, 8.3178192e+02, 7.4721512e+02, 6.6076640e+02,
+ 5.7958128e+02, 5.0626404e+02, 4.3829495e+02, 3.7955641e+02,
+ 3.3400402e+02, 3.0012060e+02, 2.6635949e+02, 2.3180026e+02,
+ 1.9980913e+02, 1.7106449e+02, 1.4708346e+02, 1.1651799e+02,
+ 8.3457665e+01, 5.6291779e+01, 3.0698836e+01, 5.4712667e+00,
+ -2.9709210e+01, -7.0496428e+01, -1.0899206e+02, -1.5337912e+02,
+ -1.9940203e+02, -2.4464990e+02, -2.9496636e+02, -3.6218204e+02,
+ -4.5477003e+02, -5.6091604e+02, -6.6582484e+02, -7.5807547e+02 ],
+
+ [ -8.3474175e+02, -8.9039341e+02, -9.2355843e+02, -9.3729800e+02,
+ -9.2464041e+02, -8.9038579e+02, -8.3678014e+02, -7.6008712e+02,
+ -6.6935538e+02, -5.6422713e+02, -4.4941540e+02, -3.2822721e+02,
+ -1.9802065e+02, -6.6766936e+01, 6.3833225e+01, 1.9485046e+02,
+ 3.2069998e+02, 4.3761734e+02, 5.4460736e+02, 6.4521909e+02,
+ 7.4169295e+02, 8.2759672e+02, 8.9638366e+02, 9.3673025e+02,
+ 9.4669839e+02, 9.2302657e+02, 8.8064813e+02, 8.2833056e+02,
+ 7.6070809e+02, 6.9391450e+02, 6.2171679e+02, 5.4789771e+02,
+ 4.8160318e+02, 4.2010754e+02, 3.6391872e+02, 3.1081191e+02,
+ 2.6834464e+02, 2.2822565e+02, 1.8578653e+02, 1.5071546e+02,
+ 1.1735576e+02, 8.3222831e+01, 4.9624826e+01, 1.0744867e+01,
+ -2.5764012e+01, -6.4812135e+01, -1.0358083e+02, -1.4353059e+02,
+ -1.8297458e+02, -2.2359073e+02, -2.6775258e+02, -3.1656152e+02,
+ -3.7871430e+02, -4.4751491e+02, -5.2485941e+02, -6.0299909e+02,
+ -6.8515536e+02, -7.6401821e+02, -8.2770748e+02, -8.7387481e+02,
+ -8.9915932e+02, -9.0643654e+02, -8.8914063e+02, -8.5144521e+02,
+ -7.9103639e+02, -7.1441804e+02, -6.2692990e+02, -5.2729939e+02,
+ -4.2275301e+02, -3.0657474e+02, -1.8688744e+02, -6.1633756e+01,
+ 5.8686296e+01, 1.8250335e+02, 3.0377201e+02, 4.1978552e+02,
+ 5.3054960e+02, 6.2835118e+02, 7.2035468e+02, 7.9934358e+02,
+ 8.5642737e+02, 8.9765907e+02, 9.2069014e+02, 9.1957966e+02,
+ 8.9145864e+02, 8.3848660e+02, 7.7429387e+02, 7.0401776e+02,
+ 6.3210907e+02, 5.6076246e+02, 4.9172735e+02, 4.2473574e+02,
+ 3.6317680e+02, 3.0715534e+02, 2.5275264e+02, 2.0664538e+02,
+ 1.6042746e+02, 1.1820978e+02, 7.3335304e+01, 3.4381568e+01,
+ -5.8542117e+00, -4.4553111e+01, -8.3479478e+01, -1.2048090e+02,
+ -1.6116063e+02, -2.0192831e+02, -2.4373220e+02, -2.8256043e+02,
+ -3.2919802e+02, -3.7322793e+02, -4.2010268e+02, -4.7218497e+02,
+ -5.3461522e+02, -6.1386549e+02, -6.9152470e+02, -7.6738453e+02,
+ -8.2527123e+02, -8.6158674e+02, -8.7895938e+02, -8.7597504e+02,
+ -8.5108741e+02, -8.0480220e+02, -7.4250154e+02, -6.5876002e+02,
+ -5.6356029e+02, -4.5524527e+02, -3.4038894e+02, -2.2360514e+02,
+ -1.0268552e+02, 2.5676655e+01, 1.5166378e+02, 2.7540954e+02,
+ 3.9465179e+02, 5.0881759e+02, 6.1514014e+02, 7.1241132e+02,
+ 7.9504576e+02, 8.7166197e+02, 9.3226594e+02, 9.7438372e+02,
+ 9.8472937e+02, 9.6485548e+02, 9.1860685e+02, 8.5256605e+02,
+ 7.8008367e+02, 7.0149395e+02, 6.2054247e+02, 5.4108956e+02,
+ 4.6123090e+02, 3.8599064e+02, 3.1521582e+02, 2.4589274e+02,
+ 1.8211975e+02, 1.3163470e+02, 8.4985461e+01, 3.6873046e+01,
+ -6.0437124e+00, -4.8770494e+01, -8.4128492e+01, -1.2196451e+02 ],
+
+])
+
+LTPF_C4_PREV = np.array([
+
+ [ 8.5827694e+02, 8.3064489e+02, 8.0499625e+02, 7.8056066e+02,
+ 7.6744901e+02, 7.5611316e+02, 7.1123694e+02, 6.4234457e+02,
+ 5.7975881e+02, 5.3276775e+02, 5.0354201e+02, 4.6493297e+02,
+ 4.2651511e+02, 3.8147439e+02, 3.2876260e+02, 2.7004720e+02,
+ 2.0149312e+02, 1.2434150e+02, 4.6683685e+01, -2.4488830e+01,
+ -9.4758661e+01, -1.6910076e+02, -2.4454068e+02, -3.2272819e+02,
+ -4.1153117e+02, -5.2406430e+02, -6.6312995e+02, -7.9501146e+02,
+ -9.1517707e+02, -1.0195879e+03, -1.1003671e+03, -1.1506760e+03,
+ -1.1718109e+03, -1.1569278e+03, -1.1251298e+03, -1.0925962e+03,
+ -1.0572755e+03, -1.0074938e+03, -9.3394117e+02, -8.3773785e+02,
+ -7.2203590e+02, -5.9088086e+02, -4.5612949e+02, -3.2040519e+02,
+ -1.7104088e+02, -2.9232508e+01, 1.0254422e+02, 2.3645451e+02,
+ 3.6931210e+02, 4.8954097e+02, 5.9869449e+02, 7.0325516e+02,
+ 7.9700038e+02, 8.6886012e+02, 9.1083211e+02, 9.2243956e+02,
+ 9.0940850e+02, 8.7320143e+02, 8.2061884e+02, 7.7544913e+02,
+ 7.3767280e+02, 7.0507470e+02, 6.8093384e+02, 6.6014067e+02,
+ 6.3137283e+02, 6.0264808e+02, 5.6924398e+02, 5.4487108e+02,
+ 5.1295321e+02, 4.8260718e+02, 4.4645113e+02, 4.0584256e+02,
+ 3.5619699e+02, 2.8935939e+02, 2.1760106e+02, 1.4449684e+02,
+ 7.4653166e+01, -1.4735621e+00, -8.3781827e+01, -1.5582846e+02,
+ -2.3783590e+02, -3.2355910e+02, -4.0747488e+02, -5.0371066e+02,
+ -6.0048961e+02, -7.0726549e+02, -8.2713764e+02, -9.4294256e+02,
+ -1.0401191e+03, -1.1242695e+03, -1.1843296e+03, -1.1977911e+03,
+ -1.1759957e+03, -1.1382443e+03, -1.0869538e+03, -1.0150254e+03,
+ -9.2445459e+02, -8.2418678e+02, -7.1231843e+02, -5.8566805e+02,
+ -4.4749524e+02, -3.2163393e+02, -1.9483077e+02, -6.6146712e+01,
+ 7.2606186e+01, 2.1709089e+02, 3.6141116e+02, 4.9774327e+02,
+ 6.2102585e+02, 7.3301494e+02, 8.2884523e+02, 9.1772806e+02,
+ 9.8287592e+02, 1.0258870e+03, 1.0350466e+03, 1.0124387e+03,
+ 9.5526828e+02, 8.4870459e+02, 6.9698370e+02, 5.5384197e+02,
+ 4.7329566e+02, 4.4187783e+02, 4.2164793e+02, 4.0723567e+02,
+ 4.0287348e+02, 3.9294225e+02, 3.8536364e+02, 3.6737694e+02,
+ 3.4038387e+02, 3.2024898e+02, 2.9202545e+02, 2.5623304e+02,
+ 2.0059931e+02, 1.4494932e+02, 8.7316562e+01, 2.0208470e+01,
+ -5.1106062e+01, -1.0972390e+02, -1.7160643e+02, -2.3635682e+02,
+ -3.0057986e+02, -3.6841959e+02, -4.5812030e+02, -5.5409463e+02,
+ -6.5667832e+02, -7.6531178e+02, -9.0843842e+02, -1.0761546e+03,
+ -1.2069858e+03, -1.2737779e+03, -1.2929641e+03, -1.2624172e+03,
+ -1.2008239e+03, -1.1122508e+03, -9.9807662e+02, -8.7056340e+02,
+ -7.3753241e+02, -6.0499387e+02, -4.6029956e+02, -3.2128673e+02 ],
+
+ [ -1.8675929e+02, -4.2406693e+01, 1.0644289e+02, 2.5996083e+02,
+ 4.0591306e+02, 5.4343259e+02, 6.6906247e+02, 7.7899810e+02,
+ 8.7298704e+02, 9.5506440e+02, 1.0209952e+03, 1.0688758e+03,
+ 1.0833988e+03, 1.0572928e+03, 9.8779757e+02, 8.6895392e+02,
+ 7.0635769e+02, 5.4680902e+02, 4.2601966e+02, 3.4987333e+02,
+ 3.1179292e+02, 3.0331866e+02, 3.0951274e+02, 3.1789860e+02,
+ 3.1563910e+02, 3.0013119e+02, 2.8624618e+02, 2.6714149e+02,
+ 2.4150830e+02, 2.0837106e+02, 1.7059521e+02, 1.2855863e+02,
+ 7.5094806e+01, 1.5176971e+01, -4.3358321e+01, -1.0315083e+02,
+ -1.6398964e+02, -2.2910287e+02, -2.9037721e+02, -3.5326931e+02,
+ -4.3186627e+02, -5.2797253e+02, -6.4097239e+02, -7.7021355e+02,
+ -9.1916034e+02, -1.0635912e+03, -1.1696907e+03, -1.2240756e+03,
+ -1.2277996e+03, -1.1942767e+03, -1.1287017e+03, -1.0350001e+03,
+ -9.2445100e+02, -7.9889645e+02, -6.6691580e+02, -5.2684803e+02,
+ -3.7726996e+02, -2.2821747e+02, -7.6317887e+01, 7.6079467e+01,
+ 2.2531300e+02, 3.6948450e+02, 4.9788068e+02, 6.1407961e+02,
+ 7.2081446e+02, 8.2045742e+02, 9.1242924e+02, 9.9212633e+02,
+ 1.0508862e+03, 1.0718419e+03, 1.0464386e+03, 9.7937941e+02,
+ 8.8142794e+02, 7.6477603e+02, 6.3740319e+02, 5.2412010e+02,
+ 4.3571759e+02, 3.6988854e+02, 3.2884698e+02, 3.0173096e+02,
+ 2.8691049e+02, 2.7882926e+02, 2.6731147e+02, 2.5356111e+02,
+ 2.3340364e+02, 2.0894382e+02, 1.8071643e+02, 1.4579425e+02,
+ 1.0855560e+02, 6.8052759e+01, 2.0813765e+01, -3.3555159e+01,
+ -8.7826734e+01, -1.4078458e+02, -1.9733530e+02, -2.5226649e+02,
+ -3.0811893e+02, -3.7371017e+02, -4.6559419e+02, -5.8909591e+02,
+ -7.2198295e+02, -8.5479624e+02, -9.7874703e+02, -1.0795937e+03,
+ -1.1503967e+03, -1.1796433e+03, -1.1713652e+03, -1.1317595e+03,
+ -1.0619895e+03, -9.6960460e+02, -8.5726543e+02, -7.3060563e+02,
+ -5.9289544e+02, -4.4495754e+02, -2.9059997e+02, -1.3479531e+02,
+ 1.7757467e+01, 1.7012020e+02, 3.1647370e+02, 4.5257127e+02,
+ 5.8125188e+02, 6.9866277e+02, 8.0708027e+02, 9.0151273e+02,
+ 9.8106784e+02, 1.0459462e+03, 1.0733030e+03, 1.0542555e+03,
+ 9.9525660e+02, 9.0830183e+02, 8.0934326e+02, 7.0399220e+02,
+ 6.0377076e+02, 5.1638905e+02, 4.4150465e+02, 3.8256291e+02,
+ 3.4048809e+02, 3.1118639e+02, 2.8406392e+02, 2.5713040e+02,
+ 2.3131764e+02, 2.0600503e+02, 1.8197113e+02, 1.5035197e+02,
+ 1.1569230e+02, 8.4266914e+01, 5.1996878e+01, 1.7843797e+01,
+ -2.6863170e+01, -7.5983644e+01, -1.2245636e+02, -1.7436828e+02,
+ -2.2708180e+02, -2.7906654e+02, -3.3755256e+02, -4.1588336e+02,
+ -5.2295173e+02, -6.4523634e+02, -7.6683613e+02, -8.7677439e+02 ],
+
+])
+
+LTPF_C4_TRANS = np.array([
+
+ -9.6976885e+02, -1.0376330e+03, -1.0764010e+03, -1.0872965e+03,
+ -1.0660439e+03, -1.0190108e+03, -9.4899438e+02, -8.5471701e+02,
+ -7.4561708e+02, -6.2178553e+02, -4.8798080e+02, -3.4713910e+02,
+ -1.9841833e+02, -5.0343781e+01, 9.6414723e+01, 2.4225179e+02,
+ 3.8080735e+02, 5.0947979e+02, 6.2776176e+02, 7.3826963e+02,
+ 8.4169803e+02, 9.3159353e+02, 1.0031138e+03, 1.0438329e+03,
+ 1.0480614e+03, 1.0127914e+03, 9.5385188e+02, 8.8138762e+02,
+ 7.9431025e+02, 7.0979394e+02, 6.2416163e+02, 5.4300509e+02,
+ 4.7372434e+02, 4.1360311e+02, 3.6279724e+02, 3.1673275e+02,
+ 2.7937838e+02, 2.4267574e+02, 2.0418215e+02, 1.7211796e+02,
+ 1.3914947e+02, 1.0348883e+02, 6.8276707e+01, 2.9143910e+01,
+ -7.9633499e+00, -4.9829988e+01, -9.3834050e+01, -1.3941156e+02,
+ -1.8501204e+02, -2.3271716e+02, -2.8327412e+02, -3.3841588e+02,
+ -4.0881202e+02, -4.9188847e+02, -5.8927352e+02, -6.8905431e+02,
+ -7.8967502e+02, -8.8144454e+02, -9.5326854e+02, -1.0026317e+03,
+ -1.0264190e+03, -1.0268593e+03, -9.9874748e+02, -9.4795333e+02,
+ -8.7252905e+02, -7.7954835e+02, -6.7411996e+02, -5.5559866e+02,
+ -4.3134824e+02, -2.9558412e+02, -1.5723885e+02, -1.5143571e+01,
+ 1.2171974e+02, 2.6041913e+02, 3.9322892e+02, 5.1828299e+02,
+ 6.3629063e+02, 7.4159801e+02, 8.3990996e+02, 9.2215495e+02,
+ 9.7897443e+02, 1.0129522e+03, 1.0197564e+03, 9.9746243e+02,
+ 9.4932784e+02, 8.7962855e+02, 8.0193420e+02, 7.2094920e+02,
+ 6.4030858e+02, 5.6344020e+02, 4.9240203e+02, 4.2631986e+02,
+ 3.6714651e+02, 3.1424334e+02, 2.6363836e+02, 2.1946532e+02,
+ 1.7487874e+02, 1.3448581e+02, 9.0857113e+01, 5.1852661e+01,
+ 1.0318345e+01, -3.0189483e+01, -7.1704052e+01, -1.1290529e+02,
+ -1.5806523e+02, -2.0311837e+02, -2.4946754e+02, -2.9428673e+02,
+ -3.4738868e+02, -4.0117413e+02, -4.6307505e+02, -5.3393190e+02,
+ -6.1557536e+02, -7.0983150e+02, -7.9873811e+02, -8.8091592e+02,
+ -9.4071232e+02, -9.7639817e+02, -9.9018818e+02, -9.8005670e+02,
+ -9.4511932e+02, -8.8673987e+02, -8.1023192e+02, -7.1271293e+02,
+ -6.0397885e+02, -4.8247591e+02, -3.5415373e+02, -2.2240894e+02,
+ -8.6345911e+01, 5.4855371e+01, 1.9247458e+02, 3.2774740e+02,
+ 4.5715456e+02, 5.8013934e+02, 6.9372155e+02, 7.9720836e+02,
+ 8.8545637e+02, 9.6285451e+02, 1.0187327e+03, 1.0521050e+03,
+ 1.0516389e+03, 1.0206935e+03, 9.6358799e+02, 8.8842240e+02,
+ 8.0838051e+02, 7.2366647e+02, 6.3870123e+02, 5.5707357e+02,
+ 4.7704505e+02, 4.0312802e+02, 3.3463611e+02, 2.6847649e+02,
+ 2.0824825e+02, 1.5901226e+02, 1.1171069e+02, 6.3026014e+01,
+ 1.8987746e+01, -2.5300684e+01, -6.3942070e+01, -1.0563596e+02,
+
+])
+
+LTPF_C5_NBITS = 320
+
+LTPF_C5_ACTIVE = np.array([ True, True ])
+LTPF_C5_PITCH_INDEX = np.array([ 56, 52 ])
+
+LTPF_C5_C_N = np.array([
+ [ 2.0480302e-01, 1.4271871e-01, -6.4036434e-03 ],
+ [ 2.0480302e-01, 1.4271871e-01, -6.4036434e-03 ],
+])
+
+LTPF_C5_C_D = np.array([
+ [ 1.5868459e-02, 1.8368837e-01, 1.8368837e-01, 1.5868459e-02 ],
+ [ 4.2799674e-02, 2.2003000e-01, 1.3427625e-01, 2.6795433e-03 ],
+])
+
+LTPF_C5_X = np.array([
+
+ [ -1.6060766e+02, -1.9568387e+02, -2.3100280e+02, -2.6630342e+02,
+ -3.0336764e+02, -3.3854889e+02, -3.7043669e+02, -4.1163573e+02,
+ -4.5567039e+02, -5.1558927e+02, -5.7814485e+02, -6.4080974e+02,
+ -6.9798700e+02, -7.4456362e+02, -7.7654511e+02, -7.9319453e+02,
+ -7.9402247e+02, -7.7652860e+02, -7.4572416e+02, -6.9989705e+02,
+ -6.3841065e+02, -5.6041492e+02, -4.6954673e+02, -3.7010557e+02,
+ -2.6541886e+02, -1.5525665e+02, -4.1036675e+01, 7.7898304e+01,
+ 1.9450287e+02, 3.0691788e+02, 4.1560715e+02, 5.1731671e+02,
+ 6.1122047e+02, 6.9593032e+02, 7.7071271e+02, 8.3246711e+02,
+ 8.7294256e+02, 8.9535004e+02, 8.9058119e+02, 8.6785095e+02,
+ 8.2896133e+02, 7.8301121e+02, 7.2447207e+02, 6.6383224e+02,
+ 5.9764845e+02, 5.3040514e+02, 4.6518541e+02, 3.9659186e+02,
+ 3.2746766e+02, 2.6753027e+02, 2.0739840e+02, 1.4677357e+02,
+ 9.5287069e+01, 4.7197825e+01, -1.1700140e+00, -4.9161682e+01,
+ -9.6726950e+01, -1.4038011e+02, -1.8662421e+02, -2.2897297e+02,
+ -2.6864070e+02, -3.1060300e+02, -3.4908047e+02, -3.8903634e+02,
+ -4.3354889e+02, -4.7982553e+02, -5.3003184e+02, -5.8409985e+02,
+ -6.3676286e+02, -6.8405252e+02, -7.2580553e+02, -7.5743871e+02,
+ -7.7706979e+02, -7.8082023e+02, -7.7270174e+02, -7.4653280e+02,
+ -7.1067906e+02, -6.5596456e+02, -5.8829707e+02, -5.0656026e+02,
+ -4.1202861e+02, -3.1175500e+02, -2.0302114e+02, -9.4710595e+01,
+ 2.0375247e+01, 1.3270062e+02, 2.4243959e+02, 3.5297406e+02,
+ 4.5553582e+02, 5.5590475e+02, 6.4792544e+02, 7.2690018e+02,
+ 7.9536436e+02, 8.5008231e+02, 8.8455109e+02, 9.0442411e+02,
+ 8.9923508e+02, 8.7803657e+02, 8.3884819e+02, 7.8786430e+02,
+ 7.2427475e+02, 6.5372622e+02, 5.8223046e+02, 5.0499317e+02,
+ 4.2757252e+02, 3.4979799e+02, 2.7384122e+02, 2.0202195e+02,
+ 1.3245127e+02, 6.9157310e+01, 1.0836031e+01, -5.0190037e+01,
+ -1.0459364e+02, -1.5805356e+02, -2.0733214e+02, -2.4766726e+02,
+ -2.9312137e+02, -3.3816241e+02, -3.7627128e+02, -4.1399424e+02,
+ -4.4836893e+02, -4.8327539e+02, -5.1189667e+02, -5.4560547e+02,
+ -5.8121896e+02, -6.1491595e+02, -6.4841741e+02, -6.7347617e+02,
+ -6.9479054e+02, -7.0418229e+02, -7.0192552e+02, -6.8320863e+02,
+ -6.5899253e+02, -6.2202504e+02, -5.7186005e+02, -5.1046639e+02,
+ -4.4158751e+02, -3.6145704e+02, -2.7098565e+02, -1.7538139e+02,
+ -7.6006538e+01, 2.3722024e+01, 1.2888233e+02, 2.3123425e+02,
+ 3.3082160e+02, 4.2819177e+02, 5.1739280e+02, 6.0102219e+02,
+ 6.7529473e+02, 7.3951297e+02, 8.0008252e+02, 8.4203459e+02,
+ 8.6655983e+02, 8.6963556e+02, 8.5619100e+02, 8.2481263e+02,
+ 7.8075652e+02, 7.2216895e+02, 6.6035959e+02, 5.8959592e+02 ],
+
+ [ 5.1338681e+02, 4.3458985e+02, 3.6021867e+02, 2.8040781e+02,
+ 2.0424899e+02, 1.3450352e+02, 6.6513343e+01, 5.6705127e+00,
+ -5.2746410e+01, -1.1038385e+02, -1.6030998e+02, -2.0583244e+02,
+ -2.4887172e+02, -2.9195508e+02, -3.2720109e+02, -3.6021736e+02,
+ -3.9187844e+02, -4.2450350e+02, -4.5121148e+02, -4.8051913e+02,
+ -5.0679429e+02, -5.3473222e+02, -5.6274008e+02, -5.8904566e+02,
+ -6.1354818e+02, -6.2864496e+02, -6.3771702e+02, -6.3780508e+02,
+ -6.2690341e+02, -6.0523722e+02, -5.7468865e+02, -5.3607922e+02,
+ -4.8568411e+02, -4.2700735e+02, -3.5998795e+02, -2.8215398e+02,
+ -2.0120100e+02, -1.1187382e+02, -2.5873841e+01, 6.7900858e+01,
+ 1.6266005e+02, 2.5147024e+02, 3.4066102e+02, 4.2711439e+02,
+ 5.0521368e+02, 5.8027967e+02, 6.4926123e+02, 7.0606425e+02,
+ 7.5197499e+02, 7.7936955e+02, 7.9241574e+02, 7.9273830e+02,
+ 7.7226162e+02, 7.4318941e+02, 6.9912979e+02, 6.4987144e+02,
+ 5.8935287e+02, 5.2867427e+02, 4.5818050e+02, 3.9091836e+02,
+ 3.1175882e+02, 2.4316163e+02, 1.6901936e+02, 1.0131712e+02,
+ 4.0884705e+01, -1.8284360e+01, -7.2463773e+01, -1.2615956e+02,
+ -1.7449474e+02, -2.1740936e+02, -2.5946712e+02, -2.9956841e+02,
+ -3.3765147e+02, -3.6878225e+02, -4.0090001e+02, -4.3495156e+02,
+ -4.6061972e+02, -4.8952939e+02, -5.1712969e+02, -5.4061916e+02,
+ -5.6432757e+02, -5.8583512e+02, -5.9997738e+02, -6.0321240e+02,
+ -6.0215834e+02, -5.9411694e+02, -5.7827835e+02, -5.5352370e+02,
+ -5.2218352e+02, -4.8118496e+02, -4.3153207e+02, -3.7290541e+02,
+ -3.0763879e+02, -2.3045577e+02, -1.5030005e+02, -6.8343251e+01,
+ 1.9827505e+01, 1.0879534e+02, 2.0178224e+02, 2.8957061e+02,
+ 3.7779733e+02, 4.6428381e+02, 5.4088918e+02, 6.1377535e+02,
+ 6.8124334e+02, 7.3734864e+02, 7.7681316e+02, 8.0293170e+02,
+ 8.0890279e+02, 8.0620381e+02, 7.8580399e+02, 7.5204050e+02,
+ 7.1105755e+02, 6.5621411e+02, 5.9523050e+02, 5.2862471e+02,
+ 4.5293754e+02, 3.7743682e+02, 3.0188947e+02, 2.2243974e+02,
+ 1.4611001e+02, 6.9741588e+01, 3.0745399e+00, -6.6469812e+01,
+ -1.2845539e+02, -1.8845561e+02, -2.4293629e+02, -2.9314084e+02,
+ -3.3894702e+02, -3.8275365e+02, -4.2041853e+02, -4.5718992e+02,
+ -4.8545538e+02, -5.1088490e+02, -5.3523663e+02, -5.5122371e+02,
+ -5.7210009e+02, -5.8455365e+02, -5.9877467e+02, -6.0919241e+02,
+ -6.1143839e+02, -6.0342076e+02, -5.8730343e+02, -5.6903506e+02,
+ -5.3921882e+02, -5.0539402e+02, -4.6156875e+02, -4.1089541e+02,
+ -3.4967700e+02, -2.8252157e+02, -2.1092501e+02, -1.3135475e+02,
+ -4.8131277e+01, 3.4353741e+01, 1.2201908e+02, 2.0824054e+02,
+ 2.9606295e+02, 3.8043837e+02, 4.5867136e+02, 5.3182302e+02 ],
+
+])
+
+LTPF_C5_PREV = np.array([
+
+ [ -9.6976885e+02, -1.0376330e+03, -1.0764010e+03, -1.0872965e+03,
+ -1.0660439e+03, -1.0190108e+03, -9.4899438e+02, -8.5471701e+02,
+ -7.4561708e+02, -6.2178553e+02, -4.8798080e+02, -3.4713910e+02,
+ -1.9841833e+02, -5.0343781e+01, 9.6414723e+01, 2.4225179e+02,
+ 3.8080735e+02, 5.0947979e+02, 6.2776176e+02, 7.3826963e+02,
+ 8.4169803e+02, 9.3159353e+02, 1.0031138e+03, 1.0438329e+03,
+ 1.0480614e+03, 1.0127914e+03, 9.5385188e+02, 8.8138762e+02,
+ 7.9431025e+02, 7.0979394e+02, 6.2416163e+02, 5.4300509e+02,
+ 4.7372434e+02, 4.1360311e+02, 3.6279724e+02, 3.1673275e+02,
+ 2.7937838e+02, 2.4267574e+02, 2.0418215e+02, 1.7211796e+02,
+ 1.3914947e+02, 1.0348883e+02, 6.8276707e+01, 2.9143910e+01,
+ -7.9633499e+00, -4.9829988e+01, -9.3834050e+01, -1.3941156e+02,
+ -1.8501204e+02, -2.3271716e+02, -2.8327412e+02, -3.3841588e+02,
+ -4.0881202e+02, -4.9188847e+02, -5.8927352e+02, -6.8905431e+02,
+ -7.8967502e+02, -8.8144454e+02, -9.5326854e+02, -1.0026317e+03,
+ -1.0264190e+03, -1.0268593e+03, -9.9874748e+02, -9.4795333e+02,
+ -8.7252905e+02, -7.7954835e+02, -6.7411996e+02, -5.5559866e+02,
+ -4.3134824e+02, -2.9558412e+02, -1.5723885e+02, -1.5143571e+01,
+ 1.2171974e+02, 2.6041913e+02, 3.9322892e+02, 5.1828299e+02,
+ 6.3629063e+02, 7.4159801e+02, 8.3990996e+02, 9.2215495e+02,
+ 9.7897443e+02, 1.0129522e+03, 1.0197564e+03, 9.9746243e+02,
+ 9.4932784e+02, 8.7962855e+02, 8.0193420e+02, 7.2094920e+02,
+ 6.4030858e+02, 5.6344020e+02, 4.9240203e+02, 4.2631986e+02,
+ 3.6714651e+02, 3.1424334e+02, 2.6363836e+02, 2.1946532e+02,
+ 1.7487874e+02, 1.3448581e+02, 9.0857113e+01, 5.1852661e+01,
+ 1.0318345e+01, -3.0189483e+01, -7.1704052e+01, -1.1290529e+02,
+ -1.5806523e+02, -2.0311837e+02, -2.4946754e+02, -2.9428673e+02,
+ -3.4738868e+02, -4.0117413e+02, -4.6307505e+02, -5.3393190e+02,
+ -6.1557536e+02, -7.0983150e+02, -7.9873811e+02, -8.8091592e+02,
+ -9.4071232e+02, -9.7639817e+02, -9.9018818e+02, -9.8005670e+02,
+ -9.4511932e+02, -8.8673987e+02, -8.1023192e+02, -7.1271293e+02,
+ -6.0397885e+02, -4.8247591e+02, -3.5415373e+02, -2.2240894e+02,
+ -8.6345911e+01, 5.4855371e+01, 1.9247458e+02, 3.2774740e+02,
+ 4.5715456e+02, 5.8013934e+02, 6.9372155e+02, 7.9720836e+02,
+ 8.8545637e+02, 9.6285451e+02, 1.0187327e+03, 1.0521050e+03,
+ 1.0516389e+03, 1.0206935e+03, 9.6358799e+02, 8.8842240e+02,
+ 8.0838051e+02, 7.2366647e+02, 6.3870123e+02, 5.5707357e+02,
+ 4.7704505e+02, 4.0312802e+02, 3.3463611e+02, 2.6847649e+02,
+ 2.0824825e+02, 1.5901226e+02, 1.1171069e+02, 6.3026014e+01,
+ 1.8987746e+01, -2.5300684e+01, -6.3942070e+01, -1.0563596e+02 ],
+
+ [ -1.4774474e+02, -1.8760166e+02, -2.2888898e+02, -2.7036124e+02,
+ -3.1332685e+02, -3.5581512e+02, -3.9771599e+02, -4.4936892e+02,
+ -5.0524457e+02, -5.7736164e+02, -6.5368200e+02, -7.3121324e+02,
+ -8.0200835e+02, -8.5934306e+02, -8.9755526e+02, -9.1640499e+02,
+ -9.1557588e+02, -8.9266707e+02, -8.5215743e+02, -7.9312106e+02,
+ -7.1595184e+02, -6.2138325e+02, -5.1398723e+02, -3.9767506e+02,
+ -2.7618028e+02, -1.4941349e+02, -1.8433316e+01, 1.1606930e+02,
+ 2.4697130e+02, 3.7323736e+02, 4.9468012e+02, 6.0791740e+02,
+ 7.1199453e+02, 8.0485505e+02, 8.8578958e+02, 9.5117733e+02,
+ 9.9264372e+02, 1.0115211e+03, 9.9864359e+02, 9.6401858e+02,
+ 9.1024930e+02, 8.4835436e+02, 7.7530833e+02, 7.0141455e+02,
+ 6.2384959e+02, 5.4721968e+02, 4.7387003e+02, 3.9972348e+02,
+ 3.2726546e+02, 2.6394537e+02, 2.0233246e+02, 1.4286080e+02,
+ 9.1074446e+01, 4.1308373e+01, -8.2303699e+00, -5.6391830e+01,
+ -1.0380366e+02, -1.4867461e+02, -1.9589518e+02, -2.3948198e+02,
+ -2.8179404e+02, -3.2661184e+02, -3.6849411e+02, -4.1204691e+02,
+ -4.6073272e+02, -5.1299590e+02, -5.7214182e+02, -6.3765069e+02,
+ -7.0266168e+02, -7.6246325e+02, -8.1462585e+02, -8.5309773e+02,
+ -8.7583931e+02, -8.7977551e+02, -8.6820607e+02, -8.3598008e+02,
+ -7.9127858e+02, -7.2555633e+02, -6.4513927e+02, -5.4928065e+02,
+ -4.4082024e+02, -3.2665281e+02, -2.0436663e+02, -8.1707251e+01,
+ 4.7901921e+01, 1.7432524e+02, 2.9759562e+02, 4.1992512e+02,
+ 5.3317251e+02, 6.4237470e+02, 7.4113789e+02, 8.2606130e+02,
+ 8.9883116e+02, 9.5428904e+02, 9.8624536e+02, 9.9869004e+02,
+ 9.8266888e+02, 9.4925619e+02, 8.9813116e+02, 8.3623319e+02,
+ 7.6348823e+02, 6.8594085e+02, 6.0808870e+02, 5.2646492e+02,
+ 4.4600650e+02, 3.6561691e+02, 2.8872526e+02, 2.1691496e+02,
+ 1.4728773e+02, 8.4221474e+01, 2.6048470e+01, -3.4388207e+01,
+ -8.8802146e+01, -1.4299353e+02, -1.9336320e+02, -2.3710707e+02,
+ -2.8587475e+02, -3.3270152e+02, -3.7422945e+02, -4.1636455e+02,
+ -4.5573665e+02, -4.9726692e+02, -5.3543762e+02, -5.8065815e+02,
+ -6.2910888e+02, -6.7690028e+02, -7.2375327e+02, -7.6132305e+02,
+ -7.9286869e+02, -8.0958989e+02, -8.1191872e+02, -7.9586469e+02,
+ -7.7057333e+02, -7.2915594e+02, -6.7231474e+02, -6.0134288e+02,
+ -5.1986758e+02, -4.2496645e+02, -3.1966315e+02, -2.0893647e+02,
+ -9.4117050e+01, 2.1901801e+01, 1.4286090e+02, 2.5974483e+02,
+ 3.7391931e+02, 4.8475194e+02, 5.8679531e+02, 6.8253551e+02,
+ 7.6686124e+02, 8.3927651e+02, 9.0416036e+02, 9.4669654e+02,
+ 9.6938119e+02, 9.6791538e+02, 9.4724817e+02, 9.0746962e+02,
+ 8.5438295e+02, 7.8710681e+02, 7.1621104e+02, 6.3739148e+02 ],
+
+])
+
+LTPF_C5_TRANS = np.array([
+
+ 5.5469254e+02, 4.6885623e+02, 3.8726237e+02, 3.0166318e+02,
+ 2.2151059e+02, 1.4759060e+02, 7.6115964e+01, 1.2068315e+01,
+ -5.0213437e+01, -1.1124791e+02, -1.6496412e+02, -2.1495097e+02,
+ -2.6214927e+02, -3.0944212e+02, -3.5014054e+02, -3.8896389e+02,
+ -4.2617800e+02, -4.6406673e+02, -4.9691186e+02, -5.3314161e+02,
+ -5.6776429e+02, -6.0515795e+02, -6.4220526e+02, -6.7634237e+02,
+ -7.0656015e+02, -7.2541177e+02, -7.3535446e+02, -7.3265481e+02,
+ -7.1676788e+02, -6.8818630e+02, -6.4788454e+02, -5.9638237e+02,
+ -5.3135114e+02, -4.5622803e+02, -3.7085252e+02, -2.7464233e+02,
+ -1.7527279e+02, -6.8212512e+01, 3.6401489e+01, 1.4772605e+02,
+ 2.5777143e+02, 3.5986766e+02, 4.6046220e+02, 5.5572298e+02,
+ 6.4084254e+02, 7.2023220e+02, 7.9091946e+02, 8.4596132e+02,
+ 8.8561830e+02, 9.0316671e+02, 9.0353933e+02, 8.8830570e+02,
+ 8.5210347e+02, 8.0683786e+02, 7.4767132e+02, 6.8402115e+02,
+ 6.1000133e+02, 5.3637714e+02, 4.5522905e+02, 3.7796360e+02,
+ 2.9165202e+02, 2.1765490e+02, 1.3937214e+02, 6.9124279e+01,
+ 5.1484918e+00, -5.7974304e+01, -1.1532103e+02, -1.7106128e+02,
+ -2.2144596e+02, -2.6763632e+02, -3.1235860e+02, -3.5424602e+02,
+ -3.9420762e+02, -4.2862777e+02, -4.6393345e+02, -5.0059201e+02,
+ -5.3052040e+02, -5.6462343e+02, -5.9733595e+02, -6.2614003e+02,
+ -6.5395598e+02, -6.7654796e+02, -6.8956058e+02, -6.9036404e+02,
+ -6.8409998e+02, -6.6772245e+02, -6.4131629e+02, -6.0423695e+02,
+ -5.5819928e+02, -5.0085813e+02, -4.3386043e+02, -3.5697723e+02,
+ -2.7353263e+02, -1.7946159e+02, -8.3894727e+01, 1.3870299e+01,
+ 1.1661147e+02, 2.1714406e+02, 3.1916911e+02, 4.1466126e+02,
+ 5.0807281e+02, 5.9699545e+02, 6.7493085e+02, 7.4602304e+02,
+ 8.0681874e+02, 8.5162090e+02, 8.7732032e+02, 8.8801241e+02,
+ 8.7733827e+02, 8.5711309e+02, 8.1939693e+02, 7.7020353e+02,
+ 7.1415915e+02, 6.4639833e+02, 5.7422282e+02, 4.9782204e+02,
+ 4.1400066e+02, 3.3290948e+02, 2.5272667e+02, 1.7094246e+02,
+ 9.4679864e+01, 1.9214845e+01, -4.7039158e+01, -1.1560544e+02,
+ -1.7609914e+02, -2.3440216e+02, -2.8752910e+02, -3.3711616e+02,
+ -3.8273508e+02, -4.2591674e+02, -4.6397521e+02, -5.0230060e+02,
+ -5.3283216e+02, -5.6227577e+02, -5.9128189e+02, -6.1269433e+02,
+ -6.3821208e+02, -6.5457809e+02, -6.7024858e+02, -6.7829939e+02,
+ -6.7675317e+02, -6.6455106e+02, -6.4328023e+02, -6.1728360e+02,
+ -5.7844437e+02, -5.3391997e+02, -4.7785175e+02, -4.1395668e+02,
+ -3.3933775e+02, -2.5814915e+02, -1.7234111e+02, -7.9862248e+01,
+ 1.5711615e+01, 1.1047993e+02, 2.0926197e+02, 3.0481978e+02,
+ 4.0036676e+02, 4.9118016e+02, 5.7429258e+02, 6.5078515e+02,
+
+])
+
+### C.4.1.10 Output signal clipping
+
+X_HAT_CLIP_10M = np.array([
+
+ [ 6.1525095e-01, 1.7117620e+00, -1.6200436e-01, -2.1107548e+00,
+ 9.1636911e-01, 8.7583398e+00, 1.4291828e+01, 1.4615904e+01,
+ 1.9312730e+01, 2.2178311e+01, 2.1178760e+01, 1.9939021e+01,
+ 3.2745193e+01, 3.1385007e+01, 4.5642888e+01, 3.8185668e+01,
+ 4.3452271e+01, 3.0174130e+01, 2.7510416e+01, 3.9048290e+00,
+ -4.1911157e+00, -3.4032526e+01, -4.3089457e+01, -7.1817465e+01,
+ -7.3319439e+01, -1.0231340e+02, -8.2645833e+01, -1.0207070e+02,
+ -7.4253115e+01, -9.5269932e+01, -1.2210097e+02, -1.3216707e+02,
+ -1.2665681e+02, -1.6033791e+02, -1.3067613e+02, -1.8796611e+01,
+ 6.2097263e+01, 7.2290617e+00, -1.2550979e+02, -8.9649115e+01,
+ 7.6135408e+02, 2.7072170e+03, 6.1558256e+03, 9.6522574e+03,
+ 1.2566221e+04, 1.5421574e+04, 1.8329565e+04, 2.1102710e+04,
+ 2.3323039e+04, 2.5451924e+04, 2.7365468e+04, 2.8891223e+04,
+ 3.0341813e+04, 3.1380038e+04, 3.2134454e+04, 3.2606958e+04,
+ 3.2683895e+04, 3.2518324e+04, 3.2036626e+04, 3.1278795e+04,
+ 3.0136453e+04, 2.8694957e+04, 2.7009676e+04, 2.5075921e+04,
+ 2.2940269e+04, 2.0564299e+04, 1.7956441e+04, 1.5202722e+04,
+ 1.2352834e+04, 9.3639445e+03, 6.2714619e+03, 3.1112267e+03,
+ -1.0075267e+02, -3.3115389e+03, -6.4954073e+03, -9.6110111e+03,
+ -1.2594144e+04, -1.5477538e+04, -1.8214406e+04, -2.0797170e+04,
+ -2.3195615e+04, -2.5355124e+04, -2.7302557e+04, -2.8919494e+04,
+ -3.0273227e+04, -3.1357707e+04, -3.2152224e+04, -3.2625545e+04,
+ -3.2768000e+04, -3.2640407e+04, -3.2172861e+04, -3.1393517e+04,
+ -3.0316009e+04, -2.8922986e+04, -2.7290775e+04, -2.5351571e+04,
+ -2.3183937e+04, -2.0795771e+04, -1.8212609e+04, -1.5453610e+04,
+ -1.2543978e+04, -9.4923186e+03, -6.3663932e+03, -3.1740539e+03,
+ 4.2407582e+01, 3.2479359e+03, 6.4369448e+03, 9.5564107e+03,
+ 1.2589389e+04, 1.5494437e+04, 1.8238168e+04, 2.0814647e+04,
+ 2.3183440e+04, 2.5340307e+04, 2.7236643e+04, 2.8879098e+04,
+ 3.0219987e+04, 3.1304367e+04, 3.2073455e+04, 3.2541098e+04,
+ 3.2660415e+04, 3.2490788e+04, 3.2004309e+04, 3.1215306e+04,
+ 3.0131477e+04, 2.8751611e+04, 2.7114762e+04, 2.5198099e+04,
+ 2.3044166e+04, 2.0655799e+04, 1.8068458e+04, 1.5312555e+04,
+ 1.2400688e+04, 9.3834439e+03, 6.2670869e+03, 3.1043555e+03,
+ -9.0364008e+01, -3.2949280e+03, -6.4558716e+03, -9.5736656e+03,
+ -1.2593429e+04, -1.5487321e+04, -1.8231003e+04, -2.0808229e+04,
+ -2.3191386e+04, -2.5327915e+04, -2.7226934e+04, -2.8860268e+04,
+ -3.0235350e+04, -3.1313467e+04, -3.2092397e+04, -3.2585580e+04,
+ -3.2768000e+04, -3.2606534e+04, -3.2146234e+04, -3.1383325e+04,
+ -3.0295384e+04, -2.8926934e+04, -2.7297985e+04, -2.5343669e+04 ],
+
+ [ -2.3210612e+04, -2.0830109e+04, -1.8262528e+04, -1.5491202e+04,
+ -1.2640992e+04, -9.6308521e+03, -6.5120997e+03, -3.2981272e+03,
+ -1.0437273e+02, 3.1237705e+03, 6.3475523e+03, 9.4251090e+03,
+ 1.2406927e+04, 1.5369182e+04, 1.8133410e+04, 2.0696011e+04,
+ 2.3075625e+04, 2.5239168e+04, 2.7178122e+04, 2.8863775e+04,
+ 3.0239107e+04, 3.1292540e+04, 3.2055374e+04, 3.2528526e+04,
+ 3.2691792e+04, 3.2554032e+04, 3.2080858e+04, 3.1269701e+04,
+ 3.0219849e+04, 2.8872409e+04, 2.7201446e+04, 2.5283194e+04,
+ 2.3137397e+04, 2.0746427e+04, 1.8171258e+04, 1.5425482e+04,
+ 1.2542866e+04, 9.5154094e+03, 6.4038902e+03, 3.2243297e+03,
+ 1.8093877e+01, -3.2004786e+03, -6.3778766e+03, -9.4986572e+03,
+ -1.2530644e+04, -1.5438896e+04, -1.8199553e+04, -2.0786963e+04,
+ -2.3172801e+04, -2.5336869e+04, -2.7256938e+04, -2.8914212e+04,
+ -3.0292811e+04, -3.1379968e+04, -3.2163160e+04, -3.2636663e+04,
+ -3.2768000e+04, -3.2642190e+04, -3.2169708e+04, -3.1389768e+04,
+ -3.0307591e+04, -2.8933213e+04, -2.7277887e+04, -2.5361709e+04,
+ -2.3197556e+04, -2.0809583e+04, -1.8223444e+04, -1.5459240e+04,
+ -1.2547850e+04, -9.5147469e+03, -6.3913071e+03, -3.2061552e+03,
+ 1.1474435e+01, 3.2280361e+03, 6.4146913e+03, 9.5376172e+03,
+ 1.2570372e+04, 1.5481142e+04, 1.8242641e+04, 2.0827867e+04,
+ 2.3213026e+04, 2.5375280e+04, 2.7293037e+04, 2.8947339e+04,
+ 3.0323330e+04, 3.1406817e+04, 3.2187891e+04, 3.2660531e+04,
+ 3.2767000e+04, 3.2659083e+04, 3.2187190e+04, 3.1402569e+04,
+ 3.0317849e+04, 2.8939620e+04, 2.7281206e+04, 2.5360297e+04,
+ 2.3194809e+04, 2.0805310e+04, 1.8215867e+04, 1.5450539e+04,
+ 1.2535402e+04, 9.5045150e+03, 6.3825434e+03, 3.1961404e+03,
+ -1.9030604e+01, -3.2350097e+03, -6.4178539e+03, -9.5376996e+03,
+ -1.2564818e+04, -1.5468879e+04, -1.8222757e+04, -2.0799617e+04,
+ -2.3177492e+04, -2.5329860e+04, -2.7239548e+04, -2.8887388e+04,
+ -3.0257022e+04, -3.1336972e+04, -3.2115659e+04, -3.2585521e+04,
+ -3.2741691e+04, -3.2583544e+04, -3.2112334e+04, -3.1332786e+04,
+ -3.0253039e+04, -2.8881031e+04, -2.7231757e+04, -2.5321143e+04,
+ -2.3168095e+04, -2.0790131e+04, -1.8212051e+04, -1.5458479e+04,
+ -1.2554090e+04, -9.5278709e+03, -6.4088050e+03, -3.2282766e+03,
+ -1.5127187e+01, 3.1974595e+03, 6.3806758e+03, 9.5013370e+03,
+ 1.2533377e+04, 1.5443257e+04, 1.8203988e+04, 2.0793445e+04,
+ 2.3180292e+04, 2.5344634e+04, 2.7265053e+04, 2.8919963e+04,
+ 3.0294320e+04, 3.1376795e+04, 3.2154178e+04, 3.2622959e+04,
+ 3.2767000e+04, 3.2617286e+04, 3.2145842e+04, 3.1360660e+04,
+ 3.0278348e+04, 2.8901877e+04, 2.7241369e+04, 2.5301056e+04 ],
+
+])
+
+X_HAT_CLIP_7M5 = np.array([
+
+ [ 9.0382948e-01, 2.8563300e+00, 2.0863167e+00, 3.2605273e+00,
+ 1.8231017e+00, -2.6473031e+00, -7.7420704e+00, -1.6971743e+01,
+ -4.4169569e+00, 4.7473387e+00, 7.9882732e+00, 2.1090757e+00,
+ 6.9477046e+00, 7.6294361e+00, 4.5069158e+00, 1.1288109e+00,
+ 5.5301798e-01, -1.2320805e+00, 1.2696965e+01, 1.7998129e+01,
+ 1.9997378e+01, 2.3310802e+01, 3.4116671e+01, 3.1619222e+01,
+ 2.3643252e+01, 2.2595989e+01, 2.4150879e+01, 1.7561939e+01,
+ 2.4167995e+01, 2.1868269e+01, 1.2021561e+01, 1.0810360e+01,
+ -1.1321816e+01, -1.3811836e+01, -2.7571991e+01, -3.3459505e+01,
+ -2.6720233e+01, -4.0425004e+01, -4.1666697e+01, -4.8106995e+01,
+ -7.1121739e+01, -8.5018856e+01, -6.4519501e+01, -6.1651047e+01,
+ -6.2001672e+01, -4.9054098e+01, 5.3605147e+00, -2.7222279e+00,
+ -6.3200946e+00, -2.8873822e+01, -5.6314175e+01, -5.9551902e+01,
+ -2.1183627e+01, -9.5007617e+01, -6.7674879e+01, 7.6546124e+01,
+ 3.6355638e+02, 2.0908440e+02, 9.2290767e+01, -8.4453487e+01,
+ -2.0810832e+02, -1.9235273e+02, -4.0634578e+02, -2.2011977e+02,
+ 6.2920459e+02, 3.1481663e+03, 6.2343351e+03, 9.4022080e+03,
+ 1.2520451e+04, 1.5313131e+04, 1.8128985e+04, 2.0762454e+04,
+ 2.3084787e+04, 2.5275848e+04, 2.7095495e+04, 2.8665301e+04,
+ 3.0094623e+04, 3.1202047e+04, 3.2006678e+04, 3.2461623e+04,
+ 3.2568832e+04, 3.2408327e+04, 3.1961953e+04, 3.1146555e+04,
+ 3.0073949e+04, 2.8725124e+04, 2.7099832e+04, 2.5196695e+04,
+ 2.3022972e+04, 2.0643354e+04, 1.8079103e+04, 1.5352852e+04,
+ 1.2476728e+04, 9.4135962e+03, 6.2948219e+03, 3.1010477e+03,
+ -9.0897787e+01, -3.3383673e+03, -6.5093586e+03, -9.6214110e+03,
+ -1.2638625e+04, -1.5564780e+04, -1.8289238e+04, -2.0877731e+04,
+ -2.3274493e+04, -2.5456613e+04, -2.7372293e+04, -2.9018289e+04,
+ -3.0399516e+04, -3.1474248e+04, -3.2213279e+04, -3.2686770e+04,
+ -3.2768000e+04, -3.2655386e+04, -3.2161995e+04, -3.1363572e+04,
+ -3.0296725e+04, -2.8893704e+04, -2.7226660e+04, -2.5303018e+04 ],
+
+ [ -2.3111848e+04, -2.0718046e+04, -1.8145256e+04, -1.5386042e+04,
+ -1.2451683e+04, -9.4561229e+03, -6.3407390e+03, -3.2078423e+03,
+ -1.4231827e+01, 3.1871864e+03, 6.4028626e+03, 9.5288605e+03,
+ 1.2522323e+04, 1.5403074e+04, 1.8148763e+04, 2.0738239e+04,
+ 2.3124038e+04, 2.5248199e+04, 2.7157343e+04, 2.8821520e+04,
+ 3.0197933e+04, 3.1280524e+04, 3.2068994e+04, 3.2535286e+04,
+ 3.2674198e+04, 3.2505688e+04, 3.2021479e+04, 3.1217393e+04,
+ 3.0139480e+04, 2.8742712e+04, 2.7081219e+04, 2.5164753e+04,
+ 2.3005958e+04, 2.0625737e+04, 1.8051360e+04, 1.5314656e+04,
+ 1.2403135e+04, 9.3958576e+03, 6.2866076e+03, 3.1150574e+03,
+ -8.3043055e+01, -3.2906309e+03, -6.4783209e+03, -9.5968770e+03,
+ -1.2627329e+04, -1.5543027e+04, -1.8297188e+04, -2.0856742e+04,
+ -2.3242831e+04, -2.5406524e+04, -2.7315500e+04, -2.8954115e+04,
+ -3.0311322e+04, -3.1397263e+04, -3.2199564e+04, -3.2663393e+04,
+ -3.2768000e+04, -3.2631820e+04, -3.2158938e+04, -3.1361864e+04,
+ -3.0286591e+04, -2.8909485e+04, -2.7252911e+04, -2.5338382e+04,
+ -2.3179744e+04, -2.0801866e+04, -1.8222214e+04, -1.5467629e+04,
+ -1.2551908e+04, -9.5234786e+03, -6.4050183e+03, -3.2234113e+03,
+ -1.0202956e+01, 3.2050827e+03, 6.3811438e+03, 9.5000550e+03,
+ 1.2526624e+04, 1.5433267e+04, 1.8190970e+04, 2.0775689e+04,
+ 2.3157406e+04, 2.5317424e+04, 2.7226647e+04, 2.8880016e+04,
+ 3.0250964e+04, 3.1333324e+04, 3.2108157e+04, 3.2579815e+04,
+ 3.2739171e+04, 3.2585501e+04, 3.2115570e+04, 3.1342610e+04,
+ 3.0239307e+04, 2.8881574e+04, 2.7232557e+04, 2.5325302e+04,
+ 2.3165560e+04, 2.0776212e+04, 1.8202819e+04, 1.5452512e+04,
+ 1.2552870e+04, 9.5323059e+03, 6.4141989e+03, 3.2353808e+03,
+ 3.2008805e+01, -3.1778835e+03, -6.3568255e+03, -9.4682388e+03,
+ -1.2490842e+04, -1.5403926e+04, -1.8154186e+04, -2.0745346e+04,
+ -2.3121161e+04, -2.5285375e+04, -2.7200767e+04, -2.8855100e+04,
+ -3.0236188e+04, -3.1303814e+04, -3.2106304e+04, -3.2610143e+04 ],
+
+])
+
+X_HAT_CLIP = [ X_HAT_CLIP_7M5, X_HAT_CLIP_10M ]
diff --git a/test/arm/ltpf_arm.c b/test/arm/ltpf_arm.c
new file mode 100644
index 0000000..e7b8bfc
--- /dev/null
+++ b/test/arm/ltpf_arm.c
@@ -0,0 +1,114 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "simd32.h"
+
+/* -------------------------------------------------------------------------- */
+
+#define TEST_ARM
+#include <ltpf.c>
+
+void lc3_put_bits_generic(lc3_bits_t *a, unsigned b, int c)
+{ (void)a, (void)b, (void)c; }
+
+unsigned lc3_get_bits_generic(struct lc3_bits *a, int b)
+{ return (void)a, (void)b, 0; }
+
+/* -------------------------------------------------------------------------- */
+
+static int check_resampler()
+{
+ int16_t __x[60+480], *x = __x + 60;
+ for (int i = -60; i < 480; i++)
+ x[i] = rand() & 0xffff;
+
+ struct lc3_ltpf_hp50_state hp50 = { 0 }, hp50_arm = { 0 };
+ int16_t y[128], y_arm[128];
+
+ resample_8k_12k8(&hp50, x, y, 128);
+ arm_resample_8k_12k8(&hp50_arm, x, y_arm, 128);
+ if (memcmp(y, y_arm, 128 * sizeof(*y)) != 0)
+ return -1;
+
+ resample_16k_12k8(&hp50, x, y, 128);
+ arm_resample_16k_12k8(&hp50_arm, x, y_arm, 128);
+ if (memcmp(y, y_arm, 128 * sizeof(*y)) != 0)
+ return -1;
+
+ resample_24k_12k8(&hp50, x, y, 128);
+ arm_resample_24k_12k8(&hp50_arm, x, y_arm, 128);
+ if (memcmp(y, y_arm, 128 * sizeof(*y)) != 0)
+ return -1;
+
+ resample_32k_12k8(&hp50, x, y, 128);
+ arm_resample_32k_12k8(&hp50_arm, x, y_arm, 128);
+ if (memcmp(y, y_arm, 128 * sizeof(*y)) != 0)
+ return -1;
+
+ resample_48k_12k8(&hp50, x, y, 128);
+ arm_resample_48k_12k8(&hp50_arm, x, y_arm, 128);
+ if (memcmp(y, y_arm, 128 * sizeof(*y)) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int check_correlate()
+{
+ int16_t alignas(4) a[500], b[500];
+ float y[100], y_arm[100];
+
+ for (int i = 0; i < 500; i++) {
+ a[i] = rand() & 0xffff;
+ b[i] = rand() & 0xffff;
+ }
+
+ correlate(a, b+200, 128, y, 100);
+ arm_correlate(a, b+200, 128, y_arm, 100);
+ if (memcmp(y, y_arm, 100 * sizeof(*y)) != 0)
+ return -1;
+
+ correlate(a, b+199, 128, y, 99);
+ arm_correlate(a, b+199, 128, y_arm, 99);
+ if (memcmp(y, y_arm, 99 * sizeof(*y)) != 0)
+ return -1;
+
+ correlate(a, b+199, 128, y, 100);
+ arm_correlate(a, b+199, 128, y_arm, 100);
+ if (memcmp(y, y_arm, 100 * sizeof(*y)) != 0)
+ return -1;
+
+ return 0;
+}
+
+int check_ltpf(void)
+{
+ int ret;
+
+ if ((ret = check_resampler()) < 0)
+ return ret;
+
+ if ((ret = check_correlate()) < 0)
+ return ret;
+
+ return 0;
+}
diff --git a/test/arm/makefile.mk b/test/arm/makefile.mk
new file mode 100644
index 0000000..91d11d2
--- /dev/null
+++ b/test/arm/makefile.mk
@@ -0,0 +1,31 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+test_arm_src += \
+ $(TEST_DIR)/arm/test_arm.c \
+ $(TEST_DIR)/arm/ltpf_arm.c \
+ $(SRC_DIR)/tables.c
+
+test_arm_include += $(SRC_DIR)
+test_arm_ldlibs += m
+
+$(eval $(call add-bin,test_arm))
+
+test_arm: $(test_arm_bin)
+ @echo " RUN $(notdir $<)"
+ $(V)$<
+
+test: test_arm
diff --git a/test/arm/simd32.h b/test/arm/simd32.h
new file mode 100644
index 0000000..ae002f4
--- /dev/null
+++ b/test/arm/simd32.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#if __ARM_FEATURE_SIMD32
+
+#include <arm_acle.h>
+
+static inline int16x2_t __pkhbt(int16x2_t a, int16x2_t b)
+{
+ int16x2_t r;
+ __asm("pkhbt %0, %1, %2" : "=r" (r) : "r" (a), "r" (b));
+ return r;
+}
+
+#else
+
+#include <stdint.h>
+
+typedef int32_t int16x2_t;
+
+__attribute__((unused))
+static int16x2_t __pkhbt(int16x2_t a, int16x2_t b)
+{
+ uint32_t a_bot = (uint32_t)a & 0x0000ffffu;
+ uint32_t b_top = (uint32_t)b & 0xffff0000u;
+
+ return (int16x2_t)(a_bot | b_top);
+}
+
+__attribute__((unused))
+static int32_t __smlad(int16x2_t a, int16x2_t b, int32_t u)
+{
+ int16_t a_hi = a >> 16, a_lo = a & 0xffff;
+ int16_t b_hi = b >> 16, b_lo = b & 0xffff;
+
+ return u + (a_hi * b_hi) + (a_lo * b_lo);
+}
+
+__attribute__((unused))
+static int64_t __smlald(int16x2_t a, int16x2_t b, int64_t u)
+{
+ int16_t a_hi = a >> 16, a_lo = a & 0xffff;
+ int16_t b_hi = b >> 16, b_lo = b & 0xffff;
+ return u + (a_hi * b_hi) + (a_lo * b_lo);
+}
+
+__attribute__((unused))
+static int64_t __smlaldx(int16x2_t a, int16x2_t b, int64_t u)
+{
+ int16_t a_hi = a >> 16, a_lo = a & 0xffff;
+ int16_t b_hi = b >> 16, b_lo = b & 0xffff;
+ return u + (a_hi * b_lo) + (a_lo * b_hi);
+}
+
+#endif /* __ARM_FEATURE_SIMD32 */
diff --git a/test/arm/test_arm.c b/test/arm/test_arm.c
new file mode 100644
index 0000000..1e5c15b
--- /dev/null
+++ b/test/arm/test_arm.c
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+
+int check_ltpf(void);
+
+int main()
+{
+ int r, ret = 0;
+
+ printf("Checking LTPF ARM... "); fflush(stdout);
+ printf("%s\n", (r = check_ltpf()) == 0 ? "OK" : "Failed");
+ ret = ret || r;
+
+ return ret;
+}
diff --git a/test/attdet.py b/test/attdet.py
new file mode 100644
index 0000000..3b6e9d9
--- /dev/null
+++ b/test/attdet.py
@@ -0,0 +1,185 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+import lc3
+import tables as T, appendix_c as C
+
+
+### ------------------------------------------------------------------------ ###
+
+class AttackDetector:
+
+ def __init__(self, dt, sr):
+
+ self.dt = dt
+ self.sr = sr
+ self.ms = T.DT_MS[dt]
+
+ self.xn1 = 0
+ self.xn2 = 0
+ self.en1 = 0
+ self.an1 = 0
+ self.p_att = 0
+
+ def is_enabled(self, nbytes):
+
+ c1 = self.dt == T.DT_10M and \
+ self.sr == T.SRATE_32K and nbytes > 80
+
+ c2 = self.dt == T.DT_10M and \
+ self.sr >= T.SRATE_48K and nbytes >= 100
+
+ c3 = self.dt == T.DT_7M5 and \
+ self.sr == T.SRATE_32K and nbytes >= 61 and nbytes < 150
+
+ c4 = self.dt == T.DT_7M5 and \
+ self.sr >= T.SRATE_48K and nbytes >= 75 and nbytes < 150
+
+ return c1 or c2 or c3 or c4
+
+ def run(self, nbytes, x):
+
+ ### 3.3.6.2 Downsampling and filtering input
+
+ mf = int(16 * self.ms)
+
+ r = len(x) // mf
+ x_att = np.array([ np.sum(x[i*r:(i+1)*r]) for i in range(mf) ])
+
+ x_hp = np.empty(mf)
+ x_hp[0 ] = 0.375 * x_att[0 ] - 0.5 * self.xn1 + 0.125 * self.xn2
+ x_hp[1 ] = 0.375 * x_att[1 ] - 0.5 * x_att[0 ] + 0.125 * self.xn1
+ x_hp[2:] = 0.375 * x_att[2:] - 0.5 * x_att[1:-1] + 0.125 * x_att[0:-2]
+ self.xn2 = x_att[-2]
+ self.xn1 = x_att[-1]
+
+ ### 3.3.6.3 Energy calculation
+
+ nb = int(self.ms / 2.5)
+
+ e_att = np.array([ np.sum(np.square(x_hp[40*i:40*(i+1)]))
+ for i in range(nb) ])
+
+ a_att = np.empty(nb)
+ a_att[0] = np.maximum(0.25 * self.an1, self.en1)
+ for i in range(1,nb):
+ a_att[i] = np.maximum(0.25 * a_att[i-1], e_att[i-1])
+ self.en1 = e_att[-1]
+ self.an1 = a_att[-1]
+
+ ### 3.3.6.4 Attack Detection
+
+ p_att = -1
+ flags = [ (e_att[i] > 8.5 * a_att[i]) for i in range(nb) ]
+
+ for (i, f) in enumerate(flags):
+ if f: p_att = i
+
+ f_att = p_att >= 0 or self.p_att - 1 >= nb // 2
+ self.p_att = 1 + p_att
+
+ return self.is_enabled(nbytes) and f_att
+
+
+def initial_state():
+ return { 'en1': 0.0, 'an1': 0.0, 'p_att': 0 }
+
+### ------------------------------------------------------------------------ ###
+
+def check_enabling(rng, dt):
+
+ ok = True
+
+ for sr in range(T.SRATE_16K, T.NUM_SRATE):
+
+ attdet = AttackDetector(dt, sr)
+
+ for nbytes in [ 61, 61-1, 75-1, 75, 80, 80+1, 100-1, 100, 150-1, 150 ]:
+
+ f_att = lc3.attdet_run(dt, sr, nbytes,
+ initial_state(), 2 * rng.random(T.NS[dt][sr]+6) - 1)
+
+ ok = ok and f_att == attdet.is_enabled(nbytes)
+
+ return ok
+
+def check_unit(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ ok = True
+
+ attdet = AttackDetector(dt, sr)
+
+ state_c = initial_state()
+ x_c = np.zeros(ns+6)
+
+ for run in range(100):
+
+ ### Generate noise, and an attack at random point
+
+ x = ((2 * rng.random(ns)) - 1) * (2 ** 8 - 1)
+ x[(ns * rng.random()).astype(int)] *= 2 ** 7
+
+ ### Check Implementation
+
+ f_att = attdet.run(100, x)
+
+ x_c = np.append(x_c[-6:], x)
+ f_att_c = lc3.attdet_run(dt, sr, 100, state_c, x_c)
+
+ ok = ok and f_att_c == f_att
+ ok = ok and np.amax(np.abs(1 - state_c['en1']/attdet.en1)) < 2
+ ok = ok and np.amax(np.abs(1 - state_c['an1']/attdet.an1)) < 2
+ ok = ok and state_c['p_att'] == attdet.p_att
+
+ return ok
+
+def check_appendix_c(dt):
+
+ sr = T.SRATE_48K
+
+ state = initial_state()
+
+ x = np.append(np.zeros(6), C.X_PCM_ATT[dt][0])
+ f_att = lc3.attdet_run(dt, sr, C.NBYTES_ATT[dt], state, x)
+ ok = f_att == C.F_ATT[dt][0]
+
+ x = np.append(x[-6:], C.X_PCM_ATT[dt][1])
+ f_att = lc3.attdet_run(dt, sr, C.NBYTES_ATT[dt], state, x)
+ ok = f_att == C.F_ATT[dt][1]
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ ok and check_enabling(rng, dt)
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.SRATE_32K, T.NUM_SRATE):
+ ok = ok and check_unit(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/attdet_py.c b/test/attdet_py.c
new file mode 100644
index 0000000..d85a8a5
--- /dev/null
+++ b/test/attdet_py.c
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <attdet.c>
+#include "ctypes.h"
+
+static PyObject *attdet_run_py(PyObject *m, PyObject *args)
+{
+ unsigned dt, sr, nbytes;
+ PyObject *attdet_obj, *x_obj;
+ struct lc3_attdet_analysis attdet = { 0 };
+ int16_t *x;
+
+ if (!PyArg_ParseTuple(args, "IIIOO",
+ &dt, &sr, &nbytes, &attdet_obj, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+ CTYPES_CHECK(NULL, attdet_obj = to_attdet_analysis(attdet_obj, &attdet));
+
+ int ns = LC3_NS(dt, sr);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_INT16, ns+6, &x));
+
+ int att = lc3_attdet_run(dt, sr, nbytes, &attdet, x+6);
+
+ from_attdet_analysis(attdet_obj, &attdet);
+ return Py_BuildValue("i", att);
+}
+
+static PyMethodDef methods[] = {
+ { "attdet_run", attdet_run_py, METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_attdet_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/bitstream.py b/test/bitstream.py
new file mode 100644
index 0000000..11edbd5
--- /dev/null
+++ b/test/bitstream.py
@@ -0,0 +1,240 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import math
+
+class Bitstream:
+
+ def __init__(self, data):
+
+ self.bytes = data
+
+ self.bp_bw = len(data) - 1
+ self.mask_bw = 1
+
+ self.bp = 0
+ self.low = 0
+ self.range = 0xffffff
+
+ def dump(self):
+
+ b = self.bytes
+
+ for i in range(0, len(b), 20):
+ print(''.join('{:02x} '.format(x)
+ for x in b[i:min(i+20, len(b))] ))
+
+class BitstreamReader(Bitstream):
+
+ def __init__(self, data):
+
+ super().__init__(data)
+
+ self.low = ( (self.bytes[0] << 16) |
+ (self.bytes[1] << 8) |
+ (self.bytes[2] ) )
+ self.bp = 3
+
+ def read_bit(self):
+
+ bit = bool(self.bytes[self.bp_bw] & self.mask_bw)
+
+ self.mask_bw <<= 1
+ if self.mask_bw == 0x100:
+ self.mask_bw = 1
+ self.bp_bw -= 1
+
+ return bit
+
+ def read_uint(self, nbits):
+
+ val = 0
+ for k in range(nbits):
+ val |= self.read_bit() << k
+
+ return val
+
+ def ac_decode(self, cum_freqs, sym_freqs):
+
+ r = self.range >> 10
+ if self.low >= r << 10:
+ raise ValueError('Invalid ac bitstream')
+
+ val = len(cum_freqs) - 1
+ while self.low < r * cum_freqs[val]:
+ val -= 1
+
+ self.low -= r * cum_freqs[val]
+ self.range = r * sym_freqs[val]
+ while self.range < 0x10000:
+ self.range <<= 8
+
+ self.low <<= 8
+ self.low &= 0xffffff
+ self.low += self.bytes[self.bp]
+ self.bp += 1
+
+ return val
+
+ def get_bits_left(self):
+
+ nbits = 8 * len(self.bytes)
+
+ nbits_bw = nbits - \
+ (8*self.bp_bw + 8 - int(math.log2(self.mask_bw)))
+
+ nbits_ac = 8 * (self.bp - 3) + \
+ (25 - int(math.floor(math.log2(self.range))))
+
+ return nbits - (nbits_bw + nbits_ac)
+
+class BitstreamWriter(Bitstream):
+
+ def __init__(self, nbytes):
+
+ super().__init__(bytearray(nbytes))
+
+ self.cache = -1
+ self.carry = 0
+ self.carry_count = 0
+
+ def write_bit(self, bit):
+
+ mask = self.mask_bw
+ bp = self.bp_bw
+
+ if bit == 0:
+ self.bytes[bp] &= ~mask
+ else:
+ self.bytes[bp] |= mask
+
+ self.mask_bw <<= 1
+ if self.mask_bw == 0x100:
+ self.mask_bw = 1
+ self.bp_bw -= 1
+
+ def write_uint(self, val, nbits):
+
+ for k in range(nbits):
+ self.write_bit(val & 1)
+ val >>= 1
+
+ def ac_shift(self):
+
+ if self.low < 0xff0000 or self.carry == 1:
+
+ if self.cache >= 0:
+ self.bytes[self.bp] = self.cache + self.carry
+ self.bp += 1
+
+ while self.carry_count > 0:
+ self.bytes[self.bp] = (self.carry + 0xff) & 0xff
+ self.bp += 1
+ self.carry_count -= 1
+
+ self.cache = self.low >> 16
+ self.carry = 0
+
+ else:
+ self.carry_count += 1
+
+ self.low <<= 8
+ self.low &= 0xffffff
+
+ def ac_encode(self, cum_freq, sym_freq):
+
+ r = self.range >> 10
+ self.low += r * cum_freq
+ if (self.low >> 24) != 0:
+ self.carry = 1
+
+ self.low &= 0xffffff
+ self.range = r * sym_freq
+ while self.range < 0x10000:
+ self.range <<= 8;
+ self.ac_shift()
+
+ def get_bits_left(self):
+
+ nbits = 8 * len(self.bytes)
+
+ nbits_bw = nbits - \
+ (8*self.bp_bw + 8 - int(math.log2(self.mask_bw)))
+
+ nbits_ac = 8 * self.bp + (25 - int(math.floor(math.log2(self.range))))
+ if self.cache >= 0:
+ nbits_ac += 8
+ if self.carry_count > 0:
+ nbits_ac += 8 * self.carry_count
+
+ return nbits - (nbits_bw + nbits_ac)
+
+ def terminate(self):
+
+ bits = 1
+ while self.range >> (24 - bits) == 0:
+ bits += 1
+
+ mask = 0xffffff >> bits;
+ val = self.low + mask;
+
+ over1 = val >> 24
+ val &= 0x00ffffff
+ high = self.low + self.range
+ over2 = high >> 24
+ high &= 0x00ffffff
+ val = val & ~mask
+
+ if over1 == over2:
+
+ if val + mask >= high:
+ bits += 1
+ mask >>= 1
+ val = ((self.low + mask) & 0x00ffffff) & ~mask
+
+ if val < self.low:
+ self.carry = 1
+
+ self.low = val
+ while bits > 0:
+ self.ac_shift()
+ bits -= 8
+ bits += 8;
+
+ val = self.cache
+
+ if self.carry_count > 0:
+ self.bytes[self.bp] = self.cache
+ self.bp += 1
+
+ while self.carry_count > 1:
+ self.bytes[self.bp] = 0xff
+ self.bp += 1
+ self.carry_count -= 1
+
+ val = 0xff >> (8 - bits)
+
+ mask = 0x80;
+ for k in range(bits):
+
+ if val & mask == 0:
+ self.bytes[self.bp] &= ~mask
+ else:
+ self.bytes[self.bp] |= mask
+
+ mask >>= 1
+
+ return self.bytes
diff --git a/test/bwdet.py b/test/bwdet.py
new file mode 100644
index 0000000..88d7c8c
--- /dev/null
+++ b/test/bwdet.py
@@ -0,0 +1,162 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+import lc3
+import tables as T, appendix_c as C
+
+
+BW_START = [
+ [ [], [ 51 ], [ 45, 58 ], [ 42, 53, 60 ], [ 40, 51, 57, 61 ] ],
+ [ [], [ 53 ], [ 47, 59 ], [ 44, 54, 60 ], [ 41, 51, 57, 61 ] ]
+]
+
+BW_STOP = [
+ [ [], [ 63 ], [ 55, 63 ], [ 51, 58, 63 ], [ 48, 55, 60, 63 ] ],
+ [ [], [ 63 ], [ 56, 63 ], [ 52, 59, 63 ], [ 49, 55, 60, 63 ] ]
+]
+
+TQ = [ 20, 10, 10, 10 ]
+
+TC = [ 15, 23, 20, 20 ]
+L = [ [ 4, 4, 3, 2 ], [ 4, 4, 3, 1 ] ]
+
+
+### ------------------------------------------------------------------------ ###
+
+class BandwidthDetector:
+
+ def __init__(self, dt, sr):
+
+ self.dt = dt
+ self.sr = sr
+
+ def run(self, e):
+
+ dt = self.dt
+ sr = self.sr
+
+ ### Stage 1, determine bw0 candidate
+
+ bw0 = 0
+
+ for bw in range(sr):
+ i0 = BW_START[dt][sr][bw]
+ i1 = BW_STOP[dt][sr][bw]
+ if np.mean(e[i0:i1+1]) >= TQ[bw]:
+ bw0 = bw + 1
+
+ ### Stage 2, Cut-off random coefficients at each steps
+
+ bw = bw0
+
+ if bw0 < sr:
+ l = L[dt][bw0]
+ i0 = BW_START[dt][sr][bw0] - l
+ i1 = BW_START[dt][sr][bw0]
+
+ c = 10 * np.log10(1e-31 + e[i0-l+1:i1-l+2] / e[i0+1:i1+2])
+ if np.amax(c) <= TC[bw0]:
+ bw = sr
+
+ self.bw = bw
+ return self.bw
+
+ def get_nbits(self):
+
+ return 0 if self.sr == 0 else \
+ 1 + np.log2(self.sr).astype(int)
+
+ def store(self, b):
+
+ b.write_uint(self.bw, self.get_nbits())
+
+ def get(self, b):
+
+ return b.read_uint(self.get_nbits())
+
+### ------------------------------------------------------------------------ ###
+
+def check_unit(rng, dt, sr):
+
+ ok = True
+
+ bwdet = BandwidthDetector(dt, sr)
+
+ for bw0 in range(sr+1):
+ for drop in range(10):
+
+ ### Generate random 'high' energy and
+ ### scale relevant bands to select 'bw0'
+
+ e = 20 + 100 * rng.random(64)
+
+ for i in range(sr):
+ if i+1 != bw0:
+ i0 = BW_START[dt][sr][i]
+ i1 = BW_STOP[dt][sr][i]
+ e[i0:i1+1] /= (np.mean(e[i0:i1+1]) / TQ[i] + 1e-3)
+
+ ### Stage 2 Condition,
+ ### cut-off random coefficients at each steps
+
+ if bw0 < sr:
+ l = L[dt][bw0]
+ i0 = BW_START[dt][sr][bw0] - l
+ i1 = BW_START[dt][sr][bw0]
+
+ e[i0-l+1:i1+2] /= np.power(10, np.arange(2*l+1) / (1 + drop))
+
+ ### Check with implementation
+
+ bw_c = lc3.bwdet_run(dt, sr, e)
+
+ ok = ok and bw_c == bwdet.run(e)
+
+ return ok
+
+def check_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ E_B = C.E_B[dt]
+ P_BW = C.P_BW[dt]
+
+ bw = lc3.bwdet_run(dt, sr, E_B[0])
+ ok = ok and bw == P_BW[0]
+
+ bw = lc3.bwdet_run(dt, sr, E_B[1])
+ ok = ok and bw == P_BW[1]
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+
+ ok = True
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_unit(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/bwdet_py.c b/test/bwdet_py.c
new file mode 100644
index 0000000..c2decb3
--- /dev/null
+++ b/test/bwdet_py.c
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <bwdet.c>
+#include "ctypes.h"
+
+static PyObject *bwdet_run_py(PyObject *m, PyObject *args)
+{
+ unsigned dt, sr;
+ PyObject *e_obj;
+ float *e;
+
+ if (!PyArg_ParseTuple(args, "IIO", &dt, &sr, &e_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+ CTYPES_CHECK("e", to_1d_ptr(e_obj, NPY_FLOAT, LC3_NUM_BANDS, &e));
+
+ int bw = lc3_bwdet_run(dt, sr, e);
+
+ return Py_BuildValue("i", bw);
+}
+
+static PyMethodDef methods[] = {
+ { "bwdet_run", bwdet_run_py, METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_bwdet_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/ctypes.h b/test/ctypes.h
new file mode 100644
index 0000000..2442657
--- /dev/null
+++ b/test/ctypes.h
@@ -0,0 +1,893 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 __CTYPES_H
+#define __CTYPES_H
+
+#include <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <stdbool.h>
+
+
+#define CTYPES_CHECK(exc, t) \
+ do { \
+ if (!(t)) return (exc) ? PyErr_Format(PyExc_TypeError, exc) : NULL; \
+ } while(0)
+
+
+/**
+ * From C types to Numpy Array types
+ */
+
+#define to_scalar(obj, t, ptr) \
+ __to_scalar(obj, t, (void *)(ptr))
+
+#define to_1d_ptr(obj, t, n, ptr) \
+ __to_1d_ptr(obj, t, n, (void **)(ptr))
+
+#define to_2d_ptr(obj, t, n1, n2, ptr) \
+ __to_2d_ptr(obj, t, n1, n2, (void **)(ptr))
+
+#define to_1d_copy(obj, t, ptr, n) \
+ __to_1d_copy(obj, t, ptr, n)
+
+#define to_2d_copy(obj, t, ptr, n1, n2) \
+ __to_2d_copy(obj, t, ptr, n1, n2)
+
+
+/**
+ * From Numpy Array types to C types
+ */
+
+#define new_scalar(obj, ptr) \
+ __new_scalar(obj, ptr)
+
+#define new_1d_ptr(t, n, ptr) \
+ __new_1d_ptr(t, n, (void **)(ptr))
+
+#define new_2d_ptr(t, n1, n2, ptr) \
+ __new_2d_ptr(t, n1, n2, (void **)(ptr))
+
+#define new_1d_copy(t, n, src) \
+ __new_1d_copy(t, n, src)
+
+#define new_2d_copy(t, n1, n2, src) \
+ __new_2d_copy(t, n1, n2, src)
+
+
+/* -------------------------------------------------------------------------- */
+
+__attribute__((unused))
+static PyObject *__to_scalar(PyObject *obj, int t, void *ptr)
+{
+ obj = obj ? PyArray_FROMANY(obj, t, 0, 0, NPY_ARRAY_FORCECAST) : obj;
+ if (!obj)
+ return NULL;
+
+ memcpy(ptr, PyArray_DATA((PyArrayObject *)obj),
+ PyArray_NBYTES((PyArrayObject *)obj));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__to_1d_ptr(PyObject *obj, int t, int n, void **ptr)
+{
+ obj = obj ? PyArray_FROMANY(obj,
+ t, 1, 1, NPY_ARRAY_FORCECAST|NPY_ARRAY_CARRAY) : obj;
+ if (!obj || (n && PyArray_SIZE((PyArrayObject *)obj) != n))
+ return NULL;
+
+ *ptr = PyArray_DATA((PyArrayObject *)obj);
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__to_2d_ptr(PyObject *obj, int t, int n1, int n2, void **ptr)
+{
+ obj = obj ? PyArray_FROMANY(obj,
+ t, 2, 2, NPY_ARRAY_FORCECAST|NPY_ARRAY_CARRAY) : obj;
+ if (!obj || (n1 && PyArray_DIMS((PyArrayObject *)obj)[0] != n1)
+ || (n2 && PyArray_DIMS((PyArrayObject *)obj)[1] != n2))
+ return NULL;
+
+ *ptr = PyArray_DATA((PyArrayObject *)obj);
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__to_1d_copy(PyObject *obj, int t, void *v, int n)
+{
+ void *src;
+
+ if ((obj = to_1d_ptr(obj, t, n, &src)))
+ memcpy(v, src, PyArray_NBYTES((PyArrayObject *)obj));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__to_2d_copy(PyObject *obj, int t, void *v, int n1, int n2)
+{
+ void *src;
+
+ if ((obj = to_2d_ptr(obj, t, n1, n2, &src)))
+ memcpy(v, src, PyArray_NBYTES((PyArrayObject *)obj));
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+__attribute__((unused))
+static PyObject *__new_scalar(int t, const void *ptr)
+{
+ PyObject *obj = PyArray_SimpleNew(0, NULL, t);
+
+ memcpy(PyArray_DATA((PyArrayObject *)obj), ptr,
+ PyArray_NBYTES((PyArrayObject *)obj));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__new_1d_ptr(int t, int n, void **ptr)
+{
+ PyObject *obj = PyArray_SimpleNew(1, (const npy_intp []){ n }, t);
+
+ *ptr = PyArray_DATA((PyArrayObject *)obj);
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__new_2d_ptr(int t, int n1, int n2, void **ptr)
+{
+ PyObject *obj;
+
+ obj = PyArray_SimpleNew(2, ((const npy_intp []){ n1, n2 }), t);
+
+ *ptr = PyArray_DATA((PyArrayObject *)obj);
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__new_1d_copy(int t, int n, const void *src)
+{
+ PyObject *obj;
+ void *dst;
+
+ if ((obj = new_1d_ptr(t, n, &dst)))
+ memcpy(dst, src, PyArray_NBYTES((PyArrayObject *)obj));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *__new_2d_copy(int t, int n1, int n2, const void *src)
+{
+ PyObject *obj;
+ void *dst;
+
+ if ((obj = new_2d_ptr(t, n1, n2, &dst)))
+ memcpy(dst, src, PyArray_NBYTES((PyArrayObject *)obj));
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+#include <lc3.h>
+
+__attribute__((unused))
+static PyObject *to_attdet_analysis(
+ PyObject *obj, struct lc3_attdet_analysis *attdet)
+{
+ CTYPES_CHECK("attdet", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("attdet.en1", to_scalar(
+ PyDict_GetItemString(obj, "en1"), NPY_INT32, &attdet->en1));
+
+ CTYPES_CHECK("attdet.an1", to_scalar(
+ PyDict_GetItemString(obj, "an1"), NPY_INT32, &attdet->an1));
+
+ CTYPES_CHECK("attdet.p_att", to_scalar(
+ PyDict_GetItemString(obj, "p_att"), NPY_INT, &attdet->p_att));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *from_attdet_analysis(
+ PyObject *obj, const struct lc3_attdet_analysis *attdet)
+{
+ if (!obj) obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "en1",
+ new_scalar(NPY_INT32, &attdet->en1));
+
+ PyDict_SetItemString(obj, "an1",
+ new_scalar(NPY_INT32, &attdet->an1));
+
+ PyDict_SetItemString(obj, "p_att",
+ new_scalar(NPY_INT, &attdet->p_att));
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+#include <ltpf.h>
+
+__attribute__((unused))
+static PyObject *to_ltpf_hp50_state(
+ PyObject *obj, struct lc3_ltpf_hp50_state *hp50)
+{
+ CTYPES_CHECK("hp50", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("hp50.s1", to_scalar(
+ PyDict_GetItemString(obj, "s1"), NPY_INT64, &hp50->s1));
+
+ CTYPES_CHECK("hp50.s2", to_scalar(
+ PyDict_GetItemString(obj, "s2"), NPY_INT64, &hp50->s2));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *from_ltpf_hp50_state(
+ PyObject *obj, const struct lc3_ltpf_hp50_state *hp50)
+{
+ PyDict_SetItemString(obj, "s1",
+ new_scalar(NPY_INT64, &hp50->s1));
+
+ PyDict_SetItemString(obj, "s2",
+ new_scalar(NPY_INT64, &hp50->s2));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_ltpf_analysis(
+ PyObject *obj, struct lc3_ltpf_analysis *ltpf)
+{
+ PyObject *nc_obj, *x_12k8_obj, *x_6k4_obj;
+ const int n_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8);
+ const int n_6k4 = sizeof(ltpf->x_6k4) / sizeof(*ltpf->x_6k4);
+
+ CTYPES_CHECK("ltpf", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("ltpf.active", to_scalar(
+ PyDict_GetItemString(obj, "active"), NPY_BOOL, &ltpf->active));
+
+ CTYPES_CHECK("ltpf.pitch", to_scalar(
+ PyDict_GetItemString(obj, "pitch"), NPY_INT, &ltpf->pitch));
+
+ CTYPES_CHECK("ltpf.nc", nc_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "nc"), NPY_FLOAT, ltpf->nc, 2));
+ PyDict_SetItemString(obj, "nc", nc_obj);
+
+ CTYPES_CHECK(NULL, to_ltpf_hp50_state(
+ PyDict_GetItemString(obj, "hp50"), &ltpf->hp50));
+
+ CTYPES_CHECK("ltpf.x_12k8", x_12k8_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "x_12k8"), NPY_INT16, ltpf->x_12k8, n_12k8));
+ PyDict_SetItemString(obj, "x_12k8", x_12k8_obj);
+
+ CTYPES_CHECK("ltpf.x_6k4", x_6k4_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "x_6k4"), NPY_INT16, ltpf->x_6k4, n_6k4));
+ PyDict_SetItemString(obj, "x_6k4", x_6k4_obj);
+
+ CTYPES_CHECK("ltpf.tc", to_scalar(
+ PyDict_GetItemString(obj, "tc"), NPY_INT, &ltpf->tc));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *from_ltpf_analysis(
+ PyObject *obj, const struct lc3_ltpf_analysis *ltpf)
+{
+ const int n_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8);
+ const int n_6k4 = sizeof(ltpf->x_6k4) / sizeof(*ltpf->x_6k4);
+
+ if (!obj) obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "active",
+ new_scalar(NPY_BOOL, &ltpf->active));
+
+ PyDict_SetItemString(obj, "pitch",
+ new_scalar(NPY_INT, &ltpf->pitch));
+
+ PyDict_SetItemString(obj, "nc",
+ new_1d_copy(NPY_FLOAT, 2, &ltpf->nc));
+
+ PyDict_SetItemString(obj, "hp50",
+ from_ltpf_hp50_state(PyDict_New(), &ltpf->hp50));
+
+ PyDict_SetItemString(obj, "x_12k8",
+ new_1d_copy(NPY_INT16, n_12k8, &ltpf->x_12k8));
+
+ PyDict_SetItemString(obj, "x_6k4",
+ new_1d_copy(NPY_INT16, n_6k4, &ltpf->x_6k4));
+
+ PyDict_SetItemString(obj, "tc",
+ new_scalar(NPY_INT, &ltpf->tc));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_ltpf_synthesis(
+ PyObject *obj, struct lc3_ltpf_synthesis *ltpf)
+{
+ PyObject *c_obj, *x_obj;
+
+ CTYPES_CHECK("ltpf", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("ltpf.active", to_scalar(
+ PyDict_GetItemString(obj, "active"), NPY_BOOL, &ltpf->active));
+
+ CTYPES_CHECK("ltpf.pitch", to_scalar(
+ PyDict_GetItemString(obj, "pitch"), NPY_INT, &ltpf->pitch));
+
+ CTYPES_CHECK("ltpf.c", c_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "c"), NPY_FLOAT, ltpf->c, 2*12));
+ PyDict_SetItemString(obj, "c", c_obj);
+
+ CTYPES_CHECK("ltpf.x", x_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "x"), NPY_FLOAT, ltpf->x, 12));
+ PyDict_SetItemString(obj, "x", x_obj);
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *from_ltpf_synthesis(
+ PyObject *obj, const struct lc3_ltpf_synthesis *ltpf)
+{
+ if (!obj) obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "active",
+ new_scalar(NPY_BOOL, &ltpf->active));
+
+ PyDict_SetItemString(obj, "pitch",
+ new_scalar(NPY_INT, &ltpf->pitch));
+
+ PyDict_SetItemString(obj, "c",
+ new_1d_copy(NPY_FLOAT, 2*12, &ltpf->c));
+
+ PyDict_SetItemString(obj, "x",
+ new_1d_copy(NPY_FLOAT, 12, &ltpf->x));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *new_ltpf_data(const struct lc3_ltpf_data *data)
+{
+ PyObject *obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "active",
+ new_scalar(NPY_BOOL, &data->active));
+
+ PyDict_SetItemString(obj, "pitch_index",
+ new_scalar(NPY_INT, &data->pitch_index));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_ltpf_data(
+ PyObject *obj, const struct lc3_ltpf_data *data)
+{
+ PyObject *item;
+
+ CTYPES_CHECK("ltpf", obj && PyDict_Check(obj));
+
+ if ((item = PyDict_GetItemString(obj, "active")))
+ CTYPES_CHECK("ltpf.active",
+ to_scalar(item, NPY_BOOL, &data->active));
+
+ if ((item = PyDict_GetItemString(obj, "pitch_index")))
+ CTYPES_CHECK("ltpf.pitch_index",
+ to_scalar(item, NPY_INT, &data->pitch_index));
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+#include <sns.h>
+
+__attribute__((unused))
+static PyObject *new_sns_data(const struct lc3_sns_data *data)
+{
+ PyObject *obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "lfcb",
+ new_scalar(NPY_INT, &data->lfcb));
+
+ PyDict_SetItemString(obj, "hfcb",
+ new_scalar(NPY_INT, &data->hfcb));
+
+ PyDict_SetItemString(obj, "shape",
+ new_scalar(NPY_INT, &data->shape));
+
+ PyDict_SetItemString(obj, "gain",
+ new_scalar(NPY_INT, &data->gain));
+
+ PyDict_SetItemString(obj, "idx_a",
+ new_scalar(NPY_INT, &data->idx_a));
+
+ PyDict_SetItemString(obj, "ls_a",
+ new_scalar(NPY_BOOL, &data->ls_a));
+
+ PyDict_SetItemString(obj, "idx_b",
+ new_scalar(NPY_INT, &data->idx_b));
+
+ PyDict_SetItemString(obj, "ls_b",
+ new_scalar(NPY_BOOL, &data->ls_b));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_sns_data(PyObject *obj, struct lc3_sns_data *data)
+{
+ PyObject *item;
+
+ CTYPES_CHECK("sns", obj && PyDict_Check(obj));
+
+ if ((item = PyDict_GetItemString(obj, "lfcb")))
+ CTYPES_CHECK("sns.lfcb", to_scalar(item, NPY_INT, &data->lfcb));
+
+ if ((item = PyDict_GetItemString(obj, "hfcb")))
+ CTYPES_CHECK("sns.hfcb", to_scalar(item, NPY_INT, &data->hfcb));
+
+ if ((item = PyDict_GetItemString(obj, "shape")))
+ CTYPES_CHECK("sns.shape", to_scalar(item, NPY_INT, &data->shape));
+
+ if ((item = PyDict_GetItemString(obj, "gain")))
+ CTYPES_CHECK("sns.gain", to_scalar(item, NPY_INT, &data->gain));
+
+ if ((item = PyDict_GetItemString(obj, "idx_a")))
+ CTYPES_CHECK("sns.idx_a", to_scalar(item, NPY_INT, &data->idx_a));
+
+ if ((item = PyDict_GetItemString(obj, "ls_a")))
+ CTYPES_CHECK("sns.ls_a", to_scalar(item, NPY_BOOL, &data->ls_a));
+
+ if ((item = PyDict_GetItemString(obj, "idx_b")))
+ CTYPES_CHECK("sns.idx_b", to_scalar(item, NPY_INT, &data->idx_b));
+
+ if ((item = PyDict_GetItemString(obj, "ls_b")))
+ CTYPES_CHECK("sns.ls_b", to_scalar(item, NPY_BOOL, &data->ls_b));
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+#include <tns.h>
+
+__attribute__((unused))
+static PyObject *new_tns_data(const struct lc3_tns_data *side)
+{
+ PyObject *obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "nfilters",
+ new_scalar(NPY_INT, &side->nfilters));
+
+ PyDict_SetItemString(obj, "lpc_weighting",
+ new_scalar(NPY_BOOL, &side->lpc_weighting));
+
+ PyDict_SetItemString(obj, "rc_order",
+ new_1d_copy(NPY_INT, 2, side->rc_order));
+
+ PyDict_SetItemString(obj, "rc",
+ new_2d_copy(NPY_INT, 2, 8, side->rc));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_tns_data(PyObject *obj, struct lc3_tns_data *side)
+{
+ PyObject *item;
+
+ CTYPES_CHECK("tns", obj && PyDict_Check(obj));
+
+ if ((item = PyDict_GetItemString(obj, "nfilters")))
+ CTYPES_CHECK("tns.nfilters",
+ to_scalar(item, NPY_INT, &side->nfilters));
+
+ if ((item = PyDict_GetItemString(obj, "lpc_weighting"))) {
+ CTYPES_CHECK("tns.lpc_weighting",
+ to_scalar(item, NPY_BOOL, &side->lpc_weighting));
+ }
+
+ if ((item = PyDict_GetItemString(obj, "rc_order"))) {
+ CTYPES_CHECK("tns.rc_order",
+ item = to_1d_copy(item, NPY_INT, side->rc_order, 2));
+ PyDict_SetItemString(obj, "rc_order", item);
+ }
+
+ if ((item = PyDict_GetItemString(obj, "rc"))) {
+ CTYPES_CHECK("tns.rc",
+ item = to_2d_copy(item, NPY_INT, side->rc, 2, 8));
+ PyDict_SetItemString(obj, "rc", item);
+ }
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+#include <spec.h>
+
+__attribute__((unused))
+static PyObject *from_spec_analysis(
+ PyObject *obj, const struct lc3_spec_analysis *spec)
+{
+ if (!obj) obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "nbits_off",
+ new_scalar(NPY_FLOAT, &spec->nbits_off));
+
+ PyDict_SetItemString(obj, "nbits_spare",
+ new_scalar(NPY_INT, &spec->nbits_spare));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_spec_analysis(
+ PyObject *obj, struct lc3_spec_analysis *spec)
+{
+ CTYPES_CHECK("spec", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("spec.nbits_off",
+ to_scalar(PyDict_GetItemString(obj, "nbits_off"),
+ NPY_FLOAT, &spec->nbits_off));
+
+ CTYPES_CHECK("spec.nbits_spare",
+ to_scalar(PyDict_GetItemString(obj, "nbits_spare"),
+ NPY_INT, &spec->nbits_spare));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *new_spec_side(const struct lc3_spec_side *side)
+{
+ PyObject *obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "g_idx",
+ new_scalar(NPY_INT, &side->g_idx));
+
+ PyDict_SetItemString(obj, "nq",
+ new_scalar(NPY_INT, &side->nq));
+
+ PyDict_SetItemString(obj, "lsb_mode",
+ new_scalar(NPY_BOOL, &side->lsb_mode));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_spec_data(
+ PyObject *obj, struct lc3_spec_side *side)
+{
+ PyObject *item;
+
+ CTYPES_CHECK("side", obj && PyDict_Check(obj));
+
+ if ((item = PyDict_GetItemString(obj, "g_idx")))
+ CTYPES_CHECK("side.g_idx",
+ to_scalar(item, NPY_INT, &side->g_idx));
+
+ if ((item = PyDict_GetItemString(obj, "nq")))
+ CTYPES_CHECK("side.nq",
+ to_scalar(item, NPY_INT, &side->nq));
+
+ if ((item = PyDict_GetItemString(obj, "lsb_mode")))
+ CTYPES_CHECK("side.lsb_mode",
+ to_scalar(item, NPY_BOOL, &side->lsb_mode));
+
+ return obj;
+}
+
+/* -------------------------------------------------------------------------- */
+
+#ifdef __CTYPES_LC3_C
+
+__attribute__((unused))
+static PyObject *new_side_data(const struct side_data *side)
+{
+ PyObject *obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "bw",
+ new_scalar(NPY_INT, &(int){ side->bw }));
+
+ PyDict_SetItemString(obj, "ltpf",
+ new_ltpf_data(&side->ltpf));
+
+ PyDict_SetItemString(obj, "sns",
+ new_sns_data(&side->sns));
+
+ PyDict_SetItemString(obj, "tns",
+ new_tns_data(&side->tns));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_side_data(PyObject *obj, struct side_data *side)
+{
+ PyObject *item;
+
+ CTYPES_CHECK("frame", obj && PyDict_Check(obj));
+
+ if ((item = PyDict_GetItemString(obj, "bw"))) {
+ int bw;
+ CTYPES_CHECK("frame.bw", to_scalar(item, NPY_INT, &bw));
+ side->bw = bw;
+ }
+
+ if ((item = PyDict_GetItemString(obj, "ltpf")))
+ to_ltpf_data(item, &side->ltpf);
+
+ if ((item = PyDict_GetItemString(obj, "sns")))
+ to_sns_data(item, &side->sns);
+
+ if ((item = PyDict_GetItemString(obj, "tns")))
+ to_tns_data(item, &side->tns);
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *new_plc_state(const struct lc3_plc_state *plc)
+{
+ PyObject *obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "seed",
+ new_scalar(NPY_UINT16, &plc->seed));
+
+ PyDict_SetItemString(obj, "count",
+ new_scalar(NPY_INT, &plc->count));
+
+ PyDict_SetItemString(obj, "alpha",
+ new_scalar(NPY_FLOAT, &plc->alpha));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_plc_state(
+ PyObject *obj, struct lc3_plc_state *plc)
+{
+ CTYPES_CHECK("plc", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("plc.seed", to_scalar(
+ PyDict_GetItemString(obj, "seed"), NPY_UINT16, &plc->seed));
+
+ CTYPES_CHECK("plc.count", to_scalar(
+ PyDict_GetItemString(obj, "count"), NPY_INT, &plc->count));
+
+ CTYPES_CHECK("plc.alpha", to_scalar(
+ PyDict_GetItemString(obj, "alpha"), NPY_FLOAT, &plc->alpha));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *from_encoder(PyObject *obj, const struct lc3_encoder *enc)
+{
+ unsigned dt = enc->dt, sr = enc->sr;
+ unsigned sr_pcm = enc->sr_pcm;
+ int ns = LC3_NS(dt, sr);
+ int nd = LC3_ND(dt, sr);
+ int nt = LC3_NT(sr);
+
+ if (!obj) obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "dt",
+ new_scalar(NPY_INT, &dt));
+
+ PyDict_SetItemString(obj, "sr",
+ new_scalar(NPY_INT, &sr));
+
+ PyDict_SetItemString(obj, "sr_pcm",
+ new_scalar(NPY_INT, &sr_pcm));
+
+ PyDict_SetItemString(obj, "attdet",
+ from_attdet_analysis(NULL, &enc->attdet));
+
+ PyDict_SetItemString(obj, "ltpf",
+ from_ltpf_analysis(NULL, &enc->ltpf));
+
+ PyDict_SetItemString(obj, "quant",
+ from_spec_analysis(NULL, &enc->spec));
+
+ PyDict_SetItemString(obj, "xt",
+ new_1d_copy(NPY_INT16, nt+ns,
+ (int16_t *)enc->x + enc->xt_off - nt));
+
+ PyDict_SetItemString(obj, "xs",
+ new_1d_copy(NPY_FLOAT, ns, enc->x + enc->xs_off));
+
+ PyDict_SetItemString(obj, "xd",
+ new_1d_copy(NPY_FLOAT, nd, enc->x + enc->xd_off));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_encoder(PyObject *obj, struct lc3_encoder *enc)
+{
+ unsigned dt, sr, sr_pcm;
+ PyObject *xt_obj, *xs_obj, *xd_obj;
+
+ CTYPES_CHECK("encoder", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("encoder.dt", to_scalar(
+ PyDict_GetItemString(obj, "dt"), NPY_INT, &dt));
+ CTYPES_CHECK("encoder.dt", (unsigned)(enc->dt = dt) < LC3_NUM_DT);
+
+ CTYPES_CHECK("encoder.sr", to_scalar(
+ PyDict_GetItemString(obj, "sr"), NPY_INT, &sr));
+ CTYPES_CHECK("encoder.sr", (unsigned)(enc->sr = sr) < LC3_NUM_SRATE);
+
+ CTYPES_CHECK("encoder.sr_pcm", to_scalar(
+ PyDict_GetItemString(obj, "sr_pcm"), NPY_INT, &sr_pcm));
+ CTYPES_CHECK("encoder.s_pcmr",
+ (unsigned)(enc->sr_pcm = sr_pcm) < LC3_NUM_SRATE);
+
+ int ns = LC3_NS(dt, sr);
+ int nd = LC3_ND(dt, sr);
+ int nt = LC3_NT(sr);
+
+ CTYPES_CHECK(NULL, to_attdet_analysis(
+ PyDict_GetItemString(obj, "attdet"), &enc->attdet));
+
+ CTYPES_CHECK(NULL, to_ltpf_analysis(
+ PyDict_GetItemString(obj, "ltpf"), &enc->ltpf));
+
+ CTYPES_CHECK(NULL, to_spec_analysis(
+ PyDict_GetItemString(obj, "quant"), &enc->spec));
+
+ CTYPES_CHECK("encoder.xt", xt_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "xt"), NPY_INT16,
+ (int16_t *)enc->x + enc->xt_off - nt, ns+nt));
+ PyDict_SetItemString(obj, "xt", xt_obj);
+
+ CTYPES_CHECK("encoder.xs", xs_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "xs"), NPY_FLOAT,
+ enc->x + enc->xs_off, ns));
+ PyDict_SetItemString(obj, "xs", xs_obj);
+
+ CTYPES_CHECK("encoder.xd", xd_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "xd"), NPY_FLOAT,
+ enc->x + enc->xd_off, nd));
+ PyDict_SetItemString(obj, "xd", xd_obj);
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *from_decoder(PyObject *obj, const struct lc3_decoder *dec)
+{
+ unsigned dt = dec->dt, sr = dec->sr;
+ unsigned sr_pcm = dec->sr_pcm;
+ unsigned xs_pos = dec->xs_off - dec->xh_off;
+ int nh = LC3_NH(dt, sr);
+ int ns = LC3_NS(dt, sr);
+ int nd = LC3_ND(dt, sr);
+
+ if (!obj) obj = PyDict_New();
+
+ PyDict_SetItemString(obj, "dt",
+ new_scalar(NPY_INT, &dt));
+
+ PyDict_SetItemString(obj, "sr",
+ new_scalar(NPY_INT, &sr));
+
+ PyDict_SetItemString(obj, "sr_pcm",
+ new_scalar(NPY_INT, &sr_pcm));
+
+ PyDict_SetItemString(obj, "ltpf",
+ from_ltpf_synthesis(NULL, &dec->ltpf));
+
+ PyDict_SetItemString(obj, "plc",
+ new_plc_state(&dec->plc));
+
+ PyDict_SetItemString(obj, "xh",
+ new_1d_copy(NPY_FLOAT, nh, dec->x + dec->xh_off));
+
+ PyDict_SetItemString(obj, "xs_pos",
+ new_scalar(NPY_INT, &xs_pos));
+
+ PyDict_SetItemString(obj, "xd",
+ new_1d_copy(NPY_FLOAT, nd, dec->x + dec->xd_off));
+
+ PyDict_SetItemString(obj, "xg",
+ new_1d_copy(NPY_FLOAT, ns, dec->x + dec->xg_off));
+
+ return obj;
+}
+
+__attribute__((unused))
+static PyObject *to_decoder(PyObject *obj, struct lc3_decoder *dec)
+{
+ unsigned dt, sr, sr_pcm, xs_pos;
+ PyObject *xh_obj, *xd_obj, *xg_obj;
+
+ CTYPES_CHECK("decoder", obj && PyDict_Check(obj));
+
+ CTYPES_CHECK("decoder.dt", to_scalar(
+ PyDict_GetItemString(obj, "dt"), NPY_INT, &dt));
+ CTYPES_CHECK("decoder.dt", (unsigned)(dec->dt = dt) < LC3_NUM_DT);
+
+ CTYPES_CHECK("decoder.sr", to_scalar(
+ PyDict_GetItemString(obj, "sr"), NPY_INT, &sr));
+ CTYPES_CHECK("decoder.sr", (unsigned)(dec->sr = sr) < LC3_NUM_SRATE);
+
+ CTYPES_CHECK("decoder.sr_pcm", to_scalar(
+ PyDict_GetItemString(obj, "sr_pcm"), NPY_INT, &sr_pcm));
+ CTYPES_CHECK("decoder.sr_pcm",
+ (unsigned)(dec->sr_pcm = sr_pcm) < LC3_NUM_SRATE);
+
+ int nh = LC3_NH(dt, sr);
+ int ns = LC3_NS(dt, sr);
+ int nd = LC3_ND(dt, sr);
+
+ CTYPES_CHECK(NULL, to_ltpf_synthesis(
+ PyDict_GetItemString(obj, "ltpf"), &dec->ltpf));
+
+ CTYPES_CHECK(NULL, to_plc_state(
+ PyDict_GetItemString(obj, "plc"), &dec->plc));
+
+ CTYPES_CHECK("decoder.xh", xh_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "xh"), NPY_FLOAT,
+ dec->x + dec->xh_off, nh));
+ PyDict_SetItemString(obj, "xh", xh_obj);
+
+ CTYPES_CHECK("decoder.xs", to_scalar(
+ PyDict_GetItemString(obj, "xs_pos"), NPY_INT, &xs_pos));
+ dec->xs_off = dec->xh_off + xs_pos;
+
+ CTYPES_CHECK("decoder.xd", xd_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "xd"), NPY_FLOAT,
+ dec->x + dec->xd_off, nd));
+ PyDict_SetItemString(obj, "xd", xd_obj);
+
+ CTYPES_CHECK("decoder.xg", xg_obj = to_1d_copy(
+ PyDict_GetItemString(obj, "xg"), NPY_FLOAT,
+ dec->x + dec->xg_off, ns));
+ PyDict_SetItemString(obj, "xg", xg_obj);
+
+ return obj;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+#endif /* __CTYPES_LC3_C */
+
+#endif /* __CTYPES */
diff --git a/test/decoder.py b/test/decoder.py
new file mode 100755
index 0000000..378871c
--- /dev/null
+++ b/test/decoder.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+import scipy.signal as signal
+import scipy.io.wavfile as wavfile
+import struct
+import argparse
+
+import lc3
+import tables as T, appendix_c as C
+
+import mdct, energy, bwdet, sns, tns, spec, ltpf
+import bitstream
+
+### ------------------------------------------------------------------------ ###
+
+class Decoder:
+
+ def __init__(self, dt_ms, sr_hz):
+
+ dt = { 7.5: T.DT_7M5, 10: T.DT_10M }[dt_ms]
+
+ sr = { 8000: T.SRATE_8K , 16000: T.SRATE_16K, 24000: T.SRATE_24K,
+ 32000: T.SRATE_32K, 48000: T.SRATE_48K }[sr_hz]
+
+ self.sr = sr
+ self.ne = T.NE[dt][sr]
+ self.ns = T.NS[dt][sr]
+
+ self.mdct = mdct.MdctInverse(dt, sr)
+
+ self.bwdet = bwdet.BandwidthDetector(dt, sr)
+ self.spec = spec.SpectrumSynthesis(dt, sr)
+ self.tns = tns.TnsSynthesis(dt)
+ self.sns = sns.SnsSynthesis(dt, sr)
+ self.ltpf = ltpf.LtpfSynthesis(dt, sr)
+
+ def decode(self, data):
+
+ b = bitstream.BitstreamReader(data)
+
+ bw = self.bwdet.get(b)
+ if bw > self.sr:
+ raise ValueError('Invalid bandwidth indication')
+
+ self.spec.load(b)
+
+ self.tns.load(b, bw, len(data))
+
+ pitch = b.read_bit()
+
+ self.sns.load(b)
+
+ if pitch:
+ self.ltpf.load(b)
+ else:
+ self.ltpf.disable()
+
+ x = self.spec.decode(b, bw, len(data))
+
+ return (x, bw, pitch)
+
+ def synthesize(self, x, bw, pitch, nbytes):
+
+ x = self.tns.run(x, bw)
+
+ x = self.sns.run(x)
+
+ x = np.append(x, np.zeros(self.ns - self.ne))
+ x = self.mdct.run(x)
+
+ x = self.ltpf.run(x, len(data))
+
+ return x
+
+ def run(self, data):
+
+ (x, bw, pitch) = self.decode(data)
+
+ x = self.synthesize(x, bw, pitch, len(data))
+
+ return x
+
+### ------------------------------------------------------------------------ ###
+
+def check_appendix_c(dt):
+
+ ok = True
+
+ dec_c = lc3.setup_decoder(int(T.DT_MS[dt] * 1000), 16000)
+
+ for i in range(len(C.BYTES_AC[dt])):
+
+ pcm = lc3.decode(dec_c, bytes(C.BYTES_AC[dt][i]))
+ ok = ok and np.max(np.abs(pcm - C.X_HAT_CLIP[dt][i])) < 1
+
+ return ok
+
+def check():
+
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser(description='LC3 Decoder Test Framework')
+ parser.add_argument('lc3_file',
+ help='Input bitstream file', type=argparse.FileType('r'))
+ parser.add_argument('--pyout',
+ help='Python output file', type=argparse.FileType('w'))
+ parser.add_argument('--cout',
+ help='C output file', type=argparse.FileType('w'))
+ args = parser.parse_args()
+
+ ### File Header ###
+
+ f_lc3 = open(args.lc3_file.name, 'rb')
+
+ header = struct.unpack('=HHHHHHHI', f_lc3.read(18))
+
+ if header[0] != 0xcc1c:
+ raise ValueError('Invalid bitstream file')
+
+ if header[4] != 1:
+ raise ValueError('Unsupported number of channels')
+
+ sr_hz = header[2] * 100
+ bitrate = header[3] * 100
+ nchannels = header[4]
+ dt_ms = header[5] / 100
+
+ f_lc3.seek(header[1])
+
+ ### Setup ###
+
+ dec = Decoder(dt_ms, sr_hz)
+ dec_c = lc3.setup_decoder(int(dt_ms * 1000), sr_hz)
+
+ pcm_c = np.empty(0).astype(np.int16)
+ pcm_py = np.empty(0).astype(np.int16)
+
+ ### Decoding loop ###
+
+ nframes = 0
+
+ while True:
+
+ data = f_lc3.read(2)
+ if len(data) != 2:
+ break
+
+ (frame_nbytes,) = struct.unpack('=H', data)
+
+ print('Decoding frame %d' % nframes, end='\r')
+
+ data = f_lc3.read(frame_nbytes)
+
+ x = dec.run(data)
+ pcm_py = np.append(pcm_py,
+ np.clip(np.round(x), -32768, 32767).astype(np.int16))
+
+ x_c = lc3.decode(dec_c, data)
+ pcm_c = np.append(pcm_c, x_c)
+
+ nframes += 1
+
+ print('done ! %16s' % '')
+
+ ### Terminate ###
+
+ if args.pyout:
+ wavfile.write(args.pyout.name, sr_hz, pcm_py)
+ if args.cout:
+ wavfile.write(args.cout.name, sr_hz, pcm_c)
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/encoder.py b/test/encoder.py
new file mode 100755
index 0000000..6395524
--- /dev/null
+++ b/test/encoder.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+import scipy.signal as signal
+import scipy.io.wavfile as wavfile
+import struct
+import argparse
+
+import lc3
+import tables as T, appendix_c as C
+
+import attdet, ltpf
+import mdct, energy, bwdet, sns, tns, spec
+import bitstream
+
+### ------------------------------------------------------------------------ ###
+
+class Encoder:
+
+ def __init__(self, dt_ms, sr_hz):
+
+ dt = { 7.5: T.DT_7M5, 10: T.DT_10M }[dt_ms]
+
+ sr = { 8000: T.SRATE_8K , 16000: T.SRATE_16K, 24000: T.SRATE_24K,
+ 32000: T.SRATE_32K, 48000: T.SRATE_48K }[sr_hz]
+
+ self.ne = T.NE[dt][sr]
+
+ self.attdet = attdet.AttackDetector(dt, sr)
+ self.ltpf = ltpf.LtpfAnalysis(dt, sr)
+
+ self.mdct = mdct.MdctForward(dt, sr)
+ self.energy = energy.EnergyBand(dt, sr)
+ self.bwdet = bwdet.BandwidthDetector(dt, sr)
+ self.sns = sns.SnsAnalysis(dt, sr)
+ self.tns = tns.TnsAnalysis(dt)
+ self.spec = spec.SpectrumAnalysis(dt, sr)
+
+ def analyse(self, x, nbytes):
+
+ att = self.attdet.run(nbytes, x)
+
+ pitch_present = self.ltpf.run(x)
+
+ x = self.mdct.run(x)[:self.ne]
+
+ (e, nn_flag) = self.energy.compute(x)
+ if nn_flag:
+ self.ltpf.disable()
+
+ bw = self.bwdet.run(e)
+
+ x = self.sns.run(e, att, x)
+
+ x = self.tns.run(x, bw, nn_flag, nbytes)
+
+ (xq, lastnz, x) = self.spec.run(bw, nbytes,
+ self.bwdet.get_nbits(), self.ltpf.get_nbits(),
+ self.sns.get_nbits(), self.tns.get_nbits(), x)
+
+ return pitch_present
+
+ def encode(self, pitch_present, nbytes):
+
+ b = bitstream.BitstreamWriter(nbytes)
+
+ self.bwdet.store(b)
+
+ self.spec.store(b)
+
+ self.tns.store(b)
+
+ b.write_bit(pitch_present)
+
+ self.sns.store(b)
+
+ if pitch_present:
+ self.ltpf.store(b)
+
+ self.spec.encode(b)
+
+ return b.terminate()
+
+ def run(self, x, nbytes):
+
+ pitch_present = self.analyse(x, nbytes)
+
+ data = self.encode(pitch_present, nbytes)
+
+ return data
+
+### ------------------------------------------------------------------------ ###
+
+def check_appendix_c(dt):
+
+ ok = True
+
+ enc_c = lc3.setup_encoder(int(T.DT_MS[dt] * 1000), 16000)
+
+ for i in range(len(C.X_PCM[dt])):
+
+ data = lc3.encode(enc_c, C.X_PCM[dt][i], C.NBYTES[dt])
+ ok = ok and data == C.BYTES_AC[dt][i]
+
+ return ok
+
+def check():
+
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
+
+def dump(data):
+ for i in range(0, len(data), 20):
+ print(''.join('{:02x} '.format(x)
+ for x in data[i:min(i+20, len(data))] ))
+
+if __name__ == "__main__":
+
+ parser = argparse.ArgumentParser(description='LC3 Encoder Test Framework')
+ parser.add_argument('wav_file',
+ help='Input wave file', type=argparse.FileType('r'))
+ parser.add_argument('--bitrate',
+ help='Bitrate in bps', type=int, required=True)
+ parser.add_argument('--dt',
+ help='Frame duration in ms', type=float, default=10)
+ parser.add_argument('--pyout',
+ help='Python output file', type=argparse.FileType('w'))
+ parser.add_argument('--cout',
+ help='C output file', type=argparse.FileType('w'))
+ args = parser.parse_args()
+
+ if args.bitrate < 16000 or args.bitrate > 320000:
+ raise ValueError('Invalid bitate %d bps' % args.bitrate)
+
+ if args.dt not in (7.5, 10):
+ raise ValueError('Invalid frame duration %.1f ms' % args.dt)
+
+ (sr_hz, pcm) = wavfile.read(args.wav_file.name)
+ if sr_hz not in (8000, 16000, 24000, 320000, 48000):
+ raise ValueError('Unsupported input samplerate: %d' % sr_hz)
+ if pcm.ndim != 1:
+ raise ValueError('Only single channel wav file supported')
+
+ ### Setup ###
+
+ enc = Encoder(args.dt, sr_hz)
+ enc_c = lc3.setup_encoder(int(args.dt * 1000), sr_hz)
+
+ frame_samples = int((args.dt * sr_hz) / 1000)
+ frame_nbytes = int((args.bitrate * args.dt) / (1000 * 8))
+
+ ### File Header ###
+
+ f_py = open(args.pyout.name, 'wb') if args.pyout else None
+ f_c = open(args.cout.name , 'wb') if args.cout else None
+
+ header = struct.pack('=HHHHHHHI', 0xcc1c, 18,
+ sr_hz // 100, args.bitrate // 100, 1, int(args.dt * 100), 0, len(pcm))
+
+ for f in (f_py, f_c):
+ if f: f.write(header)
+
+ ### Encoding loop ###
+
+ if len(pcm) % frame_samples > 0:
+ pcm = np.append(pcm, np.zeros(frame_samples - (len(pcm) % frame_samples)))
+
+ for i in range(0, len(pcm), frame_samples):
+
+ print('Encoding frame %d' % (i // frame_samples), end='\r')
+
+ frame_pcm = pcm[i:i+frame_samples]
+
+ data = enc.run(frame_pcm, frame_nbytes)
+ data_c = lc3.encode(enc_c, frame_pcm, frame_nbytes)
+
+ for f in (f_py, f_c):
+ if f: f.write(struct.pack('=H', frame_nbytes))
+
+ if f_py: f_py.write(data)
+ if f_c: f_c.write(data_c)
+
+ print('done ! %16s' % '')
+
+ ### Terminate ###
+
+ for f in (f_py, f_c):
+ if f: f.close()
+
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/energy.py b/test/energy.py
new file mode 100644
index 0000000..a1bc5c3
--- /dev/null
+++ b/test/energy.py
@@ -0,0 +1,92 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+import lc3
+import tables as T, appendix_c as C
+
+### ------------------------------------------------------------------------ ###
+
+class EnergyBand:
+
+ def __init__(self, dt, sr):
+
+ self.dt = dt
+ self.I = T.I[dt][sr]
+
+ def compute(self, x):
+
+ e = [ np.mean(np.square(x[self.I[i]:self.I[i+1]]))
+ for i in range(len(self.I)-1) ]
+
+ e_lo = np.sum(e[:len(e) - [4, 2][self.dt]])
+ e_hi = np.sum(e[len(e) - [4, 2][self.dt]:])
+
+ return np.append(e, np.zeros(64-len(e))), (e_hi > 30*e_lo)
+
+### ------------------------------------------------------------------------ ###
+
+def check_unit(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ ok = True
+
+ nrg = EnergyBand(dt, sr)
+
+ x = (2 * rng.random(T.NS[dt][sr])) - 1
+
+ (e , nn ) = nrg.compute(x)
+ (e_c, nn_c) = lc3.energy_compute(dt, sr, x)
+ ok = ok and np.amax(np.abs(e_c - e)) < 1e-5 and nn_c == nn
+
+ x[15*ns//16:] *= 1e2;
+
+ (e , nn ) = nrg.compute(x)
+ (e_c, nn_c) = lc3.energy_compute(dt, sr, x)
+ ok = ok and np.amax(np.abs(e_c - e)) < 1e-3 and nn_c == nn
+
+ return ok
+
+def check_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ e = lc3.energy_compute(dt, sr, C.X[dt][0])[0]
+ ok = ok and np.amax(np.abs(1 - e/C.E_B[dt][0])) < 1e-6
+
+ e = lc3.energy_compute(dt, sr, C.X[dt][1])[0]
+ ok = ok and np.amax(np.abs(1 - e/C.E_B[dt][1])) < 1e-6
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_unit(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/energy_py.c b/test/energy_py.c
new file mode 100644
index 0000000..3b65ba5
--- /dev/null
+++ b/test/energy_py.c
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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"
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <energy.c>
+#include "ctypes.h"
+
+static PyObject *energy_compute_py(PyObject *m, PyObject *args)
+{
+ unsigned dt, sr;
+ PyObject *x_obj, *e_obj;
+ float *x, *e;
+
+ if (!PyArg_ParseTuple(args, "IIO", &dt, &sr, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ns = LC3_NS(dt, sr);
+
+ CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ns, &x));
+ e_obj = new_1d_ptr(NPY_FLOAT, LC3_NUM_BANDS, &e);
+
+ int nn_flag = lc3_energy_compute(dt, sr, x, e);
+
+ return Py_BuildValue("Ni", e_obj, nn_flag);
+}
+
+static PyMethodDef methods[] = {
+ { "energy_compute", energy_compute_py, METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_energy_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/lc3_py.c b/test/lc3_py.c
new file mode 100644
index 0000000..2984beb
--- /dev/null
+++ b/test/lc3_py.c
@@ -0,0 +1,142 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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"
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <lc3.c>
+
+#define __CTYPES_LC3_C
+#include "ctypes.h"
+
+static PyObject *setup_encoder_py(PyObject *m, PyObject *args)
+{
+ int dt_us, sr_hz;
+
+ if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz))
+ return NULL;
+
+ CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us));
+ CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz));
+
+ lc3_encoder_t encoder = lc3_setup_encoder(dt_us, sr_hz, 0,
+ malloc(lc3_encoder_size(dt_us, sr_hz)));
+
+ PyObject *encoder_obj = from_encoder(NULL, encoder);
+
+ free(encoder);
+
+ return Py_BuildValue("N", encoder_obj);
+}
+
+static PyObject *encode_py(PyObject *m, PyObject *args)
+{
+ PyObject *encoder_obj, *pcm_obj;
+ int nbytes;
+ int16_t *pcm;
+
+ if (!PyArg_ParseTuple(args, "OOi", &encoder_obj, &pcm_obj, &nbytes))
+ return NULL;
+
+ lc3_encoder_t encoder =
+ lc3_setup_encoder(10000, 48000, 0, &(lc3_encoder_mem_48k_t){ });
+
+ CTYPES_CHECK(NULL, encoder_obj = to_encoder(encoder_obj, encoder));
+
+ int ns = LC3_NS(encoder->dt, encoder->sr);
+
+ CTYPES_CHECK("x", pcm_obj = to_1d_ptr(pcm_obj, NPY_INT16, ns, &pcm));
+ CTYPES_CHECK("nbytes", nbytes >= 20 && nbytes <= 400);
+
+ uint8_t out[nbytes];
+
+ lc3_encode(encoder, LC3_PCM_FORMAT_S16, pcm, 1, nbytes, out);
+
+ from_encoder(encoder_obj, encoder);
+
+ return Py_BuildValue("N",
+ PyBytes_FromStringAndSize((const char *)out, nbytes));
+}
+
+static PyObject *setup_decoder_py(PyObject *m, PyObject *args)
+{
+ int dt_us, sr_hz;
+
+ if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz))
+ return NULL;
+
+ CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us));
+ CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz));
+
+ lc3_decoder_t decoder = lc3_setup_decoder(dt_us, sr_hz, 0,
+ malloc(lc3_decoder_size(dt_us, sr_hz)));
+
+ PyObject *decoder_obj = from_decoder(NULL, decoder);
+
+ free(decoder);
+
+ return Py_BuildValue("N", decoder_obj);
+}
+
+static PyObject *decode_py(PyObject *m, PyObject *args)
+{
+ PyObject *decoder_obj, *pcm_obj, *in_obj;
+ int16_t *pcm;
+
+ if (!PyArg_ParseTuple(args, "OO", &decoder_obj, &in_obj))
+ return NULL;
+
+ CTYPES_CHECK("in", in_obj == Py_None || PyBytes_Check(in_obj));
+
+ char *in = in_obj == Py_None ? NULL : PyBytes_AsString(in_obj);
+ int nbytes = in_obj == Py_None ? 0 : PyBytes_Size(in_obj);
+
+ lc3_decoder_t decoder =
+ lc3_setup_decoder(10000, 48000, 0, &(lc3_decoder_mem_48k_t){ });
+
+ CTYPES_CHECK(NULL, decoder_obj = to_decoder(decoder_obj, decoder));
+
+ int ns = LC3_NS(decoder->dt, decoder->sr);
+ pcm_obj = new_1d_ptr(NPY_INT16, ns, &pcm);
+
+ lc3_decode(decoder, in, nbytes, LC3_PCM_FORMAT_S16, pcm, 1);
+
+ from_decoder(decoder_obj, decoder);
+
+ return Py_BuildValue("N", pcm_obj);
+}
+
+static PyMethodDef methods[] = {
+ { "setup_encoder" , setup_encoder_py , METH_VARARGS },
+ { "encode" , encode_py , METH_VARARGS },
+ { "setup_decoder" , setup_decoder_py , METH_VARARGS },
+ { "decode" , decode_py , METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_interface_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/ltpf.py b/test/ltpf.py
new file mode 100644
index 0000000..f60dc71
--- /dev/null
+++ b/test/ltpf.py
@@ -0,0 +1,660 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+import scipy.signal as signal
+
+import lc3
+import tables as T, appendix_c as C
+
+### ------------------------------------------------------------------------ ###
+
+class Resampler_12k8:
+
+ def __init__(self, dt, sr, history = 0):
+
+ self.sr = sr
+ self.p = 192 // T.SRATE_KHZ[sr]
+ self.w = 240 // self.p
+
+ self.n = ((T.DT_MS[dt] * 128) / 10).astype(int)
+ self.d = [ 44, 24 ][dt]
+
+ self.x = np.zeros(self.w + T.NS[dt][sr])
+ self.u = np.zeros(self.n + 2)
+ self.y = np.zeros(self.n + self.d + history)
+
+ def resample(self, x):
+
+ p = self.p
+ w = self.w
+ d = self.d
+ n = self.n
+
+ ### Sliding window
+
+ self.x[:w] = self.x[-w:]
+ self.x[w:] = x
+ self.u[:2] = self.u[-2:]
+
+ if len(self.y) > 2*n + d:
+ self.y[n+d:-n] = self.y[d+2*n:]
+ if len(self.y) > n + d:
+ self.y[-n:] = self.y[:n]
+ self.y[:d] = self.y[n:d+n]
+
+ x = self.x
+ u = self.u
+
+ ### 3.3.9.3 Resampling
+
+ h = np.zeros(240 + p)
+ h[-119:] = T.LTPF_H12K8[:119]
+ h[ :120] = T.LTPF_H12K8[119:]
+
+ for i in range(n):
+ e = (15 * i) // p
+ f = (15 * i) % p
+ k = np.arange(-120, 120 + p, p) - f
+ u[2+i] = p * np.dot( x[e:e+w+1], np.take(h, k) )
+
+ if self.sr == T.SRATE_8K:
+ u = 0.5 * u
+
+ ### 3.3.9.4 High-pass filtering
+
+ b = [ 0.9827947082978771, -1.9655894165957540, 0.9827947082978771 ]
+ a = [ 1 , -1.9652933726226904, 0.9658854605688177 ]
+
+ self.y[d:d+n] = b[0] * u[2:] + b[1] * u[1:-1] + b[2] * u[:-2]
+ for i in range(n):
+ self.y[d+i] -= a[1] * self.y[d+i-1] + a[2] * self.y[d+i-2]
+
+ return self.y
+
+
+class Resampler_6k4:
+
+ def __init__(self, n, history = 0):
+
+ self.x = np.zeros(n + 5)
+ self.n = n // 2
+
+ self.y = np.zeros(self.n + history)
+
+ def resample(self, x):
+
+ n = self.n
+
+ ### Sliding window
+
+ self.x[:3] = self.x[-5:-2]
+ self.x[3:] = x[:2*n+2]
+ x = self.x
+
+ if len(self.y) > 2*n:
+ self.y[n:-n] = self.y[2*n:]
+ if len(self.y) > n:
+ self.y[-n:] = self.y[:n]
+
+ ### 3.3.9.5 Downsampling to 6.4 KHz
+
+ h = [ 0.1236796411180537, 0.2353512128364889, 0.2819382920909148,
+ 0.2353512128364889, 0.1236796411180537 ]
+
+ self.y[:n] = [ np.dot(x[2*i:2*i+5], h) for i in range(self.n) ]
+ return self.y
+
+
+def initial_hp50_state():
+ return { 's1': 0, 's2': 0 }
+
+### ------------------------------------------------------------------------ ###
+
+class Ltpf:
+
+ def __init__(self, dt, sr):
+
+ self.dt = dt
+ self.sr = sr
+
+ (self.pitch_present, self.pitch_index) = (None, None)
+
+
+class LtpfAnalysis(Ltpf):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ self.resampler_12k8 = Resampler_12k8(
+ dt, sr, history = 232)
+
+ self.resampler_6k4 = Resampler_6k4(
+ self.resampler_12k8.n, history = 114)
+
+ self.active = False
+ self.tc = 0
+ self.pitch = 0
+ self.nc = np.zeros(2)
+
+ def get_data(self):
+
+ return { 'active' : self.active,
+ 'pitch_index' : self.pitch_index }
+
+ def get_nbits(self):
+
+ return 1 + 10 * int(self.pitch_present)
+
+ def correlate(self, x, n, k0, k1):
+
+ return [ np.dot(x[:n], np.take(x, np.arange(n) - k)) \
+ for k in range(k0, 1+k1) ]
+
+ def norm_corr(self, x, n, k):
+
+ u = x[:n]
+ v = np.take(x, np.arange(n) - k)
+ uv = np.dot(u, v)
+ return uv / np.sqrt(np.dot(u, u) * np.dot(v, v)) if uv > 0 else 0
+
+ def run(self, x):
+
+ ### 3.3.9.3-4 Resampling
+
+ x_12k8 = self.resampler_12k8.resample(x)
+
+ ### 3.3.9.5-6 Pitch detection algorithm
+
+ x = self.resampler_6k4.resample(x_12k8)
+ n = self.resampler_6k4.n
+
+ r = self.correlate(x, n, 17, 114)
+ rw = r * (1 - 0.5 * np.arange(len(r)) / (len(r) - 1))
+
+ tc = self.tc
+ k0 = max(0, tc-4)
+ k1 = min(len(r)-1, tc+4)
+ t = [ 17 + np.argmax(rw), 17 + k0 + np.argmax(r[k0:1+k1]) ]
+
+ nc = [ self.norm_corr(x, n, t[i]) for i in range(2) ]
+ ti = int(nc[1] > 0.85 * nc[0])
+ self.tc = t[ti] - 17
+
+ self.pitch_present = bool(nc[ti] > 0.6)
+
+ ### 3.3.9.7 Pitch-lag parameter
+
+ if self.pitch_present:
+ tc = self.tc + 17
+
+ x = x_12k8
+ n = self.resampler_12k8.n
+
+ k0 = max( 32, 2*tc-4)
+ k1 = min(228, 2*tc+4)
+ r = self.correlate(x, n, k0-4, k1+4)
+ e = k0 + np.argmax(r[4:-4])
+
+ h = np.zeros(42)
+ h[-15:] = T.LTPF_H4[:15]
+ h[ :16] = T.LTPF_H4[15:]
+
+ m = np.arange(-4, 5)
+ s = [ np.dot( np.take(r, e-k0+4 + m), np.take(h, 4*m-d) ) \
+ for d in range(-3, 4) ]
+
+ f = np.argmax(s[3:]) if e <= 32 else \
+ -3 + np.argmax(s) if e < 127 else \
+ -2 + 2*np.argmax(s[1:-1:2]) if e < 157 else 0
+
+ e -= (f < 0)
+ f += 4*(f < 0)
+
+ self.pitch_index = 4*e + f - 128 if e < 127 else \
+ 2*e + f//2 + 126 if e < 157 else e + 283
+
+ else:
+ e = f = 0
+ self.pitch_index = 0
+
+ ### 3.3.9.8 Activation bit
+
+ h = np.zeros(24)
+ h[-7:] = T.LTPF_HI[:7]
+ h[ :8] = T.LTPF_HI[7:]
+
+ k = np.arange(-2, 3)
+ u = [ np.dot( np.take(x, i-k), np.take(h, 4*k) ) \
+ for i in range(n) ]
+ v = [ np.dot( np.take(x, i-k), np.take(h, 4*k-f) ) \
+ for i in range(-e, n-e) ]
+
+ nc = max(0, np.dot(u, v)) / np.sqrt(np.dot(u, u) * np.dot(v, v)) \
+ if self.pitch_present else 0
+
+ pitch = e + f/4
+
+ if not self.active:
+ active = (self.dt == T.DT_10M or self.nc[1] > 0.94) \
+ and self.nc[0] > 0.94 and nc > 0.94
+
+ else:
+ dp = abs(pitch - self.pitch)
+ dc = nc - self.nc[0]
+ active = nc > 0.9 or (dp < 2 and dc > -0.1 and nc > 0.84)
+
+ if not self.pitch_present:
+ active = False
+ pitch = 0
+ nc = 0
+
+ self.active = active
+ self.pitch = pitch
+ self.nc[1] = self.nc[0]
+ self.nc[0] = nc
+
+ return self.pitch_present
+
+ def disable(self):
+
+ self.active = False
+
+ def store(self, b):
+
+ b.write_uint(self.active, 1)
+ b.write_uint(self.pitch_index, 9)
+
+
+class LtpfSynthesis(Ltpf):
+
+ C_N = [ T.LTPF_N_8K , T.LTPF_N_16K,
+ T.LTPF_N_24K, T.LTPF_N_32K, T.LTPF_N_48K ]
+
+ C_D = [ T.LTPF_D_8K , T.LTPF_D_16K,
+ T.LTPF_D_24K, T.LTPF_D_32K, T.LTPF_D_48K ]
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ self.C_N = LtpfSynthesis.C_N[sr]
+ self.C_D = LtpfSynthesis.C_D[sr]
+
+ ns = T.NS[dt][sr]
+
+ self.active = [ False, False ]
+ self.pitch_index = 0
+
+ max_pitch_12k8 = 228
+ max_pitch = max_pitch_12k8 * T.SRATE_KHZ[self.sr] / 12.8
+ max_pitch = np.ceil(max_pitch).astype(int)
+
+ self.x = np.zeros(ns)
+ self.y = np.zeros(max_pitch + len(self.C_D[0]))
+
+ self.p_e = [ 0, 0 ]
+ self.p_f = [ 0, 0 ]
+ self.c_n = [ None, None ]
+ self.c_d = [ None, None ]
+
+ def load(self, b):
+
+ self.active[0] = bool(b.read_uint(1))
+ self.pitch_index = b.read_uint(9)
+
+ def disable(self):
+
+ self.active[0] = False
+ self.pitch_index = 0
+
+ def run(self, x, nbytes):
+
+ sr = self.sr
+ dt = self.dt
+
+ ### 3.4.9.4 Filter parameters
+
+ pitch_index = self.pitch_index
+
+ if pitch_index >= 440:
+ p_e = pitch_index - 283
+ p_f = 0
+ elif pitch_index >= 380:
+ p_e = pitch_index // 2 - 63
+ p_f = 2*(pitch_index - 2*(p_e + 63))
+ else:
+ p_e = pitch_index // 4 + 32
+ p_f = pitch_index - 4*(p_e - 32)
+
+ p = (p_e + p_f / 4) * T.SRATE_KHZ[self.sr] / 12.8
+
+ self.p_e[0] = int(p * 4 + 0.5) // 4
+ self.p_f[0] = int(p * 4 + 0.5) - 4*self.p_e[0]
+
+ nbits = round(nbytes*80 / T.DT_MS[dt])
+ g_idx = max(nbits // 80, 3+sr) - (3+sr)
+
+ g = [ 0.4, 0.35, 0.3, 0.25 ][g_idx] if g_idx < 4 else 0
+ g_idx = min(g_idx, 3)
+
+ self.c_n[0] = 0.85 * g * LtpfSynthesis.C_N[sr][g_idx]
+ self.c_d[0] = g * LtpfSynthesis.C_D[sr][self.p_f[0]]
+
+ ### 3.4.9.2 Transition handling
+
+ n0 = (T.SRATE_KHZ[sr] * 1000) // 400
+ ns = T.NS[dt][sr]
+
+ x = np.append(x, self.x)
+ y = np.append(np.zeros(ns), self.y)
+ yc = y.copy()
+
+ c_n = self.c_n
+ c_d = self.c_d
+
+ l_n = len(c_n[0])
+ l_d = len(c_d[0])
+
+ d = [ self.p_e[0] - (l_d - 1) // 2,
+ self.p_e[1] - (l_d - 1) // 2 ]
+
+ for k in range(n0):
+
+ if not self.active[0] and not self.active[1]:
+ y[k] = x[k]
+
+ elif self.active[0] and not self.active[1]:
+ u = np.dot(c_n[0], np.take(x, k - np.arange(l_n))) - \
+ np.dot(c_d[0], np.take(y, k - d[0] - np.arange(l_d)))
+ y[k] = x[k] - (k/n0) * u
+
+ elif not self.active[0] and self.active[1]:
+ u = np.dot(c_n[1], np.take(x, k - np.arange(l_n))) - \
+ np.dot(c_d[1], np.take(y, k - d[1] - np.arange(l_d)))
+ y[k] = x[k] - (1 - k/n0) * u
+
+ elif self.p_e[0] == self.p_e[1] and self.p_f[0] == self.p_f[1]:
+ u = np.dot(c_n[0], np.take(x, k - np.arange(l_n))) - \
+ np.dot(c_d[0], np.take(y, k - d[0] - np.arange(l_d)))
+ y[k] = x[k] - u
+
+ else:
+ u = np.dot(c_n[1], np.take(x, k - np.arange(l_n))) - \
+ np.dot(c_d[1], np.take(y, k - d[1] - np.arange(l_d)))
+ yc[k] = x[k] - (1 - k/n0) * u
+
+ u = np.dot(c_n[0], np.take(yc, k - np.arange(l_n))) - \
+ np.dot(c_d[0], np.take(y , k - d[0] - np.arange(l_d)))
+ y[k] = yc[k] - (k/n0) * u
+
+
+ ### 3.4.9.3 Remainder of the frame
+
+ for k in range(n0, ns):
+
+ if not self.active[0]:
+ y[k] = x[k]
+
+ else:
+ u = np.dot(c_n[0], np.take(x, k - np.arange(l_n))) - \
+ np.dot(c_d[0], np.take(y, k - d[0] - np.arange(l_d)))
+ y[k] = x[k] - u
+
+ ### Sliding window
+
+ self.active[1] = self.active[0]
+ self.p_e[1] = self.p_e[0]
+ self.p_f[1] = self.p_f[0]
+ self.c_n[1] = self.c_n[0]
+ self.c_d[1] = self.c_d[0]
+
+ self.x = x[:ns]
+ self.y = np.append(self.y[ns:], y[:ns])
+
+ return y[:ns]
+
+def initial_state():
+ return { 'active' : False, 'pitch': 0, 'nc': np.zeros(2),
+ 'hp50' : initial_hp50_state(),
+ 'x_12k8' : np.zeros(384), 'x_6k4' : np.zeros(178), 'tc' : 0 }
+
+def initial_sstate():
+ return { 'active': False, 'pitch': 0,
+ 'c': np.zeros(2*12), 'x': np.zeros(12) }
+
+### ------------------------------------------------------------------------ ###
+
+def check_resampler(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ nt = (5 * T.SRATE_KHZ[sr]) // 4
+ ok = True
+
+ r = Resampler_12k8(dt, sr)
+
+ hp50_c = initial_hp50_state()
+ x_c = np.zeros(nt)
+ y_c = np.zeros(384)
+
+ for run in range(10):
+
+ x = ((2 * rng.random(ns)) - 1) * (2 ** 15 - 1)
+ y = r.resample(x)
+
+ x_c = np.append(x_c[-nt:], x.astype(np.int16))
+ y_c[:-r.n] = y_c[r.n:]
+ y_c = lc3.ltpf_resample(dt, sr, hp50_c, x_c, y_c)
+
+ ok = ok and np.amax(np.abs(y_c[-r.d-r.n:] - y[:r.d+r.n]/2)) < 4
+
+ return ok
+
+def check_resampler_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ nt = (5 * T.SRATE_KHZ[sr]) // 4
+ n = [ 96, 128 ][dt]
+ k = [ 44, 24 ][dt] + n
+
+ state = initial_hp50_state()
+
+ x = np.append(np.zeros(nt), C.X_PCM[dt][0])
+ y = np.zeros(384)
+ y = lc3.ltpf_resample(dt, sr, state, x, y)
+ u = y[-k:len(C.X_TILDE_12K8D[dt][0])-k]
+
+ ok = ok and np.amax(np.abs(u - C.X_TILDE_12K8D[dt][0]/2)) < 2
+
+ x = np.append(x[-nt:], C.X_PCM[dt][1])
+ y[:-n] = y[n:]
+ y = lc3.ltpf_resample(dt, sr, state, x, y)
+ u = y[-k:len(C.X_TILDE_12K8D[dt][1])-k]
+
+ ok = ok and np.amax(np.abs(u - C.X_TILDE_12K8D[dt][1]/2)) < 2
+
+ return ok
+
+def check_analysis(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ nt = (5 * T.SRATE_KHZ[sr]) // 4
+ ok = True
+
+ state_c = initial_state()
+ x_c = np.zeros(ns+nt)
+
+ ltpf = LtpfAnalysis(dt, sr)
+
+ t = np.arange(100 * ns) / (T.SRATE_KHZ[sr] * 1000)
+ s = signal.chirp(t, f0=10, f1=3e3, t1=t[-1], method='logarithmic')
+
+ for i in range(20):
+
+ x = s[i*ns:(i+1)*ns] * (2 ** 15 - 1)
+
+ pitch_present = ltpf.run(x)
+ data = ltpf.get_data()
+
+ x_c = np.append(x_c[-nt:], x.astype(np.int16))
+ (pitch_present_c, data_c) = lc3.ltpf_analyse(dt, sr, state_c, x_c)
+
+ ok = ok and (not pitch_present or state_c['tc'] == ltpf.tc)
+ ok = ok and np.amax(np.abs(state_c['nc'][0] - ltpf.nc[0])) < 1e-2
+ ok = ok and pitch_present_c == pitch_present
+ ok = ok and data_c['active'] == data['active']
+ ok = ok and data_c['pitch_index'] == data['pitch_index']
+ ok = ok and lc3.ltpf_get_nbits(pitch_present) == ltpf.get_nbits()
+
+ return ok
+
+def check_synthesis(rng, dt, sr):
+
+ ok = True
+
+ ns = T.NS[dt][sr]
+ nd = 18 * T.SRATE_KHZ[sr]
+
+ synthesis = LtpfSynthesis(dt, sr)
+
+ state_c = initial_sstate()
+ x_c = np.zeros(nd+ns)
+
+ for i in range(50):
+ pitch_present = bool(rng.integers(0, 10) >= 1)
+ if not pitch_present:
+ synthesis.disable()
+ else:
+ synthesis.active[0] = bool(rng.integers(0, 5) >= 1)
+ synthesis.pitch_index = rng.integers(0, 512)
+
+ data_c = None if not pitch_present else \
+ { 'active' : synthesis.active[0],
+ 'pitch_index' : synthesis.pitch_index }
+
+ x = rng.random(ns) * 1e4
+ nbytes = rng.integers(10*(2+sr), 10*(6+sr))
+
+ x_c[:nd] = x_c[ns:]
+ x_c[nd:] = x
+
+ y = synthesis.run(x, nbytes)
+ x_c = lc3.ltpf_synthesize(dt, sr, nbytes, state_c, data_c, x_c)
+
+ ok = ok and np.amax(np.abs(x_c[nd:] - y)) < 1e-2
+
+ return ok
+
+def check_analysis_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ nt = (5 * T.SRATE_KHZ[sr]) // 4
+ ok = True
+
+ state = initial_state()
+
+ x = np.append(np.zeros(nt), C.X_PCM[dt][0])
+ (pitch_present, data) = lc3.ltpf_analyse(dt, sr, state, x)
+
+ ok = ok and C.T_CURR[dt][0] - state['tc'] == 17
+ ok = ok and np.amax(np.abs(state['nc'][0] - C.NC_LTPF[dt][0])) < 1e-5
+ ok = ok and pitch_present == C.PITCH_PRESENT[dt][0]
+ ok = ok and data['pitch_index'] == C.PITCH_INDEX[dt][0]
+ ok = ok and data['active'] == C.LTPF_ACTIVE[dt][0]
+
+ x = np.append(x[-nt:], C.X_PCM[dt][1])
+ (pitch_present, data) = lc3.ltpf_analyse(dt, sr, state, x)
+
+ ok = ok and C.T_CURR[dt][1] - state['tc'] == 17
+ ok = ok and np.amax(np.abs(state['nc'][0] - C.NC_LTPF[dt][1])) < 1e-5
+ ok = ok and pitch_present == C.PITCH_PRESENT[dt][1]
+ ok = ok and data['pitch_index'] == C.PITCH_INDEX[dt][1]
+ ok = ok and data['active'] == C.LTPF_ACTIVE[dt][1]
+
+ return ok
+
+def check_synthesis_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ if dt != T.DT_10M:
+ return ok
+
+ ns = T.NS[dt][sr]
+ nd = 18 * T.SRATE_KHZ[sr]
+
+ NBYTES = [ C.LTPF_C2_NBITS // 8, C.LTPF_C3_NBITS // 8,
+ C.LTPF_C4_NBITS // 8, C.LTPF_C5_NBITS // 8 ]
+
+ ACTIVE = [ C.LTPF_C2_ACTIVE, C.LTPF_C3_ACTIVE,
+ C.LTPF_C4_ACTIVE, C.LTPF_C5_ACTIVE ]
+
+ PITCH_INDEX = [ C.LTPF_C2_PITCH_INDEX, C.LTPF_C3_PITCH_INDEX,
+ C.LTPF_C4_PITCH_INDEX, C.LTPF_C5_PITCH_INDEX ]
+
+ X = [ C.LTPF_C2_X, C.LTPF_C3_X,
+ C.LTPF_C4_X, C.LTPF_C5_X ]
+
+ PREV = [ C.LTPF_C2_PREV, C.LTPF_C3_PREV,
+ C.LTPF_C4_PREV, C.LTPF_C5_PREV ]
+
+ TRANS = [ C.LTPF_C2_TRANS, C.LTPF_C3_TRANS,
+ C.LTPF_C4_TRANS, C.LTPF_C5_TRANS ]
+
+ for i in range(4):
+
+ state = initial_sstate()
+ nbytes = NBYTES[i]
+
+ data = { 'active' : ACTIVE[i][0], 'pitch_index' : PITCH_INDEX[i][0] }
+ x = np.append(np.zeros(nd), X[i][0])
+
+ lc3.ltpf_synthesize(dt, sr, nbytes, state, data, x)
+
+ data = { 'active' : ACTIVE[i][1], 'pitch_index' : PITCH_INDEX[i][1] }
+ x[ :nd-ns] = PREV[i][0][-nd+ns:]
+ x[nd-ns:nd] = PREV[i][1]
+ x[nd:nd+ns] = X[i][1]
+
+ y = lc3.ltpf_synthesize(dt, sr, nbytes, state, data, x)[nd:]
+
+ ok = ok and np.amax(np.abs(y - TRANS[i])) < 1e-3
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_resampler(rng, dt, sr)
+ ok = ok and check_analysis(rng, dt, sr)
+ ok = ok and check_synthesis(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_resampler_appendix_c(dt)
+ ok = ok and check_analysis_appendix_c(dt)
+ ok = ok and check_synthesis_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/ltpf_py.c b/test/ltpf_py.c
new file mode 100644
index 0000000..c51eadd
--- /dev/null
+++ b/test/ltpf_py.c
@@ -0,0 +1,138 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <ltpf.c>
+#include "ctypes.h"
+
+static PyObject *resample_py(PyObject *m, PyObject *args)
+{
+ unsigned dt, sr;
+ PyObject *hp50_obj, *x_obj, *y_obj;
+ struct lc3_ltpf_hp50_state hp50;
+ int16_t *x, *y;
+
+ if (!PyArg_ParseTuple(args, "IIOOO", &dt, &sr, &hp50_obj, &x_obj, &y_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+ CTYPES_CHECK(NULL, hp50_obj = to_ltpf_hp50_state(hp50_obj, &hp50));
+
+ int ns = LC3_NS(dt, sr), nt = LC3_NT(dt);
+ int ny = sizeof((struct lc3_ltpf_analysis){ }.x_12k8) / sizeof(int16_t);
+ int n = dt == LC3_DT_7M5 ? 96 : 128;
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_INT16, ns+nt, &x));
+ CTYPES_CHECK("y", y_obj = to_1d_ptr(y_obj, NPY_INT16, ny, &y));
+
+ resample_12k8[sr](&hp50, x + nt, y + (ny - n), n);
+
+ from_ltpf_hp50_state(hp50_obj, &hp50);
+ return Py_BuildValue("O", y_obj);
+}
+
+static PyObject *analyse_py(PyObject *m, PyObject *args)
+{
+ PyObject *ltpf_obj, *x_obj;
+ unsigned dt, sr;
+ struct lc3_ltpf_analysis ltpf;
+ struct lc3_ltpf_data data = { 0 };
+ int16_t *x;
+
+ if (!PyArg_ParseTuple(args, "IIOO", &dt, &sr, &ltpf_obj, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
+ CTYPES_CHECK(NULL, ltpf_obj = to_ltpf_analysis(ltpf_obj, &ltpf));
+
+ int ns = LC3_NS(dt, sr), nt = LC3_NT(sr);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_INT16, ns+nt, &x));
+
+ int pitch_present =
+ lc3_ltpf_analyse(dt, sr, &ltpf, x + nt, &data);
+
+ from_ltpf_analysis(ltpf_obj, &ltpf);
+ return Py_BuildValue("iN", pitch_present, new_ltpf_data(&data));
+}
+
+static PyObject *synthesize_py(PyObject *m, PyObject *args)
+{
+ PyObject *ltpf_obj, *data_obj, *x_obj;
+ struct lc3_ltpf_synthesis ltpf;
+ struct lc3_ltpf_data data;
+ bool pitch_present;
+ unsigned dt, sr;
+ int nbytes;
+ float *x;
+
+ if (!PyArg_ParseTuple(args, "IIiOOO",
+ &dt, &sr, &nbytes, &ltpf_obj, &data_obj, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
+ CTYPES_CHECK("nbytes", nbytes >= 20 && nbytes <= 400);
+ CTYPES_CHECK(NULL, ltpf_obj = to_ltpf_synthesis(ltpf_obj, &ltpf));
+
+ if ((pitch_present = (data_obj != Py_None)))
+ CTYPES_CHECK(NULL, data_obj = to_ltpf_data(data_obj, &data));
+
+ int ns = LC3_NS(dt,sr), nd = 18 * LC3_SRATE_KHZ(sr);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, nd+ns, &x));
+
+ lc3_ltpf_synthesize(dt, sr, nbytes,
+ &ltpf, pitch_present ? &data : NULL, x, x + nd);
+
+ from_ltpf_synthesis(ltpf_obj, &ltpf);
+ return Py_BuildValue("O", x_obj);
+}
+
+static PyObject *get_nbits_py(PyObject *m, PyObject *args)
+{
+ int pitch_present;
+
+ if (!PyArg_ParseTuple(args, "i", &pitch_present))
+ return NULL;
+
+ int nbits = lc3_ltpf_get_nbits(pitch_present);
+
+ return Py_BuildValue("i", nbits);
+}
+
+static PyMethodDef methods[] = {
+ { "ltpf_resample" , resample_py , METH_VARARGS },
+ { "ltpf_analyse" , analyse_py , METH_VARARGS },
+ { "ltpf_synthesize", synthesize_py, METH_VARARGS },
+ { "ltpf_get_nbits" , get_nbits_py , METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_ltpf_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/makefile.mk b/test/makefile.mk
new file mode 100644
index 0000000..a7bcb04
--- /dev/null
+++ b/test/makefile.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+test_py:
+ $(V)cd $(TEST_DIR) && python3 setup.py && PYTHONPATH=build python3 run.py
+
+.PHONY: test test-clean
+
+test: test_py
+
+test-clean:
+ $(V)cd $(TEST_DIR) && python3 setup.py clean > /tmp/zero
+
+-include $(TEST_DIR)/arm/makefile.mk
+-include $(TEST_DIR)/neon/makefile.mk
+
+clean-all: test-clean
diff --git a/test/mdct.py b/test/mdct.py
new file mode 100644
index 0000000..4e6d191
--- /dev/null
+++ b/test/mdct.py
@@ -0,0 +1,198 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+import scipy.fft
+
+import lc3
+import tables as T, appendix_c as C
+
+### ------------------------------------------------------------------------ ###
+
+class Mdct:
+
+ W = [ [ T.W_7M5_60, T.W_7M5_120, T.W_7M5_180, T.W_7M5_240, T.W_7M5_360 ],
+ [ T.W_10M_80, T.W_10M_160, T.W_10M_240, T.W_10M_320, T.W_10M_480 ] ]
+
+ def __init__(self, dt, sr):
+
+ self.ns = T.NS[dt][sr]
+ self.nd = T.ND[dt][sr]
+
+ self.t = np.zeros(2*self.ns)
+ self.w = Mdct.W[dt][sr]
+
+
+class MdctForward(Mdct):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ def run(self, x):
+
+ ns = self.ns
+ nd = self.nd
+
+ self.t[nd:nd+ns] = x
+ t = self.t * self.w
+ self.t[0:nd] = x[ns-nd:]
+
+ n = len(t)
+ n2 = n // 2
+
+ z = t * np.exp(-2j * np.pi * np.arange(n) / (2*n))
+ z = scipy.fft.fft(z)[:n2]
+ z = z * np.exp(-2j * np.pi *
+ (n2/2 + 0.5) * (np.arange(n2) + 0.5) / (2 * n2))
+ return np.real(z) * np.sqrt(2/n2)
+
+
+class MdctInverse(Mdct):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ def run(self, x):
+
+ ns = self.ns
+ nd = self.nd
+
+ n = len(x)
+
+ x = np.append(x, -x[::-1])
+ z = x * np.exp(2j * np.pi * (n/2 + 0.5) * np.arange(2*n) / (2*n))
+ z = scipy.fft.ifft(z) * n
+ z = z * np.exp(2j * np.pi * (np.arange(2*n) + (n/2 + 0.5)) / (4*n))
+ t = np.real(z) * np.sqrt(2/n)
+
+ t = t * self.w[::-1]
+
+ y = np.empty(ns)
+ y[:nd] = t[ns-nd:ns] + self.t[2*ns-nd:]
+ y[nd:] = t[ns:2*ns-nd]
+ self.t = t
+
+ return y
+
+### ------------------------------------------------------------------------ ###
+
+def check_forward_unit(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ nd = T.ND[dt][sr]
+ ok = True
+
+ x = (2 * rng.random(ns)) - 1
+
+ y = [ None ] * 2
+ y_c = [ None ] * 2
+
+ mdct = MdctForward(dt, sr)
+ y[0] = mdct.run(x)
+ y[1] = mdct.run(x)
+
+ (y_c[0], d_c) = lc3.mdct_forward(dt, sr, x, np.zeros(nd))
+ y_c[1] = lc3.mdct_forward(dt, sr, x, d_c)[0]
+
+ ok = ok and np.amax(np.abs(y[0] - y_c[0])) < 1e-5
+ ok = ok and np.amax(np.abs(y[1] - y_c[1])) < 1e-5
+
+ return ok
+
+
+def check_forward_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ns = T.NS[dt][sr]
+ nd = T.ND[dt][sr]
+ ok = True
+
+ (y, d) = lc3.mdct_forward(dt, sr, C.X_PCM[dt][0], np.zeros(nd))
+ ok = ok and np.amax(np.abs(y - C.X[dt][0])) < 1e-1
+
+ (y, d) = lc3.mdct_forward(dt, sr, C.X_PCM[dt][1], d)
+ ok = ok and np.amax(np.abs(y - C.X[dt][1])) < 1e-1
+
+ return ok
+
+
+def check_inverse_unit(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ nd = [ (23 * ns) // 30, (5 * ns) // 8 ][dt]
+ ok = True
+
+ x = (2 * rng.random(ns)) - 1
+
+ y = [ None ] * 2
+ y_c = [ None ] * 2
+
+ mdct = MdctInverse(dt, sr)
+ y[0] = mdct.run(x)
+ y[1] = mdct.run(x)
+
+ (y_c[0], d_c) = lc3.mdct_inverse(dt, sr, x, np.zeros(nd))
+ y_c[1] = lc3.mdct_inverse(dt, sr, x, d_c)[0]
+
+ ok = ok and np.amax(np.abs(y[0] - y_c[0])) < 1e-5
+ ok = ok and np.amax(np.abs(y[1] - y_c[1])) < 1e-5
+
+ return ok
+
+
+def check_inverse_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ns = T.NS[dt][sr]
+ nd = [ (23 * ns) // 30, (5 * ns) // 8 ][dt]
+ ok = True
+
+ (y, d0) = lc3.mdct_inverse(dt, sr, C.X_HAT_SNS[dt][0], np.zeros(nd))
+ yr = C.T_HAT_MDCT[dt][0][ns-nd:2*ns-nd]
+ dr = C.T_HAT_MDCT[dt][0][2*ns-nd:]
+
+ ok = ok and np.amax(np.abs(yr - y )) < 1e-1
+ ok = ok and np.amax(np.abs(dr - d0)) < 1e-1
+
+ (y, d1) = lc3.mdct_inverse(dt, sr, C.X_HAT_SNS[dt][1], d0)
+ yr[ :nd] = C.T_HAT_MDCT[dt][1][ns-nd:ns] + d0
+ yr[nd:ns] = C.T_HAT_MDCT[dt][1][ns:2*ns-nd]
+ dr = C.T_HAT_MDCT[dt][1][2*ns-nd:]
+
+ ok = ok and np.amax(np.abs(yr - y )) < 1e-1
+ ok = ok and np.amax(np.abs(dr - d1)) < 1e-1
+
+ return ok
+
+
+def check():
+
+ rng = np.random.default_rng(1234)
+
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_forward_unit(rng, dt, sr)
+ ok = ok and check_inverse_unit(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_forward_appendix_c(dt)
+ ok = ok and check_inverse_appendix_c(dt)
+
+ return ok
diff --git a/test/mdct_py.c b/test/mdct_py.c
new file mode 100644
index 0000000..3479503
--- /dev/null
+++ b/test/mdct_py.c
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <mdct.c>
+#include "ctypes.h"
+
+
+static PyObject *mdct_forward_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj, *xd_obj, *y_obj, *d_obj;
+ enum lc3_dt dt;
+ enum lc3_srate sr;
+ float *x, *xd, *y, *d;
+
+ if (!PyArg_ParseTuple(args, "iiOO", &dt, &sr, &x_obj, &xd_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ns = LC3_NS(dt, sr), nd = LC3_ND(dt, sr);
+
+ CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ns, &x));
+ CTYPES_CHECK("xd", to_1d_ptr(xd_obj, NPY_FLOAT, nd, &xd));
+ d_obj = new_1d_ptr(NPY_FLOAT, nd, &d);
+ y_obj = new_1d_ptr(NPY_FLOAT, ns, &y);
+
+ memcpy(d, xd, nd * sizeof(float));
+
+ lc3_mdct_forward(dt, sr, sr, x, d, y);
+
+ return Py_BuildValue("NN", y_obj, d_obj);
+}
+
+static PyObject *mdct_inverse_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj, *xd_obj, *d_obj, *y_obj;
+ enum lc3_dt dt;
+ enum lc3_srate sr;
+ float *x, *xd, *d, *y;
+
+ if (!PyArg_ParseTuple(args, "iiOO", &dt, &sr, &x_obj, &xd_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ns = LC3_NS(dt, sr), nd = LC3_ND(dt, sr);
+
+ CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ns, &x));
+ CTYPES_CHECK("xd", to_1d_ptr(xd_obj, NPY_FLOAT, nd, &xd));
+ d_obj = new_1d_ptr(NPY_FLOAT, nd, &d);
+ y_obj = new_1d_ptr(NPY_FLOAT, ns, &y);
+
+ memcpy(d, xd, nd * sizeof(float));
+
+ lc3_mdct_inverse(dt, sr, sr, x, d, y);
+
+ return Py_BuildValue("NN", y_obj, d_obj);
+}
+
+static PyMethodDef methods[] = {
+ { "mdct_forward", mdct_forward_py, METH_VARARGS },
+ { "mdct_inverse", mdct_inverse_py, METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_mdct_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/module_py.c b/test/module_py.c
new file mode 100644
index 0000000..6163a9c
--- /dev/null
+++ b/test/module_py.c
@@ -0,0 +1,53 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+
+static struct PyModuleDef module_def = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "LC3",
+ .m_doc = "LC3 Test Python Module",
+ .m_size = -1,
+};
+
+PyMODINIT_FUNC lc3_mdct_py_init(PyObject *);
+PyMODINIT_FUNC lc3_energy_py_init(PyObject *);
+PyMODINIT_FUNC lc3_attdet_py_init(PyObject *);
+PyMODINIT_FUNC lc3_bwdet_py_init(PyObject *);
+PyMODINIT_FUNC lc3_ltpf_py_init(PyObject *);
+PyMODINIT_FUNC lc3_sns_py_init(PyObject *);
+PyMODINIT_FUNC lc3_tns_py_init(PyObject *);
+PyMODINIT_FUNC lc3_spec_py_init(PyObject *);
+PyMODINIT_FUNC lc3_interface_py_init(PyObject *);
+
+PyMODINIT_FUNC PyInit_lc3(void)
+{
+ PyObject *m = PyModule_Create(&module_def);
+
+ if (m) m = lc3_mdct_py_init(m);
+ if (m) m = lc3_energy_py_init(m);
+ if (m) m = lc3_attdet_py_init(m);
+ if (m) m = lc3_bwdet_py_init(m);
+ if (m) m = lc3_ltpf_py_init(m);
+ if (m) m = lc3_sns_py_init(m);
+ if (m) m = lc3_tns_py_init(m);
+ if (m) m = lc3_spec_py_init(m);
+ if (m) m = lc3_interface_py_init(m);
+
+ return m;
+}
diff --git a/test/neon/ltpf_neon.c b/test/neon/ltpf_neon.c
new file mode 100644
index 0000000..0577bd1
--- /dev/null
+++ b/test/neon/ltpf_neon.c
@@ -0,0 +1,116 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 "neon.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* -------------------------------------------------------------------------- */
+
+#define TEST_NEON
+#include <ltpf.c>
+
+void lc3_put_bits_generic(lc3_bits_t *a, unsigned b, int c)
+{ (void)a, (void)b, (void)c; }
+
+unsigned lc3_get_bits_generic(struct lc3_bits *a, int b)
+{ return (void)a, (void)b, 0; }
+
+/* -------------------------------------------------------------------------- */
+
+static int check_resampler()
+{
+ int16_t __x[60+480], *x = __x + 60;
+ for (int i = -60; i < 480; i++)
+ x[i] = rand() & 0xffff;
+
+ struct lc3_ltpf_hp50_state hp50 = { 0 }, hp50_neon = { 0 };
+ int16_t y[128], y_neon[128];
+
+ resample_16k_12k8(&hp50, x, y, 128);
+ neon_resample_16k_12k8(&hp50_neon, x, y_neon, 128);
+ if (memcmp(y, y_neon, 128 * sizeof(*y)) != 0)
+ return printf("Error\n"), -1;
+
+ resample_32k_12k8(&hp50, x, y, 128);
+ neon_resample_32k_12k8(&hp50_neon, x, y_neon, 128);
+ if (memcmp(y, y_neon, 128 * sizeof(*y)) != 0)
+ return printf("Error\n"), -1;
+
+ resample_48k_12k8(&hp50, x, y, 128);
+ neon_resample_48k_12k8(&hp50_neon, x, y_neon, 128);
+ if (memcmp(y, y_neon, 128 * sizeof(*y)) != 0)
+ return -1;
+
+ return 0;
+}
+
+static int check_dot()
+{
+ int16_t x[200];
+ for (int i = 0; i < 200; i++)
+ x[i] = rand() & 0xffff;
+
+ float y = dot(x, x+3, 128);
+ float y_neon = neon_dot(x, x+3, 128);
+ if (y != y_neon)
+ return -1;
+
+ return 0;
+}
+
+static int check_correlate()
+{
+ int16_t alignas(4) a[500], b[500];
+ float y[100], y_neon[100];
+
+ for (int i = 0; i < 500; i++) {
+ a[i] = rand() & 0xffff;
+ b[i] = rand() & 0xffff;
+ }
+
+ correlate(a, b+200, 128, y, 100);
+ neon_correlate(a, b+200, 128, y_neon, 100);
+ if (memcmp(y, y_neon, 100 * sizeof(*y)) != 0)
+ return -1;
+
+ correlate(a, b+199, 128, y, 99);
+ neon_correlate(a, b+199, 128, y_neon, 99);
+ if (memcmp(y, y_neon, 99 * sizeof(*y)) != 0)
+ return -1;
+
+ return 0;
+}
+
+int check_ltpf(void)
+{
+ int ret;
+
+ if ((ret = check_resampler()) < 0)
+ return ret;
+
+ if ((ret = check_dot()) < 0)
+ return ret;
+
+ if ((ret = check_correlate()) < 0)
+ return ret;
+
+ return 0;
+}
diff --git a/test/neon/makefile.mk b/test/neon/makefile.mk
new file mode 100644
index 0000000..18fc351
--- /dev/null
+++ b/test/neon/makefile.mk
@@ -0,0 +1,32 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+test_neon_src += \
+ $(TEST_DIR)/neon/test_neon.c \
+ $(TEST_DIR)/neon/ltpf_neon.c \
+ $(TEST_DIR)/neon/mdct_neon.c \
+ $(SRC_DIR)/tables.c
+
+test_neon_include += $(SRC_DIR)
+test_neon_ldlibs += m
+
+$(eval $(call add-bin,test_neon))
+
+test_neon: $(test_neon_bin)
+ @echo " RUN $(notdir $<)"
+ $(V)$<
+
+test: test_neon
diff --git a/test/neon/mdct_neon.c b/test/neon/mdct_neon.c
new file mode 100644
index 0000000..d5f3888
--- /dev/null
+++ b/test/neon/mdct_neon.c
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 "neon.h"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/* -------------------------------------------------------------------------- */
+
+#define TEST_NEON
+#include <mdct.c>
+
+/* -------------------------------------------------------------------------- */
+
+static int check_fft(void)
+{
+ struct lc3_complex x[240];
+ struct lc3_complex y[240], y_neon[240];
+
+ for (int i = 0; i < 240; i++) {
+ x[i].re = (double)rand() / RAND_MAX;
+ x[i].im = (double)rand() / RAND_MAX;
+ }
+
+ fft_5(x, y, 240/5);
+ neon_fft_5(x, y_neon, 240/5);
+ for (int i = 0; i < 240; i++)
+ if (fabsf(y[i].re - y_neon[i].re) > 1e-6f ||
+ fabsf(y[i].im - y_neon[i].im) > 1e-6f )
+ return -1;
+
+ fft_bf3(lc3_fft_twiddles_bf3[0], x, y, 240/15);
+ neon_fft_bf3(lc3_fft_twiddles_bf3[0], x, y_neon, 240/15);
+ for (int i = 0; i < 240; i++)
+ if (fabsf(y[i].re - y_neon[i].re) > 1e-6f ||
+ fabsf(y[i].im - y_neon[i].im) > 1e-6f )
+ return -1;
+
+ fft_bf2(lc3_fft_twiddles_bf2[0][1], x, y, 240/30);
+ neon_fft_bf2(lc3_fft_twiddles_bf2[0][1], x, y_neon, 240/30);
+ for (int i = 0; i < 240; i++)
+ if (fabsf(y[i].re - y_neon[i].re) > 1e-6f ||
+ fabsf(y[i].im - y_neon[i].im) > 1e-6f )
+ return -1;
+
+ return 0;
+}
+
+int check_mdct(void)
+{
+ int ret;
+
+ if ((ret = check_fft()) < 0)
+ return ret;
+
+ return 0;
+}
diff --git a/test/neon/neon.h b/test/neon/neon.h
new file mode 100644
index 0000000..aaca818
--- /dev/null
+++ b/test/neon/neon.h
@@ -0,0 +1,329 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#if __ARM_NEON && __ARM_ARCH_ISA_A64
+
+#include <arm_neon.h>
+
+#else
+
+#include <stdint.h>
+
+
+/* ----------------------------------------------------------------------------
+ * Integer
+ * -------------------------------------------------------------------------- */
+
+typedef struct { int16_t e[4]; } int16x4_t;
+
+typedef struct { int16_t e[8]; } int16x8_t;
+typedef struct { int32_t e[4]; } int32x4_t;
+typedef struct { int64_t e[2]; } int64x2_t;
+
+
+/**
+ * Load / Store
+ */
+
+__attribute__((unused))
+static int16x4_t vld1_s16(const int16_t *p)
+{
+ return (int16x4_t){ { p[0], p[1], p[2], p[3] } };
+}
+
+
+/**
+ * Arithmetic
+ */
+
+__attribute__((unused))
+static int32x4_t vmull_s16(int16x4_t a, int16x4_t b)
+{
+ return (int32x4_t){ { a.e[0] * b.e[0], a.e[1] * b.e[1],
+ a.e[2] * b.e[2], a.e[3] * b.e[3] } };
+}
+
+__attribute__((unused))
+static int32x4_t vmlal_s16(int32x4_t r, int16x4_t a, int16x4_t b)
+{
+ return (int32x4_t){ {
+ r.e[0] + a.e[0] * b.e[0], r.e[1] + a.e[1] * b.e[1],
+ r.e[2] + a.e[2] * b.e[2], r.e[3] + a.e[3] * b.e[3] } };
+}
+
+__attribute__((unused))
+static int64x2_t vpadalq_s32(int64x2_t a, int32x4_t b)
+{
+ int64x2_t r;
+
+ r.e[0] = a.e[0] + ((int64_t)b.e[0] + b.e[1]);
+ r.e[1] = a.e[1] + ((int64_t)b.e[2] + b.e[3]);
+
+ return r;
+}
+
+
+/**
+ * Reduce
+ */
+
+__attribute__((unused))
+static int32_t vaddvq_s32(int32x4_t v)
+{
+ return v.e[0] + v.e[1] + v.e[2] + v.e[3];
+}
+
+__attribute__((unused))
+static int64_t vaddvq_s64(int64x2_t v)
+{
+ return v.e[0] + v.e[1];
+}
+
+
+/**
+ * Manipulation
+ */
+
+__attribute__((unused))
+static int16x4_t vext_s16(int16x4_t a, int16x4_t b, const int n)
+{
+ int16_t x[] = { a.e[0], a.e[1], a.e[2], a.e[3],
+ b.e[0], b.e[1], b.e[2], b.e[3] };
+
+ return (int16x4_t){ { x[n], x[n+1], x[n+2], x[n+3] } };
+}
+
+__attribute__((unused))
+static int32x4_t vmovq_n_s32(uint32_t v)
+{
+ return (int32x4_t){ { v, v, v, v } };
+}
+
+__attribute__((unused))
+static int64x2_t vmovq_n_s64(int64_t v)
+{
+ return (int64x2_t){ { v, v, } };
+}
+
+
+
+/* ----------------------------------------------------------------------------
+ * Floating Point
+ * -------------------------------------------------------------------------- */
+
+typedef struct { float e[2]; } float32x2_t;
+typedef struct { float e[4]; } float32x4_t;
+
+typedef struct { float32x2_t val[2]; } float32x2x2_t;
+typedef struct { float32x4_t val[2]; } float32x4x2_t;
+
+
+/**
+ * Load / Store
+ */
+
+__attribute__((unused))
+static float32x2_t vld1_f32(const float *p)
+{
+ return (float32x2_t){ { p[0], p[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vld1q_f32(const float *p)
+{
+ return (float32x4_t){ { p[0], p[1], p[2], p[3] } };
+}
+
+__attribute__((unused))
+static float32x4_t vld1q_dup_f32(const float *p)
+{
+ return (float32x4_t){ { p[0], p[0], p[0], p[0] } };
+}
+
+__attribute__((unused))
+static float32x2x2_t vld2_f32(const float *p)
+{
+ return (float32x2x2_t){ .val[0] = { { p[0], p[2] } },
+ .val[1] = { { p[1], p[3] } } };
+}
+
+__attribute__((unused))
+static float32x4x2_t vld2q_f32(const float *p)
+{
+ return (float32x4x2_t){ .val[0] = { { p[0], p[2], p[4], p[6] } },
+ .val[1] = { { p[1], p[3], p[5], p[7] } } };
+}
+
+__attribute__((unused))
+static void vst1_f32(float *p, float32x2_t v)
+{
+ p[0] = v.e[0], p[1] = v.e[1];
+}
+
+__attribute__((unused))
+static void vst1q_f32(float *p, float32x4_t v)
+{
+ p[0] = v.e[0], p[1] = v.e[1], p[2] = v.e[2], p[3] = v.e[3];
+}
+
+/**
+ * Arithmetic
+ */
+
+__attribute__((unused))
+static float32x2_t vneg_f32(float32x2_t a)
+{
+ return (float32x2_t){ { -a.e[0], -a.e[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vnegq_f32(float32x4_t a)
+{
+ return (float32x4_t){ { -a.e[0], -a.e[1], -a.e[2], -a.e[3] } };
+}
+
+__attribute__((unused))
+static float32x4_t vaddq_f32(float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t){ { a.e[0] + b.e[0], a.e[1] + b.e[1],
+ a.e[2] + b.e[2], a.e[3] + b.e[3] } };
+}
+
+__attribute__((unused))
+static float32x4_t vsubq_f32(float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t){ { a.e[0] - b.e[0], a.e[1] - b.e[1],
+ a.e[2] - b.e[2], a.e[3] - b.e[3] } };
+}
+
+__attribute__((unused))
+static float32x2_t vfma_f32(float32x2_t a, float32x2_t b, float32x2_t c)
+{
+ return (float32x2_t){ {
+ a.e[0] + b.e[0] * c.e[0], a.e[1] + b.e[1] * c.e[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vfmaq_f32(float32x4_t a, float32x4_t b, float32x4_t c)
+{
+ return (float32x4_t){ {
+ a.e[0] + b.e[0] * c.e[0], a.e[1] + b.e[1] * c.e[1],
+ a.e[2] + b.e[2] * c.e[2], a.e[3] + b.e[3] * c.e[3] } };
+}
+
+__attribute__((unused))
+static float32x2_t vfms_f32(float32x2_t a, float32x2_t b, float32x2_t c)
+{
+ return (float32x2_t){ {
+ a.e[0] - b.e[0] * c.e[0], a.e[1] - b.e[1] * c.e[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vfmsq_f32(float32x4_t a, float32x4_t b, float32x4_t c)
+{
+ return (float32x4_t){ {
+ a.e[0] - b.e[0] * c.e[0], a.e[1] - b.e[1] * c.e[1],
+ a.e[2] - b.e[2] * c.e[2], a.e[3] - b.e[3] * c.e[3] } };
+}
+
+
+/**
+ * Manipulation
+ */
+
+__attribute__((unused))
+static float32x2_t vcreate_f32(uint64_t u)
+{
+ float *f = (float *)&u;
+ return (float32x2_t){ { f[0] , f[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vcombine_f32(float32x2_t a, float32x2_t b)
+{
+ return (float32x4_t){ { a.e[0], a.e[1], b.e[0], b.e[1] } };
+}
+
+__attribute__((unused))
+static float32x2_t vget_low_f32(float32x4_t a)
+{
+ return (float32x2_t){ { a.e[0], a.e[1] } };
+}
+
+__attribute__((unused))
+static float32x2_t vget_high_f32(float32x4_t a)
+{
+ return (float32x2_t){ { a.e[2], a.e[3] } };
+}
+
+__attribute__((unused))
+static float32x4_t vmovq_n_f32(float v)
+{
+ return (float32x4_t){ { v, v, v, v } };
+}
+
+__attribute__((unused))
+static float32x2_t vrev64_f32(float32x2_t v)
+{
+ return (float32x2_t){ { v.e[1], v.e[0] } };
+}
+
+__attribute__((unused))
+static float32x4_t vrev64q_f32(float32x4_t v)
+{
+ return (float32x4_t){ { v.e[1], v.e[0], v.e[3], v.e[2] } };
+}
+
+__attribute__((unused))
+static float32x2_t vtrn1_f32(float32x2_t a, float32x2_t b)
+{
+ return (float32x2_t){ { a.e[0], b.e[0] } };
+}
+
+__attribute__((unused))
+static float32x2_t vtrn2_f32(float32x2_t a, float32x2_t b)
+{
+ return (float32x2_t){ { a.e[1], b.e[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vtrn1q_f32(float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t){ { a.e[0], b.e[0], a.e[2], b.e[2] } };
+}
+
+__attribute__((unused))
+static float32x4_t vtrn2q_f32(float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t){ { a.e[1], b.e[1], a.e[3], b.e[3] } };
+}
+
+__attribute__((unused))
+static float32x4_t vzip1q_f32(float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t){ { a.e[0], b.e[0], a.e[1], b.e[1] } };
+}
+
+__attribute__((unused))
+static float32x4_t vzip2q_f32(float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t){ { a.e[2], b.e[2], a.e[3], b.e[3] } };
+}
+
+
+#endif /* __ARM_NEON */
diff --git a/test/neon/test_neon.c b/test/neon/test_neon.c
new file mode 100644
index 0000000..50622c7
--- /dev/null
+++ b/test/neon/test_neon.c
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+
+int check_ltpf(void);
+int check_mdct(void);
+
+int main()
+{
+ int r, ret = 0;
+
+ printf("Checking LTPF Neon... "); fflush(stdout);
+ printf("%s\n", (r = check_ltpf()) == 0 ? "OK" : "Failed");
+ ret = ret || r;
+
+ printf("Checking MDCT Neon... "); fflush(stdout);
+ printf("%s\n", (r = check_mdct()) == 0 ? "OK" : "Failed");
+ ret = ret || r;
+
+ return ret;
+}
diff --git a/test/run.py b/test/run.py
new file mode 100755
index 0000000..293527f
--- /dev/null
+++ b/test/run.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import mdct, energy, bwdet, attdet
+import ltpf, sns, tns, spec, encoder, decoder
+
+ok = True
+
+for m in [ ( mdct , "MDCT" ),
+ ( energy , "Energy Band" ),
+ ( bwdet , "Bandwidth Detector" ),
+ ( attdet , "Attack Detector" ),
+ ( ltpf , "Long Term Postfilter" ),
+ ( sns , "Spectral Noise Shaping" ),
+ ( tns , "Temporal Noise Shaping" ),
+ ( spec , "Spectral Quantization" ),
+ ( encoder , "Encoder" ),
+ ( decoder , "Decoder" ) ]:
+
+ print('[{:^6}] {:}'.format('...', m[1]), end='\r', flush=True)
+ ret = m[0].check()
+ print('[{:^6}] {:}'.format('OK' if ret else 'FAILED', m[1]))
+
+ ok = ok and ret
+
+exit(0 if ok else 1)
diff --git a/test/setup.py b/test/setup.py
new file mode 100755
index 0000000..7cbcc4a
--- /dev/null
+++ b/test/setup.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+from setuptools import setup, Extension
+import os, sys, glob
+
+if len(sys.argv) <= 1:
+ sys.argv = sys.argv + [
+ 'build', '--build-platlib', os.getcwd() + os.sep + 'build' ]
+
+INC_DIR = '..' + os.sep + 'include'
+SRC_DIR = '..' + os.sep + 'src'
+
+sources = glob.glob('*_py.c') + \
+ [ SRC_DIR + os.sep + 'tables.c',
+ SRC_DIR + os.sep + 'bits.c',
+ SRC_DIR + os.sep + 'plc.c' ]
+
+depends = [ 'ctypes.h' ] + \
+ glob.glob(INC_DIR + os.sep + '*.h') + \
+ glob.glob(SRC_DIR + os.sep + '*.[c,h]')
+
+includes = [ SRC_DIR, INC_DIR ]
+
+extension = Extension('lc3',
+ extra_compile_args = [ '-std=c11', '-ffast-math' ],
+ define_macros = [ ('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION') ],
+ sources = sources,
+ depends = depends,
+ include_dirs = includes)
+
+setup(name = 'LC3',
+ version = '1.0',
+ description = 'LC3 Test Python Module',
+ ext_modules = [ extension ])
diff --git a/test/sns.py b/test/sns.py
new file mode 100644
index 0000000..8740aab
--- /dev/null
+++ b/test/sns.py
@@ -0,0 +1,594 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+import scipy.fftpack as fftpack
+
+import lc3
+import tables as T, appendix_c as C
+
+### ------------------------------------------------------------------------ ###
+
+class Sns:
+
+ def __init__(self, dt, sr):
+
+ self.dt = dt
+ self.sr = sr
+
+ (self.ind_lf, self.ind_hf, self.shape, self.gain) = \
+ (None, None, None, None)
+
+ (self.idx_a, self.ls_a, self.idx_b, self.ls_b) = \
+ (None, None, None, None)
+
+ def get_data(self):
+
+ data = { 'lfcb' : self.ind_lf, 'hfcb' : self.ind_hf,
+ 'shape' : self.shape, 'gain' : self.gain,
+ 'idx_a' : self.idx_a, 'ls_a' : self.ls_a }
+
+ if self.idx_b is not None:
+ data.update({ 'idx_b' : self.idx_b, 'ls_b' : self.ls_b })
+
+ return data
+
+ def get_nbits(self):
+
+ return 38
+
+ def spectral_shaping(self, scf, inv, x):
+
+ ## 3.3.7.4 Scale factors interpolation
+
+ scf_i = np.empty(4*len(scf))
+ scf_i[0 ] = scf[0]
+ scf_i[1 ] = scf[0]
+ scf_i[2:62:4] = scf[:15] + 1/8 * (scf[1:] - scf[:15])
+ scf_i[3:63:4] = scf[:15] + 3/8 * (scf[1:] - scf[:15])
+ scf_i[4:64:4] = scf[:15] + 5/8 * (scf[1:] - scf[:15])
+ scf_i[5:64:4] = scf[:15] + 7/8 * (scf[1:] - scf[:15])
+ scf_i[62 ] = scf[15 ] + 1/8 * (scf[15] - scf[14 ])
+ scf_i[63 ] = scf[15 ] + 3/8 * (scf[15] - scf[14 ])
+
+ n2 = 64 - min(len(x), 64)
+
+ for i in range(n2):
+ scf_i[i] = 0.5 * (scf_i[2*i] + scf_i[2*i+1])
+ scf_i = np.append(scf_i[:n2], scf_i[2*n2:])
+
+ g_sns = np.power(2, [ -scf_i, scf_i ][inv])
+
+ ## 3.3.7.4 Spectral shaping
+
+ y = np.empty(len(x))
+ I = T.I[self.dt][self.sr]
+
+ for b in range(len(g_sns)):
+ y[I[b]:I[b+1]] = x[I[b]:I[b+1]] * g_sns[b]
+
+ return y
+
+
+class SnsAnalysis(Sns):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ def compute_scale_factors(self, e, att):
+
+ dt = self.dt
+
+ ## 3.3.7.2.1 Padding
+
+ n2 = 64 - len(e)
+
+ e = np.append(np.empty(n2), e)
+ for i in range(n2):
+ e[2*i+0] = e[2*i+1] = e[n2+i]
+
+ ## 3.3.7.2.2 Smoothing
+
+ e_s = np.zeros(len(e))
+ e_s[0 ] = 0.75 * e[0 ] + 0.25 * e[1 ]
+ e_s[1:63] = 0.25 * e[0:62] + 0.5 * e[1:63] + 0.25 * e[2:64]
+ e_s[ 63] = 0.25 * e[ 62] + 0.75 * e[ 63]
+
+ ## 3.3.7.2.3 Pre-emphasis
+
+ g_tilt = [ 14, 18, 22, 26, 30 ][self.sr]
+ e_p = e_s * (10 ** ((np.arange(64) * g_tilt) / 630))
+
+ ## 3.3.7.2.4 Noise floor
+
+ noise_floor = max(np.average(e_p) * (10 ** (-40/10)), 2 ** -32)
+ e_p = np.fmax(e_p, noise_floor * np.ones(len(e)))
+
+ ## 3.3.7.2.5 Logarithm
+
+ e_l = np.log2(10 ** -31 + e_p) / 2
+
+ ## 3.3.7.2.6 Band energy grouping
+
+ w = [ 1/12, 2/12, 3/12, 3/12, 2/12, 1/12 ]
+
+ e_4 = np.zeros(len(e_l) // 4)
+ e_4[0 ] = w[0] * e_l[0] + np.sum(w[1:] * e_l[:5])
+ e_4[1:15] = [ np.sum(w * e_l[4*i-1:4*i+5]) for i in range(1, 15) ]
+ e_4[ 15] = np.sum(w[:5] * e_l[59:64]) + w[5] * e_l[63]
+
+ ## 3.3.7.2.7 Mean removal and scaling, attack handling
+
+ scf = 0.85 * (e_4 - np.average(e_4))
+
+ scf_a = np.zeros(len(scf))
+ scf_a[0 ] = np.average(scf[:3])
+ scf_a[1 ] = np.average(scf[:4])
+ scf_a[2:14] = [ np.average(scf[i:i+5]) for i in range(12) ]
+ scf_a[ 14] = np.average(scf[12:])
+ scf_a[ 15] = np.average(scf[13:])
+
+ scf_a = (0.5 if self.dt == T.DT_10M else 0.3) * \
+ (scf_a - np.average(scf_a))
+
+ return scf_a if att else scf
+
+ def enum_mpvq(self, v):
+
+ sign = None
+ index = 0
+ x = 0
+
+ for (n, vn) in enumerate(v[::-1]):
+
+ if sign is not None and vn != 0:
+ index = 2*index + sign
+ if vn != 0:
+ sign = 1 if vn < 0 else 0
+
+ index += T.SNS_MPVQ_OFFSETS[n][x]
+ x += abs(vn)
+
+ return (index, bool(sign))
+
+ def quantize(self, scf):
+
+ ## 3.3.7.3.2 Stage 1
+
+ dmse_lf = [ np.sum((scf[:8] - T.SNS_LFCB[i]) ** 2) for i in range(32) ]
+ dmse_hf = [ np.sum((scf[8:] - T.SNS_HFCB[i]) ** 2) for i in range(32) ]
+
+ self.ind_lf = np.argmin(dmse_lf)
+ self.ind_hf = np.argmin(dmse_hf)
+
+ st1 = np.append(T.SNS_LFCB[self.ind_lf], T.SNS_HFCB[self.ind_hf])
+ r1 = scf - st1
+
+ ## 3.3.7.3.3 Stage 2
+
+ t2_rot = fftpack.dct(r1, norm = 'ortho')
+ x = np.abs(t2_rot)
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 1
+
+ K = 6
+
+ proj_fac = (K - 1) / sum(np.abs(t2_rot))
+ y3 = np.floor(x * proj_fac).astype(int)
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 2
+
+ corr_xy = np.sum(y3 * x)
+ energy_y = np.sum(y3 * y3)
+
+ k0 = sum(y3)
+ for k in range(k0, K):
+ q_pvq = ((corr_xy + x) ** 2) / (energy_y + 2*y3 + 1)
+ n_best = np.argmax(q_pvq)
+
+ corr_xy += x[n_best]
+ energy_y += 2*y3[n_best] + 1
+ y3[n_best] += 1
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 3
+
+ K = 8
+
+ y2 = y3.copy()
+
+ for k in range(sum(y2), K):
+ q_pvq = ((corr_xy + x) ** 2) / (energy_y + 2*y2 + 1)
+ n_best = np.argmax(q_pvq)
+
+ corr_xy += x[n_best]
+ energy_y += 2*y2[n_best] + 1
+ y2[n_best] += 1
+
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 4
+
+ y1 = np.append(y2[:10], [0] * 6)
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 5
+
+ corr_xy -= sum(y2[10:] * x[10:])
+ energy_y -= sum(y2[10:] * y2[10:])
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 6
+
+ K = 10
+
+ for k in range(sum(y1), K):
+ q_pvq = ((corr_xy + x[:10]) ** 2) / (energy_y + 2*y1[:10] + 1)
+ n_best = np.argmax(q_pvq)
+
+ corr_xy += x[n_best]
+ energy_y += 2*y1[n_best] + 1
+ y1[n_best] += 1
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 7
+
+ y0 = np.append(y1[:10], [ 0 ] * 6)
+
+ q_pvq = ((corr_xy + x[10:]) ** 2) / (energy_y + 2*y0[10:] + 1)
+ n_best = 10 + np.argmax(q_pvq)
+
+ y0[n_best] += 1
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 8
+
+ y0 *= np.sign(t2_rot).astype(int)
+ y1 *= np.sign(t2_rot).astype(int)
+ y2 *= np.sign(t2_rot).astype(int)
+ y3 *= np.sign(t2_rot).astype(int)
+
+ ## 3.3.7.3.3 Stage 2 Shape search, step 9
+
+ xq = [ y / np.sqrt(sum(y ** 2)) for y in (y0, y1, y2, y3) ]
+
+ ## 3.3.7.3.3 Shape and gain combination determination
+
+ G = [ T.SNS_VQ_REG_ADJ_GAINS, T.SNS_VQ_REG_LF_ADJ_GAINS,
+ T.SNS_VQ_NEAR_ADJ_GAINS, T.SNS_VQ_FAR_ADJ_GAINS ]
+
+ dMSE = [ [ sum((t2_rot - G[j][i] * xq[j]) ** 2)
+ for i in range(len(G[j])) ] for j in range(4) ]
+
+ self.shape = np.argmin([ np.min(dMSE[j]) for j in range(4) ])
+ self.gain = np.argmin(dMSE[self.shape])
+
+ gain = G[self.shape][self.gain]
+
+ ## 3.3.7.3.3 Enumeration of the selected PVQ pulse configurations
+
+ if self.shape == 0:
+ (self.idx_a, self.ls_a) = self.enum_mpvq(y0[:10])
+ (self.idx_b, self.ls_b) = self.enum_mpvq(y0[10:])
+ elif self.shape == 1:
+ (self.idx_a, self.ls_a) = self.enum_mpvq(y1[:10])
+ (self.idx_b, self.ls_b) = (None, None)
+ elif self.shape == 2:
+ (self.idx_a, self.ls_a) = self.enum_mpvq(y2)
+ (self.idx_b, self.ls_b) = (None, None)
+ elif self.shape == 3:
+ (self.idx_a, self.ls_a) = self.enum_mpvq(y3)
+ (self.idx_b, self.ls_b) = (None, None)
+
+ ## 3.3.7.3.4 Synthesis of the Quantized scale factor
+
+ scf_q = st1 + gain * fftpack.idct(xq[self.shape], norm = 'ortho')
+
+ return scf_q
+
+ def run(self, eb, att, x):
+
+ scf = self.compute_scale_factors(eb, att)
+ scf_q = self.quantize(scf)
+ y = self.spectral_shaping(scf_q, False, x)
+
+ return y
+
+ def store(self, b):
+
+ shape = self.shape
+ gain_msb_bits = np.array([ 1, 1, 2, 2 ])[shape]
+ gain_lsb_bits = np.array([ 0, 1, 0, 1 ])[shape]
+
+ b.write_uint(self.ind_lf, 5)
+ b.write_uint(self.ind_hf, 5)
+
+ b.write_bit(shape >> 1)
+
+ b.write_uint(self.gain >> gain_lsb_bits, gain_msb_bits)
+
+ b.write_bit(self.ls_a)
+
+ if self.shape == 0:
+ sz_shape_a = 2390004
+ index_joint = self.idx_a + \
+ (2 * self.idx_b + self.ls_b + 2) * sz_shape_a
+
+ elif self.shape == 1:
+ sz_shape_a = 2390004
+ index_joint = self.idx_a + (self.gain & 1) * sz_shape_a
+
+ elif self.shape == 2:
+ index_joint = self.idx_a
+
+ elif self.shape == 3:
+ sz_shape_a = 15158272
+ index_joint = sz_shape_a + (self.gain & 1) + 2 * self.idx_a
+
+ b.write_uint(index_joint, 14 - gain_msb_bits)
+ b.write_uint(index_joint >> (14 - gain_msb_bits), 12)
+
+
+class SnsSynthesis(Sns):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ def deenum_mpvq(self, index, ls, npulses, n):
+
+ y = np.zeros(n, dtype=np.intc)
+ pos = 0
+
+ for i in range(len(y)-1, -1, -1):
+
+ if index > 0:
+ yi = 0
+ while index < T.SNS_MPVQ_OFFSETS[i][npulses - yi]: yi += 1
+ index -= T.SNS_MPVQ_OFFSETS[i][npulses - yi]
+ else:
+ yi = npulses
+
+ y[pos] = [ yi, -yi ][int(ls)]
+ pos += 1
+
+ npulses -= yi
+ if npulses <= 0:
+ break
+
+ if yi > 0:
+ ls = index & 1
+ index >>= 1
+
+ return y
+
+ def unquantize(self):
+
+ ## 3.7.4.2.1-2 SNS VQ Decoding
+
+ y = np.empty(16, dtype=np.intc)
+
+ if self.shape == 0:
+ y[:10] = self.deenum_mpvq(self.idx_a, self.ls_a, 10, 10)
+ y[10:] = self.deenum_mpvq(self.idx_b, self.ls_b, 1, 6)
+ elif self.shape == 1:
+ y[:10] = self.deenum_mpvq(self.idx_a, self.ls_a, 10, 10)
+ y[10:] = np.zeros(6, dtype=np.intc)
+ elif self.shape == 2:
+ y = self.deenum_mpvq(self.idx_a, self.ls_a, 8, 16)
+ elif self.shape == 3:
+ y = self.deenum_mpvq(self.idx_a, self.ls_a, 6, 16)
+
+ ## 3.7.4.2.3 Unit energy normalization
+
+ y = y / np.sqrt(sum(y ** 2))
+
+ ## 3.7.4.2.4 Reconstruction of the quantized scale factors
+
+ G = [ T.SNS_VQ_REG_ADJ_GAINS, T.SNS_VQ_REG_LF_ADJ_GAINS,
+ T.SNS_VQ_NEAR_ADJ_GAINS, T.SNS_VQ_FAR_ADJ_GAINS ]
+
+ gain = G[self.shape][self.gain]
+
+ scf = np.append(T.SNS_LFCB[self.ind_lf], T.SNS_HFCB[self.ind_hf]) \
+ + gain * fftpack.idct(y, norm = 'ortho')
+
+ return scf
+
+ def load(self, b):
+
+ self.ind_lf = b.read_uint(5)
+ self.ind_hf = b.read_uint(5)
+
+ shape_msb = b.read_bit()
+
+ gain_msb_bits = 1 + shape_msb
+ self.gain = b.read_uint(gain_msb_bits)
+
+ self.ls_a = b.read_bit()
+
+ index_joint = b.read_uint(14 - gain_msb_bits)
+ index_joint |= b.read_uint(12) << (14 - gain_msb_bits)
+
+ if shape_msb == 0:
+ sz_shape_a = 2390004
+
+ if index_joint >= sz_shape_a * 14:
+ raise ValueError('Invalide SNS joint index')
+
+ self.idx_a = index_joint % sz_shape_a
+ index_joint = index_joint // sz_shape_a
+ if index_joint >= 2:
+ self.shape = 0
+ self.idx_b = (index_joint - 2) // 2
+ self.ls_b = (index_joint - 2) % 2
+ else:
+ self.shape = 1
+ self.gain = (self.gain << 1) + (index_joint & 1)
+
+ else:
+ sz_shape_a = 15158272
+ if index_joint >= sz_shape_a + 1549824:
+ raise ValueError('Invalide SNS joint index')
+
+ if index_joint < sz_shape_a:
+ self.shape = 2
+ self.idx_a = index_joint
+ else:
+ self.shape = 3
+ index_joint -= sz_shape_a
+ self.gain = (self.gain << 1) + (index_joint % 2)
+ self.idx_a = index_joint // 2
+
+ def run(self, x):
+
+ scf = self.unquantize()
+ y = self.spectral_shaping(scf, True, x)
+
+ return y
+
+### ------------------------------------------------------------------------ ###
+
+def check_analysis(rng, dt, sr):
+
+ ok = True
+
+ analysis = SnsAnalysis(dt, sr)
+
+ for i in range(10):
+ x = rng.random(T.NE[dt][sr]) * 1e4
+ e = rng.random(min(len(x), 64)) * 1e10
+
+ for att in (0, 1):
+ y = analysis.run(e, att, x)
+ data = analysis.get_data()
+
+ (y_c, data_c) = lc3.sns_analyze(dt, sr, e, att, x)
+
+ for k in data.keys():
+ ok = ok and data_c[k] == data[k]
+
+ ok = ok and lc3.sns_get_nbits() == analysis.get_nbits()
+ ok = ok and np.amax(np.abs(y - y_c)) < 1e-1
+
+ return ok
+
+def check_synthesis(rng, dt, sr):
+
+ ok = True
+
+ synthesis = SnsSynthesis(dt, sr)
+
+ for i in range(100):
+
+ synthesis.ind_lf = rng.integers(0, 32)
+ synthesis.ind_hf = rng.integers(0, 32)
+
+ shape = rng.integers(0, 4)
+ sz_shape_a = [ 2390004, 2390004, 15158272, 774912 ][shape]
+ sz_shape_b = [ 6, 1, 0, 0 ][shape]
+ synthesis.shape = shape
+ synthesis.gain = rng.integers(0, [ 2, 4, 4, 8 ][shape])
+ synthesis.idx_a = rng.integers(0, sz_shape_a, endpoint=True)
+ synthesis.ls_a = bool(rng.integers(0, 1, endpoint=True))
+ synthesis.idx_b = rng.integers(0, sz_shape_b, endpoint=True)
+ synthesis.ls_b = bool(rng.integers(0, 1, endpoint=True))
+
+ x = rng.random(T.NE[dt][sr]) * 1e4
+
+ y = synthesis.run(x)
+ y_c = lc3.sns_synthesize(dt, sr, synthesis.get_data(), x)
+ ok = ok and np.amax(np.abs(y - y_c)) < 2e0
+
+ return ok
+
+def check_analysis_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ for i in range(len(C.E_B[dt])):
+
+ scf = lc3.sns_compute_scale_factors(dt, sr, C.E_B[dt][i], False)
+ ok = ok and np.amax(np.abs(scf - C.SCF[dt][i])) < 1e-4
+
+ (lf, hf) = lc3.sns_resolve_codebooks(scf)
+ ok = ok and lf == C.IND_LF[dt][i] and hf == C.IND_HF[dt][i]
+
+ (y, yn, shape, gain) = lc3.sns_quantize(scf, lf, hf)
+ ok = ok and np.any(y[0][:16] - C.SNS_Y0[dt][i] == 0)
+ ok = ok and np.any(y[1][:10] - C.SNS_Y1[dt][i] == 0)
+ ok = ok and np.any(y[2][:16] - C.SNS_Y2[dt][i] == 0)
+ ok = ok and np.any(y[3][:16] - C.SNS_Y3[dt][i] == 0)
+ ok = ok and shape == 2*C.SUBMODE_MSB[dt][i] + C.SUBMODE_LSB[dt][i]
+ ok = ok and gain == C.G_IND[dt][i]
+
+ scf_q = lc3.sns_unquantize(lf, hf, yn[shape], shape, gain)
+ ok = ok and np.amax(np.abs(scf_q - C.SCF_Q[dt][i])) < 1e-5
+
+ x = lc3.sns_spectral_shaping(dt, sr, C.SCF_Q[dt][i], False, C.X[dt][i])
+ ok = ok and np.amax(np.abs(1 - x/C.X_S[dt][i])) < 1e-5
+
+ (x, data) = lc3.sns_analyze(dt, sr, C.E_B[dt][i], False, C.X[dt][i])
+ ok = ok and data['lfcb'] == C.IND_LF[dt][i]
+ ok = ok and data['hfcb'] == C.IND_HF[dt][i]
+ ok = ok and data['shape'] == \
+ 2*C.SUBMODE_MSB[dt][i] + C.SUBMODE_LSB[dt][i]
+ ok = ok and data['gain'] == C.G_IND[dt][i]
+ ok = ok and data['idx_a'] == C.IDX_A[dt][i]
+ ok = ok and data['ls_a'] == C.LS_IND_A[dt][i]
+ ok = ok and (C.IDX_B[dt][i] is None or
+ data['idx_b'] == C.IDX_B[dt][i])
+ ok = ok and (C.LS_IND_B[dt][i] is None or
+ data['ls_b'] == C.LS_IND_B[dt][i])
+ ok = ok and np.amax(np.abs(1 - x/C.X_S[dt][i])) < 1e-5
+
+ return ok
+
+def check_synthesis_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ for i in range(len(C.X_HAT_TNS[dt])):
+
+ data = {
+ 'lfcb' : C.IND_LF[dt][i], 'hfcb' : C.IND_HF[dt][i],
+ 'shape' : 2*C.SUBMODE_MSB[dt][i] + C.SUBMODE_LSB[dt][i],
+ 'gain' : C.G_IND[dt][i],
+ 'idx_a' : C.IDX_A[dt][i],
+ 'ls_a' : C.LS_IND_A[dt][i],
+ 'idx_b' : C.IDX_B[dt][i] if C.IDX_B[dt][i] is not None else 0,
+ 'ls_b' : C.LS_IND_B[dt][i] if C.LS_IND_B[dt][i] is not None else 0,
+ }
+
+ x = lc3.sns_synthesize(dt, sr, data, C.X_HAT_TNS[dt][i])
+ ok = ok and np.amax(np.abs(x - C.X_HAT_SNS[dt][i])) < 1e0
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_analysis(rng, dt, sr)
+ ok = ok and check_synthesis(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_analysis_appendix_c(dt)
+ ok = ok and check_synthesis_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/sns_py.c b/test/sns_py.c
new file mode 100644
index 0000000..2ef3e83
--- /dev/null
+++ b/test/sns_py.c
@@ -0,0 +1,215 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <sns.c>
+#include "ctypes.h"
+
+static PyObject *compute_scale_factors_py(PyObject *m, PyObject *args)
+{
+ unsigned dt, sr;
+ PyObject *eb_obj, *scf_obj;
+ float *eb, *scf;
+ int att;
+
+ if (!PyArg_ParseTuple(args, "IIOp", &dt, &sr, &eb_obj, &att))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
+
+ CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb));
+ scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf);
+
+ compute_scale_factors(dt, sr, eb, att, scf);
+
+ return Py_BuildValue("N", scf_obj);
+}
+
+static PyObject *resolve_codebooks_py(PyObject *m, PyObject *args)
+{
+ PyObject *scf_obj;
+ float *scf;
+ int lfcb_idx, hfcb_idx;
+
+ if (!PyArg_ParseTuple(args, "O", &scf_obj))
+ return NULL;
+
+ CTYPES_CHECK("eb", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf));
+
+ resolve_codebooks(scf, &lfcb_idx, &hfcb_idx);
+
+ return Py_BuildValue("ii", lfcb_idx, hfcb_idx);
+}
+
+static PyObject *quantize_py(PyObject *m, PyObject *args)
+{
+ PyObject *scf_obj, *y_obj, *yn_obj;
+ float *scf;
+ int lfcb_idx, hfcb_idx;
+ int shape_idx, gain_idx;
+ float (*yn)[16];
+ int (*y)[16];
+
+ if (!PyArg_ParseTuple(args, "Oii", &scf_obj, &lfcb_idx, &hfcb_idx))
+ return NULL;
+
+ CTYPES_CHECK("scf", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf));
+ CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32);
+ CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32);
+
+ y_obj = new_2d_ptr(NPY_INT, 4, 16, &y);
+ yn_obj = new_2d_ptr(NPY_FLOAT, 4, 16, &yn);
+
+ quantize(scf, lfcb_idx, hfcb_idx,
+ y, yn, &shape_idx, &gain_idx);
+
+ return Py_BuildValue("NNii", y_obj, yn_obj, shape_idx, gain_idx);
+}
+
+static PyObject *unquantize_py(PyObject *m, PyObject *args)
+{
+ PyObject *y_obj, *scf_obj;
+ int lfcb_idx, hfcb_idx;
+ int shape, gain;
+ float *y, *scf;
+
+ if (!PyArg_ParseTuple(args, "iiOii",
+ &lfcb_idx, &hfcb_idx, &y_obj, &shape, &gain))
+ return NULL;
+
+ CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32);
+ CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32);
+ CTYPES_CHECK("y", to_1d_ptr(y_obj, NPY_FLOAT, 16, &y));
+ CTYPES_CHECK("shape", (unsigned)shape < 4);
+ CTYPES_CHECK("gain",
+ (unsigned)gain < (unsigned)lc3_sns_vq_gains[shape].count);
+
+ scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf);
+
+ unquantize(lfcb_idx, hfcb_idx, y, shape, gain, scf);
+
+ return Py_BuildValue("N", scf_obj);
+}
+
+static PyObject *spectral_shaping_py(PyObject *m, PyObject *args)
+{
+ PyObject *scf_q_obj, *x_obj;
+ unsigned dt, sr;
+ float *scf_q, *x;
+ int inv;
+
+ if (!PyArg_ParseTuple(args, "IIOpO", &dt, &sr, &scf_q_obj, &inv, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ne = LC3_NE(dt, sr);
+
+ CTYPES_CHECK("scf_q", to_1d_ptr(scf_q_obj, NPY_FLOAT, 16, &scf_q));
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ spectral_shaping(dt, sr, scf_q, inv, x, x);
+
+ return Py_BuildValue("O", x_obj);
+}
+
+static PyObject *analyze_py(PyObject *m, PyObject *args)
+{
+ PyObject *eb_obj, *x_obj;
+ struct lc3_sns_data data = { 0 };
+ unsigned dt, sr;
+ float *eb, *x;
+ int att;
+
+ if (!PyArg_ParseTuple(args, "IIOpO", &dt, &sr, &eb_obj, &att, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ne = LC3_NE(dt, sr);
+ int nb = LC3_MIN(ne, LC3_NUM_BANDS);
+
+ CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb));
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ lc3_sns_analyze(dt, sr, eb, att, &data, x, x);
+
+ return Py_BuildValue("ON", x_obj, new_sns_data(&data));
+}
+
+static PyObject *synthesize_py(PyObject *m, PyObject *args)
+{
+ PyObject *data_obj, *x_obj;
+ struct lc3_sns_data data;
+ unsigned dt, sr;
+ float *x;
+
+ if (!PyArg_ParseTuple(args, "IIOO", &dt, &sr, &data_obj, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+ CTYPES_CHECK(NULL, data_obj = to_sns_data(data_obj, &data));
+
+ int ne = LC3_NE(dt, sr);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ lc3_sns_synthesize(dt, sr, &data, x, x);
+
+ return Py_BuildValue("O", x_obj);
+}
+
+static PyObject *get_nbits_py(PyObject *m, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ""))
+ return NULL;
+
+ int nbits = lc3_sns_get_nbits();
+
+ return Py_BuildValue("i", nbits);
+}
+
+static PyMethodDef methods[] = {
+ { "sns_compute_scale_factors", compute_scale_factors_py, METH_VARARGS },
+ { "sns_resolve_codebooks" , resolve_codebooks_py , METH_VARARGS },
+ { "sns_quantize" , quantize_py , METH_VARARGS },
+ { "sns_unquantize" , unquantize_py , METH_VARARGS },
+ { "sns_spectral_shaping" , spectral_shaping_py , METH_VARARGS },
+ { "sns_analyze" , analyze_py , METH_VARARGS },
+ { "sns_synthesize" , synthesize_py , METH_VARARGS },
+ { "sns_get_nbits" , get_nbits_py , METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_sns_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/spec.py b/test/spec.py
new file mode 100644
index 0000000..22c5e3e
--- /dev/null
+++ b/test/spec.py
@@ -0,0 +1,818 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+import lc3
+import tables as T, appendix_c as C
+
+import bwdet as m_bwdet
+import ltpf as m_ltpf
+import sns as m_sns
+import tns as m_tns
+
+### ------------------------------------------------------------------------ ###
+
+class SpectrumQuantization:
+
+ def __init__(self, dt, sr):
+
+ self.dt = dt
+ self.sr = sr
+
+ def get_gain_offset(self, nbytes):
+
+ g_off = (nbytes * 8) // (10 * (1 + self.sr))
+ g_off = -min(115, g_off) - (105 + 5*(1 + self.sr))
+
+ return g_off
+
+ def get_noise_indices(self, bw, xq, lastnz):
+
+ nf_start = [ 18, 24 ][self.dt]
+ nf_width = [ 2, 3 ][self.dt]
+
+ bw_stop = int([ 80, 160, 240, 320, 400 ][bw] * (T.DT_MS[self.dt] / 10))
+
+ xq = np.append(xq[:lastnz], np.zeros(len(xq) - lastnz))
+
+ i_nf = [ np.all(xq[k-nf_width:min(bw_stop, k+nf_width+1)] == 0)
+ for k in range(nf_start, bw_stop) ]
+
+ return (i_nf, nf_start, bw_stop)
+
+
+class SpectrumAnalysis(SpectrumQuantization):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ self.reset_off = 0
+ self.nbits_off = 0
+ self.nbits_spec = 0
+ self.nbits_est = 0
+
+ (self.g_idx, self.noise_factor, self.xq, self.lastnz,
+ self.nbits_residual_max, self.xg) = \
+ (None, None, None, None, None, None)
+
+ def estimate_gain(self, x, nbits_spec, nbits_off, g_off):
+
+ nbits = int(nbits_spec + nbits_off + 0.5)
+
+ ### Energy (dB) by 4 MDCT coefficients
+
+ e = [ np.sum(x[4*k:4*(k+1)] ** 2) for k in range(len(x) // 4) ]
+ e = 10 * np.log10(2**-31 + np.array(e))
+
+ ### Compute gain index
+
+ g_idx = 255
+
+ for i in range(8):
+ factor = 1 << (7 - i)
+ g_idx -= factor
+ tmp = 0
+ iszero = 1
+
+ for ei in e[-1::-1]:
+
+ if ei * 28/20 < g_idx + g_off:
+ if iszero == 0:
+ tmp += 2.7*28/20
+ else:
+ if g_idx + g_off < (ei - 43) * 28/20:
+ tmp += 2*ei*28/20 - 2*(g_idx + g_off) - 36*28/20
+ else:
+ tmp += ei*28/20 - (g_idx + g_off) + 7*28/20
+ iszero = 0
+
+ if tmp > nbits * 1.4 * 28/20 and iszero == 0:
+ g_idx += factor
+
+ ### Limit gain index
+
+ x_max = np.amax(np.abs(x))
+ if x_max > 0:
+ g_min = 28 * np.log10(x_max / (32768 - 0.375))
+ g_min = np.ceil(g_min).astype(int) - g_off
+ reset_off = g_idx < g_min
+ else:
+ g_min = 0
+ reset_off = True
+
+ if reset_off:
+ g_idx = g_min
+
+ return (g_idx + g_off, reset_off)
+
+ def quantize(self, g_int, x):
+
+ xg = x / 10 ** (g_int / 28)
+
+ xq = np.where(xg < 0, np.ceil(xg - 0.375), np.floor(xg + 0.375))
+ xq = xq.astype(int)
+ xq = np.fmin(np.fmax(xq, -32768), 32767)
+
+ nz_pairs = np.any([ xq[::2] != 0, xq[1::2] != 0 ], axis=0)
+ lastnz = len(xq) - 2 * np.argmax(nz_pairs[-1::-1])
+ if not np.any(nz_pairs):
+ lastnz = 0
+
+ return (xg, xq, lastnz)
+
+ def compute_nbits(self, nbytes, x, lastnz, nbits_spec):
+
+ mode = 1 if nbytes >= 20 * (3 + self.sr) else 0
+ rate = 512 if nbytes > 20 * (1 + self.sr) else 0
+
+ nbits_est = 0
+ nbits_trunc = 0
+ nbits_lsb = 0
+ lastnz_trunc = 2
+ c = 0
+
+ for n in range(0, lastnz, 2):
+ t = c + rate
+ if n > len(x) // 2:
+ t += 256
+
+ a = abs(x[n ])
+ b = abs(x[n+1])
+ lev = 0
+ while max(a, b) >= 4:
+ nbits_est += \
+ T.AC_SPEC_BITS[T.AC_SPEC_LOOKUP[t + lev*1024]][16];
+ if lev == 0 and mode == 1:
+ nbits_lsb += 2
+ else:
+ nbits_est += 2 * 2048
+
+ a >>= 1
+ b >>= 1
+ lev = min(lev + 1, 3)
+
+ nbits_est += \
+ T.AC_SPEC_BITS[T.AC_SPEC_LOOKUP[t + lev*1024]][a + 4*b]
+
+ a_lsb = abs(x[n ])
+ b_lsb = abs(x[n+1])
+ nbits_est += (min(a_lsb, 1) + min(b_lsb, 1)) * 2048
+ if lev > 0 and mode == 1:
+ a_lsb >>= 1;
+ b_lsb >>= 1;
+ nbits_lsb += int(a_lsb == 0 and x[n ] != 0)
+ nbits_lsb += int(b_lsb == 0 and x[n+1] != 0)
+
+ if (x[n] != 0 or x[n+1] != 0) and \
+ (nbits_est <= nbits_spec * 2048):
+ lastnz_trunc = n + 2;
+ nbits_trunc = nbits_est
+
+ t = 1 + (a + b) * (lev + 1) if lev <= 1 else 12 + lev;
+ c = (c & 15) * 16 + t;
+
+ nbits_est = (nbits_est + 2047) // 2048 + nbits_lsb;
+ nbits_trunc = (nbits_trunc + 2047) // 2048
+
+ self.rate = rate
+ self.lsb_mode = mode == 1 and nbits_est > nbits_spec
+
+ return (nbits_est, nbits_trunc, lastnz_trunc, self.lsb_mode)
+
+ def adjust_gain(self, g_idx, nbits, nbits_spec):
+
+ T1 = [ 80, 230, 380, 530, 680 ]
+ T2 = [ 500, 1025, 1550, 2075, 2600 ]
+ T3 = [ 850, 1700, 2550, 3400, 4250 ]
+
+ sr = self.sr
+
+ if nbits < T1[sr]:
+ delta = (nbits + 48) / 16
+
+ elif nbits < T2[sr]:
+ a = T1[sr] / 16 + 3
+ b = T2[sr] / 48
+ delta = a + (nbits - T1[sr]) * (b - a) / (T2[sr] - T1[sr])
+
+ elif nbits < T3[sr]:
+ delta = nbits / 48
+
+ else:
+ delta = T3[sr] / 48;
+
+ delta = np.fix(delta + 0.5).astype(int)
+
+ if (g_idx < 255 and nbits > nbits_spec) or \
+ (g_idx > 0 and nbits < nbits_spec - (delta + 2)):
+
+ if nbits < nbits_spec - (delta + 2):
+ return - 1
+
+ if g_idx == 254 or nbits < nbits_spec + delta:
+ return 1
+
+ else:
+ return 2
+
+ return 0
+
+ def estimate_noise(self, bw, xq, lastnz, x):
+
+ (i_nf, nf_start, nf_stop) = self.get_noise_indices(bw, xq, lastnz)
+
+ nf = 8 - 16 * sum(abs(x[nf_start:nf_stop] * i_nf)) / sum(i_nf) \
+ if sum(i_nf) > 0 else 0
+
+ return min(max(np.rint(nf).astype(int), 0), 7)
+
+ def run(self,
+ bw, nbytes, nbits_bw, nbits_ltpf, nbits_sns, nbits_tns, x):
+
+ sr = self.sr
+
+ ### Bit budget
+
+ nbits_gain = 8
+ nbits_nf = 3
+
+ nbits_ari = np.ceil(np.log2(len(x) / 2)).astype(int)
+ nbits_ari += 3 + min((8*nbytes - 1) // 1280, 2)
+
+ nbits_spec = 8*nbytes - \
+ nbits_bw - nbits_ltpf - nbits_sns - nbits_tns - \
+ nbits_gain - nbits_nf - nbits_ari
+
+ ### Global gain estimation
+
+ nbits_off = self.nbits_off + self.nbits_spec - self.nbits_est
+ nbits_off = min(40, max(-40, nbits_off))
+
+ nbits_off = 0 if self.reset_off else \
+ 0.8 * self.nbits_off + 0.2 * nbits_off
+
+ g_off = self.get_gain_offset(nbytes)
+
+ (g_int, self.reset_off) = \
+ self.estimate_gain(x, nbits_spec, nbits_off, g_off)
+ self.nbits_off = nbits_off
+ self.nbits_spec = nbits_spec
+
+ ### Quantization
+
+ (xg, xq, lastnz) = self.quantize(g_int, x)
+
+ (nbits_est, nbits_trunc, lastnz_trunc, _) = \
+ self.compute_nbits(nbytes, xq, lastnz, nbits_spec)
+
+ self.nbits_est = nbits_est
+
+ ### Adjust gain and requantize
+
+ g_adj = self.adjust_gain(g_int - g_off, nbits_est, nbits_spec)
+
+ (xg, xq, lastnz) = self.quantize(g_adj, xg)
+
+ (nbits_est, nbits_trunc, lastnz_trunc, lsb_mode) = \
+ self.compute_nbits(nbytes, xq, lastnz, nbits_spec)
+
+ self.g_idx = g_int + g_adj - g_off
+ self.xq = xq
+ self.lastnz = lastnz_trunc
+
+ self.nbits_residual_max = nbits_spec - nbits_trunc + 4
+ self.xg = xg
+
+ ### Noise factor
+
+ self.noise_factor = self.estimate_noise(bw, xq, lastnz, x)
+
+ return (self.xq, self.lastnz, self.xg)
+
+ def store(self, b):
+
+ ne = T.NE[self.dt][self.sr]
+ nbits_lastnz = np.ceil(np.log2(ne/2)).astype(int)
+
+ b.write_uint((self.lastnz >> 1) - 1, nbits_lastnz)
+ b.write_uint(self.lsb_mode, 1)
+ b.write_uint(self.g_idx, 8)
+
+ def encode(self, bits):
+
+ ### Noise factor
+
+ bits.write_uint(self.noise_factor, 3)
+
+ ### Quantized data
+
+ lsbs = []
+
+ x = self.xq
+ c = 0
+
+ for n in range(0, self.lastnz, 2):
+ t = c + self.rate
+ if n > len(x) // 2:
+ t += 256
+
+ a = abs(x[n ])
+ b = abs(x[n+1])
+ lev = 0
+ while max(a, b) >= 4:
+
+ bits.ac_encode(
+ T.AC_SPEC_CUMFREQ[T.AC_SPEC_LOOKUP[t + lev*1024]][16],
+ T.AC_SPEC_FREQ[T.AC_SPEC_LOOKUP[t + lev*1024]][16])
+
+ if lev == 0 and self.lsb_mode:
+ lsb_0 = a & 1
+ lsb_1 = b & 1
+ else:
+ bits.write_bit(a & 1)
+ bits.write_bit(b & 1)
+
+ a >>= 1
+ b >>= 1
+ lev = min(lev + 1, 3)
+
+ bits.ac_encode(
+ T.AC_SPEC_CUMFREQ[T.AC_SPEC_LOOKUP[t + lev*1024]][a + 4*b],
+ T.AC_SPEC_FREQ[T.AC_SPEC_LOOKUP[t + lev*1024]][a + 4*b])
+
+ a_lsb = abs(x[n ])
+ b_lsb = abs(x[n+1])
+ if lev > 0 and self.lsb_mode:
+ a_lsb >>= 1
+ b_lsb >>= 1
+
+ lsbs.append(lsb_0)
+ if a_lsb == 0 and x[n+0] != 0:
+ lsbs.append(int(x[n+0] < 0))
+
+ lsbs.append(lsb_1)
+ if b_lsb == 0 and x[n+1] != 0:
+ lsbs.append(int(x[n+1] < 0))
+
+ if a_lsb > 0:
+ bits.write_bit(int(x[n+0] < 0))
+
+ if b_lsb > 0:
+ bits.write_bit(int(x[n+1] < 0))
+
+ t = 1 + (a + b) * (lev + 1) if lev <= 1 else 12 + lev;
+ c = (c & 15) * 16 + t;
+
+ ### Residual data
+
+ if self.lsb_mode == 0:
+ nbits_residual = min(bits.get_bits_left(), self.nbits_residual_max)
+
+ for i in range(len(self.xg)):
+
+ if self.xq[i] == 0:
+ continue
+
+ bits.write_bit(self.xg[i] >= self.xq[i])
+ nbits_residual -= 1
+ if nbits_residual <= 0:
+ break
+
+ else:
+ nbits_residual = min(bits.get_bits_left(), len(lsbs))
+ for lsb in lsbs[:nbits_residual]:
+ bits.write_bit(lsb)
+
+
+class SpectrumSynthesis(SpectrumQuantization):
+
+ def __init__(self, dt, sr):
+
+ super().__init__(dt, sr)
+
+ (self.lastnz, self.lsb_mode, self.g_idx) = \
+ (None, None, None)
+
+ def fill_noise(self, bw, x, lastnz, f_nf, nf_seed):
+
+ (i_nf, nf_start, nf_stop) = self.get_noise_indices(bw, x, lastnz)
+
+ k_nf = nf_start + np.argwhere(i_nf)
+ l_nf = (8 - f_nf)/16
+
+ for k in k_nf:
+ nf_seed = (13849 + nf_seed * 31821) & 0xffff
+ x[k] = [ -l_nf, l_nf ][nf_seed < 0x8000]
+
+ return x
+
+ def load(self, b):
+
+ ne = T.NE[self.dt][self.sr]
+ nbits_lastnz = np.ceil(np.log2(ne/2)).astype(int)
+
+ self.lastnz = (b.read_uint(nbits_lastnz) + 1) << 1
+ self.lsb_mode = b.read_uint(1)
+ self.g_idx = b.read_uint(8)
+
+ if self.lastnz > ne:
+ raise ValueError('Invalid count of coded samples')
+
+ def decode(self, bits, bw, nbytes):
+
+ ### Noise factor
+
+ f_nf = bits.read_uint(3)
+
+ ### Quantized data
+
+ x = np.zeros(T.NE[self.dt][self.sr])
+ rate = 512 if nbytes > 20 * (1 + self.sr) else 0
+
+ levs = np.zeros(len(x), dtype=np.intc)
+ c = 0
+
+ for n in range(0, self.lastnz, 2):
+ t = c + rate
+ if n > len(x) // 2:
+ t += 256
+
+ for lev in range(14):
+
+ s = t + min(lev, 3) * 1024
+
+ sym = bits.ac_decode(
+ T.AC_SPEC_CUMFREQ[T.AC_SPEC_LOOKUP[s]],
+ T.AC_SPEC_FREQ[T.AC_SPEC_LOOKUP[s]])
+
+ if sym < 16:
+ break
+
+ if self.lsb_mode == 0 or lev > 0:
+ x[n ] += bits.read_bit() << lev
+ x[n+1] += bits.read_bit() << lev
+
+ if lev >= 14:
+ raise ValueError('Out of range value')
+
+ a = sym % 4
+ b = sym // 4
+
+ levs[n ] = lev
+ levs[n+1] = lev
+
+ x[n ] += a << lev
+ x[n+1] += b << lev
+
+ if x[n] and bits.read_bit():
+ x[n] = -x[n]
+
+ if x[n+1] and bits.read_bit():
+ x[n+1] = -x[n+1]
+
+ lev = min(lev, 3)
+ t = 1 + (a + b) * (lev + 1) if lev <= 1 else 12 + lev;
+ c = (c & 15) * 16 + t;
+
+ ### Residual data
+
+ nbits_residual = bits.get_bits_left()
+ if nbits_residual < 0:
+ raise ValueError('Out of bitstream')
+
+ if self.lsb_mode == 0:
+
+ xr = np.zeros(len(x), dtype=np.bool)
+
+ for i in range(len(x)):
+
+ if nbits_residual <= 0:
+ xr.resize(i)
+ break
+
+ if x[i] == 0:
+ continue
+
+ xr[i] = bits.read_bit()
+ nbits_residual -= 1
+
+ else:
+
+ for i in range(len(levs)):
+
+ if nbits_residual <= 0:
+ break
+
+ if levs[i] <= 0:
+ continue
+
+ lsb = bits.read_bit()
+ nbits_residual -= 1
+ if not lsb:
+ continue
+
+ sign = int(x[i] < 0)
+
+ if x[i] == 0:
+
+ if nbits_residual <= 0:
+ break
+
+ sign = bits.read_bit()
+ nbits_residual -= 1
+
+ x[i] += [ 1, -1 ][sign]
+
+ ### Set residual and noise
+
+ nf_seed = sum(abs(x.astype(np.intc)) * range(len(x)))
+
+ zero_frame = (self.lastnz <= 2 and x[0] == 0 and x[1] == 0
+ and self.g_idx <= 0 and f_nf >= 7)
+
+ if self.lsb_mode == 0:
+
+ for i in range(len(xr)):
+
+ if x[i] and xr[i] == 0:
+ x[i] += [ -0.1875, -0.3125 ][x[i] < 0]
+ elif x[i]:
+ x[i] += [ 0.1875, 0.3125 ][x[i] > 0]
+
+ if not zero_frame:
+ x = self.fill_noise(bw, x, self.lastnz, f_nf, nf_seed)
+
+ ### Rescale coefficients
+
+ g_int = self.get_gain_offset(nbytes) + self.g_idx
+ x *= 10 ** (g_int / 28)
+
+ return x
+
+
+def initial_state():
+ return { 'nbits_off' : 0.0, 'nbits_spare' : 0 }
+
+
+### ------------------------------------------------------------------------ ###
+
+def check_estimate_gain(rng, dt, sr):
+
+ ne = T.I[dt][sr][-1]
+ ok = True
+
+ analysis = SpectrumAnalysis(dt, sr)
+
+ for i in range(10):
+ x = rng.random(ne) * i * 1e2
+
+ nbytes = 20 + int(rng.random() * 100)
+ nbits_budget = 8 * nbytes - int(rng.random() * 100)
+ nbits_off = rng.random() * 10
+ g_off = 10 - int(rng.random() * 20)
+
+ (g_int, reset_off) = \
+ analysis.estimate_gain(x, nbits_budget, nbits_off, g_off)
+
+ (g_int_c, reset_off_c, _) = lc3.spec_estimate_gain(
+ dt, sr, x, nbits_budget, nbits_off, -g_off)
+
+ ok = ok and g_int_c == g_int
+ ok = ok and reset_off_c == reset_off
+
+ return ok
+
+def check_quantization(rng, dt, sr):
+
+ ne = T.I[dt][sr][-1]
+ ok = True
+
+ analysis = SpectrumAnalysis(dt, sr)
+
+ for g_int in range(-128, 128):
+
+ x = rng.random(ne) * 1e2
+ nbytes = 20 + int(rng.random() * 30)
+
+ (xg, xq, nq) = analysis.quantize(g_int, x)
+ (xg_c, xq_c, nq_c) = lc3.spec_quantize(dt, sr, g_int, x)
+
+ ok = ok and np.amax(np.abs(1 - xg_c/xg)) < 1e-6
+ ok = ok and np.any(abs(xq_c - xq) < 1)
+ ok = ok and nq_c == nq
+
+ return ok
+
+def check_compute_nbits(rng, dt, sr):
+
+ ne = T.I[dt][sr][-1]
+ ok = True
+
+ analysis = SpectrumAnalysis(dt, sr)
+
+ for nbytes in range(20, 150):
+
+ nbits_budget = nbytes * 8 - int(rng.random() * 100)
+ xq = (rng.random(ne) * 8).astype(int)
+ nq = ne // 2 + int(rng.random() * ne // 2)
+
+ nq = nq - nq % 2
+ if xq[nq-2] == 0 and xq[nq-1] == 0:
+ xq[nq-2] = 1
+
+ (nbits, nbits_trunc, nq_trunc, lsb_mode) = \
+ analysis.compute_nbits(nbytes, xq, nq, nbits_budget)
+
+ (nbits_c, nq_c, _) = \
+ lc3.spec_compute_nbits(dt, sr, nbytes, xq, nq, 0)
+
+ (nbits_trunc_c, nq_trunc_c, lsb_mode_c) = \
+ lc3.spec_compute_nbits(dt, sr, nbytes, xq, nq, nbits_budget)
+
+ ok = ok and nbits_c == nbits
+ ok = ok and nbits_trunc_c == nbits_trunc
+ ok = ok and nq_trunc_c == nq_trunc
+ ok = ok and lsb_mode_c == lsb_mode
+
+ return ok
+
+def check_adjust_gain(rng, dt, sr):
+
+ ne = T.I[dt][sr][-1]
+ ok = True
+
+ analysis = SpectrumAnalysis(dt, sr)
+
+ for g_idx in (0, 128, 254, 255):
+ for nbits in range(50, 5000, 5):
+ nbits_budget = int(nbits * (0.95 + (rng.random() * 0.1)))
+
+ g_adj = analysis.adjust_gain(g_idx, nbits, nbits_budget)
+
+ g_adj_c = lc3.spec_adjust_gain(sr, g_idx, nbits, nbits_budget, 0)
+
+ ok = ok and g_adj_c == g_adj
+
+ return ok
+
+def check_unit(rng, dt, sr):
+
+ ns = T.NS[dt][sr]
+ ne = T.I[dt][sr][-1]
+ ok = True
+
+ state_c = initial_state()
+
+ bwdet = m_bwdet.BandwidthDetector(dt, sr)
+ ltpf = m_ltpf.LtpfAnalysis(dt, sr)
+ tns = m_tns.TnsAnalysis(dt)
+ sns = m_sns.SnsAnalysis(dt, sr)
+ analysis = SpectrumAnalysis(dt, sr)
+
+ nbytes = 100
+
+ for i in range(10):
+
+ x = rng.random(ns) * 1e4
+ e = rng.random(min(len(x), 64)) * 1e10
+
+ bwdet.run(e)
+ pitch_present = ltpf.run(x)
+ tns.run(x[:ne], sr, False, nbytes)
+ sns.run(e, False, x)
+
+ (xq, nq, _) = analysis.run(sr, nbytes, bwdet.get_nbits(),
+ ltpf.get_nbits(), sns.get_nbits(), tns.get_nbits(), x[:ne])
+
+ (_, xq_c, side_c) = lc3.spec_analyze(
+ dt, sr, nbytes, pitch_present, tns.get_data(), state_c, x[:ne])
+
+ ok = ok and side_c['g_idx'] == analysis.g_idx
+ ok = ok and side_c['nq'] == nq
+ ok = ok and np.any(abs(xq_c - xq) < 1)
+
+ return ok
+
+def check_noise(rng, dt, bw):
+
+ ne = T.NE[dt][bw]
+ ok = True
+
+ analysis = SpectrumAnalysis(dt, bw)
+
+ for i in range(10):
+
+ xq = ((rng.random(ne) - 0.5) * 10 ** (0.5)).astype(int)
+ nq = ne - int(rng.random() * 5)
+ x = rng.random(ne) * i * 1e-1
+
+ nf = analysis.estimate_noise(bw, xq, nq, x)
+ nf_c = lc3.spec_estimate_noise(dt, bw, xq, nq, x)
+
+ ok = ok and nf_c == nf
+
+ return ok
+
+def check_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ne = T.NE[dt][sr]
+ ok = True
+
+ state_c = initial_state()
+
+ for i in range(len(C.X_F[dt])):
+
+ g_int = lc3.spec_estimate_gain(dt, sr, C.X_F[dt][i],
+ C.NBITS_SPEC[dt][i], C.NBITS_OFFSET[dt][i], -C.GG_OFF[dt][i])[0]
+ ok = ok and g_int == C.GG_IND[dt][i] + C.GG_OFF[dt][i]
+
+ (_, xq, nq) = lc3.spec_quantize(dt, sr,
+ C.GG_IND[dt][i] + C.GG_OFF[dt][i], C.X_F[dt][i])
+ ok = ok and np.any((xq - C.X_Q[dt][i]) == 0)
+ ok = ok and nq == C.LASTNZ[dt][i]
+
+ nbits = lc3.spec_compute_nbits(dt, sr,
+ C.NBYTES[dt], C.X_Q[dt][i], C.LASTNZ[dt][i], 0)[0]
+ ok = ok and nbits == C.NBITS_EST[dt][i]
+
+ g_adj = lc3.spec_adjust_gain(sr,
+ C.GG_IND[dt][i], C.NBITS_EST[dt][i], C.NBITS_SPEC[dt][i], 0)
+ ok = ok and g_adj == C.GG_IND_ADJ[dt][i] - C.GG_IND[dt][i]
+
+ if C.GG_IND_ADJ[dt][i] != C.GG_IND[dt][i]:
+
+ (_, xq, nq) = lc3.spec_quantize(dt, sr,
+ C.GG_IND_ADJ[dt][i] + C.GG_OFF[dt][i], C.X_F[dt][i])
+ lastnz = C.LASTNZ_REQ[dt][i]
+ ok = ok and np.any(((xq - C.X_Q_REQ[dt][i])[:lastnz]) == 0)
+
+ tns_data = {
+ 'nfilters' : C.NUM_TNS_FILTERS[dt][i],
+ 'lpc_weighting' : [ True, True ],
+ 'rc_order' : [ C.RC_ORDER[dt][i][0], 0 ],
+ 'rc' : [ C.RC_I_1[dt][i] - 8, np.zeros(8, dtype = np.intc) ]
+ }
+
+ (x, xq, side) = lc3.spec_analyze(dt, sr, C.NBYTES[dt],
+ C.PITCH_PRESENT[dt][i], tns_data, state_c, C.X_F[dt][i])
+
+ ok = ok and np.abs(state_c['nbits_off'] - C.NBITS_OFFSET[dt][i]) < 1e-5
+ if C.GG_IND_ADJ[dt][i] != C.GG_IND[dt][i]:
+ xq = C.X_Q_REQ[dt][i]
+ nq = C.LASTNZ_REQ[dt][i]
+ ok = ok and side['g_idx'] == C.GG_IND_ADJ[dt][i]
+ ok = ok and side['nq'] == nq
+ ok = ok and np.any(((xq[:nq] - xq[:nq])) == 0)
+ else:
+ xq = C.X_Q[dt][i]
+ nq = C.LASTNZ[dt][i]
+ ok = ok and side['g_idx'] == C.GG_IND[dt][i]
+ ok = ok and side['nq'] == nq
+ ok = ok and np.any((xq[:nq] - C.X_Q[dt][i][:nq]) == 0)
+ ok = ok and side['lsb_mode'] == C.LSB_MODE[dt][i]
+
+ gg = C.GG[dt][i] if C.GG_IND_ADJ[dt][i] == C.GG_IND[dt][i] \
+ else C.GG_ADJ[dt][i]
+
+ nf = lc3.spec_estimate_noise(dt, C.P_BW[dt][i],
+ xq, nq, C.X_F[dt][i] / gg)
+ ok = ok and nf == C.F_NF[dt][i]
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_estimate_gain(rng, dt, sr)
+ ok = ok and check_quantization(rng, dt, sr)
+ ok = ok and check_compute_nbits(rng, dt, sr)
+ ok = ok and check_adjust_gain(rng, dt, sr)
+ ok = ok and check_unit(rng, dt, sr)
+ ok = ok and check_noise(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/spec_py.c b/test/spec_py.c
new file mode 100644
index 0000000..730f68f
--- /dev/null
+++ b/test/spec_py.c
@@ -0,0 +1,210 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <spec.c>
+#include "ctypes.h"
+
+static PyObject *estimate_gain_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj;
+ unsigned dt, sr;
+ float *x;
+ int nbits_budget;
+ float nbits_off;
+ int g_off, g_min;
+ bool reset_off;
+
+ if (!PyArg_ParseTuple(args, "IIOifi", &dt, &sr,
+ &x_obj, &nbits_budget, &nbits_off, &g_off))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ne = LC3_NE(dt, sr);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ int g_int = estimate_gain(dt, sr,
+ x, nbits_budget, nbits_off, g_off, &reset_off, &g_min);
+
+ return Py_BuildValue("iii", g_int, reset_off, g_min);
+}
+
+static PyObject *adjust_gain_py(PyObject *m, PyObject *args)
+{
+ unsigned sr;
+ int g_idx, nbits, nbits_budget, g_idx_min;
+
+ if (!PyArg_ParseTuple(args, "Iiiii", &sr, &g_idx,
+ &nbits, &nbits_budget, &g_idx_min))
+ return NULL;
+
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+ CTYPES_CHECK("g_idx", g_idx >= 0 && g_idx <= 255);
+
+ g_idx = adjust_gain(sr, g_idx, nbits, nbits_budget, g_idx_min);
+
+ return Py_BuildValue("i", g_idx);
+}
+
+static PyObject *quantize_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj, *xq_obj;
+ unsigned dt, sr;
+ float *x;
+ int16_t *xq;
+ int g_int, nq;
+
+ if (!PyArg_ParseTuple(args, "IIiO", &dt, &sr, &g_int, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+ CTYPES_CHECK("g_int", g_int >= -255 && g_int <= 255);
+
+ int ne = LC3_NE(dt, sr);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ xq_obj = new_1d_ptr(NPY_INT16, ne, &xq);
+ uint16_t __xq[ne];
+
+ quantize(dt, sr, g_int, x, __xq, &nq);
+
+ for (int i = 0; i < nq; i++)
+ xq[i] = __xq[i] & 1 ? -(__xq[i] >> 1) : (__xq[i] >> 1);
+
+ return Py_BuildValue("ONi", x_obj, xq_obj, nq);
+}
+
+static PyObject *compute_nbits_py(PyObject *m, PyObject *args)
+{
+ PyObject *xq_obj;
+ unsigned dt, sr, nbytes;
+ int16_t *xq;
+ int nq, nbits_budget;
+ bool lsb_mode;
+
+ if (!PyArg_ParseTuple(args, "IIIOii", &dt, &sr,
+ &nbytes, &xq_obj, &nq, &nbits_budget))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ne = LC3_NE(dt, sr);
+
+ CTYPES_CHECK("xq", xq_obj = to_1d_ptr(xq_obj, NPY_INT16, ne, &xq));
+
+ uint16_t __xq[ne];
+ for (int i = 0; i < ne; i++)
+ __xq[i] = xq[i] < 0 ? (-xq[i] << 1) + 1 : (xq[i] << 1);
+
+ int nbits = compute_nbits(
+ dt, sr, nbytes, __xq, &nq, nbits_budget, &lsb_mode);
+
+ return Py_BuildValue("iii", nbits, nq, lsb_mode);
+}
+
+static PyObject *analyze_py(PyObject *m, PyObject *args)
+{
+ PyObject *tns_obj, *spec_obj, *x_obj, *xq_obj;
+ struct lc3_tns_data tns = { 0 };
+ struct lc3_spec_analysis spec = { 0 };
+ struct lc3_spec_side side = { 0 };
+ unsigned dt, sr, nbytes;
+ int pitch;
+ float *x;
+ int16_t *xq;
+
+ if (!PyArg_ParseTuple(args, "IIIpOOO", &dt, &sr, &nbytes,
+ &pitch, &tns_obj, &spec_obj, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
+
+ int ne = LC3_NE(dt, sr);
+
+ CTYPES_CHECK(NULL, tns_obj = to_tns_data(tns_obj, &tns));
+ CTYPES_CHECK(NULL, spec_obj = to_spec_analysis(spec_obj, &spec));
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ xq_obj = new_1d_ptr(NPY_INT16, ne, &xq);
+ uint16_t __xq[ne];
+
+ lc3_spec_analyze(dt, sr, nbytes, pitch, &tns, &spec, x, __xq, &side);
+
+ for (int i = 0; i < ne; i++)
+ xq[i] = __xq[i] & 1 ? -(__xq[i] >> 1) : (__xq[i] >> 1);
+
+ from_spec_analysis(spec_obj, &spec);
+ return Py_BuildValue("ONN", x_obj, xq_obj, new_spec_side(&side));
+}
+
+static PyObject *estimate_noise_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj, *xq_obj;
+ unsigned dt, bw;
+ int16_t *xq;
+ float *x;
+ int nq;
+
+ if (!PyArg_ParseTuple(args, "IIOIO", &dt, &bw, &xq_obj, &nq, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("bw", (unsigned)bw < LC3_NUM_BANDWIDTH);
+
+ int ne = LC3_NE(dt, bw);
+
+ CTYPES_CHECK("xq", xq_obj = to_1d_ptr(xq_obj, NPY_INT16, ne, &xq));
+ CTYPES_CHECK("x" , x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x ));
+
+ uint16_t __xq[nq];
+ for (int i = 0; i < nq; i++)
+ __xq[i] = xq[i] < 0 ? (-xq[i] << 1) + 1 : (xq[i] << 1);
+
+ int noise_factor = estimate_noise(dt, bw, __xq, nq, x);
+
+ return Py_BuildValue("i", noise_factor);
+}
+
+static PyMethodDef methods[] = {
+ { "spec_estimate_gain" , estimate_gain_py , METH_VARARGS },
+ { "spec_adjust_gain" , adjust_gain_py , METH_VARARGS },
+ { "spec_quantize" , quantize_py , METH_VARARGS },
+ { "spec_compute_nbits" , compute_nbits_py , METH_VARARGS },
+ { "spec_analyze" , analyze_py , METH_VARARGS },
+ { "spec_estimate_noise", estimate_noise_py, METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_spec_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/test/tables.py b/test/tables.py
new file mode 100644
index 0000000..4886586
--- /dev/null
+++ b/test/tables.py
@@ -0,0 +1,2709 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+
+### Generic ###
+
+DT_7M5 = 0
+DT_10M = 1
+NUM_DT = 2
+
+DT_MS = np.array([ 7.5, 10 ])
+
+
+SRATE_8K = 0
+SRATE_16K = 1
+SRATE_24K = 2
+SRATE_32K = 3
+SRATE_48K = 4
+NUM_SRATE = 5
+
+SRATE_KHZ = np.array([ 8, 16, 24, 32, 48 ])
+
+
+NS = [ (SRATE_KHZ * DT_MS[dt]).astype(int) for dt in range(NUM_DT) ]
+NE = [ np.append(NS[dt][:-1], (NS[dt][-1] * 5) // 6) for dt in range(NUM_DT) ]
+
+ND = [ (23 * NS[0]) // 30, (5 * NS[1]) // 8 ]
+
+
+### 3.7.1/2 ###
+
+I_10M_8K = np.array([
+ 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
+])
+
+I_10M_16K = np.array([
+ 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
+])
+
+I_10M_24K = np.array([
+ 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
+])
+
+I_10M_32K = np.array([
+ 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
+])
+
+I_10M_48K = np.array([
+ 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
+])
+
+I_7M5_8K = np.array([
+ 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
+])
+
+I_7M5_16K = np.array([
+ 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
+])
+
+I_7M5_24K = np.array([
+ 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
+])
+
+I_7M5_32K = np.array([
+ 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
+])
+
+I_7M5_48K = np.array([
+ 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
+])
+
+I = [ [ I_7M5_8K, I_7M5_16K, I_7M5_24K, I_7M5_32K, I_7M5_48K ],
+ [ I_10M_8K, I_10M_16K, I_10M_24K, I_10M_32K, I_10M_48K ] ]
+
+
+### 3.7.3 ###
+
+W_10M_80 = np.array([
+ -7.07854671e-04, -2.09819773e-03, -4.52519808e-03, -8.23397633e-03,
+ -1.33771310e-02, -1.99972156e-02, -2.80090946e-02, -3.72150208e-02,
+ -4.73176826e-02, -5.79465483e-02, -6.86760675e-02, -7.90464744e-02,
+ -8.85970547e-02, -9.68830362e-02, -1.03496124e-01, -1.08076646e-01,
+ -1.10324226e-01, -1.09980985e-01, -1.06817214e-01, -1.00619042e-01,
+ -9.11645251e-02, -7.82061748e-02, -6.14668812e-02, -4.06336286e-02,
+ -1.53632952e-02, 1.47015507e-02, 4.98973651e-02, 9.05036926e-02,
+ 1.36691102e-01, 1.88468639e-01, 2.45645680e-01, 3.07778908e-01,
+ 3.74164237e-01, 4.43811480e-01, 5.15473546e-01, 5.87666172e-01,
+ 6.58761977e-01, 7.27057670e-01, 7.90875299e-01, 8.48664336e-01,
+ 8.99132024e-01, 9.41334815e-01, 9.74763483e-01, 9.99411473e-01,
+ 1.01576037e+00, 1.02473616e+00, 1.02763429e+00, 1.02599149e+00,
+ 1.02142721e+00, 1.01543986e+00, 1.00936693e+00, 1.00350816e+00,
+ 9.98889821e-01, 9.95313390e-01, 9.92594392e-01, 9.90577196e-01,
+ 9.89137162e-01, 9.88179075e-01, 9.87624927e-01, 9.87405628e-01,
+ 9.87452485e-01, 9.87695113e-01, 9.88064062e-01, 9.88492687e-01,
+ 9.88923003e-01, 9.89307497e-01, 9.89614633e-01, 9.89831927e-01,
+ 9.89969310e-01, 9.90060335e-01, 9.90157502e-01, 9.90325529e-01,
+ 9.90630379e-01, 9.91129889e-01, 9.91866549e-01, 9.92861973e-01,
+ 9.94115607e-01, 9.95603378e-01, 9.97279311e-01, 9.99078484e-01,
+ 1.00092237e+00, 1.00272811e+00, 1.00441604e+00, 1.00591922e+00,
+ 1.00718935e+00, 1.00820015e+00, 1.00894949e+00, 1.00945824e+00,
+ 1.00976898e+00, 1.00994034e+00, 1.01003945e+00, 1.01013232e+00,
+ 1.01027252e+00, 1.01049435e+00, 1.01080807e+00, 1.01120107e+00,
+ 1.01164127e+00, 1.01208013e+00, 1.01245818e+00, 1.01270696e+00,
+ 1.01275501e+00, 1.01253013e+00, 1.01196233e+00, 1.01098214e+00,
+ 1.00951244e+00, 1.00746086e+00, 1.00470868e+00, 1.00111141e+00,
+ 9.96504102e-01, 9.90720000e-01, 9.82376587e-01, 9.70882175e-01,
+ 9.54673298e-01, 9.32155386e-01, 9.01800368e-01, 8.62398408e-01,
+ 8.13281737e-01, 7.54455197e-01, 6.86658072e-01, 6.11348804e-01,
+ 5.30618165e-01, 4.47130985e-01, 3.63911468e-01, 2.84164703e-01,
+ 2.11020945e-01, 1.47228797e-01, 9.48266535e-02, 5.48243661e-02,
+ 2.70146141e-02, 9.99674359e-03, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_10M_160 = np.array([
+ -4.61989875e-04, -9.74716672e-04, -1.66447310e-03, -2.59710692e-03,
+ -3.80628516e-03, -5.32460872e-03, -7.17588528e-03, -9.38248086e-03,
+ -1.19527030e-02, -1.48952816e-02, -1.82066640e-02, -2.18757093e-02,
+ -2.58847194e-02, -3.02086274e-02, -3.48159779e-02, -3.96706799e-02,
+ -4.47269805e-02, -4.99422586e-02, -5.52633479e-02, -6.06371724e-02,
+ -6.60096152e-02, -7.13196627e-02, -7.65117823e-02, -8.15296401e-02,
+ -8.63113754e-02, -9.08041129e-02, -9.49537776e-02, -9.87073651e-02,
+ -1.02020268e-01, -1.04843883e-01, -1.07138231e-01, -1.08869014e-01,
+ -1.09996966e-01, -1.10489847e-01, -1.10322584e-01, -1.09462175e-01,
+ -1.07883429e-01, -1.05561251e-01, -1.02465016e-01, -9.85701457e-02,
+ -9.38468492e-02, -8.82630999e-02, -8.17879272e-02, -7.43878560e-02,
+ -6.60218980e-02, -5.66565564e-02, -4.62445689e-02, -3.47458578e-02,
+ -2.21158161e-02, -8.31042570e-03, 6.71769764e-03, 2.30064206e-02,
+ 4.06010646e-02, 5.95323909e-02, 7.98335419e-02, 1.01523314e-01,
+ 1.24617139e-01, 1.49115252e-01, 1.75006740e-01, 2.02269985e-01,
+ 2.30865538e-01, 2.60736512e-01, 2.91814469e-01, 3.24009570e-01,
+ 3.57217518e-01, 3.91314689e-01, 4.26157164e-01, 4.61592545e-01,
+ 4.97447159e-01, 5.33532682e-01, 5.69654673e-01, 6.05608382e-01,
+ 6.41183084e-01, 6.76165350e-01, 7.10340055e-01, 7.43494372e-01,
+ 7.75428189e-01, 8.05943723e-01, 8.34858937e-01, 8.62010834e-01,
+ 8.87259971e-01, 9.10486312e-01, 9.31596250e-01, 9.50522086e-01,
+ 9.67236671e-01, 9.81739750e-01, 9.94055718e-01, 1.00424751e+00,
+ 1.01240743e+00, 1.01865099e+00, 1.02311884e+00, 1.02597245e+00,
+ 1.02739752e+00, 1.02758583e+00, 1.02673867e+00, 1.02506178e+00,
+ 1.02275651e+00, 1.02000914e+00, 1.01699650e+00, 1.01391595e+00,
+ 1.01104487e+00, 1.00777386e+00, 1.00484875e+00, 1.00224501e+00,
+ 9.99939317e-01, 9.97905542e-01, 9.96120338e-01, 9.94559753e-01,
+ 9.93203161e-01, 9.92029727e-01, 9.91023065e-01, 9.90166895e-01,
+ 9.89448837e-01, 9.88855636e-01, 9.88377852e-01, 9.88005163e-01,
+ 9.87729546e-01, 9.87541274e-01, 9.87432981e-01, 9.87394992e-01,
+ 9.87419705e-01, 9.87497321e-01, 9.87620124e-01, 9.87778192e-01,
+ 9.87963798e-01, 9.88167801e-01, 9.88383520e-01, 9.88602222e-01,
+ 9.88818277e-01, 9.89024798e-01, 9.89217866e-01, 9.89392368e-01,
+ 9.89546334e-01, 9.89677201e-01, 9.89785920e-01, 9.89872536e-01,
+ 9.89941079e-01, 9.89994556e-01, 9.90039402e-01, 9.90081472e-01,
+ 9.90129379e-01, 9.90190227e-01, 9.90273445e-01, 9.90386228e-01,
+ 9.90537983e-01, 9.90734883e-01, 9.90984259e-01, 9.91290512e-01,
+ 9.91658694e-01, 9.92090615e-01, 9.92588721e-01, 9.93151653e-01,
+ 9.93779087e-01, 9.94466818e-01, 9.95211663e-01, 9.96006862e-01,
+ 9.96846133e-01, 9.97720337e-01, 9.98621352e-01, 9.99538258e-01,
+ 1.00046196e+00, 1.00138055e+00, 1.00228487e+00, 1.00316385e+00,
+ 1.00400915e+00, 1.00481138e+00, 1.00556397e+00, 1.00625986e+00,
+ 1.00689557e+00, 1.00746662e+00, 1.00797244e+00, 1.00841147e+00,
+ 1.00878601e+00, 1.00909776e+00, 1.00935176e+00, 1.00955240e+00,
+ 1.00970709e+00, 1.00982209e+00, 1.00990696e+00, 1.00996902e+00,
+ 1.01001789e+00, 1.01006081e+00, 1.01010656e+00, 1.01016113e+00,
+ 1.01023108e+00, 1.01031948e+00, 1.01043047e+00, 1.01056410e+00,
+ 1.01072136e+00, 1.01089966e+00, 1.01109699e+00, 1.01130817e+00,
+ 1.01152919e+00, 1.01175301e+00, 1.01197388e+00, 1.01218284e+00,
+ 1.01237303e+00, 1.01253506e+00, 1.01266098e+00, 1.01274058e+00,
+ 1.01276592e+00, 1.01272696e+00, 1.01261590e+00, 1.01242289e+00,
+ 1.01214046e+00, 1.01175881e+00, 1.01126996e+00, 1.01066368e+00,
+ 1.00993075e+00, 1.00905825e+00, 1.00803431e+00, 1.00684335e+00,
+ 1.00547001e+00, 1.00389477e+00, 1.00209885e+00, 1.00006069e+00,
+ 9.97760020e-01, 9.95174643e-01, 9.92286108e-01, 9.89075787e-01,
+ 9.84736245e-01, 9.79861353e-01, 9.74137862e-01, 9.67333198e-01,
+ 9.59253976e-01, 9.49698408e-01, 9.38463416e-01, 9.25356797e-01,
+ 9.10198679e-01, 8.92833832e-01, 8.73143784e-01, 8.51042044e-01,
+ 8.26483991e-01, 7.99468149e-01, 7.70043128e-01, 7.38302860e-01,
+ 7.04381434e-01, 6.68461648e-01, 6.30775533e-01, 5.91579959e-01,
+ 5.51170316e-01, 5.09891542e-01, 4.68101711e-01, 4.26177297e-01,
+ 3.84517234e-01, 3.43522867e-01, 3.03600465e-01, 2.65143468e-01,
+ 2.28528397e-01, 1.94102191e-01, 1.62173542e-01, 1.33001524e-01,
+ 1.06784043e-01, 8.36505724e-02, 6.36518811e-02, 4.67653841e-02,
+ 3.28807275e-02, 2.18305756e-02, 1.33638143e-02, 6.75812489e-03,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_10M_240 = np.array([
+ -3.61349642e-04, -7.07854671e-04, -1.07444364e-03, -1.53347854e-03,
+ -2.09819773e-03, -2.77842087e-03, -3.58412992e-03, -4.52519808e-03,
+ -5.60932724e-03, -6.84323454e-03, -8.23397633e-03, -9.78531476e-03,
+ -1.14988030e-02, -1.33771310e-02, -1.54218168e-02, -1.76297991e-02,
+ -1.99972156e-02, -2.25208056e-02, -2.51940630e-02, -2.80090946e-02,
+ -3.09576509e-02, -3.40299627e-02, -3.72150208e-02, -4.05005325e-02,
+ -4.38721922e-02, -4.73176826e-02, -5.08232534e-02, -5.43716664e-02,
+ -5.79465483e-02, -6.15342620e-02, -6.51170816e-02, -6.86760675e-02,
+ -7.21944781e-02, -7.56569598e-02, -7.90464744e-02, -8.23444256e-02,
+ -8.55332458e-02, -8.85970547e-02, -9.15209110e-02, -9.42884745e-02,
+ -9.68830362e-02, -9.92912326e-02, -1.01500847e-01, -1.03496124e-01,
+ -1.05263700e-01, -1.06793998e-01, -1.08076646e-01, -1.09099730e-01,
+ -1.09852449e-01, -1.10324226e-01, -1.10508462e-01, -1.10397741e-01,
+ -1.09980985e-01, -1.09249277e-01, -1.08197423e-01, -1.06817214e-01,
+ -1.05099580e-01, -1.03036011e-01, -1.00619042e-01, -9.78412002e-02,
+ -9.46930422e-02, -9.11645251e-02, -8.72464453e-02, -8.29304391e-02,
+ -7.82061748e-02, -7.30614243e-02, -6.74846818e-02, -6.14668812e-02,
+ -5.49949726e-02, -4.80544442e-02, -4.06336286e-02, -3.27204559e-02,
+ -2.43012258e-02, -1.53632952e-02, -5.89143427e-03, 4.12659586e-03,
+ 1.47015507e-02, 2.58473819e-02, 3.75765277e-02, 4.98973651e-02,
+ 6.28203403e-02, 7.63539773e-02, 9.05036926e-02, 1.05274712e-01,
+ 1.20670347e-01, 1.36691102e-01, 1.53334389e-01, 1.70595471e-01,
+ 1.88468639e-01, 2.06944996e-01, 2.26009300e-01, 2.45645680e-01,
+ 2.65834602e-01, 2.86554381e-01, 3.07778908e-01, 3.29476944e-01,
+ 3.51617148e-01, 3.74164237e-01, 3.97073959e-01, 4.20304305e-01,
+ 4.43811480e-01, 4.67544229e-01, 4.91449863e-01, 5.15473546e-01,
+ 5.39555764e-01, 5.63639982e-01, 5.87666172e-01, 6.11569531e-01,
+ 6.35289059e-01, 6.58761977e-01, 6.81923097e-01, 7.04709282e-01,
+ 7.27057670e-01, 7.48906896e-01, 7.70199019e-01, 7.90875299e-01,
+ 8.10878869e-01, 8.30157914e-01, 8.48664336e-01, 8.66354816e-01,
+ 8.83189685e-01, 8.99132024e-01, 9.14154056e-01, 9.28228255e-01,
+ 9.41334815e-01, 9.53461939e-01, 9.64604825e-01, 9.74763483e-01,
+ 9.83943539e-01, 9.92152910e-01, 9.99411473e-01, 1.00574608e+00,
+ 1.01118397e+00, 1.01576037e+00, 1.01951507e+00, 1.02249094e+00,
+ 1.02473616e+00, 1.02630410e+00, 1.02725098e+00, 1.02763429e+00,
+ 1.02751106e+00, 1.02694280e+00, 1.02599149e+00, 1.02471615e+00,
+ 1.02317598e+00, 1.02142721e+00, 1.01952157e+00, 1.01751012e+00,
+ 1.01543986e+00, 1.01346092e+00, 1.01165490e+00, 1.00936693e+00,
+ 1.00726318e+00, 1.00531319e+00, 1.00350816e+00, 1.00184079e+00,
+ 1.00030393e+00, 9.98889821e-01, 9.97591528e-01, 9.96401528e-01,
+ 9.95313390e-01, 9.94320108e-01, 9.93415896e-01, 9.92594392e-01,
+ 9.91851028e-01, 9.91179799e-01, 9.90577196e-01, 9.90038105e-01,
+ 9.89559439e-01, 9.89137162e-01, 9.88768437e-01, 9.88449792e-01,
+ 9.88179075e-01, 9.87952836e-01, 9.87769137e-01, 9.87624927e-01,
+ 9.87517995e-01, 9.87445813e-01, 9.87405628e-01, 9.87395112e-01,
+ 9.87411537e-01, 9.87452485e-01, 9.87514989e-01, 9.87596889e-01,
+ 9.87695113e-01, 9.87807582e-01, 9.87931200e-01, 9.88064062e-01,
+ 9.88203257e-01, 9.88347108e-01, 9.88492687e-01, 9.88638659e-01,
+ 9.88782558e-01, 9.88923003e-01, 9.89058172e-01, 9.89186767e-01,
+ 9.89307497e-01, 9.89419640e-01, 9.89522076e-01, 9.89614633e-01,
+ 9.89697035e-01, 9.89769260e-01, 9.89831927e-01, 9.89885257e-01,
+ 9.89930764e-01, 9.89969310e-01, 9.90002569e-01, 9.90032156e-01,
+ 9.90060335e-01, 9.90088981e-01, 9.90120659e-01, 9.90157502e-01,
+ 9.90202395e-01, 9.90257541e-01, 9.90325529e-01, 9.90408791e-01,
+ 9.90509649e-01, 9.90630379e-01, 9.90772711e-01, 9.90938744e-01,
+ 9.91129889e-01, 9.91347632e-01, 9.91592856e-01, 9.91866549e-01,
+ 9.92169132e-01, 9.92501085e-01, 9.92861973e-01, 9.93251918e-01,
+ 9.93670021e-01, 9.94115607e-01, 9.94587315e-01, 9.95083740e-01,
+ 9.95603378e-01, 9.96143992e-01, 9.96703453e-01, 9.97279311e-01,
+ 9.97869086e-01, 9.98469709e-01, 9.99078484e-01, 9.99691901e-01,
+ 1.00030819e+00, 1.00092237e+00, 1.00153264e+00, 1.00213546e+00,
+ 1.00272811e+00, 1.00330745e+00, 1.00387093e+00, 1.00441604e+00,
+ 1.00494055e+00, 1.00544214e+00, 1.00591922e+00, 1.00637030e+00,
+ 1.00679393e+00, 1.00718935e+00, 1.00755557e+00, 1.00789267e+00,
+ 1.00820015e+00, 1.00847842e+00, 1.00872788e+00, 1.00894949e+00,
+ 1.00914411e+00, 1.00931322e+00, 1.00945824e+00, 1.00958128e+00,
+ 1.00968409e+00, 1.00976898e+00, 1.00983831e+00, 1.00989455e+00,
+ 1.00994034e+00, 1.00997792e+00, 1.01001023e+00, 1.01003945e+00,
+ 1.01006820e+00, 1.01009839e+00, 1.01013232e+00, 1.01017166e+00,
+ 1.01021810e+00, 1.01027252e+00, 1.01033649e+00, 1.01041022e+00,
+ 1.01049435e+00, 1.01058887e+00, 1.01069350e+00, 1.01080807e+00,
+ 1.01093144e+00, 1.01106288e+00, 1.01120107e+00, 1.01134470e+00,
+ 1.01149190e+00, 1.01164127e+00, 1.01179028e+00, 1.01193757e+00,
+ 1.01208013e+00, 1.01221624e+00, 1.01234291e+00, 1.01245818e+00,
+ 1.01255888e+00, 1.01264286e+00, 1.01270696e+00, 1.01274895e+00,
+ 1.01276580e+00, 1.01275501e+00, 1.01271380e+00, 1.01263978e+00,
+ 1.01253013e+00, 1.01238231e+00, 1.01219407e+00, 1.01196233e+00,
+ 1.01168517e+00, 1.01135914e+00, 1.01098214e+00, 1.01055072e+00,
+ 1.01006213e+00, 1.00951244e+00, 1.00889869e+00, 1.00821592e+00,
+ 1.00746086e+00, 1.00662774e+00, 1.00571234e+00, 1.00470868e+00,
+ 1.00361147e+00, 1.00241429e+00, 1.00111141e+00, 9.99696165e-01,
+ 9.98162595e-01, 9.96504102e-01, 9.94714888e-01, 9.92789191e-01,
+ 9.90720000e-01, 9.88479371e-01, 9.85534766e-01, 9.82376587e-01,
+ 9.78974733e-01, 9.75162381e-01, 9.70882175e-01, 9.66080552e-01,
+ 9.60697640e-01, 9.54673298e-01, 9.47947935e-01, 9.40460905e-01,
+ 9.32155386e-01, 9.22977548e-01, 9.12874535e-01, 9.01800368e-01,
+ 8.89716328e-01, 8.76590897e-01, 8.62398408e-01, 8.47120080e-01,
+ 8.30747973e-01, 8.13281737e-01, 7.94729145e-01, 7.75110884e-01,
+ 7.54455197e-01, 7.32796355e-01, 7.10179084e-01, 6.86658072e-01,
+ 6.62296243e-01, 6.37168412e-01, 6.11348804e-01, 5.84920660e-01,
+ 5.57974743e-01, 5.30618165e-01, 5.02952396e-01, 4.75086883e-01,
+ 4.47130985e-01, 4.19204992e-01, 3.91425291e-01, 3.63911468e-01,
+ 3.36783777e-01, 3.10162784e-01, 2.84164703e-01, 2.58903371e-01,
+ 2.34488060e-01, 2.11020945e-01, 1.88599764e-01, 1.67310081e-01,
+ 1.47228797e-01, 1.28422307e-01, 1.10942255e-01, 9.48266535e-02,
+ 8.00991437e-02, 6.67676585e-02, 5.48243661e-02, 4.42458885e-02,
+ 3.49936100e-02, 2.70146141e-02, 2.02437018e-02, 1.46079676e-02,
+ 9.99674359e-03, 5.30523510e-03, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_10M_320 = np.array([
+ -3.02115349e-04, -5.86773749e-04, -8.36650400e-04, -1.12663536e-03,
+ -1.47049294e-03, -1.87347339e-03, -2.33929236e-03, -2.87200807e-03,
+ -3.47625639e-03, -4.15596382e-03, -4.91456379e-03, -5.75517250e-03,
+ -6.68062338e-03, -7.69381692e-03, -8.79676075e-03, -9.99050307e-03,
+ -1.12757412e-02, -1.26533415e-02, -1.41243899e-02, -1.56888962e-02,
+ -1.73451209e-02, -1.90909737e-02, -2.09254671e-02, -2.28468479e-02,
+ -2.48520772e-02, -2.69374670e-02, -2.90995249e-02, -3.13350463e-02,
+ -3.36396073e-02, -3.60082097e-02, -3.84360174e-02, -4.09174603e-02,
+ -4.34465489e-02, -4.60178672e-02, -4.86259851e-02, -5.12647420e-02,
+ -5.39264475e-02, -5.66038431e-02, -5.92911675e-02, -6.19826820e-02,
+ -6.46702555e-02, -6.73454222e-02, -7.00009902e-02, -7.26305701e-02,
+ -7.52278496e-02, -7.77852594e-02, -8.02948025e-02, -8.27492454e-02,
+ -8.51412546e-02, -8.74637912e-02, -8.97106934e-02, -9.18756408e-02,
+ -9.39517698e-02, -9.59313774e-02, -9.78084326e-02, -9.95785130e-02,
+ -1.01236117e-01, -1.02774104e-01, -1.04186122e-01, -1.05468025e-01,
+ -1.06616088e-01, -1.07625538e-01, -1.08491230e-01, -1.09208742e-01,
+ -1.09773615e-01, -1.10180886e-01, -1.10427188e-01, -1.10510836e-01,
+ -1.10428147e-01, -1.10173922e-01, -1.09743736e-01, -1.09135313e-01,
+ -1.08346734e-01, -1.07373994e-01, -1.06213016e-01, -1.04860615e-01,
+ -1.03313240e-01, -1.01567316e-01, -9.96200551e-02, -9.74680323e-02,
+ -9.51072362e-02, -9.25330338e-02, -8.97412522e-02, -8.67287769e-02,
+ -8.34921384e-02, -8.00263990e-02, -7.63267954e-02, -7.23880616e-02,
+ -6.82057680e-02, -6.37761143e-02, -5.90938600e-02, -5.41531632e-02,
+ -4.89481272e-02, -4.34734711e-02, -3.77246130e-02, -3.16958761e-02,
+ -2.53817983e-02, -1.87768910e-02, -1.18746138e-02, -4.66909925e-03,
+ 2.84409675e-03, 1.06697612e-02, 1.88135595e-02, 2.72815601e-02,
+ 3.60781047e-02, 4.52070276e-02, 5.46723880e-02, 6.44786605e-02,
+ 7.46286220e-02, 8.51249057e-02, 9.59698399e-02, 1.07165078e-01,
+ 1.18711585e-01, 1.30610107e-01, 1.42859645e-01, 1.55458473e-01,
+ 1.68404161e-01, 1.81694789e-01, 1.95327388e-01, 2.09296321e-01,
+ 2.23594564e-01, 2.38216022e-01, 2.53152972e-01, 2.68396157e-01,
+ 2.83936139e-01, 2.99762426e-01, 3.15861908e-01, 3.32221055e-01,
+ 3.48826468e-01, 3.65664038e-01, 3.82715297e-01, 3.99961186e-01,
+ 4.17384327e-01, 4.34966962e-01, 4.52687640e-01, 4.70524201e-01,
+ 4.88453925e-01, 5.06454555e-01, 5.24500675e-01, 5.42567437e-01,
+ 5.60631204e-01, 5.78667265e-01, 5.96647704e-01, 6.14545890e-01,
+ 6.32336194e-01, 6.49992632e-01, 6.67487403e-01, 6.84793267e-01,
+ 7.01883546e-01, 7.18732254e-01, 7.35312821e-01, 7.51600199e-01,
+ 7.67569925e-01, 7.83197457e-01, 7.98458386e-01, 8.13329535e-01,
+ 8.27789227e-01, 8.41817856e-01, 8.55396130e-01, 8.68506898e-01,
+ 8.81133444e-01, 8.93259678e-01, 9.04874884e-01, 9.15965761e-01,
+ 9.26521530e-01, 9.36533999e-01, 9.45997703e-01, 9.54908841e-01,
+ 9.63265812e-01, 9.71068890e-01, 9.78320416e-01, 9.85022676e-01,
+ 9.91179208e-01, 9.96798994e-01, 1.00189402e+00, 1.00647434e+00,
+ 1.01055206e+00, 1.01414254e+00, 1.01726259e+00, 1.01992884e+00,
+ 1.02215987e+00, 1.02397632e+00, 1.02540073e+00, 1.02645534e+00,
+ 1.02716451e+00, 1.02755273e+00, 1.02764446e+00, 1.02746325e+00,
+ 1.02703590e+00, 1.02638907e+00, 1.02554820e+00, 1.02453713e+00,
+ 1.02338080e+00, 1.02210370e+00, 1.02072836e+00, 1.01927533e+00,
+ 1.01776518e+00, 1.01621736e+00, 1.01466531e+00, 1.01324907e+00,
+ 1.01194801e+00, 1.01018909e+00, 1.00855796e+00, 1.00701129e+00,
+ 1.00554876e+00, 1.00416842e+00, 1.00286727e+00, 1.00164177e+00,
+ 1.00048907e+00, 9.99406080e-01, 9.98389887e-01, 9.97437085e-01,
+ 9.96544484e-01, 9.95709855e-01, 9.94930241e-01, 9.94202405e-01,
+ 9.93524160e-01, 9.92893043e-01, 9.92306810e-01, 9.91763378e-01,
+ 9.91259764e-01, 9.90795450e-01, 9.90367789e-01, 9.89975161e-01,
+ 9.89616034e-01, 9.89289016e-01, 9.88992851e-01, 9.88726033e-01,
+ 9.88486872e-01, 9.88275104e-01, 9.88089217e-01, 9.87927711e-01,
+ 9.87789826e-01, 9.87674344e-01, 9.87580750e-01, 9.87507202e-01,
+ 9.87452945e-01, 9.87416974e-01, 9.87398469e-01, 9.87395830e-01,
+ 9.87408003e-01, 9.87434340e-01, 9.87473624e-01, 9.87524314e-01,
+ 9.87585620e-01, 9.87656379e-01, 9.87735892e-01, 9.87822558e-01,
+ 9.87915097e-01, 9.88013273e-01, 9.88115695e-01, 9.88221131e-01,
+ 9.88328903e-01, 9.88437831e-01, 9.88547679e-01, 9.88656841e-01,
+ 9.88764587e-01, 9.88870854e-01, 9.88974432e-01, 9.89074727e-01,
+ 9.89171004e-01, 9.89263102e-01, 9.89350722e-01, 9.89433065e-01,
+ 9.89509692e-01, 9.89581081e-01, 9.89646747e-01, 9.89706737e-01,
+ 9.89760693e-01, 9.89809448e-01, 9.89853013e-01, 9.89891471e-01,
+ 9.89925419e-01, 9.89955420e-01, 9.89982449e-01, 9.90006512e-01,
+ 9.90028481e-01, 9.90049748e-01, 9.90070956e-01, 9.90092836e-01,
+ 9.90116392e-01, 9.90142748e-01, 9.90173428e-01, 9.90208733e-01,
+ 9.90249864e-01, 9.90298369e-01, 9.90354850e-01, 9.90420508e-01,
+ 9.90495930e-01, 9.90582515e-01, 9.90681257e-01, 9.90792209e-01,
+ 9.90916546e-01, 9.91055074e-01, 9.91208461e-01, 9.91376861e-01,
+ 9.91560583e-01, 9.91760421e-01, 9.91976718e-01, 9.92209110e-01,
+ 9.92457914e-01, 9.92723123e-01, 9.93004954e-01, 9.93302728e-01,
+ 9.93616108e-01, 9.93945371e-01, 9.94289515e-01, 9.94648168e-01,
+ 9.95020303e-01, 9.95405817e-01, 9.95803871e-01, 9.96213027e-01,
+ 9.96632469e-01, 9.97061531e-01, 9.97499058e-01, 9.97943743e-01,
+ 9.98394057e-01, 9.98849312e-01, 9.99308343e-01, 9.99768922e-01,
+ 1.00023113e+00, 1.00069214e+00, 1.00115201e+00, 1.00160853e+00,
+ 1.00206049e+00, 1.00250721e+00, 1.00294713e+00, 1.00337891e+00,
+ 1.00380137e+00, 1.00421381e+00, 1.00461539e+00, 1.00500462e+00,
+ 1.00538063e+00, 1.00574328e+00, 1.00609151e+00, 1.00642491e+00,
+ 1.00674243e+00, 1.00704432e+00, 1.00733022e+00, 1.00759940e+00,
+ 1.00785206e+00, 1.00808818e+00, 1.00830803e+00, 1.00851125e+00,
+ 1.00869814e+00, 1.00886952e+00, 1.00902566e+00, 1.00916672e+00,
+ 1.00929336e+00, 1.00940640e+00, 1.00950702e+00, 1.00959526e+00,
+ 1.00967215e+00, 1.00973908e+00, 1.00979668e+00, 1.00984614e+00,
+ 1.00988808e+00, 1.00992409e+00, 1.00995538e+00, 1.00998227e+00,
+ 1.01000630e+00, 1.01002862e+00, 1.01005025e+00, 1.01007195e+00,
+ 1.01009437e+00, 1.01011892e+00, 1.01014650e+00, 1.01017711e+00,
+ 1.01021176e+00, 1.01025100e+00, 1.01029547e+00, 1.01034523e+00,
+ 1.01040032e+00, 1.01046156e+00, 1.01052862e+00, 1.01060152e+00,
+ 1.01067979e+00, 1.01076391e+00, 1.01085343e+00, 1.01094755e+00,
+ 1.01104595e+00, 1.01114849e+00, 1.01125440e+00, 1.01136308e+00,
+ 1.01147330e+00, 1.01158500e+00, 1.01169742e+00, 1.01180892e+00,
+ 1.01191926e+00, 1.01202724e+00, 1.01213215e+00, 1.01223273e+00,
+ 1.01232756e+00, 1.01241638e+00, 1.01249789e+00, 1.01257043e+00,
+ 1.01263330e+00, 1.01268528e+00, 1.01272556e+00, 1.01275258e+00,
+ 1.01276506e+00, 1.01276236e+00, 1.01274338e+00, 1.01270648e+00,
+ 1.01265084e+00, 1.01257543e+00, 1.01247947e+00, 1.01236111e+00,
+ 1.01221981e+00, 1.01205436e+00, 1.01186400e+00, 1.01164722e+00,
+ 1.01140252e+00, 1.01112965e+00, 1.01082695e+00, 1.01049292e+00,
+ 1.01012635e+00, 1.00972589e+00, 1.00929006e+00, 1.00881730e+00,
+ 1.00830503e+00, 1.00775283e+00, 1.00715783e+00, 1.00651805e+00,
+ 1.00583140e+00, 1.00509559e+00, 1.00430863e+00, 1.00346750e+00,
+ 1.00256950e+00, 1.00161271e+00, 1.00059427e+00, 9.99511170e-01,
+ 9.98360922e-01, 9.97140929e-01, 9.95848886e-01, 9.94481854e-01,
+ 9.93037528e-01, 9.91514656e-01, 9.89913680e-01, 9.88193062e-01,
+ 9.85942259e-01, 9.83566790e-01, 9.81142303e-01, 9.78521444e-01,
+ 9.75663604e-01, 9.72545344e-01, 9.69145663e-01, 9.65440618e-01,
+ 9.61404362e-01, 9.57011307e-01, 9.52236767e-01, 9.47054884e-01,
+ 9.41440374e-01, 9.35369161e-01, 9.28819009e-01, 9.21766289e-01,
+ 9.14189628e-01, 9.06069468e-01, 8.97389168e-01, 8.88133200e-01,
+ 8.78289389e-01, 8.67846957e-01, 8.56797064e-01, 8.45133465e-01,
+ 8.32854281e-01, 8.19959478e-01, 8.06451101e-01, 7.92334648e-01,
+ 7.77620449e-01, 7.62320618e-01, 7.46448649e-01, 7.30020573e-01,
+ 7.13056738e-01, 6.95580544e-01, 6.77617323e-01, 6.59195531e-01,
+ 6.40348643e-01, 6.21107220e-01, 6.01504928e-01, 5.81578761e-01,
+ 5.61367451e-01, 5.40918863e-01, 5.20273683e-01, 4.99478073e-01,
+ 4.78577418e-01, 4.57617260e-01, 4.36649021e-01, 4.15722146e-01,
+ 3.94885659e-01, 3.74190319e-01, 3.53686890e-01, 3.33426002e-01,
+ 3.13458647e-01, 2.93833790e-01, 2.74599264e-01, 2.55803064e-01,
+ 2.37490219e-01, 2.19703603e-01, 2.02485542e-01, 1.85874992e-01,
+ 1.69906780e-01, 1.54613227e-01, 1.40023821e-01, 1.26163740e-01,
+ 1.13053443e-01, 1.00708497e-01, 8.91402439e-02, 7.83561210e-02,
+ 6.83582123e-02, 5.91421154e-02, 5.06989301e-02, 4.30171776e-02,
+ 3.60802073e-02, 2.98631634e-02, 2.43372266e-02, 1.94767524e-02,
+ 1.52571017e-02, 1.16378749e-02, 8.43308778e-03, 4.44966900e-03,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_10M_480 = np.array([
+ -2.35303215e-04, -4.61989875e-04, -6.26293154e-04, -7.92918043e-04,
+ -9.74716672e-04, -1.18025689e-03, -1.40920904e-03, -1.66447310e-03,
+ -1.94659161e-03, -2.25708173e-03, -2.59710692e-03, -2.96760762e-03,
+ -3.37045488e-03, -3.80628516e-03, -4.27687377e-03, -4.78246990e-03,
+ -5.32460872e-03, -5.90340381e-03, -6.52041973e-03, -7.17588528e-03,
+ -7.87142282e-03, -8.60658604e-03, -9.38248086e-03, -1.01982718e-02,
+ -1.10552055e-02, -1.19527030e-02, -1.28920591e-02, -1.38726348e-02,
+ -1.48952816e-02, -1.59585662e-02, -1.70628856e-02, -1.82066640e-02,
+ -1.93906598e-02, -2.06135542e-02, -2.18757093e-02, -2.31752632e-02,
+ -2.45122745e-02, -2.58847194e-02, -2.72926374e-02, -2.87339090e-02,
+ -3.02086274e-02, -3.17144037e-02, -3.32509886e-02, -3.48159779e-02,
+ -3.64089241e-02, -3.80274232e-02, -3.96706799e-02, -4.13357542e-02,
+ -4.30220337e-02, -4.47269805e-02, -4.64502229e-02, -4.81889149e-02,
+ -4.99422586e-02, -5.17069080e-02, -5.34816204e-02, -5.52633479e-02,
+ -5.70512315e-02, -5.88427175e-02, -6.06371724e-02, -6.24310403e-02,
+ -6.42230355e-02, -6.60096152e-02, -6.77896227e-02, -6.95599687e-02,
+ -7.13196627e-02, -7.30658127e-02, -7.47975891e-02, -7.65117823e-02,
+ -7.82071142e-02, -7.98801069e-02, -8.15296401e-02, -8.31523735e-02,
+ -8.47472895e-02, -8.63113754e-02, -8.78437445e-02, -8.93416436e-02,
+ -9.08041129e-02, -9.22279576e-02, -9.36123287e-02, -9.49537776e-02,
+ -9.62515531e-02, -9.75028462e-02, -9.87073651e-02, -9.98627129e-02,
+ -1.00968022e-01, -1.02020268e-01, -1.03018380e-01, -1.03959636e-01,
+ -1.04843883e-01, -1.05668684e-01, -1.06434282e-01, -1.07138231e-01,
+ -1.07779996e-01, -1.08357063e-01, -1.08869014e-01, -1.09313559e-01,
+ -1.09690356e-01, -1.09996966e-01, -1.10233226e-01, -1.10397281e-01,
+ -1.10489847e-01, -1.10508642e-01, -1.10453743e-01, -1.10322584e-01,
+ -1.10114583e-01, -1.09827693e-01, -1.09462175e-01, -1.09016396e-01,
+ -1.08490885e-01, -1.07883429e-01, -1.07193718e-01, -1.06419636e-01,
+ -1.05561251e-01, -1.04616281e-01, -1.03584904e-01, -1.02465016e-01,
+ -1.01256900e-01, -9.99586457e-02, -9.85701457e-02, -9.70891114e-02,
+ -9.55154582e-02, -9.38468492e-02, -9.20830006e-02, -9.02217102e-02,
+ -8.82630999e-02, -8.62049382e-02, -8.40474215e-02, -8.17879272e-02,
+ -7.94262503e-02, -7.69598078e-02, -7.43878560e-02, -7.17079700e-02,
+ -6.89199478e-02, -6.60218980e-02, -6.30134942e-02, -5.98919191e-02,
+ -5.66565564e-02, -5.33040616e-02, -4.98342724e-02, -4.62445689e-02,
+ -4.25345569e-02, -3.87019577e-02, -3.47458578e-02, -3.06634152e-02,
+ -2.64542508e-02, -2.21158161e-02, -1.76474054e-02, -1.30458136e-02,
+ -8.31042570e-03, -3.43826866e-03, 1.57031548e-03, 6.71769764e-03,
+ 1.20047702e-02, 1.74339832e-02, 2.30064206e-02, 2.87248142e-02,
+ 3.45889635e-02, 4.06010646e-02, 4.67610292e-02, 5.30713391e-02,
+ 5.95323909e-02, 6.61464781e-02, 7.29129318e-02, 7.98335419e-02,
+ 8.69080741e-02, 9.41381377e-02, 1.01523314e-01, 1.09065152e-01,
+ 1.16762655e-01, 1.24617139e-01, 1.32627295e-01, 1.40793819e-01,
+ 1.49115252e-01, 1.57592141e-01, 1.66222480e-01, 1.75006740e-01,
+ 1.83943194e-01, 1.93031818e-01, 2.02269985e-01, 2.11656743e-01,
+ 2.21188852e-01, 2.30865538e-01, 2.40683799e-01, 2.50642064e-01,
+ 2.60736512e-01, 2.70965907e-01, 2.81325902e-01, 2.91814469e-01,
+ 3.02427028e-01, 3.13160350e-01, 3.24009570e-01, 3.34971959e-01,
+ 3.46042294e-01, 3.57217518e-01, 3.68491565e-01, 3.79859512e-01,
+ 3.91314689e-01, 4.02853287e-01, 4.14468833e-01, 4.26157164e-01,
+ 4.37911390e-01, 4.49725632e-01, 4.61592545e-01, 4.73506703e-01,
+ 4.85460018e-01, 4.97447159e-01, 5.09459723e-01, 5.21490984e-01,
+ 5.33532682e-01, 5.45578981e-01, 5.57621716e-01, 5.69654673e-01,
+ 5.81668558e-01, 5.93656062e-01, 6.05608382e-01, 6.17519206e-01,
+ 6.29379661e-01, 6.41183084e-01, 6.52920354e-01, 6.64584079e-01,
+ 6.76165350e-01, 6.87657395e-01, 6.99051154e-01, 7.10340055e-01,
+ 7.21514933e-01, 7.32569177e-01, 7.43494372e-01, 7.54284633e-01,
+ 7.64931365e-01, 7.75428189e-01, 7.85767017e-01, 7.95941465e-01,
+ 8.05943723e-01, 8.15768707e-01, 8.25408622e-01, 8.34858937e-01,
+ 8.44112583e-01, 8.53165119e-01, 8.62010834e-01, 8.70645634e-01,
+ 8.79063156e-01, 8.87259971e-01, 8.95231329e-01, 9.02975168e-01,
+ 9.10486312e-01, 9.17762555e-01, 9.24799743e-01, 9.31596250e-01,
+ 9.38149486e-01, 9.44458839e-01, 9.50522086e-01, 9.56340292e-01,
+ 9.61911452e-01, 9.67236671e-01, 9.72315664e-01, 9.77150119e-01,
+ 9.81739750e-01, 9.86086587e-01, 9.90190638e-01, 9.94055718e-01,
+ 9.97684240e-01, 1.00108096e+00, 1.00424751e+00, 1.00718858e+00,
+ 1.00990665e+00, 1.01240743e+00, 1.01469470e+00, 1.01677466e+00,
+ 1.01865099e+00, 1.02033046e+00, 1.02181733e+00, 1.02311884e+00,
+ 1.02424026e+00, 1.02518972e+00, 1.02597245e+00, 1.02659694e+00,
+ 1.02706918e+00, 1.02739752e+00, 1.02758790e+00, 1.02764895e+00,
+ 1.02758583e+00, 1.02740852e+00, 1.02712299e+00, 1.02673867e+00,
+ 1.02626166e+00, 1.02570100e+00, 1.02506178e+00, 1.02435398e+00,
+ 1.02358239e+00, 1.02275651e+00, 1.02188060e+00, 1.02096387e+00,
+ 1.02000914e+00, 1.01902729e+00, 1.01801944e+00, 1.01699650e+00,
+ 1.01595743e+00, 1.01492344e+00, 1.01391595e+00, 1.01304757e+00,
+ 1.01221613e+00, 1.01104487e+00, 1.00991459e+00, 1.00882489e+00,
+ 1.00777386e+00, 1.00676170e+00, 1.00578665e+00, 1.00484875e+00,
+ 1.00394608e+00, 1.00307885e+00, 1.00224501e+00, 1.00144473e+00,
+ 1.00067619e+00, 9.99939317e-01, 9.99232085e-01, 9.98554813e-01,
+ 9.97905542e-01, 9.97284268e-01, 9.96689095e-01, 9.96120338e-01,
+ 9.95576126e-01, 9.95056572e-01, 9.94559753e-01, 9.94086038e-01,
+ 9.93633779e-01, 9.93203161e-01, 9.92792187e-01, 9.92401518e-01,
+ 9.92029727e-01, 9.91676778e-01, 9.91340877e-01, 9.91023065e-01,
+ 9.90721643e-01, 9.90436680e-01, 9.90166895e-01, 9.89913101e-01,
+ 9.89673564e-01, 9.89448837e-01, 9.89237484e-01, 9.89040193e-01,
+ 9.88855636e-01, 9.88684347e-01, 9.88524761e-01, 9.88377852e-01,
+ 9.88242327e-01, 9.88118564e-01, 9.88005163e-01, 9.87903202e-01,
+ 9.87811174e-01, 9.87729546e-01, 9.87657198e-01, 9.87594984e-01,
+ 9.87541274e-01, 9.87496906e-01, 9.87460625e-01, 9.87432981e-01,
+ 9.87412641e-01, 9.87400475e-01, 9.87394992e-01, 9.87396916e-01,
+ 9.87404906e-01, 9.87419705e-01, 9.87439972e-01, 9.87466328e-01,
+ 9.87497321e-01, 9.87533893e-01, 9.87574654e-01, 9.87620124e-01,
+ 9.87668980e-01, 9.87722156e-01, 9.87778192e-01, 9.87837649e-01,
+ 9.87899199e-01, 9.87963798e-01, 9.88030030e-01, 9.88098468e-01,
+ 9.88167801e-01, 9.88239030e-01, 9.88310769e-01, 9.88383520e-01,
+ 9.88456016e-01, 9.88529420e-01, 9.88602222e-01, 9.88674940e-01,
+ 9.88746626e-01, 9.88818277e-01, 9.88888248e-01, 9.88957438e-01,
+ 9.89024798e-01, 9.89091125e-01, 9.89155170e-01, 9.89217866e-01,
+ 9.89277956e-01, 9.89336519e-01, 9.89392368e-01, 9.89446283e-01,
+ 9.89497212e-01, 9.89546334e-01, 9.89592362e-01, 9.89636265e-01,
+ 9.89677201e-01, 9.89716220e-01, 9.89752029e-01, 9.89785920e-01,
+ 9.89817027e-01, 9.89846207e-01, 9.89872536e-01, 9.89897514e-01,
+ 9.89920005e-01, 9.89941079e-01, 9.89960061e-01, 9.89978226e-01,
+ 9.89994556e-01, 9.90010350e-01, 9.90024832e-01, 9.90039402e-01,
+ 9.90053211e-01, 9.90067475e-01, 9.90081472e-01, 9.90096693e-01,
+ 9.90112245e-01, 9.90129379e-01, 9.90147465e-01, 9.90168060e-01,
+ 9.90190227e-01, 9.90215190e-01, 9.90242442e-01, 9.90273445e-01,
+ 9.90307127e-01, 9.90344891e-01, 9.90386228e-01, 9.90432448e-01,
+ 9.90482565e-01, 9.90537983e-01, 9.90598060e-01, 9.90664037e-01,
+ 9.90734883e-01, 9.90812038e-01, 9.90894786e-01, 9.90984259e-01,
+ 9.91079525e-01, 9.91181924e-01, 9.91290512e-01, 9.91406471e-01,
+ 9.91528801e-01, 9.91658694e-01, 9.91795272e-01, 9.91939622e-01,
+ 9.92090615e-01, 9.92249503e-01, 9.92415240e-01, 9.92588721e-01,
+ 9.92768871e-01, 9.92956911e-01, 9.93151653e-01, 9.93353924e-01,
+ 9.93562689e-01, 9.93779087e-01, 9.94001643e-01, 9.94231202e-01,
+ 9.94466818e-01, 9.94709344e-01, 9.94957285e-01, 9.95211663e-01,
+ 9.95471264e-01, 9.95736795e-01, 9.96006862e-01, 9.96282303e-01,
+ 9.96561799e-01, 9.96846133e-01, 9.97133827e-01, 9.97425669e-01,
+ 9.97720337e-01, 9.98018509e-01, 9.98318587e-01, 9.98621352e-01,
+ 9.98925543e-01, 9.99231731e-01, 9.99538258e-01, 9.99846116e-01,
+ 1.00015391e+00, 1.00046196e+00, 1.00076886e+00, 1.00107561e+00,
+ 1.00138055e+00, 1.00168424e+00, 1.00198543e+00, 1.00228487e+00,
+ 1.00258098e+00, 1.00287441e+00, 1.00316385e+00, 1.00345006e+00,
+ 1.00373157e+00, 1.00400915e+00, 1.00428146e+00, 1.00454934e+00,
+ 1.00481138e+00, 1.00506827e+00, 1.00531880e+00, 1.00556397e+00,
+ 1.00580227e+00, 1.00603455e+00, 1.00625986e+00, 1.00647902e+00,
+ 1.00669054e+00, 1.00689557e+00, 1.00709305e+00, 1.00728380e+00,
+ 1.00746662e+00, 1.00764273e+00, 1.00781104e+00, 1.00797244e+00,
+ 1.00812588e+00, 1.00827260e+00, 1.00841147e+00, 1.00854357e+00,
+ 1.00866802e+00, 1.00878601e+00, 1.00889653e+00, 1.00900077e+00,
+ 1.00909776e+00, 1.00918888e+00, 1.00927316e+00, 1.00935176e+00,
+ 1.00942394e+00, 1.00949118e+00, 1.00955240e+00, 1.00960889e+00,
+ 1.00965997e+00, 1.00970709e+00, 1.00974924e+00, 1.00978774e+00,
+ 1.00982209e+00, 1.00985371e+00, 1.00988150e+00, 1.00990696e+00,
+ 1.00992957e+00, 1.00995057e+00, 1.00996902e+00, 1.00998650e+00,
+ 1.01000236e+00, 1.01001789e+00, 1.01003217e+00, 1.01004672e+00,
+ 1.01006081e+00, 1.01007567e+00, 1.01009045e+00, 1.01010656e+00,
+ 1.01012323e+00, 1.01014176e+00, 1.01016113e+00, 1.01018264e+00,
+ 1.01020559e+00, 1.01023108e+00, 1.01025795e+00, 1.01028773e+00,
+ 1.01031948e+00, 1.01035408e+00, 1.01039064e+00, 1.01043047e+00,
+ 1.01047227e+00, 1.01051710e+00, 1.01056410e+00, 1.01061427e+00,
+ 1.01066629e+00, 1.01072136e+00, 1.01077842e+00, 1.01083825e+00,
+ 1.01089966e+00, 1.01096373e+00, 1.01102919e+00, 1.01109699e+00,
+ 1.01116586e+00, 1.01123661e+00, 1.01130817e+00, 1.01138145e+00,
+ 1.01145479e+00, 1.01152919e+00, 1.01160368e+00, 1.01167880e+00,
+ 1.01175301e+00, 1.01182748e+00, 1.01190094e+00, 1.01197388e+00,
+ 1.01204489e+00, 1.01211499e+00, 1.01218284e+00, 1.01224902e+00,
+ 1.01231210e+00, 1.01237303e+00, 1.01243046e+00, 1.01248497e+00,
+ 1.01253506e+00, 1.01258168e+00, 1.01262347e+00, 1.01266098e+00,
+ 1.01269276e+00, 1.01271979e+00, 1.01274058e+00, 1.01275575e+00,
+ 1.01276395e+00, 1.01276592e+00, 1.01276030e+00, 1.01274782e+00,
+ 1.01272696e+00, 1.01269861e+00, 1.01266140e+00, 1.01261590e+00,
+ 1.01256083e+00, 1.01249705e+00, 1.01242289e+00, 1.01233923e+00,
+ 1.01224492e+00, 1.01214046e+00, 1.01202430e+00, 1.01189756e+00,
+ 1.01175881e+00, 1.01160845e+00, 1.01144516e+00, 1.01126996e+00,
+ 1.01108126e+00, 1.01087961e+00, 1.01066368e+00, 1.01043418e+00,
+ 1.01018968e+00, 1.00993075e+00, 1.00965566e+00, 1.00936525e+00,
+ 1.00905825e+00, 1.00873476e+00, 1.00839308e+00, 1.00803431e+00,
+ 1.00765666e+00, 1.00726014e+00, 1.00684335e+00, 1.00640701e+00,
+ 1.00594915e+00, 1.00547001e+00, 1.00496799e+00, 1.00444353e+00,
+ 1.00389477e+00, 1.00332190e+00, 1.00272313e+00, 1.00209885e+00,
+ 1.00144728e+00, 1.00076851e+00, 1.00006069e+00, 9.99324268e-01,
+ 9.98557350e-01, 9.97760020e-01, 9.96930604e-01, 9.96069427e-01,
+ 9.95174643e-01, 9.94246644e-01, 9.93283713e-01, 9.92286108e-01,
+ 9.91252309e-01, 9.90182742e-01, 9.89075787e-01, 9.87931302e-01,
+ 9.86355322e-01, 9.84736245e-01, 9.83175095e-01, 9.81558334e-01,
+ 9.79861353e-01, 9.78061749e-01, 9.76157432e-01, 9.74137862e-01,
+ 9.71999011e-01, 9.69732741e-01, 9.67333198e-01, 9.64791512e-01,
+ 9.62101150e-01, 9.59253976e-01, 9.56242718e-01, 9.53060091e-01,
+ 9.49698408e-01, 9.46149812e-01, 9.42407161e-01, 9.38463416e-01,
+ 9.34311297e-01, 9.29944987e-01, 9.25356797e-01, 9.20540463e-01,
+ 9.15489628e-01, 9.10198679e-01, 9.04662060e-01, 8.98875519e-01,
+ 8.92833832e-01, 8.86533719e-01, 8.79971272e-01, 8.73143784e-01,
+ 8.66047653e-01, 8.58681252e-01, 8.51042044e-01, 8.43129723e-01,
+ 8.34943514e-01, 8.26483991e-01, 8.17750537e-01, 8.08744982e-01,
+ 7.99468149e-01, 7.89923516e-01, 7.80113773e-01, 7.70043128e-01,
+ 7.59714574e-01, 7.49133097e-01, 7.38302860e-01, 7.27229876e-01,
+ 7.15920192e-01, 7.04381434e-01, 6.92619693e-01, 6.80643883e-01,
+ 6.68461648e-01, 6.56083014e-01, 6.43517927e-01, 6.30775533e-01,
+ 6.17864165e-01, 6.04795463e-01, 5.91579959e-01, 5.78228937e-01,
+ 5.64753589e-01, 5.51170316e-01, 5.37490509e-01, 5.23726350e-01,
+ 5.09891542e-01, 4.96000807e-01, 4.82066294e-01, 4.68101711e-01,
+ 4.54121700e-01, 4.40142182e-01, 4.26177297e-01, 4.12241789e-01,
+ 3.98349961e-01, 3.84517234e-01, 3.70758372e-01, 3.57088679e-01,
+ 3.43522867e-01, 3.30076376e-01, 3.16764033e-01, 3.03600465e-01,
+ 2.90599616e-01, 2.77775850e-01, 2.65143468e-01, 2.52716188e-01,
+ 2.40506985e-01, 2.28528397e-01, 2.16793343e-01, 2.05313990e-01,
+ 1.94102191e-01, 1.83168087e-01, 1.72522195e-01, 1.62173542e-01,
+ 1.52132068e-01, 1.42405280e-01, 1.33001524e-01, 1.23926066e-01,
+ 1.15185830e-01, 1.06784043e-01, 9.87263751e-02, 9.10137900e-02,
+ 8.36505724e-02, 7.66350831e-02, 6.99703341e-02, 6.36518811e-02,
+ 5.76817602e-02, 5.20524422e-02, 4.67653841e-02, 4.18095054e-02,
+ 3.71864025e-02, 3.28807275e-02, 2.88954850e-02, 2.52098057e-02,
+ 2.18305756e-02, 1.87289619e-02, 1.59212782e-02, 1.33638143e-02,
+ 1.10855888e-02, 8.94347419e-03, 6.75812489e-03, 3.50443813e-03,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_7M5_60 = np.array([
+ 2.95060859e-03, 7.17541132e-03, 1.37695374e-02, 2.30953556e-02,
+ 3.54036230e-02, 5.08289304e-02, 6.94696293e-02, 9.13884278e-02,
+ 1.16604575e-01, 1.45073546e-01, 1.76711174e-01, 2.11342953e-01,
+ 2.48768614e-01, 2.88701102e-01, 3.30823871e-01, 3.74814544e-01,
+ 4.20308013e-01, 4.66904918e-01, 5.14185341e-01, 5.61710041e-01,
+ 6.09026346e-01, 6.55671016e-01, 7.01218384e-01, 7.45240679e-01,
+ 7.87369206e-01, 8.27223833e-01, 8.64513675e-01, 8.98977415e-01,
+ 9.30407518e-01, 9.58599937e-01, 9.83447719e-01, 1.00488283e+00,
+ 1.02285381e+00, 1.03740495e+00, 1.04859791e+00, 1.05656184e+00,
+ 1.06149371e+00, 1.06362578e+00, 1.06325973e+00, 1.06074505e+00,
+ 1.05643590e+00, 1.05069500e+00, 1.04392435e+00, 1.03647725e+00,
+ 1.02872867e+00, 1.02106486e+00, 1.01400658e+00, 1.00727455e+00,
+ 1.00172250e+00, 9.97309592e-01, 9.93985158e-01, 9.91683335e-01,
+ 9.90325325e-01, 9.89822613e-01, 9.90074734e-01, 9.90975314e-01,
+ 9.92412851e-01, 9.94273149e-01, 9.96439157e-01, 9.98791616e-01,
+ 1.00120985e+00, 1.00357357e+00, 1.00575984e+00, 1.00764515e+00,
+ 1.00910687e+00, 1.01002476e+00, 1.01028203e+00, 1.00976919e+00,
+ 1.00838641e+00, 1.00605124e+00, 1.00269767e+00, 9.98280464e-01,
+ 9.92777987e-01, 9.86186892e-01, 9.77634164e-01, 9.67447270e-01,
+ 9.55129725e-01, 9.40389877e-01, 9.22959280e-01, 9.02607350e-01,
+ 8.79202689e-01, 8.52641750e-01, 8.22881272e-01, 7.89971715e-01,
+ 7.54030328e-01, 7.15255742e-01, 6.73936911e-01, 6.30414716e-01,
+ 5.85078858e-01, 5.38398518e-01, 4.90833753e-01, 4.42885823e-01,
+ 3.95091024e-01, 3.48004343e-01, 3.02196710e-01, 2.58227431e-01,
+ 2.16641416e-01, 1.77922122e-01, 1.42480547e-01, 1.10652194e-01,
+ 8.26995967e-02, 5.88334516e-02, 3.92030848e-02, 2.38629107e-02,
+ 1.26976223e-02, 5.35665361e-03, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_7M5_120 = np.array([
+ 2.20824874e-03, 3.81014420e-03, 5.91552473e-03, 8.58361457e-03,
+ 1.18759723e-02, 1.58335301e-02, 2.04918652e-02, 2.58883593e-02,
+ 3.20415894e-02, 3.89616721e-02, 4.66742169e-02, 5.51849337e-02,
+ 6.45038384e-02, 7.46411071e-02, 8.56000162e-02, 9.73846703e-02,
+ 1.09993603e-01, 1.23419277e-01, 1.37655457e-01, 1.52690437e-01,
+ 1.68513363e-01, 1.85093105e-01, 2.02410419e-01, 2.20450365e-01,
+ 2.39167941e-01, 2.58526168e-01, 2.78498539e-01, 2.99038432e-01,
+ 3.20104862e-01, 3.41658622e-01, 3.63660034e-01, 3.86062695e-01,
+ 4.08815272e-01, 4.31871046e-01, 4.55176988e-01, 4.78676593e-01,
+ 5.02324813e-01, 5.26060916e-01, 5.49831283e-01, 5.73576883e-01,
+ 5.97241338e-01, 6.20770242e-01, 6.44099662e-01, 6.67176382e-01,
+ 6.89958854e-01, 7.12379980e-01, 7.34396372e-01, 7.55966688e-01,
+ 7.77036981e-01, 7.97558114e-01, 8.17490856e-01, 8.36796950e-01,
+ 8.55447310e-01, 8.73400798e-01, 8.90635719e-01, 9.07128770e-01,
+ 9.22848784e-01, 9.37763323e-01, 9.51860206e-01, 9.65130600e-01,
+ 9.77556541e-01, 9.89126209e-01, 9.99846919e-01, 1.00970073e+00,
+ 1.01868229e+00, 1.02681455e+00, 1.03408981e+00, 1.04051196e+00,
+ 1.04610837e+00, 1.05088565e+00, 1.05486289e+00, 1.05807221e+00,
+ 1.06053414e+00, 1.06227662e+00, 1.06333815e+00, 1.06375557e+00,
+ 1.06356632e+00, 1.06282156e+00, 1.06155996e+00, 1.05981709e+00,
+ 1.05765876e+00, 1.05512006e+00, 1.05223985e+00, 1.04908779e+00,
+ 1.04569860e+00, 1.04210831e+00, 1.03838099e+00, 1.03455276e+00,
+ 1.03067200e+00, 1.02679167e+00, 1.02295558e+00, 1.01920733e+00,
+ 1.01587289e+00, 1.01221017e+00, 1.00884559e+00, 1.00577851e+00,
+ 1.00300262e+00, 1.00051460e+00, 9.98309229e-01, 9.96378601e-01,
+ 9.94718132e-01, 9.93316216e-01, 9.92166957e-01, 9.91258603e-01,
+ 9.90581104e-01, 9.90123118e-01, 9.89873712e-01, 9.89818707e-01,
+ 9.89946800e-01, 9.90243175e-01, 9.90695564e-01, 9.91288540e-01,
+ 9.92009469e-01, 9.92842693e-01, 9.93775067e-01, 9.94790398e-01,
+ 9.95875534e-01, 9.97014367e-01, 9.98192871e-01, 9.99394506e-01,
+ 1.00060586e+00, 1.00181040e+00, 1.00299457e+00, 1.00414155e+00,
+ 1.00523688e+00, 1.00626393e+00, 1.00720890e+00, 1.00805489e+00,
+ 1.00878802e+00, 1.00939182e+00, 1.00985296e+00, 1.01015529e+00,
+ 1.01028602e+00, 1.01022988e+00, 1.00997541e+00, 1.00950846e+00,
+ 1.00881848e+00, 1.00789488e+00, 1.00672876e+00, 1.00530991e+00,
+ 1.00363456e+00, 1.00169363e+00, 9.99485663e-01, 9.97006370e-01,
+ 9.94254687e-01, 9.91231967e-01, 9.87937115e-01, 9.84375125e-01,
+ 9.79890963e-01, 9.75269879e-01, 9.70180498e-01, 9.64580027e-01,
+ 9.58425534e-01, 9.51684014e-01, 9.44320232e-01, 9.36290624e-01,
+ 9.27580507e-01, 9.18153414e-01, 9.07976524e-01, 8.97050058e-01,
+ 8.85351360e-01, 8.72857927e-01, 8.59579819e-01, 8.45502615e-01,
+ 8.30619943e-01, 8.14946648e-01, 7.98489378e-01, 7.81262450e-01,
+ 7.63291769e-01, 7.44590843e-01, 7.25199287e-01, 7.05153668e-01,
+ 6.84490545e-01, 6.63245210e-01, 6.41477162e-01, 6.19235334e-01,
+ 5.96559133e-01, 5.73519989e-01, 5.50173851e-01, 5.26568538e-01,
+ 5.02781159e-01, 4.78860889e-01, 4.54877894e-01, 4.30898123e-01,
+ 4.06993964e-01, 3.83234031e-01, 3.59680098e-01, 3.36408100e-01,
+ 3.13496418e-01, 2.91010565e-01, 2.69019585e-01, 2.47584348e-01,
+ 2.26788433e-01, 2.06677771e-01, 1.87310343e-01, 1.68739644e-01,
+ 1.51012382e-01, 1.34171842e-01, 1.18254662e-01, 1.03290734e-01,
+ 8.93117360e-02, 7.63429787e-02, 6.44077291e-02, 5.35243715e-02,
+ 4.37084453e-02, 3.49667099e-02, 2.72984629e-02, 2.06895808e-02,
+ 1.51125125e-02, 1.05228754e-02, 6.85547314e-03, 4.02351119e-03,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_7M5_180 = np.array([
+ 1.97084908e-03, 2.95060859e-03, 4.12447721e-03, 5.52688664e-03,
+ 7.17541132e-03, 9.08757730e-03, 1.12819105e-02, 1.37695374e-02,
+ 1.65600266e-02, 1.96650895e-02, 2.30953556e-02, 2.68612894e-02,
+ 3.09632560e-02, 3.54036230e-02, 4.01915610e-02, 4.53331403e-02,
+ 5.08289304e-02, 5.66815448e-02, 6.28935304e-02, 6.94696293e-02,
+ 7.64106314e-02, 8.37160016e-02, 9.13884278e-02, 9.94294008e-02,
+ 1.07834725e-01, 1.16604575e-01, 1.25736503e-01, 1.35226811e-01,
+ 1.45073546e-01, 1.55273819e-01, 1.65822194e-01, 1.76711174e-01,
+ 1.87928776e-01, 1.99473180e-01, 2.11342953e-01, 2.23524554e-01,
+ 2.36003100e-01, 2.48768614e-01, 2.61813811e-01, 2.75129161e-01,
+ 2.88701102e-01, 3.02514034e-01, 3.16558805e-01, 3.30823871e-01,
+ 3.45295567e-01, 3.59963992e-01, 3.74814544e-01, 3.89831817e-01,
+ 4.05001010e-01, 4.20308013e-01, 4.35739515e-01, 4.51277817e-01,
+ 4.66904918e-01, 4.82609041e-01, 4.98375466e-01, 5.14185341e-01,
+ 5.30021478e-01, 5.45869352e-01, 5.61710041e-01, 5.77528151e-01,
+ 5.93304696e-01, 6.09026346e-01, 6.24674189e-01, 6.40227555e-01,
+ 6.55671016e-01, 6.70995935e-01, 6.86184559e-01, 7.01218384e-01,
+ 7.16078449e-01, 7.30756084e-01, 7.45240679e-01, 7.59515122e-01,
+ 7.73561955e-01, 7.87369206e-01, 8.00923138e-01, 8.14211386e-01,
+ 8.27223833e-01, 8.39952374e-01, 8.52386102e-01, 8.64513675e-01,
+ 8.76324079e-01, 8.87814288e-01, 8.98977415e-01, 9.09803319e-01,
+ 9.20284312e-01, 9.30407518e-01, 9.40169652e-01, 9.49567795e-01,
+ 9.58599937e-01, 9.67260260e-01, 9.75545166e-01, 9.83447719e-01,
+ 9.90971957e-01, 9.98119269e-01, 1.00488283e+00, 1.01125773e+00,
+ 1.01724436e+00, 1.02285381e+00, 1.02808734e+00, 1.03293706e+00,
+ 1.03740495e+00, 1.04150164e+00, 1.04523236e+00, 1.04859791e+00,
+ 1.05160340e+00, 1.05425505e+00, 1.05656184e+00, 1.05853400e+00,
+ 1.06017414e+00, 1.06149371e+00, 1.06249943e+00, 1.06320577e+00,
+ 1.06362578e+00, 1.06376487e+00, 1.06363778e+00, 1.06325973e+00,
+ 1.06264695e+00, 1.06180496e+00, 1.06074505e+00, 1.05948492e+00,
+ 1.05804533e+00, 1.05643590e+00, 1.05466218e+00, 1.05274047e+00,
+ 1.05069500e+00, 1.04853894e+00, 1.04627898e+00, 1.04392435e+00,
+ 1.04149540e+00, 1.03901003e+00, 1.03647725e+00, 1.03390793e+00,
+ 1.03131989e+00, 1.02872867e+00, 1.02614832e+00, 1.02358988e+00,
+ 1.02106486e+00, 1.01856262e+00, 1.01655770e+00, 1.01400658e+00,
+ 1.01162953e+00, 1.00938590e+00, 1.00727455e+00, 1.00529616e+00,
+ 1.00344526e+00, 1.00172250e+00, 1.00012792e+00, 9.98657533e-01,
+ 9.97309592e-01, 9.96083571e-01, 9.94976569e-01, 9.93985158e-01,
+ 9.93107530e-01, 9.92341305e-01, 9.91683335e-01, 9.91130070e-01,
+ 9.90678325e-01, 9.90325325e-01, 9.90067562e-01, 9.89901282e-01,
+ 9.89822613e-01, 9.89827845e-01, 9.89913241e-01, 9.90074734e-01,
+ 9.90308256e-01, 9.90609852e-01, 9.90975314e-01, 9.91400330e-01,
+ 9.91880966e-01, 9.92412851e-01, 9.92991779e-01, 9.93613381e-01,
+ 9.94273149e-01, 9.94966958e-01, 9.95690370e-01, 9.96439157e-01,
+ 9.97208572e-01, 9.97994275e-01, 9.98791616e-01, 9.99596062e-01,
+ 1.00040410e+00, 1.00120985e+00, 1.00200976e+00, 1.00279924e+00,
+ 1.00357357e+00, 1.00432828e+00, 1.00505850e+00, 1.00575984e+00,
+ 1.00642767e+00, 1.00705768e+00, 1.00764515e+00, 1.00818549e+00,
+ 1.00867427e+00, 1.00910687e+00, 1.00947916e+00, 1.00978659e+00,
+ 1.01002476e+00, 1.01018954e+00, 1.01027669e+00, 1.01028203e+00,
+ 1.01020174e+00, 1.01003208e+00, 1.00976919e+00, 1.00940939e+00,
+ 1.00894931e+00, 1.00838641e+00, 1.00771780e+00, 1.00694031e+00,
+ 1.00605124e+00, 1.00504879e+00, 1.00393183e+00, 1.00269767e+00,
+ 1.00134427e+00, 9.99872092e-01, 9.98280464e-01, 9.96566569e-01,
+ 9.94731737e-01, 9.92777987e-01, 9.90701374e-01, 9.88504165e-01,
+ 9.86186892e-01, 9.83711989e-01, 9.80584643e-01, 9.77634164e-01,
+ 9.74455033e-01, 9.71062916e-01, 9.67447270e-01, 9.63593926e-01,
+ 9.59491398e-01, 9.55129725e-01, 9.50501326e-01, 9.45592810e-01,
+ 9.40389877e-01, 9.34886760e-01, 9.29080559e-01, 9.22959280e-01,
+ 9.16509579e-01, 9.09724456e-01, 9.02607350e-01, 8.95155084e-01,
+ 8.87356154e-01, 8.79202689e-01, 8.70699698e-01, 8.61847424e-01,
+ 8.52641750e-01, 8.43077833e-01, 8.33154905e-01, 8.22881272e-01,
+ 8.12257597e-01, 8.01285439e-01, 7.89971715e-01, 7.78318177e-01,
+ 7.66337710e-01, 7.54030328e-01, 7.41407991e-01, 7.28477501e-01,
+ 7.15255742e-01, 7.01751739e-01, 6.87975632e-01, 6.73936911e-01,
+ 6.59652573e-01, 6.45139489e-01, 6.30414716e-01, 6.15483622e-01,
+ 6.00365852e-01, 5.85078858e-01, 5.69649536e-01, 5.54084810e-01,
+ 5.38398518e-01, 5.22614738e-01, 5.06756805e-01, 4.90833753e-01,
+ 4.74866033e-01, 4.58876566e-01, 4.42885823e-01, 4.26906539e-01,
+ 4.10970973e-01, 3.95091024e-01, 3.79291327e-01, 3.63587417e-01,
+ 3.48004343e-01, 3.32563201e-01, 3.17287485e-01, 3.02196710e-01,
+ 2.87309403e-01, 2.72643992e-01, 2.58227431e-01, 2.44072856e-01,
+ 2.30208977e-01, 2.16641416e-01, 2.03398481e-01, 1.90486162e-01,
+ 1.77922122e-01, 1.65726674e-01, 1.53906397e-01, 1.42480547e-01,
+ 1.31453980e-01, 1.20841778e-01, 1.10652194e-01, 1.00891734e-01,
+ 9.15718851e-02, 8.26995967e-02, 7.42815529e-02, 6.63242382e-02,
+ 5.88334516e-02, 5.18140676e-02, 4.52698346e-02, 3.92030848e-02,
+ 3.36144159e-02, 2.85023308e-02, 2.38629107e-02, 1.96894227e-02,
+ 1.59720527e-02, 1.26976223e-02, 9.84937739e-03, 7.40724463e-03,
+ 5.35665361e-03, 3.83226552e-03, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_7M5_240 = np.array([
+ 1.84833037e-03, 2.56481839e-03, 3.36762118e-03, 4.28736617e-03,
+ 5.33830143e-03, 6.52679223e-03, 7.86112587e-03, 9.34628179e-03,
+ 1.09916868e-02, 1.28011172e-02, 1.47805911e-02, 1.69307043e-02,
+ 1.92592307e-02, 2.17696937e-02, 2.44685983e-02, 2.73556543e-02,
+ 3.04319230e-02, 3.36980464e-02, 3.71583577e-02, 4.08148180e-02,
+ 4.46708068e-02, 4.87262995e-02, 5.29820633e-02, 5.74382470e-02,
+ 6.20968580e-02, 6.69609767e-02, 7.20298364e-02, 7.73039146e-02,
+ 8.27825574e-02, 8.84682102e-02, 9.43607566e-02, 1.00460272e-01,
+ 1.06763824e-01, 1.13273679e-01, 1.19986420e-01, 1.26903521e-01,
+ 1.34020853e-01, 1.41339557e-01, 1.48857211e-01, 1.56573685e-01,
+ 1.64484622e-01, 1.72589077e-01, 1.80879090e-01, 1.89354320e-01,
+ 1.98012244e-01, 2.06854141e-01, 2.15875319e-01, 2.25068672e-01,
+ 2.34427407e-01, 2.43948314e-01, 2.53627993e-01, 2.63464061e-01,
+ 2.73450494e-01, 2.83582189e-01, 2.93853469e-01, 3.04257373e-01,
+ 3.14790914e-01, 3.25449123e-01, 3.36227410e-01, 3.47118760e-01,
+ 3.58120177e-01, 3.69224663e-01, 3.80427793e-01, 3.91720023e-01,
+ 4.03097022e-01, 4.14551955e-01, 4.26081719e-01, 4.37676318e-01,
+ 4.49330196e-01, 4.61034855e-01, 4.72786043e-01, 4.84576777e-01,
+ 4.96401707e-01, 5.08252458e-01, 5.20122078e-01, 5.32002077e-01,
+ 5.43888090e-01, 5.55771601e-01, 5.67645739e-01, 5.79502786e-01,
+ 5.91335035e-01, 6.03138367e-01, 6.14904172e-01, 6.26623941e-01,
+ 6.38288834e-01, 6.49893375e-01, 6.61432360e-01, 6.72902514e-01,
+ 6.84293750e-01, 6.95600460e-01, 7.06811784e-01, 7.17923425e-01,
+ 7.28931386e-01, 7.39832773e-01, 7.50618982e-01, 7.61284053e-01,
+ 7.71818919e-01, 7.82220992e-01, 7.92481330e-01, 8.02599448e-01,
+ 8.12565230e-01, 8.22377129e-01, 8.32030518e-01, 8.41523208e-01,
+ 8.50848313e-01, 8.60002412e-01, 8.68979881e-01, 8.77778347e-01,
+ 8.86395904e-01, 8.94829421e-01, 9.03077626e-01, 9.11132652e-01,
+ 9.18993585e-01, 9.26652937e-01, 9.34111420e-01, 9.41364344e-01,
+ 9.48412967e-01, 9.55255630e-01, 9.61892013e-01, 9.68316363e-01,
+ 9.74530156e-01, 9.80528338e-01, 9.86313928e-01, 9.91886049e-01,
+ 9.97246345e-01, 1.00239190e+00, 1.00731946e+00, 1.01202707e+00,
+ 1.01651654e+00, 1.02079430e+00, 1.02486082e+00, 1.02871471e+00,
+ 1.03235170e+00, 1.03577375e+00, 1.03898432e+00, 1.04198786e+00,
+ 1.04478564e+00, 1.04737818e+00, 1.04976743e+00, 1.05195405e+00,
+ 1.05394290e+00, 1.05573463e+00, 1.05734177e+00, 1.05875726e+00,
+ 1.05998674e+00, 1.06103672e+00, 1.06190651e+00, 1.06260369e+00,
+ 1.06313289e+00, 1.06350237e+00, 1.06370981e+00, 1.06376322e+00,
+ 1.06366765e+00, 1.06343012e+00, 1.06305656e+00, 1.06255421e+00,
+ 1.06192235e+00, 1.06116702e+00, 1.06029469e+00, 1.05931469e+00,
+ 1.05823465e+00, 1.05705891e+00, 1.05578948e+00, 1.05442979e+00,
+ 1.05298793e+00, 1.05147505e+00, 1.04989930e+00, 1.04826213e+00,
+ 1.04656691e+00, 1.04481699e+00, 1.04302125e+00, 1.04118768e+00,
+ 1.03932339e+00, 1.03743168e+00, 1.03551757e+00, 1.03358511e+00,
+ 1.03164371e+00, 1.02969955e+00, 1.02775944e+00, 1.02582719e+00,
+ 1.02390791e+00, 1.02200805e+00, 1.02013910e+00, 1.01826310e+00,
+ 1.01687901e+00, 1.01492195e+00, 1.01309662e+00, 1.01134205e+00,
+ 1.00965912e+00, 1.00805036e+00, 1.00651754e+00, 1.00505799e+00,
+ 1.00366956e+00, 1.00235327e+00, 1.00110981e+00, 9.99937523e-01,
+ 9.98834524e-01, 9.97800606e-01, 9.96835756e-01, 9.95938881e-01,
+ 9.95108459e-01, 9.94343411e-01, 9.93642921e-01, 9.93005832e-01,
+ 9.92430984e-01, 9.91917493e-01, 9.91463898e-01, 9.91068214e-01,
+ 9.90729218e-01, 9.90446225e-01, 9.90217819e-01, 9.90041963e-01,
+ 9.89917085e-01, 9.89841975e-01, 9.89815048e-01, 9.89834329e-01,
+ 9.89898211e-01, 9.90005403e-01, 9.90154189e-01, 9.90342427e-01,
+ 9.90568459e-01, 9.90830953e-01, 9.91128038e-01, 9.91457566e-01,
+ 9.91817881e-01, 9.92207559e-01, 9.92624757e-01, 9.93067358e-01,
+ 9.93533398e-01, 9.94021410e-01, 9.94529685e-01, 9.95055964e-01,
+ 9.95598351e-01, 9.96155580e-01, 9.96725627e-01, 9.97306092e-01,
+ 9.97895214e-01, 9.98491441e-01, 9.99092890e-01, 9.99697063e-01,
+ 1.00030303e+00, 1.00090793e+00, 1.00151084e+00, 1.00210923e+00,
+ 1.00270118e+00, 1.00328513e+00, 1.00385926e+00, 1.00442111e+00,
+ 1.00496860e+00, 1.00550040e+00, 1.00601455e+00, 1.00650869e+00,
+ 1.00698104e+00, 1.00743004e+00, 1.00785364e+00, 1.00824962e+00,
+ 1.00861604e+00, 1.00895138e+00, 1.00925390e+00, 1.00952134e+00,
+ 1.00975175e+00, 1.00994371e+00, 1.01009550e+00, 1.01020488e+00,
+ 1.01027007e+00, 1.01028975e+00, 1.01026227e+00, 1.01018562e+00,
+ 1.01005820e+00, 1.00987882e+00, 1.00964593e+00, 1.00935753e+00,
+ 1.00901228e+00, 1.00860959e+00, 1.00814837e+00, 1.00762674e+00,
+ 1.00704343e+00, 1.00639775e+00, 1.00568877e+00, 1.00491559e+00,
+ 1.00407768e+00, 1.00317429e+00, 1.00220424e+00, 1.00116684e+00,
+ 1.00006248e+00, 9.98891422e-01, 9.97652252e-01, 9.96343856e-01,
+ 9.94967462e-01, 9.93524663e-01, 9.92013927e-01, 9.90433283e-01,
+ 9.88785147e-01, 9.87072681e-01, 9.85297443e-01, 9.83401161e-01,
+ 9.80949418e-01, 9.78782729e-01, 9.76468238e-01, 9.74042850e-01,
+ 9.71498848e-01, 9.68829968e-01, 9.66030974e-01, 9.63095104e-01,
+ 9.60018198e-01, 9.56795738e-01, 9.53426267e-01, 9.49903482e-01,
+ 9.46222115e-01, 9.42375820e-01, 9.38361702e-01, 9.34177798e-01,
+ 9.29823124e-01, 9.25292320e-01, 9.20580120e-01, 9.15679793e-01,
+ 9.10590604e-01, 9.05315030e-01, 8.99852756e-01, 8.94199497e-01,
+ 8.88350152e-01, 8.82301631e-01, 8.76054874e-01, 8.69612385e-01,
+ 8.62972799e-01, 8.56135198e-01, 8.49098179e-01, 8.41857024e-01,
+ 8.34414055e-01, 8.26774617e-01, 8.18939244e-01, 8.10904891e-01,
+ 8.02675318e-01, 7.94253751e-01, 7.85641662e-01, 7.76838609e-01,
+ 7.67853193e-01, 7.58685181e-01, 7.49330658e-01, 7.39809171e-01,
+ 7.30109944e-01, 7.20247781e-01, 7.10224161e-01, 7.00044326e-01,
+ 6.89711890e-01, 6.79231154e-01, 6.68608179e-01, 6.57850997e-01,
+ 6.46965718e-01, 6.35959617e-01, 6.24840336e-01, 6.13603503e-01,
+ 6.02265091e-01, 5.90829083e-01, 5.79309408e-01, 5.67711124e-01,
+ 5.56037416e-01, 5.44293664e-01, 5.32489768e-01, 5.20636084e-01,
+ 5.08743273e-01, 4.96811166e-01, 4.84849881e-01, 4.72868107e-01,
+ 4.60875918e-01, 4.48881081e-01, 4.36891039e-01, 4.24912022e-01,
+ 4.12960603e-01, 4.01035896e-01, 3.89157867e-01, 3.77322199e-01,
+ 3.65543767e-01, 3.53832356e-01, 3.42196115e-01, 3.30644820e-01,
+ 3.19187559e-01, 3.07833309e-01, 2.96588182e-01, 2.85463717e-01,
+ 2.74462409e-01, 2.63609584e-01, 2.52883101e-01, 2.42323489e-01,
+ 2.31925746e-01, 2.21690837e-01, 2.11638058e-01, 2.01766920e-01,
+ 1.92082236e-01, 1.82589160e-01, 1.73305997e-01, 1.64229200e-01,
+ 1.55362654e-01, 1.46717079e-01, 1.38299391e-01, 1.30105078e-01,
+ 1.22145310e-01, 1.14423458e-01, 1.06941076e-01, 9.97025893e-02,
+ 9.27124283e-02, 8.59737427e-02, 7.94893311e-02, 7.32616579e-02,
+ 6.72934102e-02, 6.15874081e-02, 5.61458003e-02, 5.09700747e-02,
+ 4.60617047e-02, 4.14220117e-02, 3.70514189e-02, 3.29494666e-02,
+ 2.91153327e-02, 2.55476401e-02, 2.22437711e-02, 1.92000659e-02,
+ 1.64122205e-02, 1.38747611e-02, 1.15806353e-02, 9.52213664e-03,
+ 7.69137380e-03, 6.07207833e-03, 4.62581217e-03, 3.60685164e-03,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+W_7M5_360 = np.array([
+ 1.72152668e-03, 2.20824874e-03, 2.68901752e-03, 3.22613342e-03,
+ 3.81014420e-03, 4.45371932e-03, 5.15369240e-03, 5.91552473e-03,
+ 6.73869158e-03, 7.62861841e-03, 8.58361457e-03, 9.60938437e-03,
+ 1.07060753e-02, 1.18759723e-02, 1.31190130e-02, 1.44390108e-02,
+ 1.58335301e-02, 1.73063081e-02, 1.88584711e-02, 2.04918652e-02,
+ 2.22061476e-02, 2.40057166e-02, 2.58883593e-02, 2.78552326e-02,
+ 2.99059145e-02, 3.20415894e-02, 3.42610013e-02, 3.65680973e-02,
+ 3.89616721e-02, 4.14435824e-02, 4.40140796e-02, 4.66742169e-02,
+ 4.94214625e-02, 5.22588489e-02, 5.51849337e-02, 5.82005143e-02,
+ 6.13059845e-02, 6.45038384e-02, 6.77913923e-02, 7.11707833e-02,
+ 7.46411071e-02, 7.82028053e-02, 8.18549521e-02, 8.56000162e-02,
+ 8.94357617e-02, 9.33642589e-02, 9.73846703e-02, 1.01496718e-01,
+ 1.05698760e-01, 1.09993603e-01, 1.14378287e-01, 1.18853508e-01,
+ 1.23419277e-01, 1.28075997e-01, 1.32820581e-01, 1.37655457e-01,
+ 1.42578648e-01, 1.47590522e-01, 1.52690437e-01, 1.57878853e-01,
+ 1.63152529e-01, 1.68513363e-01, 1.73957969e-01, 1.79484737e-01,
+ 1.85093105e-01, 1.90784835e-01, 1.96556497e-01, 2.02410419e-01,
+ 2.08345433e-01, 2.14359825e-01, 2.20450365e-01, 2.26617296e-01,
+ 2.32856279e-01, 2.39167941e-01, 2.45550642e-01, 2.52003951e-01,
+ 2.58526168e-01, 2.65118408e-01, 2.71775911e-01, 2.78498539e-01,
+ 2.85284606e-01, 2.92132459e-01, 2.99038432e-01, 3.06004256e-01,
+ 3.13026529e-01, 3.20104862e-01, 3.27237324e-01, 3.34423210e-01,
+ 3.41658622e-01, 3.48944976e-01, 3.56279252e-01, 3.63660034e-01,
+ 3.71085146e-01, 3.78554327e-01, 3.86062695e-01, 3.93610554e-01,
+ 4.01195225e-01, 4.08815272e-01, 4.16468460e-01, 4.24155411e-01,
+ 4.31871046e-01, 4.39614744e-01, 4.47384019e-01, 4.55176988e-01,
+ 4.62990138e-01, 4.70824619e-01, 4.78676593e-01, 4.86545433e-01,
+ 4.94428714e-01, 5.02324813e-01, 5.10229471e-01, 5.18142927e-01,
+ 5.26060916e-01, 5.33982818e-01, 5.41906817e-01, 5.49831283e-01,
+ 5.57751234e-01, 5.65667636e-01, 5.73576883e-01, 5.81476666e-01,
+ 5.89364661e-01, 5.97241338e-01, 6.05102013e-01, 6.12946170e-01,
+ 6.20770242e-01, 6.28572094e-01, 6.36348526e-01, 6.44099662e-01,
+ 6.51820973e-01, 6.59513822e-01, 6.67176382e-01, 6.74806795e-01,
+ 6.82400711e-01, 6.89958854e-01, 6.97475722e-01, 7.04950145e-01,
+ 7.12379980e-01, 7.19765434e-01, 7.27103833e-01, 7.34396372e-01,
+ 7.41638561e-01, 7.48829639e-01, 7.55966688e-01, 7.63049259e-01,
+ 7.70072273e-01, 7.77036981e-01, 7.83941108e-01, 7.90781257e-01,
+ 7.97558114e-01, 8.04271381e-01, 8.10914901e-01, 8.17490856e-01,
+ 8.23997094e-01, 8.30432785e-01, 8.36796950e-01, 8.43089298e-01,
+ 8.49305847e-01, 8.55447310e-01, 8.61511037e-01, 8.67496281e-01,
+ 8.73400798e-01, 8.79227518e-01, 8.84972438e-01, 8.90635719e-01,
+ 8.96217173e-01, 9.01716414e-01, 9.07128770e-01, 9.12456578e-01,
+ 9.17697261e-01, 9.22848784e-01, 9.27909917e-01, 9.32882596e-01,
+ 9.37763323e-01, 9.42553356e-01, 9.47252428e-01, 9.51860206e-01,
+ 9.56376060e-01, 9.60800602e-01, 9.65130600e-01, 9.69366689e-01,
+ 9.73508812e-01, 9.77556541e-01, 9.81507226e-01, 9.85364580e-01,
+ 9.89126209e-01, 9.92794201e-01, 9.96367545e-01, 9.99846919e-01,
+ 1.00322812e+00, 1.00651341e+00, 1.00970073e+00, 1.01279029e+00,
+ 1.01578293e+00, 1.01868229e+00, 1.02148657e+00, 1.02419772e+00,
+ 1.02681455e+00, 1.02933598e+00, 1.03176043e+00, 1.03408981e+00,
+ 1.03632326e+00, 1.03846361e+00, 1.04051196e+00, 1.04246831e+00,
+ 1.04433331e+00, 1.04610837e+00, 1.04779018e+00, 1.04938334e+00,
+ 1.05088565e+00, 1.05229923e+00, 1.05362522e+00, 1.05486289e+00,
+ 1.05601521e+00, 1.05708746e+00, 1.05807221e+00, 1.05897524e+00,
+ 1.05979447e+00, 1.06053414e+00, 1.06119412e+00, 1.06177366e+00,
+ 1.06227662e+00, 1.06270324e+00, 1.06305569e+00, 1.06333815e+00,
+ 1.06354800e+00, 1.06368607e+00, 1.06375557e+00, 1.06375743e+00,
+ 1.06369358e+00, 1.06356632e+00, 1.06337707e+00, 1.06312782e+00,
+ 1.06282156e+00, 1.06245782e+00, 1.06203634e+00, 1.06155996e+00,
+ 1.06102951e+00, 1.06044797e+00, 1.05981709e+00, 1.05914163e+00,
+ 1.05842136e+00, 1.05765876e+00, 1.05685377e+00, 1.05600761e+00,
+ 1.05512006e+00, 1.05419505e+00, 1.05323346e+00, 1.05223985e+00,
+ 1.05121668e+00, 1.05016637e+00, 1.04908779e+00, 1.04798366e+00,
+ 1.04685334e+00, 1.04569860e+00, 1.04452056e+00, 1.04332348e+00,
+ 1.04210831e+00, 1.04087907e+00, 1.03963603e+00, 1.03838099e+00,
+ 1.03711403e+00, 1.03583813e+00, 1.03455276e+00, 1.03326200e+00,
+ 1.03196750e+00, 1.03067200e+00, 1.02937564e+00, 1.02808244e+00,
+ 1.02679167e+00, 1.02550635e+00, 1.02422655e+00, 1.02295558e+00,
+ 1.02169299e+00, 1.02044475e+00, 1.01920733e+00, 1.01799992e+00,
+ 1.01716022e+00, 1.01587289e+00, 1.01461783e+00, 1.01339738e+00,
+ 1.01221017e+00, 1.01105652e+00, 1.00993444e+00, 1.00884559e+00,
+ 1.00778956e+00, 1.00676790e+00, 1.00577851e+00, 1.00482173e+00,
+ 1.00389592e+00, 1.00300262e+00, 1.00214091e+00, 1.00131213e+00,
+ 1.00051460e+00, 9.99748988e-01, 9.99013486e-01, 9.98309229e-01,
+ 9.97634934e-01, 9.96991885e-01, 9.96378601e-01, 9.95795982e-01,
+ 9.95242217e-01, 9.94718132e-01, 9.94222122e-01, 9.93755313e-01,
+ 9.93316216e-01, 9.92905809e-01, 9.92522422e-01, 9.92166957e-01,
+ 9.91837704e-01, 9.91535508e-01, 9.91258603e-01, 9.91007878e-01,
+ 9.90781723e-01, 9.90581104e-01, 9.90404336e-01, 9.90252267e-01,
+ 9.90123118e-01, 9.90017726e-01, 9.89934325e-01, 9.89873712e-01,
+ 9.89834110e-01, 9.89816359e-01, 9.89818707e-01, 9.89841998e-01,
+ 9.89884438e-01, 9.89946800e-01, 9.90027287e-01, 9.90126680e-01,
+ 9.90243175e-01, 9.90377594e-01, 9.90528134e-01, 9.90695564e-01,
+ 9.90878043e-01, 9.91076302e-01, 9.91288540e-01, 9.91515602e-01,
+ 9.91755666e-01, 9.92009469e-01, 9.92275155e-01, 9.92553486e-01,
+ 9.92842693e-01, 9.93143533e-01, 9.93454080e-01, 9.93775067e-01,
+ 9.94104689e-01, 9.94443742e-01, 9.94790398e-01, 9.95145361e-01,
+ 9.95506800e-01, 9.95875534e-01, 9.96249681e-01, 9.96629919e-01,
+ 9.97014367e-01, 9.97403799e-01, 9.97796404e-01, 9.98192871e-01,
+ 9.98591286e-01, 9.98992436e-01, 9.99394506e-01, 9.99798247e-01,
+ 1.00020179e+00, 1.00060586e+00, 1.00100858e+00, 1.00141070e+00,
+ 1.00181040e+00, 1.00220846e+00, 1.00260296e+00, 1.00299457e+00,
+ 1.00338148e+00, 1.00376444e+00, 1.00414155e+00, 1.00451348e+00,
+ 1.00487832e+00, 1.00523688e+00, 1.00558730e+00, 1.00593027e+00,
+ 1.00626393e+00, 1.00658905e+00, 1.00690380e+00, 1.00720890e+00,
+ 1.00750238e+00, 1.00778498e+00, 1.00805489e+00, 1.00831287e+00,
+ 1.00855700e+00, 1.00878802e+00, 1.00900405e+00, 1.00920593e+00,
+ 1.00939182e+00, 1.00956244e+00, 1.00971590e+00, 1.00985296e+00,
+ 1.00997177e+00, 1.01007317e+00, 1.01015529e+00, 1.01021893e+00,
+ 1.01026225e+00, 1.01028602e+00, 1.01028842e+00, 1.01027030e+00,
+ 1.01022988e+00, 1.01016802e+00, 1.01008292e+00, 1.00997541e+00,
+ 1.00984369e+00, 1.00968863e+00, 1.00950846e+00, 1.00930404e+00,
+ 1.00907371e+00, 1.00881848e+00, 1.00853675e+00, 1.00822947e+00,
+ 1.00789488e+00, 1.00753391e+00, 1.00714488e+00, 1.00672876e+00,
+ 1.00628393e+00, 1.00581146e+00, 1.00530991e+00, 1.00478053e+00,
+ 1.00422177e+00, 1.00363456e+00, 1.00301719e+00, 1.00237067e+00,
+ 1.00169363e+00, 1.00098749e+00, 1.00025108e+00, 9.99485663e-01,
+ 9.98689592e-01, 9.97863666e-01, 9.97006370e-01, 9.96119199e-01,
+ 9.95201404e-01, 9.94254687e-01, 9.93277595e-01, 9.92270651e-01,
+ 9.91231967e-01, 9.90163286e-01, 9.89064394e-01, 9.87937115e-01,
+ 9.86779736e-01, 9.85592773e-01, 9.84375125e-01, 9.83129288e-01,
+ 9.81348463e-01, 9.79890963e-01, 9.78400459e-01, 9.76860435e-01,
+ 9.75269879e-01, 9.73627353e-01, 9.71931341e-01, 9.70180498e-01,
+ 9.68372652e-01, 9.66506952e-01, 9.64580027e-01, 9.62592318e-01,
+ 9.60540986e-01, 9.58425534e-01, 9.56244393e-01, 9.53998416e-01,
+ 9.51684014e-01, 9.49301185e-01, 9.46846884e-01, 9.44320232e-01,
+ 9.41718404e-01, 9.39042580e-01, 9.36290624e-01, 9.33464050e-01,
+ 9.30560854e-01, 9.27580507e-01, 9.24519592e-01, 9.21378471e-01,
+ 9.18153414e-01, 9.14844696e-01, 9.11451652e-01, 9.07976524e-01,
+ 9.04417545e-01, 9.00776308e-01, 8.97050058e-01, 8.93238398e-01,
+ 8.89338681e-01, 8.85351360e-01, 8.81274023e-01, 8.77109638e-01,
+ 8.72857927e-01, 8.68519505e-01, 8.64092796e-01, 8.59579819e-01,
+ 8.54976007e-01, 8.50285220e-01, 8.45502615e-01, 8.40630470e-01,
+ 8.35667925e-01, 8.30619943e-01, 8.25482007e-01, 8.20258909e-01,
+ 8.14946648e-01, 8.09546696e-01, 8.04059978e-01, 7.98489378e-01,
+ 7.92831417e-01, 7.87090668e-01, 7.81262450e-01, 7.75353947e-01,
+ 7.69363613e-01, 7.63291769e-01, 7.57139016e-01, 7.50901711e-01,
+ 7.44590843e-01, 7.38205136e-01, 7.31738075e-01, 7.25199287e-01,
+ 7.18588225e-01, 7.11905687e-01, 7.05153668e-01, 6.98332634e-01,
+ 6.91444101e-01, 6.84490545e-01, 6.77470119e-01, 6.70388375e-01,
+ 6.63245210e-01, 6.56045780e-01, 6.48788627e-01, 6.41477162e-01,
+ 6.34114323e-01, 6.26702000e-01, 6.19235334e-01, 6.11720596e-01,
+ 6.04161612e-01, 5.96559133e-01, 5.88914401e-01, 5.81234783e-01,
+ 5.73519989e-01, 5.65770616e-01, 5.57988067e-01, 5.50173851e-01,
+ 5.42330194e-01, 5.34460798e-01, 5.26568538e-01, 5.18656324e-01,
+ 5.10728813e-01, 5.02781159e-01, 4.94819491e-01, 4.86845139e-01,
+ 4.78860889e-01, 4.70869928e-01, 4.62875144e-01, 4.54877894e-01,
+ 4.46882512e-01, 4.38889325e-01, 4.30898123e-01, 4.22918322e-01,
+ 4.14950878e-01, 4.06993964e-01, 3.99052648e-01, 3.91134614e-01,
+ 3.83234031e-01, 3.75354653e-01, 3.67502060e-01, 3.59680098e-01,
+ 3.51887312e-01, 3.44130166e-01, 3.36408100e-01, 3.28728966e-01,
+ 3.21090505e-01, 3.13496418e-01, 3.05951565e-01, 2.98454319e-01,
+ 2.91010565e-01, 2.83621109e-01, 2.76285415e-01, 2.69019585e-01,
+ 2.61812445e-01, 2.54659232e-01, 2.47584348e-01, 2.40578694e-01,
+ 2.33647009e-01, 2.26788433e-01, 2.20001992e-01, 2.13301325e-01,
+ 2.06677771e-01, 2.00140409e-01, 1.93683630e-01, 1.87310343e-01,
+ 1.81027384e-01, 1.74839476e-01, 1.68739644e-01, 1.62737273e-01,
+ 1.56825277e-01, 1.51012382e-01, 1.45298230e-01, 1.39687469e-01,
+ 1.34171842e-01, 1.28762544e-01, 1.23455562e-01, 1.18254662e-01,
+ 1.13159677e-01, 1.08171439e-01, 1.03290734e-01, 9.85202978e-02,
+ 9.38600023e-02, 8.93117360e-02, 8.48752103e-02, 8.05523737e-02,
+ 7.63429787e-02, 7.22489246e-02, 6.82699120e-02, 6.44077291e-02,
+ 6.06620003e-02, 5.70343711e-02, 5.35243715e-02, 5.01334690e-02,
+ 4.68610790e-02, 4.37084453e-02, 4.06748365e-02, 3.77612269e-02,
+ 3.49667099e-02, 3.22919275e-02, 2.97357669e-02, 2.72984629e-02,
+ 2.49787186e-02, 2.27762542e-02, 2.06895808e-02, 1.87178169e-02,
+ 1.68593418e-02, 1.51125125e-02, 1.34757094e-02, 1.19462709e-02,
+ 1.05228754e-02, 9.20130941e-03, 7.98124316e-03, 6.85547314e-03,
+ 5.82657334e-03, 4.87838525e-03, 4.02351119e-03, 3.15418663e-03,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
+])
+
+
+### 3.7.4 ###
+
+SNS_LFCB = np.array([
+
+ [ 2.26283366e+00, 8.13311269e-01, -5.30193495e-01, -1.35664836e+00,
+ -1.59952177e+00, -1.44098768e+00, -1.14381648e+00, -7.55203768e-01 ],
+
+ [ 2.94516479e+00, 2.41143318e+00, 9.60455106e-01, -4.43226488e-01,
+ -1.22913612e+00, -1.55590039e+00, -1.49688656e+00, -1.11689987e+00 ],
+
+ [ -2.18610707e+00, -1.97152136e+00, -1.78718620e+00, -1.91865896e+00,
+ -1.79399122e+00, -1.35738404e+00, -7.05444279e-01, -4.78172945e-02 ],
+
+ [ 6.93688237e-01, 9.55609857e-01, 5.75230787e-01, -1.14603419e-01,
+ -6.46050637e-01, -9.52351370e-01, -1.07405247e+00, -7.58087707e-01 ],
+
+ [ -1.29752132e+00, -7.40369057e-01, -3.45372484e-01, -3.13285696e-01,
+ -4.02977243e-01, -3.72020853e-01, -7.83414177e-02, 9.70441304e-02 ],
+
+ [ 9.14652038e-01, 1.74293043e+00, 1.90906627e+00, 1.54408484e+00,
+ 1.09344961e+00, 6.47479550e-01, 3.61790752e-02, -2.97092807e-01 ],
+
+ [ -2.51428813e+00, -2.89175271e+00, -2.00450667e+00, -7.50912274e-01,
+ 4.41202105e-01, 1.20190988e+00, 1.32742857e+00, 1.22049081e+00 ],
+
+ [ -9.22188405e-01, 6.32495141e-01, 1.08736431e+00, 6.08628625e-01,
+ 1.31174568e-01, -2.96149158e-01, -2.07013517e-01, 1.34924917e-01 ],
+
+ [ 7.90322288e-01, 6.28401262e-01, 3.93117924e-01, 4.80007711e-01,
+ 4.47815138e-01, 2.09734215e-01, 6.56691996e-03, -8.61242342e-02 ],
+
+ [ 1.44775580e+00, 2.72399952e+00, 2.31083269e+00, 9.35051270e-01,
+ -2.74743911e-01, -9.02077697e-01, -9.40681512e-01, -6.33697039e-01 ],
+
+ [ 7.93354526e-01, 1.43931186e-02, -5.67834845e-01, -6.54760468e-01,
+ -4.79458998e-01, -1.73894662e-01, 6.80162706e-02, 2.95125948e-01 ],
+
+ [ 2.72425347e+00, 2.95947572e+00, 1.84953559e+00, 5.63284922e-01,
+ 1.39917088e-01, 3.59641093e-01, 6.89461355e-01, 6.39790177e-01 ],
+
+ [ -5.30830198e-01, -2.12690683e-01, 5.76613628e-03, 4.24871484e-01,
+ 4.73128952e-01, 8.58894199e-01, 1.19111161e+00, 9.96189670e-01 ],
+
+ [ 1.68728411e+00, 2.43614509e+00, 2.33019429e+00, 1.77983778e+00,
+ 1.44411295e+00, 1.51995177e+00, 1.47199394e+00, 9.77682474e-01 ],
+
+ [ -2.95183273e+00, -1.59393497e+00, -1.09918773e-01, 3.88609073e-01,
+ 5.12932650e-01, 6.28112597e-01, 8.22621796e-01, 8.75891425e-01 ],
+
+ [ 1.01878343e-01, 5.89857324e-01, 6.19047647e-01, 1.26731314e+00,
+ 2.41961048e+00, 2.25174253e+00, 5.26537031e-01, -3.96591513e-01 ],
+
+ [ 2.68254575e+00, 1.32738011e+00, 1.30185274e-01, -3.38533089e-01,
+ -3.68219236e-01, -1.91689947e-01, -1.54782377e-01, -2.34207178e-01 ],
+
+ [ 4.82697924e+00, 3.11947804e+00, 1.39513671e+00, 2.50295316e-01,
+ -3.93613839e-01, -6.43458173e-01, -6.42570737e-01, -7.23193223e-01 ],
+
+ [ 8.78419936e-02, -5.69586840e-01, -1.14506016e+00, -1.66968488e+00,
+ -1.84534418e+00, -1.56468027e+00, -1.11746759e+00, -5.33981663e-01 ],
+
+ [ 1.39102308e+00, 1.98146479e+00, 1.11265796e+00, -2.20107509e-01,
+ -7.74965612e-01, -5.94063874e-01, 1.36937681e-01, 8.18242891e-01 ],
+
+ [ 3.84585894e-01, -1.60588786e-01, -5.39366810e-01, -5.29309079e-01,
+ 1.90433547e-01, 2.56062918e+00, 2.81896398e+00, 6.56670876e-01 ],
+
+ [ 1.93227399e+00, 3.01030180e+00, 3.06543894e+00, 2.50110161e+00,
+ 1.93089593e+00, 5.72153811e-01, -8.11741794e-01, -1.17641811e+00 ],
+
+ [ 1.75080463e-01, -7.50522832e-01, -1.03943893e+00, -1.13577509e+00,
+ -1.04197904e+00, -1.52060099e-02, 2.07048392e+00, 3.42948918e+00 ],
+
+ [ -1.18817020e+00, 3.66792874e-01, 1.30957830e+00, 1.68330687e+00,
+ 1.25100924e+00, 9.42375752e-01, 8.26250483e-01, 4.39952741e-01 ],
+
+ [ 2.53322203e+00, 2.11274643e+00, 1.26288412e+00, 7.61513512e-01,
+ 5.22117938e-01, 1.18680070e-01, -4.52346828e-01, -7.00352426e-01 ],
+
+ [ 3.99889837e+00, 4.07901751e+00, 2.82285661e+00, 1.72607213e+00,
+ 6.47144377e-01, -3.31148521e-01, -8.84042571e-01, -1.12697341e+00 ],
+
+ [ 5.07902593e-01, 1.58838450e+00, 1.72899024e+00, 1.00692230e+00,
+ 3.77121232e-01, 4.76370767e-01, 1.08754740e+00, 1.08756266e+00 ],
+
+ [ 3.16856825e+00, 3.25853458e+00, 2.42230591e+00, 1.79446078e+00,
+ 1.52177911e+00, 1.17196707e+00, 4.89394597e-01, -6.22795716e-02 ],
+
+ [ 1.89414767e+00, 1.25108695e+00, 5.90451211e-01, 6.08358583e-01,
+ 8.78171010e-01, 1.11912511e+00, 1.01857662e+00, 6.20453891e-01 ],
+
+ [ 9.48880605e-01, 2.13239439e+00, 2.72345350e+00, 2.76986077e+00,
+ 2.54286973e+00, 2.02046264e+00, 8.30045859e-01, -2.75569174e-02 ],
+
+ [ -1.88026757e+00, -1.26431073e+00, 3.11424977e-01, 1.83670210e+00,
+ 2.25634192e+00, 2.04818998e+00, 2.19526837e+00, 2.02659614e+00 ],
+
+ [ 2.46375746e-01, 9.55621773e-01, 1.52046777e+00, 1.97647400e+00,
+ 1.94043867e+00, 2.23375847e+00, 1.98835978e+00, 1.27232673e+00 ],
+
+])
+
+SNS_HFCB = np.array([
+
+ [ 2.32028419e-01, -1.00890271e+00, -2.14223503e+00, -2.37533814e+00,
+ -2.23041933e+00, -2.17595881e+00, -2.29065914e+00, -2.53286398e+00 ],
+
+ [ -1.29503937e+00, -1.79929965e+00, -1.88703148e+00, -1.80991660e+00,
+ -1.76340038e+00, -1.83418428e+00, -1.80480981e+00, -1.73679545e+00 ],
+
+ [ 1.39285716e-01, -2.58185126e-01, -6.50804573e-01, -1.06815732e+00,
+ -1.61928742e+00, -2.18762566e+00, -2.63757587e+00, -2.97897750e+00 ],
+
+ [ -3.16513102e-01, -4.77747657e-01, -5.51162076e-01, -4.84788283e-01,
+ -2.38388394e-01, -1.43024507e-01, 6.83186674e-02, 8.83061717e-02 ],
+
+ [ 8.79518405e-01, 2.98340096e-01, -9.15386396e-01, -2.20645975e+00,
+ -2.74142181e+00, -2.86139074e+00, -2.88841597e+00, -2.95182608e+00 ],
+
+ [ -2.96701922e-01, -9.75004919e-01, -1.35857500e+00, -9.83721106e-01,
+ -6.52956939e-01, -9.89986993e-01, -1.61467225e+00, -2.40712302e+00 ],
+
+ [ 3.40981100e-01, 2.68899789e-01, 5.63335685e-02, 4.99114047e-02,
+ -9.54130727e-02, -7.60166146e-01, -2.32758120e+00, -3.77155485e+00 ],
+
+ [ -1.41229759e+00, -1.48522119e+00, -1.18603580e+00, -6.25001634e-01,
+ 1.53902497e-01, 5.76386498e-01, 7.95092604e-01, 5.96564632e-01 ],
+
+ [ -2.28839512e-01, -3.33719070e-01, -8.09321359e-01, -1.63587877e+00,
+ -1.88486397e+00, -1.64496691e+00, -1.40515778e+00, -1.46666471e+00 ],
+
+ [ -1.07148629e+00, -1.41767015e+00, -1.54891762e+00, -1.45296062e+00,
+ -1.03182970e+00, -6.90642640e-01, -4.28843805e-01, -4.94960215e-01 ],
+
+ [ -5.90988511e-01, -7.11737759e-02, 3.45719523e-01, 3.00549461e-01,
+ -1.11865218e+00, -2.44089151e+00, -2.22854732e+00, -1.89509228e+00 ],
+
+ [ -8.48434099e-01, -5.83226811e-01, 9.00423688e-02, 8.45025008e-01,
+ 1.06572385e+00, 7.37582999e-01, 2.56590452e-01, -4.91963360e-01 ],
+
+ [ 1.14069146e+00, 9.64016892e-01, 3.81461206e-01, -4.82849341e-01,
+ -1.81632721e+00, -2.80279513e+00, -3.23385725e+00, -3.45908714e+00 ],
+
+ [ -3.76283238e-01, 4.25675462e-02, 5.16547697e-01, 2.51716882e-01,
+ -2.16179968e-01, -5.34074091e-01, -6.40786096e-01, -8.69745032e-01 ],
+
+ [ 6.65004121e-01, 1.09790765e+00, 1.38342667e+00, 1.34327359e+00,
+ 8.22978837e-01, 2.15876799e-01, -4.04925753e-01, -1.07025606e+00 ],
+
+ [ -8.26265954e-01, -6.71181233e-01, -2.28495593e-01, 5.18980853e-01,
+ 1.36721896e+00, 2.18023038e+00, 2.53596093e+00, 2.20121099e+00 ],
+
+ [ 1.41008327e+00, 7.54441908e-01, -1.30550585e+00, -1.87133711e+00,
+ -1.24008685e+00, -1.26712925e+00, -2.03670813e+00, -2.89685162e+00 ],
+
+ [ 3.61386818e-01, -2.19991705e-02, -5.79368834e-01, -8.79427961e-01,
+ -8.50685023e-01, -7.79397050e-01, -7.32182927e-01, -8.88348515e-01 ],
+
+ [ 4.37469239e-01, 3.05440420e-01, -7.38786566e-03, -4.95649855e-01,
+ -8.06651271e-01, -1.22431892e+00, -1.70157770e+00, -2.24491914e+00 ],
+
+ [ 6.48100319e-01, 6.82299134e-01, 2.53247464e-01, 7.35842144e-02,
+ 3.14216709e-01, 2.34729881e-01, 1.44600134e-01, -6.82120179e-02 ],
+
+ [ 1.11919833e+00, 1.23465533e+00, 5.89170238e-01, -1.37192460e+00,
+ -2.37095707e+00, -2.00779783e+00, -1.66688540e+00, -1.92631846e+00 ],
+
+ [ 1.41847497e-01, -1.10660071e-01, -2.82824593e-01, -6.59813475e-03,
+ 2.85929280e-01, 4.60445530e-02, -6.02596416e-01, -2.26568729e+00 ],
+
+ [ 5.04046955e-01, 8.26982163e-01, 1.11981236e+00, 1.17914044e+00,
+ 1.07987429e+00, 6.97536239e-01, -9.12548817e-01, -3.57684747e+00 ],
+
+ [ -5.01076050e-01, -3.25678006e-01, 2.80798195e-02, 2.62054555e-01,
+ 3.60590806e-01, 6.35623722e-01, 9.59012467e-01, 1.30745157e+00 ],
+
+ [ 3.74970983e+00, 1.52342612e+00, -4.57715662e-01, -7.98711008e-01,
+ -3.86819329e-01, -3.75901062e-01, -6.57836900e-01, -1.28163964e+00 ],
+
+ [ -1.15258991e+00, -1.10800886e+00, -5.62615117e-01, -2.20562124e-01,
+ -3.49842880e-01, -7.53432770e-01, -9.88596593e-01, -1.28790472e+00 ],
+
+ [ 1.02827246e+00, 1.09770519e+00, 7.68645546e-01, 2.06081978e-01,
+ -3.42805735e-01, -7.54939405e-01, -1.04196178e+00, -1.50335653e+00 ],
+
+ [ 1.28831972e-01, 6.89439395e-01, 1.12346905e+00, 1.30934523e+00,
+ 1.35511965e+00, 1.42311381e+00, 1.15706449e+00, 4.06319438e-01 ],
+
+ [ 1.34033030e+00, 1.38996825e+00, 1.04467922e+00, 6.35822746e-01,
+ -2.74733756e-01, -1.54923372e+00, -2.44239710e+00, -3.02457607e+00 ],
+
+ [ 2.13843105e+00, 4.24711267e+00, 2.89734110e+00, 9.32730658e-01,
+ -2.92822250e-01, -8.10404297e-01, -7.88868099e-01, -9.35353149e-01 ],
+
+ [ 5.64830487e-01, 1.59184978e+00, 2.39771699e+00, 3.03697344e+00,
+ 2.66424350e+00, 1.39304485e+00, 4.03834024e-01, -6.56270971e-01 ],
+
+ [ -4.22460548e-01, 3.26149625e-01, 1.39171313e+00, 2.23146615e+00,
+ 2.61179442e+00, 2.66540340e+00, 2.40103554e+00, 1.75920380e+00 ],
+
+])
+
+SNS_VQ_REG_ADJ_GAINS = \
+ np.array([ 8915, 12054 ]) / 4096
+
+SNS_VQ_REG_LF_ADJ_GAINS = \
+ np.array([ 6245, 15043, 17861, 21014 ]) / 4096
+
+SNS_VQ_NEAR_ADJ_GAINS = \
+ np.array([ 7099, 9132, 11253, 14808 ]) / 4096
+
+SNS_VQ_FAR_ADJ_GAINS = \
+ np.array([ 4336, 5067, 5895, 8149, 10235, 12825, 16868, 19882 ]) / 4096
+
+SNS_MPVQ_OFFSETS = np.array([
+ [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
+ [ 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 ],
+ [ 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 ],
+ [ 0, 1, 31, 481, 4991, 39041, 246047,1303777,5984767,24331777,89129247 ],
+])
+
+### 3.7.5 ###
+
+TNS_ORDER_BITS = np.array([
+ [ 0, 17234, 13988, 11216, 8694, 6566, 4977, 3961, 3040 ],
+ [ 0, 12683, 9437, 6874, 5541, 5121, 5170, 5359, 5056 ]
+])
+
+TNS_ORDER_FREQ = np.array([
+ [ 3, 9, 23, 54, 111, 190, 268, 366 ],
+ [ 14, 42, 100, 157, 181, 178, 167, 185 ]
+])
+
+TNS_ORDER_CUMFREQ = np.array([
+ [ 0, 3, 12, 35, 89, 200, 390, 658 ],
+ [ 0, 14, 56, 156, 313, 494, 672, 839 ]
+])
+
+TNS_COEF_BITS = np.array([
+
+ [ 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 ]
+
+])
+
+TNS_COEF_FREQ = np.array([
+ [ 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 ]
+])
+
+TNS_COEF_CUMFREQ = np.array([
+
+ [ 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 ],
+
+])
+
+
+### 3.7.6 ###
+
+LTPF_H12K8 = np.array([
+ -2.04305583e-05, -4.46345894e-05, -7.16366399e-05, -1.00101113e-04,
+ -1.28372848e-04, -1.54543830e-04, -1.76544567e-04, -1.92256960e-04,
+ -1.99643819e-04, -1.96888686e-04, -1.82538332e-04, -1.55639427e-04,
+ -1.15860365e-04, -6.35893034e-05, 2.81006480e-19, 7.29218021e-05,
+ 1.52397076e-04, 2.34920777e-04, 3.16378650e-04, 3.92211738e-04,
+ 4.57623849e-04, 5.07824294e-04, 5.38295523e-04, 5.45072918e-04,
+ 5.25022155e-04, 4.76098424e-04, 3.97571380e-04, 2.90200217e-04,
+ 1.56344667e-04, -5.81880142e-19, -1.73252713e-04, -3.56385965e-04,
+ -5.41155231e-04, -7.18414023e-04, -8.78505232e-04, -1.01171451e-03,
+ -1.10876706e-03, -1.16134522e-03, -1.16260169e-03, -1.10764097e-03,
+ -9.93941563e-04, -8.21692190e-04, -5.94017766e-04, -3.17074654e-04,
+ 9.74695082e-19, 3.45293760e-04, 7.04480871e-04, 1.06133447e-03,
+ 1.39837473e-03, 1.69763080e-03, 1.94148675e-03, 2.11357591e-03,
+ 2.19968245e-03, 2.18860625e-03, 2.07294546e-03, 1.84975249e-03,
+ 1.52102188e-03, 1.09397426e-03, 5.81108062e-04, -1.42248266e-18,
+ -6.27153730e-04, -1.27425140e-03, -1.91223839e-03, -2.51026925e-03,
+ -3.03703830e-03, -3.46222687e-03, -3.75800672e-03, -3.90053247e-03,
+ -3.87135231e-03, -3.65866558e-03, -3.25835851e-03, -2.67475555e-03,
+ -1.92103305e-03, -1.01925433e-03, 1.86962369e-18, 1.09841545e-03,
+ 2.23113197e-03, 3.34830927e-03, 4.39702277e-03, 5.32342672e-03,
+ 6.07510531e-03, 6.60352025e-03, 6.86645399e-03, 6.83034270e-03,
+ 6.47239234e-03, 5.78237521e-03, 4.76401273e-03, 3.43586351e-03,
+ 1.83165284e-03, -2.25189837e-18, -1.99647619e-03, -4.08266886e-03,
+ -6.17308037e-03, -8.17444895e-03, -9.98882386e-03, -1.15169871e-02,
+ -1.26621006e-02, -1.33334458e-02, -1.34501120e-02, -1.29444881e-02,
+ -1.17654154e-02, -9.88086732e-03, -7.28003640e-03, -3.97473021e-03,
+ 2.50961778e-18, 4.58604422e-03, 9.70324900e-03, 1.52512477e-02,
+ 2.11120585e-02, 2.71533724e-02, 3.32324245e-02, 3.92003203e-02,
+ 4.49066644e-02, 5.02043309e-02, 5.49542017e-02, 5.90297032e-02,
+ 6.23209727e-02, 6.47385023e-02, 6.62161245e-02, 6.67132287e-02,
+ 6.62161245e-02, 6.47385023e-02, 6.23209727e-02, 5.90297032e-02,
+ 5.49542017e-02, 5.02043309e-02, 4.49066644e-02, 3.92003203e-02,
+ 3.32324245e-02, 2.71533724e-02, 2.11120585e-02, 1.52512477e-02,
+ 9.70324900e-03, 4.58604422e-03, 2.50961778e-18, -3.97473021e-03,
+ -7.28003640e-03, -9.88086732e-03, -1.17654154e-02, -1.29444881e-02,
+ -1.34501120e-02, -1.33334458e-02, -1.26621006e-02, -1.15169871e-02,
+ -9.98882386e-03, -8.17444895e-03, -6.17308037e-03, -4.08266886e-03,
+ -1.99647619e-03, -2.25189837e-18, 1.83165284e-03, 3.43586351e-03,
+ 4.76401273e-03, 5.78237521e-03, 6.47239234e-03, 6.83034270e-03,
+ 6.86645399e-03, 6.60352025e-03, 6.07510531e-03, 5.32342672e-03,
+ 4.39702277e-03, 3.34830927e-03, 2.23113197e-03, 1.09841545e-03,
+ 1.86962369e-18, -1.01925433e-03, -1.92103305e-03, -2.67475555e-03,
+ -3.25835851e-03, -3.65866558e-03, -3.87135231e-03, -3.90053247e-03,
+ -3.75800672e-03, -3.46222687e-03, -3.03703830e-03, -2.51026925e-03,
+ -1.91223839e-03, -1.27425140e-03, -6.27153730e-04, -1.42248266e-18,
+ 5.81108062e-04, 1.09397426e-03, 1.52102188e-03, 1.84975249e-03,
+ 2.07294546e-03, 2.18860625e-03, 2.19968245e-03, 2.11357591e-03,
+ 1.94148675e-03, 1.69763080e-03, 1.39837473e-03, 1.06133447e-03,
+ 7.04480871e-04, 3.45293760e-04, 9.74695082e-19, -3.17074654e-04,
+ -5.94017766e-04, -8.21692190e-04, -9.93941563e-04, -1.10764097e-03,
+ -1.16260169e-03, -1.16134522e-03, -1.10876706e-03, -1.01171451e-03,
+ -8.78505232e-04, -7.18414023e-04, -5.41155231e-04, -3.56385965e-04,
+ -1.73252713e-04, -5.81880142e-19, 1.56344667e-04, 2.90200217e-04,
+ 3.97571380e-04, 4.76098424e-04, 5.25022155e-04, 5.45072918e-04,
+ 5.38295523e-04, 5.07824294e-04, 4.57623849e-04, 3.92211738e-04,
+ 3.16378650e-04, 2.34920777e-04, 1.52397076e-04, 7.29218021e-05,
+ 2.81006480e-19, -6.35893034e-05, -1.15860365e-04, -1.55639427e-04,
+ -1.82538332e-04, -1.96888686e-04, -1.99643819e-04, -1.92256960e-04,
+ -1.76544567e-04, -1.54543830e-04, -1.28372848e-04, -1.00101113e-04,
+ -7.16366399e-05, -4.46345894e-05, -2.04305583e-05
+])
+
+LTPF_H4 = np.array([
+ -2.87456116e-03, -3.00125103e-03, 2.74547165e-03, 1.53572770e-02,
+ 2.86823405e-02, 2.95038503e-02, 4.59833449e-03, -4.72963246e-02,
+ -1.05835916e-01, -1.30305021e-01, -7.54404636e-02, 8.35788573e-02,
+ 3.30182571e-01, 6.03297008e-01, 8.17488686e-01, 8.98638285e-01,
+ 8.17488686e-01, 6.03297008e-01, 3.30182571e-01, 8.35788573e-02,
+ -7.54404636e-02, -1.30305021e-01, -1.05835916e-01, -4.72963246e-02,
+ 4.59833449e-03, 2.95038503e-02, 2.86823405e-02, 1.53572770e-02,
+ 2.74547165e-03, -3.00125103e-03, -2.87456116e-03
+])
+
+LTPF_HI = np.array([
+ 6.69885837e-03, 3.96711478e-02, 1.06999186e-01, 2.09880463e-01,
+ 3.35690625e-01, 4.59220930e-01, 5.50075002e-01, 5.83527575e-01,
+ 5.50075002e-01, 4.59220930e-01, 3.35690625e-01, 2.09880463e-01,
+ 1.06999186e-01, 3.96711478e-02, 6.69885837e-03
+])
+
+LTPF_N_8K = np.array([
+ [ 6.02361821e-01, 4.19760926e-01, -1.88342453e-02 ],
+ [ 5.99476858e-01, 4.19760926e-01, -1.59492828e-02 ],
+ [ 5.96776466e-01, 4.19760926e-01, -1.32488910e-02 ],
+ [ 5.94241012e-01, 4.19760926e-01, -1.07134366e-02 ],
+])
+
+LTPF_N_16K = np.array([
+ [ 6.02361821e-01, 4.19760926e-01, -1.88342453e-02 ],
+ [ 5.99476858e-01, 4.19760926e-01, -1.59492828e-02 ],
+ [ 5.96776466e-01, 4.19760926e-01, -1.32488910e-02 ],
+ [ 5.94241012e-01, 4.19760926e-01, -1.07134366e-02 ],
+])
+
+LTPF_N_24K = np.array([
+
+ [ 3.98969559e-01, 5.14250861e-01, 1.00438297e-01, -1.27889396e-02,
+ -1.57228008e-03 ],
+
+ [ 3.94863491e-01, 5.12381921e-01, 1.04319493e-01, -1.09199996e-02,
+ -1.34740833e-03 ],
+
+ [ 3.90984448e-01, 5.10605352e-01, 1.07983252e-01, -9.14343107e-03,
+ -1.13212462e-03 ],
+
+ [ 3.87309389e-01, 5.08912208e-01, 1.11451738e-01, -7.45028713e-03,
+ -9.25551405e-04 ],
+
+])
+
+LTPF_N_32K = np.array([
+
+ [ 2.98237945e-01, 4.65280920e-01, 2.10599743e-01, 3.76678038e-02,
+ -1.01569616e-02, -2.53588100e-03, -3.18294617e-04 ],
+
+ [ 2.94383415e-01, 4.61929400e-01, 2.12946577e-01, 4.06617500e-02,
+ -8.69327230e-03, -2.17830711e-03, -2.74288806e-04 ],
+
+ [ 2.90743921e-01, 4.58746191e-01, 2.15145697e-01, 4.35010477e-02,
+ -7.29549535e-03, -1.83439564e-03, -2.31692019e-04 ],
+
+ [ 2.87297585e-01, 4.55714889e-01, 2.17212695e-01, 4.62008888e-02,
+ -5.95746380e-03, -1.50293428e-03, -1.90385191e-04 ],
+
+])
+
+LTPF_N_48K = np.array([
+
+ [ 1.98136374e-01, 3.52449490e-01, 2.51369527e-01, 1.42414624e-01,
+ 5.70473102e-02, 9.29336624e-03, -7.22602537e-03, -3.17267989e-03,
+ -1.12183596e-03, -2.90295724e-04, -4.27081559e-05 ],
+
+ [ 1.95070943e-01, 3.48466041e-01, 2.50998846e-01, 1.44116741e-01,
+ 5.92894732e-02, 1.10892383e-02, -6.19290811e-03, -2.72670551e-03,
+ -9.66712583e-04, -2.50810092e-04, -3.69993877e-05 ],
+
+ [ 1.92181006e-01, 3.44694556e-01, 2.50622009e-01, 1.45710245e-01,
+ 6.14113213e-02, 1.27994140e-02, -5.20372109e-03, -2.29732451e-03,
+ -8.16560813e-04, -2.12385575e-04, -3.14127133e-05 ],
+
+ [ 1.89448531e-01, 3.41113925e-01, 2.50240688e-01, 1.47206563e-01,
+ 6.34247723e-02, 1.44320343e-02, -4.25444914e-03, -1.88308147e-03,
+ -6.70961906e-04, -1.74936334e-04, -2.59386474e-05 ],
+
+])
+
+LTPF_D_8K = np.array([
+
+ [ 0.00000000e+00, 2.09880463e-01, 5.83527575e-01, 2.09880463e-01,
+ 0.00000000e+00 ],
+
+ [ 0.00000000e+00, 1.06999186e-01, 5.50075002e-01, 3.35690625e-01,
+ 6.69885837e-03 ],
+
+ [ 0.00000000e+00, 3.96711478e-02, 4.59220930e-01, 4.59220930e-01,
+ 3.96711478e-02 ],
+
+ [ 0.00000000e+00, 6.69885837e-03, 3.35690625e-01, 5.50075002e-01,
+ 1.06999186e-01 ],
+
+])
+
+LTPF_D_16K = np.array([
+
+ [ 0.00000000e+00, 2.09880463e-01, 5.83527575e-01, 2.09880463e-01,
+ 0.00000000e+00 ],
+
+ [ 0.00000000e+00, 1.06999186e-01, 5.50075002e-01, 3.35690625e-01,
+ 6.69885837e-03 ],
+
+ [ 0.00000000e+00, 3.96711478e-02, 4.59220930e-01, 4.59220930e-01,
+ 3.96711478e-02 ],
+
+ [ 0.00000000e+00, 6.69885837e-03, 3.35690625e-01, 5.50075002e-01,
+ 1.06999186e-01 ],
+
+])
+
+LTPF_D_24K = np.array([
+
+ [ 0.00000000e+00, 6.32223163e-02, 2.50730961e-01, 3.71390943e-01,
+ 2.50730961e-01, 6.32223163e-02, 0.00000000e+00 ],
+
+ [ 0.00000000e+00, 3.45927217e-02, 1.98651560e-01, 3.62641173e-01,
+ 2.98675055e-01, 1.01309287e-01, 4.26354371e-03 ],
+
+ [ 0.00000000e+00, 1.53574678e-02, 1.47434488e-01, 3.37425955e-01,
+ 3.37425955e-01, 1.47434488e-01, 1.53574678e-02 ],
+
+ [ 0.00000000e+00, 4.26354371e-03, 1.01309287e-01, 2.98675055e-01,
+ 3.62641173e-01, 1.98651560e-01, 3.45927217e-02 ],
+
+])
+
+LTPF_D_32K = np.array([
+
+ [ 0.00000000e+00, 2.90040188e-02, 1.12985742e-01, 2.21202403e-01,
+ 2.72390947e-01, 2.21202403e-01, 1.12985742e-01, 2.90040188e-02,
+ 0.00000000e+00 ],
+
+ [ 0.00000000e+00, 1.70315342e-02, 8.72250379e-02, 1.96140776e-01,
+ 2.68923798e-01, 2.42499910e-01, 1.40577336e-01, 4.47487717e-02,
+ 3.12703024e-03 ],
+
+ [ 0.00000000e+00, 8.56367375e-03, 6.42622294e-02, 1.68767671e-01,
+ 2.58744594e-01, 2.58744594e-01, 1.68767671e-01, 6.42622294e-02,
+ 8.56367375e-03 ],
+
+ [ 0.00000000e+00, 3.12703024e-03, 4.47487717e-02, 1.40577336e-01,
+ 2.42499910e-01, 2.68923798e-01, 1.96140776e-01, 8.72250379e-02,
+ 1.70315342e-02 ],
+
+])
+
+LTPF_D_48K = np.array([
+
+ [ 0.00000000e+00, 1.08235939e-02, 3.60896922e-02, 7.67640147e-02,
+ 1.24153058e-01, 1.62759644e-01, 1.77677142e-01, 1.62759644e-01,
+ 1.24153058e-01, 7.67640147e-02, 3.60896922e-02, 1.08235939e-02,
+ 0.00000000e+00 ],
+
+ [ 0.00000000e+00, 7.04140493e-03, 2.81970232e-02, 6.54704494e-02,
+ 1.12464799e-01, 1.54841896e-01, 1.76712238e-01, 1.69150721e-01,
+ 1.35290158e-01, 8.85142501e-02, 4.49935385e-02, 1.55761371e-02,
+ 2.03972196e-03 ],
+
+ [ 0.00000000e+00, 4.14699847e-03, 2.13575731e-02, 5.48273558e-02,
+ 1.00497144e-01, 1.45606034e-01, 1.73843984e-01, 1.73843984e-01,
+ 1.45606034e-01, 1.00497144e-01, 5.48273558e-02, 2.13575731e-02,
+ 4.14699847e-03 ],
+
+ [ 0.00000000e+00, 2.03972196e-03, 1.55761371e-02, 4.49935385e-02,
+ 8.85142501e-02, 1.35290158e-01, 1.69150721e-01, 1.76712238e-01,
+ 1.54841896e-01, 1.12464799e-01, 6.54704494e-02, 2.81970232e-02,
+ 7.04140493e-03 ],
+
+])
+
+### 3.7.7 ###
+
+AC_SPEC_LOOKUP = np.array([
+ 1, 39, 7, 25, 22, 22, 28, 22, 22, 22, 22, 28, 28, 28, 34, 31,
+ 31, 40, 43, 46, 49, 52, 14, 17, 36, 36, 36, 38, 0, 57, 38, 22,
+ 0, 8, 9, 11, 47, 14, 14, 17, 36, 36, 36, 38, 59, 59, 38, 22,
+ 22, 26, 46, 29, 30, 32, 33, 35, 36, 36, 36, 38, 0, 59, 23, 22,
+ 46, 46, 45, 47, 48, 50, 50, 18, 54, 54, 54, 38, 59, 59, 59, 22,
+ 0, 62, 63, 3, 33, 2, 2, 61, 20, 20, 20, 21, 59, 59, 39, 28,
+ 28, 63, 63, 3, 33, 2, 2, 61, 38, 38, 38, 21, 59, 59, 39, 28,
+ 28, 6, 6, 6, 2, 18, 61, 20, 21, 21, 21, 59, 39, 39, 7, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 51, 51, 51, 53, 54, 20, 38, 38, 57, 39, 39, 39, 7, 24, 34,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 56, 38, 57, 57, 59, 7, 7, 7, 42, 42, 34,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5, 4, 4, 5, 21, 21, 59, 7, 7, 7, 7, 25, 25, 25, 34,
+ 4, 4, 4, 4, 5, 23, 23, 39, 7, 7, 7, 42, 25, 25, 22, 31,
+ 31, 39, 39, 39, 39, 7, 7, 42, 0, 25, 22, 22, 22, 28, 34, 31,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
+ 55, 55, 40, 8, 9, 49, 49, 52, 17, 17, 17, 4, 0, 20, 17, 60,
+ 40, 40, 8, 43, 27, 49, 49, 14, 17, 17, 17, 36, 42, 42, 17, 57,
+ 57, 40, 8, 26, 27, 49, 12, 14, 17, 17, 17, 36, 0, 38, 36, 1,
+ 8, 8, 43, 9, 11, 49, 12, 14, 14, 33, 50, 50, 50, 61, 36, 39,
+ 8, 8, 43, 46, 49, 52, 30, 14, 14, 33, 50, 50, 50, 50, 18, 25,
+ 8, 8, 43, 46, 49, 52, 30, 14, 14, 18, 5, 5, 5, 61, 18, 23,
+ 43, 43, 43, 9, 49, 52, 3, 14, 14, 50, 50, 50, 50, 61, 17, 24,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 9, 11, 52, 52, 14, 14, 17, 61, 61, 61, 54, 17, 39,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 44, 27, 29, 52, 48, 52, 52, 17, 17, 17, 17, 2, 17, 7,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 9, 27, 27, 12, 52, 14, 14, 58, 41, 41, 41, 6, 17, 37,
+ 9, 9, 9, 27, 11, 49, 12, 52, 14, 14, 14, 50, 0, 53, 17, 28,
+ 52, 52, 49, 52, 12, 52, 30, 14, 14, 17, 2, 2, 2, 38, 38, 34,
+ 31, 34, 34, 31, 31, 31, 31, 19, 19, 19, 19, 19, 19, 19, 31, 19,
+ 44, 44, 62, 30, 32, 58, 35, 36, 36, 38, 0, 59, 7, 7, 39, 34,
+ 34, 45, 47, 48, 33, 35, 35, 36, 38, 38, 38, 59, 7, 7, 39, 34,
+ 34, 62, 30, 15, 50, 53, 53, 54, 21, 21, 21, 59, 7, 7, 7, 34,
+ 30, 30, 48, 33, 58, 18, 18, 56, 23, 23, 23, 59, 7, 7, 24, 34,
+ 34, 6, 6, 58, 53, 54, 54, 21, 59, 59, 59, 39, 7, 7, 42, 34,
+ 6, 6, 33, 58, 53, 54, 61, 21, 59, 59, 59, 39, 7, 7, 42, 34,
+ 34, 51, 51, 53, 54, 56, 56, 57, 39, 39, 39, 7, 42, 42, 25, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 4, 4, 4, 5, 23, 23, 39, 7, 7, 7, 42, 25, 25, 22, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 5, 5, 5, 5, 57, 57, 39, 24, 24, 24, 42, 22, 22, 28, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 41, 41, 41, 41, 39, 39, 7, 42, 42, 42, 25, 28, 28, 28, 31,
+ 31, 41, 41, 41, 41, 39, 39, 24, 25, 25, 25, 22, 28, 28, 34, 31,
+ 31, 10, 10, 10, 10, 10, 10, 28, 34, 34, 34, 34, 34, 34, 31, 19,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 9, 11, 47, 32, 50, 18, 18, 20, 21, 21, 21, 39, 59, 34,
+ 26, 26, 27, 29, 30, 33, 50, 18, 18, 20, 57, 57, 57, 59, 59, 34,
+ 27, 27, 11, 12, 48, 50, 58, 61, 61, 56, 57, 57, 57, 59, 39, 34,
+ 45, 45, 12, 30, 32, 2, 2, 61, 38, 38, 38, 57, 0, 59, 39, 34,
+ 63, 63, 3, 32, 58, 18, 18, 20, 21, 21, 21, 59, 39, 39, 7, 31,
+ 31, 3, 3, 33, 58, 18, 18, 20, 21, 21, 21, 59, 7, 7, 7, 31,
+ 6, 6, 51, 51, 53, 54, 54, 38, 57, 57, 57, 39, 7, 7, 42, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 51, 53, 53, 54, 56, 56, 57, 59, 59, 59, 7, 24, 24, 25, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 4, 4, 4, 54, 21, 21, 57, 39, 39, 39, 7, 42, 42, 22, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 5, 5, 5, 5, 23, 23, 59, 7, 7, 7, 42, 22, 22, 28, 31,
+ 31, 4, 4, 4, 5, 23, 23, 39, 24, 24, 24, 25, 28, 28, 34, 31,
+ 31, 10, 10, 10, 10, 10, 10, 28, 34, 34, 34, 31, 31, 31, 31, 19,
+ 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 60, 60, 60, 60, 60, 16,
+ 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 60,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 13, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0,
+ 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 60, 16,
+ 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 60, 16,
+ 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 16,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 16,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 16,
+ 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 60, 60, 60, 60, 60, 16,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 16, 16, 16, 16, 16, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 60, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 60, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 13, 0, 13, 13, 13, 13, 13, 13, 13, 60, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 60, 16,
+ 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 60, 60, 60, 60, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 13, 13, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 0, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 19, 13, 13, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 60, 13, 13, 13, 13, 13, 13, 60, 60, 60, 60, 60, 60, 60, 60, 16,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 60, 60, 60, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 60,
+ 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 60,
+ 13, 13, 13, 13, 13, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 13, 13, 13, 13, 0, 0,
+ 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 60,
+ 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+])
+
+AC_SPEC_BITS = np.array([
+
+ [ 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 ],
+
+ [ 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 ],
+
+ [ 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 ],
+
+ [ 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 ]
+])
+
+AC_SPEC_CUMFREQ = np.array([
+
+ [ 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 ],
+
+ [ 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 ],
+
+ [ 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 ]
+
+])
+
+AC_SPEC_FREQ = np.array([
+
+ [ 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 ],
+
+ [ 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 ],
+
+ [ 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 ]
+
+])
diff --git a/test/tns.py b/test/tns.py
new file mode 100644
index 0000000..d537590
--- /dev/null
+++ b/test/tns.py
@@ -0,0 +1,440 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+import numpy as np
+
+import lc3
+import tables as T, appendix_c as C
+
+### ------------------------------------------------------------------------ ###
+
+class Tns:
+
+ SUB_LIM_10M_NB = [ [ 12, 34, 57, 80 ] ]
+ SUB_LIM_10M_WB = [ [ 12, 61, 110, 160 ] ]
+ SUB_LIM_10M_SSWB = [ [ 12, 88, 164, 240 ] ]
+ SUB_LIM_10M_SWB = [ [ 12, 61, 110, 160 ], [ 160, 213, 266, 320 ] ]
+ SUB_LIM_10M_FB = [ [ 12, 74, 137, 200 ], [ 200, 266, 333, 400 ] ]
+
+ SUB_LIM_10M = [ SUB_LIM_10M_NB, SUB_LIM_10M_WB,
+ SUB_LIM_10M_SSWB, SUB_LIM_10M_SWB, SUB_LIM_10M_FB ]
+
+ SUB_LIM_7M5_NB = [ [ 9, 26, 43, 60 ] ]
+ SUB_LIM_7M5_WB = [ [ 9, 46, 83, 120 ] ]
+ SUB_LIM_7M5_SSWB = [ [ 9, 66, 123, 180 ] ]
+ SUB_LIM_7M5_SWB = [ [ 9, 46, 82, 120 ], [ 120, 159, 200, 240 ] ]
+ SUB_LIM_7M5_FB = [ [ 9, 56, 103, 150 ], [ 150, 200, 250, 300 ] ]
+
+ SUB_LIM_7M5 = [ SUB_LIM_7M5_NB, SUB_LIM_7M5_WB,
+ SUB_LIM_7M5_SSWB, SUB_LIM_7M5_SWB, SUB_LIM_7M5_FB ]
+
+ SUB_LIM = [ SUB_LIM_7M5, SUB_LIM_10M ]
+
+ FREQ_LIM_10M_NB = [ 12, 80 ]
+ FREQ_LIM_10M_WB = [ 12, 160 ]
+ FREQ_LIM_10M_SSWB = [ 12, 240 ]
+ FREQ_LIM_10M_SWB = [ 12, 160, 320 ]
+ FREQ_LIM_10M_FB = [ 12, 200, 400 ]
+
+ FREQ_LIM_10M = [ FREQ_LIM_10M_NB, FREQ_LIM_10M_WB,
+ FREQ_LIM_10M_SSWB, FREQ_LIM_10M_SWB, FREQ_LIM_10M_FB ]
+
+ FREQ_LIM_7M5_NB = [ 9, 60 ]
+ FREQ_LIM_7M5_WB = [ 9, 120 ]
+ FREQ_LIM_7M5_SSWB = [ 9, 180 ]
+ FREQ_LIM_7M5_SWB = [ 9, 120, 240 ]
+ FREQ_LIM_7M5_FB = [ 9, 150, 300 ]
+
+ FREQ_LIM_7M5 = [ FREQ_LIM_7M5_NB, FREQ_LIM_7M5_WB,
+ FREQ_LIM_7M5_SSWB, FREQ_LIM_7M5_SWB, FREQ_LIM_7M5_FB ]
+
+ FREQ_LIM = [ FREQ_LIM_7M5, FREQ_LIM_10M ]
+
+ def __init__(self, dt):
+
+ self.dt = dt
+
+ (self.nfilters, self.lpc_weighting, self.rc_order, self.rc) = \
+ (0, False, np.array([ 0, 0 ]), np.array([ 0, 0 ]))
+
+ def get_data(self):
+
+ return { 'nfilters' : self.nfilters,
+ 'lpc_weighting' : self.lpc_weighting,
+ 'rc_order' : self.rc_order, 'rc' : self.rc - 8 }
+
+ def get_nbits(self):
+
+ lpc_weighting = self.lpc_weighting
+ nbits = 0
+
+ for f in range(self.nfilters):
+ rc_order = self.rc_order[f]
+ rc = self.rc[f]
+
+ nbits_order = T.TNS_ORDER_BITS[int(lpc_weighting)][rc_order]
+ nbits_coef = sum([ T.TNS_COEF_BITS[k][rc[k]]
+ for k in range(rc_order) ])
+
+ nbits += ((2048 + nbits_order + nbits_coef) + 2047) >> 11
+
+ return nbits
+
+
+class TnsAnalysis(Tns):
+
+ def __init__(self, dt):
+
+ super().__init__(dt)
+
+ def compute_lpc_coeffs(self, bw, f, x):
+
+ ### Normalized autocorrelation function
+
+ S = Tns.SUB_LIM[self.dt][bw][f]
+
+ r = np.append([ 3 ], np.zeros(8))
+ e = [ sum(x[S[s]:S[s+1]] ** 2) for s in range(3) ]
+
+ for k in range(len(r) if sum(e) > 0 else 0):
+ c = [ np.dot(x[S[s]:S[s+1]-k], x[S[s]+k:S[s+1]])
+ for s in range(3) ]
+
+ r[k] = np.sum( np.array(c) / np.array(e) )
+
+ r *= np.exp(-0.5 * (0.02 * np.pi * np.arange(9)) ** 2)
+
+ ### Levinson-Durbin recursion
+
+ err = r[0]
+ a = np.ones(len(r))
+
+ for k in range(1, len(a)):
+
+ rc = -sum(a[:k] * r[k:0:-1]) / err
+
+ a[1:k] += rc * a[k-1:0:-1]
+ a[k] = rc
+
+ err *= 1 - rc ** 2
+
+ return (r[0] / err, a)
+
+ def lpc_weight(self, pred_gain, a):
+
+ gamma = 1 - (1 - 0.85) * (2 - pred_gain) / (2 - 1.5)
+ return a * np.power(gamma, np.arange(len(a)))
+
+ def coeffs_reflexion(self, a):
+
+ rc = np.zeros(8)
+ b = a.copy()
+
+ for k in range(8, 0, -1):
+ rc[k-1] = b[k]
+ e = 1 - rc[k-1] ** 2
+ b[1:k] = (b[1:k] - rc[k-1] * b[k-1:0:-1]) / e
+
+ return rc
+
+ def quantization(self, rc, lpc_weighting):
+
+ delta = np.pi / 17
+ rc_i = np.rint(np.arcsin(rc) / delta).astype(int) + 8
+ rc_q = np.sin(delta * (rc_i - 8))
+
+ rc_order = len(rc_i) - np.argmin(rc_i[::-1] == 8)
+
+ return (rc_order, rc_q, rc_i)
+
+ def filtering(self, st, x, rc_order, rc):
+
+ y = np.empty(len(x))
+
+ for i in range(len(x)):
+
+ xi = x[i]
+ s1 = xi
+
+ for k in range(rc_order):
+ s0 = st[k]
+ st[k] = s1
+
+ s1 = rc[k] * xi + s0
+ xi += rc[k] * s0
+
+ y[i] = xi
+
+ return y
+
+ def run(self, x, bw, nn_flag, nbytes):
+
+ fstate = np.zeros(8)
+ y = x.copy()
+
+ self.nfilters = len(Tns.SUB_LIM[self.dt][bw])
+ self.lpc_weighting = nbytes * 8 < 48 * T.DT_MS[self.dt]
+ self.rc_order = np.zeros(2, dtype=np.intc)
+ self.rc = np.zeros((2, 8), dtype=np.intc)
+
+ for f in range(self.nfilters):
+
+ (pred_gain, a) = self.compute_lpc_coeffs(bw, f, x)
+
+ tns_off = pred_gain <= 1.5 or nn_flag
+ if tns_off:
+ continue
+
+ if self.lpc_weighting and pred_gain < 2:
+ a = self.lpc_weight(pred_gain, a)
+
+ rc = self.coeffs_reflexion(a)
+
+ (rc_order, rc_q, rc_i) = \
+ self.quantization(rc, self.lpc_weighting)
+
+ self.rc_order[f] = rc_order
+ self.rc[f] = rc_i
+
+ if rc_order > 0:
+ i0 = Tns.FREQ_LIM[self.dt][bw][f]
+ i1 = Tns.FREQ_LIM[self.dt][bw][f+1]
+
+ y[i0:i1] = self.filtering(
+ fstate, x[i0:i1], rc_order, rc_q)
+
+ return y
+
+ def store(self, b):
+
+ for f in range(self.nfilters):
+ lpc_weighting = self.lpc_weighting
+ rc_order = self.rc_order[f]
+ rc = self.rc[f]
+
+ b.write_bit(min(rc_order, 1))
+
+ if rc_order > 0:
+ b.ac_encode(
+ T.TNS_ORDER_CUMFREQ[int(lpc_weighting)][rc_order-1],
+ T.TNS_ORDER_FREQ[int(lpc_weighting)][rc_order-1] )
+
+ for k in range(rc_order):
+ b.ac_encode(T.TNS_COEF_CUMFREQ[k][rc[k]],
+ T.TNS_COEF_FREQ[k][rc[k]] )
+
+
+class TnsSynthesis(Tns):
+
+ def filtering(self, st, x, rc_order, rc):
+
+ y = x.copy()
+
+ for i in range(len(x)):
+
+ xi = x[i] - rc[rc_order-1] * st[rc_order-1]
+ for k in range(rc_order-2, -1, -1):
+ xi -= rc[k] * st[k]
+ st[k+1] = xi * rc[k] + st[k];
+ st[0] = xi;
+
+ y[i] = xi
+
+ return y
+
+ def load(self, b, bw, nbytes):
+
+ self.nfilters = len(Tns.SUB_LIM[self.dt][bw])
+ self.lpc_weighting = nbytes * 8 < 48 * T.DT_MS[self.dt]
+ self.rc_order = np.zeros(2, dtype=np.intc)
+ self.rc = 8 * np.ones((2, 8), dtype=np.intc)
+
+ for f in range(self.nfilters):
+
+ if not b.read_bit():
+ continue
+
+ rc_order = 1 + b.ac_decode(
+ T.TNS_ORDER_CUMFREQ[int(self.lpc_weighting)],
+ T.TNS_ORDER_FREQ[int(self.lpc_weighting)])
+
+ self.rc_order[f] = rc_order
+
+ for k in range(rc_order):
+ rc = b.ac_decode(T.TNS_COEF_CUMFREQ[k], T.TNS_COEF_FREQ[k])
+ self.rc[f][k] = rc
+
+ def run(self, x, bw):
+
+ fstate = np.zeros(8)
+ y = x.copy()
+
+ for f in range(self.nfilters):
+
+ rc_order = self.rc_order[f]
+ rc = np.sin((np.pi / 17) * (self.rc[f] - 8))
+
+ if rc_order > 0:
+ i0 = Tns.FREQ_LIM[self.dt][bw][f]
+ i1 = Tns.FREQ_LIM[self.dt][bw][f+1]
+
+ y[i0:i1] = self.filtering(
+ fstate, x[i0:i1], rc_order, rc)
+
+ return y
+
+
+### ------------------------------------------------------------------------ ###
+
+def check_analysis(rng, dt, bw):
+
+ ok = True
+
+ analysis = TnsAnalysis(dt)
+ nbytes_lim = int((48 * T.DT_MS[dt]) // 8)
+
+ for i in range(10):
+ x = rng.random(T.NE[dt][bw]) * 1e2
+ x = pow(x, .5 + i/5)
+
+ for nn_flag in (True, False):
+ for nbytes in (nbytes_lim, nbytes_lim + 1):
+
+ y = analysis.run(x, bw, nn_flag, nbytes)
+ (y_c, data_c) = lc3.tns_analyze(dt, bw, nn_flag, nbytes, x)
+
+ ok = ok and data_c['nfilters'] == analysis.nfilters
+ ok = ok and data_c['lpc_weighting'] == analysis.lpc_weighting
+ for f in range(analysis.nfilters):
+ rc_order = analysis.rc_order[f]
+ rc_order_c = data_c['rc_order'][f]
+ rc_c = 8 + data_c['rc'][f]
+ ok = ok and rc_order_c == rc_order
+ ok = ok and not np.any((rc_c - analysis.rc[f])[:rc_order])
+
+ ok = ok and lc3.tns_get_nbits(data_c) == analysis.get_nbits()
+ ok = ok and np.amax(np.abs(y_c - y)) < 1e-2
+
+ return ok
+
+def check_synthesis(rng, dt, bw):
+
+ ok = True
+ synthesis = TnsSynthesis(dt)
+
+ for i in range(100):
+
+ x = rng.random(T.NE[dt][bw]) * 1e2
+
+ synthesis.nfilters = 1 + int(bw >= T.SRATE_32K)
+ synthesis.rc_order = rng.integers(0, 9, 2)
+ synthesis.rc = rng.integers(0, 17, 16).reshape(2, 8)
+
+ y = synthesis.run(x, bw)
+ y_c = lc3.tns_synthesize(dt, bw, synthesis.get_data(), x)
+
+ ok = ok and np.amax(np.abs(y_c - y) < 1e-6)
+
+ return ok
+
+def check_analysis_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ fs = Tns.FREQ_LIM[dt][sr][0]
+ fe = Tns.FREQ_LIM[dt][sr][1]
+ st = np.zeros(8)
+
+ for i in range(len(C.X_S[dt])):
+
+ (_, a) = lc3.tns_compute_lpc_coeffs(dt, sr, C.X_S[dt][i])
+ ok = ok and np.amax(np.abs(a[0] - C.TNS_LEV_A[dt][i])) < 1e-5
+
+ rc = lc3.tns_lpc_reflection(a[0])
+ ok = ok and np.amax(np.abs(rc - C.TNS_LEV_RC[dt][i])) < 1e-5
+
+ (rc_order, rc_i) = lc3.tns_quantize_rc(C.TNS_LEV_RC[dt][i])
+ ok = ok and rc_order == C.RC_ORDER[dt][i][0]
+ ok = ok and np.any((rc_i + 8) - C.RC_I_1[dt][i] == 0)
+
+ rc_q = lc3.tns_unquantize_rc(rc_i, rc_order)
+ ok = ok and np.amax(np.abs(rc_q - C.RC_Q_1[dt][i])) < 1e-6
+
+ (x, side) = lc3.tns_analyze(dt, sr, False, C.NBYTES[dt], C.X_S[dt][i])
+ ok = ok and side['nfilters'] == 1
+ ok = ok and side['rc_order'][0] == C.RC_ORDER[dt][i][0]
+ ok = ok and not np.any((side['rc'][0] + 8) - C.RC_I_1[dt][i])
+ ok = ok and lc3.tns_get_nbits(side) == C.NBITS_TNS[dt][i]
+ ok = ok and np.amax(np.abs(x - C.X_F[dt][i])) < 1e-3
+
+ return ok
+
+def check_synthesis_appendix_c(dt):
+
+ sr = T.SRATE_16K
+ ok = True
+
+ for i in range(len(C.X_HAT_Q[dt])):
+
+ side = {
+ 'nfilters' : 1,
+ 'lpc_weighting' : C.NBYTES[dt] * 8 < 48 * T.DT_MS[dt],
+ 'rc_order': C.RC_ORDER[dt][i],
+ 'rc': [ C.RC_I_1[dt][i] - 8, C.RC_I_2[dt][i] - 8 ]
+ }
+
+ g_int = C.GG_IND_ADJ[dt][i] + C.GG_OFF[dt][i]
+ x = C.X_HAT_Q[dt][i] * (10 ** (g_int / 28))
+
+ x = lc3.tns_synthesize(dt, sr, side, x)
+ ok = ok and np.amax(np.abs(x - C.X_HAT_TNS[dt][i])) < 1e-3
+
+ if dt != T.DT_10M:
+ return ok
+
+ sr = T.SRATE_48K
+
+ side = {
+ 'nfilters' : 2,
+ 'lpc_weighting' : False,
+ 'rc_order': C.RC_ORDER_48K_10M,
+ 'rc': [ C.RC_I_1_48K_10M - 8, C.RC_I_2_48K_10M - 8 ]
+ }
+
+ x = C.X_HAT_F_48K_10M
+ x = lc3.tns_synthesize(dt, sr, side, x)
+ ok = ok and np.amax(np.abs(x - C.X_HAT_TNS_48K_10M)) < 1e-3
+
+ return ok
+
+def check():
+
+ rng = np.random.default_rng(1234)
+ ok = True
+
+ for dt in range(T.NUM_DT):
+ for sr in range(T.NUM_SRATE):
+ ok = ok and check_analysis(rng, dt, sr)
+ ok = ok and check_synthesis(rng, dt, sr)
+
+ for dt in range(T.NUM_DT):
+ ok = ok and check_analysis_appendix_c(dt)
+ ok = ok and check_synthesis_appendix_c(dt)
+
+ return ok
+
+### ------------------------------------------------------------------------ ###
diff --git a/test/tns_py.c b/test/tns_py.c
new file mode 100644
index 0000000..cb96d02
--- /dev/null
+++ b/test/tns_py.c
@@ -0,0 +1,183 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <Python.h>
+#include <numpy/ndarrayobject.h>
+
+#include <tns.c>
+#include "ctypes.h"
+
+static PyObject *compute_lpc_coeffs_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj, *a_obj, *g_obj;
+ unsigned dt, bw;
+ float *x, *g, (*a)[9];
+
+ if (!PyArg_ParseTuple(args, "IIO", &dt, &bw, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("sr", (unsigned)bw < LC3_NUM_BANDWIDTH);
+
+ int ne = LC3_NE(dt, bw);
+
+ CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ g_obj = new_1d_ptr(NPY_FLOAT, 2, &g);
+ a_obj = new_2d_ptr(NPY_FLOAT, 2, 9, &a);
+
+ compute_lpc_coeffs(dt, bw, x, g, a);
+
+ return Py_BuildValue("NN", g_obj, a_obj);
+}
+
+static PyObject *lpc_reflection_py(PyObject *m, PyObject *args)
+{
+ PyObject *a_obj, *rc_obj;
+ float *a, *rc;
+
+ if (!PyArg_ParseTuple(args, "O", &a_obj))
+ return NULL;
+
+ CTYPES_CHECK("a", to_1d_ptr(a_obj, NPY_FLOAT, 9, &a));
+ rc_obj = new_1d_ptr(NPY_FLOAT, 8, &rc);
+
+ lpc_reflection(a, rc);
+
+ return Py_BuildValue("N", rc_obj);
+}
+
+static PyObject *quantize_rc_py(PyObject *m, PyObject *args)
+{
+ PyObject *rc_obj, *rc_q_obj;
+ float *rc;
+ int rc_order, *rc_q;
+
+ if (!PyArg_ParseTuple(args, "O", &rc_obj))
+ return NULL;
+
+ CTYPES_CHECK("rc", to_1d_ptr(rc_obj, NPY_FLOAT, 8, &rc));
+
+ rc_q_obj = new_1d_ptr(NPY_INT, 8, &rc_q);
+
+ quantize_rc(rc, &rc_order, rc_q);
+
+ return Py_BuildValue("iN", rc_order, rc_q_obj);
+}
+
+static PyObject *unquantize_rc_py(PyObject *m, PyObject *args)
+{
+ PyObject *rc_q_obj, *rc_obj;
+ int rc_order, *rc_q;
+ float *rc;
+
+ if (!PyArg_ParseTuple(args, "OI", &rc_q_obj, &rc_order))
+ return NULL;
+
+ CTYPES_CHECK("rc_q", to_1d_ptr(rc_q_obj, NPY_INT, 8, &rc_q));
+ CTYPES_CHECK("rc_order", (unsigned)rc_order <= 8);
+
+ rc_obj = new_1d_ptr(NPY_FLOAT, 8, &rc);
+
+ unquantize_rc(rc_q, rc_order, rc);
+
+ return Py_BuildValue("N", rc_obj);
+}
+
+static PyObject *analyze_py(PyObject *m, PyObject *args)
+{
+ PyObject *x_obj;
+ struct lc3_tns_data data = { 0 };
+ unsigned dt, bw;
+ int nn_flag;
+ unsigned nbytes;
+ float *x;
+
+ if (!PyArg_ParseTuple(args, "IIpIO", &dt, &bw, &nn_flag, &nbytes, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("bw", (unsigned)bw < LC3_NUM_BANDWIDTH);
+
+ int ne = LC3_NE(dt, bw);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ lc3_tns_analyze(dt, bw, nn_flag, nbytes, &data, x);
+
+ return Py_BuildValue("ON", x_obj, new_tns_data(&data));
+}
+
+static PyObject *synthesize_py(PyObject *m, PyObject *args)
+{
+ PyObject *data_obj, *x_obj;
+ unsigned dt, bw;
+ struct lc3_tns_data data;
+ float *x;
+
+ if (!PyArg_ParseTuple(args, "IIOO", &dt, &bw, &data_obj, &x_obj))
+ return NULL;
+
+ CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
+ CTYPES_CHECK("bw", (unsigned)bw < LC3_NUM_BANDWIDTH);
+ CTYPES_CHECK(NULL, data_obj = to_tns_data(data_obj, &data));
+
+ int ne = LC3_NE(dt, bw);
+
+ CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
+
+ lc3_tns_synthesize(dt, bw, &data, x);
+
+ return Py_BuildValue("O", x_obj);
+}
+
+static PyObject *get_nbits_py(PyObject *m, PyObject *args)
+{
+ PyObject *data_obj;
+ struct lc3_tns_data data = { 0 };
+
+ if (!PyArg_ParseTuple(args, "O", &data_obj))
+ return NULL;
+
+ CTYPES_CHECK("data", to_tns_data(data_obj, &data));
+
+ int nbits = lc3_tns_get_nbits(&data);
+
+ return Py_BuildValue("i", nbits);
+}
+
+static PyMethodDef methods[] = {
+ { "tns_compute_lpc_coeffs", compute_lpc_coeffs_py, METH_VARARGS },
+ { "tns_lpc_reflection" , lpc_reflection_py , METH_VARARGS },
+ { "tns_quantize_rc" , quantize_rc_py , METH_VARARGS },
+ { "tns_unquantize_rc" , unquantize_rc_py , METH_VARARGS },
+ { "tns_analyze" , analyze_py , METH_VARARGS },
+ { "tns_synthesize" , synthesize_py , METH_VARARGS },
+ { "tns_get_nbits" , get_nbits_py , METH_VARARGS },
+ { NULL },
+};
+
+PyMODINIT_FUNC lc3_tns_py_init(PyObject *m)
+{
+ import_array();
+
+ PyModule_AddFunctions(m, methods);
+
+ return m;
+}
diff --git a/tools/dlc3.c b/tools/dlc3.c
new file mode 100644
index 0000000..109615b
--- /dev/null
+++ b/tools/dlc3.c
@@ -0,0 +1,257 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#define _POSIX_C_SOURCE 199309L
+
+#include <stdalign.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <errno.h>
+
+#include <lc3.h>
+#include "lc3bin.h"
+#include "wave.h"
+
+#ifndef MIN
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+#endif
+
+#ifndef MAX
+#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
+#endif
+
+
+/**
+ * Error handling
+ */
+
+static void error(int status, const char *format, ...)
+{
+ va_list args;
+
+ fflush(stdout);
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+
+ fprintf(stderr, status ? ": %s\n" : "\n", strerror(status));
+ exit(status);
+}
+
+
+/**
+ * Parameters
+ */
+
+struct parameters {
+ const char *fname_in;
+ const char *fname_out;
+ int bitdepth;
+ int srate_hz;
+};
+
+static struct parameters parse_args(int argc, char *argv[])
+{
+ static const char *usage =
+ "Usage: %s [in_file] [wav_file]\n"
+ "\n"
+ "wav_file\t" "Input wave file, stdin if omitted\n"
+ "out_file\t" "Output bitstream file, stdout if omitted\n"
+ "\n"
+ "Options:\n"
+ "\t-h\t" "Display help\n"
+ "\t-b\t" "Output bitdepth, 16 bits (default) or 24 bits\n"
+ "\t-r\t" "Output samplerate, default is LC3 stream samplerate\n"
+ "\n";
+
+ struct parameters p = { .bitdepth = 16 };
+
+ for (int iarg = 1; iarg < argc; ) {
+ const char *arg = argv[iarg++];
+
+ if (arg[0] == '-') {
+ if (arg[2] != '\0')
+ error(EINVAL, "Option %s", arg);
+
+ char opt = arg[1];
+ const char *optarg = NULL;
+
+ switch (opt) {
+ case 'b': case 'r':
+ if (iarg >= argc)
+ error(EINVAL, "Argument %s", arg);
+ optarg = argv[iarg++];
+ }
+
+ switch (opt) {
+ case 'h': fprintf(stderr, usage, argv[0]); exit(0);
+ case 'b': p.bitdepth = atoi(optarg); break;
+ case 'r': p.srate_hz = atoi(optarg); break;
+ default:
+ error(EINVAL, "Option %s", arg);
+ }
+
+ } else {
+
+ if (!p.fname_in)
+ p.fname_in = arg;
+ else if (!p.fname_out)
+ p.fname_out = arg;
+ else
+ error(EINVAL, "Argument %s", arg);
+ }
+ }
+
+ return p;
+}
+
+/**
+ * Return time in (us) from unspecified point in the past
+ */
+static unsigned clock_us(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ return (unsigned)(ts.tv_sec * 1000*1000) + (unsigned)(ts.tv_nsec / 1000);
+}
+
+/**
+ * Entry point
+ */
+int main(int argc, char *argv[])
+{
+ /* --- Read parameters --- */
+
+ struct parameters p = parse_args(argc, argv);
+ FILE *fp_in = stdin, *fp_out = stdout;
+
+ if (p.fname_in && (fp_in = fopen(p.fname_in, "rb")) == NULL)
+ error(errno, "%s", p.fname_in);
+
+ if (p.fname_out && (fp_out = fopen(p.fname_out, "wb")) == NULL)
+ error(errno, "%s", p.fname_out);
+
+ if (p.srate_hz && !LC3_CHECK_SR_HZ(p.srate_hz))
+ error(EINVAL, "Samplerate %d Hz", p.srate_hz);
+
+ if (p.bitdepth && p.bitdepth != 16 && p.bitdepth != 24)
+ error(EINVAL, "Bitdepth %d", p.bitdepth);
+
+ /* --- Check parameters --- */
+
+ int frame_us, srate_hz, nch, nsamples;
+
+ if (lc3bin_read_header(fp_in, &frame_us, &srate_hz, &nch, &nsamples) < 0)
+ error(EINVAL, "LC3 binary input file");
+
+ if (nch < 1 || nch > 2)
+ error(EINVAL, "Number of channels %d", nch);
+
+ if (!LC3_CHECK_DT_US(frame_us))
+ error(EINVAL, "Frame duration");
+
+ if (!LC3_CHECK_SR_HZ(srate_hz) || (p.srate_hz && p.srate_hz < srate_hz))
+ error(EINVAL, "Samplerate %d Hz", srate_hz);
+
+ int pcm_sbits = p.bitdepth;
+ int pcm_sbytes = pcm_sbits / 8;
+
+ int pcm_srate_hz = !p.srate_hz ? srate_hz : p.srate_hz;
+ int pcm_samples = !p.srate_hz ? nsamples :
+ ((int64_t)nsamples * pcm_srate_hz) / srate_hz;
+
+ wave_write_header(fp_out,
+ pcm_sbits, pcm_sbytes, pcm_srate_hz, nch, pcm_samples);
+
+ /* --- Setup decoding --- */
+
+ uint8_t in[2 * LC3_MAX_FRAME_BYTES];
+ int8_t alignas(int32_t) pcm[2 * LC3_MAX_FRAME_SAMPLES*4];
+ lc3_decoder_t dec[2];
+
+ int frame_samples = lc3_frame_samples(frame_us, pcm_srate_hz);
+ int encode_samples = pcm_samples +
+ lc3_delay_samples(frame_us, pcm_srate_hz);
+ enum lc3_pcm_format pcm_fmt =
+ pcm_sbits == 24 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16;
+
+ for (int ich = 0; ich < nch; ich++)
+ dec[ich] = lc3_setup_decoder(frame_us, srate_hz, p.srate_hz,
+ malloc(lc3_decoder_size(frame_us, pcm_srate_hz)));
+
+ /* --- Decoding loop --- */
+
+ static const char *dash_line = "========================================";
+
+ int nsec = 0;
+ unsigned t0 = clock_us();
+
+ for (int i = 0; i * frame_samples < encode_samples; i++) {
+
+ int frame_bytes = lc3bin_read_data(fp_in, nch, in);
+
+ if (floorf(i * frame_us * 1e-6) > nsec) {
+
+ float progress = fminf((float)i * frame_samples / pcm_samples, 1);
+
+ fprintf(stderr, "%02d:%02d [%-40s]\r",
+ nsec / 60, nsec % 60,
+ dash_line + (int)floorf((1 - progress) * 40));
+
+ nsec = rint(i * frame_us * 1e-6);
+ }
+
+ if (frame_bytes <= 0)
+ memset(pcm, 0, nch * frame_samples * pcm_sbytes);
+ else
+ for (int ich = 0; ich < nch; ich++)
+ lc3_decode(dec[ich],
+ in + ich * frame_bytes, frame_bytes,
+ pcm_fmt, pcm + ich * pcm_sbytes, nch);
+
+ int pcm_offset = i > 0 ? 0 : encode_samples - pcm_samples;
+ int pcm_nwrite = MIN(frame_samples - pcm_offset,
+ encode_samples - i*frame_samples);
+
+ wave_write_pcm(fp_out, pcm_sbytes, pcm, nch, pcm_offset, pcm_nwrite);
+ }
+
+ unsigned t = (clock_us() - t0) / 1000;
+ nsec = nsamples / srate_hz;
+
+ fprintf(stderr, "%02d:%02d Decoded in %d.%03d seconds %20s\n",
+ nsec / 60, nsec % 60, t / 1000, t % 1000, "");
+
+ /* --- Cleanup --- */
+
+ for (int ich = 0; ich < nch; ich++)
+ free(dec[ich]);
+
+ if (fp_in != stdin)
+ fclose(fp_in);
+
+ if (fp_out != stdout)
+ fclose(fp_out);
+}
diff --git a/tools/elc3.c b/tools/elc3.c
new file mode 100644
index 0000000..654fa7f
--- /dev/null
+++ b/tools/elc3.c
@@ -0,0 +1,260 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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.
+ *
+ ******************************************************************************/
+
+#define _POSIX_C_SOURCE 199309L
+
+#include <stdalign.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <errno.h>
+
+#include <lc3.h>
+#include "lc3bin.h"
+#include "wave.h"
+
+
+/**
+ * Error handling
+ */
+
+static void error(int status, const char *format, ...)
+{
+ va_list args;
+
+ fflush(stdout);
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+
+ fprintf(stderr, status ? ": %s\n" : "\n", strerror(status));
+ exit(status);
+}
+
+
+/**
+ * Parameters
+ */
+
+struct parameters {
+ const char *fname_in;
+ const char *fname_out;
+ float frame_ms;
+ int srate_hz;
+ int bitrate;
+};
+
+static struct parameters parse_args(int argc, char *argv[])
+{
+ static const char *usage =
+ "Usage: %s [options] [wav_file] [out_file]\n"
+ "\n"
+ "wav_file\t" "Input wave file, stdin if omitted\n"
+ "out_file\t" "Output bitstream file, stdout if omitted\n"
+ "\n"
+ "Options:\n"
+ "\t-h\t" "Display help\n"
+ "\t-b\t" "Bitrate in bps (mandatory)\n"
+ "\t-m\t" "Frame duration in ms (default 10)\n"
+ "\t-r\t" "Encoder samplerate (default is input samplerate)\n"
+ "\n";
+
+ struct parameters p = { .frame_ms = 10 };
+
+ for (int iarg = 1; iarg < argc; ) {
+ const char *arg = argv[iarg++];
+
+ if (arg[0] == '-') {
+ if (arg[2] != '\0')
+ error(EINVAL, "Option %s", arg);
+
+ char opt = arg[1];
+ const char *optarg = NULL;
+
+ switch (opt) {
+ case 'b': case 'm': case 'r':
+ if (iarg >= argc)
+ error(EINVAL, "Argument %s", arg);
+ optarg = argv[iarg++];
+ }
+
+ switch (opt) {
+ case 'h': fprintf(stderr, usage, argv[0]); exit(0);
+ case 'b': p.bitrate = atoi(optarg); break;
+ case 'm': p.frame_ms = atof(optarg); break;
+ case 'r': p.srate_hz = atoi(optarg); break;
+ default:
+ error(EINVAL, "Option %s", arg);
+ }
+
+ } else {
+
+ if (!p.fname_in)
+ p.fname_in = arg;
+ else if (!p.fname_out)
+ p.fname_out = arg;
+ else
+ error(EINVAL, "Argument %s", arg);
+ }
+ }
+
+ return p;
+}
+
+
+/**
+ * Return time in (us) from unspecified point in the past
+ */
+
+static unsigned clock_us(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return (unsigned)(ts.tv_sec * 1000*1000) + (unsigned)(ts.tv_nsec / 1000);
+}
+
+
+/**
+ * Entry point
+ */
+
+int main(int argc, char *argv[])
+{
+ /* --- Read parameters --- */
+
+ struct parameters p = parse_args(argc, argv);
+ FILE *fp_in = stdin, *fp_out = stdout;
+
+ if (p.fname_in && (fp_in = fopen(p.fname_in, "rb")) == NULL)
+ error(errno, "%s", p.fname_in);
+
+ if (p.fname_out && (fp_out = fopen(p.fname_out, "wb")) == NULL)
+ error(errno, "%s", p.fname_out);
+
+ if (p.srate_hz && !LC3_CHECK_SR_HZ(p.srate_hz))
+ error(EINVAL, "Samplerate %d Hz", p.srate_hz);
+
+ /* --- Check parameters --- */
+
+ int frame_us = p.frame_ms * 1000;
+ int srate_hz, nch, nsamples;
+ int pcm_sbits, pcm_sbytes;
+
+ if (wave_read_header(fp_in,
+ &pcm_sbits, &pcm_sbytes, &srate_hz, &nch, &nsamples) < 0)
+ error(EINVAL, "Bad or unsupported WAVE input file");
+
+ if (p.bitrate <= 0)
+ error(EINVAL, "Bitrate");
+
+ if (!LC3_CHECK_DT_US(frame_us))
+ error(EINVAL, "Frame duration");
+
+ if (!LC3_CHECK_SR_HZ(srate_hz) || (p.srate_hz && p.srate_hz > srate_hz))
+ error(EINVAL, "Samplerate %d Hz", srate_hz);
+
+ if (pcm_sbits != 16 && pcm_sbits != 24)
+ error(EINVAL, "Bitdepth %d", pcm_sbits);
+
+ if ((pcm_sbits == 16 && pcm_sbytes != 16/8) ||
+ (pcm_sbits == 24 && pcm_sbytes != 24/8 && pcm_sbytes != 32/8))
+ error(EINVAL, "Sample storage on %d bytes", pcm_sbytes);
+
+ if (nch < 1 || nch > 2)
+ error(EINVAL, "Number of channels %d", nch);
+
+ int enc_srate_hz = !p.srate_hz ? srate_hz : p.srate_hz;
+ int enc_samples = !p.srate_hz ? nsamples :
+ ((int64_t)nsamples * enc_srate_hz) / srate_hz;
+
+ lc3bin_write_header(fp_out,
+ frame_us, enc_srate_hz, p.bitrate, nch, enc_samples);
+
+ /* --- Setup encoding --- */
+
+ int8_t alignas(int32_t) pcm[2 * LC3_MAX_FRAME_SAMPLES*4];
+ uint8_t out[2 * LC3_MAX_FRAME_BYTES];
+ lc3_encoder_t enc[2];
+
+ int frame_bytes = lc3_frame_bytes(frame_us, p.bitrate / nch);
+ int frame_samples = lc3_frame_samples(frame_us, srate_hz);
+ int encode_samples = nsamples + lc3_delay_samples(frame_us, srate_hz);
+ enum lc3_pcm_format pcm_fmt =
+ pcm_sbytes == 32/8 ? LC3_PCM_FORMAT_S24 :
+ pcm_sbytes == 24/8 ? LC3_PCM_FORMAT_S24_3LE : LC3_PCM_FORMAT_S16;
+
+ for (int ich = 0; ich < nch; ich++)
+ enc[ich] = lc3_setup_encoder(frame_us, enc_srate_hz, srate_hz,
+ malloc(lc3_encoder_size(frame_us, srate_hz)));
+
+ /* --- Encoding loop --- */
+
+ static const char *dash_line = "========================================";
+
+ int nsec = 0;
+ unsigned t0 = clock_us();
+
+ for (int i = 0; i * frame_samples < encode_samples; i++) {
+
+ int nread = wave_read_pcm(fp_in, pcm_sbytes, nch, frame_samples, pcm);
+
+ memset(pcm + nread * nch * pcm_sbytes, 0,
+ nch * (frame_samples - nread) * pcm_sbytes);
+
+ if (floorf(i * frame_us * 1e-6) > nsec) {
+ float progress = fminf(
+ (float)i * frame_samples / encode_samples, 1);
+
+ fprintf(stderr, "%02d:%02d [%-40s]\r",
+ nsec / 60, nsec % 60,
+ dash_line + (int)floorf((1 - progress) * 40));
+
+ nsec = (int)(i * frame_us * 1e-6);
+ }
+
+ for (int ich = 0; ich < nch; ich++)
+ lc3_encode(enc[ich],
+ pcm_fmt, pcm + ich * pcm_sbytes, nch,
+ frame_bytes, out + ich * frame_bytes);
+
+ lc3bin_write_data(fp_out, out, nch, frame_bytes);
+ }
+
+ unsigned t = (clock_us() - t0) / 1000;
+ nsec = encode_samples / srate_hz;
+
+ fprintf(stderr, "%02d:%02d Encoded in %d.%d seconds %20s\n",
+ nsec / 60, nsec % 60, t / 1000, t % 1000, "");
+
+ /* --- Cleanup --- */
+
+ for (int ich = 0; ich < nch; ich++)
+ free(enc[ich]);
+
+ if (fp_in != stdin)
+ fclose(fp_in);
+
+ if (fp_out != stdout)
+ fclose(fp_out);
+}
diff --git a/tools/lc3bin.c b/tools/lc3bin.c
new file mode 100644
index 0000000..4187808
--- /dev/null
+++ b/tools/lc3bin.c
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <stdint.h>
+#include "lc3bin.h"
+
+
+/**
+ * LC3 binary header
+ */
+
+#define LC3_FILE_ID (0x1C | (0xCC << 8))
+
+struct lc3bin_header {
+ uint16_t file_id;
+ uint16_t header_size;
+ uint16_t srate_100hz;
+ uint16_t bitrate_100bps;
+ uint16_t channels;
+ uint16_t frame_10us;
+ uint16_t rfu;
+ uint16_t nsamples_low;
+ uint16_t nsamples_high;
+};
+
+
+/**
+ * Read LC3 binary header
+ */
+int lc3bin_read_header(FILE *fp,
+ int *frame_us, int *srate_hz, int *nchannels, int *nsamples)
+{
+ struct lc3bin_header hdr;
+
+ if (fread(&hdr, sizeof(hdr), 1, fp) != 1
+ || hdr.file_id != LC3_FILE_ID)
+ return -1;
+
+ *nchannels = hdr.channels;
+ *frame_us = hdr.frame_10us * 10;
+ *srate_hz = hdr.srate_100hz * 100;
+ *nsamples = hdr.nsamples_low | (hdr.nsamples_high << 16);
+
+ fseek(fp, SEEK_SET, hdr.header_size);
+
+ return 0;
+}
+
+/**
+ * Read LC3 block of data
+ */
+int lc3bin_read_data(FILE *fp, int nchannels, void *buffer)
+{
+ uint16_t nbytes;
+
+ if (fread(&nbytes, sizeof(nbytes), 1, fp) < 1
+ || nbytes > nchannels * LC3_MAX_FRAME_BYTES
+ || nbytes % nchannels
+ || fread(buffer, nbytes, 1, fp) < 1)
+ return -1;
+
+ return nbytes / nchannels;
+}
+
+/**
+ * Write LC3 binary header
+ */
+void lc3bin_write_header(FILE *fp,
+ int frame_us, int srate_hz, int bitrate, int nchannels, int nsamples)
+{
+ struct lc3bin_header hdr = {
+ .file_id = LC3_FILE_ID,
+ .header_size = sizeof(struct lc3bin_header),
+ .srate_100hz = srate_hz / 100,
+ .bitrate_100bps = bitrate / 100,
+ .channels = nchannels,
+ .frame_10us = frame_us / 10,
+ .nsamples_low = nsamples & 0xffff,
+ .nsamples_high = nsamples >> 16,
+ };
+
+ fwrite(&hdr, sizeof(hdr), 1, fp);
+}
+
+/**
+ * Write LC3 block of data
+ */
+void lc3bin_write_data(FILE *fp,
+ const void *data, int nchannels, int frame_bytes)
+{
+ uint16_t nbytes = nchannels * frame_bytes;
+ fwrite(&nbytes, sizeof(nbytes), 1, fp);
+
+ fwrite(data, 1, nbytes, fp);
+}
diff --git a/tools/lc3bin.h b/tools/lc3bin.h
new file mode 100644
index 0000000..b2d70e6
--- /dev/null
+++ b/tools/lc3bin.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 __LC3BIN_H
+#define __LC3BIN_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <lc3.h>
+
+
+/**
+ * Read LC3 binary header
+ * fp Opened file, moved after header on return
+ * frame_us Return frame duration, in us
+ * srate_hz Return samplerate, in Hz
+ * nchannels Return number of channels
+ * nsamples Return count of source samples by channels
+ * return 0: Ok -1: Bad LC3 File
+ */
+int lc3bin_read_header(FILE *fp,
+ int *frame_us, int *srate_hz, int *nchannels, int *nsamples);
+
+/**
+ * Read LC3 block of data
+ * fp Opened file
+ * nchannels Number of channels
+ * buffer Output buffer of `nchannels * LC3_MAX_FRAME_BYTES`
+ * return Size of each 'nchannels` frames, -1 on error
+ */
+int lc3bin_read_data(FILE *fp, int nchannels, void *buffer);
+
+/**
+ * Write LC3 binary header
+ * fp Opened file, moved after header on return
+ * frame_us Frame duration, in us
+ * srate_hz Samplerate, in Hz
+ * bitrate Bitrate indication of the stream, in bps
+ * nchannels Number of channels
+ * nsamples Count of source samples by channels
+ */
+void lc3bin_write_header(FILE *fp,
+ int frame_us, int srate_hz, int bitrate, int nchannels, int nsamples);
+
+/**
+ * Write LC3 block of data
+ * fp Opened file
+ * data The frames data
+ * nchannels Number of channels
+ * frame_bytes Size of each `nchannels` frames
+ */
+void lc3bin_write_data(FILE *fp,
+ const void *data, int nchannels, int frame_bytes);
+
+
+#endif /* __LC3BIN_H */
diff --git a/tools/makefile.mk b/tools/makefile.mk
new file mode 100644
index 0000000..cc19c29
--- /dev/null
+++ b/tools/makefile.mk
@@ -0,0 +1,42 @@
+#
+# Copyright 2022 Google LLC
+#
+# 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.
+#
+
+elc3_src += \
+ $(TOOLS_DIR)/elc3.c \
+ $(TOOLS_DIR)/lc3bin.c \
+ $(TOOLS_DIR)/wave.c
+
+elc3_lib += liblc3
+elc3_ldlibs += m
+elc3_ldflags += -flto
+
+$(eval $(call add-bin,elc3))
+
+
+dlc3_src += \
+ $(TOOLS_DIR)/dlc3.c \
+ $(TOOLS_DIR)/lc3bin.c \
+ $(TOOLS_DIR)/wave.c
+
+dlc3_lib += liblc3
+dlc3_ldlibs += m
+elc3_ldflags += -flto
+
+$(eval $(call add-bin,dlc3))
+
+
+.PHONY: tools
+tools: elc3 dlc3
diff --git a/tools/meson.build b/tools/meson.build
new file mode 100644
index 0000000..8d0cf49
--- /dev/null
+++ b/tools/meson.build
@@ -0,0 +1,32 @@
+# Copyright © 2022 Intel Corporation
+#
+# 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.
+
+inc = include_directories('../include')
+
+lc3toolslib = static_library('lc3toolslib',
+ ['lc3bin.c', 'wave.c'],
+ link_with: lc3lib,
+ include_directories: inc,
+ dependencies: m_dep,
+)
+
+executable('elc3', ['elc3.c'],
+ link_with : lc3toolslib,
+ include_directories: inc,
+ install: true)
+
+executable('dlc3', ['dlc3.c'],
+ link_with : lc3toolslib,
+ include_directories: inc,
+ install: true)
diff --git a/tools/wave.c b/tools/wave.c
new file mode 100644
index 0000000..bdff777
--- /dev/null
+++ b/tools/wave.c
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 <stdint.h>
+#include "wave.h"
+
+
+/**
+ * Id formatting
+ */
+
+#define __WAVE_ID(s) \
+ (uint32_t)( s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) )
+
+
+/**
+ * File format statement
+ * | type_id WAVE_FILE_TYPE_ID
+ * | size File size - 8 bytes
+ * | type_id WAVE_FILE_FMT_ID
+ */
+
+#define WAVE_FILE_TYPE_ID __WAVE_ID("RIFF")
+#define WAVE_FILE_FMT_ID __WAVE_ID("WAVE")
+
+struct wave_file {
+ uint32_t type_id;
+ uint32_t size;
+ uint32_t fmt_id;
+};
+
+
+/**
+ * Audio format statement
+ * | id WAVE_FORMAT_ID
+ * | size Size of the block - 8 bytes (= 16 bytes)
+ * | format WAVE_FORMAT_PCM
+ * | channels Number of channels
+ * | samplerate Sampling rate
+ * | byterate Bytes per secondes = `samplerate * framesize`
+ * | framesize Bytes per sampling time = `channels * bitdepth / 8`
+ * | bitdepth Number of bits per sample
+ */
+
+#define WAVE_FORMAT_ID __WAVE_ID("fmt ")
+#define WAVE_FORMAT_PCM 1
+
+struct wave_format {
+ uint32_t id;
+ uint32_t size;
+ uint16_t fmt;
+ uint16_t channels;
+ uint32_t samplerate;
+ uint32_t byterate;
+ uint16_t framesize;
+ uint16_t bitdepth;
+};
+
+
+/**
+ * Audio data statement
+ * | id WAV_DATA_ID
+ * | size Size of the data following
+ */
+
+#define WAVE_DATA_ID __WAVE_ID("data")
+
+struct wave_data {
+ uint32_t id;
+ uint32_t size;
+};
+
+
+/**
+ * Read WAVE file header
+ */
+int wave_read_header(FILE *fp, int *bitdepth, int *samplesize,
+ int *samplerate, int *nchannels, int *nframes)
+{
+ struct wave_file file;
+ struct wave_format format;
+ struct wave_data data;
+
+ if (fread(&file, sizeof(file), 1, fp) != 1
+ || file.type_id != WAVE_FILE_TYPE_ID
+ || file.fmt_id != WAVE_FILE_FMT_ID)
+ return -1;
+
+ if (fread(&format, sizeof(format), 1, fp) != 1
+ || format.id != WAVE_FORMAT_ID
+ || format.fmt != WAVE_FORMAT_PCM
+ || format.channels <= 0
+ || format.samplerate <= 0
+ || format.framesize <= 0
+ || format.byterate != format.samplerate * format.framesize)
+ return -1;
+
+ fseek(fp, sizeof(format) - (8 + format.size), SEEK_CUR);
+
+ if (fread(&data, sizeof(data), 1, fp) != 1
+ || data.id != WAVE_DATA_ID)
+ return -1;
+
+ *bitdepth = format.bitdepth;
+ *samplesize = format.framesize / format.channels;
+ *samplerate = format.samplerate;
+ *nchannels = format.channels;
+ *nframes = data.size / format.framesize;
+
+ return 0;
+}
+
+/**
+ * Read PCM samples from wave file
+ */
+int wave_read_pcm(FILE *fp, int samplesize,
+ int nch, int count, void *buffer)
+{
+ return fread(buffer, nch * samplesize, count, fp);
+}
+
+/**
+ * Write WAVE file header
+ */
+void wave_write_header(FILE *fp, int bitdepth, int samplesize,
+ int samplerate, int nchannels, int nframes)
+{
+ struct {
+ struct wave_file file;
+ struct wave_format format;
+ struct wave_data data;
+ } header;
+
+ long data_size = nchannels * nframes * samplesize;
+ long file_size = sizeof(header) + data_size;
+
+ header.file = (struct wave_file){
+ WAVE_FILE_TYPE_ID, file_size - 8,
+ .fmt_id = WAVE_FILE_FMT_ID
+ };
+
+ header.format = (struct wave_format){
+ WAVE_FORMAT_ID, sizeof(header.format) - 8,
+ .fmt = WAVE_FORMAT_PCM,
+ .channels = nchannels,
+ .samplerate = samplerate,
+ .byterate = samplerate * nchannels * samplesize,
+ .framesize = nchannels * samplesize,
+ .bitdepth = bitdepth,
+ };
+
+ header.data = (struct wave_data){
+ WAVE_DATA_ID, data_size
+ };
+
+ fwrite(&header, sizeof(header), 1, fp);
+}
+
+/**
+ * Write PCM samples to wave file
+ */
+void wave_write_pcm(FILE *fp, int samplesize,
+ const void *_pcm, int nch, int off, int count)
+{
+ const int8_t *pcm = _pcm;
+ fwrite(pcm + nch * off * samplesize, nch * samplesize, count, fp);
+}
diff --git a/tools/wave.h b/tools/wave.h
new file mode 100644
index 0000000..87e8186
--- /dev/null
+++ b/tools/wave.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * Copyright 2022 Google LLC
+ *
+ * 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 __WAVE_H
+#define __WAVE_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+
+/**
+ * Read WAVE file header
+ * fp Opened file, moved after header on return
+ * bitdepth Return bitdepth
+ * samplesize Return size of samples, in bytes
+ * samplerate Return samplerate, in Hz
+ * nchannels Return number of channels
+ * nframes Return count of frames
+ * return 0: Ok -1: Bad or unsupported WAVE File
+ */
+int wave_read_header(FILE *fp, int *bitdepth, int *samplesize,
+ int *samplerate, int *nchannels, int *nframes);
+
+/**
+ * Read PCM samples from wave file
+ * fp Opened file
+ * samplesize Size of samples, in bytes
+ * nch, count Number of channels and count of frames to read
+ * buffer Output buffer of `nchannels * count` interleaved samples
+ * return Number of frames read
+ */
+int wave_read_pcm(FILE *fp, int samplesize,
+ int nch, int count, void *_buffer);
+
+/**
+ * Write WAVE file header
+ * fp Opened file, moved after header on return
+ * bitdepth Bitdepth
+ * samplesize Size of samples
+ * samplerate Samplerate, in Hz
+ * nchannels Number of channels
+ * nframes Count of frames
+ */
+void wave_write_header(FILE *fp, int bitdepth, int samplesize,
+ int samplerate, int nchannels, int nframes);
+
+/**
+ * Write PCM samples to wave file
+ * fp Opened file
+ * samplesize Size of samples, in bytes
+ * pcm, nch PCM frames, as 'nch' interleaved samples
+ * off, count Offset and count of frames
+ */
+void wave_write_pcm(FILE *fp, int samplesize,
+ const void *pcm, int nch, int off, int count);
+
+
+#endif /* __WAVE_H */
diff --git a/zephyr/module.yml b/zephyr/module.yml
new file mode 100644
index 0000000..7874832
--- /dev/null
+++ b/zephyr/module.yml
@@ -0,0 +1,4 @@
+name: liblc3
+build:
+ cmake-ext: True
+ kconfig-ext: True