Loading bluetooth/audio/utils/Android.bp +80 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ cc_library_shared { "aidl_session/BluetoothAudioSession.cpp", "aidl_session/HidlToAidlMiddleware.cpp", "aidl_session/BluetoothLeAudioCodecsProvider.cpp", "aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp", ], export_include_dirs: ["aidl_session/"], header_libs: [ Loading @@ -61,9 +62,13 @@ cc_library_shared { "liblog", "libhidlbase", "libxml2", "libflatbuffers-cpp", ], generated_sources: ["le_audio_codec_capabilities"], generated_headers: ["le_audio_codec_capabilities"], generated_headers: [ "le_audio_codec_capabilities", "AIDLLeAudioSetConfigSchemas_h", ], } cc_test { Loading Loading @@ -98,3 +103,77 @@ xsd_config { api_dir: "le_audio_codec_capabilities/schema", root_elements: ["leAudioOffloadSetting"], } genrule { name: "AIDLLeAudioSetConfigSchemas_h", tools: [ "flatc", ], cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -o $(genDir) --cpp $(in) ", srcs: [ "le_audio_configuration_set/audio_set_configurations.fbs", "le_audio_configuration_set/audio_set_scenarios.fbs", ], out: [ "audio_set_configurations_generated.h", "audio_set_scenarios_generated.h", ], } // Binary generation genrule { name: "AIDLLeAudioSetScenariosSchema_bfbs", tools: [ "flatc", ], cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -b --schema -o $(genDir) $(in) ", srcs: [ "le_audio_configuration_set/audio_set_scenarios.fbs", ], out: [ "audio_set_scenarios.bfbs", ], } genrule { name: "AIDLLeAudioSetConfigsSchema_bfbs", tools: [ "flatc", ], cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -b --schema -o $(genDir) $(in) ", srcs: [ "le_audio_configuration_set/audio_set_configurations.fbs", ], out: [ "audio_set_configurations.bfbs", ], } // Add to prebuilt etc prebuilt_etc { name: "aidl_audio_set_scenarios_bfbs", src: ":AIDLLeAudioSetScenariosSchema_bfbs", filename: "aidl_audio_set_scenarios.bfbs", sub_dir: "aidl/le_audio", } prebuilt_etc { name: "aidl_audio_set_scenarios_json", src: "le_audio_configuration_set/audio_set_scenarios.json", filename: "aidl_audio_set_scenarios.json", sub_dir: "aidl/le_audio", } prebuilt_etc { name: "aidl_audio_set_configurations_bfbs", src: ":AIDLLeAudioSetConfigsSchema_bfbs", filename: "aidl_audio_set_configurations.bfbs", sub_dir: "aidl/le_audio", } prebuilt_etc { name: "aidl_audio_set_configurations_json", src: "le_audio_configuration_set/audio_set_configurations.json", filename: "aidl_audio_set_configurations.json", sub_dir: "aidl/le_audio", } bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h> #include <android-base/logging.h> #include "BluetoothLeAudioAseConfigurationSettingProvider.h" #include "BluetoothLeAudioCodecsProvider.h" namespace aidl { Loading Loading @@ -438,6 +439,12 @@ std::vector<CodecInfo> BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo( return codec_info_map_iter->second; } std::vector<LeAudioAseConfigurationSetting> BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings() { return AudioSetConfigurationProviderJson:: GetLeAudioAseConfigurationSettings(); } } // namespace audio } // namespace bluetooth } // namespace hardware Loading bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h +7 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h> #include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/CodecInfo.h> #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/OpusConfiguration.h> Loading @@ -34,6 +35,9 @@ namespace hardware { namespace bluetooth { namespace audio { using LeAudioAseConfigurationSetting = IBluetoothAudioProvider::LeAudioAseConfigurationSetting; class BluetoothAudioCodecs { public: static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities(); Loading @@ -50,6 +54,9 @@ class BluetoothAudioCodecs { static std::vector<CodecInfo> GetLeAudioOffloadCodecInfo( const SessionType& session_type); static std::vector<LeAudioAseConfigurationSetting> GetLeAudioAseConfigurationSettings(); private: template <typename T> struct identity { Loading bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h 0 → 100644 +125 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h> #include <map> #include <mutex> #include <optional> #include <string> #include <string_view> #include <tuple> #include "audio_set_configurations_generated.h" #include "audio_set_scenarios_generated.h" namespace aidl { namespace android { namespace hardware { namespace bluetooth { namespace audio { using LeAudioAseConfigurationSetting = IBluetoothAudioProvider::LeAudioAseConfigurationSetting; using AseDirectionConfiguration = IBluetoothAudioProvider:: LeAudioAseConfigurationSetting::AseDirectionConfiguration; using LeAudioAseQosConfiguration = IBluetoothAudioProvider::LeAudioAseQosConfiguration; using LeAudioDataPathConfiguration = IBluetoothAudioProvider::LeAudioDataPathConfiguration; enum class CodecLocation { HOST, ADSP, CONTROLLER, }; class AudioSetConfigurationProviderJson { public: static std::vector<LeAudioAseConfigurationSetting> GetLeAudioAseConfigurationSettings(); private: static void LoadAudioSetConfigurationProviderJson(); static const le_audio::CodecSpecificConfiguration* LookupCodecSpecificParam( const flatbuffers::Vector<flatbuffers::Offset< le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params, le_audio::CodecSpecificLtvGenericTypes type); static void populateAudioChannelAllocation( CodecSpecificConfigurationLtv::AudioChannelAllocation& audio_channel_allocation, uint32_t audio_location); static void populateConfigurationData( LeAudioAseConfiguration& ase, const flatbuffers::Vector< flatbuffers::Offset<le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params); static void populateAseConfiguration( LeAudioAseConfiguration& ase, const le_audio::AudioSetSubConfiguration* flat_subconfig, const le_audio::QosConfiguration* qos_cfg); static void populateAseQosConfiguration( LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg); static AseDirectionConfiguration SetConfigurationFromFlatSubconfig( const le_audio::AudioSetSubConfiguration* flat_subconfig, const le_audio::QosConfiguration* qos_cfg, CodecLocation location); static void processSubconfig( const le_audio::AudioSetSubConfiguration* subconfig, const le_audio::QosConfiguration* qos_cfg, std::vector<std::optional<AseDirectionConfiguration>>& directionAseConfiguration, CodecLocation location); static void PopulateAseConfigurationFromFlat( const le_audio::AudioSetConfiguration* flat_cfg, std::vector<const le_audio::CodecConfiguration*>* codec_cfgs, std::vector<const le_audio::QosConfiguration*>* qos_cfgs, CodecLocation location, std::vector<std::optional<AseDirectionConfiguration>>& sourceAseConfiguration, std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration, ConfigurationFlags& configurationFlags); static bool LoadConfigurationsFromFiles(const char* schema_file, const char* content_file, CodecLocation location); static bool LoadScenariosFromFiles(const char* schema_file, const char* content_file); static bool LoadContent( std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> config_files, std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> scenario_files, CodecLocation location); }; } // namespace audio } // namespace bluetooth } // namespace hardware } // namespace android } // namespace aidl bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs 0 → 100644 +91 −0 Original line number Diff line number Diff line /* * Copyright (c) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ namespace aidl.android.hardware.bluetooth.audio.le_audio; enum CodecSpecificLtvGenericTypes : byte { SUPPORTED_SAMPLING_FREQUENCY = 0x01, SUPPORTED_FRAME_DURATION = 0x02, SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 0x03, SUPPORTED_OCTETS_PER_CODEC_FRAME = 0x04, SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 0x05, } /// Note: Holds either a single value (when `value_width == 0`) or multiple /// values if `value.length()` is no-remainder divisible by the non-zero /// `value_width`. /// Note: Consider extending it with `flags` field, to hold additional info like /// IsBitfield, IsRange, etc. if we need these type-specific validations. table CompoundValue { value: [ubyte] (required); value_width: ubyte = 0; } table CodecSpecificConfiguration { name: string; type: ubyte (key); compound_value: CompoundValue; } struct CodecId { coding_format: ubyte; vendor_company_id : ushort; vendor_codec_id : ushort; } enum AudioSetConfigurationStrategy : byte { MONO_ONE_CIS_PER_DEVICE = 0x00, STEREO_TWO_CISES_PER_DEVICE = 0x01, STEREO_ONE_CIS_PER_DEVICE = 0x02, } enum AudioSetConfigurationDirection : byte { SINK = 0x01, SOURCE = 0x02, } enum AudioSetConfigurationTargetLatency : byte { LOW = 0x01, BALANCED_RELIABILITY = 0x02, HIGH_RELIABILITY = 0x03, } table AudioSetSubConfiguration { device_cnt: ubyte; ase_cnt: ubyte; direction: AudioSetConfigurationDirection = SINK; configuration_strategy: AudioSetConfigurationStrategy; codec_id : CodecId (required); codec_configuration: [CodecSpecificConfiguration] (required); } table CodecConfiguration { name: string (key, required); subconfigurations: [AudioSetSubConfiguration] (required); } table QosConfiguration { name: string (key, required); target_latency: AudioSetConfigurationTargetLatency = BALANCED_RELIABILITY; retransmission_number: ubyte; max_transport_latency : ushort; } /// Each set configration can contain multiple logical subconfigurations, which /// all must be configurable with the current set of audio devices. For example, /// one can define multiple output stream configurations with different /// qualities, or assign different configurations to each stream direction. table AudioSetConfiguration { name: string (key, required); codec_config_name: string (required); qos_config_name: [string] (required); } table AudioSetConfigurations { _comments_: [string]; configurations: [AudioSetConfiguration] (required); codec_configurations: [CodecConfiguration] (required); qos_configurations: [QosConfiguration] (required); } root_type AudioSetConfigurations; Loading
bluetooth/audio/utils/Android.bp +80 −1 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ cc_library_shared { "aidl_session/BluetoothAudioSession.cpp", "aidl_session/HidlToAidlMiddleware.cpp", "aidl_session/BluetoothLeAudioCodecsProvider.cpp", "aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp", ], export_include_dirs: ["aidl_session/"], header_libs: [ Loading @@ -61,9 +62,13 @@ cc_library_shared { "liblog", "libhidlbase", "libxml2", "libflatbuffers-cpp", ], generated_sources: ["le_audio_codec_capabilities"], generated_headers: ["le_audio_codec_capabilities"], generated_headers: [ "le_audio_codec_capabilities", "AIDLLeAudioSetConfigSchemas_h", ], } cc_test { Loading Loading @@ -98,3 +103,77 @@ xsd_config { api_dir: "le_audio_codec_capabilities/schema", root_elements: ["leAudioOffloadSetting"], } genrule { name: "AIDLLeAudioSetConfigSchemas_h", tools: [ "flatc", ], cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -o $(genDir) --cpp $(in) ", srcs: [ "le_audio_configuration_set/audio_set_configurations.fbs", "le_audio_configuration_set/audio_set_scenarios.fbs", ], out: [ "audio_set_configurations_generated.h", "audio_set_scenarios_generated.h", ], } // Binary generation genrule { name: "AIDLLeAudioSetScenariosSchema_bfbs", tools: [ "flatc", ], cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -b --schema -o $(genDir) $(in) ", srcs: [ "le_audio_configuration_set/audio_set_scenarios.fbs", ], out: [ "audio_set_scenarios.bfbs", ], } genrule { name: "AIDLLeAudioSetConfigsSchema_bfbs", tools: [ "flatc", ], cmd: "$(location flatc) -I hardware/interfaces/bluetooth/audio/utils/ -b --schema -o $(genDir) $(in) ", srcs: [ "le_audio_configuration_set/audio_set_configurations.fbs", ], out: [ "audio_set_configurations.bfbs", ], } // Add to prebuilt etc prebuilt_etc { name: "aidl_audio_set_scenarios_bfbs", src: ":AIDLLeAudioSetScenariosSchema_bfbs", filename: "aidl_audio_set_scenarios.bfbs", sub_dir: "aidl/le_audio", } prebuilt_etc { name: "aidl_audio_set_scenarios_json", src: "le_audio_configuration_set/audio_set_scenarios.json", filename: "aidl_audio_set_scenarios.json", sub_dir: "aidl/le_audio", } prebuilt_etc { name: "aidl_audio_set_configurations_bfbs", src: ":AIDLLeAudioSetConfigsSchema_bfbs", filename: "aidl_audio_set_configurations.bfbs", sub_dir: "aidl/le_audio", } prebuilt_etc { name: "aidl_audio_set_configurations_json", src: "le_audio_configuration_set/audio_set_configurations.json", filename: "aidl_audio_set_configurations.json", sub_dir: "aidl/le_audio", }
bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ #include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h> #include <android-base/logging.h> #include "BluetoothLeAudioAseConfigurationSettingProvider.h" #include "BluetoothLeAudioCodecsProvider.h" namespace aidl { Loading Loading @@ -438,6 +439,12 @@ std::vector<CodecInfo> BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo( return codec_info_map_iter->second; } std::vector<LeAudioAseConfigurationSetting> BluetoothAudioCodecs::GetLeAudioAseConfigurationSettings() { return AudioSetConfigurationProviderJson:: GetLeAudioAseConfigurationSettings(); } } // namespace audio } // namespace bluetooth } // namespace hardware Loading
bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h +7 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h> #include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/CodecInfo.h> #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h> #include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h> #include <aidl/android/hardware/bluetooth/audio/OpusConfiguration.h> Loading @@ -34,6 +35,9 @@ namespace hardware { namespace bluetooth { namespace audio { using LeAudioAseConfigurationSetting = IBluetoothAudioProvider::LeAudioAseConfigurationSetting; class BluetoothAudioCodecs { public: static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities(); Loading @@ -50,6 +54,9 @@ class BluetoothAudioCodecs { static std::vector<CodecInfo> GetLeAudioOffloadCodecInfo( const SessionType& session_type); static std::vector<LeAudioAseConfigurationSetting> GetLeAudioAseConfigurationSettings(); private: template <typename T> struct identity { Loading
bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.h 0 → 100644 +125 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h> #include <map> #include <mutex> #include <optional> #include <string> #include <string_view> #include <tuple> #include "audio_set_configurations_generated.h" #include "audio_set_scenarios_generated.h" namespace aidl { namespace android { namespace hardware { namespace bluetooth { namespace audio { using LeAudioAseConfigurationSetting = IBluetoothAudioProvider::LeAudioAseConfigurationSetting; using AseDirectionConfiguration = IBluetoothAudioProvider:: LeAudioAseConfigurationSetting::AseDirectionConfiguration; using LeAudioAseQosConfiguration = IBluetoothAudioProvider::LeAudioAseQosConfiguration; using LeAudioDataPathConfiguration = IBluetoothAudioProvider::LeAudioDataPathConfiguration; enum class CodecLocation { HOST, ADSP, CONTROLLER, }; class AudioSetConfigurationProviderJson { public: static std::vector<LeAudioAseConfigurationSetting> GetLeAudioAseConfigurationSettings(); private: static void LoadAudioSetConfigurationProviderJson(); static const le_audio::CodecSpecificConfiguration* LookupCodecSpecificParam( const flatbuffers::Vector<flatbuffers::Offset< le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params, le_audio::CodecSpecificLtvGenericTypes type); static void populateAudioChannelAllocation( CodecSpecificConfigurationLtv::AudioChannelAllocation& audio_channel_allocation, uint32_t audio_location); static void populateConfigurationData( LeAudioAseConfiguration& ase, const flatbuffers::Vector< flatbuffers::Offset<le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params); static void populateAseConfiguration( LeAudioAseConfiguration& ase, const le_audio::AudioSetSubConfiguration* flat_subconfig, const le_audio::QosConfiguration* qos_cfg); static void populateAseQosConfiguration( LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg); static AseDirectionConfiguration SetConfigurationFromFlatSubconfig( const le_audio::AudioSetSubConfiguration* flat_subconfig, const le_audio::QosConfiguration* qos_cfg, CodecLocation location); static void processSubconfig( const le_audio::AudioSetSubConfiguration* subconfig, const le_audio::QosConfiguration* qos_cfg, std::vector<std::optional<AseDirectionConfiguration>>& directionAseConfiguration, CodecLocation location); static void PopulateAseConfigurationFromFlat( const le_audio::AudioSetConfiguration* flat_cfg, std::vector<const le_audio::CodecConfiguration*>* codec_cfgs, std::vector<const le_audio::QosConfiguration*>* qos_cfgs, CodecLocation location, std::vector<std::optional<AseDirectionConfiguration>>& sourceAseConfiguration, std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration, ConfigurationFlags& configurationFlags); static bool LoadConfigurationsFromFiles(const char* schema_file, const char* content_file, CodecLocation location); static bool LoadScenariosFromFiles(const char* schema_file, const char* content_file); static bool LoadContent( std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> config_files, std::vector<std::pair<const char* /*schema*/, const char* /*content*/>> scenario_files, CodecLocation location); }; } // namespace audio } // namespace bluetooth } // namespace hardware } // namespace android } // namespace aidl
bluetooth/audio/utils/le_audio_configuration_set/audio_set_configurations.fbs 0 → 100644 +91 −0 Original line number Diff line number Diff line /* * Copyright (c) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ namespace aidl.android.hardware.bluetooth.audio.le_audio; enum CodecSpecificLtvGenericTypes : byte { SUPPORTED_SAMPLING_FREQUENCY = 0x01, SUPPORTED_FRAME_DURATION = 0x02, SUPPORTED_AUDIO_CHANNEL_ALLOCATION = 0x03, SUPPORTED_OCTETS_PER_CODEC_FRAME = 0x04, SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU = 0x05, } /// Note: Holds either a single value (when `value_width == 0`) or multiple /// values if `value.length()` is no-remainder divisible by the non-zero /// `value_width`. /// Note: Consider extending it with `flags` field, to hold additional info like /// IsBitfield, IsRange, etc. if we need these type-specific validations. table CompoundValue { value: [ubyte] (required); value_width: ubyte = 0; } table CodecSpecificConfiguration { name: string; type: ubyte (key); compound_value: CompoundValue; } struct CodecId { coding_format: ubyte; vendor_company_id : ushort; vendor_codec_id : ushort; } enum AudioSetConfigurationStrategy : byte { MONO_ONE_CIS_PER_DEVICE = 0x00, STEREO_TWO_CISES_PER_DEVICE = 0x01, STEREO_ONE_CIS_PER_DEVICE = 0x02, } enum AudioSetConfigurationDirection : byte { SINK = 0x01, SOURCE = 0x02, } enum AudioSetConfigurationTargetLatency : byte { LOW = 0x01, BALANCED_RELIABILITY = 0x02, HIGH_RELIABILITY = 0x03, } table AudioSetSubConfiguration { device_cnt: ubyte; ase_cnt: ubyte; direction: AudioSetConfigurationDirection = SINK; configuration_strategy: AudioSetConfigurationStrategy; codec_id : CodecId (required); codec_configuration: [CodecSpecificConfiguration] (required); } table CodecConfiguration { name: string (key, required); subconfigurations: [AudioSetSubConfiguration] (required); } table QosConfiguration { name: string (key, required); target_latency: AudioSetConfigurationTargetLatency = BALANCED_RELIABILITY; retransmission_number: ubyte; max_transport_latency : ushort; } /// Each set configration can contain multiple logical subconfigurations, which /// all must be configurable with the current set of audio devices. For example, /// one can define multiple output stream configurations with different /// qualities, or assign different configurations to each stream direction. table AudioSetConfiguration { name: string (key, required); codec_config_name: string (required); qos_config_name: [string] (required); } table AudioSetConfigurations { _comments_: [string]; configurations: [AudioSetConfiguration] (required); codec_configurations: [CodecConfiguration] (required); qos_configurations: [QosConfiguration] (required); } root_type AudioSetConfigurations;