├── .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 |
--------------------------------------------------------------------------------