12 #ifndef hifi_AudioRingBuffer_h
13 #define hifi_AudioRingBuffer_h
15 #include "AudioConstants.h"
17 #include <QtCore/QIODevice>
19 #include <SharedUtil.h>
22 const int DEFAULT_RING_BUFFER_FRAME_CAPACITY = 10;
25 class AudioRingBufferTemplate {
27 static const int SampleSize =
sizeof(Sample);
30 AudioRingBufferTemplate(
int numFrameSamples,
int numFramesCapacity = DEFAULT_RING_BUFFER_FRAME_CAPACITY);
31 ~AudioRingBufferTemplate();
34 AudioRingBufferTemplate(
const AudioRingBufferTemplate&) =
delete;
35 AudioRingBufferTemplate(AudioRingBufferTemplate&&) =
delete;
36 AudioRingBufferTemplate& operator=(
const AudioRingBufferTemplate&) =
delete;
46 void resizeForFrameSize(
int numFrameSamples);
56 int readSamples(Sample* destination,
int maxSamples);
61 int appendSamples(Sample* destination,
int maxSamples,
bool append =
true);
64 void skipSamples(
int maxSamples) { shiftReadPosition(std::min(maxSamples, samplesAvailable())); }
68 int writeSamples(
const Sample* source,
int maxSamples);
73 int addSilentSamples(
int maxSamples);
77 int readData(
char* destination,
int maxSize);
81 int appendData(
char* destination,
int maxSize);
85 int writeData(
const char* source,
int maxSize);
88 Sample& operator[](
const int index) {
return *shiftedPositionAccomodatingWrap(_nextOutput, index); }
89 const Sample& operator[] (
const int index)
const {
return *shiftedPositionAccomodatingWrap(_nextOutput, index); }
94 void shiftReadPosition(
unsigned int numSamples) { _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples); }
96 int samplesAvailable()
const;
97 int framesAvailable()
const {
return (_numFrameSamples == 0) ? 0 : samplesAvailable() / _numFrameSamples; }
98 float getNextOutputFrameLoudness()
const {
return getFrameLoudness(_nextOutput); }
101 int getNumFrameSamples()
const {
return _numFrameSamples; }
102 int getFrameCapacity()
const {
return _frameCapacity; }
103 int getSampleCapacity()
const {
return _sampleCapacity; }
105 int getOverflowCount()
const {
return _overflowCount; }
107 class ConstIterator {
114 ConstIterator(Sample* bufferFirst,
int capacity, Sample* at) :
115 _bufferLength(capacity),
116 _bufferFirst(bufferFirst),
117 _bufferLast(bufferFirst + capacity - 1),
119 ConstIterator(
const ConstIterator& rhs) =
default;
121 bool isNull()
const {
return _at == NULL; }
123 bool operator==(
const ConstIterator& rhs) {
return _at == rhs._at; }
124 bool operator!=(
const ConstIterator& rhs) {
return _at != rhs._at; }
125 const Sample& operator*() {
return *_at; }
127 ConstIterator& operator=(
const ConstIterator& rhs) {
128 _bufferLength = rhs._bufferLength;
129 _bufferFirst = rhs._bufferFirst;
130 _bufferLast = rhs._bufferLast;
134 ConstIterator& operator++() {
135 _at = (_at == _bufferLast) ? _bufferFirst : _at + 1;
138 ConstIterator operator++(
int) {
139 ConstIterator tmp(*
this);
143 ConstIterator& operator--() {
144 _at = (_at == _bufferFirst) ? _bufferLast : _at - 1;
147 ConstIterator operator--(
int) {
148 ConstIterator tmp(*
this);
152 const Sample& operator[] (
int i) {
153 return *atShiftedBy(i);
155 ConstIterator operator+(
int i) {
156 return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i));
158 ConstIterator operator-(
int i) {
159 return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i));
162 void readSamples(Sample* dest,
int numSamples) {
163 auto samplesToEnd = _bufferLast - _at + 1;
165 if (samplesToEnd >= numSamples) {
166 memcpy(dest, _at, numSamples * SampleSize);
169 auto samplesFromStart = numSamples - samplesToEnd;
170 memcpy(dest, _at, samplesToEnd * SampleSize);
171 memcpy(dest + samplesToEnd, _bufferFirst, samplesFromStart * SampleSize);
173 _at = _bufferFirst + samplesFromStart;
176 void readSamplesWithFade(Sample* dest,
int numSamples,
float fade) {
178 for (
int i = 0; i < numSamples; i++) {
179 *dest = (float)*at * fade;
181 at = (at == _bufferLast) ? _bufferFirst : at + 1;
187 Sample* atShiftedBy(
int i) {
188 i = (_at - _bufferFirst + i) % _bufferLength;
192 return _bufferFirst + i;
196 Sample* _bufferFirst;
201 ConstIterator nextOutput()
const {
202 return ConstIterator(_buffer, _bufferLength, _nextOutput);
204 ConstIterator lastFrameWritten()
const {
205 return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples;
208 int writeSamples(ConstIterator source,
int maxSamples);
209 int writeSamplesWithFade(ConstIterator source,
int maxSamples,
float fade);
211 float getFrameLoudness(ConstIterator frameStart)
const;
214 Sample* shiftedPositionAccomodatingWrap(Sample* position,
int numSamplesShift)
const;
215 float getFrameLoudness(
const Sample* frameStart)
const;
217 int _numFrameSamples;
221 int _overflowCount{ 0 };
223 Sample* _nextOutput{
nullptr };
224 Sample* _endOfLastWrite{
nullptr };
225 Sample* _buffer{
nullptr };
229 using AudioRingBuffer = AudioRingBufferTemplate<int16_t>;
230 using AudioMixRingBuffer = AudioRingBufferTemplate<float>;