1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "bta/le_audio/broadcaster/broadcaster_types.h"
19 #include "bta/le_audio/le_audio_types.h"
20 
21 namespace bluetooth::le_audio {
22 namespace broadcaster {
23 
24 constexpr types::LeAudioCodecId kLeAudioCodecIdLc3 = {
25     .coding_format = types::kLeAudioCodingFormatLC3,
26     .vendor_company_id = types::kLeAudioVendorCompanyIdUndefined,
27     .vendor_codec_id = types::kLeAudioVendorCodecIdUndefined};
28 
29 // Quality subgroup configurations
30 static const BroadcastSubgroupCodecConfig lc3_mono_16_2 =
31     BroadcastSubgroupCodecConfig(
32         kLeAudioCodecIdLc3,
33         {BroadcastSubgroupBisCodecConfig{
34             // num_bis
35             1,
36             // bis_channel_cnt_
37             1,
38             // codec_specific
39             types::LeAudioLtvMap({
40                 LTV_ENTRY_SAMPLING_FREQUENCY(
41                     codec_spec_conf::kLeAudioSamplingFreq16000Hz),
42                 LTV_ENTRY_FRAME_DURATION(
43                     codec_spec_conf::kLeAudioCodecFrameDur10000us),
44                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(40),
45             }),
46         }},
47         // bits_per_sample
48         16);
49 
50 static const BroadcastSubgroupCodecConfig lc3_stereo_16_2 =
51     BroadcastSubgroupCodecConfig(
52         kLeAudioCodecIdLc3,
53         {BroadcastSubgroupBisCodecConfig{
54             // num_bis
55             2,
56             // bis_channel_cnt_
57             1,
58             // codec_specific
59             types::LeAudioLtvMap({
60                 LTV_ENTRY_SAMPLING_FREQUENCY(
61                     codec_spec_conf::kLeAudioSamplingFreq16000Hz),
62                 LTV_ENTRY_FRAME_DURATION(
63                     codec_spec_conf::kLeAudioCodecFrameDur10000us),
64                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(40),
65             }),
66         }},
67         // bits_per_sample
68         16);
69 
70 static const BroadcastSubgroupCodecConfig lc3_stereo_24_2 =
71     BroadcastSubgroupCodecConfig(
72         kLeAudioCodecIdLc3,
73         {BroadcastSubgroupBisCodecConfig{
74             // num_bis
75             2,
76             // bis_channel_cnt_
77             1,
78             // codec_specific
79             types::LeAudioLtvMap({
80                 LTV_ENTRY_SAMPLING_FREQUENCY(
81                     codec_spec_conf::kLeAudioSamplingFreq24000Hz),
82                 LTV_ENTRY_FRAME_DURATION(
83                     codec_spec_conf::kLeAudioCodecFrameDur10000us),
84                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(60),
85             }),
86         }},
87         // bits_per_sample
88         16);
89 
90 static const BroadcastSubgroupCodecConfig lc3_stereo_48_1 =
91     BroadcastSubgroupCodecConfig(
92         kLeAudioCodecIdLc3,
93         {BroadcastSubgroupBisCodecConfig{
94             // num_bis
95             2,
96             // bis_channel_cnt_
97             1,
98             // codec_specific
99             types::LeAudioLtvMap({
100                 LTV_ENTRY_SAMPLING_FREQUENCY(
101                     codec_spec_conf::kLeAudioSamplingFreq48000Hz),
102                 LTV_ENTRY_FRAME_DURATION(
103                     codec_spec_conf::kLeAudioCodecFrameDur7500us),
104                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(75),
105             }),
106         }},
107         // bits_per_sample
108         16);
109 
110 static const BroadcastSubgroupCodecConfig lc3_stereo_48_2 =
111     BroadcastSubgroupCodecConfig(
112         kLeAudioCodecIdLc3,
113         {BroadcastSubgroupBisCodecConfig{
114             // num_bis
115             2,
116             // bis_channel_cnt_
117             1,
118             // codec_specific
119             types::LeAudioLtvMap({
120                 LTV_ENTRY_SAMPLING_FREQUENCY(
121                     codec_spec_conf::kLeAudioSamplingFreq48000Hz),
122                 LTV_ENTRY_FRAME_DURATION(
123                     codec_spec_conf::kLeAudioCodecFrameDur10000us),
124                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(100),
125             }),
126         }},
127         // bits_per_sample
128         16);
129 
130 static const BroadcastSubgroupCodecConfig lc3_stereo_48_3 =
131     BroadcastSubgroupCodecConfig(
132         kLeAudioCodecIdLc3,
133         {BroadcastSubgroupBisCodecConfig{
134             // num_bis
135             2,
136             // bis_channel_cnt_
137             1,
138             // codec_specific
139             types::LeAudioLtvMap({
140                 LTV_ENTRY_SAMPLING_FREQUENCY(
141                     codec_spec_conf::kLeAudioSamplingFreq48000Hz),
142                 LTV_ENTRY_FRAME_DURATION(
143                     codec_spec_conf::kLeAudioCodecFrameDur7500us),
144                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(90),
145             }),
146         }},
147         // bits_per_sample
148         16);
149 
150 static const BroadcastSubgroupCodecConfig lc3_stereo_48_4 =
151     BroadcastSubgroupCodecConfig(
152         kLeAudioCodecIdLc3,
153         {BroadcastSubgroupBisCodecConfig{
154             // num_bis
155             2,
156             // bis_channel_cnt_
157             1,
158             // codec_specific
159             types::LeAudioLtvMap({
160                 LTV_ENTRY_SAMPLING_FREQUENCY(
161                     codec_spec_conf::kLeAudioSamplingFreq48000Hz),
162                 LTV_ENTRY_FRAME_DURATION(
163                     codec_spec_conf::kLeAudioCodecFrameDur10000us),
164                 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(120),
165             }),
166         }},
167         // bits_per_sample
168         16);
169 
170 static const types::DataPathConfiguration lc3_data_path = {
171     .dataPathId = bluetooth::hci::iso_manager::kIsoDataPathHci,
172     .dataPathConfig = {},
173     .isoDataPathConfig =
174         {
175             .codecId = kLeAudioCodecIdLc3,
176             .isTransparent = true,
177             .controllerDelayUs = 0x00000000,  // irrlevant for transparent mode
178             .configuration = {},
179         },
180 };
181 
182 static const BroadcastQosConfig qos_config_2_10 = BroadcastQosConfig(2, 10);
183 static const BroadcastQosConfig qos_config_4_45 = BroadcastQosConfig(4, 45);
184 static const BroadcastQosConfig qos_config_4_50 = BroadcastQosConfig(4, 50);
185 static const BroadcastQosConfig qos_config_4_60 = BroadcastQosConfig(4, 60);
186 static const BroadcastQosConfig qos_config_4_65 = BroadcastQosConfig(4, 65);
187 
188 // Standard single subgroup configurations
189 static const BroadcastConfiguration lc3_mono_16_2_1 = {
190     // subgroup list, qos configuration, data path configuration
191     .subgroups = {lc3_mono_16_2},
192     .qos = qos_config_2_10,
193     .data_path = lc3_data_path,
194     .sduIntervalUs = 10000,
195     .maxSduOctets = 40,
196     .phy = 0x02,   // PHY_LE_2M
197     .packing = 0,  // Sequential
198     .framing = 0,  // Unframed
199 };
200 
201 static const BroadcastConfiguration lc3_mono_16_2_2 = {
202     // subgroup list, qos configuration, data path configuration
203     .subgroups = {lc3_mono_16_2},
204     .qos = qos_config_4_60,
205     .data_path = lc3_data_path,
206     .sduIntervalUs = 10000,
207     .maxSduOctets = 40,
208     .phy = 0x02,   // PHY_LE_2M
209     .packing = 0,  // Sequential
210     .framing = 0,  // Unframed
211 };
212 
213 static const BroadcastConfiguration lc3_stereo_16_2_2 = {
214     // subgroup list, qos configuration, data path configuration
215     .subgroups = {lc3_stereo_16_2},
216     .qos = qos_config_4_60,
217     .data_path = lc3_data_path,
218     .sduIntervalUs = 10000,
219     .maxSduOctets = 80,
220     .phy = 0x02,   // PHY_LE_2M
221     .packing = 0,  // Sequential
222     .framing = 0,  // Unframed
223 };
224 
225 static const BroadcastConfiguration lc3_stereo_24_2_1 = {
226     // subgroup list, qos configuration, data path configuration
227     .subgroups = {lc3_stereo_24_2},
228     .qos = qos_config_2_10,
229     .data_path = lc3_data_path,
230     .sduIntervalUs = 10000,
231     .maxSduOctets = 120,
232     .phy = 0x02,   // PHY_LE_2M
233     .packing = 0,  // Sequential
234     .framing = 0,  // Unframed
235 };
236 
237 static const BroadcastConfiguration lc3_stereo_24_2_2 = {
238     // subgroup list, qos configuration, data path configuration
239     .subgroups = {lc3_stereo_24_2},
240     .qos = qos_config_4_60,
241     .data_path = lc3_data_path,
242     .sduIntervalUs = 10000,
243     .maxSduOctets = 120,
244     .phy = 0x02,   // PHY_LE_2M
245     .packing = 0,  // Sequential
246     .framing = 0,  // Unframed
247 };
248 
249 static const BroadcastConfiguration lc3_stereo_48_1_2 = {
250     // subgroup list, qos configuration, data path configuration
251     .subgroups = {lc3_stereo_48_1},
252     .qos = qos_config_4_50,
253     .data_path = lc3_data_path,
254     .sduIntervalUs = 10000,
255     .maxSduOctets = 150,
256     .phy = 0x02,   // PHY_LE_2M
257     .packing = 0,  // Sequential
258     .framing = 0   // Unframed,
259 };
260 
261 static const BroadcastConfiguration lc3_stereo_48_2_2 = {
262     // subgroup list, qos configuration, data path configuration
263     .subgroups = {lc3_stereo_48_2},
264     .qos = qos_config_4_65,
265     .data_path = lc3_data_path,
266     .sduIntervalUs = 10000,
267     .maxSduOctets = 200,
268     .phy = 0x02,   // PHY_LE_2M
269     .packing = 0,  // Sequential
270     .framing = 0   // Unframed,
271 };
272 
273 static const BroadcastConfiguration lc3_stereo_48_3_2 = {
274     // subgroup list, qos configuration, data path configuration
275     .subgroups = {lc3_stereo_48_3},
276     .qos = qos_config_4_50,
277     .data_path = lc3_data_path,
278     .sduIntervalUs = 10000,
279     .maxSduOctets = 180,
280     .phy = 0x02,   // PHY_LE_2M
281     .packing = 0,  // Sequential
282     .framing = 0   // Unframed,
283 };
284 
285 static const BroadcastConfiguration lc3_stereo_48_4_2 = {
286     // subgroup list, qos configuration, data path configuration
287     .subgroups = {lc3_stereo_48_4},
288     .qos = qos_config_4_65,
289     .data_path = lc3_data_path,
290     .sduIntervalUs = 10000,
291     .maxSduOctets = 240,
292     .phy = 0x02,   // PHY_LE_2M
293     .packing = 0,  // Sequential
294     .framing = 0   // Unframed,
295 };
296 
297 // Takes a list of subgroup requirements (audio context, quality index)
298 BroadcastConfiguration GetBroadcastConfig(
299     const std::vector<std::pair<types::LeAudioContextType, uint8_t>>&
300         subgroup_quality);
301 
302 }  // namespace broadcaster
303 }  // namespace bluetooth::le_audio
304