Skip to content

Commit

Permalink
Improve CF equality code
Browse files Browse the repository at this point in the history
  • Loading branch information
firthm01 committed Feb 12, 2024
1 parent 5651c47 commit 9ff952e
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 110 deletions.
97 changes: 97 additions & 0 deletions shared/helper/adm_equality_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#pragma once

#include <optional>
#include <functional>
#include <memory>
#include <algorithm>
#include <adm/adm.hpp>

namespace adm {
namespace helpers {

std::optional<adm::AudioBlockFormatDirectSpeakers const> static_ds_block(adm::AudioChannelFormat const& cf) {
using namespace adm;
if (cf.get<TypeDescriptor>() == TypeDefinition::DIRECT_SPEAKERS) {
auto blocks = cf.getElements<AudioBlockFormatDirectSpeakers>();
if (blocks.size() == 1) {
return blocks.front();
}
}
return {};
}

namespace equality {
using namespace adm;

enum class CompareHasResult { Neither, Both, Mismatch };

template<typename Property, typename Parent> CompareHasResult compareHas(Parent const& lhs, Parent const& rhs) {
bool hasProp = lhs.template has<Property>();
if (hasProp != rhs.template has<Property>())
return CompareHasResult::Mismatch;
if (hasProp)
return CompareHasResult::Both;
return CompareHasResult::Neither;
}

template<typename T> bool equals(T const& lhs, T const& rhs) {
return std::equal_to<T>{}(lhs, rhs);
}

template<typename Property, typename Parent> bool propertyMatch(Parent const& lhs, Parent const& rhs) {
switch (compareHas<Property>(lhs, rhs)) {
case CompareHasResult::Mismatch:
return false;
case CompareHasResult::Neither:
return true;
case CompareHasResult::Both:
return equals(lhs.template get<Property>(), rhs.template get<Property>());
default:
return false; // just to keep compiler warnings away
}
}

template<typename... Properties, typename Parent> bool propertiesMatch(Parent const& lhs, Parent const& rhs) {
return (propertyMatch<Properties, Parent>(lhs, rhs) && ...);
}

template<> bool equals(Gain const& lhs, Gain const& rhs) {
return lhs.get() == rhs.get();
}

template<> bool equals(SpeakerLabels const& lhs, SpeakerLabels const& rhs) {
return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}

template<> bool equals(HeadphoneVirtualise const& lhs, HeadphoneVirtualise const& rhs) {
return propertiesMatch<Bypass, DirectToReverberantRatio>(lhs, rhs);
}

template<> bool equals(ScreenEdgeLock const& lhs, ScreenEdgeLock const& rhs) {
return propertiesMatch<HorizontalEdge, VerticalEdge>(lhs, rhs);
}

template<> bool equals(SphericalSpeakerPosition const& lhs, SphericalSpeakerPosition const& rhs) {
return propertiesMatch<Azimuth, AzimuthMin, AzimuthMax, Elevation, ElevationMin, ElevationMax, Distance, DistanceMin, DistanceMax, ScreenEdgeLock>(lhs, rhs);
}

template<> bool equals(CartesianSpeakerPosition const& lhs, CartesianSpeakerPosition const& rhs) {
return propertiesMatch<X, XMin, XMax, Y, YMin, YMax, Z, ZMin, ZMax, ScreenEdgeLock>(lhs, rhs);
}

bool isEquivalentByProperties(std::shared_ptr<const adm::AudioChannelFormat> cfA, std::shared_ptr<const adm::AudioChannelFormat> cfB) {
if (compareHas<TypeDescriptor>(*cfA, *cfB) != CompareHasResult::Both) {
return false;
}
// TODO: only support matching up DS AudioChannelFormats for now
auto bfA = adm::helpers::static_ds_block(*cfA);
auto bfB = adm::helpers::static_ds_block(*cfB);
if(bfA && bfB) {
return propertiesMatch<SpeakerLabels, Importance, HeadLocked, Gain, HeadphoneVirtualise, SphericalSpeakerPosition, CartesianSpeakerPosition>(*bfA, *bfB);
}
return false;
}
}

}
}
111 changes: 2 additions & 109 deletions shared/helper/adm_preset_definitions_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
#include <adm/common_definitions.hpp>
#include <adm/parse.hpp>
#include <algorithm>
#include <string>
#include <string_view>
#include <sstream>
#include <vector>
#include <helper/container_helpers.hpp>
#include <helper/supplementary_definitions.hpp>
#include <helper/cartesianspeakerlayouts.h>
#include <helper/adm_equality_helpers.h>

namespace {
std::vector<std::string_view> splitString(const std::string& input, char delimiter, size_t maxElements) {
Expand All @@ -30,19 +29,6 @@ namespace {

return result;
}

template <typename Prop, typename Elm>
bool matchingProp(const Elm& elmA, const Elm& elmB) {
bool hasProp = elmA.template has<Prop>();
if (hasProp != elmB.template has<Prop>())
return false;
if (hasProp) {
auto valA = elmA.template get<Prop>();
auto valB = elmB.template get<Prop>();
if (valA != valB) return false;
}
return true;
}
}

std::shared_ptr<AdmPresetDefinitionsHelper> AdmPresetDefinitionsHelper::getSingleton()
Expand Down Expand Up @@ -217,7 +203,7 @@ std::shared_ptr<AdmPresetDefinitionsHelper::PackFormatData const> AdmPresetDefin
}
// Custom CF's must be matched by properties, because they won't have consistent ID's
else {
if (!isEquivalentByProperties(pfDataCfDatas[i]->channelFormat, cfsToFind[i].second)) {
if (!adm::helpers::equality::isEquivalentByProperties(pfDataCfDatas[i]->channelFormat, cfsToFind[i].second)) {
matching = false;
break;
}
Expand Down Expand Up @@ -303,99 +289,6 @@ void AdmPresetDefinitionsHelper::recursePackFormatsForChannelFormats(std::shared
}
}

bool AdmPresetDefinitionsHelper::isEquivalentByProperties(std::shared_ptr<const adm::AudioChannelFormat> cfA, std::shared_ptr<const adm::AudioChannelFormat> cfB)
{
auto td = cfA->get<adm::TypeDescriptor>();
if (td != cfB->get<adm::TypeDescriptor>())
return false;

// TODO: only support matching up DS AudioChannelFormats for now
if (td == adm::TypeDefinition::DIRECT_SPEAKERS) {
auto bfsA = cfA->getElements<adm::AudioBlockFormatDirectSpeakers>();
auto bfsB = cfB->getElements<adm::AudioBlockFormatDirectSpeakers>();
if (bfsA.size() != 1 || bfsB.size() != 1)
return false;
auto bfA = bfsA[0];
auto bfB = bfsB[0];

auto slsA = bfA.get<adm::SpeakerLabels>();
auto slsB = bfB.get<adm::SpeakerLabels>();
if (slsA.size() != slsB.size())
return false;
for (int i = 0; i < slsA.size(); ++i) {
if (slsA[i] != slsB[i])
return false;
}

if (!matchingProp<adm::Importance>(bfA, bfB)) return false;
if (!matchingProp<adm::HeadLocked>(bfA, bfB)) return false;

if (bfA.has<adm::Gain>() != bfB.has<adm::Gain>())
return false;
if (bfA.has<adm::Gain>()) {
if (bfA.get<adm::Gain>().get() != bfB.get<adm::Gain>().get())
return false;
}

if (bfA.has<adm::HeadphoneVirtualise>() != bfB.has<adm::HeadphoneVirtualise>())
return false;
if (bfA.has<adm::HeadphoneVirtualise>()) {
auto hpvA = bfA.get<adm::HeadphoneVirtualise>();
auto hpvB = bfB.get<adm::HeadphoneVirtualise>();
if (!matchingProp<adm::Bypass>(hpvA, hpvB)) return false;
if (!matchingProp<adm::DirectToReverberantRatio>(hpvA, hpvB)) return false;
}

if (bfA.has<adm::SphericalSpeakerPosition>() && bfB.has<adm::SphericalSpeakerPosition>()) {

auto spA = bfA.get<adm::SphericalSpeakerPosition>();
auto spB = bfB.get<adm::SphericalSpeakerPosition>();
if (!matchingProp<adm::Azimuth>(spA, spB)) return false;
if (!matchingProp<adm::AzimuthMin>(spA, spB)) return false;
if (!matchingProp<adm::AzimuthMax>(spA, spB)) return false;
if (!matchingProp<adm::Elevation>(spA, spB)) return false;
if (!matchingProp<adm::ElevationMin>(spA, spB)) return false;
if (!matchingProp<adm::ElevationMax>(spA, spB)) return false;
if (!matchingProp<adm::Distance>(spA, spB)) return false;
if (!matchingProp<adm::DistanceMin>(spA, spB)) return false;
if (!matchingProp<adm::DistanceMax>(spA, spB)) return false;

auto selA = spA.get<adm::ScreenEdgeLock>();
auto selB = spB.get<adm::ScreenEdgeLock>();
if (!matchingProp<adm::HorizontalEdge>(selA, selB)) return false;
if (!matchingProp<adm::VerticalEdge>(selA, selB)) return false;

}
else if (bfA.has<adm::CartesianSpeakerPosition>() && bfB.has<adm::CartesianSpeakerPosition>()) {

auto spA = bfA.get<adm::CartesianSpeakerPosition>();
auto spB = bfB.get<adm::CartesianSpeakerPosition>();
if (!matchingProp<adm::X>(spA, spB)) return false;
if (!matchingProp<adm::XMin>(spA, spB)) return false;
if (!matchingProp<adm::XMax>(spA, spB)) return false;
if (!matchingProp<adm::Y>(spA, spB)) return false;
if (!matchingProp<adm::YMin>(spA, spB)) return false;
if (!matchingProp<adm::YMax>(spA, spB)) return false;
if (!matchingProp<adm::Z>(spA, spB)) return false;
if (!matchingProp<adm::ZMin>(spA, spB)) return false;
if (!matchingProp<adm::ZMax>(spA, spB)) return false;

auto selA = spA.get<adm::ScreenEdgeLock>();
auto selB = spB.get<adm::ScreenEdgeLock>();
if (!matchingProp<adm::HorizontalEdge>(selA, selB)) return false;
if (!matchingProp<adm::VerticalEdge>(selA, selB)) return false;

}
else {
return false;
}

return true;
}

return false;
}



AdmPresetDefinitionsHelper::ChannelFormatData::ChannelFormatData(std::shared_ptr<adm::AudioChannelFormat> cf, std::shared_ptr<adm::AudioPackFormat> fromPackFormat)
Expand Down
1 change: 0 additions & 1 deletion shared/helper/adm_preset_definitions_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ class AdmPresetDefinitionsHelper {
private:
void populateElementRelationshipsFor(adm::TypeDescriptor);
void recursePackFormatsForChannelFormats(std::shared_ptr<adm::AudioPackFormat> fromPackFormat, std::shared_ptr<PackFormatData> forPackFormatData);
bool isEquivalentByProperties(std::shared_ptr<const adm::AudioChannelFormat> cfA, std::shared_ptr<const adm::AudioChannelFormat> cfB);
std::shared_ptr<adm::Document> presetDefinitions;
std::vector<std::shared_ptr<TypeDefinitionData const>> typeDefinitionDatas{ 6, nullptr }; // last elm index 5 (highest TD)
};

0 comments on commit 9ff952e

Please sign in to comment.