├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── include └── sbc.h ├── makefile.mk ├── src ├── arm-v7em │ └── sbc.s ├── bits.c ├── bits.h └── sbc.c └── tools ├── dsbc.c ├── esbc.c ├── makefile.mk ├── wave.c └── wave.h /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.gitignore 3 | bin 4 | build 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code Reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google/conduct/). 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at: 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | V ?= @ 18 | 19 | BUILD_DIR := build 20 | BIN_DIR := bin 21 | 22 | 23 | # 24 | # Set `gcc` as default compiler 25 | # 26 | 27 | CC := $(if $(CC)=cc,gcc,$(CC)) 28 | AS := $(if $(AS)=as,$(CC),$(AS)) 29 | LD := $(if $(LD)=ld,$(CC),$(LD)) 30 | 31 | CFLAGS += $(if $(DEBUG),-O0 -g,-O3) 32 | CFLAGS += -std=c11 -Wall -Wextra 33 | 34 | 35 | # 36 | # Declarations 37 | # 38 | 39 | lib_list := 40 | bin_list := 41 | 42 | define add-lib 43 | $(eval $(1)_bin ?= $(1).a) 44 | $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin))) 45 | 46 | lib_list += $(1) 47 | LIB += $($(1)_bin) 48 | endef 49 | 50 | define add-bin 51 | $(eval $(1)_bin ?= $(1)) 52 | $(eval $(1)_bin := $(addprefix $(BIN_DIR)/,$($(1)_bin))) 53 | 54 | $($(1)_bin): LDLIBS += $(if $(filter $(LIBC),bionic),\ 55 | $(filter-out rt pthread,$($(1)_ldlibs)),$($(1)_ldlibs)) 56 | $($(1)_bin): LDFLAGS += $($(1)_ldflags) 57 | 58 | bin_list += $(1) 59 | BIN += $($(1)_bin) 60 | endef 61 | 62 | define set-target 63 | $(eval $(1)_obj ?= $(patsubst %.c,%.o,$(filter %.c,$($(1)_src))) \ 64 | $(patsubst %.s,%.o,$(filter %.s,$($(1)_src)))) 65 | $(eval $(1)_obj := $(addprefix $(BUILD_DIR)/,$($(1)_obj))) 66 | $(eval $(1)_lib := $(foreach lib, $($(1)_lib), $($(lib)_bin))) 67 | 68 | $($(1)_obj): INCLUDE += $($(1)_include) 69 | $($(1)_obj): DEFINE += $($(1)_define) 70 | $($(1)_obj): CFLAGS += $($(1)_cflags) 71 | 72 | -include $($(1)_obj:.o=.d) 73 | 74 | $($(1)_bin): $($(1)_lib) 75 | $($(1)_bin): $($(1)_obj) 76 | $($(1)_bin): $($(1)_dependencies) 77 | 78 | .PHONY: $(1) 79 | $(1): $($(1)_bin) 80 | endef 81 | 82 | .PHONY: default 83 | default: 84 | 85 | include makefile.mk 86 | 87 | 88 | # 89 | # Rules 90 | # 91 | 92 | MAKEFILE_DEPS := $(MAKEFILE_LIST) 93 | 94 | $(foreach lib, $(lib_list), $(eval $(call set-target,$(lib)))) 95 | $(foreach bin, $(bin_list), $(eval $(call set-target,$(bin)))) 96 | 97 | $(BUILD_DIR)/%.o: %.c $(MAKEFILE_DEPS) 98 | @echo " CC $(notdir $<)" 99 | $(V)mkdir -p $(dir $@) 100 | $(V)$(CC) $< -c $(CFLAGS) \ 101 | $(addprefix -I,$(INCLUDE)) \ 102 | $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@ 103 | 104 | $(BUILD_DIR)/%.o: %.s $(MAKEFILE_DEPS) 105 | @echo " AS $(notdir $<)" 106 | $(V)mkdir -p $(dir $@) 107 | $(V)$(AS) $< -c $(CFLAGS) \ 108 | $(addprefix -I,$(INCLUDE)) \ 109 | $(addprefix -D,$(DEFINE)) -MMD -MF $(@:.o=.d) -o $@ 110 | 111 | $(LIB): $(MAKEFILE_DEPS) 112 | @echo " AR $(notdir $@)" 113 | $(V)mkdir -p $(dir $@) 114 | $(V)$(AR) rcs $@ $(filter %.o,$^) 115 | 116 | $(BIN): $(MAKEFILE_DEPS) 117 | @echo " LD $(notdir $@)" 118 | $(V)mkdir -p $(dir $@) 119 | $(V)$(LD) $(filter %.o,$^) $(filter %.a,$^) $(LDFLAGS) \ 120 | $(addprefix -l,$(LDLIBS)) -o $@ 121 | 122 | clean: 123 | $(V)rm -rf $(BUILD_DIR) 124 | $(V)rm -rf $(BIN_DIR) 125 | 126 | clean-all: clean 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Subband Codec (SBC) 2 | 3 | The SBC codec is the mandotory codec for Bluetooth audio over A2DP Profile 4 | 5 | The technical specification of the codec is covered in Appendix B of [_Advanced Audio Distribution_](https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457083) 6 | 7 | mSBC extension is covered by Appendix A of [_Hands-Free Profile_](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=489628) 8 | 9 | ## Overview 10 | 11 | The directory layout is as follows : 12 | - include: Library interface 13 | - src: Source files 14 | - tools: Standalone encoder/decoder tools 15 | - build: Building outputs 16 | - bin: Compilation output 17 | 18 | ## How to build 19 | 20 | The default toolchain used is GCC. Invoke `make` to build the library. 21 | 22 | ```sh 23 | $ make -j 24 | ``` 25 | 26 | Compiled library `libsbc.a` will be found in `bin` directory. 27 | 28 | #### Cross compilation 29 | 30 | The cc, as, ld and ar can be selected with respective Makefile variables `CC`, 31 | `AS`, `LD` and `AR`. The `AS` and `LD` selections are optionnal, and fallback 32 | to `CC` selection when not defined. 33 | 34 | ```sh 35 | $ make -j CC=path_to_toolchain/bin/toolchain-prefix-gcc CFLAGS="..." 36 | ``` 37 | 38 | Compiled library will be found in `bin` directory. 39 | 40 | #### Enabling assembly 41 | 42 | Assembly code is available for armv7-em architecture. Enabling assembly code 43 | is done with the `ARCH` Makefile variable. Following example enable assembly 44 | optimization for target CPU ARM Cortex M4 : 45 | 46 | ```sh 47 | $ make -j CC=path_to_arm_toolchain/bin/toolchain-prefix-gcc \ 48 | CFLAGS="-mcpu=cortex-m4 -mthumb" ARCH="arm-v7em" 49 | ``` 50 | ## Tools 51 | 52 | Tools can be all compiled, while involking `make` as follows : 53 | 54 | ```sh 55 | $ make tools 56 | ``` 57 | 58 | The standalone encoder `esbc` take a `wave` file as input and encode it 59 | according given parameter. The standalone decoder `dsbc` do the inverse 60 | operation. 61 | 62 | Refer to `esbc -h` or `dsbc -h` for options. 63 | 64 | Note that `esbc` output bitstream to standard output when output file is 65 | omitted. On the other side `dsbc` read from standard input when input output 66 | file are omitted. 67 | In such way you can easly test encoding / decoding loop with : 68 | 69 | ```sh 70 | $ ./esbc -b | ./dsbc > 71 | ``` 72 | 73 | Adding Linux `aplay` tools, you are able to instant hear the result : 74 | 75 | ```sh 76 | $ ./esbc -b | ./dsbc | aplay 77 | ``` 78 | -------------------------------------------------------------------------------- /include/sbc.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | /** 20 | * Subband Codec (SBC) 21 | * 22 | * This implementation conforms to : 23 | * Advanced Audio Distribution v1.3.2 - Appendix B 24 | * Hands-Free Profile v1.8 - Appendix A 25 | * Bluetooth Profile Specification 26 | * 27 | * --- 28 | * 29 | * Antoine SOULIER, Tempow / Google LLC 30 | * 31 | */ 32 | 33 | #ifndef __SBC_H 34 | #define __SBC_H 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | 45 | /** 46 | * Normative SBC Constants / Limits 47 | */ 48 | 49 | #define SBC_HEADER_SIZE ( 4) 50 | #define SBC_PROBE_SIZE SBC_HEADER_SIZE 51 | 52 | #define SBC_MAX_SUBBANDS ( 8) 53 | #define SBC_MAX_BLOCKS (16) 54 | #define SBC_MAX_SAMPLES (SBC_MAX_BLOCKS * SBC_MAX_SUBBANDS) 55 | 56 | #define SBC_MSBC_SAMPLES (120) 57 | #define SBC_MSBC_SIZE ( 57) 58 | 59 | 60 | /** 61 | * SBC Frame description, include : 62 | * - The sampling frequency 63 | * - The channel mode 64 | * - The number of blocks, subbands encoded 65 | * - The bit allocation method and bitpool selected 66 | */ 67 | 68 | enum sbc_freq 69 | { 70 | SBC_FREQ_16K, 71 | SBC_FREQ_32K, 72 | SBC_FREQ_44K1, 73 | SBC_FREQ_48K, 74 | 75 | SBC_NUM_FREQ 76 | }; 77 | 78 | enum sbc_mode 79 | { 80 | SBC_MODE_MONO, 81 | SBC_MODE_DUAL_CHANNEL, 82 | SBC_MODE_STEREO, 83 | SBC_MODE_JOINT_STEREO, 84 | 85 | SBC_NUM_MODE 86 | }; 87 | 88 | enum sbc_bam 89 | { 90 | SBC_BAM_LOUDNESS, 91 | SBC_BAM_SNR, 92 | 93 | SBC_NUM_BAM 94 | }; 95 | 96 | struct sbc_frame 97 | { 98 | bool msbc; 99 | enum sbc_freq freq; 100 | enum sbc_mode mode; 101 | enum sbc_bam bam; 102 | int nblocks, nsubbands; 103 | int bitpool; 104 | }; 105 | 106 | 107 | /** 108 | * Algorithmic codec delay (Encoding + Decoding) 109 | * From number of subbands or frame configuration 110 | */ 111 | 112 | #define SBC_DELAY_SUBBANDS(nsubbands) \ 113 | (10 * (nsubbands)) 114 | 115 | #define SBC_DELAY(frame) \ 116 | SBC_DELAY_SUBBANDS((frame)->nsubbands) 117 | 118 | 119 | /** 120 | * Private context 121 | */ 122 | 123 | struct sbc_dstate 124 | { 125 | int idx; 126 | int16_t alignas(sizeof(int)) v[2][SBC_MAX_SUBBANDS][10]; 127 | }; 128 | 129 | struct sbc_estate 130 | { 131 | int idx; 132 | int16_t alignas(sizeof(int)) x[2][SBC_MAX_SUBBANDS][5]; 133 | int32_t y[4]; 134 | }; 135 | 136 | typedef struct sbc 137 | { 138 | int nchannels; 139 | int nblocks, nsubbands; 140 | 141 | union { 142 | struct sbc_dstate dstates[2]; 143 | struct sbc_estate estates[2]; 144 | }; 145 | 146 | } sbc_t; 147 | 148 | 149 | /** 150 | * Return the sampling frequency in Hz 151 | * freq The frequency enum value 152 | * return The Hz frequency value 153 | */ 154 | int sbc_get_freq_hz(enum sbc_freq freq); 155 | 156 | /** 157 | * Return the frame size from a frame description 158 | * frame The frame description 159 | * return The size of the frame, 0 on error 160 | */ 161 | unsigned sbc_get_frame_size(const struct sbc_frame *frame); 162 | 163 | /** 164 | * Return the bitrate from a frame description 165 | * frame The frame description 166 | * return The bitrate in bps, 0 on error 167 | */ 168 | unsigned sbc_get_frame_bitrate(const struct sbc_frame *frame); 169 | 170 | /** 171 | * Reset of the context 172 | * sbc Context to reset 173 | */ 174 | void sbc_reset(sbc_t *sbc); 175 | 176 | /** 177 | * Probe the data and return frame description 178 | * data Data pointer with at least ̀`SBC_PROBE_SIZE` bytes 179 | * frame Frame description 180 | * return 0 on success, -1 otherwise 181 | */ 182 | int sbc_probe(const void *data, struct sbc_frame *frame); 183 | 184 | /** 185 | * Decode a frame 186 | * sbc Decoding context 187 | * data, size Frame data, and maximum readable size 188 | * frame Return of frame description 189 | * pcmx Output PCM buffer for channel L/R 190 | * pitchx Number of samples between two consecutives 191 | * return 0 on success, -1 otherwise 192 | * 193 | * `data` can be NULL to enable PLC emulation 194 | */ 195 | int sbc_decode(sbc_t *sbc, 196 | const void *data, unsigned size, struct sbc_frame *frame, 197 | int16_t *pcml, int pitchl, int16_t *pcmr, int pitchr); 198 | 199 | /** 200 | * Encode a frame 201 | * sbc Encoding context 202 | * pcmx Input PCM buffer for channel L/R 203 | * pitchx Number of samples between two consecutives 204 | * frame Frame description as encoding parameters 205 | * data, size Output frame data, and maximum writable size 206 | * return 0 on success, -1 otherwise 207 | */ 208 | int sbc_encode(sbc_t *sbc, 209 | const int16_t *pcml, int pitchl, const int16_t *pcmr, int pitchr, 210 | const struct sbc_frame *frame, void *data, unsigned size); 211 | 212 | 213 | #ifdef __cplusplus 214 | } 215 | #endif 216 | 217 | #endif /* !__SBC_H */ 218 | -------------------------------------------------------------------------------- /makefile.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at: 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | INCLUDE += include 18 | SRC_DIR := src 19 | 20 | libsbc_src += \ 21 | $(SRC_DIR)/bits.c \ 22 | $(SRC_DIR)/sbc.c 23 | 24 | ifneq ($(if $(ARCH),$(wildcard $(SRC_DIR)/$(ARCH))),) 25 | libsbc_define += SBC_ASM 26 | libsbc_src += $(SRC_DIR)/$(ARCH)/sbc.s 27 | endif 28 | 29 | $(eval $(call add-lib,libsbc)) 30 | 31 | default: libsbc 32 | 33 | -include tools/makefile.mk 34 | -------------------------------------------------------------------------------- /src/arm-v7em/sbc.s: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | .syntax unified 20 | .thumb 21 | 22 | 23 | /** 24 | * Synthesize samples of a 4 subbands block 25 | * state Previous transformed samples of the channel 26 | * in Sub-band input samples 27 | * scale Scale factor of samples 28 | * out Output adress of PCM samples 29 | * pitch Number of PCM samples between two consecutive 30 | */ 31 | 32 | .text 33 | 34 | .align 4 35 | 36 | cos_table_4: 37 | .short 5793, 5793, -8192, -8192, 3135, -7568 38 | 39 | win_table_4_0: 40 | .short 0, -126, -358, -848, -4443, -9644, 4443, -848, 358, -126 41 | .short 0, -126, -358, -848, -4443, -9644, 4443, -848 42 | .short 43 | .short -18, -128, -670, -201, -6389, -9235, 2544, -1055, 100, -90 44 | .short -18, -128, -670, -201, -6389, -9235, 2544, -1055 45 | .short 46 | .short -49, -61, -946, 944, -8082, -8082, 944, -946, -61, -49 47 | .short -49, -61, -946, 944, -8082, -8082, 944, -946 48 | .short 49 | .short -90, 100, -1055, 2544, -9235, -6389, -201, -670, -128, -18 50 | .short -90, 100, -1055, 2544, -9235, -6389, -201, -670 51 | 52 | win_table_4_1: 53 | .short -126, -358, -848, -4443, -9644, 4443, -848, 358, -126 54 | .short 0, -126, -358, -848, -4443, -9644, 4443, -848, 358 55 | .short 56 | .short -128, -670, -201, -6389, -9235, 2544, -1055, 100, -90 57 | .short -18, -128, -670, -201, -6389, -9235, 2544, -1055, 100 58 | .short 59 | .short -61, -946, 944, -8082, -8082, 944, -946, -61, -49 60 | .short -49, -61, -946, 944, -8082, -8082, 944, -946, -61 61 | .short 62 | .short 100, -1055, 2544, -9235, -6389, -201, -670, -128, -18 63 | .short -90, 100, -1055, 2544, -9235, -6389, -201, -670, -128 64 | 65 | .thumb_func 66 | .global sbc_synthesize_4 67 | 68 | sbc_synthesize_4: 69 | 70 | push { r3-r11, lr } /* Push registers */ 71 | 72 | /* DCT of subbands samples .............................................. */ 73 | 74 | ldm r1 , { r6-r7 } /* r6-7 = s[0-3] */ 75 | 76 | shasx r5 , r6 , r7 /* r5 = s12 : d03 */ 77 | shsax r6 , r6 , r7 /* r6 = d12 : s03 */ 78 | 79 | pkhtb r4 , r5 , r6 /* r4 = s12 : s03 */ 80 | pkhtb r5 , r6 , r5 /* r5 = d12 : d03 */ 81 | 82 | ldr r1 , [r0], #4 /* r1 = state->idx */ 83 | mov r11 , r0 /* r11 = &state->v[0] */ 84 | mov r12 , r0 /* r12 = &state->v[0] */ 85 | ands r10 , r1 , #1 /* r10 = state->idx & 1, Z = r10 EQ 0 */ 86 | ite ne /* If-Then-Else ... */ 87 | addne r11 , r11 , #160 /* ... r11 = &state->v[1] */ 88 | addeq r12 , r12 , #160 /* ... r12 = &state->v[1] */ 89 | 90 | cmp r1 , #0 /* Compare state->idx */ 91 | ite ne /* If-Then-Else ... */ 92 | rsbne r1 , r1 , #10 /* ... r1 = state->idx ? */ 93 | moveq r1 , #0 /* ... 10 - state->idx : 0 */ 94 | add r11 , r11 , r1 , LSL #1 /* r11 = &state->v[ odd][0][idx] */ 95 | add r12 , r12 , r1 , LSL #1 /* r12 = &state->v[!odd][0][idx] */ 96 | 97 | adr r14 , cos_table_4 /* r14 = &cos_table */ 98 | 99 | add r2 , r2 , #12 /* r2 = scale + 12 = shr */ 100 | mov r1 , #1 /* r1 = 1 */ 101 | sub r8 , r2 , #1 /* r8 = shr - 1 */ 102 | lsl r1 , r1 , r8 /* r1 = 1 << (shr - 1) */ 103 | 104 | ldm r14!, { r7-r9 } /* r7-r10 = cos( 2,2, -0,-0, 3,-1 ) */ 105 | 106 | smlsd r6 , r4 , r7 , r1 /* r6 += s03 cos(2) - s12 cos(2) */ 107 | asr r6 , r2 /* r6 = a0 */ 108 | rsb r3 , r6 , #0 /* r3 = -a0 */ 109 | 110 | ssat r6 , #16 , r6 /* r6 = sat( a0) */ 111 | strh r6 , [r11, #0] /* Store v0[0] */ 112 | 113 | ssat r6 , #16 , r3 /* r6 = sat(-a0) */ 114 | strh r6 , [r12, #0] /* Store v1[0] */ 115 | 116 | smlad r6 , r4 , r8 , r1 /* r6 += -s03 cos(0) + -s12 cos(0) */ 117 | asr r6 , r2 /* r6 = b1 */ 118 | ssat r6 , #16 , r6 /* r6 = sat(b1) */ 119 | strh r6 , [r12, #40] /* Store v1[2] */ 120 | 121 | smlad r6 , r5 , r9 , r1 /* r6 += d03 cos(3) + -d12 cos(1) */ 122 | asr r6 , r2 /* r6 = a1 */ 123 | rsb r3 , r6 , #0 /* r6 = -a1 */ 124 | 125 | ssat r6 , #16 , r6 /* r6 = sat(a1) */ 126 | strh r6 , [r11, #20] /* Store v0[1] */ 127 | 128 | ssat r6 , #16 , r3 /* r6 = sat(-a1) */ 129 | strh r6 , [r11, #60] /* Store v0[3] */ 130 | 131 | smlsdx r6 , r5 , r9 , r1 /* r6 += -d03 cos(3) - -d12 cos(3) */ 132 | asr r6 , r2 /* r6 = b0 */ 133 | ssat r6 , #16 , r6 /* r6 = sat(b0) */ 134 | strh r6 , [r12, #20] /* Store v1[1] */ 135 | strh r6 , [r12, #60] /* Store v1[3] */ 136 | 137 | /* Update state index ................................................... */ 138 | 139 | ldr r1 , [r0, #-4] /* r1 = state->idx */ 140 | cmp r1 , #9 /* Compare state->idx */ 141 | ite lt /* If-Then-Else ... */ 142 | addlt r2 , r1 , #1 /* ... r2 = state->idx < 9 ? */ 143 | movge r2 , #0 /* ... state->idx + 1 : 0 */ 144 | str r2 , [r0, #-4] /* state->idx = r2 */ 145 | 146 | /* Window and output samples ............................................ */ 147 | 148 | mov r12 , r0 /* r12 = &state->v[0] */ 149 | ands r11 , r1 , #1 /* r11 = state->idx & 1, Z = r11 EQ 0 */ 150 | itte ne /* If-Then-Then-Else ... */ 151 | addne r12 , r12 , #160 /* ... r12 = &state->v[1] */ 152 | adrne r14 , win_table_4_1 /* ... r14 = &win_table_0 */ 153 | adreq r14 , win_table_4_0 /* ... r14 = &win_table_1 */ 154 | 155 | sub r1 , r1 , r11 /* r1 = state->idx &~ 1 */ 156 | add r14 , r14 , r1 , LSL 1 /* r14 = &window + state->idx */ 157 | 158 | pop { r1 } /* r1 = out_ptr */ 159 | ldr r2 , [sp, #36] /* r2 = pitch */ 160 | 161 | mov r0 , #0x1000 /* r0 = 1 << 12 */ 162 | 163 | ldm r12!, { r4-r7 } /* r4-r7 = u[0][0-7] */ 164 | ldm r14!, { r8-r11 } /* r8-r11 = w[0][0-7] */ 165 | 166 | smlad r3 , r4 , r8 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 167 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 168 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 169 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 170 | 171 | ldm r12!, { r4-r7 } /* r4-r7 = u[0][8-9], u[1][0-5] */ 172 | ldr r8 , [r14], #20 /* r8 = w[0][8-9], r14 = &w[1] */ 173 | ldm r14!, { r9-r11 } /* r9-r11 = w[1][0-5] */ 174 | 175 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 176 | 177 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[0] */ 178 | strh r3 , [r1] /* *out = s[0] */ 179 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 180 | 181 | smlad r3 , r5 , r9 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 182 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 183 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 184 | 185 | ldm r12!, { r4-r7 } /* r4-r7 = u[1][6-9], u[2][0-3] */ 186 | ldrd r8 , r9 , [r14], #24 /* r10-r11 = w[1][6-9], r14 = &w[2] */ 187 | ldm r14!, { r10-r11 } /* r9-r11 = w[2][0-3] */ 188 | 189 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 190 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 191 | 192 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[1] */ 193 | strh r3 , [r1] /* *out = s[1] */ 194 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 195 | 196 | smlad r3 , r6 , r10 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 197 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 198 | 199 | ldm r12!, { r4-r7 } /* r4-r7 = u[2][4-9], u[3][0-1] */ 200 | ldm r14!, { r8-r9 } /* r8-r9 = w[2][4-7] */ 201 | ldr r10 , [r14], #20 /* r10 = w[2][8-9], r14 = &w[3] */ 202 | ldr r11 , [r14], #4 /* r11 = w[3][0-1] */ 203 | 204 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 205 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 206 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 207 | 208 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[2] */ 209 | strh r3 , [r1] /* *out = s[2] */ 210 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 211 | 212 | smlad r3 , r7 , r11 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 213 | 214 | ldm r12!, { r4-r7 } /* r4-r7 = u[3][2-9] */ 215 | ldm r14!, { r8-r10 } /* r9-r11 = w[3][2-7] */ 216 | ldr r11 , [r14] /* r10 = w[3][8-9], r14 = &w[4] */ 217 | 218 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 219 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 220 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 221 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 222 | 223 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[3] */ 224 | strh r3 , [r1] /* *out = s[3] */ 225 | 226 | pop { r4-r11, pc } /* Pop registers and return */ 227 | 228 | 229 | /** 230 | * Synthesize samples of a 8 subbands block 231 | * state Previous transformed samples of the channel 232 | * in Sub-band input samples 233 | * scale Scale factor of samples 234 | * out Output adress of PCM samples 235 | * pitch Number of PCM samples between two consecutive 236 | */ 237 | 238 | .text 239 | 240 | .align 4 241 | 242 | cos_table_8: 243 | .short 5793, -5793, -8192, -8192 244 | .short 7568, -7568, 3135, -3135 245 | .short 4551, -6811, 1598, -8035 246 | 247 | win_table_8_0: 248 | .short 0, -132, -371, -848, -4456, -9631, 4456, -848, 371, -132 249 | .short 0, -132, -371, -848, -4456, -9631, 4456, -848 250 | 251 | .short -10, -138, -526, -580, -5438, -9528, 3486, -1004, 229, -117 252 | .short -10, -138, -526, -580, -5438, -9528, 3486, -1004 253 | 254 | .short -22, -131, -685, -192, -6395, -9224, 2561, -1063, 108, -97 255 | .short -22, -131, -685, -192, -6395, -9224, 2561, -1063 256 | 257 | .short -36, -106, -835, 322, -7287, -8734, 1711, -1042, 12, -75 258 | .short -36, -106, -835, 322, -7287, -8734, 1711, -1042 259 | 260 | .short -54, -59, -960, 959, -8078, -8078, 959, -960, -59, -54 261 | .short -54, -59, -960, 959, -8078, -8078, 959, -960 262 | 263 | .short -75, 12, -1042, 1711, -8734, -7287, 322, -835, -106, -36 264 | .short -75, 12, -1042, 1711, -8734, -7287, 322, -835 265 | 266 | .short -97, 108, -1063, 2561, -9224, -6395, -192, -685, -131, -22 267 | .short -97, 108, -1063, 2561, -9224, -6395, -192, -685 268 | 269 | .short -117, 229, -1004, 3486, -9528, -5438, -580, -526, -138, -10 270 | .short -117, 229, -1004, 3486, -9528, -5438, -580, -526 271 | 272 | win_table_8_1: 273 | .short -132, -371, -848, -4456, -9631, 4456, -848, 371, -132 274 | .short 0, -132, -371, -848, -4456, -9631, 4456, -848, 371 275 | 276 | .short -138, -526, -580, -5438, -9528, 3486, -1004, 229, -117 277 | .short -10, -138, -526, -580, -5438, -9528, 3486, -1004, 229 278 | 279 | .short -131, -685, -192, -6395, -9224, 2561, -1063, 108, -97 280 | .short -22, -131, -685, -192, -6395, -9224, 2561, -1063, 108 281 | 282 | .short -106, -835, 322, -7287, -8734, 1711, -1042, 12, -75 283 | .short -36, -106, -835, 322, -7287, -8734, 1711, -1042, 12 284 | 285 | .short -59, -960, 959, -8078, -8078, 959, -960, -59, -54 286 | .short -54, -59, -960, 959, -8078, -8078, 959, -960, -59 287 | 288 | .short 12, -1042, 1711, -8734, -7287, 322, -835, -106, -36 289 | .short -75, 12, -1042, 1711, -8734, -7287, 322, -835, -106 290 | 291 | .short 108, -1063, 2561, -9224, -6395, -192, -685, -131, -22 292 | .short -97, 108, -1063, 2561, -9224, -6395, -192, -685, -131 293 | 294 | .short 229, -1004, 3486, -9528, -5438, -580, -526, -138, -10 295 | .short -117, 229, -1004, 3486, -9528, -5438, -580, -526, -138 296 | 297 | .thumb_func 298 | .global sbc_synthesize_8 299 | 300 | sbc_synthesize_8: 301 | 302 | push { r3-r11, lr } /* Push registers */ 303 | 304 | /* DCT of subbands samples .............................................. */ 305 | 306 | ldm r1 , { r8-r11 } /* r8-11 = s[0-7] */ 307 | 308 | shasx r6 , r8 , r11 /* r6 = s16 : d07 */ 309 | shasx r7 , r9 , r10 /* r7 = s34 : d25 */ 310 | shsax r8 , r8 , r11 /* r8 = d16 : s07 */ 311 | shsax r9 , r9 , r10 /* r9 = d34 : s25 */ 312 | 313 | pkhtb r4 , r7 , r8 /* r4 = s34 : s07 */ 314 | pkhtb r5 , r6 , r9 /* r5 = s16 : s25 */ 315 | pkhtb r6 , r9 , r6 /* r6 = d34 : d07 */ 316 | pkhtb r7 , r8 , r7 /* r7 = d16 : d25 */ 317 | 318 | ldr r1 , [r0], #4 /* r1 = state->idx */ 319 | mov r11 , r0 /* r11 = &state->v[0] */ 320 | mov r12 , r0 /* r12 = &state->v[0] */ 321 | ands r10 , r1 , #1 /* r10 = state->idx & 1, Z = r10 EQ 0 */ 322 | ite ne /* If-Then-Else ... */ 323 | addne r11 , r11 , #160 /* ... r11 = &state->v[1] */ 324 | addeq r12 , r12 , #160 /* ... r12 = &state->v[1] */ 325 | 326 | cmp r1 , #0 /* Compare state->idx */ 327 | ite ne /* If-Then-Else ... */ 328 | rsbne r1 , r1 , #10 /* ... r1 = state->idx ? */ 329 | moveq r1 , #0 /* ... 10 - state->idx : 0 */ 330 | add r11 , r11 , r1 , LSL #1 /* r11 = &state->v[ odd][0][idx] */ 331 | add r12 , r12 , r1 , LSL #1 /* r12 = &state->v[!odd][0][idx] */ 332 | 333 | adr r14 , cos_table_8 /* r14 = &cos_table */ 334 | 335 | add r2 , r2 , #12 /* r2 = scale + 12 = shr */ 336 | mov r1 , #1 /* r1 = 1 */ 337 | sub r8 , r2 , #1 /* r8 = shr - 1 */ 338 | lsl r1 , r1 , r8 /* r1 = 1 << (shr - 1) */ 339 | 340 | ldm r14!, { r9-r10 } /* r9-r10 = cos( 4, -4, -0, -0 ) */ 341 | 342 | smlsd r8 , r4 , r9 , r1 /* r8 += s07 cos(4) - -s34 cos(4) */ 343 | smlsdx r8 , r5 , r9 , r8 /* r8 += -s25 cos(4) - s16 cos(4) */ 344 | asr r8 , r2 /* r8 = a0 */ 345 | rsb r3 , r8 , #0 /* r3 = -a0 */ 346 | 347 | ssat r8 , #16 , r8 /* r8 = sat( a0) */ 348 | strh r8 , [r11, #0] /* Store v0[0] */ 349 | 350 | ssat r8 , #16 , r3 /* r8 = sat(-a0) */ 351 | strh r8 , [r12, #0] /* Store v1[0] */ 352 | 353 | smlad r8 , r4 , r10 , r1 /* r8 += -s07 cos(0) + -s16 cos(0) */ 354 | smlad r8 , r5 , r10 , r8 /* r8 += -s25 cos(0) + -s34 cos(0) */ 355 | asr r8 , r2 /* r8 = b3 */ 356 | ssat r8 , #16 , r8 /* r8 = sat(b3) */ 357 | strh r8 , [r12, #80] /* Store v1[4] */ 358 | 359 | ldm r14!, { r9-r10 } /* r9-r10 = cos16( 2, -2, 6, -6 ) */ 360 | 361 | smlad r8 , r4 , r10 , r1 /* r8 += s07 cos(6) + -s34 cos(6) */ 362 | smlad r8 , r5 , r9 , r8 /* r8 += s25 cos(2) + -s16 cos(2) */ 363 | asr r8 , r2 /* r8 = a2 */ 364 | rsb r3 , r8 , #0 /* r3 = -a2 */ 365 | 366 | ssat r8 , #16 , r8 /* r8 = sat(a2) */ 367 | strh r8 , [r11, #40] /* Store v0[2] */ 368 | 369 | ssat r8 , #16 , r3 /* r8 = sat(-a2) */ 370 | strh r8 , [r11, #120] /* Store v0[6] */ 371 | 372 | smladx r8 , r4 , r9 , r1 /* r8 += -s07 cos(2) + s34 cos(2) */ 373 | smlad r8 , r5 , r10 , r8 /* r8 += s25 cos(6) - s16 cos(6) */ 374 | asr r8 , r2 /* r8 = b1 */ 375 | ssat r8 , #16 , r8 /* r8 = sat(b1) */ 376 | strh r8 , [r12, #40] /* Store v1[2] */ 377 | strh r8 , [r12, #120] /* Store v1[6] */ 378 | 379 | ldm r14!, { r9-r10 } /* r9-r10 = cos( 5, -3, 7, -1 ) */ 380 | 381 | smlsd r8 , r6 , r9 , r1 /* r8 += d07 cos(5) - -d34 cos(3) */ 382 | smlad r8 , r7 , r10 , r8 /* r8 += d25 cos(7) + -d16 cos(1) */ 383 | asr r8 , r2 /* r8 = a1 */ 384 | rsb r3 , r8 , #0 /* r3 = -a1 */ 385 | 386 | ssat r8 , #16 , r8 /* r8 = sat(a1) */ 387 | strh r8 , [r11, #20] /* Store v0[1] */ 388 | 389 | ssat r8 , #16 , r3 /* r8 = sat(-a1) */ 390 | strh r8 , [r11, #140] /* Store v0[7] */ 391 | 392 | smladx r8 , r6 , r9 , r1 /* r8 += -d07 cos(3) + d34 cos(5) */ 393 | smlsdx r8 , r10 , r7 , r8 /* r8 += d16 cos(7) - -d25 cos(1) */ 394 | asr r8 , r2 /* r8 = b0 */ 395 | ssat r8 , #16 , r8 /* r8 = sat(b0) */ 396 | strh r8 , [r12, #20] /* Store v1[1] */ 397 | strh r8 , [r12, #140] /* Store v1[7] */ 398 | 399 | mov r8 , #0 /* r14 = 0 */ 400 | ssub16 r9 , r8 , r9 /* r9 = cos( -5, 3 ) */ 401 | 402 | smlad r8 , r6 , r10 , r1 /* r8 += d07 cos(7) + -d34 cos(1) */ 403 | smladx r8 , r7 , r9 , r8 /* r8 += d25 cos(3) + -d16 cos(5) */ 404 | asr r8 , r2 /* r8 = a3 */ 405 | rsb r3 , r8 , #0 /* r3 = -a3 */ 406 | 407 | ssat r8 , #16 , r8 /* r8 = sat(a3) */ 408 | strh r8 , [r11, #60] /* Store v0[3] */ 409 | 410 | ssat r8 , #16 , r3 /* r8 = sat(-a3) */ 411 | strh r8 , [r11, #100] /* Store v0[5] */ 412 | 413 | smlsdx r8 , r6 , r10 , r1 /* r8 += -d07 cos(1) - d34 cos(7) */ 414 | smlsd r8 , r7 , r9 , r8 /* r8 += -d25 cos(5) - d16 cos(3) */ 415 | asr r8 , r2 /* r8 = b2 */ 416 | ssat r8 , #16 , r8 /* r8 = sat(b2) */ 417 | strh r8 , [r12, #60] /* Store v1[3] */ 418 | strh r8 , [r12, #100] /* Store v1[5] */ 419 | 420 | /* Update state index ................................................... */ 421 | 422 | ldr r1 , [r0, #-4] /* r1 = state->idx */ 423 | cmp r1 , #9 /* Compare state->idx */ 424 | ite lt /* If-Then-Else ... */ 425 | addlt r2 , r1 , #1 /* ... r2 = state->idx < 9 ? */ 426 | movge r2 , #0 /* ... state->idx + 1 : 0 */ 427 | str r2 , [r0, #-4] /* state->idx = r2 */ 428 | 429 | /* Window and output samples ............................................ */ 430 | 431 | mov r12 , r0 /* r12 = &state->v[0] */ 432 | ands r11 , r1 , #1 /* r11 = state->idx & 1, Z = r11 EQ 0 */ 433 | itte ne /* If-Then-Then-Else ... */ 434 | addne r12 , r12 , #160 /* ... r12 = &state->v[1] */ 435 | adrne r14 , win_table_8_1 /* ... r14 = &win_table_0 */ 436 | adreq r14 , win_table_8_0 /* ... r14 = &win_table_1 */ 437 | 438 | sub r1 , r1 , r11 /* r1 = state->idx &~ 1 */ 439 | add r14 , r14 , r1 , LSL 1 /* r14 = &window + state->idx */ 440 | 441 | pop { r1 } /* r1 = out_ptr */ 442 | ldr r2 , [sp, #36] /* r2 = pitch */ 443 | 444 | mov r0 , #0x1000 /* r0 = 1 << 12 */ 445 | 446 | ldm r12!, { r4-r7 } /* r4-r7 = u[0][0-7] */ 447 | ldm r14!, { r8-r11 } /* r8-r11 = w[0][0-7] */ 448 | 449 | smlad r3 , r4 , r8 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 450 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 451 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 452 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 453 | 454 | ldm r12!, { r4-r7 } /* r4-r7 = u[0][8-9], u[1][0-5] */ 455 | ldr r8 , [r14], #20 /* r8 = w[0][8-9], r14 = &w[1] */ 456 | ldm r14!, { r9-r11 } /* r9-r11 = w[1][0-5] */ 457 | 458 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 459 | 460 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[0] */ 461 | strh r3 , [r1] /* *out = s[0] */ 462 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 463 | 464 | smlad r3 , r5 , r9 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 465 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 466 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 467 | 468 | ldm r12!, { r4-r7 } /* r4-r7 = u[1][6-9], u[2][0-3] */ 469 | ldrd r8 , r9 , [r14], #24 /* r10-r11 = w[1][6-9], r14 = &w[2] */ 470 | ldm r14!, { r10-r11 } /* r9-r11 = w[2][0-3] */ 471 | 472 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 473 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 474 | 475 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[1] */ 476 | strh r3 , [r1] /* *out = s[1] */ 477 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 478 | 479 | smlad r3 , r6 , r10 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 480 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 481 | 482 | ldm r12!, { r4-r7 } /* r4-r7 = u[2][4-9], u[3][0-1] */ 483 | ldm r14!, { r8-r9 } /* r8-r9 = w[2][4-7] */ 484 | ldr r10 , [r14], #20 /* r10 = w[2][8-9], r14 = &w[3] */ 485 | ldr r11 , [r14], #4 /* r11 = w[3][0-1] */ 486 | 487 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 488 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 489 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 490 | 491 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[2] */ 492 | strh r3 , [r1] /* *out = s[2] */ 493 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 494 | 495 | smlad r3 , r7 , r11 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 496 | 497 | ldm r12!, { r4-r7 } /* r4-r7 = u[3][2-9] */ 498 | ldm r14!, { r8-r10 } /* r9-r11 = w[3][2-7] */ 499 | ldr r11 , [r14], #20 /* r10 = w[3][8-9], r14 = &w[4] */ 500 | 501 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 502 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 503 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 504 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 505 | 506 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[3] */ 507 | strh r3 , [r1] /* *out = s[3] */ 508 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 509 | 510 | ldm r12!, { r4-r7 } /* r4-r7 = u[4][0-7] */ 511 | ldm r14!, { r8-r11 } /* r8-r11 = w[4][0-7] */ 512 | 513 | smlad r3 , r4 , r8 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 514 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 515 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 516 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 517 | 518 | ldm r12!, { r4-r7 } /* r4-r7 = u[4][8-9], u[5][0-5] */ 519 | ldr r8 , [r14], #20 /* r8 = w[4][8-9], r14 = &w[5] */ 520 | ldm r14!, { r9-r11 } /* r9-r11 = w[5][0-5] */ 521 | 522 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 523 | 524 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[4] */ 525 | strh r3 , [r1] /* *out = s[4] */ 526 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 527 | 528 | smlad r3 , r5 , r9 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 529 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 530 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 531 | 532 | ldm r12!, { r4-r7 } /* r4-r7 = u[5][6-9], u[6][0-3] */ 533 | ldrd r8 , r9 , [r14], #24 /* r10-r11 = w[5][6-9], r14 = &w[6] */ 534 | ldm r14!, { r10-r11 } /* r9-r11 = w[6][0-3] */ 535 | 536 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 537 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 538 | 539 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[5] */ 540 | strh r3 , [r1] /* *out = s[5] */ 541 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 542 | 543 | smlad r3 , r6 , r10 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 544 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 545 | 546 | ldm r12!, { r4-r7 } /* r4-r7 = u[6][4-9], u[7][0-1] */ 547 | ldm r14!, { r8-r9 } /* r8-r9 = w[6][4-7] */ 548 | ldr r10 , [r14], #20 /* r10 = w[6][8-9], r14 = &w[7] */ 549 | ldr r11 , [r14], #4 /* r11 = w[7][0-1] */ 550 | 551 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 552 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 553 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 554 | 555 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[6] */ 556 | strh r3 , [r1] /* *out = s[6] */ 557 | add r1 , r1 , r2 , LSL #1 /* out += pitch */ 558 | 559 | smlad r3 , r7 , r11 , r0 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 560 | 561 | ldm r12!, { r4-r7 } /* r4-r7 = u[7][2-9] */ 562 | ldm r14!, { r8-r11 } /* r9-r11 = w[7][2-9] */ 563 | 564 | smlad r3 , r4 , r8 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 565 | smlad r3 , r5 , r9 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 566 | smlad r3 , r6 , r10 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 567 | smlad r3 , r7 , r11 , r3 /* r3 += *(u++) *(w++) + *(u++) *(w++) */ 568 | 569 | ssat r3 , #16 , r3 , ASR #13 /* r3 = s[7] */ 570 | strh r3 , [r1] /* *out = s[7] */ 571 | 572 | pop { r4-r11, pc } /* Pop registers and return */ 573 | -------------------------------------------------------------------------------- /src/bits.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include "bits.h" 20 | 21 | 22 | /** 23 | * Accumulator bit size 24 | */ 25 | 26 | #define ACCU_NBITS (8 * sizeof(bits_accu_t)) 27 | 28 | 29 | /** 30 | * Bits extraction : 31 | * MASK Mask of less-significant `n` bits 32 | * EXT Extract the value `v` from bits `b(s+n-1)..b(s)` 33 | */ 34 | 35 | #define MASK(n) ( (1U << (n)) - 1 ) 36 | #define EXT(v, s, n) ( ((v) >> (s)) & MASK(n) ) 37 | 38 | 39 | /** 40 | * Sub-function of "load_accu()", general way loading 41 | * bits Bitsream context 42 | */ 43 | static void load_accu_slow(struct sbc_bits *bits) 44 | { 45 | while (bits->accu.nleft < ACCU_NBITS - 7 && bits->data.nleft) { 46 | bits->accu.v = (bits->accu.v << 8) | *(bits->data.p++); 47 | bits->accu.nleft += 8; 48 | bits->data.nleft--; 49 | } 50 | 51 | if (bits->accu.nleft < ACCU_NBITS - 7) 52 | { 53 | unsigned nover = ((ACCU_NBITS - bits->accu.nleft) >> 3) << 3; 54 | 55 | if (bits->accu.nleft >= bits->accu.nover) 56 | bits->accu.nover += nover; 57 | else 58 | bits->accu.nover = UINT_MAX; 59 | 60 | if (nover < ACCU_NBITS) 61 | bits->accu.v <<= nover; 62 | else 63 | bits->accu.v = 0; 64 | 65 | bits->accu.nleft += nover; 66 | } 67 | } 68 | 69 | /** 70 | * Load the accumulator 71 | * bits Bitsream context 72 | * 73 | * On return `8 * sizeof(bits_accu_t) - (accu.nleft % 8)` are available 74 | */ 75 | static inline void load_accu(struct sbc_bits *bits) 76 | { 77 | unsigned nbytes = sizeof(bits_accu_t) - ((bits->accu.nleft + 7) >> 3); 78 | 79 | if (nbytes > bits->data.nleft) { 80 | load_accu_slow(bits); 81 | return; 82 | } 83 | 84 | bits->accu.nleft += nbytes << 3; 85 | bits->data.nleft -= nbytes; 86 | while (nbytes--) 87 | bits->accu.v = (bits->accu.v << 8) | *(bits->data.p++); 88 | } 89 | 90 | /** 91 | * Flush the accumulator 92 | * bits Bitsream context 93 | * 94 | * On return `8 * sizeof(bits_accu_t) - (accu.nleft % 8)` are available 95 | */ 96 | static inline void flush_accu(struct sbc_bits *bits) 97 | { 98 | unsigned nbytes = sizeof(bits_accu_t) - ((bits->accu.nleft + 7) >> 3); 99 | 100 | unsigned nflush = nbytes < bits->data.nleft ? nbytes : bits->data.nleft; 101 | bits->data.nleft -= nflush; 102 | 103 | for (int shr = (ACCU_NBITS - 8) - bits->accu.nleft; nflush--; shr -= 8) 104 | *(bits->data.p++) = bits->accu.v >> shr; 105 | 106 | bits->accu.v &= (1 << bits->accu.nleft) - 1; 107 | bits->accu.nleft += nbytes << 3; 108 | } 109 | 110 | /** 111 | * Setup bitstream reader context 112 | */ 113 | void sbc_setup_bits(struct sbc_bits *bits, 114 | enum sbc_bits_mode mode, void *data, unsigned size) 115 | { 116 | *bits = (struct sbc_bits){ 117 | .mode = mode, 118 | .accu.nleft = mode == SBC_BITS_READ ? 0 : 8*sizeof(bits_accu_t), 119 | .data.p = data, .data.nbytes = size, .data.nleft = size, 120 | }; 121 | } 122 | 123 | /** 124 | * Return the bit position in the stream 125 | * bits Bitstream context 126 | */ 127 | unsigned sbc_tell_bits(sbc_bits_t *bits) 128 | { 129 | unsigned nbytes = bits->data.nbytes - bits->data.nleft; 130 | if (bits->mode == SBC_BITS_WRITE) 131 | nbytes += sizeof(bits_accu_t); 132 | 133 | return 8 * nbytes - ( bits->accu.nleft < bits->accu.nover ? 0 : 134 | bits->accu.nleft - bits->accu.nover ); 135 | } 136 | 137 | /** 138 | * Get from 1 to 32 bits 139 | */ 140 | unsigned __sbc_get_bits(struct sbc_bits *bits, unsigned n) 141 | { 142 | if (n > 32) n = 32; 143 | 144 | if (!bits->accu.nleft) 145 | load_accu(bits); 146 | 147 | if (bits->accu.nleft >= n) 148 | return (bits->accu.nleft -= n), 149 | EXT(bits->accu.v, bits->accu.nleft, n); 150 | 151 | n -= bits->accu.nleft; 152 | unsigned v = bits->accu.v & MASK(bits->accu.nleft); 153 | bits->accu.nleft = 0; 154 | 155 | load_accu(bits); 156 | 157 | return (bits->accu.nleft -= n), 158 | ((v << n) | EXT(bits->accu.v, bits->accu.nleft, n)); 159 | } 160 | 161 | /** 162 | * Put from 1 to 32 bits 163 | */ 164 | void __sbc_put_bits(struct sbc_bits *bits, unsigned v, unsigned n) 165 | { 166 | if (n > 32) n = 32; 167 | 168 | if (!bits->accu.nleft) 169 | flush_accu(bits); 170 | 171 | int m = bits->accu.nleft < n ? bits->accu.nleft : n; 172 | n -= m; 173 | 174 | bits->accu.nleft -= m; 175 | bits->accu.v = (bits->accu.v << m) | ((v >> n) & ((1U << m) - 1)); 176 | 177 | if (n <= 0) 178 | return; 179 | 180 | flush_accu(bits); 181 | 182 | bits->accu.nleft -= n; 183 | bits->accu.v = (bits->accu.v << n) | (v & ((1U << n) - 1)); 184 | } 185 | 186 | /** 187 | * Flush pending bytes 188 | */ 189 | void sbc_flush_bits(struct sbc_bits *bits) 190 | { 191 | flush_accu(bits); 192 | } 193 | -------------------------------------------------------------------------------- /src/bits.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef __SBC_BITS_H 20 | #define __SBC_BITS_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | /** 28 | * Bitstream mode 29 | */ 30 | enum sbc_bits_mode 31 | { 32 | SBC_BITS_READ = 0, 33 | SBC_BITS_WRITE, 34 | }; 35 | 36 | 37 | /** 38 | * Private context 39 | */ 40 | 41 | typedef unsigned bits_accu_t; 42 | 43 | typedef struct sbc_bits 44 | { 45 | enum sbc_bits_mode mode; 46 | 47 | struct { 48 | uint8_t *p; 49 | unsigned nbytes; 50 | unsigned nleft; 51 | } data; 52 | 53 | struct { 54 | bits_accu_t v; 55 | unsigned nleft; 56 | unsigned nover; 57 | } accu; 58 | 59 | bool error; 60 | 61 | } sbc_bits_t; 62 | 63 | 64 | /** 65 | * Debug trace procedure, enable with `SBC_BITS_TRACE` 66 | */ 67 | 68 | #ifdef SBC_BITS_TRACE 69 | 70 | #include 71 | 72 | #define sbc_trace(pos, name, val) \ 73 | fprintf(stderr, "|%5u| %-32s : %4d\n", pos, name, val) 74 | 75 | #endif /* SBC_BITS_TRACE */ 76 | 77 | 78 | /** 79 | * Helper macros on bitstream reading 80 | */ 81 | 82 | #define SBC_WITH_BITS(bits) \ 83 | do { \ 84 | sbc_bits_t *__bits = bits 85 | 86 | #ifndef SBC_BITS_TRACE 87 | 88 | #define SBC_GET_BITS(name, n) sbc_get_bits(__bits, n) 89 | #define SBC_GET_FIXED(name, n, v) sbc_get_fixed(__bits, n, v) 90 | 91 | #define SBC_PUT_BITS(name, v, n) sbc_put_bits(__bits, v, n) 92 | 93 | #else 94 | 95 | #define SBC_GET_BITS(name, n) sbc_get_named_bits(__bits, name, n) 96 | #define SBC_GET_FIXED(name, n, v) sbc_get_named_fixed(__bits, name, n, v) 97 | 98 | #define SBC_PUT_BITS(name, v, n) sbc_put_named_bits(__bits, name, v, n) 99 | 100 | #endif 101 | 102 | #define SBC_END_WITH_BITS() \ 103 | } while(0) 104 | 105 | /** 106 | * Setup bitstream context 107 | * bits Context to setup 108 | * mode Bitstream mode "read or write" 109 | * data Data buffer to read or write 110 | * size Number of bytes available 111 | */ 112 | void sbc_setup_bits(sbc_bits_t *bits, 113 | enum sbc_bits_mode mode, void *data, unsigned size); 114 | 115 | /** 116 | * Return the bit position in the stream 117 | * bits Bitstream context 118 | */ 119 | unsigned sbc_tell_bits(sbc_bits_t *bits); 120 | 121 | 122 | /* ---------------------------------------------------------------------------- 123 | * Reading 124 | * ------------------------------------------------------------------------- */ 125 | 126 | /** 127 | * Return true when a reading error is detected 128 | * return True whenever an error has been detected 129 | */ 130 | static inline bool sbc_bits_error(sbc_bits_t *bits); 131 | 132 | /** 133 | * Get from 0 to 32 bits 134 | * bits Bitsream context 135 | * n Number of bits to read (0 to 32) 136 | * 137 | * For 0 bit reading, the value 0 is returned 138 | * If there is no more data to read from the bistsream, 139 | * the missing bits are emulated with bits of value 0. 140 | */ 141 | static inline unsigned sbc_get_bits(sbc_bits_t *bits, unsigned n); 142 | 143 | /** 144 | * Get from 1 to 32 bits, whose value is a constant 145 | * bits Bitsream context 146 | * n Number of bits to read (1 to 32) 147 | * val Fixed value to check 148 | */ 149 | static inline void sbc_get_fixed(struct sbc_bits *bits, unsigned n, unsigned v); 150 | 151 | 152 | /* ---------------------------------------------------------------------------- 153 | * Writing 154 | * ------------------------------------------------------------------------- */ 155 | 156 | /** 157 | * Put from 0 to 32 bits 158 | * bits Bitsream context 159 | * n Number of bits to write (0 to 32) 160 | */ 161 | static inline void sbc_put_bits(sbc_bits_t *bits, unsigned v, unsigned n); 162 | 163 | /** 164 | * Flush pending bytes 165 | * bits Bitsream context 166 | */ 167 | void sbc_flush_bits(sbc_bits_t *bits); 168 | 169 | 170 | /* ---------------------------------------------------------------------------- 171 | * Inline implementations 172 | * ------------------------------------------------------------------------- */ 173 | 174 | static inline bool sbc_bits_error(struct sbc_bits *bits) 175 | { 176 | return bits->error; 177 | } 178 | 179 | extern unsigned __sbc_get_bits(sbc_bits_t *, unsigned); 180 | extern void __sbc_put_bits(sbc_bits_t *, unsigned, unsigned); 181 | 182 | static inline unsigned sbc_get_bits(struct sbc_bits *bits, unsigned n) 183 | { 184 | if (bits->accu.nleft < n) 185 | return __sbc_get_bits(bits, n); 186 | 187 | bits->accu.nleft -= n; 188 | return (bits->accu.v >> bits->accu.nleft) & ((1U << n) - 1); 189 | } 190 | 191 | static inline void sbc_put_bits(struct sbc_bits *bits, unsigned v, unsigned n) 192 | { 193 | if (bits->accu.nleft < n) 194 | __sbc_put_bits(bits, v, n); 195 | else { 196 | bits->accu.nleft -= n; 197 | bits->accu.v = (bits->accu.v << n) | (v & ((1U << n) - 1)); 198 | } 199 | } 200 | 201 | static inline void sbc_get_fixed(struct sbc_bits *bits, unsigned n, unsigned v) 202 | { 203 | if (sbc_get_bits(bits, n) != v) 204 | bits->error = true; 205 | } 206 | 207 | #ifdef SBC_BITS_TRACE 208 | 209 | static inline unsigned sbc_get_named_bits( 210 | struct sbc_bits *bits, const char *name, unsigned n) 211 | { 212 | unsigned off = sbc_tell_bits(bits); 213 | unsigned val = sbc_get_bits(bits, n); 214 | return sbc_trace(off, name, val), val; 215 | } 216 | 217 | static inline void sbc_put_named_bits( 218 | struct sbc_bits *bits, const char *name, unsigned v, unsigned n) 219 | { 220 | sbc_trace(sbc_tell_bits(bits), name, v); 221 | sbc_put_bits(bits, v, n); 222 | } 223 | 224 | static inline void sbc_get_named_fixed(struct sbc_bits *bits, 225 | const char *name, unsigned n, unsigned fixed_value) 226 | { 227 | unsigned off = sbc_tell_bits(bits); 228 | unsigned val = sbc_get_bits(bits, n); 229 | 230 | if (val != fixed_value) 231 | bits->error = true; 232 | 233 | sbc_trace(off, name, val); 234 | } 235 | 236 | #endif /* SBC_BITS_TRACE */ 237 | 238 | #endif /* __SBC_BITS_H */ 239 | -------------------------------------------------------------------------------- /src/sbc.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | 22 | #undef SBC_BITS_TRACE 23 | #include "bits.h" 24 | 25 | 26 | /** 27 | * SBC Frame header size 28 | */ 29 | 30 | #define SBC_HEADER_SIZE ( 4) 31 | 32 | 33 | /** 34 | * Assembly declaration 35 | */ 36 | 37 | void sbc_synthesize_4(struct sbc_dstate *state, 38 | const int16_t *in, int scale, int16_t *out, int pitch); 39 | 40 | void sbc_synthesize_8(struct sbc_dstate *state, 41 | const int16_t *in, int scale, int16_t *out, int pitch); 42 | 43 | #ifndef SBC_ASM 44 | #define ASM(fn) (fn##_c) 45 | #else 46 | #define ASM(fn) (fn) 47 | #endif 48 | 49 | 50 | /** 51 | * Macros 52 | * MIN/MAX Minimum and maximum between 2 values 53 | * SAT16 Signed saturation on 16 bits 54 | * Saturate on 16 bits 55 | */ 56 | 57 | #define SBC_MIN(a, b) ( (a) < (b) ? (a) : (b) ) 58 | #define SBC_MAX(a, b) ( (a) > (b) ? (a) : (b) ) 59 | 60 | #define SBC_SAT16(v) (int16_t)\ 61 | ( (v) > INT16_MAX ? INT16_MAX : \ 62 | (v) < INT16_MIN ? INT16_MIN : (v) ) 63 | 64 | 65 | /** 66 | * Count number of leading zero bits 67 | */ 68 | 69 | #define SBC_CLZ(n) __builtin_clz(n) 70 | 71 | 72 | /** 73 | * mSBC constant frame description 74 | */ 75 | static const struct sbc_frame msbc_frame = { 76 | .msbc = true, 77 | .mode = SBC_MODE_MONO, 78 | .freq = SBC_FREQ_16K, 79 | .bam = SBC_BAM_LOUDNESS, 80 | .nsubbands = 8, .nblocks = 15, 81 | .bitpool = 26 82 | }; 83 | 84 | 85 | /* ---------------------------------------------------------------------------- 86 | * Common 87 | * ------------------------------------------------------------------------- */ 88 | 89 | /** 90 | * Compute CRC of frame 91 | * frame La description de frame 92 | * data, size Frame data, and maximum readable size 93 | * return The CRC-8 value, -1: size too small 94 | */ 95 | static int compute_crc( 96 | const struct sbc_frame *frame, const uint8_t *data, unsigned size) 97 | { 98 | /* Look-up table par 8 bits 99 | * Generator polynomial G(X) = X^8 + X^4 + X^3 + X^2 + 1 (0x1d) */ 100 | 101 | static const uint8_t t[] = { 102 | 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 103 | 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, 104 | 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, 105 | 0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 106 | 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, 107 | 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c, 108 | 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, 109 | 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, 110 | 0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, 111 | 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, 112 | 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, 113 | 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, 114 | 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 115 | 0x7c, 0x61, 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, 116 | 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a, 117 | 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, 118 | 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, 119 | 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, 120 | 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 121 | 0x03, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, 122 | 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, 123 | 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, 124 | 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, 125 | 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, 126 | 0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66, 127 | 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, 128 | 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, 129 | 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 130 | 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, 131 | 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09, 132 | 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c, 133 | 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4, 134 | }; 135 | 136 | /* The CRC cover the syntax indicated with "[]" : 137 | * 138 | * Header() 139 | * | syncword 8 140 | * | [ desc ] 16 141 | * | crc 8 142 | * Data() 143 | * | SI mode `Join-Stereo` 144 | * | | [ joint ] nsb x 1 145 | * | [ scale-factors ] nch x nsb x 4 146 | * | ... */ 147 | 148 | int nch = 1 + (frame->mode != SBC_MODE_MONO); 149 | int nsb = frame->nsubbands; 150 | unsigned i, nbit = nch*nsb*4 + 151 | (frame->mode == SBC_MODE_JOINT_STEREO ? nsb : 0); 152 | 153 | if (size < ((SBC_HEADER_SIZE*8 + nbit + 7) >> 3)) 154 | return -1; 155 | 156 | uint8_t crc = 0x0f; 157 | crc = t[crc ^ data[1]]; 158 | crc = t[crc ^ data[2]]; 159 | 160 | for (i = 4; i < 4 + nbit/8; i++) 161 | crc = t[crc ^ data[i]]; 162 | 163 | if (nbit % 8) 164 | crc = (crc << 4) ^ t[(crc >> 4) ^ (data[i] >> 4)]; 165 | 166 | return crc; 167 | } 168 | 169 | /** 170 | * Check a frame description 171 | * frame The frame description to check 172 | * return True when valid, False otherwise 173 | */ 174 | static bool check_frame(const struct sbc_frame *frame) 175 | { 176 | /* --- Check number of sub-blocks and sub-bands --- */ 177 | 178 | if ((unsigned)(frame->nblocks - 4) > 12 || 179 | (!frame->msbc && frame->nblocks % 4 != 0)) 180 | return false; 181 | 182 | if ((unsigned)(frame->nsubbands - 4) > 4 || frame->nsubbands % 4 != 0) 183 | return false; 184 | 185 | /* --- Validate the bitpool value --- */ 186 | 187 | bool two_channels = (frame->mode != SBC_MODE_MONO); 188 | bool dual_mode = (frame->mode == SBC_MODE_DUAL_CHANNEL); 189 | bool joint_mode = (frame->mode == SBC_MODE_JOINT_STEREO); 190 | bool stereo_mode = joint_mode || (frame->mode == SBC_MODE_STEREO); 191 | 192 | int max_bits = 193 | ((16 * frame->nsubbands * frame->nblocks) << two_channels) - 194 | (SBC_HEADER_SIZE * 8) - 195 | ((4 * frame->nsubbands) << two_channels) - 196 | (joint_mode ? frame->nsubbands : 0); 197 | 198 | int max_bitpool = SBC_MIN( max_bits / (frame->nblocks << dual_mode), 199 | (16 << stereo_mode) * frame->nsubbands ); 200 | 201 | return frame->bitpool <= max_bitpool; 202 | } 203 | 204 | /** 205 | * Compute the bit distribution for Independent or Stereo Channel 206 | * frame Frame description 207 | * scale_factors Scale-factor values 208 | * nbits Return of allocated bits for each channels / subbands 209 | */ 210 | static void compute_nbits(const struct sbc_frame *frame, 211 | const int (*scale_factors)[SBC_MAX_SUBBANDS], 212 | int (*nbits)[SBC_MAX_SUBBANDS]) 213 | { 214 | /* --- Offsets of "Loudness" bit allocation --- */ 215 | 216 | static const int loudness_offset_4[SBC_NUM_FREQ][4] = { 217 | [SBC_FREQ_16K ] = { -1, 0, 0, 0 }, 218 | [SBC_FREQ_32K ] = { -2, 0, 0, 1 }, 219 | [SBC_FREQ_44K1] = { -2, 0, 0, 1 }, 220 | [SBC_FREQ_48K ] = { -2, 0, 0, 1 }, 221 | }; 222 | 223 | static const int loudness_offset_8[SBC_NUM_FREQ][8] = { 224 | [SBC_FREQ_16K ] = { -2, 0, 0, 0, 0, 0, 0, 1 }, 225 | [SBC_FREQ_32K ] = { -3, 0, 0, 0, 0, 0, 1, 2 }, 226 | [SBC_FREQ_44K1] = { -4, 0, 0, 0, 0, 0, 1, 2 }, 227 | [SBC_FREQ_48K ] = { -4, 0, 0, 0, 0, 0, 1, 2 }, 228 | }; 229 | 230 | /* --- Compute the number of bits needed --- */ 231 | 232 | const int *loudness_offset = frame->nsubbands == 4 ? 233 | loudness_offset_4[frame->freq] : loudness_offset_8[frame->freq]; 234 | 235 | bool stereo_mode = frame->mode == SBC_MODE_STEREO || 236 | frame->mode == SBC_MODE_JOINT_STEREO; 237 | 238 | int nsubbands = frame->nsubbands; 239 | int nchannels = 1 + stereo_mode; 240 | 241 | int bitneeds[2][SBC_MAX_SUBBANDS]; 242 | int max_bitneed = 0; 243 | 244 | for (int ich = 0; ich < nchannels; ich++) 245 | for (int isb = 0; isb < nsubbands; isb++) { 246 | int bitneed, scf = scale_factors[ich][isb]; 247 | 248 | if (frame->bam == SBC_BAM_LOUDNESS) { 249 | bitneed = scf ? scf - loudness_offset[isb] : -5; 250 | bitneed >>= (bitneed > 0); 251 | } else { 252 | bitneed = scf; 253 | } 254 | 255 | if (bitneed > max_bitneed) 256 | max_bitneed = bitneed; 257 | 258 | bitneeds[ich][isb] = bitneed; 259 | } 260 | 261 | /* --- Loop over the bit distribution, until reaching the bitpool --- */ 262 | 263 | int bitpool = frame->bitpool; 264 | 265 | int bitcount = 0; 266 | int bitslice = max_bitneed + 1; 267 | 268 | for (int bc = 0; bc < bitpool; ) { 269 | 270 | int bs = bitslice--; 271 | bitcount = bc; 272 | if (bitcount == bitpool) 273 | break; 274 | 275 | for (int ich = 0; ich < nchannels; ich++) 276 | for (int isb = 0; isb < nsubbands; isb++) { 277 | int bn = bitneeds[ich][isb]; 278 | bc += (bn >= bs && bn < bs + 15) + (bn == bs); 279 | } 280 | } 281 | 282 | /* --- Bits distribution --- */ 283 | 284 | for (int ich = 0; ich < nchannels; ich++) 285 | for (int isb = 0; isb < nsubbands; isb++) { 286 | int nbit = bitneeds[ich][isb] - bitslice; 287 | nbits[ich][isb] = nbit < 2 ? 0 : nbit > 16 ? 16 : nbit; 288 | } 289 | 290 | /* --- Allocate remaining bits --- */ 291 | 292 | for (int isb = 0; isb < nsubbands && bitcount < bitpool; isb++) 293 | for (int ich = 0; ich < nchannels && bitcount < bitpool; ich++) { 294 | 295 | int n = nbits[ich][isb] && nbits[ich][isb] < 16 ? 1 : 296 | bitneeds[ich][isb] == bitslice + 1 && 297 | bitpool > bitcount + 1 ? 2 : 0; 298 | 299 | nbits[ich][isb] += n; 300 | bitcount += n; 301 | } 302 | 303 | for (int isb = 0; isb < nsubbands && bitcount < bitpool; isb++) 304 | for (int ich = 0; ich < nchannels && bitcount < bitpool; ich++) { 305 | 306 | int n = (nbits[ich][isb] < 16); 307 | nbits[ich][isb] += n; 308 | bitcount += n; 309 | } 310 | } 311 | 312 | /** 313 | * Return the sampling frequency in Hz 314 | */ 315 | int sbc_get_freq_hz(enum sbc_freq freq) 316 | { 317 | static const int freq_hz[SBC_NUM_FREQ] = { 318 | [SBC_FREQ_16K ] = 16000, [SBC_FREQ_32K ] = 32000, 319 | [SBC_FREQ_44K1] = 44100, [SBC_FREQ_48K ] = 48000, 320 | }; 321 | 322 | return freq_hz[freq]; 323 | } 324 | 325 | /** 326 | * Return the frame size from a frame description 327 | */ 328 | unsigned sbc_get_frame_size(const struct sbc_frame *frame) 329 | { 330 | if (!check_frame(frame)) 331 | return 0; 332 | 333 | bool two_channels = (frame->mode != SBC_MODE_MONO); 334 | bool dual_mode = (frame->mode == SBC_MODE_DUAL_CHANNEL); 335 | bool joint_mode = (frame->mode == SBC_MODE_JOINT_STEREO); 336 | 337 | unsigned nbits = 338 | ((4 * frame->nsubbands) << two_channels) + 339 | ((frame->nblocks * frame->bitpool) << dual_mode) + 340 | ((joint_mode ? frame->nsubbands : 0)); 341 | 342 | return SBC_HEADER_SIZE + ((nbits + 7) >> 3); 343 | } 344 | 345 | /** 346 | * Return the bitrate from a frame description 347 | */ 348 | unsigned sbc_get_frame_bitrate(const struct sbc_frame *frame) 349 | { 350 | if (!check_frame(frame)) 351 | return 0; 352 | 353 | unsigned nsamples = frame->nblocks * frame->nsubbands; 354 | unsigned nbits = 8 * sbc_get_frame_size(frame); 355 | 356 | return (nbits * sbc_get_freq_hz(frame->freq)) / nsamples; 357 | } 358 | 359 | /** 360 | * Return the bitrate from a frame description 361 | */ 362 | int sbc_get_frame_bps(enum sbc_freq freq) 363 | { 364 | static const int freq_hz[SBC_NUM_FREQ] = { 365 | [SBC_FREQ_16K ] = 16000, [SBC_FREQ_32K ] = 32000, 366 | [SBC_FREQ_44K1] = 44100, [SBC_FREQ_48K ] = 48000, 367 | }; 368 | 369 | return freq_hz[freq]; 370 | } 371 | 372 | /** 373 | * Reset of the context 374 | */ 375 | void sbc_reset(struct sbc *sbc) 376 | { 377 | *sbc = (struct sbc){ }; 378 | } 379 | 380 | 381 | /* ---------------------------------------------------------------------------- 382 | * Decoding 383 | * ------------------------------------------------------------------------- */ 384 | 385 | /** 386 | * Decode the 4 bytes frame header 387 | * bits Bitstream reader 388 | * frame Return the frame description 389 | * crc Return the CRC validating the stream, or NULL 390 | * return True on success, False otherwise 391 | */ 392 | static bool decode_header(sbc_bits_t *bits, struct sbc_frame *frame, int *crc) 393 | { 394 | static const enum sbc_freq dec_freq[] = 395 | { SBC_FREQ_16K, SBC_FREQ_32K, SBC_FREQ_44K1, SBC_FREQ_48K }; 396 | 397 | static const enum sbc_mode dec_mode[] = 398 | { SBC_MODE_MONO, SBC_MODE_DUAL_CHANNEL, 399 | SBC_MODE_STEREO, SBC_MODE_JOINT_STEREO }; 400 | 401 | static const enum sbc_bam dec_bam[] = 402 | { SBC_BAM_LOUDNESS, SBC_BAM_SNR }; 403 | 404 | /* --- Decode header --- 405 | * 406 | * Two possible headers : 407 | * - Header, with syncword 0x9c (A2DP) 408 | * - mSBC header, with syncword 0xad (HFP) */ 409 | 410 | SBC_WITH_BITS(bits); 411 | 412 | int syncword = SBC_GET_BITS("syncword", 8); 413 | frame->msbc = (syncword == 0xad); 414 | if (frame->msbc) { 415 | SBC_GET_BITS("reserved", 16); 416 | *frame = msbc_frame; 417 | } 418 | 419 | else if (syncword == 0x9c) { 420 | frame->freq = dec_freq[SBC_GET_BITS("sampling_frequency", 2)]; 421 | frame->nblocks = (1 + SBC_GET_BITS("blocks", 2)) << 2; 422 | frame->mode = dec_mode[SBC_GET_BITS("channel_mode", 2)]; 423 | frame->bam = dec_bam[SBC_GET_BITS("allocation_method", 1)]; 424 | frame->nsubbands = (1 + SBC_GET_BITS("subbands", 1)) << 2; 425 | frame->bitpool = SBC_GET_BITS("bitpool", 8); 426 | 427 | } else 428 | return false; 429 | 430 | if (crc) 431 | *crc = SBC_GET_BITS("crc_check", 8); 432 | 433 | SBC_END_WITH_BITS(); 434 | 435 | /* --- Check bitpool value and return --- */ 436 | 437 | return check_frame(frame); 438 | } 439 | 440 | /** 441 | * Decode frame data 442 | * bits Bitstream reader 443 | * frame Frame description 444 | * sb_samples Return the sub-band samples, by channels 445 | * sb_scale Return the sample scaler, by track (indep. channels) 446 | */ 447 | static void decode_frame(sbc_bits_t *bits, const struct sbc_frame *frame, 448 | int16_t (*sb_samples)[SBC_MAX_SAMPLES], int *sb_scale) 449 | { 450 | static const int range_scale[] = { 451 | 0xFFFFFFF, 0x5555556, 0x2492492, 0x1111111, 452 | 0x0842108, 0x0410410, 0x0204081, 0x0101010, 453 | 0x0080402, 0x0040100, 0x0020040, 0x0010010, 454 | 0x0008004, 0x0004001, 0x0002000, 0x0001000 455 | }; 456 | 457 | /* --- Decode joint bands indications --- */ 458 | 459 | SBC_WITH_BITS(bits); 460 | 461 | unsigned mjoint = 0; 462 | 463 | if (frame->mode == SBC_MODE_JOINT_STEREO && frame->nsubbands == 4) 464 | { 465 | unsigned v = SBC_GET_BITS("join[]", 4); 466 | mjoint = (( 0x00) << 3) | ((v & 0x02) << 1) | 467 | ((v & 0x04) >> 1) | ((v & 0x08) >> 3) ; 468 | 469 | } else if (frame->mode == SBC_MODE_JOINT_STEREO) { 470 | unsigned v = SBC_GET_BITS("join[]", 8); 471 | 472 | mjoint = (( 0x00) << 7) | ((v & 0x02) << 5) | 473 | ((v & 0x04) << 3) | ((v & 0x08) << 1) | 474 | ((v & 0x10) >> 1) | ((v & 0x20) >> 3) | 475 | ((v & 0x40) >> 5) | ((v & 0x80) >> 7) ; 476 | } 477 | 478 | /* --- Decode scale factors --- */ 479 | 480 | int nchannels = 1 + (frame->mode != SBC_MODE_MONO); 481 | int nsubbands = frame->nsubbands; 482 | 483 | int scale_factors[2][SBC_MAX_SUBBANDS]; 484 | int nbits[2][SBC_MAX_SUBBANDS]; 485 | 486 | for (int ich = 0; ich < nchannels; ich++) 487 | for (int isb = 0; isb < nsubbands; isb++) 488 | scale_factors[ich][isb] = SBC_GET_BITS("scale_factor", 4); 489 | 490 | compute_nbits(frame, scale_factors, nbits); 491 | if (frame->mode == SBC_MODE_DUAL_CHANNEL) 492 | compute_nbits(frame, scale_factors + 1, nbits + 1); 493 | 494 | /* --- Decode samples --- 495 | * 496 | * They are unquantized according : 497 | * 498 | * 2 sample + 1 499 | * sb_sample = ( -------------- - 1 ) 2^(scf + 1) 500 | * 2^nbit - 1 501 | * 502 | * A sample is coded on maximum 16 bits, and the scale factor is limited 503 | * to 15 bits. Thus the dynamic of sub-bands samples are 17 bits. 504 | * Regarding "Joint-Stereo" sub-bands, uncoupling increase the dynamic 505 | * to 18 bits. 506 | * 507 | * The `1 / (2^nbit - 1)` values are precalculated on 1.28 : 508 | * 509 | * sb_sample = ((2 sample + 1) * range_scale - 2^28) / 2^shr 510 | * 511 | * with shr = 28 - ((scf + 1) + sb_scale) 512 | * sb_scale = (15 - max(scale_factor[])) - (18 - 16) 513 | * 514 | * We introduce `sb_scale`, to limit the range on 16 bits, or increase 515 | * precision when the scale-factor of the frame is below 13. */ 516 | 517 | for (int ich = 0; ich < nchannels; ich++) { 518 | int max_scf = 0; 519 | 520 | for (int isb = 0; isb < nsubbands; isb++) { 521 | int scf = scale_factors[ich][isb] + ((mjoint >> isb) & 1); 522 | if (scf > max_scf) max_scf = scf; 523 | } 524 | 525 | sb_scale[ich] = (15 - max_scf) - (17 - 16); 526 | } 527 | 528 | if (frame->mode == SBC_MODE_JOINT_STEREO) 529 | sb_scale[0] = sb_scale[1] = 530 | sb_scale[0] < sb_scale[1] ? sb_scale[0] : sb_scale[1]; 531 | 532 | for (int iblk = 0; iblk < frame->nblocks; iblk++) 533 | for (int ich = 0; ich < nchannels; ich++) { 534 | int16_t *p_sb_samples = sb_samples[ich] + iblk*nsubbands; 535 | 536 | for (int isb = 0; isb < nsubbands; isb++) { 537 | int nbit = nbits[ich][isb]; 538 | int scf = scale_factors[ich][isb]; 539 | 540 | if (!nbit) { *(p_sb_samples++) = 0; continue; } 541 | 542 | int s = SBC_GET_BITS("audio_sample", nbit); 543 | s = ((s << 1) | 1) * range_scale[nbit-1]; 544 | 545 | *(p_sb_samples++) = 546 | (s - (1 << 28)) >> (28 - ((scf + 1) + sb_scale[ich])); 547 | } 548 | } 549 | 550 | /* --- Uncoupling "Joint-Stereo" --- 551 | * 552 | * The `Left/Right` samples are coded as : 553 | * `sb_sample(left ) = sb_sample(ch 0) + sb_sample(ch 1)` 554 | * `sb_sample(right) = sb_sample(ch 0) - sb_sample(ch 1)` */ 555 | 556 | for (int isb = 0; isb < nsubbands; isb++) { 557 | 558 | if (((mjoint >> isb) & 1) == 0) 559 | continue; 560 | 561 | for (int iblk = 0; iblk < frame->nblocks; iblk++) { 562 | int16_t s0 = sb_samples[0][iblk*nsubbands + isb]; 563 | int16_t s1 = sb_samples[1][iblk*nsubbands + isb]; 564 | 565 | sb_samples[0][iblk*nsubbands + isb] = s0 + s1; 566 | sb_samples[1][iblk*nsubbands + isb] = s0 - s1; 567 | } 568 | } 569 | 570 | /* --- Remove padding --- */ 571 | 572 | int padding_nbits = 8 - (sbc_tell_bits(bits) % 8); 573 | if (padding_nbits < 8) 574 | SBC_GET_FIXED("padding_bits", padding_nbits, 0); 575 | 576 | SBC_END_WITH_BITS(); 577 | } 578 | 579 | /** 580 | * Perform a DCT on 4 samples 581 | * in Subbands input samples 582 | * scale Scale factor of input samples (-2 to 14) 583 | * out0 Output of 1st half samples 584 | * out1 Output of 2nd half samples 585 | * idx Index of transformed samples 586 | */ 587 | static inline void dct4(const int16_t *in, int scale, 588 | int16_t (*out0)[10], int16_t (*out1)[10], int idx) 589 | { 590 | /* cos(i*pi/8) for i = [0;3], in fixed 0.13 */ 591 | 592 | static const int16_t cos8[] = { 8192, 7568, 5793, 3135 }; 593 | 594 | /* --- DCT of subbands samples --- 595 | * ___ 596 | * \ 597 | * u[k] = /__ h(k,i) * s(i) , i = [0;n-1] k = [0;2n-1] 598 | * i 599 | * 600 | * With n the number of subbands (4) 601 | * h(k,i) = cos( (i + 1/2) (k + n/2) pi/n ) 602 | * 603 | * Note : 604 | * 605 | * h( 2, i) = 0 et h( n-k,i) = -h(k,i) , k = [0;n/2-1] 606 | * h(12, i) = -1 et h(2n-k,i) = h(n+k,i) , k = [1;n/2-1] 607 | * 608 | * To assist the windowing step, the 2 halves are stored in 2 buffers. 609 | * After scaling of coefficients, the result is saturated on 16 bits. */ 610 | 611 | int16_t s03 = (in[0] + in[3]) >> 1, d03 = (in[0] - in[3]) >> 1; 612 | int16_t s12 = (in[1] + in[2]) >> 1, d12 = (in[1] - in[2]) >> 1; 613 | 614 | int a0 = ( (s03 - s12 ) * cos8[2] ); 615 | int b1 = (-(s03 + s12 ) ) << 13; 616 | int a1 = ( d03*cos8[3] - d12 * cos8[1] ); 617 | int b0 = (-d03*cos8[1] - d12 * cos8[3] ); 618 | 619 | int shr = 12 + scale; 620 | 621 | a0 = (a0 + (1 << (shr-1))) >> shr; b0 = (b0 + (1 << (shr-1))) >> shr; 622 | a1 = (a1 + (1 << (shr-1))) >> shr; b1 = (b1 + (1 << (shr-1))) >> shr; 623 | 624 | out0[0][idx] = SBC_SAT16( a0); out0[3][idx] = SBC_SAT16(-a1); 625 | out0[1][idx] = SBC_SAT16( a1); out0[2][idx] = SBC_SAT16( 0); 626 | 627 | out1[0][idx] = SBC_SAT16(-a0); out1[3][idx] = SBC_SAT16( b0); 628 | out1[1][idx] = SBC_SAT16( b0); out1[2][idx] = SBC_SAT16( b1); 629 | } 630 | 631 | /** 632 | * Perform a DCT on 8 samples 633 | * in Subbands input samples 634 | * scale Scale factor of input samples (-2 to 14) 635 | * out0 Output of 1st half samples 636 | * out1 Output of 2nd half samples 637 | * idx Index of transformed samples 638 | */ 639 | static inline void dct8(const int16_t *in, int scale, 640 | int16_t (*out0)[10], int16_t (*out1)[10], int idx) 641 | { 642 | /* cos(i*pi/16) for i = [0;7], in fixed 0.13 */ 643 | 644 | static const int16_t cos16[] = 645 | { 8192, 8035, 7568, 6811, 5793, 4551, 3135, 1598 }; 646 | 647 | /* --- DCT of subbands samples --- 648 | * ___ 649 | * \ 650 | * u[k] = /__ h(k,i) * s(i) , i = [0;n-1] k = [0;2n-1] 651 | * i 652 | * 653 | * With n the number of subbands (8) 654 | * h(k,i) = cos( (i + 1/2) (k + n/2) pi/n ) 655 | * 656 | * 657 | * 658 | * Note : 659 | * 660 | * h( 4, i) = 0 et h( n-k,i) = -h(k,i) , k = [0;n/2-1] 661 | * h(12, i) = -1 et h(2n-k,i) = h(n+k,i) , k = [1;n/2-1] 662 | * 663 | * To assist the windowing step, the 2 halves are stored in 2 buffers. 664 | * After scaling of coefficients, the result is saturated on 16 bits. */ 665 | 666 | int16_t s07 = (in[0] + in[7]) >> 1, d07 = (in[0] - in[7]) >> 1; 667 | int16_t s16 = (in[1] + in[6]) >> 1, d16 = (in[1] - in[6]) >> 1; 668 | int16_t s25 = (in[2] + in[5]) >> 1, d25 = (in[2] - in[5]) >> 1; 669 | int16_t s34 = (in[3] + in[4]) >> 1, d34 = (in[3] - in[4]) >> 1; 670 | 671 | int a0 = ( (s07 + s34) - (s25 + s16) ) * cos16[4]; 672 | int b3 = (-(s07 + s34) - (s25 + s16) ) << 13; 673 | int a2 = ( (s07 - s34) * cos16[6] + (s25 - s16) * cos16[2] ); 674 | int b1 = ( (s34 - s07) * cos16[2] + (s25 - s16) * cos16[6] ); 675 | int a1 = ( d07*cos16[5] - d16*cos16[1] + d25*cos16[7] + d34*cos16[3] ); 676 | int b2 = (-d07*cos16[1] - d16*cos16[3] - d25*cos16[5] - d34*cos16[7] ); 677 | int a3 = ( d07*cos16[7] - d16*cos16[5] + d25*cos16[3] - d34*cos16[1] ); 678 | int b0 = (-d07*cos16[3] + d16*cos16[7] + d25*cos16[1] + d34*cos16[5] ); 679 | 680 | int shr = 12 + scale; 681 | 682 | a0 = (a0 + (1 << (shr-1))) >> shr; b0 = (b0 + (1 << (shr-1))) >> shr; 683 | a1 = (a1 + (1 << (shr-1))) >> shr; b1 = (b1 + (1 << (shr-1))) >> shr; 684 | a2 = (a2 + (1 << (shr-1))) >> shr; b2 = (b2 + (1 << (shr-1))) >> shr; 685 | a3 = (a3 + (1 << (shr-1))) >> shr; b3 = (b3 + (1 << (shr-1))) >> shr; 686 | 687 | out0[0][idx] = SBC_SAT16( a0); out0[7][idx] = SBC_SAT16(-a1); 688 | out0[1][idx] = SBC_SAT16( a1); out0[6][idx] = SBC_SAT16(-a2); 689 | out0[2][idx] = SBC_SAT16( a2); out0[5][idx] = SBC_SAT16(-a3); 690 | out0[3][idx] = SBC_SAT16( a3); out0[4][idx] = SBC_SAT16( 0); 691 | 692 | out1[0][idx] = SBC_SAT16(-a0); out1[7][idx] = SBC_SAT16( b0); 693 | out1[1][idx] = SBC_SAT16( b0); out1[6][idx] = SBC_SAT16( b1); 694 | out1[2][idx] = SBC_SAT16( b1); out1[5][idx] = SBC_SAT16( b2); 695 | out1[3][idx] = SBC_SAT16( b2); out1[4][idx] = SBC_SAT16( b3); 696 | } 697 | 698 | /** 699 | * Apply window on reconstructed samples 700 | * in, n Reconstructed samples and number of subbands 701 | * window Window coefficients 702 | * offset Offset of coefficients for each samples 703 | * out Output adress of PCM samples 704 | * pitch Number of PCM samples between two consecutive 705 | */ 706 | static inline void apply_window(const int16_t (*in)[10], int n, 707 | const int16_t (*window)[2*10], int offset, int16_t *out, int pitch) 708 | { 709 | const int16_t *u = (const int16_t *)in; 710 | 711 | for (int i = 0; i < n; i++) { 712 | const int16_t *w = window[i] + offset; 713 | int s; 714 | 715 | s = *(u++) * *(w++); s += *(u++) * *(w++); 716 | s += *(u++) * *(w++); s += *(u++) * *(w++); 717 | s += *(u++) * *(w++); s += *(u++) * *(w++); 718 | s += *(u++) * *(w++); s += *(u++) * *(w++); 719 | s += *(u++) * *(w++); s += *(u++) * *(w++); 720 | 721 | *out = SBC_SAT16((s + (1 << 12)) >> 13); out += pitch; 722 | } 723 | } 724 | 725 | /** 726 | * Synthesize samples of a 4 subbands block 727 | * state Previous transformed samples of the channel 728 | * in Sub-band samples 729 | * scale Scale factor of samples 730 | * out Output adress of PCM samples 731 | * pitch Number of samples between two consecutive 732 | */ 733 | void sbc_synthesize_4_c(struct sbc_dstate *state, 734 | const int16_t *in, int scale, int16_t *out, int pitch) 735 | { 736 | /* --- Windowing coefficients (fixed 2.13) --- 737 | * 738 | * The table is duplicated and transposed to fit the circular 739 | * buffer of reconstructed samples */ 740 | 741 | static const int16_t window[4][2*10] = { 742 | { 0, -126, -358, -848, -4443, -9644, 4443, -848, 358, -126, 743 | 0, -126, -358, -848, -4443, -9644, 4443, -848, 358, -126 }, 744 | 745 | { -18, -128, -670, -201, -6389, -9235, 2544, -1055, 100, -90, 746 | -18, -128, -670, -201, -6389, -9235, 2544, -1055, 100, -90 }, 747 | 748 | { -49, -61, -946, 944, -8082, -8082, 944, -946, -61, -49, 749 | -49, -61, -946, 944, -8082, -8082, 944, -946, -61, -49 }, 750 | 751 | { -90, 100, -1055, 2544, -9235, -6389, -201, -670, -128, -18, 752 | -90, 100, -1055, 2544, -9235, -6389, -201, -670, -128, -18 } 753 | }; 754 | 755 | /* --- IDCT and windowing --- */ 756 | 757 | int dct_idx = state->idx ? 10 - state->idx : 0, odd = dct_idx & 1; 758 | 759 | dct4(in, scale, state->v[odd], state->v[!odd], dct_idx); 760 | apply_window(state->v[odd], 4, window, state->idx, out, pitch); 761 | 762 | state->idx = state->idx < 9 ? state->idx + 1 : 0; 763 | } 764 | 765 | /** 766 | * Synthesize samples of a 8 subbands block 767 | * state Previous transformed samples of the channel 768 | * sb_samples Sub-band samples 769 | * sb_scale Scale factor of samples (-2 to 14) 770 | * out Output adress of PCM samples 771 | * pitch Number of PCM samples between two consecutive 772 | */ 773 | void sbc_synthesize_8_c(struct sbc_dstate *state, 774 | const int16_t *in, int scale, int16_t *out, int pitch) 775 | { 776 | /* --- Windowing coefficients (fixed 2.13) --- 777 | * 778 | * The table is duplicated and transposed to fit the circular 779 | * buffer of reconstructed samples */ 780 | 781 | static const int16_t window[8][2*10] = { 782 | { 0, -132, -371, -848, -4456, -9631, 4456, -848, 371, -132, 783 | 0, -132, -371, -848, -4456, -9631, 4456, -848, 371, -132 }, 784 | 785 | { -10, -138, -526, -580, -5438, -9528, 3486, -1004, 229, -117, 786 | -10, -138, -526, -580, -5438, -9528, 3486, -1004, 229, -117 }, 787 | 788 | { -22, -131, -685, -192, -6395, -9224, 2561, -1063, 108, -97, 789 | -22, -131, -685, -192, -6395, -9224, 2561, -1063, 108, -97 }, 790 | 791 | { -36, -106, -835, 322, -7287, -8734, 1711, -1042, 12, -75, 792 | -36, -106, -835, 322, -7287, -8734, 1711, -1042, 12, -75 }, 793 | 794 | { -54, -59, -960, 959, -8078, -8078, 959, -960, -59, -54, 795 | -54, -59, -960, 959, -8078, -8078, 959, -960, -59, -54 }, 796 | 797 | { -75, 12, -1042, 1711, -8734, -7287, 322, -835, -106, -36, 798 | -75, 12, -1042, 1711, -8734, -7287, 322, -835, -106, -36 }, 799 | 800 | { -97, 108, -1063, 2561, -9224, -6395, -192, -685, -131, -22, 801 | -97, 108, -1063, 2561, -9224, -6395, -192, -685, -131, -22 }, 802 | 803 | { -117, 229, -1004, 3486, -9528, -5438, -580, -526, -138, -10, 804 | -117, 229, -1004, 3486, -9528, -5438, -580, -526, -138, -10 } 805 | }; 806 | 807 | /* --- IDCT and windowing --- */ 808 | 809 | int dct_idx = state->idx ? 10 - state->idx : 0, odd = dct_idx & 1; 810 | 811 | dct8(in, scale, state->v[odd], state->v[!odd], dct_idx); 812 | apply_window(state->v[odd], 8, window, state->idx, out, pitch); 813 | 814 | state->idx = state->idx < 9 ? state->idx + 1 : 0; 815 | } 816 | 817 | /** 818 | * Synthesize samples of a channel 819 | * state Previous transformed samples of the channel 820 | * nblocks Number of blocks (4, 8, 12 or 16) 821 | * nsubbands Number of subbands (4 or 8) 822 | * in Sub-band input samples 823 | * scale Scale factor of samples 824 | * out Output adress of PCM samples 825 | * pitch Number of PCM samples between two consecutive 826 | */ 827 | static inline void synthesize( 828 | struct sbc_dstate *state, int nblocks, int nsubbands, 829 | const int16_t *in, int scale, int16_t *out, int pitch) 830 | { 831 | for (int iblk = 0; iblk < nblocks; iblk++) { 832 | 833 | if (nsubbands == 4) 834 | ASM(sbc_synthesize_4)(state, in, scale, out, pitch); 835 | else 836 | ASM(sbc_synthesize_8)(state, in, scale, out, pitch); 837 | 838 | in += nsubbands; 839 | out += nsubbands * pitch; 840 | } 841 | } 842 | 843 | /** 844 | * Probe data and return frame description 845 | */ 846 | int sbc_probe(const void *data, struct sbc_frame *frame) 847 | { 848 | sbc_bits_t bits; 849 | 850 | sbc_setup_bits(&bits, SBC_BITS_READ, (void *)data, SBC_HEADER_SIZE); 851 | return !decode_header(&bits, frame, NULL) || 852 | sbc_bits_error(&bits) ? -1 : 0; 853 | } 854 | 855 | /** 856 | * Decode a frame 857 | */ 858 | int sbc_decode(struct sbc *sbc, 859 | const void *data, unsigned size, struct sbc_frame *frame, 860 | int16_t *pcml, int pitchl, int16_t *pcmr, int pitchr) 861 | { 862 | sbc_bits_t bits; 863 | int crc; 864 | 865 | /* --- Decode the frame header --- */ 866 | 867 | if (data) { 868 | 869 | if (size < SBC_HEADER_SIZE) 870 | return -1; 871 | 872 | sbc_setup_bits(&bits, SBC_BITS_READ, (void *)data, SBC_HEADER_SIZE); 873 | if (!decode_header(&bits, frame, &crc) || sbc_bits_error(&bits)) 874 | return -1; 875 | 876 | if (size < sbc_get_frame_size(frame) || 877 | compute_crc(frame, data, size) != crc) 878 | return -1; 879 | } 880 | 881 | /* --- Decode the frame data --- */ 882 | 883 | int16_t alignas(sizeof(int)) sb_samples[2][SBC_MAX_SAMPLES]; 884 | int sb_scale[2]; 885 | 886 | if (data) { 887 | 888 | sbc_setup_bits(&bits, SBC_BITS_READ, 889 | (void *)((uintptr_t)data + SBC_HEADER_SIZE), 890 | sbc_get_frame_size(frame) - SBC_HEADER_SIZE); 891 | 892 | decode_frame(&bits, frame, sb_samples, sb_scale); 893 | 894 | sbc->nchannels = 1 + (frame->mode != SBC_MODE_MONO); 895 | sbc->nblocks = frame->nblocks; 896 | sbc->nsubbands = frame->nsubbands; 897 | 898 | } else { 899 | 900 | int nsamples = sbc->nblocks * sbc->nsubbands; 901 | 902 | for (int ich = 0; ich < sbc->nchannels; ich++) { 903 | memset(sb_samples[ich], 0, nsamples * sizeof(int16_t)); 904 | sb_scale[ich] = 0; 905 | } 906 | } 907 | 908 | synthesize(&sbc->dstates[0], sbc->nblocks, sbc->nsubbands, 909 | sb_samples[0], sb_scale[0], pcml, pitchl); 910 | 911 | if (frame->mode != SBC_MODE_MONO) 912 | synthesize(&sbc->dstates[1], sbc->nblocks, sbc->nsubbands, 913 | sb_samples[1], sb_scale[1], pcmr, pitchr); 914 | 915 | return 0; 916 | } 917 | 918 | 919 | /* ---------------------------------------------------------------------------- 920 | * Encoding 921 | * ------------------------------------------------------------------------- */ 922 | 923 | /** 924 | * Compute the scale factors and joint-stereo mask from sub-band samples 925 | * frame Frame description 926 | * sb_samples Sub-band samples (fixed 17.14) 927 | * scale_factors Output of sub-bands scale-factors 928 | * mjoint Masque of joint sub-bands 929 | */ 930 | static void compute_scale_factors_js(const struct sbc_frame *frame, 931 | const int16_t (*sb_samples)[SBC_MAX_SAMPLES], 932 | int (*scale_factors)[SBC_MAX_SUBBANDS], unsigned *mjoint) 933 | { 934 | /* As long as coding L+R / 2, L-R / 2 result at smaller 935 | * scale-factors, the bands are joint. */ 936 | 937 | *mjoint = 0; 938 | 939 | for (int isb = 0; isb < frame->nsubbands; isb++) { 940 | unsigned m[2] = { }, mj[2] = { }; 941 | 942 | for (int iblk = 0; iblk < frame->nblocks; iblk++) { 943 | int s0 = sb_samples[0][iblk * frame->nsubbands + isb]; 944 | int s1 = sb_samples[1][iblk * frame->nsubbands + isb]; 945 | 946 | m[0] |= s0 < 0 ? ~s0 : s0; 947 | m[1] |= s1 < 0 ? ~s1 : s1; 948 | 949 | mj[0] |= s0 + s1 < 0 ? ~(s0 + s1) : s0 + s1; 950 | mj[1] |= s0 - s1 < 0 ? ~(s0 - s1) : s0 - s1; 951 | } 952 | 953 | int scf0 = m[0] ? (8*sizeof(unsigned) - 1) - SBC_CLZ(m[0]) : 0; 954 | int scf1 = m[1] ? (8*sizeof(unsigned) - 1) - SBC_CLZ(m[1]) : 0; 955 | 956 | int js0 = mj[0] ? (8*sizeof(unsigned) - 1) - SBC_CLZ(mj[0]) : 0; 957 | int js1 = mj[1] ? (8*sizeof(unsigned) - 1) - SBC_CLZ(mj[1]) : 0; 958 | 959 | if (isb < frame->nsubbands-1 && js0 + js1 < scf0 + scf1) { 960 | *mjoint |= 1 << isb; 961 | scf0 = js0, scf1 = js1; 962 | } 963 | 964 | scale_factors[0][isb] = scf0; 965 | scale_factors[1][isb] = scf1; 966 | } 967 | } 968 | 969 | /** 970 | * Compute the scale factors from sub-band samples 971 | * frame Frame description 972 | * sb_samples Sub-band samples 973 | * scale_factors Output of sub-bands scale-factors 974 | * mjoint Masque of joint sub-bands (Joint-Stereo mode) 975 | */ 976 | static void compute_scale_factors(const struct sbc_frame *frame, 977 | const int16_t (*sb_samples)[SBC_MAX_SAMPLES], 978 | int (*scale_factors)[SBC_MAX_SUBBANDS]) 979 | { 980 | for (int ich = 0; ich < 1 + (frame->mode != SBC_MODE_MONO); ich++) 981 | for (int isb = 0; isb < frame->nsubbands; isb++) { 982 | unsigned m = 0; 983 | 984 | for (int iblk = 0; iblk < frame->nblocks; iblk++) { 985 | int s = sb_samples[ich][iblk * frame->nsubbands + isb]; 986 | 987 | m |= s < 0 ? ~s : s; 988 | } 989 | 990 | int scf = m ? (8*sizeof(unsigned) - 1) - SBC_CLZ(m) : 0; 991 | scale_factors[ich][isb] = scf; 992 | } 993 | } 994 | 995 | /** 996 | * Encode the 4 bytes frame header 997 | * bits Bitstream writer 998 | * frame Frame description to encode 999 | */ 1000 | static void encode_header(sbc_bits_t *bits, const struct sbc_frame *frame) 1001 | { 1002 | static const int enc_freq[SBC_NUM_FREQ] = { 1003 | /* SBC_FREQ_16K */ 0, /* SBC_FREQ_32K */ 1, 1004 | /* SBC_FREQ_44K1 */ 2, /* SBC_FREQ_48K */ 3 1005 | }; 1006 | 1007 | static const int enc_mode[SBC_NUM_MODE] = { 1008 | /* SBC_MODE_MONO */ 0, /* SBC_MODE_DUAL_CHANNEL */ 1, 1009 | /* SBC_MODE_STEREO */ 2, /* SBC_MODE_JOINT_STEREO */ 3 }; 1010 | 1011 | static const int enc_bam[SBC_NUM_BAM] = { 1012 | /* SBC_BAM_LOUDNESS */ 0, /* SBC_BAM_SNR */ 1 }; 1013 | 1014 | /* Two possible headers : 1015 | * - Header, with syncword 0x9c (A2DP) 1016 | * - mSBC header, with syncword 0xad (HFP) */ 1017 | 1018 | SBC_WITH_BITS(bits); 1019 | 1020 | SBC_PUT_BITS("syncword", frame->msbc ? 0xad : 0x9c, 8); 1021 | 1022 | if (!frame->msbc) { 1023 | SBC_PUT_BITS("sampling_frequency", enc_freq[frame->freq], 2); 1024 | SBC_PUT_BITS("blocks", (frame->nblocks >> 2) - 1, 2); 1025 | SBC_PUT_BITS("channel_mode", enc_mode[frame->mode], 2); 1026 | SBC_PUT_BITS("allocation_method", enc_bam[frame->bam], 1); 1027 | SBC_PUT_BITS("subbands", (frame->nsubbands >> 2) - 1, 1); 1028 | SBC_PUT_BITS("bitpool", frame->bitpool, 8); 1029 | } else 1030 | SBC_PUT_BITS("reserved", 0, 16); 1031 | 1032 | SBC_PUT_BITS("crc_check", 0, 8); 1033 | 1034 | SBC_END_WITH_BITS(); 1035 | } 1036 | 1037 | /** 1038 | * Put the CRC of the frame 1039 | * frame Frame description 1040 | * data, size Frame data, and maximum writable size 1041 | * return 0: On success -1: size too small 1042 | */ 1043 | static int put_crc(const struct sbc_frame *frame, void *data, unsigned size) 1044 | { 1045 | int crc = compute_crc(frame, data, size); 1046 | return crc < 0 ? -1 : (((uint8_t *)data)[3] = crc), 0; 1047 | } 1048 | 1049 | /** 1050 | * Encode frame data 1051 | * bits Bitstream writer 1052 | * frame Frame description 1053 | * sb_samples Sub-band samples, by channels 1054 | */ 1055 | static void encode_frame(sbc_bits_t *bits, 1056 | const struct sbc_frame *frame, int16_t (*sb_samples)[SBC_MAX_SAMPLES] ) 1057 | { 1058 | SBC_WITH_BITS(bits); 1059 | 1060 | /* --- Compute Scale Factors --- */ 1061 | 1062 | int scale_factors[2][SBC_MAX_SUBBANDS]; 1063 | unsigned mjoint = 0; 1064 | 1065 | if (frame->mode == SBC_MODE_JOINT_STEREO) 1066 | compute_scale_factors_js(frame, sb_samples, scale_factors, &mjoint); 1067 | else 1068 | compute_scale_factors(frame, sb_samples, scale_factors); 1069 | 1070 | if (frame->mode == SBC_MODE_DUAL_CHANNEL) 1071 | compute_scale_factors(frame, sb_samples + 1, scale_factors + 1); 1072 | 1073 | /* --- Joint-Stereo mask --- */ 1074 | 1075 | if (frame->mode == SBC_MODE_JOINT_STEREO && frame->nsubbands == 4) 1076 | SBC_PUT_BITS("join[]", 1077 | ((mjoint & 0x01) << 3) | ((mjoint & 0x02) << 1) | 1078 | ((mjoint & 0x04) >> 1) | (( 0x00) >> 3) , 4); 1079 | 1080 | else if (frame->mode == SBC_MODE_JOINT_STEREO) 1081 | SBC_PUT_BITS("join[]", 1082 | ((mjoint & 0x01) << 7) | ((mjoint & 0x02) << 5) | 1083 | ((mjoint & 0x04) << 3) | ((mjoint & 0x08) << 1) | 1084 | ((mjoint & 0x10) >> 1) | ((mjoint & 0x20) >> 3) | 1085 | ((mjoint & 0x40) >> 5) | (( 0x00) >> 7) , 8); 1086 | 1087 | /* --- Encode Scale Factors --- */ 1088 | 1089 | int nchannels = 1 + (frame->mode != SBC_MODE_MONO); 1090 | int nsubbands = frame->nsubbands; 1091 | int nbits[2][SBC_MAX_SUBBANDS]; 1092 | 1093 | for (int ich = 0; ich < nchannels; ich++) 1094 | for (int isb = 0; isb < nsubbands; isb++) 1095 | SBC_PUT_BITS("scale_factor", scale_factors[ich][isb], 4); 1096 | 1097 | compute_nbits(frame, scale_factors, nbits); 1098 | if (frame->mode == SBC_MODE_DUAL_CHANNEL) 1099 | compute_nbits(frame, scale_factors + 1, nbits + 1); 1100 | 1101 | /* --- Coupling Joint-Stereo --- */ 1102 | 1103 | for (int isb = 0; isb < nsubbands; isb++) { 1104 | 1105 | if (((mjoint >> isb) & 1) == 0) 1106 | continue; 1107 | 1108 | for (int iblk = 0; iblk < frame->nblocks; iblk++) { 1109 | int16_t s0 = sb_samples[0][iblk*nsubbands + isb]; 1110 | int16_t s1 = sb_samples[1][iblk*nsubbands + isb]; 1111 | 1112 | sb_samples[0][iblk*nsubbands + isb] = (s0 + s1) >> 1; 1113 | sb_samples[1][iblk*nsubbands + isb] = (s0 - s1) >> 1; 1114 | } 1115 | } 1116 | 1117 | /* --- Quantization --- 1118 | * 1119 | * The quantization is given by : 1120 | * 1121 | * sb_sample 1122 | * sb_sample = ( ( ------------- + 1 ) (2^nbit - 1) ) >> 1 1123 | * 2^(scf + 1) 1124 | * 1125 | * The number of bits coding a sample is limited to 16 bits, 1126 | * thus the unquantized sub-bands samples cannot overflow */ 1127 | 1128 | for (int iblk = 0; iblk < frame->nblocks; iblk++) 1129 | for (int ich = 0; ich < nchannels; ich++) 1130 | for (int isb = 0; isb < nsubbands; isb++) { 1131 | int nbit = nbits[ich][isb]; 1132 | int scf = scale_factors[ich][isb]; 1133 | 1134 | if (!nbit) continue; 1135 | 1136 | int s = sb_samples[ich][iblk*nsubbands + isb] ; 1137 | int range = ~(UINT_MAX << nbit); 1138 | 1139 | SBC_PUT_BITS("audio_sample", 1140 | (((s * range) >> (scf + 1)) + range) >> 1, nbit); 1141 | } 1142 | 1143 | 1144 | /* --- Padding --- */ 1145 | 1146 | int padding_nbits = 8 - (sbc_tell_bits(bits) % 8); 1147 | SBC_PUT_BITS("padding_bits", 0, padding_nbits < 8 ? padding_nbits : 0); 1148 | 1149 | SBC_END_WITH_BITS(); 1150 | } 1151 | 1152 | /** 1153 | * Tranform 4 PCM samples into 4 sub-bands samples of a channel 1154 | * state Previous PCM samples of the channel 1155 | * in PCM input samples 1156 | * pitch Number of PCM samples betwwen two consecutive 1157 | * out Output address of sub-band samples 1158 | */ 1159 | static void analyze_4( 1160 | struct sbc_estate *state, const int16_t *in, int pitch, int16_t *out) 1161 | { 1162 | /* --- Windowing coefficients (fixed 2.13) --- 1163 | * 1164 | * The table is duplicated and transposed to fit the circular 1165 | * buffer of PCM samples, and DCT symmetry. */ 1166 | 1167 | static const int16_t window[2][4][5*2] = { 1168 | 1169 | { /* 0 1 2 3 4 0 1 2 3 4 */ 1170 | /* 0 */ { 0, 358, 4443,-4443, -358, 0, 358, 4443,-4443, -358 }, 1171 | /* 2 */ { 49, 946, 8082, -944, 61, 49, 946, 8082, -944, 61 }, 1172 | /* 1 */ { 18, 670, 6389,-2544, -100, 18, 670, 6389,-2544, -100 }, 1173 | /* 3 */ { 90, 1055, 9235, 201, 128, 90, 1055, 9235, 201, 128 }, 1174 | }, /* ---------------------------------------------------------- */ 1175 | 1176 | { /* 0 1 2 3 4 0 1 2 3 4 */ 1177 | /* 0 */ { 126, 848, 9644, 848, 126, 126, 848, 9644, 848, 126 }, 1178 | /* 2 */ { 61, -944, 8082, 946, 49, 61, -944, 8082, 946, 49 }, 1179 | /* 1 */ { 128, 201, 9235, 1055, 90, 128, 201, 9235, 1055, 90 }, 1180 | /* 3 */ { -100,-2544, 6389, 670, 18, -100,-2544, 6389, 670, 18 }, 1181 | }, /* ---------------------------------------------------------- */ 1182 | 1183 | }; 1184 | 1185 | /* --- Load PCM samples --- 1186 | * 1187 | * - To assist the windowing step, which is done by halves, 1188 | * the odd and even blocks of samples are separated 1189 | * 1190 | * - Rely on DCT symmetry : 1191 | * 1192 | * h(k,i) = cos( (i + 1/2) (k - n/2) pi/n ) , n = 4 1193 | * 1194 | * h( n-k,i) = h( k,i) , k = [0;n/2-1] 1195 | * h(2n-k,i) = -h(n+k,i) , k = [1;n/2-1] 1196 | * 1197 | * The "symmetric" samples are stored closer, thus we arite samples 1198 | * in the order : [ 0, 2, (1, 3) ] */ 1199 | 1200 | int idx = state->idx >> 1, odd = state->idx & 1; 1201 | 1202 | int16_t (*x)[5] = state->x[odd]; 1203 | int in_idx = idx ? 5 - idx : 0; 1204 | 1205 | x[0][in_idx] = in[(3-0) * pitch]; x[1][in_idx] = in[(3-2) * pitch]; 1206 | x[2][in_idx] = in[(3-1) * pitch]; x[3][in_idx] = in[(3-3) * pitch]; 1207 | 1208 | /* --- Process and window --- 1209 | * ___ 1210 | * \ 1211 | * y(i) = /__ x0[i + k*4] * w0[i + k*4] , i = [0;3] , k = [0;4] 1212 | * k 1213 | * ___ 1214 | * \ 1215 | * y(i) = /__ x1[i + k*4] * w1[i + k*4] , i = [4;7] , k = [0;4] 1216 | * k 1217 | * 1218 | * x0()/w0() Blcoks, windowing coefficients 1219 | * x1()/w1() Blocks, windowing coefficients with inverse 1220 | * parity, starting the previous block. 1221 | * 1222 | * Symmetry of cosinus function : 1223 | * 1224 | * h(0,i) = h(4,i) = +/- pi/4 , h(2,i) = 1 , h(6,i) = 0 1225 | * h(1,i) = h(3,i) , h( 5,i) = -h(7,i) 1226 | * 1227 | * Thus, we do : 1228 | * y'(0) = y(0) + y(4) y'(2) = y(5) - y(7) 1229 | * y'(1) = y(1) + y(3) y'(3) = y(2) */ 1230 | 1231 | const int16_t (*w0)[10] = (const int16_t (*)[10])(window[0][0] + idx); 1232 | const int16_t (*w1)[10] = (const int16_t (*)[10])(window[1][0] + idx); 1233 | int y0, y1, y2, y3; int16_t y[4]; 1234 | 1235 | y0 = x[0][0] * w0[0][0] + x[0][1] * w0[0][1] + 1236 | x[0][2] * w0[0][2] + x[0][3] * w0[0][3] + 1237 | x[0][4] * w0[0][4] + state->y[0]; 1238 | 1239 | state->y[0] = 1240 | x[0][0] * w1[0][0] + x[0][1] * w1[0][1] + 1241 | x[0][2] * w1[0][2] + x[0][3] * w1[0][3] + 1242 | x[0][4] * w1[0][4] ; 1243 | 1244 | y1 = x[2][0] * w0[2][0] + x[2][1] * w0[2][1] + 1245 | x[2][2] * w0[2][2] + x[2][3] * w0[2][3] + 1246 | x[2][4] * w0[2][4] + x[3][0] * w0[3][0] + 1247 | x[3][1] * w0[3][1] + x[3][2] * w0[3][2] + 1248 | x[3][3] * w0[3][3] + x[3][4] * w0[3][4] ; 1249 | 1250 | y2 = state->y[1]; 1251 | state->y[1] = 1252 | x[2][0] * w1[2][0] + x[2][1] * w1[2][1] + 1253 | x[2][2] * w1[2][2] + x[2][3] * w1[2][3] + 1254 | x[2][4] * w1[2][4] - x[3][0] * w1[3][0] - 1255 | x[3][1] * w1[3][1] - x[3][2] * w1[3][2] - 1256 | x[3][3] * w1[3][3] - x[3][4] * w1[3][4] ; 1257 | 1258 | y3 = x[1][0] * w0[1][0] + x[1][1] * w0[1][1] + 1259 | x[1][2] * w0[1][2] + x[1][3] * w0[1][3] + 1260 | x[1][4] * w0[1][4] ; 1261 | 1262 | y[0] = SBC_SAT16((y0 + (1 << 14)) >> 15); 1263 | y[1] = SBC_SAT16((y1 + (1 << 14)) >> 15); 1264 | y[2] = SBC_SAT16((y2 + (1 << 14)) >> 15); 1265 | y[3] = SBC_SAT16((y3 + (1 << 14)) >> 15); 1266 | 1267 | state->idx = state->idx < 9 ? state->idx + 1 : 0; 1268 | 1269 | /* --- Output subbands coefficients --- 1270 | * 1271 | * With H(k,i) = sign(x(k,i)) cos(abs(x(k,i)) * pi/8), 1272 | * x(i,k) = 1273 | * 1274 | * k\i | 0 1 2 3 1275 | * -----|---------------- 1276 | * 0 | 2 -2 -2 2 = h(0,i) = h(4,i) 1277 | * 1 | 1 3 -3 -1 = h(1,i) = h(3,i) 1278 | * 2 | 3 -1 1 -3 = h(5,i) = -h(7,i) 1279 | * 3 | 0 0 0 0 = h(2,i) 1280 | * 1281 | * h(k,i) = cos( (i + 1/2) (k - 4/2) pi/8 ) */ 1282 | 1283 | static const int16_t cos8[4] = { 8192, 7568, 5793, 3135 }; 1284 | int s0, s1, s2, s3; 1285 | 1286 | s0 = y[0] * cos8[2] + y[1] * cos8[1] + y[2] * cos8[3] + (y[3] << 13); 1287 | s1 = -y[0] * cos8[2] + y[1] * cos8[3] - y[2] * cos8[1] + (y[3] << 13); 1288 | s2 = -y[0] * cos8[2] - y[1] * cos8[3] + y[2] * cos8[1] + (y[3] << 13); 1289 | s3 = y[0] * cos8[2] - y[1] * cos8[1] - y[2] * cos8[3] + (y[3] << 13); 1290 | 1291 | *(out++) = SBC_SAT16((s0 + (1 << 12)) >> 13); 1292 | *(out++) = SBC_SAT16((s1 + (1 << 12)) >> 13); 1293 | *(out++) = SBC_SAT16((s2 + (1 << 12)) >> 13); 1294 | *(out++) = SBC_SAT16((s3 + (1 << 12)) >> 13); 1295 | } 1296 | 1297 | /** 1298 | * Tranform 8 PCM samples into 8 sub-bands samples of a channel 1299 | * state Previous PCM samples of the channel 1300 | * in PCM input samples 1301 | * pitch Number of PCM samples betwwen two consecutive 1302 | * out Output address of sub-band samples 1303 | */ 1304 | static void analyze_8( 1305 | struct sbc_estate *state, const int16_t *in, int pitch, int16_t *out) 1306 | { 1307 | /* --- Windowing coefficients (fixed 2.13) --- 1308 | * 1309 | * The table is transposed and "scrambled" to fit the circular 1310 | * buffer of PCM samples, and DCT symmetry. */ 1311 | 1312 | static const int16_t window[2][8][5*2] = { 1313 | 1314 | { /* 0 1 2 3 4 0 1 2 3 4 */ 1315 | /* 0 */ { 0, 185, 2228,-2228, -185, 0, 185, 2228,-2228, -185 }, 1316 | /* 4 */ { 27, 480, 4039, -480, 30, 27, 480, 4039, -480, 30 }, 1317 | /* 1 */ { 5, 263, 2719,-1743, -115, 5, 263, 2719,-1743, -115 }, 1318 | /* 7 */ { 58, 502, 4764, 290, 69, 58, 502, 4764, 290, 69 }, 1319 | /* 2 */ { 11, 343, 3197,-1280, -54, 11, 343, 3197,-1280, -54 }, 1320 | /* 6 */ { 48, 532, 4612, 96, 65, 48, 532, 4612, 96, 65 }, 1321 | /* 3 */ { 18, 418, 3644, -856, -6, 18, 418, 3644, -856, -6 }, 1322 | /* 5 */ { 37, 521, 4367, -161, 53, 37, 521, 4367, -161, 53 }, 1323 | }, /* ---------------------------------------------------------- */ 1324 | 1325 | { /* 0 1 2 3 4 0 1 2 3 4 */ 1326 | /* 0 */ { 66, 424, 4815, 424, 66, 66, 424, 4815, 424, 66 }, 1327 | /* 4 */ { 30, -480, 4039, 480, 27, 30, -480, 4039, 480, 27 }, 1328 | /* 1 */ { 69, 290, 4764, 502, 58, 69, 290, 4764, 502, 58 }, 1329 | /* 7 */ { -115,-1743, 2719, 263, 5, -115,-1743, 2719, 263, 5 }, 1330 | /* 2 */ { 65, 96, 4612, 532, 48, 65, 96, 4612, 532, 48 }, 1331 | /* 6 */ { -54,-1280, 3197, 343, 11, -54,-1280, 3197, 343, 11 }, 1332 | /* 3 */ { 53, -161, 4367, 521, 37, 53, -161, 4367, 521, 37 }, 1333 | /* 5 */ { -6, -856, 3644, 418, 18, -6, -856, 3644, 418, 18 }, 1334 | }, /* ---------------------------------------------------------- */ 1335 | 1336 | }; 1337 | 1338 | /* --- Load PCM samples --- 1339 | * 1340 | * - To assist the windowing step, which is done by halves, 1341 | * the odd and even blocks of samples are separated 1342 | * 1343 | * - Rely on DCT symmetry : 1344 | * 1345 | * h(k,i) = cos( (i + 1/2) (k - n/2) pi/n ) , n = 8 1346 | * 1347 | * h( n-k,i) = h( k,i) , k = [0;n/2-1] 1348 | * h(2n-k,i) = -h(n+k,i) , k = [1;n/2-1] 1349 | * 1350 | * The "symmetric" samples are stored closer, thus we arite samples 1351 | * in the order : [ 0, 4, (1, 7), (2, 6), (3, 5) ] */ 1352 | 1353 | int idx = state->idx >> 1, odd = state->idx & 1; 1354 | 1355 | int16_t (*x)[5] = state->x[odd]; 1356 | int in_idx = idx ? 5 - idx : 0; 1357 | 1358 | x[0][in_idx] = in[(7-0) * pitch]; x[1][in_idx] = in[(7-4) * pitch]; 1359 | x[2][in_idx] = in[(7-1) * pitch]; x[3][in_idx] = in[(7-7) * pitch]; 1360 | x[4][in_idx] = in[(7-2) * pitch]; x[5][in_idx] = in[(7-6) * pitch]; 1361 | x[6][in_idx] = in[(7-3) * pitch]; x[7][in_idx] = in[(7-5) * pitch]; 1362 | 1363 | /* --- Process and window --- 1364 | * ___ 1365 | * \ 1366 | * y(i) = /__ x0[i + k*8] * w0[i + k*8] , i = [0; 7] , k = [0;4] 1367 | * k 1368 | * ___ 1369 | * \ 1370 | * y(i) = /__ x1[i + k*8] * w1[i + k*8] , i = [8;15] , k = [0;4] 1371 | * k 1372 | * 1373 | * x0()/w0() Blocks, windowing coefficients 1374 | * x1()/w1() Blocks, windowing coefficients with inverse 1375 | * parity, starting the previous block. 1376 | * 1377 | * Symmetry of cosinus function : 1378 | * 1379 | * h( 0,i) = h( 8,i) = +/- pi/4 , h( 4,i) = 1 , h(12,i) = 0 1380 | * h( 1,i) = h( 7,i) , h( 2,i) = h( 6,i) , h( 3,i) = h( 5,i) 1381 | * h( 9,i) = -h(15,i) , h(10,i) = -h(14,i) , h(12,i) = -h(13,i) 1382 | * 1383 | * Thus, we do : 1384 | * y'(0) = y(0) + y(8) y'(4) = y( 9) - y(15) 1385 | * y'(1) = y(1) + y(7) y'(5) = y(10) - y(14) 1386 | * y'(2) = y(2) + y(6) y'(6) = y(11) - y(13) 1387 | * y'(3) = y(3) + y(5) y'(7) = y( 4) */ 1388 | 1389 | const int16_t (*w0)[10] = (const int16_t (*)[10])(window[0][0] + idx); 1390 | const int16_t (*w1)[10] = (const int16_t (*)[10])(window[1][0] + idx); 1391 | int y0, y1, y2, y3, y4, y5, y6, y7; int16_t y[8]; 1392 | 1393 | y0 = x[0][0] * w0[0][0] + x[0][1] * w0[0][1] + 1394 | x[0][2] * w0[0][2] + x[0][3] * w0[0][3] + 1395 | x[0][4] * w0[0][4] + state->y[0]; 1396 | 1397 | state->y[0] = 1398 | x[0][0] * w1[0][0] + x[0][1] * w1[0][1] + 1399 | x[0][2] * w1[0][2] + x[0][3] * w1[0][3] + 1400 | x[0][4] * w1[0][4] ; 1401 | 1402 | y1 = x[2][0] * w0[2][0] + x[2][1] * w0[2][1] + 1403 | x[2][2] * w0[2][2] + x[2][3] * w0[2][3] + 1404 | x[2][4] * w0[2][4] + x[3][0] * w0[3][0] + 1405 | x[3][1] * w0[3][1] + x[3][2] * w0[3][2] + 1406 | x[3][3] * w0[3][3] + x[3][4] * w0[3][4] ; 1407 | 1408 | y4 = state->y[1]; 1409 | state->y[1] = 1410 | x[2][0] * w1[2][0] + x[2][1] * w1[2][1] + 1411 | x[2][2] * w1[2][2] + x[2][3] * w1[2][3] + 1412 | x[2][4] * w1[2][4] - x[3][0] * w1[3][0] - 1413 | x[3][1] * w1[3][1] - x[3][2] * w1[3][2] - 1414 | x[3][3] * w1[3][3] - x[3][4] * w1[3][4] ; 1415 | 1416 | y2 = x[4][0] * w0[4][0] + x[4][1] * w0[4][1] + 1417 | x[4][2] * w0[4][2] + x[4][3] * w0[4][3] + 1418 | x[4][4] * w0[4][4] + x[5][0] * w0[5][0] + 1419 | x[5][1] * w0[5][1] + x[5][2] * w0[5][2] + 1420 | x[5][3] * w0[5][3] + x[5][4] * w0[5][4] ; 1421 | 1422 | y5 = state->y[2]; 1423 | state->y[2] = 1424 | x[4][0] * w1[4][0] + x[4][1] * w1[4][1] + 1425 | x[4][2] * w1[4][2] + x[4][3] * w1[4][3] + 1426 | x[4][4] * w1[4][4] - x[5][0] * w1[5][0] - 1427 | x[5][1] * w1[5][1] - x[5][2] * w1[5][2] - 1428 | x[5][3] * w1[5][3] - x[5][4] * w1[5][4] ; 1429 | 1430 | y3 = x[6][0] * w0[6][0] + x[6][1] * w0[6][1] + 1431 | x[6][2] * w0[6][2] + x[6][3] * w0[6][3] + 1432 | x[6][4] * w0[6][4] + x[7][0] * w0[7][0] + 1433 | x[7][1] * w0[7][1] + x[7][2] * w0[7][2] + 1434 | x[7][3] * w0[7][3] + x[7][4] * w0[7][4] ; 1435 | 1436 | y6 = state->y[3]; 1437 | state->y[3] = 1438 | x[6][0] * w1[6][0] + x[6][1] * w1[6][1] + 1439 | x[6][2] * w1[6][2] + x[6][3] * w1[6][3] + 1440 | x[6][4] * w1[6][4] - x[7][0] * w1[7][0] - 1441 | x[7][1] * w1[7][1] - x[7][2] * w1[7][2] - 1442 | x[7][3] * w1[7][3] - x[7][4] * w1[7][4] ; 1443 | 1444 | y7 = x[1][0] * w0[1][0] + x[1][1] * w0[1][1] + 1445 | x[1][2] * w0[1][2] + x[1][3] * w0[1][3] + 1446 | x[1][4] * w0[1][4] ; 1447 | 1448 | y[0] = SBC_SAT16((y0 + (1 << 14)) >> 15); 1449 | y[1] = SBC_SAT16((y1 + (1 << 14)) >> 15); 1450 | y[2] = SBC_SAT16((y2 + (1 << 14)) >> 15); 1451 | y[3] = SBC_SAT16((y3 + (1 << 14)) >> 15); 1452 | y[4] = SBC_SAT16((y4 + (1 << 14)) >> 15); 1453 | y[5] = SBC_SAT16((y5 + (1 << 14)) >> 15); 1454 | y[6] = SBC_SAT16((y6 + (1 << 14)) >> 15); 1455 | y[7] = SBC_SAT16((y7 + (1 << 14)) >> 15); 1456 | 1457 | state->idx = state->idx < 9 ? state->idx + 1 : 0; 1458 | 1459 | /* --- Output subbands coefficients --- 1460 | * 1461 | * With H(k,i) = sign(x(k,i)) cos(abs(x(k,i)) * pi/16), 1462 | * x(i,k) = 1463 | * 1464 | * k\i | 0 1 2 3 4 5 6 7 1465 | * -----|-------------------------------- 1466 | * 0 | 4 -4 -4 4 4 -4 -4 4 = h( 0,i) = h( 8,i) 1467 | * 1 | 3 -7 -1 -5 5 1 7 -3 = h( 1,i) = h( 7,i) 1468 | * 2 | 2 6 -6 -2 -2 -6 6 2 = h( 2,i) = h( 6,i) 1469 | * 3 | 1 3 5 7 -7 -5 -3 -1 = h( 3,i) = h( 5,i) 1470 | * | 1471 | * 4 | 5 -1 7 3 -3 -7 1 -5 = h( 9,i) = -h(15,i) 1472 | * 5 | 6 -2 2 -6 -6 2 -2 6 = h(10,i) = -h(14,i) 1473 | * 6 | 7 -5 3 -1 1 -3 5 -7 = h(11,i) = -h(13,i) 1474 | * 7 | 0 0 0 0 0 0 0 0 = h( 4,i) 1475 | * 1476 | * h(k,i) = cos( (i + 1/2) (k - 8/2) pi/8 ) */ 1477 | 1478 | static const int16_t cosmat[8][8] = { 1479 | /* 0 */ { 5793, 6811, 7568, 8035, 4551, 3135, 1598, 8192 }, 1480 | /* 1 */ { -5793, -1598, 3135, 6811, -8035, -7568, -4551, 8192 }, 1481 | /* 2 */ { -5793, -8035, -3135, 4551, 1598, 7568, 6811, 8192 }, 1482 | /* 3 */ { 5793, -4551, -7568, 1598, 6811, -3135, -8035, 8192 }, 1483 | /* 4 */ { 5793, 4551, -7568, -1598, -6811, -3135, 8035, 8192 }, 1484 | /* 5 */ { -5793, 8035, -3135, -4551, -1598, 7568, -6811, 8192 }, 1485 | /* 6 */ { -5793, 1598, 3135, -6811, 8035, -7568, 4551, 8192 }, 1486 | /* 7 */ { 5793, -6811, 7568, -8035, -4551, 3135, -1598, 8192 }, 1487 | }; 1488 | 1489 | for (int i = 0; i < 8; i++) { 1490 | int s = y[0] * cosmat[i][0] + y[1] * cosmat[i][1] + 1491 | y[2] * cosmat[i][2] + y[3] * cosmat[i][3] + 1492 | y[4] * cosmat[i][4] + y[5] * cosmat[i][5] + 1493 | y[6] * cosmat[i][6] + y[7] * cosmat[i][7] ; 1494 | *(out++) = SBC_SAT16((s + (1 << 12)) >> 13); 1495 | } 1496 | } 1497 | 1498 | /** 1499 | * Tranform PCM samples into sub-bands samples of a channel 1500 | * state Previous PCM samples of the channel 1501 | * frame Frame description 1502 | * in PCM input samples 1503 | * pitch Number of samples between two consecutive 1504 | * out Sub-band samples 1505 | */ 1506 | static inline void analyze(struct sbc_estate *state, 1507 | const struct sbc_frame *frame, const int16_t *in, int pitch, int16_t *out) 1508 | { 1509 | for (int iblk = 0; iblk < frame->nblocks; iblk++) { 1510 | 1511 | if (frame->nsubbands == 4) 1512 | analyze_4(state, in, pitch, out); 1513 | else 1514 | analyze_8(state, in, pitch, out); 1515 | 1516 | in += frame->nsubbands * pitch; 1517 | out += frame->nsubbands; 1518 | } 1519 | } 1520 | 1521 | /** 1522 | * Encode a frame 1523 | */ 1524 | int sbc_encode(struct sbc *sbc, 1525 | const int16_t *pcml, int pitchl, const int16_t *pcmr, int pitchr, 1526 | const struct sbc_frame *frame, void *data, unsigned size) 1527 | { 1528 | /* --- Override configuration on mSBC signaling --- */ 1529 | 1530 | if (frame->msbc) 1531 | frame = &msbc_frame; 1532 | 1533 | /* --- Check the given frame description --- */ 1534 | 1535 | if (!check_frame(frame) || size < sbc_get_frame_size(frame)) 1536 | return -1; 1537 | 1538 | /* -- Analyse PCM samples --- */ 1539 | 1540 | int16_t alignas(sizeof(int)) sb_samples[2][SBC_MAX_SAMPLES]; 1541 | 1542 | analyze(&sbc->estates[0], frame, pcml, pitchl, sb_samples[0]); 1543 | if (frame->mode != SBC_MODE_MONO) 1544 | analyze(&sbc->estates[1], frame, pcmr, pitchr, sb_samples[1]); 1545 | 1546 | /* --- Encode the frame --- */ 1547 | 1548 | sbc_bits_t bits; 1549 | 1550 | sbc_setup_bits(&bits, SBC_BITS_WRITE, 1551 | (void *)((uintptr_t)data + SBC_HEADER_SIZE), 1552 | sbc_get_frame_size(frame) - SBC_HEADER_SIZE); 1553 | encode_frame(&bits, frame, sb_samples); 1554 | sbc_flush_bits(&bits); 1555 | 1556 | sbc_setup_bits(&bits, SBC_BITS_WRITE, data, SBC_HEADER_SIZE); 1557 | encode_header(&bits, frame); 1558 | sbc_flush_bits(&bits); 1559 | 1560 | put_crc(frame, data, size); 1561 | 1562 | return 0; 1563 | } 1564 | -------------------------------------------------------------------------------- /tools/dsbc.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include "wave.h" 27 | 28 | 29 | /** 30 | * Error handling 31 | */ 32 | 33 | static void error(int status, const char *format, ...) 34 | { 35 | va_list args; 36 | 37 | fflush(stdout); 38 | 39 | va_start(args, format); 40 | vfprintf(stderr, format, args); 41 | va_end(args); 42 | 43 | fprintf(stderr, status ? ": %s\n" : "\n", strerror(status)); 44 | exit(status); 45 | } 46 | 47 | 48 | /** 49 | * Parameters 50 | */ 51 | 52 | struct parameters { 53 | const char *fname_in; 54 | const char *fname_out; 55 | }; 56 | 57 | static struct parameters parse_args(int argc, char *argv[]) 58 | { 59 | static const char *usage = 60 | "Usage: %s [in_file] [wav_file]\n" 61 | "\n" 62 | "wav_file\t" "Input wave file, stdin if omitted\n" 63 | "out_file\t" "Output bitstream file, stdout if omitted\n" 64 | "\n" 65 | "Options:\n" 66 | "\t-h\t" "Display help\n" 67 | "\n"; 68 | 69 | struct parameters p = { }; 70 | 71 | for (int iarg = 1; iarg < argc; ) { 72 | const char *arg = argv[iarg++]; 73 | 74 | if (arg[0] == '-') { 75 | if (arg[2] != '\0') 76 | error(EINVAL, "Option %s", arg); 77 | 78 | char opt = arg[1]; 79 | 80 | switch (opt) { 81 | case 'h': fprintf(stderr, usage, argv[0]); exit(0); 82 | default: 83 | error(EINVAL, "Option %s", arg); 84 | } 85 | 86 | } else { 87 | 88 | if (!p.fname_in) 89 | p.fname_in = arg; 90 | else if (!p.fname_out) 91 | p.fname_out = arg; 92 | else 93 | error(EINVAL, "Argument %s", arg); 94 | } 95 | } 96 | 97 | return p; 98 | } 99 | 100 | 101 | /** 102 | * Entry point 103 | */ 104 | int main(int argc, char *argv[]) 105 | { 106 | /* --- Read parameters --- */ 107 | 108 | struct parameters p = parse_args(argc, argv); 109 | FILE *fp_in = stdin, *fp_out = stdout; 110 | 111 | if (p.fname_in && (fp_in = fopen(p.fname_in, "rb")) == NULL) 112 | error(errno, "%s", p.fname_in); 113 | 114 | if (p.fname_out && (fp_out = fopen(p.fname_out, "wb")) == NULL) 115 | error(errno, "%s", p.fname_out); 116 | 117 | /* --- Setup decoding --- */ 118 | 119 | static const char *sbc_mode_str[] = { 120 | [SBC_MODE_MONO ] = "Mono", 121 | [SBC_MODE_DUAL_CHANNEL] = "Dual-Channel", 122 | [SBC_MODE_STEREO ] = "Stereo", 123 | [SBC_MODE_JOINT_STEREO] = "Joint-Stereo" 124 | }; 125 | 126 | uint8_t data[2*SBC_MAX_SAMPLES*sizeof(int16_t)]; 127 | int16_t pcm[2*SBC_MAX_SAMPLES]; 128 | struct sbc_frame frame; 129 | sbc_t sbc; 130 | 131 | if (fread(data, SBC_PROBE_SIZE, 1, fp_in) < 1 132 | || sbc_probe(data, &frame) < 0) 133 | error(EINVAL, "SBC input file format"); 134 | 135 | int srate_hz = sbc_get_freq_hz(frame.freq); 136 | 137 | fprintf(stderr, "%s %d Hz -- %.1f kbps (bitpool %d)" 138 | " -- %d blocks, %d subbands\n", 139 | sbc_mode_str[frame.mode], srate_hz, 140 | sbc_get_frame_bitrate(&frame) * 1e-3, frame.bitpool, 141 | frame.nblocks, frame.nsubbands); 142 | 143 | int nch = 1 + (frame.mode != SBC_MODE_MONO); 144 | 145 | wave_write_header(fp_out, 16, sizeof(*pcm), 146 | sbc_get_freq_hz(frame.freq), nch, -1); 147 | 148 | sbc_reset(&sbc); 149 | 150 | /* --- Decoding loop --- */ 151 | 152 | for (int i = 0; i == 0 || (fread(data, SBC_PROBE_SIZE, 1, fp_in) >= 1 153 | && sbc_probe(data, &frame) == 0); i++) { 154 | 155 | if (fread(data + SBC_PROBE_SIZE, 156 | sbc_get_frame_size(&frame) - SBC_PROBE_SIZE, 1, fp_in) < 1) 157 | break; 158 | 159 | sbc_decode(&sbc, data, sizeof(data), 160 | &frame, pcm + 0, nch, pcm + 1, 2); 161 | 162 | int npcm = frame.nblocks * frame.nsubbands; 163 | wave_write_pcm(fp_out, sizeof(*pcm), pcm, nch, 0, npcm); 164 | } 165 | 166 | /* --- Cleanup --- */ 167 | 168 | if (fp_in != stdin) 169 | fclose(fp_in); 170 | 171 | if (fp_out != stdout) 172 | fclose(fp_out); 173 | } 174 | -------------------------------------------------------------------------------- /tools/esbc.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include "wave.h" 27 | 28 | 29 | /** 30 | * Error handling 31 | */ 32 | 33 | static void error(int status, const char *format, ...) 34 | { 35 | va_list args; 36 | 37 | fflush(stdout); 38 | 39 | va_start(args, format); 40 | vfprintf(stderr, format, args); 41 | va_end(args); 42 | 43 | fprintf(stderr, status ? ": %s\n" : "\n", strerror(status)); 44 | exit(status); 45 | } 46 | 47 | 48 | /** 49 | * Parameters 50 | */ 51 | 52 | struct parameters { 53 | const char *fname_in; 54 | const char *fname_out; 55 | struct sbc_frame frame; 56 | }; 57 | 58 | static struct parameters parse_args(int argc, char *argv[]) 59 | { 60 | static const char *usage = 61 | "Usage: %s [in_file] [wav_file]\n" 62 | "\n" 63 | "wav_file\t" "Input wave file, stdin if omitted\n" 64 | "out_file\t" "Output bitstream file, stdout if omitted\n" 65 | "\n" 66 | "Options:\n" 67 | "\t-h\t" "Display help\n" 68 | "\t-d\t" "Dual channel mode\n" 69 | "\t-j\t" "Joint Stereo mode\n" 70 | "\t-b \t" "Bitpool value (default is 35)\n" 71 | "\t-s \t" "Number of subbands (default is 8)\n" 72 | "\t-B \t" "Number of blocks (default is 16)\n" 73 | "\t-S\t" "Use SNR bit allocation (default is Loudness)\n" 74 | "\n"; 75 | 76 | struct parameters p = { }; 77 | struct sbc_frame *frame = &p.frame; 78 | 79 | *frame = (struct sbc_frame){ 80 | .mode = SBC_MODE_STEREO, 81 | .nsubbands = 8, .nblocks = 16, 82 | .bam = SBC_BAM_LOUDNESS, 83 | .bitpool = 35 84 | }; 85 | 86 | for (int iarg = 1; iarg < argc; ) { 87 | const char *arg = argv[iarg++]; 88 | 89 | if (arg[0] == '-') { 90 | if (arg[2] != '\0') 91 | error(EINVAL, "Option %s", arg); 92 | 93 | char opt = arg[1]; 94 | const char *optarg; 95 | 96 | switch (opt) { 97 | case 'b': case 's': case 'B': 98 | if (iarg >= argc) 99 | error(EINVAL, "Argument %s", arg); 100 | optarg = argv[iarg++]; 101 | } 102 | 103 | switch (opt) { 104 | case 'h': fprintf(stderr, usage, argv[0]); exit(0); 105 | case 'j': frame->mode = SBC_MODE_JOINT_STEREO; break; 106 | case 'd': frame->mode = SBC_MODE_DUAL_CHANNEL; break; 107 | case 'b': frame->bitpool = atoi(optarg); break; 108 | case 's': frame->nsubbands = atoi(optarg); break; 109 | case 'B': frame->nblocks = atoi(optarg); break; 110 | case 'S': frame->bam = SBC_BAM_SNR; break; 111 | default: 112 | error(EINVAL, "Option %s", arg); 113 | } 114 | 115 | } else { 116 | 117 | if (!p.fname_in) 118 | p.fname_in = arg; 119 | else if (!p.fname_out) 120 | p.fname_out = arg; 121 | else 122 | error(EINVAL, "Argument %s", arg); 123 | } 124 | } 125 | 126 | return p; 127 | } 128 | 129 | 130 | /** 131 | * Entry point 132 | */ 133 | int main(int argc, char *argv[]) 134 | { 135 | /* --- Read parameters --- */ 136 | 137 | struct parameters p = parse_args(argc, argv); 138 | struct sbc_frame *frame = &p.frame; 139 | FILE *fp_in = stdin, *fp_out = stdout; 140 | 141 | if (p.fname_in && (fp_in = fopen(p.fname_in, "rb")) == NULL) 142 | error(errno, "%s", p.fname_in); 143 | 144 | if (p.fname_out && (fp_out = fopen(p.fname_out, "wb")) == NULL) 145 | error(errno, "%s", p.fname_out); 146 | 147 | /* --- Check parameters --- */ 148 | 149 | int srate_hz, nch, nsamples; 150 | int pcm_sbits, pcm_sbytes; 151 | 152 | if (wave_read_header(fp_in, 153 | &pcm_sbits, &pcm_sbytes, &srate_hz, &nch, &nsamples) < 0) 154 | error(EINVAL, "Bad or unsupported WAVE input file"); 155 | 156 | frame->freq = srate_hz == 16000 ? SBC_FREQ_16K : 157 | srate_hz == 32000 ? SBC_FREQ_32K : 158 | srate_hz == 44100 ? SBC_FREQ_44K1 : 159 | srate_hz == 48000 ? SBC_FREQ_48K : SBC_NUM_FREQ; 160 | 161 | if (nch == 1) 162 | frame->mode = SBC_MODE_MONO; 163 | 164 | if (frame->freq >= SBC_NUM_FREQ) 165 | error(EINVAL, "Samplerate %d Hz", srate_hz); 166 | 167 | if (pcm_sbits != 16 || pcm_sbytes != sizeof(int16_t)) 168 | error(EINVAL, "Bitdepth %d", pcm_sbits); 169 | 170 | if (nch < 1 || nch > 2) 171 | error(EINVAL, "Number of channels %d", nch); 172 | 173 | /* --- Setup decoding --- */ 174 | 175 | uint8_t data[2*SBC_MAX_SAMPLES*sizeof(int16_t)]; 176 | int16_t pcm[2*SBC_MAX_SAMPLES]; 177 | sbc_t sbc; 178 | 179 | int npcm = frame->nblocks * frame->nsubbands; 180 | 181 | sbc_reset(&sbc); 182 | 183 | /* --- Encoding loop --- */ 184 | 185 | for (int i = 0; wave_read_pcm(fp_in, 186 | pcm_sbytes, nch, npcm, pcm) >= npcm; i++) { 187 | 188 | sbc_encode(&sbc, 189 | pcm + 0, nch, pcm + 1, 2, frame, data, sizeof(data)); 190 | 191 | fwrite(data, sbc_get_frame_size(frame), 1, fp_out); 192 | } 193 | 194 | /* --- Cleanup --- */ 195 | 196 | if (fp_in != stdin) 197 | fclose(fp_in); 198 | 199 | if (fp_out != stdout) 200 | fclose(fp_out); 201 | } 202 | -------------------------------------------------------------------------------- /tools/makefile.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at: 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | TOOLS_DIR = tools 18 | 19 | 20 | esbc_src += \ 21 | $(TOOLS_DIR)/esbc.c \ 22 | $(TOOLS_DIR)/wave.c 23 | 24 | esbc_lib += libsbc 25 | esbc_ldlibs += m 26 | 27 | $(eval $(call add-bin,esbc)) 28 | 29 | 30 | dsbc_src += \ 31 | $(TOOLS_DIR)/dsbc.c \ 32 | $(TOOLS_DIR)/wave.c 33 | 34 | dsbc_lib += libsbc 35 | dsbc_ldlibs += m 36 | 37 | $(eval $(call add-bin,dsbc)) 38 | 39 | 40 | .PHONY: tools 41 | tools: esbc dsbc 42 | -------------------------------------------------------------------------------- /tools/wave.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include "wave.h" 22 | 23 | 24 | /** 25 | * Id formatting 26 | */ 27 | 28 | #define __WAVE_ID(s) \ 29 | (uint32_t)( s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) ) 30 | 31 | 32 | /** 33 | * File format statement 34 | * | type_id WAVE_FILE_TYPE_ID 35 | * | size File size - 8 bytes 36 | * | type_id WAVE_FILE_FMT_ID 37 | */ 38 | 39 | #define WAVE_FILE_TYPE_ID __WAVE_ID("RIFF") 40 | #define WAVE_FILE_FMT_ID __WAVE_ID("WAVE") 41 | 42 | struct wave_file { 43 | uint32_t type_id; 44 | uint32_t size; 45 | uint32_t fmt_id; 46 | }; 47 | 48 | 49 | /** 50 | * Audio format statement 51 | * | id WAVE_FORMAT_ID 52 | * | size Size of the block - 8 bytes (= 16 bytes) 53 | * | format WAVE_FORMAT_PCM 54 | * | channels Number of channels 55 | * | samplerate Sampling rate 56 | * | byterate Bytes per secondes = `samplerate * framesize` 57 | * | framesize Bytes per sampling time = `channels * bitdepth / 8` 58 | * | bitdepth Number of bits per sample 59 | */ 60 | 61 | #define WAVE_FORMAT_ID __WAVE_ID("fmt ") 62 | #define WAVE_FORMAT_PCM 1 63 | 64 | struct wave_format { 65 | uint32_t id; 66 | uint32_t size; 67 | uint16_t fmt; 68 | uint16_t channels; 69 | uint32_t samplerate; 70 | uint32_t byterate; 71 | uint16_t framesize; 72 | uint16_t bitdepth; 73 | }; 74 | 75 | 76 | /** 77 | * Audio data statement 78 | * | id WAV_DATA_ID 79 | * | size Size of the data following 80 | */ 81 | 82 | #define WAVE_DATA_ID __WAVE_ID("data") 83 | 84 | struct wave_data { 85 | uint32_t id; 86 | uint32_t size; 87 | }; 88 | 89 | 90 | /** 91 | * Read WAVE file header 92 | */ 93 | int wave_read_header(FILE *fp, int *bitdepth, int *samplesize, 94 | int *samplerate, int *nchannels, int *nframes) 95 | { 96 | struct wave_file file; 97 | struct wave_format format; 98 | struct wave_data data; 99 | 100 | if (fread(&file, sizeof(file), 1, fp) != 1 101 | || file.type_id != WAVE_FILE_TYPE_ID 102 | || file.fmt_id != WAVE_FILE_FMT_ID) 103 | return -1; 104 | 105 | if (fread(&format, sizeof(format), 1, fp) != 1 106 | || format.id != WAVE_FORMAT_ID 107 | || format.fmt != WAVE_FORMAT_PCM 108 | || format.byterate != format.samplerate * format.framesize) 109 | return -1; 110 | 111 | fseek(fp, sizeof(format) - (8 + format.size), SEEK_CUR); 112 | 113 | if (fread(&data, sizeof(data), 1, fp) != 1 114 | || data.id != WAVE_DATA_ID) 115 | return -1; 116 | 117 | *bitdepth = format.bitdepth; 118 | *samplesize = format.framesize / format.channels; 119 | *samplerate = format.samplerate; 120 | *nchannels = format.channels; 121 | *nframes = data.size < INT_MAX ? (int)(data.size / format.framesize) : -1; 122 | 123 | return 0; 124 | } 125 | 126 | /** 127 | * Read PCM samples from wave file 128 | */ 129 | int wave_read_pcm(FILE *fp, int samplesize, 130 | int nch, int count, void *buffer) 131 | { 132 | return fread(buffer, nch * samplesize, count, fp); 133 | } 134 | 135 | /** 136 | * Write WAVE file header 137 | */ 138 | void wave_write_header(FILE *fp, int bitdepth, int samplesize, 139 | int samplerate, int nchannels, int nframes) 140 | { 141 | struct { 142 | struct wave_file file; 143 | struct wave_format format; 144 | struct wave_data data; 145 | } header; 146 | 147 | long data_size = nframes >= 0 ? nchannels * nframes * samplesize : -1; 148 | long file_size = data_size >= 0 ? (long)sizeof(header) + data_size : -1; 149 | 150 | header.file = (struct wave_file){ 151 | WAVE_FILE_TYPE_ID, file_size >= 0 ? file_size - 8 : UINT_MAX, 152 | .fmt_id = WAVE_FILE_FMT_ID 153 | }; 154 | 155 | header.format = (struct wave_format){ 156 | WAVE_FORMAT_ID, sizeof(header.format) - 8, 157 | .fmt = WAVE_FORMAT_PCM, 158 | .channels = nchannels, 159 | .samplerate = samplerate, 160 | .byterate = samplerate * nchannels * samplesize, 161 | .framesize = nchannels * samplesize, 162 | .bitdepth = bitdepth, 163 | }; 164 | 165 | header.data = (struct wave_data){ 166 | WAVE_DATA_ID, data_size >= 0 ? data_size : UINT_MAX 167 | }; 168 | 169 | fwrite(&header, sizeof(header), 1, fp); 170 | } 171 | 172 | /** 173 | * Write PCM samples to wave file 174 | */ 175 | void wave_write_pcm(FILE *fp, int samplesize, 176 | const void *_pcm, int nch, int off, int count) 177 | { 178 | const int8_t *pcm = _pcm; 179 | fwrite(pcm + nch * off * samplesize, nch * samplesize, count, fp); 180 | } 181 | -------------------------------------------------------------------------------- /tools/wave.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright 2022 Google LLC 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at: 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | ******************************************************************************/ 18 | 19 | #ifndef __WAVE_H 20 | #define __WAVE_H 21 | 22 | #include 23 | #include 24 | 25 | 26 | /** 27 | * Read WAVE file header 28 | * fp Opened file, moved after header on return 29 | * bitdepth Return bitdepth 30 | * samplesize Return size of samples, in bytes 31 | * samplerate Return samplerate, in Hz 32 | * nchannels Return number of channels 33 | * nframes Return count of frames, -1 when undefined 34 | * return 0: Ok -1: Bad or unsupported WAVE File 35 | */ 36 | int wave_read_header(FILE *fp, int *bitdepth, int *samplesize, 37 | int *samplerate, int *nchannels, int *nframes); 38 | 39 | /** 40 | * Read PCM samples from wave file 41 | * fp Opened file 42 | * samplesize Size of samples, in bytes 43 | * nch, count Number of channels and count of frames to read 44 | * buffer Output buffer of `nchannels * count` interleaved samples 45 | * return Number of frames read 46 | */ 47 | int wave_read_pcm(FILE *fp, int samplesize, 48 | int nch, int count, void *_buffer); 49 | 50 | /** 51 | * Write WAVE file header 52 | * fp Opened file, moved after header on return 53 | * bitdepth Bitdepth 54 | * samplesize Size of samples 55 | * samplerate Samplerate, in Hz 56 | * nchannels Number of channels 57 | * nframes Count of frames, -1 when undefined 58 | */ 59 | void wave_write_header(FILE *fp, int bitdepth, int samplesize, 60 | int samplerate, int nchannels, int nframes); 61 | 62 | /** 63 | * Write PCM samples to wave file 64 | * fp Opened file 65 | * samplesize Size of samples, in bytes 66 | * pcm, nch PCM frames, as 'nch' interleaved samples 67 | * off, count Offset and count of frames 68 | */ 69 | void wave_write_pcm(FILE *fp, int samplesize, 70 | const void *pcm, int nch, int off, int count); 71 | 72 | 73 | #endif /* __WAVE_H */ 74 | --------------------------------------------------------------------------------