Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AudioSource v2 API #1317

Merged
merged 82 commits into from
Nov 25, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
3dad001
Add a class for handling directed index ranges
uklotzde Jul 8, 2017
a942fe3
Rename "chunk" to "slice" for sample buffers
uklotzde Jul 8, 2017
67353de
Use loggers in CachingReader components
uklotzde Jul 8, 2017
f8e5ddc
Introduce AudioSource v2 API
uklotzde Jul 9, 2017
e1b6b07
Migrate SoundSources to the new v2 API
uklotzde Jul 13, 2017
baae34f
Disable failing test for SoundSourceFFmpeg
uklotzde Jul 20, 2017
661691b
Change naming of IndexRange members to avoid misunderstandings
uklotzde Jul 26, 2017
e1bcb82
Rename various member functions in IndexRange
uklotzde Jul 27, 2017
c713d3c
Optimize and test conversion mono -> stereo
uklotzde Jul 29, 2017
7d6c622
Use optimized function to adjust index ranges
uklotzde Aug 2, 2017
a02fa40
Improve versatility and safety of SampleBuffer and its companions
uklotzde Jul 30, 2017
36c51de
Introduce next abstraction level of the AudioSource API
uklotzde Jul 30, 2017
844cf35
Abort reading of sample data if not (yet) available and cached
uklotzde Aug 2, 2017
085ff55
Move common functionality from AudioSource into base class
uklotzde Sep 6, 2017
76215d2
Finalize the new AudioSource v2 API
uklotzde Sep 16, 2017
f32e4ef
Update literals and documentation of OpenResult enum
uklotzde Sep 17, 2017
23be952
Give SoundSources a 2nd chance to open unreadable files
uklotzde Sep 17, 2017
09f0e38
Fix wrong assertion
uklotzde Sep 25, 2017
6d94410
Remove ability to 'skip' from public AudioSource API
uklotzde Oct 4, 2017
a0cdbff
Hide more implementation details from the public AudioSource API
uklotzde Oct 4, 2017
06bbc86
Extract all pure virtual functions into source interfaces
uklotzde Oct 5, 2017
000441f
Consolidate sample buffers classes
uklotzde Oct 17, 2017
a5f4729
Reorder code for parsing track metadata and cover art
uklotzde Oct 17, 2017
e4bd431
Enclose sample buffering classes into namespace 'mixxx'
uklotzde Oct 19, 2017
8d3b5c9
Align and extend APIs for buffering samples
uklotzde Oct 19, 2017
7aebcfe
Replace some include guards with #pragma once
uklotzde Oct 19, 2017
d375111
Fix naming and documentation of sample buffering
uklotzde Oct 19, 2017
1c7fe91
Fix Windows build
uklotzde Oct 20, 2017
7a52da4
Rename IndexRange member functions
uklotzde Oct 20, 2017
4a445a9
More expressive Audio- and MetadataSource interfaces
uklotzde Oct 27, 2017
e323c74
Consistently use "sample rate" instead of "sampling rate"
uklotzde Oct 28, 2017
828c2f2
Use 'Duration' instead of 'double' for track metadata
uklotzde Oct 28, 2017
e2586c9
Reuse audio property types for track metadata
uklotzde Oct 28, 2017
5777283
Add new property classes for storing track metadata
uklotzde Oct 28, 2017
820d086
Use new album/track info classes for storing track metadata
uklotzde Oct 28, 2017
4c4173b
Add tagging for MusicBrainz track and album release identifiers
uklotzde Oct 28, 2017
2daa790
Support both artist/release MusicBrainz identifiers
uklotzde Oct 29, 2017
b382524
Add tagging support for MusicBrainz Release Group identifier
uklotzde Oct 29, 2017
43b4cd9
Simplify parsing of ID3v2 TXXX frames
uklotzde Oct 29, 2017
bd4a2d2
Code cleanup
uklotzde Oct 29, 2017
2b1ecda
Add tagging support for various fields
uklotzde Oct 29, 2017
a51f666
Split AudioSource into reader interface and abstract base class
uklotzde Oct 29, 2017
bc32b72
Fix Windows build
uklotzde Oct 29, 2017
f9a5364
Explicitly initialize const member
uklotzde Oct 29, 2017
dddc728
Fix chromaprint calculations
uklotzde Nov 3, 2017
42184da
Explicitly define the internal number of channels for the engine
uklotzde Nov 3, 2017
0db7619
Programmatic distinction between ChannelLayout and ChannelCount
uklotzde Nov 3, 2017
d72fb9f
Collect track db properties in TrackRecord
uklotzde Nov 3, 2017
f239392
Use TrackRecord in Track object
uklotzde Nov 3, 2017
b1a8328
Shift code from overloaded Track object into TrackRecord
uklotzde Nov 3, 2017
03222e3
Export track metadata only if it has been modified (still disabled)
uklotzde Nov 4, 2017
a02cffd
Prepare next level of metadata synchronization
uklotzde Nov 4, 2017
30a8251
Reorder and optimize code for exporting track metadata
uklotzde Nov 4, 2017
0985786
Add a flag for explicitly requesting to save/export track metadata
uklotzde Nov 4, 2017
10f2f81
Improve code for implicitly exporting/saving track metadata
uklotzde Nov 4, 2017
9bd0c33
Use "import"/"export" for track metadata synchronization
uklotzde Nov 5, 2017
b1d7fb2
More renamings to improve consistency
uklotzde Nov 5, 2017
38e8e21
Remove unneeded file I/O and leave a NOTE
uklotzde Nov 6, 2017
1b4af53
Rename member function (once again)
uklotzde Nov 6, 2017
6faefb5
Delete obsolete comments and warnings
uklotzde Nov 6, 2017
bdef9be
Minor code reorderings
uklotzde Nov 6, 2017
e3bedc5
Merge branch 'master' into audiosourcev2
uklotzde Nov 19, 2017
9420f2a
Merge branch 'master' into tmpv2
uklotzde Nov 19, 2017
51cefc5
Improve API of ReadAheadSampleBuffer
uklotzde Nov 19, 2017
124df54
Improve API and documentation of Readable-/WritableSampleFrames
uklotzde Nov 19, 2017
70b341c
Fix reliable detection of FAAD2 version on Fedora 27 / SCons 2.5.1
uklotzde Nov 19, 2017
a54db81
Fix awkward and fatal confusion between FIFO and LIFO order!!!
uklotzde Nov 19, 2017
19da4ce
Add comment about the remaining capacity of sample buffer
uklotzde Nov 19, 2017
445a48b
Rename parameters
uklotzde Nov 19, 2017
de761e3
Fix detection of FAAD2 version 2.7
uklotzde Nov 19, 2017
b7566c3
Replace readFromTail() with dropFromTail()
uklotzde Nov 20, 2017
a257340
Reorder #include directives
uklotzde Nov 20, 2017
407b7f2
Re-add missing #include directive
uklotzde Nov 20, 2017
9382025
Merge branch 'master' into audiosourcev2
uklotzde Nov 20, 2017
755d55b
Merge branch 'master' into audiosourcev2
uklotzde Nov 23, 2017
ee517e3
Use "length" for both slices and ranges
uklotzde Nov 25, 2017
8822348
Add a utility function to reduce nesting of member function calls
uklotzde Nov 25, 2017
66eaa75
Align function signatures of length() and data()
uklotzde Nov 25, 2017
70e29d5
Clarify how ReadAheadSampleBuffer is intended to be used
uklotzde Nov 25, 2017
665cf61
Rename function: writeToTail() -> growForWriting()
uklotzde Nov 25, 2017
f63e2fa
Rename function: dropFromTail() -> shrinkAfterWriting()
uklotzde Nov 25, 2017
d6765cf
Rename function: readFromHead() -> shrinkForReading()
uklotzde Nov 25, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions plugins/soundsourcem4a/soundsourcem4a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ ReadableSampleFrames SoundSourceM4A::readSampleFramesClamped(
if (!m_sampleBuffer.empty()) {
// Consume previously decoded sample data
const SampleBuffer::ReadableSlice readableSlice(
m_sampleBuffer.readLifo(numberOfSamplesRemaining));
m_sampleBuffer.readFromHead(numberOfSamplesRemaining));
if (writableSampleFrames.writableData()) {
SampleUtil::copy(
writableSampleFrames.writableData(outputSampleOffset),
Expand Down Expand Up @@ -506,7 +506,7 @@ ReadableSampleFrames SoundSourceM4A::readSampleFramesClamped(
const SINT writeToTailCount = math_max(
numberOfSamplesRemaining, decodeBufferCapacityMin);
const SampleBuffer::WritableSlice writableSlice(
m_sampleBuffer.write(writeToTailCount));
m_sampleBuffer.writeToTail(writeToTailCount));
pDecodeBuffer = writableSlice.data();
decodeBufferCapacity = writableSlice.size();
}
Expand Down Expand Up @@ -562,14 +562,14 @@ ReadableSampleFrames SoundSourceM4A::readSampleFramesClamped(
} else {
// Decoded into temporary buffer
DEBUG_ASSERT(numberOfSamplesDecoded <= decodeBufferCapacity);
// Adjust the size of the buffer to the samples that
// Shrink the size of the buffer to the samples that
// have actually been decoded
m_sampleBuffer.readFifo(decodeBufferCapacity - numberOfSamplesDecoded);
m_sampleBuffer.readFromTail(decodeBufferCapacity - numberOfSamplesDecoded);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider to rename this function to shrinkTail or something? The return value is never used.

// Read from the buffer's head
numberOfSamplesRead =
std::min(numberOfSamplesDecoded, numberOfSamplesRemaining);
const SampleBuffer::ReadableSlice readableSlice(
m_sampleBuffer.readLifo(numberOfSamplesRead));
m_sampleBuffer.readFromHead(numberOfSamplesRead));
DEBUG_ASSERT(readableSlice.size() == numberOfSamplesRead);
if (writableSampleFrames.writableData()) {
SampleUtil::copy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ ReadableSampleFrames SoundSourceMediaFoundation::readSampleFramesClamped(
SINT numberOfFramesRemaining = numberOfFramesTotal;
while (numberOfFramesRemaining > 0) {
SampleBuffer::ReadableSlice readableSlice(
m_sampleBuffer.readLifo(
m_sampleBuffer.readFromHead(
frames2samples(numberOfFramesRemaining)));
DEBUG_ASSERT(readableSlice.size()
<= frames2samples(numberOfFramesRemaining));
Expand Down Expand Up @@ -431,7 +431,7 @@ ReadableSampleFrames SoundSourceMediaFoundation::readSampleFramesClamped(
}
// Buffer the remaining samples
SampleBuffer::WritableSlice writableSlice(
m_sampleBuffer.write(lockedSampleBufferCount));
m_sampleBuffer.writeToTail(lockedSampleBufferCount));
// The required capacity has been calculated in advance (see above)
DEBUG_ASSERT(writableSlice.size() == lockedSampleBufferCount);
SampleUtil::copy(
Expand Down
4 changes: 2 additions & 2 deletions src/sources/soundsourceflac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ ReadableSampleFrames SoundSourceFLAC::readSampleFramesClamped(
const SINT numberOfSamplesRead =
std::min(m_sampleBuffer.readableLength(), numberOfSamplesRemaining);
const SampleBuffer::ReadableSlice readableSlice(
m_sampleBuffer.readLifo(numberOfSamplesRead));
m_sampleBuffer.readFromHead(numberOfSamplesRead));
DEBUG_ASSERT(readableSlice.size() == numberOfSamplesRead);
if (writableSampleFrames.writableData()) {
SampleUtil::copy(
Expand Down Expand Up @@ -376,7 +376,7 @@ FLAC__StreamDecoderWriteStatus SoundSourceFLAC::flacWrite(
// Decode buffer should be empty before decoding the next frame
DEBUG_ASSERT(m_sampleBuffer.empty());
const SampleBuffer::WritableSlice writableSlice(
m_sampleBuffer.write(frames2samples(numReadableFrames)));
m_sampleBuffer.writeToTail(frames2samples(numReadableFrames)));

const SINT numWritableFrames = samples2frames(writableSlice.size());
DEBUG_ASSERT(numWritableFrames <= numReadableFrames);
Expand Down
87 changes: 56 additions & 31 deletions src/test/samplebuffertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "test/mixxxtest.h"
#include "util/readaheadsamplebuffer.h"


class ReadAheadSampleBufferTest: public MixxxTest {
public:
ReadAheadSampleBufferTest()
Expand All @@ -15,29 +16,29 @@ class ReadAheadSampleBufferTest: public MixxxTest {
protected:
static const SINT kCapacity;

SINT write(mixxx::ReadAheadSampleBuffer* pSampleBuffer, SINT size) {
SINT writeToTail(mixxx::ReadAheadSampleBuffer* pSampleBuffer, SINT size) {
const mixxx::SampleBuffer::WritableSlice writableSlice(
pSampleBuffer->write(size));
pSampleBuffer->writeToTail(size));
for (SINT i = 0; i < writableSlice.size(); ++i) {
writableSlice[i] = m_writeValue;
m_writeValue += CSAMPLE_ONE;
}
return writableSlice.size();
}

SINT readFifoAndVerify(mixxx::ReadAheadSampleBuffer* pSampleBuffer, SINT size) {
SINT readFromHeadAndVerify(mixxx::ReadAheadSampleBuffer* pSampleBuffer, SINT size) {
const mixxx::SampleBuffer::ReadableSlice readableSlice(
pSampleBuffer->readFifo(size));
pSampleBuffer->readFromHead(size));
for (SINT i = 0; i < readableSlice.size(); ++i) {
EXPECT_EQ(readableSlice[i], m_readValue);
m_readValue += CSAMPLE_ONE;
}
return readableSlice.size();
}

SINT readLifoAndVerify(mixxx::ReadAheadSampleBuffer* pSampleBuffer, SINT size) {
SINT readFromTailAndVerify(mixxx::ReadAheadSampleBuffer* pSampleBuffer, SINT size) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused function.

const mixxx::SampleBuffer::ReadableSlice readableSlice(
pSampleBuffer->readLifo(size));
pSampleBuffer->readFromTail(size));
for (SINT i = readableSlice.size(); i-- > 0; ) {
m_writeValue -= CSAMPLE_ONE;
EXPECT_EQ(readableSlice[i], m_writeValue);
Expand Down Expand Up @@ -66,13 +67,13 @@ TEST_F(ReadAheadSampleBufferTest, emptyWithoutCapacity) {
EXPECT_TRUE(sampleBuffer.empty());

const mixxx::SampleBuffer::WritableSlice writableSlice(
sampleBuffer.write(10));
sampleBuffer.writeToTail(10));
EXPECT_EQ(writableSlice.data(), static_cast<CSAMPLE*>(NULL));
EXPECT_EQ(writableSlice.size(), 0);
EXPECT_TRUE(sampleBuffer.empty());

const mixxx::SampleBuffer::ReadableSlice readableSlice(
sampleBuffer.readLifo(10));
sampleBuffer.readFromTail(10));
EXPECT_EQ(readableSlice.data(), static_cast<const CSAMPLE*>(NULL));
EXPECT_EQ(readableSlice.size(), 0);
EXPECT_TRUE(sampleBuffer.empty());
Expand All @@ -89,79 +90,103 @@ TEST_F(ReadAheadSampleBufferTest, emptyWithCapacity) {
TEST_F(ReadAheadSampleBufferTest, readWriteTrim) {
mixxx::ReadAheadSampleBuffer sampleBuffer(kCapacity);

SINT writeCount1 = write(&sampleBuffer, kCapacity + 10);
EXPECT_EQ(writeCount1, kCapacity); // buffer is full
SINT writeCount1 = writeToTail(&sampleBuffer, kCapacity + 10);
// Buffer is completely filled with samples
EXPECT_EQ(writeCount1, kCapacity);
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity);
EXPECT_EQ(sampleBuffer.writableLength(), 0);

SINT readCount1 = readFifoAndVerify(&sampleBuffer, kCapacity - 10);
SINT readCount1 = readFromHeadAndVerify(&sampleBuffer, kCapacity - 10);
// Buffer contains the remaining 10 samples, but is still full
EXPECT_EQ(readCount1, kCapacity - 10);
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity - readCount1);
EXPECT_EQ(sampleBuffer.writableLength(), 0);

SINT writeCount2 = write(&sampleBuffer, kCapacity);
EXPECT_EQ(writeCount2, 0); // no tail capacity left
SINT writeCount2 = writeToTail(&sampleBuffer, kCapacity);
// Impossible to write more samples
EXPECT_EQ(writeCount2, 0);
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity - readCount1);
EXPECT_EQ(sampleBuffer.writableLength(), 0);

// Trim buffer contents by reallocation
mixxx::ReadAheadSampleBuffer(sampleBuffer).swap(sampleBuffer);

SINT writeCount3 = write(&sampleBuffer, kCapacity);
EXPECT_EQ(writeCount3, readCount1); // buffer has been refilled
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity - readCount1);
EXPECT_EQ(sampleBuffer.writableLength(), readCount1);

SINT readCount2 = readFifoAndVerify(&sampleBuffer, kCapacity - 10);
EXPECT_EQ(readCount2, kCapacity - 10);
// Refill Buffer with samples
SINT writeCount3 = writeToTail(&sampleBuffer, kCapacity);
EXPECT_EQ(writeCount3, readCount1);
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity);
EXPECT_EQ(sampleBuffer.writableLength(), 0);

// Trim buffer contents by reallocation
// Read from the end
SINT readCount2 = readFromTailAndVerify(&sampleBuffer, readCount1);
EXPECT_EQ(readCount2, readCount1);
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity - readCount1);
EXPECT_EQ(sampleBuffer.writableLength(), readCount1);

// Trim buffer contents by reallocation has no effect
mixxx::ReadAheadSampleBuffer(sampleBuffer).swap(sampleBuffer);
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity - readCount1);
EXPECT_EQ(sampleBuffer.writableLength(), readCount1);

SINT writeCount4 = write(&sampleBuffer, kCapacity);
// Refill Buffer with samples
SINT writeCount4 = writeToTail(&sampleBuffer, kCapacity);
EXPECT_EQ(writeCount4, readCount2); // buffer has been refilled
EXPECT_FALSE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), kCapacity);
EXPECT_EQ(sampleBuffer.writableLength(), 0);

SINT readCount3 = readFifoAndVerify(&sampleBuffer, kCapacity + 10);
EXPECT_EQ(readCount3, kCapacity); // whole buffer has been read
// Read whole buffer
SINT readCount3 = readFromTailAndVerify(&sampleBuffer, kCapacity + 10);
EXPECT_EQ(readCount3, kCapacity);
EXPECT_TRUE(sampleBuffer.empty());
EXPECT_EQ(sampleBuffer.readableLength(), 0);
EXPECT_EQ(sampleBuffer.writableLength(), kCapacity);
}

TEST_F(ReadAheadSampleBufferTest, shrink) {
mixxx::ReadAheadSampleBuffer sampleBuffer(kCapacity);

SINT writeCount1 = write(&sampleBuffer, kCapacity - 10);
SINT writeCount1 = writeToTail(&sampleBuffer, kCapacity - 10);
EXPECT_EQ(writeCount1, kCapacity - 10);
EXPECT_FALSE(sampleBuffer.empty());
SINT shrinkCount1 = readLifoAndVerify(&sampleBuffer, 10);
SINT shrinkCount1 = readFromHeadAndVerify(&sampleBuffer, 10);
EXPECT_EQ(shrinkCount1, 10);
SINT readCount1 = readFifoAndVerify(&sampleBuffer, 10);
SINT readCount1 = readFromTailAndVerify(&sampleBuffer, 10);
EXPECT_EQ(readCount1, 10);
EXPECT_FALSE(sampleBuffer.empty());
SINT readCount2 = readFifoAndVerify(&sampleBuffer, kCapacity - 40);
SINT readCount2 = readFromTailAndVerify(&sampleBuffer, kCapacity - 40);
EXPECT_EQ(readCount2, kCapacity - 40);
EXPECT_FALSE(sampleBuffer.empty());
SINT readCount3 = readFifoAndVerify(&sampleBuffer, 20);
SINT readCount3 = readFromTailAndVerify(&sampleBuffer, 20);
EXPECT_EQ(readCount3, 10);
EXPECT_TRUE(sampleBuffer.empty());

SINT writeCount2 = write(&sampleBuffer, 20);
SINT writeCount2 = writeToTail(&sampleBuffer, 20);
EXPECT_EQ(writeCount2, 20);
EXPECT_FALSE(sampleBuffer.empty());
SINT shrinkCount2 = readLifoAndVerify(&sampleBuffer, 21);
SINT shrinkCount2 = readFromHeadAndVerify(&sampleBuffer, 21);
EXPECT_EQ(shrinkCount2, 20);
EXPECT_TRUE(sampleBuffer.empty());
}

TEST_F(ReadAheadSampleBufferTest, clear) {
mixxx::ReadAheadSampleBuffer sampleBuffer(kCapacity);

SINT writeCount = write(&sampleBuffer, 10);
SINT writeCount = writeToTail(&sampleBuffer, 10);
EXPECT_EQ(writeCount, 10);
EXPECT_FALSE(sampleBuffer.empty());
clear(&sampleBuffer);
EXPECT_TRUE(sampleBuffer.empty());
SINT readCount = readFifoAndVerify(&sampleBuffer, 10);
SINT readCount = readFromTailAndVerify(&sampleBuffer, 10);
EXPECT_EQ(readCount, 0);
EXPECT_TRUE(sampleBuffer.empty());
}
10 changes: 5 additions & 5 deletions src/util/readaheadsamplebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ void ReadAheadSampleBuffer::clear() {
void ReadAheadSampleBuffer::adjustCapacity(SINT capacity) {
DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer;

SINT newCapacity = std::min(readableLength(), capacity);
if (newCapacity != capacity) {
SINT newCapacity = math_max(readableLength(), capacity);
if (newCapacity != this->capacity()) {
ReadAheadSampleBuffer tmp(*this, newCapacity);
swap(tmp);
}

DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer;
}

SampleBuffer::WritableSlice ReadAheadSampleBuffer::write(SINT writeLength) {
SampleBuffer::WritableSlice ReadAheadSampleBuffer::writeToTail(SINT writeLength) {
DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer;

const SINT tailLength = math_min(writeLength, writableLength());
Expand All @@ -74,7 +74,7 @@ SampleBuffer::WritableSlice ReadAheadSampleBuffer::write(SINT writeLength) {
return tailSlice;
}

SampleBuffer::ReadableSlice ReadAheadSampleBuffer::readFifo(SINT readLength) {
SampleBuffer::ReadableSlice ReadAheadSampleBuffer::readFromTail(SINT readLength) {
DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer;

const SINT tailLength = math_min(readLength, readableLength());
Expand All @@ -91,7 +91,7 @@ SampleBuffer::ReadableSlice ReadAheadSampleBuffer::readFifo(SINT readLength) {
return tailSlice;
}

SampleBuffer::ReadableSlice ReadAheadSampleBuffer::readLifo(SINT readLength) {
SampleBuffer::ReadableSlice ReadAheadSampleBuffer::readFromHead(SINT readLength) {
DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer;

const SINT headLength = math_min(readLength, readableLength());
Expand Down
24 changes: 13 additions & 11 deletions src/util/readaheadsamplebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
namespace mixxx {

// A FIFO/LIFO sample buffer with fixed capacity and range checking.
// It works best when consuming all buffered samples before writing
// any new samples.
//
// Samples are written at the tail and read from the head (FIFO) or
// from the tail (LIFO). It is intended to consume all buffered samples
// before writing any new samples.
//
// This class is not thread-safe and is not intended to be used from
// multiple threads!
Expand Down Expand Up @@ -63,37 +65,37 @@ class ReadAheadSampleBuffer final {
return capacity() - m_readableRange.end();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_readableRange start always at 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. I added an additional comment that tries to clarify how the buffering internally works. Because it is not a full-featured ring buffer the full capacity only becomes available again after all written samples have been consumed. But that's sufficient for our use case.

}

// Reserves space at the buffer's back end for writing samples.
// Reserves space at the buffer's tail for writing samples.
//
// Returns a pointer to the continuous memory region and the
// actual number of samples that have been reserved. The maximum
// length is limited by writableLength().
//
// The returned pointer is valid until the next write() operation.
SampleBuffer::WritableSlice write(SINT writeLength);
// The returned pointer is valid until the next writeToTail() operation.
SampleBuffer::WritableSlice writeToTail(SINT writeLength);

// The number of readable samples.
SINT readableLength() const {
return m_readableRange.length();
}

// Consumes buffered samples in FIFO order.
// Consumes buffered samples from the head of the buffer.
//
// Returns a pointer to the continuous memory region and the actual
// number of readable samples. The maximum length is limited by
// readableLength().
//
// The returned pointer is valid until the next write() operation.
SampleBuffer::ReadableSlice readFifo(SINT readLength);
// The returned pointer is valid until the next writeToTail() operation.
SampleBuffer::ReadableSlice readFromHead(SINT readLength);

// Consumes buffered samples in LIFO order.
// Consumes buffered samples from the tail of the buffer
//
// Returns a pointer to the continuous memory region and the actual
// number of readable samples. The maximum length is limited by
// readableLength().
//
// The returned pointer is valid until the next write() operation.
SampleBuffer::ReadableSlice readLifo(SINT readLength);
// The returned pointer is valid until the next writeToTail() operation.
SampleBuffer::ReadableSlice readFromTail(SINT readLength);

private:
ReadAheadSampleBuffer(
Expand Down