Merge changes Iefd406fc,I0f6cfbda into main

* changes:
  New parsing logic and configuration matching for LE Audio
  Update the default set configuration file and format.
This commit is contained in:
Bao Do
2024-07-19 07:18:24 +00:00
committed by Gerrit Code Review
8 changed files with 2593 additions and 6415 deletions

View File

@@ -121,6 +121,40 @@ bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
return (sessionType == session_type_);
}
std::string getSettingOutputString(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting) {
std::stringstream ss;
std::string name = "";
if (!setting.sinkAseConfiguration.has_value() &&
!setting.sourceAseConfiguration.has_value())
return "";
std::vector<
std::optional<LeAudioAseConfigurationSetting::AseDirectionConfiguration>>*
directionAseConfiguration;
if (setting.sinkAseConfiguration.has_value() &&
!setting.sinkAseConfiguration.value().empty())
directionAseConfiguration = &setting.sinkAseConfiguration.value();
else
directionAseConfiguration = &setting.sourceAseConfiguration.value();
for (auto& aseConfiguration : *directionAseConfiguration) {
if (aseConfiguration.has_value() &&
aseConfiguration.value().aseConfiguration.metadata.has_value()) {
for (auto& meta :
aseConfiguration.value().aseConfiguration.metadata.value()) {
if (meta.has_value() &&
meta.value().getTag() == MetadataLtv::vendorSpecific) {
auto k = meta.value().get<MetadataLtv::vendorSpecific>().opaqueValue;
name = std::string(k.begin(), k.end());
break;
}
}
}
}
ss << "setting name: " << name << ", setting: " << setting.toString();
return ss.str();
}
ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
const AudioConfiguration& audio_config,
@@ -218,15 +252,24 @@ bool LeAudioOffloadAudioProvider::isMatchedFrameDuration(
return false;
}
int getCountFromBitmask(int bitmask) {
return std::bitset<32>(bitmask).count();
}
bool LeAudioOffloadAudioProvider::isMatchedAudioChannel(
CodecSpecificConfigurationLtv::AudioChannelAllocation&
/*cfg_channel*/,
CodecSpecificConfigurationLtv::AudioChannelAllocation& cfg_channel,
CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts&
/*capability_channel*/) {
// Simply ignore.
// Later can use additional capabilities to match requirement.
bool isMatched = true;
return isMatched;
capability_channel) {
int count = getCountFromBitmask(cfg_channel.bitmask);
if (count == 1 &&
!(capability_channel.bitmask &
CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts::ONE))
return false;
if (count == 2 &&
!(capability_channel.bitmask &
CodecSpecificCapabilitiesLtv::SupportedAudioChannelCounts::TWO))
return false;
return true;
}
bool LeAudioOffloadAudioProvider::isMatchedCodecFramesPerSDU(
@@ -322,12 +365,6 @@ bool LeAudioOffloadAudioProvider::isCapabilitiesMatchedCodecConfiguration(
return true;
}
bool isMonoConfig(
CodecSpecificConfigurationLtv::AudioChannelAllocation allocation) {
auto channel_count = std::bitset<32>(allocation.bitmask);
return (channel_count.count() <= 1);
}
bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
LeAudioAseConfiguration& setting_cfg,
const LeAudioAseConfiguration& requirement_cfg) {
@@ -337,9 +374,6 @@ bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
if (!setting_cfg.codecId.has_value()) return false;
if (!isMatchedValidCodec(setting_cfg.codecId.value(),
requirement_cfg.codecId.value())) {
LOG(WARNING) << __func__ << ": Doesn't match valid codec, cfg = "
<< setting_cfg.codecId.value().toString()
<< ", req = " << requirement_cfg.codecId.value().toString();
return false;
}
}
@@ -347,9 +381,6 @@ bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
if (requirement_cfg.targetLatency !=
LeAudioAseConfiguration::TargetLatency::UNDEFINED &&
setting_cfg.targetLatency != requirement_cfg.targetLatency) {
LOG(WARNING) << __func__ << ": Doesn't match target latency, cfg = "
<< int(setting_cfg.targetLatency)
<< ", req = " << int(requirement_cfg.targetLatency);
return false;
}
// Ignore PHY requirement
@@ -365,8 +396,6 @@ bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
auto cfg = cfg_tag_map.find(requirement_cfg.getTag());
// Config not found for this requirement, cannot match
if (cfg == cfg_tag_map.end()) {
LOG(WARNING) << __func__ << ": Config not found for the requirement "
<< requirement_cfg.toString();
return false;
}
@@ -377,10 +406,6 @@ bool LeAudioOffloadAudioProvider::filterMatchedAseConfiguration(
continue;
if (cfg->second != requirement_cfg) {
LOG(WARNING) << __func__
<< ": Config doesn't match the requirement, cfg = "
<< cfg->second.toString()
<< ", req = " << requirement_cfg.toString();
return false;
}
}
@@ -437,10 +462,6 @@ int getLeAudioAseConfigurationAllocationBitmask(LeAudioAseConfiguration cfg) {
return 0;
}
int getCountFromBitmask(int bitmask) {
return std::bitset<32>(bitmask).count();
}
std::optional<AseDirectionConfiguration> findValidMonoConfig(
std::vector<AseDirectionConfiguration>& valid_direction_configurations,
int bitmask) {
@@ -505,14 +526,13 @@ std::vector<AseDirectionConfiguration> getValidConfigurationsFromAllocation(
return {};
}
// Check and filter each index to see if it's a match.
void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
direction_configurations,
const std::vector<std::optional<AseDirectionRequirement>>& requirements,
std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
valid_direction_configurations,
bool is_exact) {
// For every requirement, find the matched ase configuration
valid_direction_configurations) {
if (!direction_configurations.has_value()) return;
if (!valid_direction_configurations.has_value()) {
@@ -520,38 +540,55 @@ void LeAudioOffloadAudioProvider::filterRequirementAseDirectionConfiguration(
std::vector<std::optional<AseDirectionConfiguration>>();
}
for (auto& requirement : requirements) {
if (!requirement.has_value()) continue;
auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
requirement.value().aseConfiguration);
auto req_channel_count = getCountFromBitmask(req_allocation_bitmask);
auto temp = std::vector<AseDirectionConfiguration>();
for (auto direction_configuration : direction_configurations.value()) {
if (!direction_configuration.has_value()) continue;
if (!filterMatchedAseConfiguration(
direction_configuration.value().aseConfiguration,
requirement.value().aseConfiguration))
continue;
// Valid if match any requirement.
temp.push_back(direction_configuration.value());
}
// Get the best matching config based on channel allocation
auto total_cfg_channel_count = 0;
auto req_valid_configs = getValidConfigurationsFromAllocation(
req_allocation_bitmask, temp, is_exact);
// Count and check required channel counts
for (auto& cfg : req_valid_configs) {
total_cfg_channel_count += getCountFromBitmask(
getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration));
valid_direction_configurations.value().push_back(cfg);
}
if (total_cfg_channel_count != req_channel_count) {
// Exact matching process
// Need to respect the number of device
for (int i = 0; i < requirements.size(); ++i) {
auto requirement = requirements[i];
auto direction_configuration = direction_configurations.value()[i];
if (!direction_configuration.has_value()) {
valid_direction_configurations = std::nullopt;
return;
}
auto cfg = direction_configuration.value();
if (!filterMatchedAseConfiguration(cfg.aseConfiguration,
requirement.value().aseConfiguration)) {
valid_direction_configurations = std::nullopt;
return; // No way to match
}
// For exact match, we require this direction to have the same allocation.
// If stereo, need stereo.
// If mono, need mono (modified to the correct required allocation)
auto req_allocation_bitmask = getLeAudioAseConfigurationAllocationBitmask(
requirement.value().aseConfiguration);
int req_channel_count = getCountFromBitmask(req_allocation_bitmask);
int cfg_bitmask =
getLeAudioAseConfigurationAllocationBitmask(cfg.aseConfiguration);
int cfg_channel_count = getCountFromBitmask(cfg_bitmask);
if (req_channel_count <= 1) {
// MONO case, is a match if also mono, modify to the same allocation
if (cfg_channel_count > 1) {
valid_direction_configurations = std::nullopt;
return; // Not a match
}
// Modify the bitmask to be the same as the requirement
for (auto& codec_cfg : cfg.aseConfiguration.codecConfiguration) {
if (codec_cfg.getTag() ==
CodecSpecificConfigurationLtv::Tag::audioChannelAllocation) {
codec_cfg
.get<CodecSpecificConfigurationLtv::Tag::audioChannelAllocation>()
.bitmask = req_allocation_bitmask;
break;
}
}
} else {
// STEREO case, is a match if same allocation
if (req_allocation_bitmask != cfg_bitmask) {
valid_direction_configurations = std::nullopt;
return; // Not a match
}
}
// Push to list if valid
valid_direction_configurations.value().push_back(cfg);
}
}
@@ -612,8 +649,8 @@ LeAudioOffloadAudioProvider::getCapabilitiesMatchedAseConfigurationSettings(
std::optional<LeAudioAseConfigurationSetting>
LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement& requirement,
bool is_exact) {
const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
requirement) {
// Try to match context in metadata.
if ((setting.audioContext.bitmask & requirement.audioContext.bitmask) !=
requirement.audioContext.bitmask)
@@ -629,10 +666,29 @@ LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
.flags = setting.flags,
};
// The number of AseDirectionRequirement in the requirement
// is the number of device.
// The exact matching process is as follow:
// 1. Setting direction has the same number of cfg (ignore when null require)
// 2. For each index, it's a 1-1 filter / mapping.
if (requirement.sinkAseRequirement.has_value() &&
requirement.sinkAseRequirement.value().size() !=
setting.sinkAseConfiguration.value().size()) {
return std::nullopt;
}
if (requirement.sourceAseRequirement.has_value() &&
requirement.sourceAseRequirement.value().size() !=
setting.sourceAseConfiguration.value().size()) {
return std::nullopt;
}
if (requirement.sinkAseRequirement.has_value()) {
filterRequirementAseDirectionConfiguration(
setting.sinkAseConfiguration, requirement.sinkAseRequirement.value(),
filtered_setting.sinkAseConfiguration, is_exact);
filtered_setting.sinkAseConfiguration);
if (!filtered_setting.sinkAseConfiguration.has_value()) {
return std::nullopt;
}
@@ -642,7 +698,7 @@ LeAudioOffloadAudioProvider::getRequirementMatchedAseConfigurationSettings(
filterRequirementAseDirectionConfiguration(
setting.sourceAseConfiguration,
requirement.sourceAseRequirement.value(),
filtered_setting.sourceAseConfiguration, is_exact);
filtered_setting.sourceAseConfiguration);
if (!filtered_setting.sourceAseConfiguration.has_value()) {
return std::nullopt;
}
@@ -656,8 +712,7 @@ LeAudioOffloadAudioProvider::matchWithRequirement(
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>&
matched_ase_configuration_settings,
const std::vector<IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
in_requirements,
bool is_exact) {
in_requirements) {
// Each requirement will match with a valid setting
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting> result;
for (auto& requirement : in_requirements) {
@@ -667,12 +722,12 @@ LeAudioOffloadAudioProvider::matchWithRequirement(
for (auto& setting : matched_ase_configuration_settings) {
auto filtered_ase_configuration_setting =
getRequirementMatchedAseConfigurationSettings(setting, requirement,
is_exact);
getRequirementMatchedAseConfigurationSettings(setting, requirement);
if (filtered_ase_configuration_setting.has_value()) {
result.push_back(filtered_ase_configuration_setting.value());
LOG(INFO) << __func__ << ": Result = "
<< filtered_ase_configuration_setting.value().toString();
LOG(INFO) << __func__ << ": Result found: "
<< getSettingOutputString(
filtered_ase_configuration_setting.value());
// Found a matched setting, ignore other settings
is_matched = true;
break;
@@ -690,8 +745,8 @@ LeAudioOffloadAudioProvider::matchWithRequirement(
}
// For each requirement, a valid ASE configuration will satify:
// - matched with any sink capability (if presented)
// - OR matched with any source capability (if presented)
// - matched with the sink capability (if presented)
// - AND matched with the source capability (if presented)
// - and the setting need to pass the requirement
ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
const std::optional<std::vector<
@@ -719,49 +774,55 @@ ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
// -> preferred list will have settings with MEDIA context
// -> non-preferred list will have settings with any context
// We want to match requirement with preferred context settings first
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
sink_matched_ase_configuration_settings;
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
matched_ase_configuration_settings;
// Matched ASE configuration with non-preferred audio context
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
sink_non_prefer_matched_ase_configuration_settings;
std::vector<IBluetoothAudioProvider::LeAudioAseConfigurationSetting>
non_prefer_matched_ase_configuration_settings;
if (in_remoteSinkAudioCapabilities.has_value())
// Matching each setting with any remote capabilities
// A setting must match both source and sink.
// First filter all setting matched with sink capability
if (in_remoteSinkAudioCapabilities.has_value()) {
for (auto& setting : ase_configuration_settings)
for (auto& capability : in_remoteSinkAudioCapabilities.value()) {
if (!capability.has_value()) continue;
// LOG(DEBUG) << __func__ << ": " << capability.value().toString();
auto filtered_ase_configuration_setting =
getCapabilitiesMatchedAseConfigurationSettings(
setting, capability.value(), kLeAudioDirectionSink);
if (filtered_ase_configuration_setting.has_value()) {
// Push to non-prefer first for the broadest matching possible
non_prefer_matched_ase_configuration_settings.push_back(
sink_non_prefer_matched_ase_configuration_settings.push_back(
filtered_ase_configuration_setting.value());
// Try to filter out prefer context to another vector.
if (filterCapabilitiesMatchedContext(
filtered_ase_configuration_setting.value().audioContext,
capability.value())) {
matched_ase_configuration_settings.push_back(
sink_matched_ase_configuration_settings.push_back(
filtered_ase_configuration_setting.value());
}
}
}
} else {
sink_matched_ase_configuration_settings = ase_configuration_settings;
sink_non_prefer_matched_ase_configuration_settings =
ase_configuration_settings;
}
// Combine filter every source capability
if (in_remoteSourceAudioCapabilities.has_value())
// Matching each setting with any remote capabilities
for (auto& setting : ase_configuration_settings)
if (in_remoteSourceAudioCapabilities.has_value()) {
// Prefer context
for (auto& setting : sink_matched_ase_configuration_settings)
for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
if (!capability.has_value()) continue;
auto filtered_ase_configuration_setting =
getCapabilitiesMatchedAseConfigurationSettings(
setting, capability.value(), kLeAudioDirectionSource);
if (filtered_ase_configuration_setting.has_value()) {
// Put into the same list
// possibly duplicated, filtered by requirement later
// Push to non-prefer first for the broadest matching possible
non_prefer_matched_ase_configuration_settings.push_back(
filtered_ase_configuration_setting.value());
// Try to filter out prefer context to another vector.
if (filterCapabilitiesMatchedContext(
filtered_ase_configuration_setting.value().audioContext,
@@ -772,43 +833,52 @@ ndk::ScopedAStatus LeAudioOffloadAudioProvider::getLeAudioAseConfiguration(
}
}
// Non prefer context
for (auto& setting : sink_non_prefer_matched_ase_configuration_settings)
for (auto& capability : in_remoteSourceAudioCapabilities.value()) {
if (!capability.has_value()) continue;
auto filtered_ase_configuration_setting =
getCapabilitiesMatchedAseConfigurationSettings(
setting, capability.value(), kLeAudioDirectionSource);
if (filtered_ase_configuration_setting.has_value()) {
// Push to non-prefer first for the broadest matching possible
non_prefer_matched_ase_configuration_settings.push_back(
filtered_ase_configuration_setting.value());
}
}
} else {
matched_ase_configuration_settings =
sink_matched_ase_configuration_settings;
non_prefer_matched_ase_configuration_settings =
sink_non_prefer_matched_ase_configuration_settings;
}
// Matching priority list:
// Preferred context - exact match with allocation
// Any context - exact match with allocation
// Preferred context - loose match with allocation
// Any context - loose match with allocation
// A loose match will attempt to return 2 settings with the
// combined allocation bitmask equal the required allocation.
// For example, we can return 2 link (left link and right link) when
// the requirement required 1 (left + right) link.
auto result = matchWithRequirement(matched_ase_configuration_settings,
in_requirements, true);
if (result.empty()) {
LOG(WARNING)
<< __func__
<< ": Cannot match with preferred context settings - exact match";
result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
in_requirements, true);
LOG(DEBUG) << __func__ << ": Called with requirement: ";
for (auto& requirement : in_requirements) {
LOG(DEBUG) << __func__ << " requirement: " << requirement.toString();
}
if (result.empty()) {
LOG(WARNING)
<< __func__
<< ": Cannot match with non-preferred context settings - exact match";
result = matchWithRequirement(matched_ase_configuration_settings,
in_requirements, false);
LOG(DEBUG) << __func__ << ": List of settings with the same context:";
for (auto& setting : matched_ase_configuration_settings) {
LOG(DEBUG) << __func__ << ": " << getSettingOutputString(setting);
}
auto result =
matchWithRequirement(matched_ase_configuration_settings, in_requirements);
if (result.empty()) {
LOG(WARNING) << __func__
<< ": Cannot match with preferred context settings - "
"non-exact match";
<< ": Cannot match with preferred context settings";
result = matchWithRequirement(non_prefer_matched_ase_configuration_settings,
in_requirements, false);
in_requirements);
}
if (result.empty())
if (result.empty()) {
LOG(ERROR) << __func__
<< ": Cannot match with non preferred context settings - "
"non-exact match";
<< ": Cannot match with non-preferred context settings";
}
*_aidl_return = result;
return ndk::ScopedAStatus::ok();
};

View File

@@ -139,8 +139,7 @@ class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
direction_configurations,
const std::vector<std::optional<AseDirectionRequirement>>& requirements,
std::optional<std::vector<std::optional<AseDirectionConfiguration>>>&
valid_direction_configurations,
bool is_exact);
valid_direction_configurations);
std::optional<LeAudioAseConfigurationSetting>
getCapabilitiesMatchedAseConfigurationSettings(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
@@ -150,8 +149,7 @@ class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
getRequirementMatchedAseConfigurationSettings(
IBluetoothAudioProvider::LeAudioAseConfigurationSetting& setting,
const IBluetoothAudioProvider::LeAudioConfigurationRequirement&
requirement,
bool is_exact);
requirement);
bool isMatchedQosRequirement(LeAudioAseQosConfiguration setting_qos,
AseQosDirectionRequirement requirement_qos);
std::optional<LeAudioBroadcastConfigurationSetting>
@@ -175,8 +173,7 @@ class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
matched_ase_configuration_settings,
const std::vector<
IBluetoothAudioProvider::LeAudioConfigurationRequirement>&
in_requirements,
bool is_exact);
in_requirements);
};
class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {

View File

@@ -81,9 +81,9 @@ cc_library_shared {
],
required: [
"aidl_audio_set_configurations_bfbs",
"aidl_audio_set_configurations_json",
"aidl_default_audio_set_configurations_json",
"aidl_audio_set_scenarios_bfbs",
"aidl_audio_set_scenarios_json",
"aidl_default_audio_set_scenarios_json",
"hfp_codec_capabilities_xml",
],
}
@@ -215,9 +215,9 @@ prebuilt_etc {
}
prebuilt_etc {
name: "aidl_audio_set_scenarios_json",
name: "aidl_default_audio_set_scenarios_json",
src: "le_audio_configuration_set/audio_set_scenarios.json",
filename: "aidl_audio_set_scenarios.json",
filename: "aidl_default_audio_set_scenarios.json",
sub_dir: "aidl/le_audio",
vendor: true,
}
@@ -239,9 +239,9 @@ prebuilt_etc {
}
prebuilt_etc {
name: "aidl_audio_set_configurations_json",
name: "aidl_default_audio_set_configurations_json",
src: "le_audio_configuration_set/audio_set_configurations.json",
filename: "aidl_audio_set_configurations.json",
filename: "aidl_default_audio_set_configurations.json",
sub_dir: "aidl/le_audio",
vendor: true,
}

View File

@@ -240,18 +240,31 @@ std::map<uint32_t, uint32_t> audio_channel_allocation_map = {
CodecSpecificConfigurationLtv::AudioChannelAllocation::RIGHT_SURROUND},
};
// Set configuration and scenario files with fallback default
static const std::vector<
std::pair<const char* /*schema*/, const char* /*content*/>>
kLeAudioSetConfigs = {{"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_configurations.bfbs",
"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_configurations.json"}};
kLeAudioSetConfigs = {
{"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_configurations.bfbs",
"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_configurations.json"},
{"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_configurations.bfbs",
"/vendor/etc/aidl/le_audio/"
"aidl_default_audio_set_configurations.json"},
};
static const std::vector<
std::pair<const char* /*schema*/, const char* /*content*/>>
kLeAudioSetScenarios = {{"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_scenarios.bfbs",
"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_scenarios.json"}};
"aidl_audio_set_scenarios.json"},
{"/vendor/etc/aidl/le_audio/"
"aidl_audio_set_scenarios.bfbs",
"/vendor/etc/aidl/le_audio/"
"aidl_default_audio_set_scenarios.json"}};
/* Implementation */
@@ -374,7 +387,7 @@ void AudioSetConfigurationProviderJson::populateConfigurationData(
}
void AudioSetConfigurationProviderJson::populateAseConfiguration(
LeAudioAseConfiguration& ase,
const std::string& name, LeAudioAseConfiguration& ase,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg) {
// Target latency
@@ -411,20 +424,36 @@ void AudioSetConfigurationProviderJson::populateAseConfiguration(
}
// Codec configuration data
populateConfigurationData(ase, flat_subconfig->codec_configuration());
// Populate the config name for easier debug
auto meta = std::vector<std::optional<MetadataLtv>>();
MetadataLtv::VendorSpecific cfg_name;
cfg_name.opaqueValue = std::vector<uint8_t>(name.begin(), name.end());
meta.push_back(cfg_name);
ase.metadata = meta;
}
void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
LeAudioAseQosConfiguration& qos, const le_audio::QosConfiguration* qos_cfg,
LeAudioAseConfiguration& ase) {
LeAudioAseConfiguration& ase, uint8_t ase_channel_cnt) {
std::optional<CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU>
frameBlock = std::nullopt;
std::optional<CodecSpecificConfigurationLtv::FrameDuration> frameDuration =
std::nullopt;
std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
allocation = std::nullopt;
std::optional<CodecSpecificConfigurationLtv::OctetsPerCodecFrame> octet =
std::nullopt;
// Hack to put back allocation
CodecSpecificConfigurationLtv::AudioChannelAllocation allocation =
CodecSpecificConfigurationLtv::AudioChannelAllocation();
if (ase_channel_cnt == 1) {
allocation.bitmask |=
CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER;
} else {
allocation.bitmask |=
CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT |
CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT;
}
for (auto& cfg_ltv : ase.codecConfiguration) {
auto tag = cfg_ltv.getTag();
if (tag == CodecSpecificConfigurationLtv::codecFrameBlocksPerSDU) {
@@ -433,11 +462,12 @@ void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
} else if (tag == CodecSpecificConfigurationLtv::frameDuration) {
frameDuration =
cfg_ltv.get<CodecSpecificConfigurationLtv::frameDuration>();
} else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
allocation =
cfg_ltv.get<CodecSpecificConfigurationLtv::audioChannelAllocation>();
} else if (tag == CodecSpecificConfigurationLtv::octetsPerCodecFrame) {
octet = cfg_ltv.get<CodecSpecificConfigurationLtv::octetsPerCodecFrame>();
} else if (tag == CodecSpecificConfigurationLtv::audioChannelAllocation) {
// Change to the old hack allocation
cfg_ltv.set<CodecSpecificConfigurationLtv::audioChannelAllocation>(
allocation);
}
}
@@ -445,9 +475,8 @@ void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
if (frameBlock.has_value()) frameBlockValue = frameBlock.value().value;
// Populate maxSdu
if (allocation.has_value() && octet.has_value()) {
auto channel_count = std::bitset<32>(allocation.value().bitmask).count();
qos.maxSdu = channel_count * octet.value().value * frameBlockValue;
if (octet.has_value()) {
qos.maxSdu = ase_channel_cnt * octet.value().value * frameBlockValue;
}
// Populate sduIntervalUs
if (frameDuration.has_value()) {
@@ -468,6 +497,7 @@ void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
// Parse into AseDirectionConfiguration
AseDirectionConfiguration
AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
const std::string& name,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg, CodecLocation location) {
AseDirectionConfiguration direction_conf;
@@ -477,10 +507,11 @@ AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
LeAudioDataPathConfiguration path;
// Translate into LeAudioAseConfiguration
populateAseConfiguration(ase, flat_subconfig, qos_cfg);
populateAseConfiguration(name, ase, flat_subconfig, qos_cfg);
// Translate into LeAudioAseQosConfiguration
populateAseQosConfiguration(qos, qos_cfg, ase);
populateAseQosConfiguration(qos, qos_cfg, ase,
flat_subconfig->ase_channel_cnt());
// Translate location to data path id
switch (location) {
@@ -510,13 +541,18 @@ AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
// Parse into AseDirectionConfiguration and the ConfigurationFlags
// and put them in the given list.
void AudioSetConfigurationProviderJson::processSubconfig(
const std::string& name,
const le_audio::AudioSetSubConfiguration* subconfig,
const le_audio::QosConfiguration* qos_cfg,
std::vector<std::optional<AseDirectionConfiguration>>&
directionAseConfiguration,
CodecLocation location) {
directionAseConfiguration.push_back(
SetConfigurationFromFlatSubconfig(subconfig, qos_cfg, location));
auto ase_cnt = subconfig->ase_cnt();
auto config =
SetConfigurationFromFlatSubconfig(name, subconfig, qos_cfg, location);
directionAseConfiguration.push_back(config);
// Put the same setting again.
if (ase_cnt == 2) directionAseConfiguration.push_back(config);
}
void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
@@ -587,11 +623,11 @@ void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
/* Load subconfigurations */
for (auto subconfig : *codec_cfg->subconfigurations()) {
if (subconfig->direction() == kLeAudioDirectionSink) {
processSubconfig(subconfig, qos_sink_cfg, sinkAseConfiguration,
location);
processSubconfig(flat_cfg->name()->str(), subconfig, qos_sink_cfg,
sinkAseConfiguration, location);
} else {
processSubconfig(subconfig, qos_source_cfg, sourceAseConfiguration,
location);
processSubconfig(flat_cfg->name()->str(), subconfig, qos_source_cfg,
sourceAseConfiguration, location);
}
}
} else {
@@ -742,9 +778,6 @@ bool AudioSetConfigurationProviderJson::LoadScenariosFromFiles(
LOG(DEBUG) << "Updating " << flat_scenarios->size() << " scenarios.";
for (auto const& scenario : *flat_scenarios) {
LOG(DEBUG) << "Scenario " << scenario->name()->c_str()
<< " configs: " << scenario->configurations()->size();
if (!scenario->configurations()) continue;
std::string scenario_name = scenario->name()->c_str();
AudioContext context;
@@ -758,6 +791,9 @@ bool AudioSetConfigurationProviderJson::LoadScenariosFromFiles(
context = AudioContext(game_context);
else if (scenario_name == "VoiceAssistants")
context = AudioContext(voice_assistants_context);
LOG(DEBUG) << "Scenario " << scenario->name()->c_str()
<< " configs: " << scenario->configurations()->size()
<< " context: " << context.toString();
for (auto it = scenario->configurations()->begin();
it != scenario->configurations()->end(); ++it) {
@@ -790,14 +826,22 @@ bool AudioSetConfigurationProviderJson::LoadContent(
std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
scenario_files,
CodecLocation location) {
bool is_loaded_config = false;
for (auto [schema, content] : config_files) {
if (!LoadConfigurationsFromFiles(schema, content, location)) return false;
if (LoadConfigurationsFromFiles(schema, content, location)) {
is_loaded_config = true;
break;
}
}
bool is_loaded_scenario = false;
for (auto [schema, content] : scenario_files) {
if (!LoadScenariosFromFiles(schema, content)) return false;
if (LoadScenariosFromFiles(schema, content)) {
is_loaded_scenario = true;
break;
}
}
return true;
return is_loaded_config && is_loaded_scenario;
}
} // namespace audio

View File

@@ -73,19 +73,22 @@ class AudioSetConfigurationProviderJson {
flat_codec_specific_params);
static void populateAseConfiguration(
LeAudioAseConfiguration& ase,
const std::string& name, 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, LeAudioAseConfiguration& ase);
const le_audio::QosConfiguration* qos_cfg, LeAudioAseConfiguration& ase,
uint8_t ase_channel_cnt);
static AseDirectionConfiguration SetConfigurationFromFlatSubconfig(
const std::string& name,
const le_audio::AudioSetSubConfiguration* flat_subconfig,
const le_audio::QosConfiguration* qos_cfg, CodecLocation location);
static void processSubconfig(
const std::string& name,
const le_audio::AudioSetSubConfiguration* subconfig,
const le_audio::QosConfiguration* qos_cfg,
std::vector<std::optional<AseDirectionConfiguration>>&

View File

@@ -56,10 +56,9 @@ enum AudioSetConfigurationTargetLatency : byte {
HIGH_RELIABILITY = 0x03,
}
table AudioSetSubConfiguration {
device_cnt: ubyte;
ase_channel_cnt: ubyte;
ase_cnt: ubyte;
direction: AudioSetConfigurationDirection = SINK;
configuration_strategy: AudioSetConfigurationStrategy;
codec_id : CodecId (required);
codec_configuration: [CodecSpecificConfiguration] (required);
}

View File

@@ -8,251 +8,206 @@
{
"name": "Conversational",
"configurations": [
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_2",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_2",
"DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
"DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
"DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
"DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_32_2_1",
"DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_2_1",
"DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"DualDev_OneChanDoubleStereoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_2",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_2",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
"DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_48_4_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_48_3_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_24_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_24_1_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability",
"VND_SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32khz_Server_Prefered_1",
"VND_SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32khz_60oct_R3_L22_1",
"DualDev_OneChanMonoSnk_16_2_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability"
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_2",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_2",
"Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_2",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_2",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_48_4_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_48_3_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_24_1_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability",
"VND_SingleDev_TwoChanStereoSnk_OneChanStereoSrc_32khz_60oct_R3_L22_1",
"Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability"
]
},
{
"name": "Media",
"configurations": [
"DualDev_OneChanStereoSnk_48_4_High_Reliability",
"DualDev_OneChanStereoSnk_48_4_2",
"DualDev_OneChanStereoSnk_48_2_High_Reliability",
"DualDev_OneChanStereoSnk_48_2_2",
"DualDev_OneChanStereoSnk_48_3_High_Reliability",
"DualDev_OneChanStereoSnk_48_3_2",
"DualDev_OneChanStereoSnk_48_1_High_Reliability",
"DualDev_OneChanStereoSnk_48_1_2",
"DualDev_OneChanStereoSnk_24_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_24_2_2",
"DualDev_OneChanStereoSnk_16_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_16_2_2",
"DualDev_OneChanStereoSnk_16_1_Balanced_Reliability",
"DualDev_OneChanStereoSnk_16_1_2",
"SingleDev_OneChanStereoSnk_48_4_High_Reliability",
"SingleDev_OneChanStereoSnk_48_4_2",
"SingleDev_OneChanStereoSnk_48_2_High_Reliability",
"SingleDev_OneChanStereoSnk_48_2_2",
"SingleDev_OneChanStereoSnk_48_3_High_Reliability",
"SingleDev_OneChanStereoSnk_48_3_2",
"SingleDev_OneChanStereoSnk_48_1_High_Reliability",
"SingleDev_OneChanStereoSnk_48_1_2",
"SingleDev_OneChanStereoSnk_24_2_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_24_2_2",
"SingleDev_OneChanStereoSnk_16_2_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_16_2_2",
"SingleDev_OneChanStereoSnk_16_1_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_16_1_2",
"SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_2",
"SingleDev_TwoChanStereoSnk_48_4_High_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_2",
"SingleDev_TwoChanStereoSnk_48_2_High_Reliability",
"SingleDev_TwoChanStereoSnk_48_2_2",
"SingleDev_TwoChanStereoSnk_48_3_High_Reliability",
"SingleDev_TwoChanStereoSnk_48_3_2",
"SingleDev_TwoChanStereoSnk_48_1_High_Reliability",
"SingleDev_TwoChanStereoSnk_48_1_2",
"SingleDev_TwoChanStereoSnk_24_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_24_2_2",
"SingleDev_TwoChanStereoSnk_16_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_16_2_2",
"SingleDev_TwoChanStereoSnk_16_1_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_16_1_2",
"SingleDev_OneChanMonoSnk_48_4_High_Reliability",
"SingleDev_OneChanMonoSnk_48_4_2",
"SingleDev_OneChanMonoSnk_48_2_High_Reliability",
"SingleDev_OneChanMonoSnk_48_2_2",
"SingleDev_OneChanMonoSnk_48_3_High_Reliability",
"SingleDev_OneChanMonoSnk_48_3_2",
"SingleDev_OneChanMonoSnk_48_1_High_Reliability",
"SingleDev_OneChanMonoSnk_48_1_2",
"SingleDev_OneChanMonoSnk_32_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_32_2_2",
"SingleDev_OneChanMonoSnk_32_1_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_32_1_2",
"SingleDev_OneChanMonoSnk_24_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_24_2_2",
"SingleDev_OneChanMonoSnk_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_16_2_2",
"SingleDev_OneChanMonoSnk_16_1_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_16_1_2",
"Two-OneChan-SnkAse-Lc3_48_4_High_Reliability",
"Two-OneChan-SnkAse-Lc3_48_4_2",
"Two-OneChan-SnkAse-Lc3_48_2_High_Reliability",
"Two-OneChan-SnkAse-Lc3_48_2_2",
"Two-OneChan-SnkAse-Lc3_48_3_High_Reliability",
"Two-OneChan-SnkAse-Lc3_48_3_2",
"Two-OneChan-SnkAse-Lc3_48_1_High_Reliability",
"Two-OneChan-SnkAse-Lc3_48_1_2",
"Two-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_24_2_2",
"Two-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_16_2_2",
"Two-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_16_1_2",
"One-TwoChan-SnkAse-Lc3_48_4_High_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4_2",
"One-TwoChan-SnkAse-Lc3_48_2_High_Reliability",
"One-TwoChan-SnkAse-Lc3_48_2_2",
"One-TwoChan-SnkAse-Lc3_48_3_High_Reliability",
"One-TwoChan-SnkAse-Lc3_48_3_2",
"One-TwoChan-SnkAse-Lc3_48_1_High_Reliability",
"One-TwoChan-SnkAse-Lc3_48_1_2",
"One-TwoChan-SnkAse-Lc3_24_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_24_2_2",
"One-TwoChan-SnkAse-Lc3_16_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_16_2_2",
"One-TwoChan-SnkAse-Lc3_16_1_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_16_1_2",
"One-OneChan-SnkAse-Lc3_48_4_High_Reliability",
"One-OneChan-SnkAse-Lc3_48_4_2",
"One-OneChan-SnkAse-Lc3_48_2_High_Reliability",
"One-OneChan-SnkAse-Lc3_48_2_2",
"One-OneChan-SnkAse-Lc3_48_3_High_Reliability",
"One-OneChan-SnkAse-Lc3_48_3_2",
"One-OneChan-SnkAse-Lc3_48_1_High_Reliability",
"One-OneChan-SnkAse-Lc3_48_1_2",
"One-OneChan-SnkAse-Lc3_32_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_32_2_2",
"One-OneChan-SnkAse-Lc3_32_1_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_32_1_2",
"One-OneChan-SnkAse-Lc3_24_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_24_2_2",
"One-OneChan-SnkAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_16_2_2",
"One-OneChan-SnkAse-Lc3_16_1_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_16_1_2",
"VND_DualDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
"VND_DualDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
"VND_SingleDev_TwoChanStereoSnk_48khz_100octs_High_Reliability_1",
"VND_SingleDev_TwoChanStereoSnk_48khz_100octs_R15_L70_1",
"VND_SingleDev_OneChanStereoSnk_48khz_100octs_High_Reliability_1",
"VND_SingleDev_OneChanStereoSnk_48khz_100octs_R15_L70_1",
"DualDev_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanStereoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability"
"Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability"
]
},
{
"name": "Game",
"configurations": [
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Low_Latency",
"Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"VND_SingleDev_TwoChanStereoSnk_48khz_75octs_TwoChanStereoSrc_16khz_30octs_Balanced_Reliability_1",
"VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_TwoChanStereoSrc_16khz_30octs_R3_L12_1",
"VND_SingleDev_TwoChanStereoSnk_48khz_75octs_High_Reliability_1",
"VND_SingleDev_TwoChanStereoSnk_48khz_75octs_R5_L12_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
"DualDev_OneChanStereoSnk_48_2_Low_Latency",
"DualDev_OneChanStereoSnk_48_3_Low_Latency",
"DualDev_OneChanStereoSnk_48_1_Low_Latency",
"DualDev_OneChanStereoSnk_32_2_Low_Latency",
"DualDev_OneChanStereoSnk_32_1_Low_Latency",
"DualDev_OneChanStereoSnk_24_2_Low_Latency",
"DualDev_OneChanStereoSnk_24_1_Low_Latency",
"DualDev_OneChanStereoSnk_16_2_Low_Latency",
"DualDev_OneChanStereoSnk_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_48_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_48_3_Low_Latency",
"SingleDev_TwoChanStereoSnk_48_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_32_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_24_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_24_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_16_1_Low_Latency",
"SingleDev_OneChanStereoSnk_48_2_Low_Latency",
"SingleDev_OneChanStereoSnk_48_3_Low_Latency",
"SingleDev_OneChanStereoSnk_48_1_Low_Latency",
"SingleDev_OneChanStereoSnk_32_2_Low_Latency",
"SingleDev_OneChanStereoSnk_32_1_Low_Latency",
"SingleDev_OneChanStereoSnk_24_2_Low_Latency",
"SingleDev_OneChanStereoSnk_24_1_Low_Latency",
"SingleDev_OneChanStereoSnk_16_2_Low_Latency",
"SingleDev_OneChanStereoSnk_16_1_Low_Latency"
"Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_48_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_48_3_Low_Latency",
"Two-OneChan-SnkAse-Lc3_48_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_32_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_24_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_24_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_48_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_48_3_Low_Latency",
"One-TwoChan-SnkAse-Lc3_48_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_24_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_24_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1_Low_Latency"
]
},
{
"name": "VoiceAssistants",
"configurations": [
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
"DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_16_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_24_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_48_4_OneChanStereoSrc_32_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
"DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
"DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
"DualDev_OneChanDoubleStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_16_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_24_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_TwoChanStereoSrc_32_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
"SingleDev_OneChanStereoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_24_2_Balanced_Reliability",
"SingleDev_OneChanMonoSnk_48_4_OneChanMonoSrc_32_2_Balanced_Reliability"
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
"Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability",
"Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_48_4-Two-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
"Two-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_24_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4-One-TwoChan-SrcAse-Lc3_32_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_24_2_Balanced_Reliability",
"One-OneChan-SnkAse-Lc3_48_4-One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability"
]
},
{
@@ -260,44 +215,44 @@
"configurations": [
"VND_SingleDev_TwoChanStereoSrc_48khz_100octs_Balanced_Reliability_1",
"VND_SingleDev_TwoChanStereoSrc_48khz_100octs_R11_L40_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_32_2_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_2_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_Low_Latency",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_16_1_1",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_48_2_Balanced_Reliability",
"DualDev_OneChanStereoSnk_OneChanStereoSrc_48_1_Balanced_Reliability",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_32_2_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_2_1",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_TwoChanStereoSrc_16_1_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_TwoChanStereoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_OneChanStereoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_32_2_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_2_1",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_Low_Latency",
"SingleDev_OneChanMonoSnk_OneChanMonoSrc_16_1_1",
"SingleDev_OneChanMonoSrc_48_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_48_1_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_32_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_32_1_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_16_2_Balanced_Reliability",
"SingleDev_OneChanMonoSrc_16_1_Balanced_Reliability"
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-Two-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-Two-OneChan-SrcAse-Lc3_16_2_1",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-Two-OneChan-SrcAse-Lc3_16_1_1",
"Two-TwoChan-SnkAse-Lc3_48_2-Two-TwoChan-SrcAse-Lc3_48_2_Balanced_Reliability",
"Two-TwoChan-SnkAse-Lc3_48_1-Two-TwoChan-SrcAse-Lc3_48_1_Balanced_Reliability",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-TwoChan-SrcAse-Lc3_32_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-TwoChan-SrcAse-Lc3_16_2_1",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-TwoChan-SrcAse-Lc3_16_1_1",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-TwoChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"Two-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"Two-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_32_2-One-OneChan-SrcAse-Lc3_32_2_1",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_2-One-OneChan-SrcAse-Lc3_16_2_1",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_Low_Latency",
"One-OneChan-SnkAse-Lc3_16_1-One-OneChan-SrcAse-Lc3_16_1_1",
"One-OneChan-SrcAse-Lc3_48_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_48_1_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_32_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_32_1_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_16_2_Balanced_Reliability",
"One-OneChan-SrcAse-Lc3_16_1_Balanced_Reliability"
]
}
]