libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
audiochannelmap.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
13#include <promeki/namespace.h>
14#include <promeki/list.h>
15#include <promeki/pair.h>
16#include <promeki/sharedptr.h>
17#include <promeki/string.h>
18#include <promeki/result.h>
19#include <promeki/error.h>
20#include <promeki/datastream.h>
21#include <promeki/enums_audio.h>
23
24PROMEKI_NAMESPACE_BEGIN
25
83class AudioChannelMap {
84 PROMEKI_SHARED_FINAL(AudioChannelMap)
85 public:
86 PROMEKI_DATATYPE(AudioChannelMap, DataTypeAudioChannelMap, 1)
87
88
89 using Entry = Pair<AudioStreamDesc, ChannelRole>;
90
92 using EntryList = ::promeki::List<Entry>;
93
95 using List = ::promeki::List<AudioChannelMap>;
96
98 using Ptr = SharedPtr<AudioChannelMap>;
99
101 using PtrList = ::promeki::List<Ptr>;
102
104 using ChannelRoleList = ::promeki::List<ChannelRole>;
105
117 struct WellKnownLayout {
118 String name;
119 ChannelRoleList roles;
120 };
121
123 using WellKnownLayoutList = ::promeki::List<WellKnownLayout>;
124
126 static WellKnownLayoutList wellKnownLayouts();
127
150 static Result<AudioChannelMap> fromString(const String &str);
151
185 static AudioChannelMap defaultForChannels(size_t channels);
186
195 static AudioChannelMap defaultForChannels(size_t channels, const AudioStreamDesc &stream);
196
198 AudioChannelMap() = default;
199
204 explicit AudioChannelMap(ChannelRoleList roles) {
205 _entries.reserve(roles.size());
206 for (const ChannelRole &r : roles) _entries.pushToBack(Entry(AudioStreamDesc(), r));
207 }
208
213 AudioChannelMap(std::initializer_list<ChannelRole> roles) {
214 _entries.reserve(roles.size());
215 for (const ChannelRole &r : roles) _entries.pushToBack(Entry(AudioStreamDesc(), r));
216 }
217
223 AudioChannelMap(const AudioStreamDesc &stream, ChannelRoleList roles) {
224 _entries.reserve(roles.size());
225 for (const ChannelRole &r : roles) _entries.pushToBack(Entry(stream, r));
226 }
227
231 AudioChannelMap(const AudioStreamDesc &stream, std::initializer_list<ChannelRole> roles) {
232 _entries.reserve(roles.size());
233 for (const ChannelRole &r : roles) _entries.pushToBack(Entry(stream, r));
234 }
235
244 explicit AudioChannelMap(EntryList entries) : _entries(std::move(entries)) {}
245
247 AudioChannelMap(std::initializer_list<Entry> entries) : _entries(entries) {}
248
250 bool isValid() const { return !_entries.isEmpty(); }
251
253 size_t channels() const { return _entries.size(); }
254
256 const EntryList &entries() const { return _entries; }
257
259 ChannelRole role(size_t index) const {
260 if (index >= _entries.size()) return ChannelRole::Unused;
261 return _entries[index].second();
262 }
263
265 AudioStreamDesc stream(size_t index) const {
266 if (index >= _entries.size()) return AudioStreamDesc();
267 return _entries[index].first();
268 }
269
271 Entry entry(size_t index) const {
272 if (index >= _entries.size()) return Entry(AudioStreamDesc(), ChannelRole::Unused);
273 return _entries[index];
274 }
275
282 void setRole(size_t index, const ChannelRole &role);
283
290 void setStream(size_t index, const AudioStreamDesc &stream);
291
293 void setEntry(size_t index, const AudioStreamDesc &stream, const ChannelRole &role);
294
300 int indexOf(const ChannelRole &role) const;
301
306 int indexOf(const AudioStreamDesc &stream, const ChannelRole &role) const;
307
309 bool contains(const ChannelRole &role) const { return indexOf(role) >= 0; }
310
318 bool isSingleStream() const;
319
326 AudioStreamDesc commonStream() const;
327
337 String wellKnownName() const;
338
340 bool isWellKnown() const { return !wellKnownName().isEmpty(); }
341
349 String toString() const;
350
397 String toSt2110ChannelOrder() const;
398
442 static Result<AudioChannelMap> fromSt2110ChannelOrder(const String &value);
443
445 bool operator==(const AudioChannelMap &o) const { return _entries == o._entries; }
446 bool operator!=(const AudioChannelMap &o) const { return !(*this == o); }
447
456 Error writeToStream(DataStream &s) const;
457
462 template <uint32_t V> static Result<AudioChannelMap> readFromStream(DataStream &s);
463
464 private:
465 EntryList _entries;
466};
467
468inline Error AudioChannelMap::writeToStream(DataStream &s) const {
469 s << static_cast<uint32_t>(channels());
470 for (const auto &entry : entries()) {
471 s << entry.first().name();
472 s << static_cast<int32_t>(entry.second().value());
473 }
474 return s.status() == DataStream::Ok ? Error::Ok : s.toError();
475}
476
477template <>
478inline Result<AudioChannelMap> AudioChannelMap::readFromStream<1>(DataStream &s) {
479 uint32_t count = 0;
480 s >> count;
481 if (s.status() != DataStream::Ok) return makeError<AudioChannelMap>(s.toError());
482 AudioChannelMap::EntryList entries;
483 entries.reserve(count);
484 for (uint32_t i = 0; i < count; ++i) {
485 String streamName;
486 int32_t roleValue = 0;
487 s >> streamName >> roleValue;
488 AudioStreamDesc stream = (streamName.isEmpty() || streamName == "Undefined")
489 ? AudioStreamDesc()
490 : AudioStreamDesc(streamName);
491 entries.pushToBack(AudioChannelMap::Entry(stream, ChannelRole(roleValue)));
492 }
493 if (s.status() != DataStream::Ok) return makeError<AudioChannelMap>(s.toError());
494 return makeResult(AudioChannelMap(std::move(entries)));
495}
496
497PROMEKI_NAMESPACE_END
498
499PROMEKI_FORMAT_VIA_TOSTRING(promeki::AudioChannelMap);
500
509template <> struct std::hash<promeki::AudioChannelMap> {
510 size_t operator()(const promeki::AudioChannelMap &v) const noexcept {
511 size_t h = 0;
512 for (const auto &entry : v.entries()) {
513 size_t s = std::hash<promeki::AudioStreamDesc>()(entry.first());
514 size_t r = std::hash<promeki::ChannelRole>()(entry.second());
515 size_t combined = s ^ (r + 0x9e3779b97f4a7c15ULL + (s << 6) + (s >> 2));
516 h = h ^ (combined + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2));
517 }
518 return h;
519 }
520};
521
522#endif // PROMEKI_ENABLE_PROAV