diff options
author | David Duarte <licorne@google.com> | 2023-08-16 00:52:36 +0000 |
---|---|---|
committer | David Duarte <licorne@google.com> | 2023-08-16 00:52:36 +0000 |
commit | 7609a5f5aef68e68f75a0c15f9a2e2b0a08112d3 (patch) | |
tree | cd4bc279cbc1c86d8d6da136be5ae737bcae50c9 | |
parent | d1c37a2582a7a09d3f69280dbcbc04f1861eaef7 (diff) | |
parent | 1a5938ebaca4f13fe79ce074f5dee079783aa29f (diff) | |
download | liblc3-7609a5f5aef68e68f75a0c15f9a2e2b0a08112d3.tar.gz |
Merge tag 'v1.0.4' into HEAD
Change-Id: I098b3d42976e254209e5fae2aef85f0201a442df
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | CONTRIBUTING.md | 28 | ||||
-rw-r--r-- | LICENSE | 202 | ||||
-rw-r--r-- | Makefile | 148 | ||||
-rw-r--r-- | README.md | 132 | ||||
-rw-r--r-- | fuzz/dfuzz.cc | 64 | ||||
-rw-r--r-- | fuzz/efuzz.cc | 117 | ||||
-rw-r--r-- | fuzz/makefile.mk | 52 | ||||
-rw-r--r-- | include/lc3.h | 313 | ||||
-rw-r--r-- | include/lc3_cpp.h | 283 | ||||
-rw-r--r-- | include/lc3_private.h | 163 | ||||
-rw-r--r-- | meson.build | 34 | ||||
-rw-r--r-- | meson_options.txt | 18 | ||||
-rw-r--r-- | src/attdet.c | 92 | ||||
-rw-r--r-- | src/attdet.h | 44 | ||||
-rw-r--r-- | src/bits.c | 375 | ||||
-rw-r--r-- | src/bits.h | 315 | ||||
-rw-r--r-- | src/bwdet.c | 129 | ||||
-rw-r--r-- | src/bwdet.h | 69 | ||||
-rw-r--r-- | src/common.h | 151 | ||||
-rw-r--r-- | src/energy.c | 70 | ||||
-rw-r--r-- | src/energy.h | 43 | ||||
-rw-r--r-- | src/fastmath.h | 158 | ||||
-rw-r--r-- | src/lc3.c | 704 | ||||
-rw-r--r-- | src/ltpf.c | 905 | ||||
-rw-r--r-- | src/ltpf.h | 111 | ||||
-rw-r--r-- | src/ltpf_arm.h | 506 | ||||
-rw-r--r-- | src/ltpf_neon.h | 281 | ||||
-rw-r--r-- | src/makefile.mk | 35 | ||||
-rw-r--r-- | src/mdct.c | 469 | ||||
-rw-r--r-- | src/mdct.h | 57 | ||||
-rw-r--r-- | src/mdct_neon.h | 296 | ||||
-rw-r--r-- | src/meson.build | 61 | ||||
-rw-r--r-- | src/plc.c | 61 | ||||
-rw-r--r-- | src/plc.h | 57 | ||||
-rw-r--r-- | src/sns.c | 880 | ||||
-rw-r--r-- | src/sns.h | 103 | ||||
-rw-r--r-- | src/spec.c | 907 | ||||
-rw-r--r-- | src/spec.h | 119 | ||||
-rw-r--r-- | src/tables.c | 3457 | ||||
-rw-r--r-- | src/tables.h | 94 | ||||
-rw-r--r-- | src/tns.c | 457 | ||||
-rw-r--r-- | src/tns.h | 99 | ||||
-rwxr-xr-x | tables/fastmath.py | 122 | ||||
-rwxr-xr-x | tables/mktables.py | 231 | ||||
-rw-r--r-- | test/appendix_c.py | 4083 | ||||
-rw-r--r-- | test/arm/ltpf_arm.c | 114 | ||||
-rw-r--r-- | test/arm/makefile.mk | 31 | ||||
-rw-r--r-- | test/arm/simd32.h | 70 | ||||
-rw-r--r-- | test/arm/test_arm.c | 32 | ||||
-rw-r--r-- | test/attdet.py | 185 | ||||
-rw-r--r-- | test/attdet_py.c | 62 | ||||
-rw-r--r-- | test/bitstream.py | 240 | ||||
-rw-r--r-- | test/bwdet.py | 162 | ||||
-rw-r--r-- | test/bwdet_py.c | 55 | ||||
-rw-r--r-- | test/ctypes.h | 893 | ||||
-rwxr-xr-x | test/decoder.py | 197 | ||||
-rwxr-xr-x | test/encoder.py | 212 | ||||
-rw-r--r-- | test/energy.py | 92 | ||||
-rw-r--r-- | test/energy_py.c | 62 | ||||
-rw-r--r-- | test/lc3_py.c | 142 | ||||
-rw-r--r-- | test/ltpf.py | 660 | ||||
-rw-r--r-- | test/ltpf_py.c | 138 | ||||
-rw-r--r-- | test/makefile.mk | 30 | ||||
-rw-r--r-- | test/mdct.py | 198 | ||||
-rw-r--r-- | test/mdct_py.c | 93 | ||||
-rw-r--r-- | test/module_py.c | 53 | ||||
-rw-r--r-- | test/neon/ltpf_neon.c | 116 | ||||
-rw-r--r-- | test/neon/makefile.mk | 32 | ||||
-rw-r--r-- | test/neon/mdct_neon.c | 74 | ||||
-rw-r--r-- | test/neon/neon.h | 329 | ||||
-rw-r--r-- | test/neon/test_neon.c | 37 | ||||
-rwxr-xr-x | test/run.py | 40 | ||||
-rwxr-xr-x | test/setup.py | 49 | ||||
-rw-r--r-- | test/sns.py | 594 | ||||
-rw-r--r-- | test/sns_py.c | 215 | ||||
-rw-r--r-- | test/spec.py | 818 | ||||
-rw-r--r-- | test/spec_py.c | 210 | ||||
-rw-r--r-- | test/tables.py | 2709 | ||||
-rw-r--r-- | test/tns.py | 440 | ||||
-rw-r--r-- | test/tns_py.c | 183 | ||||
-rw-r--r-- | tools/dlc3.c | 257 | ||||
-rw-r--r-- | tools/elc3.c | 260 | ||||
-rw-r--r-- | tools/lc3bin.c | 110 | ||||
-rw-r--r-- | tools/lc3bin.h | 71 | ||||
-rw-r--r-- | tools/makefile.mk | 42 | ||||
-rw-r--r-- | tools/meson.build | 32 | ||||
-rw-r--r-- | tools/wave.c | 182 | ||||
-rw-r--r-- | tools/wave.h | 73 | ||||
-rw-r--r-- | zephyr/module.yml | 4 |
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/). @@ -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](<pf->hp50, x, x_12k8, n_12k8); + + x_12k8 -= (dt == LC3_DT_7M5 ? 44 : 24); + + /* --- Resampling to 6.4 KHz --- */ + + int z_6k4 = sizeof(ltpf->x_6k4) / sizeof(*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, <pf->active)); + + CTYPES_CHECK("ltpf.pitch", to_scalar( + PyDict_GetItemString(obj, "pitch"), NPY_INT, <pf->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"), <pf->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, <pf->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, <pf->active)); + + PyDict_SetItemString(obj, "pitch", + new_scalar(NPY_INT, <pf->pitch)); + + PyDict_SetItemString(obj, "nc", + new_1d_copy(NPY_FLOAT, 2, <pf->nc)); + + PyDict_SetItemString(obj, "hp50", + from_ltpf_hp50_state(PyDict_New(), <pf->hp50)); + + PyDict_SetItemString(obj, "x_12k8", + new_1d_copy(NPY_INT16, n_12k8, <pf->x_12k8)); + + PyDict_SetItemString(obj, "x_6k4", + new_1d_copy(NPY_INT16, n_6k4, <pf->x_6k4)); + + PyDict_SetItemString(obj, "tc", + new_scalar(NPY_INT, <pf->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, <pf->active)); + + CTYPES_CHECK("ltpf.pitch", to_scalar( + PyDict_GetItemString(obj, "pitch"), NPY_INT, <pf->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, <pf->active)); + + PyDict_SetItemString(obj, "pitch", + new_scalar(NPY_INT, <pf->pitch)); + + PyDict_SetItemString(obj, "c", + new_1d_copy(NPY_FLOAT, 2*12, <pf->c)); + + PyDict_SetItemString(obj, "x", + new_1d_copy(NPY_FLOAT, 12, <pf->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, <pf_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, <pf)); + + 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, <pf, x + nt, &data); + + from_ltpf_analysis(ltpf_obj, <pf); + 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, <pf_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, <pf)); + + 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, + <pf, pitch_present ? &data : NULL, x, x + nd); + + from_ltpf_synthesis(ltpf_obj, <pf); + 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 |