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