11#include <promeki/config.h>
12#if PROMEKI_ENABLE_PROAV
21PROMEKI_NAMESPACE_BEGIN
23class SdpMediaDescription;
50 PROMEKI_SHARED_FINAL(AudioDesc)
53 using Ptr = SharedPtr<AudioDesc>;
56 using List = ::promeki::List<AudioDesc>;
59 using PtrList = ::promeki::List<Ptr>;
70 static AudioDesc fromJson(
const JsonObject &json, Error *err =
nullptr);
90 static AudioDesc fromSdp(
const SdpMediaDescription &md);
93 AudioDesc() =
default;
106 AudioDesc(
float sr,
unsigned int ch)
107 : _format(AudioFormat::NativeFloat), _sampleRate(sr), _channels(ch),
108 _channelMap(AudioChannelMap::defaultForChannels(ch)) {
109 if (!validParams()) reset();
123 AudioDesc(
const AudioFormat &fmt,
float sr,
unsigned int ch)
124 : _format(fmt), _sampleRate(sr), _channels(ch),
125 _channelMap(AudioChannelMap::defaultForChannels(ch)) {
126 if (!validParams()) reset();
139 AudioDesc(
const AudioFormat &fmt,
float sr, AudioChannelMap map)
140 : _format(fmt), _sampleRate(sr), _channels(static_cast<unsigned int>(map.channels())),
141 _channelMap(std::move(map)) {
142 if (!validParams()) reset();
162 SdpMediaDescription toSdp(uint8_t payloadType)
const;
169 bool formatEquals(
const AudioDesc &other)
const {
170 return _format == other._format && _sampleRate == other._sampleRate &&
171 _channels == other._channels && _channelMap == other._channelMap;
179 bool operator==(
const AudioDesc &other)
const {
180 return formatEquals(other) && _metadata == other._metadata;
184 bool isValid()
const {
return _format.isValid() && _sampleRate > 0.0f && _channels > 0; }
187 bool isCompressed()
const {
return _format.isCompressed(); }
193 bool isNative()
const {
return _format.id() == AudioFormat::NativeFloat; }
200 AudioDesc workingDesc()
const {
201 return AudioDesc(AudioFormat(AudioFormat::NativeFloat), _sampleRate, _channels);
205 String toString()
const {
206 return String::sprintf(
"[%s %fHz %uc]", _format.name().cstr(), _sampleRate, _channels);
217 JsonObject toJson()
const {
219 ret.set(
"Format", _format.name());
220 ret.set(
"SampleRate", _sampleRate);
221 ret.set(
"Channels", _channels);
224 if (_channelMap != AudioChannelMap::defaultForChannels(_channels)) {
225 ret.set(
"ChannelMap", _channelMap.toString());
227 if (!_metadata.isEmpty()) ret.set(
"Metadata", _metadata.toJson());
232 const AudioFormat &format()
const {
return _format; }
235 void setFormat(
const AudioFormat &val) { _format = val; }
238 float sampleRate()
const {
return _sampleRate; }
241 void setSampleRate(
float val) { _sampleRate = val; }
244 unsigned int channels()
const {
return _channels; }
253 void setChannels(
unsigned int val) {
255 _channelMap = AudioChannelMap::defaultForChannels(val);
259 const AudioChannelMap &channelMap()
const {
return _channelMap; }
269 void setChannelMap(
const AudioChannelMap &map) {
270 if (map.channels() == _channels) _channelMap = map;
274 const Metadata &metadata()
const {
return _metadata; }
277 Metadata &metadata() {
return _metadata; }
280 size_t bytesPerSample()
const {
return _format.bytesPerSample(); }
290 size_t bytesPerSampleStride()
const {
291 return _format.isPlanar() ? _format.bytesPerSample() : _format.bytesPerSample() * _channels;
305 size_t channelBufferOffset(
unsigned int chan,
size_t bufferSamples)
const {
306 return _format.isPlanar() ? _format.bytesPerSample() * bufferSamples * chan
307 : _format.bytesPerSample() * chan;
315 size_t bufferSize(
size_t samples)
const {
return _format.bytesPerSample() * _channels * samples; }
323 void samplesToFloat(
float *out,
const uint8_t *in,
size_t samples)
const {
324 _format.samplesToFloat(out, in, samples * _channels);
333 void floatToSamples(uint8_t *out,
const float *in,
size_t samples)
const {
334 _format.floatToSamples(out, in, samples * _channels);
339 float _sampleRate = 0.0f;
340 unsigned int _channels = 0;
341 AudioChannelMap _channelMap;
344 bool validParams()
const {
return _format.isValid() && _sampleRate > 0.0f && _channels > 0; }
347 _format = AudioFormat();
350 _channelMap = AudioChannelMap();
357inline DataStream &operator<<(DataStream &stream,
const AudioDesc &desc) {
358 stream.beginFrame(DataTypeAudioDesc, 1);
359 stream << desc.format();
360 stream << desc.sampleRate();
361 stream << static_cast<uint32_t>(desc.channels());
362 stream << desc.channelMap();
363 stream << desc.metadata();
371inline DataStream &operator>>(DataStream &stream, AudioDesc &desc) {
372 if (!stream.readFrame(DataTypeAudioDesc)) {
381 stream >> fmt >> sr >> ch >> map >> meta;
382 if (stream.status() != DataStream::Ok) {
386 desc = AudioDesc(fmt, sr, ch);
389 if (map.channels() == ch) desc.setChannelMap(map);
390 desc.metadata() = std::move(meta);
396PROMEKI_FORMAT_VIA_TOSTRING(promeki::AudioDesc);