xref: /aosp_15_r20/external/liblc3/src/lc3.c (revision 49fe348c0058011ee60b6957cdd9d52742df84bc)
1*49fe348cSAndroid Build Coastguard Worker /******************************************************************************
2*49fe348cSAndroid Build Coastguard Worker  *
3*49fe348cSAndroid Build Coastguard Worker  *  Copyright 2022 Google LLC
4*49fe348cSAndroid Build Coastguard Worker  *
5*49fe348cSAndroid Build Coastguard Worker  *  Licensed under the Apache License, Version 2.0 (the "License");
6*49fe348cSAndroid Build Coastguard Worker  *  you may not use this file except in compliance with the License.
7*49fe348cSAndroid Build Coastguard Worker  *  You may obtain a copy of the License at:
8*49fe348cSAndroid Build Coastguard Worker  *
9*49fe348cSAndroid Build Coastguard Worker  *  http://www.apache.org/licenses/LICENSE-2.0
10*49fe348cSAndroid Build Coastguard Worker  *
11*49fe348cSAndroid Build Coastguard Worker  *  Unless required by applicable law or agreed to in writing, software
12*49fe348cSAndroid Build Coastguard Worker  *  distributed under the License is distributed on an "AS IS" BASIS,
13*49fe348cSAndroid Build Coastguard Worker  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*49fe348cSAndroid Build Coastguard Worker  *  See the License for the specific language governing permissions and
15*49fe348cSAndroid Build Coastguard Worker  *  limitations under the License.
16*49fe348cSAndroid Build Coastguard Worker  *
17*49fe348cSAndroid Build Coastguard Worker  ******************************************************************************/
18*49fe348cSAndroid Build Coastguard Worker 
19*49fe348cSAndroid Build Coastguard Worker #include <lc3.h>
20*49fe348cSAndroid Build Coastguard Worker 
21*49fe348cSAndroid Build Coastguard Worker #include "common.h"
22*49fe348cSAndroid Build Coastguard Worker #include "bits.h"
23*49fe348cSAndroid Build Coastguard Worker 
24*49fe348cSAndroid Build Coastguard Worker #include "attdet.h"
25*49fe348cSAndroid Build Coastguard Worker #include "bwdet.h"
26*49fe348cSAndroid Build Coastguard Worker #include "ltpf.h"
27*49fe348cSAndroid Build Coastguard Worker #include "mdct.h"
28*49fe348cSAndroid Build Coastguard Worker #include "energy.h"
29*49fe348cSAndroid Build Coastguard Worker #include "sns.h"
30*49fe348cSAndroid Build Coastguard Worker #include "tns.h"
31*49fe348cSAndroid Build Coastguard Worker #include "spec.h"
32*49fe348cSAndroid Build Coastguard Worker #include "plc.h"
33*49fe348cSAndroid Build Coastguard Worker 
34*49fe348cSAndroid Build Coastguard Worker 
35*49fe348cSAndroid Build Coastguard Worker /**
36*49fe348cSAndroid Build Coastguard Worker  * Frame side data
37*49fe348cSAndroid Build Coastguard Worker  */
38*49fe348cSAndroid Build Coastguard Worker 
39*49fe348cSAndroid Build Coastguard Worker struct side_data {
40*49fe348cSAndroid Build Coastguard Worker     enum lc3_bandwidth bw;
41*49fe348cSAndroid Build Coastguard Worker     bool pitch_present;
42*49fe348cSAndroid Build Coastguard Worker     lc3_ltpf_data_t ltpf;
43*49fe348cSAndroid Build Coastguard Worker     lc3_sns_data_t sns;
44*49fe348cSAndroid Build Coastguard Worker     lc3_tns_data_t tns;
45*49fe348cSAndroid Build Coastguard Worker     lc3_spec_side_t spec;
46*49fe348cSAndroid Build Coastguard Worker };
47*49fe348cSAndroid Build Coastguard Worker 
48*49fe348cSAndroid Build Coastguard Worker 
49*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
50*49fe348cSAndroid Build Coastguard Worker  *  General
51*49fe348cSAndroid Build Coastguard Worker  * -------------------------------------------------------------------------- */
52*49fe348cSAndroid Build Coastguard Worker 
53*49fe348cSAndroid Build Coastguard Worker /**
54*49fe348cSAndroid Build Coastguard Worker  * Resolve frame duration in us
55*49fe348cSAndroid Build Coastguard Worker  * us              Frame duration in us
56*49fe348cSAndroid Build Coastguard Worker  * hrmode          High-resolution mode indication
57*49fe348cSAndroid Build Coastguard Worker  * return          Frame duration identifier, or LC3_NUM_DT
58*49fe348cSAndroid Build Coastguard Worker  */
resolve_dt(int us,bool hrmode)59*49fe348cSAndroid Build Coastguard Worker static enum lc3_dt resolve_dt(int us, bool hrmode)
60*49fe348cSAndroid Build Coastguard Worker {
61*49fe348cSAndroid Build Coastguard Worker     return LC3_PLUS && us ==  2500 ? LC3_DT_2M5 :
62*49fe348cSAndroid Build Coastguard Worker            LC3_PLUS && us ==  5000 ? LC3_DT_5M  :
63*49fe348cSAndroid Build Coastguard Worker            !hrmode  && us ==  7500 ? LC3_DT_7M5 :
64*49fe348cSAndroid Build Coastguard Worker                        us == 10000 ? LC3_DT_10M : LC3_NUM_DT;
65*49fe348cSAndroid Build Coastguard Worker }
66*49fe348cSAndroid Build Coastguard Worker 
67*49fe348cSAndroid Build Coastguard Worker /**
68*49fe348cSAndroid Build Coastguard Worker  * Resolve samplerate in Hz
69*49fe348cSAndroid Build Coastguard Worker  * hz              Samplerate in Hz
70*49fe348cSAndroid Build Coastguard Worker  * hrmode          High-resolution mode indication
71*49fe348cSAndroid Build Coastguard Worker  * return          Sample rate identifier, or LC3_NUM_SRATE
72*49fe348cSAndroid Build Coastguard Worker  */
resolve_srate(int hz,bool hrmode)73*49fe348cSAndroid Build Coastguard Worker static enum lc3_srate resolve_srate(int hz, bool hrmode)
74*49fe348cSAndroid Build Coastguard Worker {
75*49fe348cSAndroid Build Coastguard Worker     hrmode = LC3_PLUS_HR && hrmode;
76*49fe348cSAndroid Build Coastguard Worker 
77*49fe348cSAndroid Build Coastguard Worker     return !hrmode && hz ==  8000 ? LC3_SRATE_8K     :
78*49fe348cSAndroid Build Coastguard Worker            !hrmode && hz == 16000 ? LC3_SRATE_16K    :
79*49fe348cSAndroid Build Coastguard Worker            !hrmode && hz == 24000 ? LC3_SRATE_24K    :
80*49fe348cSAndroid Build Coastguard Worker            !hrmode && hz == 32000 ? LC3_SRATE_32K    :
81*49fe348cSAndroid Build Coastguard Worker            !hrmode && hz == 48000 ? LC3_SRATE_48K    :
82*49fe348cSAndroid Build Coastguard Worker             hrmode && hz == 48000 ? LC3_SRATE_48K_HR :
83*49fe348cSAndroid Build Coastguard Worker             hrmode && hz == 96000 ? LC3_SRATE_96K_HR : LC3_NUM_SRATE;
84*49fe348cSAndroid Build Coastguard Worker }
85*49fe348cSAndroid Build Coastguard Worker 
86*49fe348cSAndroid Build Coastguard Worker /**
87*49fe348cSAndroid Build Coastguard Worker  * Return the number of PCM samples in a frame
88*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_frame_samples(bool hrmode,int dt_us,int sr_hz)89*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_hr_frame_samples(bool hrmode, int dt_us, int sr_hz)
90*49fe348cSAndroid Build Coastguard Worker {
91*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = resolve_dt(dt_us, hrmode);
92*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
93*49fe348cSAndroid Build Coastguard Worker 
94*49fe348cSAndroid Build Coastguard Worker     if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
95*49fe348cSAndroid Build Coastguard Worker         return -1;
96*49fe348cSAndroid Build Coastguard Worker 
97*49fe348cSAndroid Build Coastguard Worker     return lc3_ns(dt, sr);
98*49fe348cSAndroid Build Coastguard Worker }
99*49fe348cSAndroid Build Coastguard Worker 
lc3_frame_samples(int dt_us,int sr_hz)100*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_frame_samples(int dt_us, int sr_hz)
101*49fe348cSAndroid Build Coastguard Worker {
102*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_frame_samples(false, dt_us, sr_hz);
103*49fe348cSAndroid Build Coastguard Worker }
104*49fe348cSAndroid Build Coastguard Worker 
105*49fe348cSAndroid Build Coastguard Worker /**
106*49fe348cSAndroid Build Coastguard Worker  * Return the size of frames or frame blocks, from bitrate
107*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_frame_block_bytes(bool hrmode,int dt_us,int sr_hz,int nchannels,int bitrate)108*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_hr_frame_block_bytes(
109*49fe348cSAndroid Build Coastguard Worker     bool hrmode, int dt_us, int sr_hz, int nchannels, int bitrate)
110*49fe348cSAndroid Build Coastguard Worker {
111*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = resolve_dt(dt_us, hrmode);
112*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
113*49fe348cSAndroid Build Coastguard Worker 
114*49fe348cSAndroid Build Coastguard Worker     if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE
115*49fe348cSAndroid Build Coastguard Worker             || nchannels < 1 || nchannels > 8 || bitrate < 0)
116*49fe348cSAndroid Build Coastguard Worker         return -1;
117*49fe348cSAndroid Build Coastguard Worker 
118*49fe348cSAndroid Build Coastguard Worker     bitrate = LC3_CLIP(bitrate, 0, 8*LC3_HR_MAX_BITRATE);
119*49fe348cSAndroid Build Coastguard Worker 
120*49fe348cSAndroid Build Coastguard Worker     return LC3_CLIP((bitrate * (int)(1 + dt)) / 3200,
121*49fe348cSAndroid Build Coastguard Worker         nchannels * lc3_min_frame_bytes(dt, sr),
122*49fe348cSAndroid Build Coastguard Worker         nchannels * lc3_max_frame_bytes(dt, sr) );
123*49fe348cSAndroid Build Coastguard Worker }
124*49fe348cSAndroid Build Coastguard Worker 
lc3_frame_bock_bytes(int dt_us,int nchannels,int bitrate)125*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_frame_bock_bytes(int dt_us, int nchannels, int bitrate)
126*49fe348cSAndroid Build Coastguard Worker {
127*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_frame_block_bytes(false, dt_us, 8000, nchannels, bitrate);
128*49fe348cSAndroid Build Coastguard Worker }
129*49fe348cSAndroid Build Coastguard Worker 
lc3_hr_frame_bytes(bool hrmode,int dt_us,int sr_hz,int bitrate)130*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_hr_frame_bytes(
131*49fe348cSAndroid Build Coastguard Worker     bool hrmode, int dt_us, int sr_hz, int bitrate)
132*49fe348cSAndroid Build Coastguard Worker {
133*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_frame_block_bytes(hrmode, dt_us, sr_hz, 1, bitrate);
134*49fe348cSAndroid Build Coastguard Worker }
135*49fe348cSAndroid Build Coastguard Worker 
lc3_frame_bytes(int dt_us,int bitrate)136*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_frame_bytes(int dt_us, int bitrate)
137*49fe348cSAndroid Build Coastguard Worker {
138*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_frame_bytes(false, dt_us, 8000, bitrate);
139*49fe348cSAndroid Build Coastguard Worker }
140*49fe348cSAndroid Build Coastguard Worker 
141*49fe348cSAndroid Build Coastguard Worker /**
142*49fe348cSAndroid Build Coastguard Worker  * Resolve the bitrate, from the size of frames or frame blocks
143*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_resolve_bitrate(bool hrmode,int dt_us,int sr_hz,int nbytes)144*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_hr_resolve_bitrate(
145*49fe348cSAndroid Build Coastguard Worker     bool hrmode, int dt_us, int sr_hz, int nbytes)
146*49fe348cSAndroid Build Coastguard Worker {
147*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = resolve_dt(dt_us, hrmode);
148*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
149*49fe348cSAndroid Build Coastguard Worker 
150*49fe348cSAndroid Build Coastguard Worker     if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE || nbytes < 0)
151*49fe348cSAndroid Build Coastguard Worker         return -1;
152*49fe348cSAndroid Build Coastguard Worker 
153*49fe348cSAndroid Build Coastguard Worker     return LC3_MIN(((int64_t)nbytes * 3200 + dt) / (1 + dt), INT_MAX);
154*49fe348cSAndroid Build Coastguard Worker }
155*49fe348cSAndroid Build Coastguard Worker 
lc3_resolve_bitrate(int dt_us,int nbytes)156*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_resolve_bitrate(int dt_us, int nbytes)
157*49fe348cSAndroid Build Coastguard Worker {
158*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_resolve_bitrate(false, dt_us, 8000, nbytes);
159*49fe348cSAndroid Build Coastguard Worker }
160*49fe348cSAndroid Build Coastguard Worker 
161*49fe348cSAndroid Build Coastguard Worker /**
162*49fe348cSAndroid Build Coastguard Worker  * Return algorithmic delay, as a number of samples
163*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_delay_samples(bool hrmode,int dt_us,int sr_hz)164*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_hr_delay_samples(bool hrmode, int dt_us, int sr_hz)
165*49fe348cSAndroid Build Coastguard Worker {
166*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = resolve_dt(dt_us, hrmode);
167*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
168*49fe348cSAndroid Build Coastguard Worker 
169*49fe348cSAndroid Build Coastguard Worker     if (dt >= LC3_NUM_DT || sr >= LC3_NUM_SRATE)
170*49fe348cSAndroid Build Coastguard Worker         return -1;
171*49fe348cSAndroid Build Coastguard Worker 
172*49fe348cSAndroid Build Coastguard Worker     return 2 * lc3_nd(dt, sr) - lc3_ns(dt, sr);
173*49fe348cSAndroid Build Coastguard Worker }
174*49fe348cSAndroid Build Coastguard Worker 
lc3_delay_samples(int dt_us,int sr_hz)175*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_delay_samples(int dt_us, int sr_hz)
176*49fe348cSAndroid Build Coastguard Worker {
177*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_delay_samples(false, dt_us, sr_hz);
178*49fe348cSAndroid Build Coastguard Worker }
179*49fe348cSAndroid Build Coastguard Worker 
180*49fe348cSAndroid Build Coastguard Worker 
181*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
182*49fe348cSAndroid Build Coastguard Worker  *  Encoder
183*49fe348cSAndroid Build Coastguard Worker  * -------------------------------------------------------------------------- */
184*49fe348cSAndroid Build Coastguard Worker 
185*49fe348cSAndroid Build Coastguard Worker /**
186*49fe348cSAndroid Build Coastguard Worker  * Input PCM Samples from signed 16 bits
187*49fe348cSAndroid Build Coastguard Worker  * encoder         Encoder state
188*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Input PCM samples, and count between two consecutives
189*49fe348cSAndroid Build Coastguard Worker  */
load_s16(struct lc3_encoder * encoder,const void * _pcm,int stride)190*49fe348cSAndroid Build Coastguard Worker static void load_s16(
191*49fe348cSAndroid Build Coastguard Worker     struct lc3_encoder *encoder, const void *_pcm, int stride)
192*49fe348cSAndroid Build Coastguard Worker {
193*49fe348cSAndroid Build Coastguard Worker     const int16_t *pcm = _pcm;
194*49fe348cSAndroid Build Coastguard Worker 
195*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = encoder->dt;
196*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = encoder->sr_pcm;
197*49fe348cSAndroid Build Coastguard Worker 
198*49fe348cSAndroid Build Coastguard Worker     int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
199*49fe348cSAndroid Build Coastguard Worker     float *xs = encoder->x + encoder->xs_off;
200*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
201*49fe348cSAndroid Build Coastguard Worker 
202*49fe348cSAndroid Build Coastguard Worker     for (int i = 0; i < ns; i++, pcm += stride)
203*49fe348cSAndroid Build Coastguard Worker         xt[i] = *pcm, xs[i] = *pcm;
204*49fe348cSAndroid Build Coastguard Worker }
205*49fe348cSAndroid Build Coastguard Worker 
206*49fe348cSAndroid Build Coastguard Worker /**
207*49fe348cSAndroid Build Coastguard Worker  * Input PCM Samples from signed 24 bits
208*49fe348cSAndroid Build Coastguard Worker  * encoder         Encoder state
209*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Input PCM samples, and count between two consecutives
210*49fe348cSAndroid Build Coastguard Worker  */
load_s24(struct lc3_encoder * encoder,const void * _pcm,int stride)211*49fe348cSAndroid Build Coastguard Worker static void load_s24(
212*49fe348cSAndroid Build Coastguard Worker     struct lc3_encoder *encoder, const void *_pcm, int stride)
213*49fe348cSAndroid Build Coastguard Worker {
214*49fe348cSAndroid Build Coastguard Worker     const int32_t *pcm = _pcm;
215*49fe348cSAndroid Build Coastguard Worker 
216*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = encoder->dt;
217*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = encoder->sr_pcm;
218*49fe348cSAndroid Build Coastguard Worker 
219*49fe348cSAndroid Build Coastguard Worker     int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
220*49fe348cSAndroid Build Coastguard Worker     float *xs = encoder->x + encoder->xs_off;
221*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
222*49fe348cSAndroid Build Coastguard Worker 
223*49fe348cSAndroid Build Coastguard Worker     for (int i = 0; i < ns; i++, pcm += stride) {
224*49fe348cSAndroid Build Coastguard Worker         xt[i] = *pcm >> 8;
225*49fe348cSAndroid Build Coastguard Worker         xs[i] = lc3_ldexpf(*pcm, -8);
226*49fe348cSAndroid Build Coastguard Worker     }
227*49fe348cSAndroid Build Coastguard Worker }
228*49fe348cSAndroid Build Coastguard Worker 
229*49fe348cSAndroid Build Coastguard Worker /**
230*49fe348cSAndroid Build Coastguard Worker  * Input PCM Samples from signed 24 bits packed
231*49fe348cSAndroid Build Coastguard Worker  * encoder         Encoder state
232*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Input PCM samples, and count between two consecutives
233*49fe348cSAndroid Build Coastguard Worker  */
load_s24_3le(struct lc3_encoder * encoder,const void * _pcm,int stride)234*49fe348cSAndroid Build Coastguard Worker static void load_s24_3le(
235*49fe348cSAndroid Build Coastguard Worker     struct lc3_encoder *encoder, const void *_pcm, int stride)
236*49fe348cSAndroid Build Coastguard Worker {
237*49fe348cSAndroid Build Coastguard Worker     const uint8_t *pcm = _pcm;
238*49fe348cSAndroid Build Coastguard Worker 
239*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = encoder->dt;
240*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = encoder->sr_pcm;
241*49fe348cSAndroid Build Coastguard Worker 
242*49fe348cSAndroid Build Coastguard Worker     int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
243*49fe348cSAndroid Build Coastguard Worker     float *xs = encoder->x + encoder->xs_off;
244*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
245*49fe348cSAndroid Build Coastguard Worker 
246*49fe348cSAndroid Build Coastguard Worker     for (int i = 0; i < ns; i++, pcm += 3*stride) {
247*49fe348cSAndroid Build Coastguard Worker         int32_t in = ((uint32_t)pcm[0] <<  8) |
248*49fe348cSAndroid Build Coastguard Worker                      ((uint32_t)pcm[1] << 16) |
249*49fe348cSAndroid Build Coastguard Worker                      ((uint32_t)pcm[2] << 24)  ;
250*49fe348cSAndroid Build Coastguard Worker 
251*49fe348cSAndroid Build Coastguard Worker         xt[i] = in >> 16;
252*49fe348cSAndroid Build Coastguard Worker         xs[i] = lc3_ldexpf(in, -16);
253*49fe348cSAndroid Build Coastguard Worker     }
254*49fe348cSAndroid Build Coastguard Worker }
255*49fe348cSAndroid Build Coastguard Worker 
256*49fe348cSAndroid Build Coastguard Worker /**
257*49fe348cSAndroid Build Coastguard Worker  * Input PCM Samples from float 32 bits
258*49fe348cSAndroid Build Coastguard Worker  * encoder         Encoder state
259*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Input PCM samples, and count between two consecutives
260*49fe348cSAndroid Build Coastguard Worker  */
load_float(struct lc3_encoder * encoder,const void * _pcm,int stride)261*49fe348cSAndroid Build Coastguard Worker static void load_float(
262*49fe348cSAndroid Build Coastguard Worker     struct lc3_encoder *encoder, const void *_pcm, int stride)
263*49fe348cSAndroid Build Coastguard Worker {
264*49fe348cSAndroid Build Coastguard Worker     const float *pcm = _pcm;
265*49fe348cSAndroid Build Coastguard Worker 
266*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = encoder->dt;
267*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = encoder->sr_pcm;
268*49fe348cSAndroid Build Coastguard Worker 
269*49fe348cSAndroid Build Coastguard Worker     int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
270*49fe348cSAndroid Build Coastguard Worker     float *xs = encoder->x + encoder->xs_off;
271*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
272*49fe348cSAndroid Build Coastguard Worker 
273*49fe348cSAndroid Build Coastguard Worker     for (int i = 0; i < ns; i++, pcm += stride) {
274*49fe348cSAndroid Build Coastguard Worker         xs[i] = lc3_ldexpf(*pcm, 15);
275*49fe348cSAndroid Build Coastguard Worker         xt[i] = LC3_SAT16((int32_t)xs[i]);
276*49fe348cSAndroid Build Coastguard Worker     }
277*49fe348cSAndroid Build Coastguard Worker }
278*49fe348cSAndroid Build Coastguard Worker 
279*49fe348cSAndroid Build Coastguard Worker /**
280*49fe348cSAndroid Build Coastguard Worker  * Frame Analysis
281*49fe348cSAndroid Build Coastguard Worker  * encoder         Encoder state
282*49fe348cSAndroid Build Coastguard Worker  * nbytes          Size in bytes of the frame
283*49fe348cSAndroid Build Coastguard Worker  * side            Return frame data
284*49fe348cSAndroid Build Coastguard Worker  */
analyze(struct lc3_encoder * encoder,int nbytes,struct side_data * side)285*49fe348cSAndroid Build Coastguard Worker static void analyze(struct lc3_encoder *encoder,
286*49fe348cSAndroid Build Coastguard Worker     int nbytes, struct side_data *side)
287*49fe348cSAndroid Build Coastguard Worker {
288*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = encoder->dt;
289*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = encoder->sr;
290*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr_pcm = encoder->sr_pcm;
291*49fe348cSAndroid Build Coastguard Worker 
292*49fe348cSAndroid Build Coastguard Worker     int16_t *xt = (int16_t *)encoder->x + encoder->xt_off;
293*49fe348cSAndroid Build Coastguard Worker     float *xs = encoder->x + encoder->xs_off;
294*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr_pcm);
295*49fe348cSAndroid Build Coastguard Worker     int nt = lc3_nt(sr_pcm);
296*49fe348cSAndroid Build Coastguard Worker 
297*49fe348cSAndroid Build Coastguard Worker     float *xd = encoder->x + encoder->xd_off;
298*49fe348cSAndroid Build Coastguard Worker     float *xf = xs;
299*49fe348cSAndroid Build Coastguard Worker 
300*49fe348cSAndroid Build Coastguard Worker     /* --- Temporal --- */
301*49fe348cSAndroid Build Coastguard Worker 
302*49fe348cSAndroid Build Coastguard Worker     bool att = lc3_attdet_run(dt, sr_pcm, nbytes, &encoder->attdet, xt);
303*49fe348cSAndroid Build Coastguard Worker 
304*49fe348cSAndroid Build Coastguard Worker     side->pitch_present =
305*49fe348cSAndroid Build Coastguard Worker         lc3_ltpf_analyse(dt, sr_pcm, &encoder->ltpf, xt, &side->ltpf);
306*49fe348cSAndroid Build Coastguard Worker 
307*49fe348cSAndroid Build Coastguard Worker     memmove(xt - nt, xt + (ns-nt), nt * sizeof(*xt));
308*49fe348cSAndroid Build Coastguard Worker 
309*49fe348cSAndroid Build Coastguard Worker     /* --- Spectral --- */
310*49fe348cSAndroid Build Coastguard Worker 
311*49fe348cSAndroid Build Coastguard Worker     float e[LC3_MAX_BANDS];
312*49fe348cSAndroid Build Coastguard Worker 
313*49fe348cSAndroid Build Coastguard Worker     lc3_mdct_forward(dt, sr_pcm, sr, xs, xd, xf);
314*49fe348cSAndroid Build Coastguard Worker 
315*49fe348cSAndroid Build Coastguard Worker     bool nn_flag = lc3_energy_compute(dt, sr, xf, e);
316*49fe348cSAndroid Build Coastguard Worker     if (nn_flag)
317*49fe348cSAndroid Build Coastguard Worker         lc3_ltpf_disable(&side->ltpf);
318*49fe348cSAndroid Build Coastguard Worker 
319*49fe348cSAndroid Build Coastguard Worker     side->bw = lc3_bwdet_run(dt, sr, e);
320*49fe348cSAndroid Build Coastguard Worker 
321*49fe348cSAndroid Build Coastguard Worker     lc3_sns_analyze(dt, sr, nbytes, e, att, &side->sns, xf, xf);
322*49fe348cSAndroid Build Coastguard Worker 
323*49fe348cSAndroid Build Coastguard Worker     lc3_tns_analyze(dt, side->bw, nn_flag, nbytes, &side->tns, xf);
324*49fe348cSAndroid Build Coastguard Worker 
325*49fe348cSAndroid Build Coastguard Worker     lc3_spec_analyze(dt, sr,
326*49fe348cSAndroid Build Coastguard Worker         nbytes, side->pitch_present, &side->tns,
327*49fe348cSAndroid Build Coastguard Worker         &encoder->spec, xf, &side->spec);
328*49fe348cSAndroid Build Coastguard Worker }
329*49fe348cSAndroid Build Coastguard Worker 
330*49fe348cSAndroid Build Coastguard Worker /**
331*49fe348cSAndroid Build Coastguard Worker  * Encode bitstream
332*49fe348cSAndroid Build Coastguard Worker  * encoder         Encoder state
333*49fe348cSAndroid Build Coastguard Worker  * side            The frame data
334*49fe348cSAndroid Build Coastguard Worker  * nbytes          Target size of the frame (20 to 400)
335*49fe348cSAndroid Build Coastguard Worker  * buffer          Output bitstream buffer of `nbytes` size
336*49fe348cSAndroid Build Coastguard Worker  */
encode(struct lc3_encoder * encoder,const struct side_data * side,int nbytes,void * buffer)337*49fe348cSAndroid Build Coastguard Worker static void encode(struct lc3_encoder *encoder,
338*49fe348cSAndroid Build Coastguard Worker     const struct side_data *side, int nbytes, void *buffer)
339*49fe348cSAndroid Build Coastguard Worker {
340*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = encoder->dt;
341*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = encoder->sr;
342*49fe348cSAndroid Build Coastguard Worker 
343*49fe348cSAndroid Build Coastguard Worker     float *xf = encoder->x + encoder->xs_off;
344*49fe348cSAndroid Build Coastguard Worker     enum lc3_bandwidth bw = side->bw;
345*49fe348cSAndroid Build Coastguard Worker 
346*49fe348cSAndroid Build Coastguard Worker     lc3_bits_t bits;
347*49fe348cSAndroid Build Coastguard Worker 
348*49fe348cSAndroid Build Coastguard Worker     lc3_setup_bits(&bits, LC3_BITS_MODE_WRITE, buffer, nbytes);
349*49fe348cSAndroid Build Coastguard Worker 
350*49fe348cSAndroid Build Coastguard Worker     lc3_bwdet_put_bw(&bits, sr, bw);
351*49fe348cSAndroid Build Coastguard Worker 
352*49fe348cSAndroid Build Coastguard Worker     lc3_spec_put_side(&bits, dt, sr, &side->spec);
353*49fe348cSAndroid Build Coastguard Worker 
354*49fe348cSAndroid Build Coastguard Worker     lc3_tns_put_data(&bits, &side->tns);
355*49fe348cSAndroid Build Coastguard Worker 
356*49fe348cSAndroid Build Coastguard Worker     lc3_put_bit(&bits, side->pitch_present);
357*49fe348cSAndroid Build Coastguard Worker 
358*49fe348cSAndroid Build Coastguard Worker     lc3_sns_put_data(&bits, &side->sns);
359*49fe348cSAndroid Build Coastguard Worker 
360*49fe348cSAndroid Build Coastguard Worker     if (side->pitch_present)
361*49fe348cSAndroid Build Coastguard Worker         lc3_ltpf_put_data(&bits, &side->ltpf);
362*49fe348cSAndroid Build Coastguard Worker 
363*49fe348cSAndroid Build Coastguard Worker     lc3_spec_encode(&bits, dt, sr, bw, nbytes, &side->spec, xf);
364*49fe348cSAndroid Build Coastguard Worker 
365*49fe348cSAndroid Build Coastguard Worker     lc3_flush_bits(&bits);
366*49fe348cSAndroid Build Coastguard Worker }
367*49fe348cSAndroid Build Coastguard Worker 
368*49fe348cSAndroid Build Coastguard Worker /**
369*49fe348cSAndroid Build Coastguard Worker  * Return size needed for an encoder
370*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_encoder_size(bool hrmode,int dt_us,int sr_hz)371*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT unsigned lc3_hr_encoder_size(bool hrmode, int dt_us, int sr_hz)
372*49fe348cSAndroid Build Coastguard Worker {
373*49fe348cSAndroid Build Coastguard Worker     if (resolve_dt(dt_us, hrmode) >= LC3_NUM_DT ||
374*49fe348cSAndroid Build Coastguard Worker         resolve_srate(sr_hz, hrmode) >= LC3_NUM_SRATE)
375*49fe348cSAndroid Build Coastguard Worker         return 0;
376*49fe348cSAndroid Build Coastguard Worker 
377*49fe348cSAndroid Build Coastguard Worker     return sizeof(struct lc3_encoder) +
378*49fe348cSAndroid Build Coastguard Worker         (LC3_ENCODER_BUFFER_COUNT(dt_us, sr_hz)-1) * sizeof(float);
379*49fe348cSAndroid Build Coastguard Worker }
380*49fe348cSAndroid Build Coastguard Worker 
lc3_encoder_size(int dt_us,int sr_hz)381*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT unsigned lc3_encoder_size(int dt_us, int sr_hz)
382*49fe348cSAndroid Build Coastguard Worker {
383*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_encoder_size(false, dt_us, sr_hz);
384*49fe348cSAndroid Build Coastguard Worker }
385*49fe348cSAndroid Build Coastguard Worker 
386*49fe348cSAndroid Build Coastguard Worker /**
387*49fe348cSAndroid Build Coastguard Worker  * Setup encoder
388*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_setup_encoder(bool hrmode,int dt_us,int sr_hz,int sr_pcm_hz,void * mem)389*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT struct lc3_encoder *lc3_hr_setup_encoder(
390*49fe348cSAndroid Build Coastguard Worker     bool hrmode, int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
391*49fe348cSAndroid Build Coastguard Worker {
392*49fe348cSAndroid Build Coastguard Worker     if (sr_pcm_hz <= 0)
393*49fe348cSAndroid Build Coastguard Worker         sr_pcm_hz = sr_hz;
394*49fe348cSAndroid Build Coastguard Worker 
395*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = resolve_dt(dt_us, hrmode);
396*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
397*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr_pcm = resolve_srate(sr_pcm_hz, hrmode);
398*49fe348cSAndroid Build Coastguard Worker 
399*49fe348cSAndroid Build Coastguard Worker     if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
400*49fe348cSAndroid Build Coastguard Worker         return NULL;
401*49fe348cSAndroid Build Coastguard Worker 
402*49fe348cSAndroid Build Coastguard Worker     struct lc3_encoder *encoder = mem;
403*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr_pcm);
404*49fe348cSAndroid Build Coastguard Worker     int nt = lc3_nt(sr_pcm);
405*49fe348cSAndroid Build Coastguard Worker 
406*49fe348cSAndroid Build Coastguard Worker     *encoder = (struct lc3_encoder){
407*49fe348cSAndroid Build Coastguard Worker         .dt = dt, .sr = sr,
408*49fe348cSAndroid Build Coastguard Worker         .sr_pcm = sr_pcm,
409*49fe348cSAndroid Build Coastguard Worker 
410*49fe348cSAndroid Build Coastguard Worker         .xt_off = nt,
411*49fe348cSAndroid Build Coastguard Worker         .xs_off = (nt + ns) / 2,
412*49fe348cSAndroid Build Coastguard Worker         .xd_off = (nt + ns) / 2 + ns,
413*49fe348cSAndroid Build Coastguard Worker     };
414*49fe348cSAndroid Build Coastguard Worker 
415*49fe348cSAndroid Build Coastguard Worker     memset(encoder->x, 0,
416*49fe348cSAndroid Build Coastguard Worker         LC3_ENCODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float));
417*49fe348cSAndroid Build Coastguard Worker 
418*49fe348cSAndroid Build Coastguard Worker     return encoder;
419*49fe348cSAndroid Build Coastguard Worker }
420*49fe348cSAndroid Build Coastguard Worker 
lc3_setup_encoder(int dt_us,int sr_hz,int sr_pcm_hz,void * mem)421*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT struct lc3_encoder *lc3_setup_encoder(
422*49fe348cSAndroid Build Coastguard Worker     int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
423*49fe348cSAndroid Build Coastguard Worker {
424*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_setup_encoder(false, dt_us, sr_hz, sr_pcm_hz, mem);
425*49fe348cSAndroid Build Coastguard Worker }
426*49fe348cSAndroid Build Coastguard Worker 
427*49fe348cSAndroid Build Coastguard Worker /**
428*49fe348cSAndroid Build Coastguard Worker  * Encode a frame
429*49fe348cSAndroid Build Coastguard Worker  */
lc3_encode(struct lc3_encoder * encoder,enum lc3_pcm_format fmt,const void * pcm,int stride,int nbytes,void * out)430*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_encode(struct lc3_encoder *encoder,
431*49fe348cSAndroid Build Coastguard Worker     enum lc3_pcm_format fmt, const void *pcm, int stride, int nbytes, void *out)
432*49fe348cSAndroid Build Coastguard Worker {
433*49fe348cSAndroid Build Coastguard Worker     static void (* const load[])(struct lc3_encoder *, const void *, int) = {
434*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_S16    ] = load_s16,
435*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_S24    ] = load_s24,
436*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_S24_3LE] = load_s24_3le,
437*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_FLOAT  ] = load_float,
438*49fe348cSAndroid Build Coastguard Worker     };
439*49fe348cSAndroid Build Coastguard Worker 
440*49fe348cSAndroid Build Coastguard Worker     /* --- Check parameters --- */
441*49fe348cSAndroid Build Coastguard Worker 
442*49fe348cSAndroid Build Coastguard Worker     if (!encoder || nbytes < lc3_min_frame_bytes(encoder->dt, encoder->sr)
443*49fe348cSAndroid Build Coastguard Worker                  || nbytes > lc3_max_frame_bytes(encoder->dt, encoder->sr))
444*49fe348cSAndroid Build Coastguard Worker         return -1;
445*49fe348cSAndroid Build Coastguard Worker 
446*49fe348cSAndroid Build Coastguard Worker     /* --- Processing --- */
447*49fe348cSAndroid Build Coastguard Worker 
448*49fe348cSAndroid Build Coastguard Worker     struct side_data side;
449*49fe348cSAndroid Build Coastguard Worker 
450*49fe348cSAndroid Build Coastguard Worker     load[fmt](encoder, pcm, stride);
451*49fe348cSAndroid Build Coastguard Worker 
452*49fe348cSAndroid Build Coastguard Worker     analyze(encoder, nbytes, &side);
453*49fe348cSAndroid Build Coastguard Worker 
454*49fe348cSAndroid Build Coastguard Worker     encode(encoder, &side, nbytes, out);
455*49fe348cSAndroid Build Coastguard Worker 
456*49fe348cSAndroid Build Coastguard Worker     return 0;
457*49fe348cSAndroid Build Coastguard Worker }
458*49fe348cSAndroid Build Coastguard Worker 
459*49fe348cSAndroid Build Coastguard Worker 
460*49fe348cSAndroid Build Coastguard Worker /* ----------------------------------------------------------------------------
461*49fe348cSAndroid Build Coastguard Worker  *  Decoder
462*49fe348cSAndroid Build Coastguard Worker  * -------------------------------------------------------------------------- */
463*49fe348cSAndroid Build Coastguard Worker 
464*49fe348cSAndroid Build Coastguard Worker /**
465*49fe348cSAndroid Build Coastguard Worker  * Output PCM Samples to signed 16 bits
466*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
467*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Output PCM samples, and count between two consecutives
468*49fe348cSAndroid Build Coastguard Worker  */
store_s16(struct lc3_decoder * decoder,void * _pcm,int stride)469*49fe348cSAndroid Build Coastguard Worker static void store_s16(
470*49fe348cSAndroid Build Coastguard Worker     struct lc3_decoder *decoder, void *_pcm, int stride)
471*49fe348cSAndroid Build Coastguard Worker {
472*49fe348cSAndroid Build Coastguard Worker     int16_t *pcm = _pcm;
473*49fe348cSAndroid Build Coastguard Worker 
474*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
475*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = decoder->sr_pcm;
476*49fe348cSAndroid Build Coastguard Worker 
477*49fe348cSAndroid Build Coastguard Worker     float *xs = decoder->x + decoder->xs_off;
478*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
479*49fe348cSAndroid Build Coastguard Worker 
480*49fe348cSAndroid Build Coastguard Worker     for ( ; ns > 0; ns--, xs++, pcm += stride) {
481*49fe348cSAndroid Build Coastguard Worker         int32_t s = *xs >= 0 ? (int)(*xs + 0.5f) : (int)(*xs - 0.5f);
482*49fe348cSAndroid Build Coastguard Worker         *pcm = LC3_SAT16(s);
483*49fe348cSAndroid Build Coastguard Worker     }
484*49fe348cSAndroid Build Coastguard Worker }
485*49fe348cSAndroid Build Coastguard Worker 
486*49fe348cSAndroid Build Coastguard Worker /**
487*49fe348cSAndroid Build Coastguard Worker  * Output PCM Samples to signed 24 bits
488*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
489*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Output PCM samples, and count between two consecutives
490*49fe348cSAndroid Build Coastguard Worker  */
store_s24(struct lc3_decoder * decoder,void * _pcm,int stride)491*49fe348cSAndroid Build Coastguard Worker static void store_s24(
492*49fe348cSAndroid Build Coastguard Worker     struct lc3_decoder *decoder, void *_pcm, int stride)
493*49fe348cSAndroid Build Coastguard Worker {
494*49fe348cSAndroid Build Coastguard Worker     int32_t *pcm = _pcm;
495*49fe348cSAndroid Build Coastguard Worker 
496*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
497*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = decoder->sr_pcm;
498*49fe348cSAndroid Build Coastguard Worker 
499*49fe348cSAndroid Build Coastguard Worker     float *xs = decoder->x + decoder->xs_off;
500*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
501*49fe348cSAndroid Build Coastguard Worker 
502*49fe348cSAndroid Build Coastguard Worker     for ( ; ns > 0; ns--, xs++, pcm += stride) {
503*49fe348cSAndroid Build Coastguard Worker         int32_t s = *xs >= 0 ? (int32_t)(lc3_ldexpf(*xs, 8) + 0.5f)
504*49fe348cSAndroid Build Coastguard Worker                              : (int32_t)(lc3_ldexpf(*xs, 8) - 0.5f);
505*49fe348cSAndroid Build Coastguard Worker         *pcm = LC3_SAT24(s);
506*49fe348cSAndroid Build Coastguard Worker     }
507*49fe348cSAndroid Build Coastguard Worker }
508*49fe348cSAndroid Build Coastguard Worker 
509*49fe348cSAndroid Build Coastguard Worker /**
510*49fe348cSAndroid Build Coastguard Worker  * Output PCM Samples to signed 24 bits packed
511*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
512*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Output PCM samples, and count between two consecutives
513*49fe348cSAndroid Build Coastguard Worker  */
store_s24_3le(struct lc3_decoder * decoder,void * _pcm,int stride)514*49fe348cSAndroid Build Coastguard Worker static void store_s24_3le(
515*49fe348cSAndroid Build Coastguard Worker     struct lc3_decoder *decoder, void *_pcm, int stride)
516*49fe348cSAndroid Build Coastguard Worker {
517*49fe348cSAndroid Build Coastguard Worker     uint8_t *pcm = _pcm;
518*49fe348cSAndroid Build Coastguard Worker 
519*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
520*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = decoder->sr_pcm;
521*49fe348cSAndroid Build Coastguard Worker 
522*49fe348cSAndroid Build Coastguard Worker     float *xs = decoder->x + decoder->xs_off;
523*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
524*49fe348cSAndroid Build Coastguard Worker 
525*49fe348cSAndroid Build Coastguard Worker     for ( ; ns > 0; ns--, xs++, pcm += 3*stride) {
526*49fe348cSAndroid Build Coastguard Worker         int32_t s = *xs >= 0 ? (int32_t)(lc3_ldexpf(*xs, 8) + 0.5f)
527*49fe348cSAndroid Build Coastguard Worker                              : (int32_t)(lc3_ldexpf(*xs, 8) - 0.5f);
528*49fe348cSAndroid Build Coastguard Worker 
529*49fe348cSAndroid Build Coastguard Worker         s = LC3_SAT24(s);
530*49fe348cSAndroid Build Coastguard Worker         pcm[0] = (s >>  0) & 0xff;
531*49fe348cSAndroid Build Coastguard Worker         pcm[1] = (s >>  8) & 0xff;
532*49fe348cSAndroid Build Coastguard Worker         pcm[2] = (s >> 16) & 0xff;
533*49fe348cSAndroid Build Coastguard Worker     }
534*49fe348cSAndroid Build Coastguard Worker }
535*49fe348cSAndroid Build Coastguard Worker 
536*49fe348cSAndroid Build Coastguard Worker /**
537*49fe348cSAndroid Build Coastguard Worker  * Output PCM Samples to float 32 bits
538*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
539*49fe348cSAndroid Build Coastguard Worker  * pcm, stride     Output PCM samples, and count between two consecutives
540*49fe348cSAndroid Build Coastguard Worker  */
store_float(struct lc3_decoder * decoder,void * _pcm,int stride)541*49fe348cSAndroid Build Coastguard Worker static void store_float(
542*49fe348cSAndroid Build Coastguard Worker     struct lc3_decoder *decoder, void *_pcm, int stride)
543*49fe348cSAndroid Build Coastguard Worker {
544*49fe348cSAndroid Build Coastguard Worker     float *pcm = _pcm;
545*49fe348cSAndroid Build Coastguard Worker 
546*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
547*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = decoder->sr_pcm;
548*49fe348cSAndroid Build Coastguard Worker 
549*49fe348cSAndroid Build Coastguard Worker     float *xs = decoder->x + decoder->xs_off;
550*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
551*49fe348cSAndroid Build Coastguard Worker 
552*49fe348cSAndroid Build Coastguard Worker     for ( ; ns > 0; ns--, xs++, pcm += stride) {
553*49fe348cSAndroid Build Coastguard Worker         float s = lc3_ldexpf(*xs, -15);
554*49fe348cSAndroid Build Coastguard Worker         *pcm = fminf(fmaxf(s, -1.f), 1.f);
555*49fe348cSAndroid Build Coastguard Worker     }
556*49fe348cSAndroid Build Coastguard Worker }
557*49fe348cSAndroid Build Coastguard Worker 
558*49fe348cSAndroid Build Coastguard Worker /**
559*49fe348cSAndroid Build Coastguard Worker  * Decode bitstream
560*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
561*49fe348cSAndroid Build Coastguard Worker  * data, nbytes    Input bitstream buffer
562*49fe348cSAndroid Build Coastguard Worker  * side            Return the side data
563*49fe348cSAndroid Build Coastguard Worker  * return          0: Ok  < 0: Bitsream error detected
564*49fe348cSAndroid Build Coastguard Worker  */
decode(struct lc3_decoder * decoder,const void * data,int nbytes,struct side_data * side)565*49fe348cSAndroid Build Coastguard Worker static int decode(struct lc3_decoder *decoder,
566*49fe348cSAndroid Build Coastguard Worker     const void *data, int nbytes, struct side_data *side)
567*49fe348cSAndroid Build Coastguard Worker {
568*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
569*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = decoder->sr;
570*49fe348cSAndroid Build Coastguard Worker 
571*49fe348cSAndroid Build Coastguard Worker     float *xf = decoder->x + decoder->xs_off;
572*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr);
573*49fe348cSAndroid Build Coastguard Worker     int ne = lc3_ne(dt, sr);
574*49fe348cSAndroid Build Coastguard Worker 
575*49fe348cSAndroid Build Coastguard Worker     lc3_bits_t bits;
576*49fe348cSAndroid Build Coastguard Worker     int ret = 0;
577*49fe348cSAndroid Build Coastguard Worker 
578*49fe348cSAndroid Build Coastguard Worker     lc3_setup_bits(&bits, LC3_BITS_MODE_READ, (void *)data, nbytes);
579*49fe348cSAndroid Build Coastguard Worker 
580*49fe348cSAndroid Build Coastguard Worker     if ((ret = lc3_bwdet_get_bw(&bits, sr, &side->bw)) < 0)
581*49fe348cSAndroid Build Coastguard Worker         return ret;
582*49fe348cSAndroid Build Coastguard Worker 
583*49fe348cSAndroid Build Coastguard Worker     if ((ret = lc3_spec_get_side(&bits, dt, sr, &side->spec)) < 0)
584*49fe348cSAndroid Build Coastguard Worker         return ret;
585*49fe348cSAndroid Build Coastguard Worker 
586*49fe348cSAndroid Build Coastguard Worker     if ((ret = lc3_tns_get_data(&bits, dt, side->bw, nbytes, &side->tns)) < 0)
587*49fe348cSAndroid Build Coastguard Worker         return ret;
588*49fe348cSAndroid Build Coastguard Worker 
589*49fe348cSAndroid Build Coastguard Worker     side->pitch_present = lc3_get_bit(&bits);
590*49fe348cSAndroid Build Coastguard Worker 
591*49fe348cSAndroid Build Coastguard Worker     if ((ret = lc3_sns_get_data(&bits, &side->sns)) < 0)
592*49fe348cSAndroid Build Coastguard Worker         return ret;
593*49fe348cSAndroid Build Coastguard Worker 
594*49fe348cSAndroid Build Coastguard Worker     if (side->pitch_present)
595*49fe348cSAndroid Build Coastguard Worker       lc3_ltpf_get_data(&bits, &side->ltpf);
596*49fe348cSAndroid Build Coastguard Worker 
597*49fe348cSAndroid Build Coastguard Worker     if ((ret = lc3_spec_decode(&bits, dt, sr,
598*49fe348cSAndroid Build Coastguard Worker                     side->bw, nbytes, &side->spec, xf)) < 0)
599*49fe348cSAndroid Build Coastguard Worker         return ret;
600*49fe348cSAndroid Build Coastguard Worker 
601*49fe348cSAndroid Build Coastguard Worker     memset(xf + ne, 0, (ns - ne) * sizeof(float));
602*49fe348cSAndroid Build Coastguard Worker 
603*49fe348cSAndroid Build Coastguard Worker     return lc3_check_bits(&bits);
604*49fe348cSAndroid Build Coastguard Worker }
605*49fe348cSAndroid Build Coastguard Worker 
606*49fe348cSAndroid Build Coastguard Worker /**
607*49fe348cSAndroid Build Coastguard Worker  * Frame synthesis
608*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
609*49fe348cSAndroid Build Coastguard Worker  * side            Frame data, NULL performs PLC
610*49fe348cSAndroid Build Coastguard Worker  * nbytes          Size in bytes of the frame
611*49fe348cSAndroid Build Coastguard Worker  */
synthesize(struct lc3_decoder * decoder,const struct side_data * side,int nbytes)612*49fe348cSAndroid Build Coastguard Worker static void synthesize(struct lc3_decoder *decoder,
613*49fe348cSAndroid Build Coastguard Worker     const struct side_data *side, int nbytes)
614*49fe348cSAndroid Build Coastguard Worker {
615*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
616*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = decoder->sr;
617*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr_pcm = decoder->sr_pcm;
618*49fe348cSAndroid Build Coastguard Worker 
619*49fe348cSAndroid Build Coastguard Worker     float *xf = decoder->x + decoder->xs_off;
620*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr_pcm);
621*49fe348cSAndroid Build Coastguard Worker     int ne = lc3_ne(dt, sr);
622*49fe348cSAndroid Build Coastguard Worker 
623*49fe348cSAndroid Build Coastguard Worker     float *xg = decoder->x + decoder->xg_off;
624*49fe348cSAndroid Build Coastguard Worker     float *xs = xf;
625*49fe348cSAndroid Build Coastguard Worker 
626*49fe348cSAndroid Build Coastguard Worker     float *xd = decoder->x + decoder->xd_off;
627*49fe348cSAndroid Build Coastguard Worker     float *xh = decoder->x + decoder->xh_off;
628*49fe348cSAndroid Build Coastguard Worker 
629*49fe348cSAndroid Build Coastguard Worker     if (side) {
630*49fe348cSAndroid Build Coastguard Worker         enum lc3_bandwidth bw = side->bw;
631*49fe348cSAndroid Build Coastguard Worker 
632*49fe348cSAndroid Build Coastguard Worker         lc3_plc_suspend(&decoder->plc);
633*49fe348cSAndroid Build Coastguard Worker 
634*49fe348cSAndroid Build Coastguard Worker         lc3_tns_synthesize(dt, bw, &side->tns, xf);
635*49fe348cSAndroid Build Coastguard Worker 
636*49fe348cSAndroid Build Coastguard Worker         lc3_sns_synthesize(dt, sr, &side->sns, xf, xg);
637*49fe348cSAndroid Build Coastguard Worker 
638*49fe348cSAndroid Build Coastguard Worker         lc3_mdct_inverse(dt, sr_pcm, sr, xg, xd, xs);
639*49fe348cSAndroid Build Coastguard Worker 
640*49fe348cSAndroid Build Coastguard Worker     } else {
641*49fe348cSAndroid Build Coastguard Worker         lc3_plc_synthesize(dt, sr, &decoder->plc, xg, xf);
642*49fe348cSAndroid Build Coastguard Worker 
643*49fe348cSAndroid Build Coastguard Worker         memset(xf + ne, 0, (ns - ne) * sizeof(float));
644*49fe348cSAndroid Build Coastguard Worker 
645*49fe348cSAndroid Build Coastguard Worker         lc3_mdct_inverse(dt, sr_pcm, sr, xf, xd, xs);
646*49fe348cSAndroid Build Coastguard Worker     }
647*49fe348cSAndroid Build Coastguard Worker 
648*49fe348cSAndroid Build Coastguard Worker     if (!lc3_hr(sr))
649*49fe348cSAndroid Build Coastguard Worker         lc3_ltpf_synthesize(dt, sr_pcm, nbytes, &decoder->ltpf,
650*49fe348cSAndroid Build Coastguard Worker             side && side->pitch_present ? &side->ltpf : NULL, xh, xs);
651*49fe348cSAndroid Build Coastguard Worker }
652*49fe348cSAndroid Build Coastguard Worker 
653*49fe348cSAndroid Build Coastguard Worker /**
654*49fe348cSAndroid Build Coastguard Worker  * Update decoder state on decoding completion
655*49fe348cSAndroid Build Coastguard Worker  * decoder         Decoder state
656*49fe348cSAndroid Build Coastguard Worker  */
complete(struct lc3_decoder * decoder)657*49fe348cSAndroid Build Coastguard Worker static void complete(struct lc3_decoder *decoder)
658*49fe348cSAndroid Build Coastguard Worker {
659*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = decoder->dt;
660*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr_pcm = decoder->sr_pcm;
661*49fe348cSAndroid Build Coastguard Worker     int nh = lc3_nh(dt, sr_pcm);
662*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr_pcm);
663*49fe348cSAndroid Build Coastguard Worker 
664*49fe348cSAndroid Build Coastguard Worker     decoder->xs_off = decoder->xs_off - decoder->xh_off < nh ?
665*49fe348cSAndroid Build Coastguard Worker         decoder->xs_off + ns : decoder->xh_off;
666*49fe348cSAndroid Build Coastguard Worker }
667*49fe348cSAndroid Build Coastguard Worker 
668*49fe348cSAndroid Build Coastguard Worker /**
669*49fe348cSAndroid Build Coastguard Worker  * Return size needed for a decoder
670*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_decoder_size(bool hrmode,int dt_us,int sr_hz)671*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT unsigned lc3_hr_decoder_size(bool hrmode, int dt_us, int sr_hz)
672*49fe348cSAndroid Build Coastguard Worker {
673*49fe348cSAndroid Build Coastguard Worker     if (resolve_dt(dt_us, hrmode) >= LC3_NUM_DT ||
674*49fe348cSAndroid Build Coastguard Worker         resolve_srate(sr_hz, hrmode) >= LC3_NUM_SRATE)
675*49fe348cSAndroid Build Coastguard Worker         return 0;
676*49fe348cSAndroid Build Coastguard Worker 
677*49fe348cSAndroid Build Coastguard Worker     return sizeof(struct lc3_decoder) +
678*49fe348cSAndroid Build Coastguard Worker         (LC3_DECODER_BUFFER_COUNT(dt_us, sr_hz)-1) * sizeof(float);
679*49fe348cSAndroid Build Coastguard Worker }
680*49fe348cSAndroid Build Coastguard Worker 
lc3_decoder_size(int dt_us,int sr_hz)681*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT unsigned lc3_decoder_size(int dt_us, int sr_hz)
682*49fe348cSAndroid Build Coastguard Worker {
683*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_decoder_size(false, dt_us, sr_hz);
684*49fe348cSAndroid Build Coastguard Worker }
685*49fe348cSAndroid Build Coastguard Worker 
686*49fe348cSAndroid Build Coastguard Worker /**
687*49fe348cSAndroid Build Coastguard Worker  * Setup decoder
688*49fe348cSAndroid Build Coastguard Worker  */
lc3_hr_setup_decoder(bool hrmode,int dt_us,int sr_hz,int sr_pcm_hz,void * mem)689*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT struct lc3_decoder *lc3_hr_setup_decoder(
690*49fe348cSAndroid Build Coastguard Worker     bool hrmode, int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
691*49fe348cSAndroid Build Coastguard Worker {
692*49fe348cSAndroid Build Coastguard Worker     if (sr_pcm_hz <= 0)
693*49fe348cSAndroid Build Coastguard Worker         sr_pcm_hz = sr_hz;
694*49fe348cSAndroid Build Coastguard Worker 
695*49fe348cSAndroid Build Coastguard Worker     enum lc3_dt dt = resolve_dt(dt_us, hrmode);
696*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr = resolve_srate(sr_hz, hrmode);
697*49fe348cSAndroid Build Coastguard Worker     enum lc3_srate sr_pcm = resolve_srate(sr_pcm_hz, hrmode);
698*49fe348cSAndroid Build Coastguard Worker 
699*49fe348cSAndroid Build Coastguard Worker     if (dt >= LC3_NUM_DT || sr_pcm >= LC3_NUM_SRATE || sr > sr_pcm || !mem)
700*49fe348cSAndroid Build Coastguard Worker         return NULL;
701*49fe348cSAndroid Build Coastguard Worker 
702*49fe348cSAndroid Build Coastguard Worker     struct lc3_decoder *decoder = mem;
703*49fe348cSAndroid Build Coastguard Worker     int nh = lc3_nh(dt, sr_pcm);
704*49fe348cSAndroid Build Coastguard Worker     int ns = lc3_ns(dt, sr_pcm);
705*49fe348cSAndroid Build Coastguard Worker     int nd = lc3_nd(dt, sr_pcm);
706*49fe348cSAndroid Build Coastguard Worker 
707*49fe348cSAndroid Build Coastguard Worker     *decoder = (struct lc3_decoder){
708*49fe348cSAndroid Build Coastguard Worker         .dt = dt, .sr = sr,
709*49fe348cSAndroid Build Coastguard Worker         .sr_pcm = sr_pcm,
710*49fe348cSAndroid Build Coastguard Worker 
711*49fe348cSAndroid Build Coastguard Worker         .xh_off = 0,
712*49fe348cSAndroid Build Coastguard Worker         .xs_off = nh,
713*49fe348cSAndroid Build Coastguard Worker         .xd_off = nh + ns,
714*49fe348cSAndroid Build Coastguard Worker         .xg_off = nh + ns + nd,
715*49fe348cSAndroid Build Coastguard Worker     };
716*49fe348cSAndroid Build Coastguard Worker 
717*49fe348cSAndroid Build Coastguard Worker     lc3_plc_reset(&decoder->plc);
718*49fe348cSAndroid Build Coastguard Worker 
719*49fe348cSAndroid Build Coastguard Worker     memset(decoder->x, 0,
720*49fe348cSAndroid Build Coastguard Worker         LC3_DECODER_BUFFER_COUNT(dt_us, sr_pcm_hz) * sizeof(float));
721*49fe348cSAndroid Build Coastguard Worker 
722*49fe348cSAndroid Build Coastguard Worker     return decoder;
723*49fe348cSAndroid Build Coastguard Worker }
724*49fe348cSAndroid Build Coastguard Worker 
lc3_setup_decoder(int dt_us,int sr_hz,int sr_pcm_hz,void * mem)725*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT struct lc3_decoder *lc3_setup_decoder(
726*49fe348cSAndroid Build Coastguard Worker     int dt_us, int sr_hz, int sr_pcm_hz, void *mem)
727*49fe348cSAndroid Build Coastguard Worker {
728*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_setup_decoder(false, dt_us, sr_hz, sr_pcm_hz, mem);
729*49fe348cSAndroid Build Coastguard Worker }
730*49fe348cSAndroid Build Coastguard Worker 
731*49fe348cSAndroid Build Coastguard Worker /**
732*49fe348cSAndroid Build Coastguard Worker  * Decode a frame
733*49fe348cSAndroid Build Coastguard Worker  */
lc3_decode(struct lc3_decoder * decoder,const void * in,int nbytes,enum lc3_pcm_format fmt,void * pcm,int stride)734*49fe348cSAndroid Build Coastguard Worker LC3_EXPORT int lc3_decode(struct lc3_decoder *decoder,
735*49fe348cSAndroid Build Coastguard Worker     const void *in, int nbytes, enum lc3_pcm_format fmt, void *pcm, int stride)
736*49fe348cSAndroid Build Coastguard Worker {
737*49fe348cSAndroid Build Coastguard Worker     static void (* const store[])(struct lc3_decoder *, void *, int) = {
738*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_S16    ] = store_s16,
739*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_S24    ] = store_s24,
740*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_S24_3LE] = store_s24_3le,
741*49fe348cSAndroid Build Coastguard Worker         [LC3_PCM_FORMAT_FLOAT  ] = store_float,
742*49fe348cSAndroid Build Coastguard Worker     };
743*49fe348cSAndroid Build Coastguard Worker 
744*49fe348cSAndroid Build Coastguard Worker     /* --- Check parameters --- */
745*49fe348cSAndroid Build Coastguard Worker 
746*49fe348cSAndroid Build Coastguard Worker     if (!decoder)
747*49fe348cSAndroid Build Coastguard Worker         return -1;
748*49fe348cSAndroid Build Coastguard Worker 
749*49fe348cSAndroid Build Coastguard Worker     if (in && (nbytes < LC3_MIN_FRAME_BYTES ||
750*49fe348cSAndroid Build Coastguard Worker                nbytes > lc3_max_frame_bytes(decoder->dt, decoder->sr) ))
751*49fe348cSAndroid Build Coastguard Worker         return -1;
752*49fe348cSAndroid Build Coastguard Worker 
753*49fe348cSAndroid Build Coastguard Worker     /* --- Processing --- */
754*49fe348cSAndroid Build Coastguard Worker 
755*49fe348cSAndroid Build Coastguard Worker     struct side_data side;
756*49fe348cSAndroid Build Coastguard Worker 
757*49fe348cSAndroid Build Coastguard Worker     int ret = !in || (decode(decoder, in, nbytes, &side) < 0);
758*49fe348cSAndroid Build Coastguard Worker 
759*49fe348cSAndroid Build Coastguard Worker     synthesize(decoder, ret ? NULL : &side, nbytes);
760*49fe348cSAndroid Build Coastguard Worker 
761*49fe348cSAndroid Build Coastguard Worker     store[fmt](decoder, pcm, stride);
762*49fe348cSAndroid Build Coastguard Worker 
763*49fe348cSAndroid Build Coastguard Worker     complete(decoder);
764*49fe348cSAndroid Build Coastguard Worker 
765*49fe348cSAndroid Build Coastguard Worker     return ret;
766*49fe348cSAndroid Build Coastguard Worker }
767