Init foo_input_joc
build / windows (push) Has been cancelled

This commit is contained in:
2026-09-25 17:07:04 +08:00
commit ad62a914e6
127 changed files with 38545 additions and 0 deletions
@@ -0,0 +1,71 @@
#include "speaker/speaker_layout_lookup.h"
#include <cstring>
namespace joc::speaker {
namespace {
struct FrozenLayout {
const char* name;
std::uint32_t out_ch_config;
std::uint32_t speaker_bitfield;
};
constexpr FrozenLayout kLayouts[kLayoutCount] = {
{"2.0", 0, 1},
{"3.1", 3, 7},
{"5.1", 7, 15},
{"7.1", 11, 31},
{"5.1.2", 13, 1039},
{"5.1.4", 14, 2575},
{"7.1.2", 15, 1055},
{"7.1.4", 16, 2591},
{"9.1.4", 19, 2719},
{"9.1.6", 20, 3743},
};
void fill(const FrozenLayout& source, LayoutInfo* out) {
out->name = source.name;
out->out_ch_config = source.out_ch_config;
out->speaker_bitfield = source.speaker_bitfield;
out->channel_count = ejoc_speaker_layout_channel_count(source.speaker_bitfield);
}
} // namespace
bool layout_at(int index, LayoutInfo* out) {
if (out == nullptr || index < 0 || index >= kLayoutCount) {
return false;
}
fill(kLayouts[index], out);
return true;
}
bool layout_by_name(const char* name, LayoutInfo* out) {
if (name == nullptr || out == nullptr) {
return false;
}
for (int index = 0; index < kLayoutCount; ++index) {
if (std::strcmp(name, kLayouts[index].name) == 0) {
fill(kLayouts[index], out);
return true;
}
}
return false;
}
bool layout_by_bitfield(std::uint32_t bitfield, LayoutInfo* out) {
if (out == nullptr) {
return false;
}
for (int index = 0; index < kLayoutCount; ++index) {
if (kLayouts[index].speaker_bitfield == bitfield) {
fill(kLayouts[index], out);
return true;
}
}
return false;
}
} // namespace joc::speaker
@@ -0,0 +1,28 @@
#pragma once
#include <cstdint>
#include "eac3joc_core.h"
#include "joc_core.h"
namespace joc::speaker {
inline constexpr int kLayoutCount = 10;
struct LayoutInfo {
const char* name = "";
std::uint32_t out_ch_config = 0;
std::uint32_t speaker_bitfield = 0;
std::uint32_t channel_count = 0;
};
// All ten layouts in the reference's order (2.0, 3.1, 5.1, 7.1, 5.1.2, 5.1.4,
bool layout_at(int index, LayoutInfo* out);
// False when the name is unknown (case-sensitive, exactly as the reference CLI).
bool layout_by_name(const char* name, LayoutInfo* out);
bool layout_by_bitfield(std::uint32_t bitfield, LayoutInfo* out);
} // namespace joc::speaker
+534
View File
@@ -0,0 +1,534 @@
#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
namespace ejoc::speaker_tables {
inline constexpr std::size_t kMaxPoints = 15;
inline constexpr std::size_t kMaxGroups = 4;
inline constexpr std::size_t kMaxGroupSize = 3;
inline constexpr std::size_t kMaxChannels = 16;
struct SpeakerPoint {
std::array<std::uint16_t, 3> coordinate_q15{};
std::uint8_t speaker_id{};
};
struct AxisGroup {
std::uint8_t size{};
std::array<std::uint8_t, kMaxGroupSize> indices{};
};
struct RegionGeometry {
std::uint8_t point_count{};
std::uint8_t mode{};
std::uint8_t axis0_group_count{};
std::uint8_t axis1_group_count{};
std::array<SpeakerPoint, kMaxPoints> points{};
std::array<AxisGroup, kMaxGroups> axis0_groups{};
std::array<AxisGroup, kMaxGroups> axis1_groups{};
};
struct LayoutGeometry {
std::uint32_t speaker_bitfield{};
std::uint8_t out_ch_config{};
std::uint8_t channel_count{};
std::array<std::uint8_t, kMaxChannels> standard_from_internal{};
std::array<RegionGeometry, 7> regions{};
};
inline constexpr std::array<LayoutGeometry, 10> kLayouts{{
LayoutGeometry{
0x1u, 0, 2,
{{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0x7u, 3, 4,
{{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
1, 1, 1, 0,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0xFu, 7, 6,
{{0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
5, 2, 2, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 2, 2, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 2, 2, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 2, 2, 0,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
2, 1, 1, 0,
{{SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0x1Fu, 11, 8,
{{0, 1, 2, 3, 6, 7, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
7, 2, 3, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 2, 2, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 2, 2, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 2, 2, 0,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
4, 2, 2, 0,
{{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0x40Fu, 13, 8,
{{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 3, 2, 1,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 3, 1, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
4, 3, 1, 1,
{{SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0xA0Fu, 14, 10,
{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
9, 3, 2, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 2, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 2, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 2,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 1, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
6, 3, 1, 2,
{{SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {2, 3, 0}}, AxisGroup{2, {4, 5, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 3, 1, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0x41Fu, 15, 10,
{{0, 1, 2, 3, 6, 7, 4, 5, 8, 9, 0, 0, 0, 0, 0, 0}},
{{
RegionGeometry{
9, 3, 3, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}}},
{{AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 3, 2, 1,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 3, 1, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
6, 3, 2, 1,
{{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {4, 5, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
3, 1, 1, 0,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0xA1Fu, 16, 12,
{{0, 1, 2, 3, 6, 7, 4, 5, 8, 9, 10, 11, 0, 0, 0, 0}},
{{
RegionGeometry{
11, 3, 3, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}}},
{{AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 2, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 2, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 2,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 1, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
8, 3, 2, 2,
{{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {4, 5, 0}}, AxisGroup{2, {6, 7, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
5, 3, 1, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0xA9Fu, 19, 14,
{{0, 1, 2, 3, 6, 7, 4, 5, 10, 11, 12, 13, 8, 9, 0, 0}},
{{
RegionGeometry{
13, 3, 4, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}}},
{{AxisGroup{2, {9, 10, 0}}, AxisGroup{2, {11, 12, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
11, 3, 3, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}}},
{{AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 2, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 2,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 1, 2,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
8, 3, 2, 2,
{{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {4, 5, 0}}, AxisGroup{2, {6, 7, 0}}, AxisGroup{}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
},
LayoutGeometry{
0xE9Fu, 20, 16,
{{0, 1, 2, 3, 6, 7, 4, 5, 10, 11, 14, 15, 12, 13, 8, 9}},
{{
RegionGeometry{
15, 3, 4, 3,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}}},
{{AxisGroup{2, {9, 10, 0}}, AxisGroup{2, {11, 12, 0}}, AxisGroup{2, {13, 14, 0}}, AxisGroup{}}}
},
RegionGeometry{
13, 3, 3, 3,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}}},
{{AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{2, {11, 12, 0}}, AxisGroup{}}}
},
RegionGeometry{
11, 3, 2, 3,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 2, 3,
{{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}}}
},
RegionGeometry{
9, 3, 1, 3,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}}}
},
RegionGeometry{
10, 3, 2, 3,
{{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {4, 5, 0}}, AxisGroup{2, {6, 7, 0}}, AxisGroup{2, {8, 9, 0}}, AxisGroup{}}}
},
RegionGeometry{
7, 3, 2, 1,
{{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}},
{{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}},
{{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}
}
}}
}
}};
inline constexpr const LayoutGeometry* find_layout(const std::uint32_t speaker_bitfield) noexcept {
for (const auto& layout : kLayouts) {
if (layout.speaker_bitfield == speaker_bitfield) {
return &layout;
}
}
return nullptr;
}
} // namespace ejoc::speaker_tables
+495
View File
@@ -0,0 +1,495 @@
#define EJOC_BUILD_DLL
#include "eac3joc_core.h"
#include "speaker_layouts.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <new>
namespace ejoc::speaker {
using speaker_tables::AxisGroup;
using speaker_tables::LayoutGeometry;
using speaker_tables::RegionGeometry;
constexpr double kPi = 3.141592653589793238462643383279502884;
constexpr double kQ15Scale = 32768.0;
constexpr double kQ15Max = 32767.0 / kQ15Scale;
constexpr double kGainSnapThreshold = 1.0e-4;
constexpr std::size_t kObjects = EJOC_MAX_OBJECTS;
constexpr std::size_t kChannels = EJOC_OUTPUT_CHANNELS;
constexpr std::size_t kBlock = EJOC_SPEAKER_BLOCK_SAMPLES;
using PointGains = std::array<double, speaker_tables::kMaxPoints>;
using ChannelGains = std::array<double, kChannels>;
using ObjectChannelGains = std::array<ChannelGains, kObjects>;
using RemainingCounts = std::array<std::array<std::uint32_t, kChannels>, kObjects>;
inline double clamp(const double value, const double low, const double high) noexcept {
return value < low ? low : (value > high ? high : value);
}
inline double coordinate(const RegionGeometry& region, const std::size_t point,
const std::size_t component) noexcept {
return static_cast<double>(region.points[point].coordinate_q15[component]) / kQ15Scale;
}
std::uint64_t expand_speaker_bitfield(const std::uint32_t compact) noexcept {
constexpr std::array<std::uint64_t, 22> expansions{{
0x00000003ULL, 0x00000004ULL, 0x00000008ULL, 0x00000030ULL,
0x000000C0ULL, 0x00000100ULL, 0x00000600ULL, 0x00001800ULL,
0x00006000ULL, 0x00018000ULL, 0x00060000ULL, 0x00180000ULL,
0x00600000ULL, 0x01800000ULL, 0x06000000ULL, 0x18000000ULL,
0x60000000ULL, 0x080000000ULL, 0x600000000ULL, 0x800000000ULL,
0x1000000000ULL, 0x2000000000ULL,
}};
std::uint64_t expanded = 0;
for (std::size_t bit_index = 0; bit_index < expansions.size(); ++bit_index) {
if ((compact & (1u << bit_index)) != 0) {
expanded |= expansions[bit_index];
}
}
return expanded;
}
inline int bit(const std::uint64_t value, const unsigned index) noexcept {
return static_cast<int>((value >> index) & 1ULL);
}
double layout_attenuation_db(const std::uint32_t compact) noexcept {
const std::uint64_t expanded = expand_speaker_bitfield(compact);
const int height_channels = 2 * (
bit(expanded, 13) + bit(expanded, 15) + bit(expanded, 17) +
bit(expanded, 19) + bit(expanded, 21));
const int floor_channels = bit(expanded, 8) + 2 * (
bit(expanded, 31) + bit(expanded, 4) + bit(expanded, 6) +
bit(expanded, 11) + bit(expanded, 25) + bit(expanded, 27) +
bit(expanded, 29) + bit(expanded, 33));
const double height_factor = std::min(static_cast<double>(height_channels) / 4.0, 1.0);
const double floor_factor = std::min(static_cast<double>(floor_channels) / 4.0, 1.0);
return -std::max(4.5 - 1.5 * height_factor - 3.0 * floor_factor, 0.0);
}
int floor_y_exponent(const std::uint32_t compact) noexcept {
const std::uint32_t low = static_cast<std::uint32_t>(expand_speaker_bitfield(compact));
return ((low & 0x130u) != 0 && (low & 0x18C0u) == 0) ? 1 : 0;
}
inline void equal_power_pair(const double position, double& lower, double& upper) noexcept {
const double angle = (kPi * 0.5) * position;
lower = std::cos(angle);
upper = std::sin(angle);
}
void axis0_gains(const RegionGeometry& region,
const std::array<AxisGroup, speaker_tables::kMaxGroups>& groups,
const std::uint8_t group_count,
const double value,
PointGains& output) noexcept {
output.fill(0.0);
for (std::size_t row = 0; row < group_count; ++row) {
const auto& group = groups[row];
if (group.size == 0) {
continue;
}
const std::size_t first = group.indices[0];
const std::size_t last = group.indices[group.size - 1];
const double first_value = coordinate(region, first, 0);
const double last_value = coordinate(region, last, 0);
if (value <= first_value) {
output[first] = 1.0;
continue;
}
if (value >= last_value) {
output[last] = 1.0;
continue;
}
for (std::size_t index = 0; index + 1 < group.size; ++index) {
const std::size_t lower_index = group.indices[index];
const std::size_t upper_index = group.indices[index + 1];
const double lower_value = coordinate(region, lower_index, 0);
const double upper_value = coordinate(region, upper_index, 0);
if (value > lower_value && value <= upper_value) {
const double position = (value - lower_value) / (upper_value - lower_value);
equal_power_pair(position, output[lower_index], output[upper_index]);
break;
}
}
}
}
void axis1_gains(const RegionGeometry& region,
const std::array<AxisGroup, speaker_tables::kMaxGroups>& groups,
const std::uint8_t group_count,
const double value,
PointGains& output) noexcept {
output.fill(0.0);
if (group_count == 0) {
return;
}
const auto& first_group = groups[0];
const auto& last_group = groups[group_count - 1];
const double first_value = coordinate(region, first_group.indices[0], 1);
const double last_value = coordinate(region, last_group.indices[0], 1);
if (value <= first_value) {
for (std::size_t index = 0; index < first_group.size; ++index) {
output[first_group.indices[index]] = 1.0;
}
return;
}
if (value > last_value) {
for (std::size_t index = 0; index < last_group.size; ++index) {
output[last_group.indices[index]] = 1.0;
}
return;
}
for (std::size_t row = 0; row + 1 < group_count; ++row) {
const auto& lower_group = groups[row];
const auto& upper_group = groups[row + 1];
const double lower_value = coordinate(region, lower_group.indices[0], 1);
const double upper_value = coordinate(region, upper_group.indices[0], 1);
if (value >= lower_value && value <= upper_value) {
const double position = (value - lower_value) / (upper_value - lower_value);
double lower_gain = 0.0;
double upper_gain = 0.0;
equal_power_pair(position, lower_gain, upper_gain);
for (std::size_t index = 0; index < lower_group.size; ++index) {
output[lower_group.indices[index]] = lower_gain;
}
for (std::size_t index = 0; index < upper_group.size; ++index) {
output[upper_group.indices[index]] = upper_gain;
}
return;
}
}
}
void plane_gains(const RegionGeometry& region,
const std::array<AxisGroup, speaker_tables::kMaxGroups>& groups,
const std::uint8_t group_count,
const double u,
const double v,
const std::uint8_t mode,
PointGains& output) noexcept {
axis0_gains(region, groups, group_count, u, output);
if (mode >= 2) {
PointGains vertical{};
axis1_gains(region, groups, group_count, v, vertical);
for (std::size_t point = 0; point < region.point_count; ++point) {
output[point] *= vertical[point];
}
}
}
class Renderer {
public:
explicit Renderer(const LayoutGeometry* layout) noexcept : layout_(layout) {
for (std::size_t standard = 0; standard < layout_->channel_count; ++standard) {
standard_index_for_internal_[layout_->standard_from_internal[standard]] =
static_cast<std::uint8_t>(standard);
}
attenuation_db_ = layout_attenuation_db(layout_->speaker_bitfield);
floor_y_exponent_ = floor_y_exponent(layout_->speaker_bitfield);
reset_state();
}
int reset() noexcept {
reset_state();
error_[0] = '\0';
return 0;
}
const char* last_error() const noexcept {
return error_[0] ? error_.data() : "";
}
int process(const float* input,
const std::uint32_t sample_count,
const std::uint32_t metadata_count,
const std::uint32_t* metadata_offsets,
const std::uint32_t* ramp_durations,
const std::uint16_t* positions_q15,
const std::uint8_t* region_indices,
const std::uint8_t* height_enabled,
const double* object_gains,
double* output) noexcept {
error_[0] = '\0';
if (!input || !output) {
return fail("null PCM pointer passed to ejoc_speaker_renderer_process");
}
if ((sample_count % kBlock) != 0) {
return fail("sample_count must be a multiple of 32");
}
if (metadata_count && (!metadata_offsets || !ramp_durations || !positions_q15)) {
return fail("metadata arrays are null while metadata_count is nonzero");
}
if (!validate_metadata(sample_count, metadata_count, metadata_offsets,
positions_q15, region_indices, object_gains)) {
return -1;
}
std::fill(output, output + static_cast<std::size_t>(sample_count) * layout_->channel_count, 0.0);
const bool has_lfe = (layout_->speaker_bitfield & 0x4u) != 0;
const std::size_t total_blocks = sample_count / kBlock;
std::size_t event = 0;
for (std::size_t block = 0; block < total_blocks; ++block) {
while (event < metadata_count && aligned_block(metadata_offsets[event]) == block) {
apply_event(event, ramp_durations, positions_q15, region_indices,
height_enabled, object_gains);
++event;
}
mix_block(input, output, block, has_lfe);
}
while (event < metadata_count && aligned_block(metadata_offsets[event]) == total_blocks) {
apply_event(event, ramp_durations, positions_q15, region_indices,
height_enabled, object_gains);
++event;
}
if (event != metadata_count) {
return fail("metadata alignment produced an event outside this process call");
}
return 0;
}
private:
void reset_state() noexcept {
for (auto& row : current_) row.fill(0.0);
for (auto& row : target_) row.fill(0.0);
for (auto& row : step_) row.fill(0.0);
for (auto& row : remaining_) row.fill(0);
}
int fail(const char* message) noexcept {
std::snprintf(error_.data(), error_.size(), "%s", message);
return -1;
}
bool validate_metadata(const std::uint32_t sample_count,
const std::uint32_t metadata_count,
const std::uint32_t* metadata_offsets,
const std::uint16_t* positions_q15,
const std::uint8_t* region_indices,
const double* object_gains) noexcept {
for (std::size_t event = 0; event < metadata_count; ++event) {
if (metadata_offsets[event] > sample_count) {
fail("metadata offset exceeds sample_count");
return false;
}
if (event && metadata_offsets[event] < metadata_offsets[event - 1]) {
fail("metadata offsets must be nondecreasing");
return false;
}
for (std::size_t object = 0; object < kObjects; ++object) {
const std::size_t object_event = event * kObjects + object;
if (region_indices && region_indices[object_event] >= 7) {
fail("region index is above 6");
return false;
}
if (object_gains && !std::isfinite(object_gains[object_event])) {
fail("object gain is not finite");
return false;
}
const std::size_t coordinate_base = object_event * EJOC_SPEAKER_COORDINATES;
for (std::size_t component = 0; component < EJOC_SPEAKER_COORDINATES; ++component) {
if (positions_q15[coordinate_base + component] > 32767u) {
fail("Q15 object coordinate is above 32767");
return false;
}
}
}
}
return true;
}
static std::size_t aligned_block(const std::uint32_t sample) noexcept {
return (static_cast<std::size_t>(sample) + kBlock / 2 - 1) / kBlock;
}
static std::uint32_t ramp_blocks(const std::uint32_t duration) noexcept {
return static_cast<std::uint32_t>(
(static_cast<std::size_t>(duration) + kBlock / 2 - 1) / kBlock);
}
void render_point(const std::uint16_t* position,
const std::uint8_t region_index,
const bool enable_height,
const double object_gain,
ChannelGains& output) const noexcept {
output.fill(0.0);
const auto& region = layout_->regions[region_index];
const double u = static_cast<double>(position[0]) / kQ15Scale;
const double v = static_cast<double>(position[1]) / kQ15Scale;
const double w = static_cast<double>(position[2]) / kQ15Scale;
const double floor_v = clamp(std::ldexp(v, floor_y_exponent_), 0.0, 1.0);
PointGains floor{};
plane_gains(region, region.axis0_groups, region.axis0_group_count,
u, floor_v, region.mode, floor);
PointGains point = floor;
if (region.mode == 3) {
PointGains height{};
plane_gains(region, region.axis1_groups, region.axis1_group_count,
u, v, 3, height);
const double z = enable_height ? clamp(w, 0.0, kQ15Max) : 0.0;
if (z >= kQ15Max) {
point = height;
} else if (z > 0.0) {
double floor_weight = 0.0;
double height_weight = 0.0;
equal_power_pair(z, floor_weight, height_weight);
for (std::size_t index = 0; index < region.point_count; ++index) {
point[index] = floor[index] * floor_weight + height[index] * height_weight;
}
}
}
const double y_term = clamp(v / 0.6, 0.0, 1.0);
const double z_term = clamp((w - 0.2) / 0.8, 0.0, 1.0);
const double amount = clamp(y_term + z_term, 0.0, 1.0);
const double gain = std::pow(10.0, attenuation_db_ * amount / 20.0) * object_gain;
for (std::size_t index = 0; index < region.point_count; ++index) {
output[region.points[index].speaker_id] = point[index] * gain;
}
}
void apply_event(const std::size_t event,
const std::uint32_t* ramp_durations,
const std::uint16_t* positions_q15,
const std::uint8_t* region_indices,
const std::uint8_t* height_enabled,
const double* object_gains) noexcept {
const std::uint32_t blocks = ramp_blocks(ramp_durations[event]);
for (std::size_t object = 0; object < kObjects; ++object) {
const std::size_t object_event = event * kObjects + object;
const auto* position = positions_q15 + object_event * EJOC_SPEAKER_COORDINATES;
const std::uint8_t region = region_indices ? region_indices[object_event] : 0;
const bool height = !height_enabled || height_enabled[object_event] != 0;
const double object_gain = object_gains ? object_gains[object_event] : 1.0;
ChannelGains next{};
render_point(position, region, height, object_gain, next);
for (std::size_t channel = 0; channel < layout_->channel_count; ++channel) {
const double difference = next[channel] - current_[object][channel];
target_[object][channel] = next[channel];
if (std::abs(difference) >= kGainSnapThreshold && blocks != 0) {
step_[object][channel] = difference / static_cast<double>(blocks);
remaining_[object][channel] = blocks;
} else {
current_[object][channel] = next[channel];
step_[object][channel] = 0.0;
remaining_[object][channel] = 0;
}
}
}
}
void mix_block(const float* input, double* output, const std::size_t block,
const bool has_lfe) noexcept {
const std::size_t start = block * kBlock;
if (has_lfe) {
for (std::size_t sample = 0; sample < kBlock; ++sample) {
output[(start + sample) * layout_->channel_count + 3] =
static_cast<double>(input[(start + sample) * EJOC_OUTPUT_CHANNELS]);
}
}
for (std::size_t object = 0; object < kObjects; ++object) {
for (std::size_t internal = 0; internal < layout_->channel_count; ++internal) {
const bool active = remaining_[object][internal] != 0;
const double fixed_gain = target_[object][internal];
if (!active && fixed_gain == 0.0) {
continue;
}
const std::size_t standard = standard_index_for_internal_[internal];
for (std::size_t sample = 0; sample < kBlock; ++sample) {
const double gain = active
? current_[object][internal] +
(static_cast<double>(sample) / static_cast<double>(kBlock)) *
step_[object][internal]
: fixed_gain;
output[(start + sample) * layout_->channel_count + standard] +=
static_cast<double>(
input[(start + sample) * EJOC_OUTPUT_CHANNELS + object + 1]) * gain;
}
if (active) {
current_[object][internal] += step_[object][internal];
--remaining_[object][internal];
if (remaining_[object][internal] == 0) {
current_[object][internal] = target_[object][internal];
}
} else {
current_[object][internal] = target_[object][internal];
}
}
}
}
const LayoutGeometry* layout_;
double attenuation_db_{};
int floor_y_exponent_{};
ObjectChannelGains current_{};
ObjectChannelGains target_{};
ObjectChannelGains step_{};
RemainingCounts remaining_{};
std::array<std::uint8_t, kChannels> standard_index_for_internal_{};
std::array<char, 256> error_{};
};
} // namespace ejoc::speaker
extern "C" {
uint32_t EJOC_CALL ejoc_speaker_layout_channel_count(const uint32_t speaker_bitfield) {
const auto* layout = ejoc::speaker_tables::find_layout(speaker_bitfield);
return layout ? layout->channel_count : 0;
}
ejoc_speaker_renderer_handle EJOC_CALL ejoc_speaker_renderer_create(
const uint32_t speaker_bitfield) {
const auto* layout = ejoc::speaker_tables::find_layout(speaker_bitfield);
if (!layout) {
return nullptr;
}
return new (std::nothrow) ejoc::speaker::Renderer(layout);
}
void EJOC_CALL ejoc_speaker_renderer_destroy(ejoc_speaker_renderer_handle handle) {
delete static_cast<ejoc::speaker::Renderer*>(handle);
}
int EJOC_CALL ejoc_speaker_renderer_reset(ejoc_speaker_renderer_handle handle) {
if (!handle) {
return -1;
}
return static_cast<ejoc::speaker::Renderer*>(handle)->reset();
}
const char* EJOC_CALL ejoc_speaker_renderer_last_error(ejoc_speaker_renderer_handle handle) {
if (!handle) {
return "speaker renderer handle is null";
}
return static_cast<ejoc::speaker::Renderer*>(handle)->last_error();
}
int EJOC_CALL ejoc_speaker_renderer_process(
ejoc_speaker_renderer_handle handle,
const float* objects16_interleaved,
const uint32_t sample_count,
const uint32_t metadata_count,
const uint32_t* metadata_offsets,
const uint32_t* ramp_durations,
const uint16_t* positions_q15,
const uint8_t* region_indices,
const uint8_t* height_enabled,
const double* object_gains,
double* output_interleaved) {
if (!handle) {
return -1;
}
return static_cast<ejoc::speaker::Renderer*>(handle)->process(
objects16_interleaved, sample_count, metadata_count,
metadata_offsets, ramp_durations, positions_q15,
region_indices, height_enabled, object_gains, output_interleaved);
}
} // extern "C"
+62
View File
@@ -0,0 +1,62 @@
#include "speaker/speaker_step.h"
#include <cstdio>
namespace joc::speaker {
Status step(SpeakerStep* context, const std::vector<float>& objects16_planar,
const oamd::OamdUpdate* update, std::string* error) {
if (context == nullptr || context->handle == nullptr) {
return Status::fail(JOC_ERR_STATE, stage::kRender, "speaker renderer is not open");
}
if (objects16_planar.size() !=
static_cast<std::size_t>(JOC_OUTPUT_CHANNELS) * JOC_FRAME_SAMPLES) {
return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender,
"objects16 must be [16][1536]");
}
context->interleaved.assign(static_cast<std::size_t>(JOC_FRAME_SAMPLES) * JOC_OUTPUT_CHANNELS,
0.0f);
for (std::size_t n = 0; n < JOC_FRAME_SAMPLES; ++n) {
for (std::size_t c = 0; c < JOC_OUTPUT_CHANNELS; ++c) {
context->interleaved[n * JOC_OUTPUT_CHANNELS + c] =
objects16_planar[c * JOC_FRAME_SAMPLES + n];
}
}
context->output.assign(
static_cast<std::size_t>(JOC_FRAME_SAMPLES) * context->layout.channel_count, 0.0);
context->last_had_payload = update != nullptr;
std::uint32_t ramp = 0;
if (update != nullptr) {
context->state.apply(*update);
ramp = update->ramp_duration_samples;
context->last_block_offset = update->block_offset_samples;
context->last_ramp_duration = update->ramp_duration_samples;
context->last_object_count = update->object_count;
}
std::uint16_t positions[oamd::kObjects][3] = {};
context->state.object_positions_q15(positions);
// A frame without OAMD must not touch the gains at all (no event), otherwise a
// pending ramp would snap - matching the reference exactly.
const std::uint32_t event_count = context->last_had_payload ? 1u : 0u;
const std::uint32_t offset = context->metadata_offset;
const int result = ejoc_speaker_renderer_process(
context->handle, context->interleaved.data(), JOC_FRAME_SAMPLES, event_count,
event_count != 0u ? &offset : nullptr, event_count != 0u ? &ramp : nullptr,
event_count != 0u ? &positions[0][0] : nullptr, nullptr, nullptr, nullptr,
context->output.data());
if (result != 0) {
const char* message = ejoc_speaker_renderer_last_error(context->handle);
const std::string text =
"ejoc_speaker_renderer_process failed (" + std::to_string(result) + "): " +
(message != nullptr ? message : "unknown");
if (error != nullptr) {
*error = text;
}
return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, text);
}
return Status::success();
}
} // namespace joc::speaker
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "eac3joc_core.h"
#include "foundation/status.h"
#include "oamd/oamd_parser.h"
#include "speaker/speaker_layout_lookup.h"
namespace joc::speaker {
struct SpeakerStep {
ejoc_speaker_renderer_handle handle = nullptr;
LayoutInfo layout{};
oamd::OamdState state;
std::uint32_t metadata_offset = 1473;
std::vector<float> interleaved;
std::vector<double> output;
std::uint32_t last_block_offset = 0;
std::uint32_t last_ramp_duration = 0;
std::uint32_t last_object_count = 0;
bool last_had_payload = false;
};
Status step(SpeakerStep* context, const std::vector<float>& objects16_planar,
const oamd::OamdUpdate* update, std::string* error);
} // namespace joc::speaker