xref: /aosp_15_r20/external/liblc3/include/lc3_cpp.h (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 /**
20*49fe348cSAndroid Build Coastguard Worker  * Low Complexity Communication Codec (LC3) - C++ interface
21*49fe348cSAndroid Build Coastguard Worker  */
22*49fe348cSAndroid Build Coastguard Worker 
23*49fe348cSAndroid Build Coastguard Worker #ifndef __LC3_CPP_H
24*49fe348cSAndroid Build Coastguard Worker #define __LC3_CPP_H
25*49fe348cSAndroid Build Coastguard Worker 
26*49fe348cSAndroid Build Coastguard Worker #include <cassert>
27*49fe348cSAndroid Build Coastguard Worker #include <memory>
28*49fe348cSAndroid Build Coastguard Worker #include <vector>
29*49fe348cSAndroid Build Coastguard Worker #include <stdlib.h>
30*49fe348cSAndroid Build Coastguard Worker 
31*49fe348cSAndroid Build Coastguard Worker #include "lc3.h"
32*49fe348cSAndroid Build Coastguard Worker 
33*49fe348cSAndroid Build Coastguard Worker namespace lc3 {
34*49fe348cSAndroid Build Coastguard Worker 
35*49fe348cSAndroid Build Coastguard Worker // PCM Sample Format
36*49fe348cSAndroid Build Coastguard Worker // - Signed 16 bits, in 16 bits words (int16_t)
37*49fe348cSAndroid Build Coastguard Worker // - Signed 24 bits, using low three bytes of 32 bits words (int32_t)
38*49fe348cSAndroid Build Coastguard Worker //   The high byte sign extends (bits 31..24 set to b23)
39*49fe348cSAndroid Build Coastguard Worker // - Signed 24 bits packed in 3 bytes little endian
40*49fe348cSAndroid Build Coastguard Worker // - Floating point 32 bits (float type), in range -1 to 1
41*49fe348cSAndroid Build Coastguard Worker 
42*49fe348cSAndroid Build Coastguard Worker enum class PcmFormat {
43*49fe348cSAndroid Build Coastguard Worker   kS16 = LC3_PCM_FORMAT_S16,
44*49fe348cSAndroid Build Coastguard Worker   kS24 = LC3_PCM_FORMAT_S24,
45*49fe348cSAndroid Build Coastguard Worker   kS24In3Le = LC3_PCM_FORMAT_S24_3LE,
46*49fe348cSAndroid Build Coastguard Worker   kF32 = LC3_PCM_FORMAT_FLOAT
47*49fe348cSAndroid Build Coastguard Worker };
48*49fe348cSAndroid Build Coastguard Worker 
49*49fe348cSAndroid Build Coastguard Worker // Base Encoder/Decoder Class
50*49fe348cSAndroid Build Coastguard Worker template <typename T>
51*49fe348cSAndroid Build Coastguard Worker class Base {
52*49fe348cSAndroid Build Coastguard Worker  protected:
Base(int dt_us,int sr_hz,int sr_pcm_hz,size_t nchannels,bool hrmode)53*49fe348cSAndroid Build Coastguard Worker   Base(int dt_us, int sr_hz, int sr_pcm_hz, size_t nchannels, bool hrmode)
54*49fe348cSAndroid Build Coastguard Worker       : dt_us_(dt_us),
55*49fe348cSAndroid Build Coastguard Worker         sr_hz_(sr_hz),
56*49fe348cSAndroid Build Coastguard Worker         sr_pcm_hz_(sr_pcm_hz == 0 ? sr_hz : sr_pcm_hz),
57*49fe348cSAndroid Build Coastguard Worker         nchannels_(nchannels),
58*49fe348cSAndroid Build Coastguard Worker         hrmode_(hrmode) {
59*49fe348cSAndroid Build Coastguard Worker     states.reserve(nchannels_);
60*49fe348cSAndroid Build Coastguard Worker   }
61*49fe348cSAndroid Build Coastguard Worker 
62*49fe348cSAndroid Build Coastguard Worker   virtual ~Base() = default;
63*49fe348cSAndroid Build Coastguard Worker 
64*49fe348cSAndroid Build Coastguard Worker   int dt_us_, sr_hz_;
65*49fe348cSAndroid Build Coastguard Worker   int sr_pcm_hz_;
66*49fe348cSAndroid Build Coastguard Worker   size_t nchannels_;
67*49fe348cSAndroid Build Coastguard Worker   bool hrmode_;
68*49fe348cSAndroid Build Coastguard Worker 
69*49fe348cSAndroid Build Coastguard Worker   using state_ptr = std::unique_ptr<T, decltype(&free)>;
70*49fe348cSAndroid Build Coastguard Worker   std::vector<state_ptr> states;
71*49fe348cSAndroid Build Coastguard Worker 
72*49fe348cSAndroid Build Coastguard Worker  public:
73*49fe348cSAndroid Build Coastguard Worker   // Return the number of PCM samples in a frame
GetFrameSamples()74*49fe348cSAndroid Build Coastguard Worker   int GetFrameSamples() {
75*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_frame_samples(hrmode_, dt_us_, sr_pcm_hz_); }
76*49fe348cSAndroid Build Coastguard Worker 
77*49fe348cSAndroid Build Coastguard Worker   // Return the size of a frame block, from bitrate
GetFrameBytes(int bitrate)78*49fe348cSAndroid Build Coastguard Worker   int GetFrameBytes(int bitrate) {
79*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_frame_block_bytes(
80*49fe348cSAndroid Build Coastguard Worker         hrmode_, dt_us_, sr_hz_, nchannels_, bitrate); }
81*49fe348cSAndroid Build Coastguard Worker 
82*49fe348cSAndroid Build Coastguard Worker   // Resolve the bitrate, from the size of frame blocks
ResolveBitrate(int nbytes)83*49fe348cSAndroid Build Coastguard Worker   int ResolveBitrate(int nbytes) {
84*49fe348cSAndroid Build Coastguard Worker     return lc3_hr_resolve_bitrate(hrmode_, dt_us_, sr_hz_, nbytes); }
85*49fe348cSAndroid Build Coastguard Worker 
86*49fe348cSAndroid Build Coastguard Worker   // Return algorithmic delay, as a number of samples
GetDelaySamples()87*49fe348cSAndroid Build Coastguard Worker   int GetDelaySamples() {
88*49fe348cSAndroid Build Coastguard Worker       return lc3_hr_delay_samples(hrmode_, dt_us_, sr_pcm_hz_); }
89*49fe348cSAndroid Build Coastguard Worker 
90*49fe348cSAndroid Build Coastguard Worker };  // class Base
91*49fe348cSAndroid Build Coastguard Worker 
92*49fe348cSAndroid Build Coastguard Worker // Encoder Class
93*49fe348cSAndroid Build Coastguard Worker class Encoder : public Base<struct lc3_encoder> {
94*49fe348cSAndroid Build Coastguard Worker   template <typename T>
EncodeImpl(PcmFormat fmt,const T * pcm,int block_size,uint8_t * out)95*49fe348cSAndroid Build Coastguard Worker   int EncodeImpl(PcmFormat fmt, const T *pcm, int block_size, uint8_t *out) {
96*49fe348cSAndroid Build Coastguard Worker     if (states.size() != nchannels_) return -1;
97*49fe348cSAndroid Build Coastguard Worker 
98*49fe348cSAndroid Build Coastguard Worker     enum lc3_pcm_format cfmt = static_cast<lc3_pcm_format>(fmt);
99*49fe348cSAndroid Build Coastguard Worker     int ret = 0;
100*49fe348cSAndroid Build Coastguard Worker 
101*49fe348cSAndroid Build Coastguard Worker     uint8_t *out_ptr = out;
102*49fe348cSAndroid Build Coastguard Worker     for (size_t ich = 0; ich < nchannels_; ich++) {
103*49fe348cSAndroid Build Coastguard Worker       int frame_size = block_size / nchannels_
104*49fe348cSAndroid Build Coastguard Worker           + (ich < block_size % nchannels_);
105*49fe348cSAndroid Build Coastguard Worker 
106*49fe348cSAndroid Build Coastguard Worker       ret |= lc3_encode(states[ich].get(), cfmt, pcm + ich, nchannels_,
107*49fe348cSAndroid Build Coastguard Worker                         frame_size, out_ptr);
108*49fe348cSAndroid Build Coastguard Worker 
109*49fe348cSAndroid Build Coastguard Worker       out_ptr += frame_size;
110*49fe348cSAndroid Build Coastguard Worker     }
111*49fe348cSAndroid Build Coastguard Worker 
112*49fe348cSAndroid Build Coastguard Worker     return ret;
113*49fe348cSAndroid Build Coastguard Worker   }
114*49fe348cSAndroid Build Coastguard Worker 
115*49fe348cSAndroid Build Coastguard Worker  public:
116*49fe348cSAndroid Build Coastguard Worker   // Encoder construction / destruction
117*49fe348cSAndroid Build Coastguard Worker   //
118*49fe348cSAndroid Build Coastguard Worker   // The frame duration `dt_us` is 2500, 5000, 7500 or 10000 us.
119*49fe348cSAndroid Build Coastguard Worker   // The sample rate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
120*49fe348cSAndroid Build Coastguard Worker   // The `hrmode` flag enables the high-resolution mode, in which case
121*49fe348cSAndroid Build Coastguard Worker   // the sample rate is 48000 or 96000 Hz.
122*49fe348cSAndroid Build Coastguard Worker   //
123*49fe348cSAndroid Build Coastguard Worker   // The `sr_pcm_hz` parameter is a downsampling option of PCM input,
124*49fe348cSAndroid Build Coastguard Worker   // the value 0 fallback to the sample rate of the encoded stream `sr_hz`.
125*49fe348cSAndroid Build Coastguard Worker   // When used, `sr_pcm_hz` is intended to be higher or equal to the encoder
126*49fe348cSAndroid Build Coastguard Worker   // sample rate `sr_hz`.
127*49fe348cSAndroid Build Coastguard Worker 
128*49fe348cSAndroid Build Coastguard Worker   Encoder(int dt_us, int sr_hz, int sr_pcm_hz = 0,
129*49fe348cSAndroid Build Coastguard Worker           size_t nchannels = 1, bool hrmode = false)
Base(dt_us,sr_hz,sr_pcm_hz,nchannels,hrmode)130*49fe348cSAndroid Build Coastguard Worker       : Base(dt_us, sr_hz, sr_pcm_hz, nchannels, hrmode) {
131*49fe348cSAndroid Build Coastguard Worker     for (size_t ich = 0; ich < nchannels_; ich++) {
132*49fe348cSAndroid Build Coastguard Worker       auto s = state_ptr((lc3_encoder_t)
133*49fe348cSAndroid Build Coastguard Worker         malloc(lc3_hr_encoder_size(hrmode_, dt_us_, sr_pcm_hz_)), free);
134*49fe348cSAndroid Build Coastguard Worker 
135*49fe348cSAndroid Build Coastguard Worker       if (lc3_hr_setup_encoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
136*49fe348cSAndroid Build Coastguard Worker         states.push_back(std::move(s));
137*49fe348cSAndroid Build Coastguard Worker     }
138*49fe348cSAndroid Build Coastguard Worker   }
139*49fe348cSAndroid Build Coastguard Worker 
140*49fe348cSAndroid Build Coastguard Worker   ~Encoder() override = default;
141*49fe348cSAndroid Build Coastguard Worker 
142*49fe348cSAndroid Build Coastguard Worker   // Reset encoder state
143*49fe348cSAndroid Build Coastguard Worker 
Reset()144*49fe348cSAndroid Build Coastguard Worker   void Reset() {
145*49fe348cSAndroid Build Coastguard Worker     for (auto &s : states)
146*49fe348cSAndroid Build Coastguard Worker       lc3_hr_setup_encoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get());
147*49fe348cSAndroid Build Coastguard Worker   }
148*49fe348cSAndroid Build Coastguard Worker 
149*49fe348cSAndroid Build Coastguard Worker   // Encode
150*49fe348cSAndroid Build Coastguard Worker   //
151*49fe348cSAndroid Build Coastguard Worker   // The input PCM samples are given in signed 16 bits, 24 bits, float,
152*49fe348cSAndroid Build Coastguard Worker   // according the type of `pcm` input buffer, or by selecting a format.
153*49fe348cSAndroid Build Coastguard Worker   //
154*49fe348cSAndroid Build Coastguard Worker   // The PCM samples are read in interleaved way, and consecutive
155*49fe348cSAndroid Build Coastguard Worker   // `nchannels` frames, are output in `out` buffer, of size `buffer_size`.
156*49fe348cSAndroid Build Coastguard Worker   //
157*49fe348cSAndroid Build Coastguard Worker   // The value returned is 0 on successs, -1 otherwise.
158*49fe348cSAndroid Build Coastguard Worker 
Encode(const int16_t * pcm,int block_size,uint8_t * out)159*49fe348cSAndroid Build Coastguard Worker   int Encode(const int16_t *pcm, int block_size, uint8_t *out) {
160*49fe348cSAndroid Build Coastguard Worker     return EncodeImpl(PcmFormat::kS16, pcm, block_size, out);
161*49fe348cSAndroid Build Coastguard Worker   }
162*49fe348cSAndroid Build Coastguard Worker 
Encode(const int32_t * pcm,int block_size,uint8_t * out)163*49fe348cSAndroid Build Coastguard Worker   int Encode(const int32_t *pcm, int block_size, uint8_t *out) {
164*49fe348cSAndroid Build Coastguard Worker     return EncodeImpl(PcmFormat::kS24, pcm, block_size, out);
165*49fe348cSAndroid Build Coastguard Worker   }
166*49fe348cSAndroid Build Coastguard Worker 
Encode(const float * pcm,int block_size,uint8_t * out)167*49fe348cSAndroid Build Coastguard Worker   int Encode(const float *pcm, int block_size, uint8_t *out) {
168*49fe348cSAndroid Build Coastguard Worker     return EncodeImpl(PcmFormat::kF32, pcm, block_size, out);
169*49fe348cSAndroid Build Coastguard Worker   }
170*49fe348cSAndroid Build Coastguard Worker 
Encode(PcmFormat fmt,const void * pcm,int block_size,uint8_t * out)171*49fe348cSAndroid Build Coastguard Worker   int Encode(PcmFormat fmt, const void *pcm, int block_size, uint8_t *out) {
172*49fe348cSAndroid Build Coastguard Worker     uintptr_t pcm_ptr = reinterpret_cast<uintptr_t>(pcm);
173*49fe348cSAndroid Build Coastguard Worker 
174*49fe348cSAndroid Build Coastguard Worker     switch (fmt) {
175*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kS16:
176*49fe348cSAndroid Build Coastguard Worker         assert(pcm_ptr % alignof(int16_t) == 0);
177*49fe348cSAndroid Build Coastguard Worker         return EncodeImpl(fmt, reinterpret_cast<const int16_t *>(pcm),
178*49fe348cSAndroid Build Coastguard Worker                           block_size, out);
179*49fe348cSAndroid Build Coastguard Worker 
180*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kS24:
181*49fe348cSAndroid Build Coastguard Worker         assert(pcm_ptr % alignof(int32_t) == 0);
182*49fe348cSAndroid Build Coastguard Worker         return EncodeImpl(fmt, reinterpret_cast<const int32_t *>(pcm),
183*49fe348cSAndroid Build Coastguard Worker                           block_size, out);
184*49fe348cSAndroid Build Coastguard Worker 
185*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kS24In3Le:
186*49fe348cSAndroid Build Coastguard Worker         return EncodeImpl(fmt, reinterpret_cast<const int8_t(*)[3]>(pcm),
187*49fe348cSAndroid Build Coastguard Worker                           block_size, out);
188*49fe348cSAndroid Build Coastguard Worker 
189*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kF32:
190*49fe348cSAndroid Build Coastguard Worker         assert(pcm_ptr % alignof(float) == 0);
191*49fe348cSAndroid Build Coastguard Worker         return EncodeImpl(fmt, reinterpret_cast<const float *>(pcm), block_size,
192*49fe348cSAndroid Build Coastguard Worker                           out);
193*49fe348cSAndroid Build Coastguard Worker     }
194*49fe348cSAndroid Build Coastguard Worker 
195*49fe348cSAndroid Build Coastguard Worker     return -1;
196*49fe348cSAndroid Build Coastguard Worker   }
197*49fe348cSAndroid Build Coastguard Worker 
198*49fe348cSAndroid Build Coastguard Worker };  // class Encoder
199*49fe348cSAndroid Build Coastguard Worker 
200*49fe348cSAndroid Build Coastguard Worker // Decoder Class
201*49fe348cSAndroid Build Coastguard Worker class Decoder : public Base<struct lc3_decoder> {
202*49fe348cSAndroid Build Coastguard Worker   template <typename T>
DecodeImpl(const uint8_t * in,int block_size,PcmFormat fmt,T * pcm)203*49fe348cSAndroid Build Coastguard Worker   int DecodeImpl(const uint8_t *in, int block_size, PcmFormat fmt, T *pcm) {
204*49fe348cSAndroid Build Coastguard Worker     if (states.size() != nchannels_) return -1;
205*49fe348cSAndroid Build Coastguard Worker 
206*49fe348cSAndroid Build Coastguard Worker     enum lc3_pcm_format cfmt = static_cast<enum lc3_pcm_format>(fmt);
207*49fe348cSAndroid Build Coastguard Worker     int ret = 0;
208*49fe348cSAndroid Build Coastguard Worker 
209*49fe348cSAndroid Build Coastguard Worker     const uint8_t *in_ptr = in;
210*49fe348cSAndroid Build Coastguard Worker     for (size_t ich = 0; ich < nchannels_; ich++) {
211*49fe348cSAndroid Build Coastguard Worker       int frame_size = block_size / nchannels_
212*49fe348cSAndroid Build Coastguard Worker           + (ich < block_size % nchannels_);
213*49fe348cSAndroid Build Coastguard Worker 
214*49fe348cSAndroid Build Coastguard Worker       ret |= lc3_decode(states[ich].get(), in_ptr, frame_size,
215*49fe348cSAndroid Build Coastguard Worker                         cfmt, pcm + ich, nchannels_);
216*49fe348cSAndroid Build Coastguard Worker 
217*49fe348cSAndroid Build Coastguard Worker       in_ptr += frame_size;
218*49fe348cSAndroid Build Coastguard Worker     }
219*49fe348cSAndroid Build Coastguard Worker 
220*49fe348cSAndroid Build Coastguard Worker     return ret;
221*49fe348cSAndroid Build Coastguard Worker   }
222*49fe348cSAndroid Build Coastguard Worker 
223*49fe348cSAndroid Build Coastguard Worker  public:
224*49fe348cSAndroid Build Coastguard Worker   // Decoder construction / destruction
225*49fe348cSAndroid Build Coastguard Worker   //
226*49fe348cSAndroid Build Coastguard Worker   // The frame duration `dt_us` is 2500, 5000, 7500 or 10000 us.
227*49fe348cSAndroid Build Coastguard Worker   // The sample rate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
228*49fe348cSAndroid Build Coastguard Worker   // The `hrmode` flag enables the high-resolution mode, in which case
229*49fe348cSAndroid Build Coastguard Worker   // the sample rate is 48000 or 96000 Hz.
230*49fe348cSAndroid Build Coastguard Worker   //
231*49fe348cSAndroid Build Coastguard Worker   // The `sr_pcm_hz` parameter is an downsampling option of PCM output,
232*49fe348cSAndroid Build Coastguard Worker   // the value 0 fallback to the sample rate of the decoded stream `sr_hz`.
233*49fe348cSAndroid Build Coastguard Worker   // When used, `sr_pcm_hz` is intended to be higher or equal to the decoder
234*49fe348cSAndroid Build Coastguard Worker   // sample rate `sr_hz`.
235*49fe348cSAndroid Build Coastguard Worker 
236*49fe348cSAndroid Build Coastguard Worker   Decoder(int dt_us, int sr_hz, int sr_pcm_hz = 0,
237*49fe348cSAndroid Build Coastguard Worker           size_t nchannels = 1, bool hrmode = false)
Base(dt_us,sr_hz,sr_pcm_hz,nchannels,hrmode)238*49fe348cSAndroid Build Coastguard Worker       : Base(dt_us, sr_hz, sr_pcm_hz, nchannels, hrmode) {
239*49fe348cSAndroid Build Coastguard Worker     for (size_t i = 0; i < nchannels_; i++) {
240*49fe348cSAndroid Build Coastguard Worker       auto s = state_ptr((lc3_decoder_t)
241*49fe348cSAndroid Build Coastguard Worker         malloc(lc3_hr_decoder_size(hrmode_, dt_us_, sr_pcm_hz_)), free);
242*49fe348cSAndroid Build Coastguard Worker 
243*49fe348cSAndroid Build Coastguard Worker       if (lc3_hr_setup_decoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
244*49fe348cSAndroid Build Coastguard Worker         states.push_back(std::move(s));
245*49fe348cSAndroid Build Coastguard Worker     }
246*49fe348cSAndroid Build Coastguard Worker   }
247*49fe348cSAndroid Build Coastguard Worker 
248*49fe348cSAndroid Build Coastguard Worker   ~Decoder() override = default;
249*49fe348cSAndroid Build Coastguard Worker 
250*49fe348cSAndroid Build Coastguard Worker   // Reset decoder state
251*49fe348cSAndroid Build Coastguard Worker 
Reset()252*49fe348cSAndroid Build Coastguard Worker   void Reset() {
253*49fe348cSAndroid Build Coastguard Worker     for (auto &s : states)
254*49fe348cSAndroid Build Coastguard Worker       lc3_hr_setup_decoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get());
255*49fe348cSAndroid Build Coastguard Worker   }
256*49fe348cSAndroid Build Coastguard Worker 
257*49fe348cSAndroid Build Coastguard Worker   // Decode
258*49fe348cSAndroid Build Coastguard Worker   //
259*49fe348cSAndroid Build Coastguard Worker   // Decode a frame block of size `block_size`,
260*49fe348cSAndroid Build Coastguard Worker   // in the `pcm` buffer in interleaved way.
261*49fe348cSAndroid Build Coastguard Worker   //
262*49fe348cSAndroid Build Coastguard Worker   // The PCM samples are output in signed 16 bits, 24 bits, float,
263*49fe348cSAndroid Build Coastguard Worker   // according the type of `pcm` output buffer, or by selecting a format.
264*49fe348cSAndroid Build Coastguard Worker   //
265*49fe348cSAndroid Build Coastguard Worker   // The value returned is 0 on successs, 1 when PLC has been performed,
266*49fe348cSAndroid Build Coastguard Worker   // and -1 otherwise.
267*49fe348cSAndroid Build Coastguard Worker 
Decode(const uint8_t * in,int block_size,int16_t * pcm)268*49fe348cSAndroid Build Coastguard Worker   int Decode(const uint8_t *in, int block_size, int16_t *pcm) {
269*49fe348cSAndroid Build Coastguard Worker     return DecodeImpl(in, block_size, PcmFormat::kS16, pcm);
270*49fe348cSAndroid Build Coastguard Worker   }
271*49fe348cSAndroid Build Coastguard Worker 
Decode(const uint8_t * in,int block_size,int32_t * pcm)272*49fe348cSAndroid Build Coastguard Worker   int Decode(const uint8_t *in, int block_size, int32_t *pcm) {
273*49fe348cSAndroid Build Coastguard Worker     return DecodeImpl(in, block_size, PcmFormat::kS24In3Le, pcm);
274*49fe348cSAndroid Build Coastguard Worker   }
275*49fe348cSAndroid Build Coastguard Worker 
Decode(const uint8_t * in,int block_size,float * pcm)276*49fe348cSAndroid Build Coastguard Worker   int Decode(const uint8_t *in, int block_size, float *pcm) {
277*49fe348cSAndroid Build Coastguard Worker     return DecodeImpl(in, block_size, PcmFormat::kF32, pcm);
278*49fe348cSAndroid Build Coastguard Worker   }
279*49fe348cSAndroid Build Coastguard Worker 
Decode(const uint8_t * in,int block_size,PcmFormat fmt,void * pcm)280*49fe348cSAndroid Build Coastguard Worker   int Decode(const uint8_t *in, int block_size, PcmFormat fmt, void *pcm) {
281*49fe348cSAndroid Build Coastguard Worker     uintptr_t pcm_ptr = reinterpret_cast<uintptr_t>(pcm);
282*49fe348cSAndroid Build Coastguard Worker 
283*49fe348cSAndroid Build Coastguard Worker     switch (fmt) {
284*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kS16:
285*49fe348cSAndroid Build Coastguard Worker         assert(pcm_ptr % alignof(int16_t) == 0);
286*49fe348cSAndroid Build Coastguard Worker         return DecodeImpl(in, block_size, fmt,
287*49fe348cSAndroid Build Coastguard Worker                           reinterpret_cast<int16_t *>(pcm));
288*49fe348cSAndroid Build Coastguard Worker 
289*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kS24:
290*49fe348cSAndroid Build Coastguard Worker         assert(pcm_ptr % alignof(int32_t) == 0);
291*49fe348cSAndroid Build Coastguard Worker         return DecodeImpl(in, block_size, fmt,
292*49fe348cSAndroid Build Coastguard Worker                           reinterpret_cast<int32_t *>(pcm));
293*49fe348cSAndroid Build Coastguard Worker 
294*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kS24In3Le:
295*49fe348cSAndroid Build Coastguard Worker         return DecodeImpl(in, block_size, fmt,
296*49fe348cSAndroid Build Coastguard Worker                           reinterpret_cast<int8_t(*)[3]>(pcm));
297*49fe348cSAndroid Build Coastguard Worker 
298*49fe348cSAndroid Build Coastguard Worker       case PcmFormat::kF32:
299*49fe348cSAndroid Build Coastguard Worker         assert(pcm_ptr % alignof(float) == 0);
300*49fe348cSAndroid Build Coastguard Worker         return DecodeImpl(in, block_size, fmt, reinterpret_cast<float *>(pcm));
301*49fe348cSAndroid Build Coastguard Worker     }
302*49fe348cSAndroid Build Coastguard Worker 
303*49fe348cSAndroid Build Coastguard Worker     return -1;
304*49fe348cSAndroid Build Coastguard Worker   }
305*49fe348cSAndroid Build Coastguard Worker 
306*49fe348cSAndroid Build Coastguard Worker };  // class Decoder
307*49fe348cSAndroid Build Coastguard Worker 
308*49fe348cSAndroid Build Coastguard Worker }  // namespace lc3
309*49fe348cSAndroid Build Coastguard Worker 
310*49fe348cSAndroid Build Coastguard Worker #endif /* __LC3_CPP_H */
311