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.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
352 bool operator==(const AudioChannelMap &o) const { return _entries == o._entries; }
353 bool operator!=(const AudioChannelMap &o) const { return !(*this == o); }
354
363 Error writeToStream(DataStream &s) const;
364
369 template <uint32_t V> static Result<AudioChannelMap> readFromStream(DataStream &s);
370
371 private:
372 EntryList _entries;
373};
374
375inline Error AudioChannelMap::writeToStream(DataStream &s) const {
376 s << static_cast<uint32_t>(channels());
377 for (const auto &entry : entries()) {
378 s << entry.first().name();
379 s << static_cast<int32_t>(entry.second().value());
380 }
381 return s.status() == DataStream::Ok ? Error::Ok : s.toError();
382}
383
384template <>
385inline Result<AudioChannelMap> AudioChannelMap::readFromStream<1>(DataStream &s) {
386 uint32_t count = 0;
387 s >> count;
388 if (s.status() != DataStream::Ok) return makeError<AudioChannelMap>(s.toError());
389 AudioChannelMap::EntryList entries;
390 entries.reserve(count);
391 for (uint32_t i = 0; i < count; ++i) {
392 String streamName;
393 int32_t roleValue = 0;
394 s >> streamName >> roleValue;
395 AudioStreamDesc stream = (streamName.isEmpty() || streamName == "Undefined")
396 ? AudioStreamDesc()
397 : AudioStreamDesc(streamName);
398 entries.pushToBack(AudioChannelMap::Entry(stream, ChannelRole(roleValue)));
399 }
400 if (s.status() != DataStream::Ok) return makeError<AudioChannelMap>(s.toError());
401 return makeResult(AudioChannelMap(std::move(entries)));
402}
403
404PROMEKI_NAMESPACE_END
405
406PROMEKI_FORMAT_VIA_TOSTRING(promeki::AudioChannelMap);
407
416template <> struct std::hash<promeki::AudioChannelMap> {
417 size_t operator()(const promeki::AudioChannelMap &v) const noexcept {
418 size_t h = 0;
419 for (const auto &entry : v.entries()) {
420 size_t s = std::hash<promeki::AudioStreamDesc>()(entry.first());
421 size_t r = std::hash<promeki::ChannelRole>()(entry.second());
422 size_t combined = s ^ (r + 0x9e3779b97f4a7c15ULL + (s << 6) + (s >> 2));
423 h = h ^ (combined + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2));
424 }
425 return h;
426 }
427};
428
429#endif // PROMEKI_ENABLE_PROAV