xref: /btstack/src/btstack_lc3plus_fraunhofer.c (revision d60a1028c7699fe210efeebd03e9fb2be1fe3e5e)
1*d60a1028SMatthias Ringwald /*
2*d60a1028SMatthias Ringwald  * Copyright (C) 2022 BlueKitchen GmbH
3*d60a1028SMatthias Ringwald  *
4*d60a1028SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*d60a1028SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*d60a1028SMatthias Ringwald  * are met:
7*d60a1028SMatthias Ringwald  *
8*d60a1028SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*d60a1028SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*d60a1028SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*d60a1028SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*d60a1028SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*d60a1028SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*d60a1028SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*d60a1028SMatthias Ringwald  *    from this software without specific prior written permission.
16*d60a1028SMatthias Ringwald  *
17*d60a1028SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
18*d60a1028SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*d60a1028SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20*d60a1028SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
21*d60a1028SMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22*d60a1028SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23*d60a1028SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24*d60a1028SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25*d60a1028SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26*d60a1028SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27*d60a1028SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*d60a1028SMatthias Ringwald  * SUCH DAMAGE.
29*d60a1028SMatthias Ringwald  *
30*d60a1028SMatthias Ringwald  */
31*d60a1028SMatthias Ringwald 
32*d60a1028SMatthias Ringwald #define BTSTACK_FILE__ "btstack_lc3_plus_fraunhofer.c"
33*d60a1028SMatthias Ringwald 
34*d60a1028SMatthias Ringwald /**
35*d60a1028SMatthias Ringwald  * @title LC3 Plus Fraunhofer Adapter
36*d60a1028SMatthias Ringwald  */
37*d60a1028SMatthias Ringwald 
38*d60a1028SMatthias Ringwald #include "btstack_config.h"
39*d60a1028SMatthias Ringwald #include "bluetooth.h"
40*d60a1028SMatthias Ringwald 
41*d60a1028SMatthias Ringwald #include "btstack_lc3plus_fraunhofer.h"
42*d60a1028SMatthias Ringwald #include "btstack_debug.h"
43*d60a1028SMatthias Ringwald #include <string.h>
44*d60a1028SMatthias Ringwald 
45*d60a1028SMatthias Ringwald #ifdef HAVE_LC3PLUS
46*d60a1028SMatthias Ringwald 
47*d60a1028SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480
48*d60a1028SMatthias Ringwald 
49*d60a1028SMatthias Ringwald static uint8_t lc3plus_farunhofer_scratch[LC3PLUS_DEC_MAX_SCRATCH_SIZE];
50*d60a1028SMatthias Ringwald 
51*d60a1028SMatthias Ringwald static uint16_t lc3_frame_duration_in_us(btstack_lc3_frame_duration_t frame_duration){
52*d60a1028SMatthias Ringwald     switch (frame_duration) {
53*d60a1028SMatthias Ringwald         case BTSTACK_LC3_FRAME_DURATION_7500US:
54*d60a1028SMatthias Ringwald             return 7500;
55*d60a1028SMatthias Ringwald         case BTSTACK_LC3_FRAME_DURATION_10000US:
56*d60a1028SMatthias Ringwald             return 10000;
57*d60a1028SMatthias Ringwald         default:
58*d60a1028SMatthias Ringwald             return 0;
59*d60a1028SMatthias Ringwald     }
60*d60a1028SMatthias Ringwald }
61*d60a1028SMatthias Ringwald 
62*d60a1028SMatthias Ringwald /* Decoder implementation */
63*d60a1028SMatthias Ringwald 
64*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_decoder_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame){
65*d60a1028SMatthias Ringwald     btstack_lc3plus_fraunhofer_decoder_t * instance = (btstack_lc3plus_fraunhofer_decoder_t *) context;
66*d60a1028SMatthias Ringwald     LC3PLUS_Dec * decoder = (LC3PLUS_Dec*) instance->decoder;
67*d60a1028SMatthias Ringwald 
68*d60a1028SMatthias Ringwald     // map frame duration
69*d60a1028SMatthias Ringwald     uint16_t duration_us = lc3_frame_duration_in_us(frame_duration);
70*d60a1028SMatthias Ringwald     if (duration_us == 0){
71*d60a1028SMatthias Ringwald         return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
72*d60a1028SMatthias Ringwald     }
73*d60a1028SMatthias Ringwald 
74*d60a1028SMatthias Ringwald     // store config
75*d60a1028SMatthias Ringwald     instance->sample_rate = sample_rate;
76*d60a1028SMatthias Ringwald     instance->frame_duration = frame_duration;
77*d60a1028SMatthias Ringwald     instance->octets_per_frame = octets_per_frame;
78*d60a1028SMatthias Ringwald     instance->samples_per_frame = btstack_lc3_samples_per_frame(sample_rate, frame_duration);
79*d60a1028SMatthias Ringwald 
80*d60a1028SMatthias Ringwald     LC3PLUS_Error error;
81*d60a1028SMatthias Ringwald     error = lc3plus_dec_init(decoder, sample_rate, 1, LC3PLUS_PLC_ADVANCED, 0);
82*d60a1028SMatthias Ringwald     btstack_assert(error == LC3PLUS_OK);
83*d60a1028SMatthias Ringwald 
84*d60a1028SMatthias Ringwald     error = lc3plus_dec_set_frame_dms(decoder, duration_us / 100);
85*d60a1028SMatthias Ringwald     btstack_assert(error == LC3PLUS_OK);
86*d60a1028SMatthias Ringwald 
87*d60a1028SMatthias Ringwald     return ERROR_CODE_SUCCESS;
88*d60a1028SMatthias Ringwald }
89*d60a1028SMatthias Ringwald 
90*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_decoder_decode_signed_16(void * context, const uint8_t *bytes, uint8_t BFI, int16_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) {
91*d60a1028SMatthias Ringwald     btstack_lc3plus_fraunhofer_decoder_t *instance = (btstack_lc3plus_fraunhofer_decoder_t *) context;
92*d60a1028SMatthias Ringwald     LC3PLUS_Dec *decoder = (LC3PLUS_Dec *) instance->decoder;
93*d60a1028SMatthias Ringwald 
94*d60a1028SMatthias Ringwald     // temporary output buffer to interleave samples for caller
95*d60a1028SMatthias Ringwald     int16_t temp_out[MAX_SAMPLES_PER_FRAME];
96*d60a1028SMatthias Ringwald 
97*d60a1028SMatthias Ringwald     // output_samples: array of channel buffers. use temp_out if stride is used
98*d60a1028SMatthias Ringwald     int16_t *output_samples[1];
99*d60a1028SMatthias Ringwald     if (stride > 1) {
100*d60a1028SMatthias Ringwald         output_samples[0] = temp_out;
101*d60a1028SMatthias Ringwald     } else {
102*d60a1028SMatthias Ringwald         output_samples[0] = pcm_out;
103*d60a1028SMatthias Ringwald     }
104*d60a1028SMatthias Ringwald 
105*d60a1028SMatthias Ringwald     // trigger plc if BFI by passing 0 valid input bytes
106*d60a1028SMatthias Ringwald     uint16_t byte_count = instance->octets_per_frame;
107*d60a1028SMatthias Ringwald     if (BFI != 0){
108*d60a1028SMatthias Ringwald         byte_count = 0;
109*d60a1028SMatthias Ringwald     }
110*d60a1028SMatthias Ringwald 
111*d60a1028SMatthias Ringwald     LC3PLUS_Error error = lc3plus_dec16(decoder, (void*) bytes, byte_count, output_samples, lc3plus_farunhofer_scratch, BFI);
112*d60a1028SMatthias Ringwald 
113*d60a1028SMatthias Ringwald     // store samples
114*d60a1028SMatthias Ringwald     if (stride > 1){
115*d60a1028SMatthias Ringwald         uint16_t i;
116*d60a1028SMatthias Ringwald         for (i = 0; i < instance->samples_per_frame; i++){
117*d60a1028SMatthias Ringwald             pcm_out [i * stride] = temp_out[i];
118*d60a1028SMatthias Ringwald         }
119*d60a1028SMatthias Ringwald     }
120*d60a1028SMatthias Ringwald 
121*d60a1028SMatthias Ringwald     // map error
122*d60a1028SMatthias Ringwald     switch (error){
123*d60a1028SMatthias Ringwald         case LC3PLUS_OK:
124*d60a1028SMatthias Ringwald             // success
125*d60a1028SMatthias Ringwald             return ERROR_CODE_SUCCESS;
126*d60a1028SMatthias Ringwald         case LC3PLUS_DECODE_ERROR:
127*d60a1028SMatthias Ringwald             // PLC enagaged
128*d60a1028SMatthias Ringwald             *BEC_detect = 1;
129*d60a1028SMatthias Ringwald             return ERROR_CODE_SUCCESS;
130*d60a1028SMatthias Ringwald         default:
131*d60a1028SMatthias Ringwald             return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
132*d60a1028SMatthias Ringwald     }
133*d60a1028SMatthias Ringwald }
134*d60a1028SMatthias Ringwald 
135*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_decoder_decode_signed_24(void * context, const uint8_t *bytes, uint8_t BFI, int32_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) {
136*d60a1028SMatthias Ringwald     btstack_lc3plus_fraunhofer_decoder_t * instance = (btstack_lc3plus_fraunhofer_decoder_t *) context;
137*d60a1028SMatthias Ringwald     LC3PLUS_Dec * decoder = (LC3PLUS_Dec*) instance->decoder;
138*d60a1028SMatthias Ringwald 
139*d60a1028SMatthias Ringwald     // output_samples: array of channel buffers.
140*d60a1028SMatthias Ringwald     int32_t * output_samples[1];
141*d60a1028SMatthias Ringwald     output_samples[0] = pcm_out;
142*d60a1028SMatthias Ringwald 
143*d60a1028SMatthias Ringwald     // trigger plc if BFI by passing 0 valid input bytes
144*d60a1028SMatthias Ringwald     uint16_t byte_count = instance->octets_per_frame;
145*d60a1028SMatthias Ringwald     if (BFI != 0){
146*d60a1028SMatthias Ringwald         byte_count = 0;
147*d60a1028SMatthias Ringwald     }
148*d60a1028SMatthias Ringwald 
149*d60a1028SMatthias Ringwald     LC3PLUS_Error error = lc3plus_dec24(decoder, (void *) bytes, byte_count, output_samples, lc3plus_farunhofer_scratch, BFI);
150*d60a1028SMatthias Ringwald 
151*d60a1028SMatthias Ringwald     // map error
152*d60a1028SMatthias Ringwald     switch (error){
153*d60a1028SMatthias Ringwald         case LC3PLUS_OK:
154*d60a1028SMatthias Ringwald             // success
155*d60a1028SMatthias Ringwald             return ERROR_CODE_SUCCESS;
156*d60a1028SMatthias Ringwald         case LC3PLUS_DECODE_ERROR:
157*d60a1028SMatthias Ringwald             // PLC enagaged
158*d60a1028SMatthias Ringwald             *BEC_detect = 1;
159*d60a1028SMatthias Ringwald             return ERROR_CODE_SUCCESS;
160*d60a1028SMatthias Ringwald         default:
161*d60a1028SMatthias Ringwald             return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
162*d60a1028SMatthias Ringwald     }
163*d60a1028SMatthias Ringwald }
164*d60a1028SMatthias Ringwald 
165*d60a1028SMatthias Ringwald static const btstack_lc3_decoder_t btstack_l3cplus_fraunhofer_decoder_instance = {
166*d60a1028SMatthias Ringwald         lc3plus_fraunhofer_decoder_configure,
167*d60a1028SMatthias Ringwald         lc3plus_fraunhofer_decoder_decode_signed_16,
168*d60a1028SMatthias Ringwald         lc3plus_fraunhofer_decoder_decode_signed_24
169*d60a1028SMatthias Ringwald };
170*d60a1028SMatthias Ringwald 
171*d60a1028SMatthias Ringwald const btstack_lc3_decoder_t * btstack_lc3plus_fraunhofer_decoder_init_instance(btstack_lc3plus_fraunhofer_decoder_t * context){
172*d60a1028SMatthias Ringwald     memset(context, 0, sizeof(btstack_lc3plus_fraunhofer_decoder_t));
173*d60a1028SMatthias Ringwald     return &btstack_l3cplus_fraunhofer_decoder_instance;
174*d60a1028SMatthias Ringwald }
175*d60a1028SMatthias Ringwald 
176*d60a1028SMatthias Ringwald /* Encoder implementation */
177*d60a1028SMatthias Ringwald 
178*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_encoder_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame){
179*d60a1028SMatthias Ringwald     btstack_lc3plus_fraunhofer_encoder_t * instance = (btstack_lc3plus_fraunhofer_encoder_t *) context;
180*d60a1028SMatthias Ringwald     return ERROR_CODE_COMMAND_DISALLOWED;
181*d60a1028SMatthias Ringwald }
182*d60a1028SMatthias Ringwald 
183*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_encoder_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes){
184*d60a1028SMatthias Ringwald     return ERROR_CODE_COMMAND_DISALLOWED;
185*d60a1028SMatthias Ringwald }
186*d60a1028SMatthias Ringwald 
187*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_encoder_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes) {
188*d60a1028SMatthias Ringwald     return ERROR_CODE_COMMAND_DISALLOWED;
189*d60a1028SMatthias Ringwald }
190*d60a1028SMatthias Ringwald 
191*d60a1028SMatthias Ringwald static const btstack_lc3_encoder_t btstack_l3cplus_fraunhofer_encoder_instance = {
192*d60a1028SMatthias Ringwald         lc3plus_fraunhofer_encoder_configure,
193*d60a1028SMatthias Ringwald         lc3plus_fraunhofer_encoder_encode_signed_16,
194*d60a1028SMatthias Ringwald         lc3plus_fraunhofer_encoder_encode_signed_24
195*d60a1028SMatthias Ringwald };
196*d60a1028SMatthias Ringwald 
197*d60a1028SMatthias Ringwald const btstack_lc3_encoder_t * btstack_lc3plus_fraunhofer_encoder_init_instance(btstack_lc3plus_fraunhofer_encoder_t * context){
198*d60a1028SMatthias Ringwald     memset(context, 0, sizeof(btstack_lc3plus_fraunhofer_encoder_t));
199*d60a1028SMatthias Ringwald     return &btstack_l3cplus_fraunhofer_encoder_instance;
200*d60a1028SMatthias Ringwald }
201*d60a1028SMatthias Ringwald 
202*d60a1028SMatthias Ringwald #endif /* HAVE_LC3PLUS */
203