libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
audiobuffer.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/audiodesc.h>
15#include <promeki/audiometer.h>
16#include <promeki/buffer.h>
17#include <promeki/deque.h>
18#include <promeki/error.h>
19#include <promeki/result.h>
20#include <promeki/enums.h>
21#include <promeki/list.h>
23#include <promeki/mutex.h>
26#if PROMEKI_ENABLE_SRC
28#endif
29
30PROMEKI_NAMESPACE_BEGIN
31
190class AudioBuffer {
191 public:
193 using PopResult = Result<size_t>;
194
196 AudioBuffer() = default;
197
199 explicit AudioBuffer(const AudioDesc &format);
200
202 AudioBuffer(const AudioDesc &format, size_t capacity);
203
204 AudioBuffer(const AudioBuffer &) = delete;
205 AudioBuffer &operator=(const AudioBuffer &) = delete;
206
208 AudioBuffer(AudioBuffer &&other) noexcept;
209
211 AudioBuffer &operator=(AudioBuffer &&other) noexcept;
212
214 ~AudioBuffer() = default;
215
217 bool isValid() const { return _format.isValid(); }
218
239 AudioDesc format() const {
240 Mutex::Locker lock(_mutex);
241 return _format;
242 }
243
248 void setFormat(const AudioDesc &format);
249
251 const AudioDesc &inputFormat() const { return _inputFormat; }
252
267 void setInputFormat(const AudioDesc &input);
268
281 Error setResamplerQuality(const SrcQuality &quality);
282
308 Error enableDriftCorrection(size_t targetSamples, double gain = 0.001);
309
321 void disableDriftCorrection();
322
328 bool driftCorrectionEnabled() const;
329
339 double driftRatio() const;
340
348 Error reserve(size_t samples);
349
351 size_t capacity() const {
352 Mutex::Locker lock(_mutex);
353 return _capacity;
354 }
355
357 size_t available() const {
358 Mutex::Locker lock(_mutex);
359 return _count;
360 }
361
363 size_t free() const {
364 Mutex::Locker lock(_mutex);
365 return _capacity - _count;
366 }
367
369 bool isEmpty() const {
370 Mutex::Locker lock(_mutex);
371 return _count == 0;
372 }
373
375 bool isFull() const {
376 Mutex::Locker lock(_mutex);
377 return _count >= _capacity;
378 }
379
381 void clear();
382
399 Error setChannelGains(const List<float> &gains);
400
402 List<float> channelGains() const;
403
429 Error setChannelRemap(const List<int> &remap);
430
432 List<int> channelRemap() const;
433
449 void setMeter(AudioMeter::Ptr meter);
450
452 AudioMeter::Ptr meter() const;
453
470 Error push(const void *data, size_t samples, const AudioDesc &srcFormat,
471 const MediaTimeStamp &pts = MediaTimeStamp());
472
500 Error pushSilence(size_t samples, const MediaTimeStamp &pts = MediaTimeStamp());
501
518 PopResult pop(void *dst, size_t samples, MediaTimeStamp *firstSamplePts = nullptr);
519
530 PopResult popWait(void *dst, size_t samples, unsigned int timeoutMs = 0,
531 MediaTimeStamp *firstSamplePts = nullptr);
532
541 PopResult peek(void *dst, size_t samples,
542 MediaTimeStamp *firstSamplePts = nullptr) const;
543
548 PopResult drop(size_t samples);
549
569 Error push(const PcmAudioPayload &payload);
570
598 Result<PcmAudioPayload::Ptr> popPayload(size_t minSamples, size_t maxSamples);
599
618 Result<PcmAudioPayload::Ptr> popWaitPayload(size_t minSamples, size_t maxSamples,
619 unsigned int timeoutMs = 0);
620
626 MediaTimeStamp nextSamplePts() const;
627
640 int64_t resamplerSampleDelta() const;
641
642 private:
644 size_t bytesPerSample() const;
645
647 void writeBytesAtTail(const uint8_t *data, size_t samples);
648
650 void readBytesFromHead(uint8_t *dst, size_t samples, size_t skip) const;
651
652 // Lock-free internals called with _mutex already held.
653 Error pushLocked(const void *data, size_t samples, const AudioDesc &srcFormat,
654 const MediaTimeStamp &pts, size_t &outputSamples);
655 Error pushSilenceLocked(size_t samples);
656 size_t popLocked(void *dst, size_t samples);
657
659 struct Anchor {
660 uint64_t outputIndex = 0;
661 MediaTimeStamp pts;
662 };
663
672 void layAnchorLocked(uint64_t outputIndex, const MediaTimeStamp &pts);
673
679 MediaTimeStamp ptsAtOutputIndexLocked(uint64_t outputIndex) const;
680
686 void pruneAnchorsLocked();
687
688 mutable Mutex _mutex;
689 WaitCondition _cv;
690
691 AudioDesc _format;
692 AudioDesc _inputFormat;
693 Buffer _storage;
694 size_t _capacity = 0;
695 size_t _head = 0;
696 size_t _tail = 0;
697 size_t _count = 0;
698 List<float> _gains;
699 List<int> _remap;
700 AudioMeter::Ptr _meter;
701
702 Deque<Anchor> _anchors;
703 uint64_t _outputProducedTotal = 0;
704 uint64_t _outputConsumedTotal = 0;
705 int64_t _resamplerSampleDelta = 0;
706
708 bool needsFloatProcessing() const { return !_remap.isEmpty() || !_gains.isEmpty() || _meter.isValid(); }
709
710#if PROMEKI_ENABLE_SRC
711 SrcQuality _resamplerQuality;
712 AudioResampler _resampler;
713 bool _driftEnabled = false;
714 size_t _driftTarget = 0;
715 double _driftGain = 0.001;
716 double _driftRatio = 1.0;
717 double _driftIntegral = 0.0;
718
729 Error resampleAndPush(const float *nativeData, size_t samples,
730 size_t &outputSamples, long &inputUsed);
731
733 bool needsResampler(const AudioDesc &srcFormat) const;
734
736 double computeRatio(const AudioDesc &srcFormat);
737#endif
738};
739
740PROMEKI_NAMESPACE_END
741
742#endif // PROMEKI_ENABLE_PROAV