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