#include "util/readaheadsamplebuffer.h" #include "util/sample.h" #define DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer \ DEBUG_ASSERT(m_readableRange.orientation() != IndexRange::Orientation::Backward); \ DEBUG_ASSERT(0 <= m_readableRange.start()); \ DEBUG_ASSERT(m_readableRange.end() <= m_sampleBuffer.size()); \ DEBUG_ASSERT(!empty() || (0 == m_readableRange.start())); \ DEBUG_ASSERT(!empty() || (0 == m_readableRange.end())) namespace mixxx { ReadAheadSampleBuffer::ReadAheadSampleBuffer( SINT capacity) : m_sampleBuffer(capacity), m_readableRange(IndexRange::between(0, 0)) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; } ReadAheadSampleBuffer::ReadAheadSampleBuffer( const ReadAheadSampleBuffer& that, SINT capacity) : ReadAheadSampleBuffer(capacity) { DEBUG_ASSERT(that.readableLength() <= capacity); // Copy all readable contents to the beginning of the buffer // for maximizing the writable capacity. SampleUtil::copy( m_sampleBuffer.data(), that.m_sampleBuffer.data(that.m_readableRange.start()), that.readableLength()); m_readableRange.growBack(that.readableLength()); DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; } void ReadAheadSampleBuffer::swap(ReadAheadSampleBuffer& that) { m_sampleBuffer.swap(that.m_sampleBuffer); std::swap(m_readableRange, that.m_readableRange); } void ReadAheadSampleBuffer::clear() { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; m_readableRange = IndexRange::between(0, 0); DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; } void ReadAheadSampleBuffer::adjustCapacity(SINT capacity) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; SINT newCapacity = math_max(readableLength(), capacity); if (newCapacity != this->capacity()) { ReadAheadSampleBuffer tmp(*this, newCapacity); swap(tmp); } DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; } SampleBuffer::WritableSlice ReadAheadSampleBuffer::growForWriting(SINT maxWriteLength) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; const SINT tailLength = math_min(maxWriteLength, writableLength()); const SampleBuffer::WritableSlice tailSlice( m_sampleBuffer, m_readableRange.end(), tailLength); m_readableRange.growBack(tailLength); DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; return tailSlice; } SINT ReadAheadSampleBuffer::shrinkAfterWriting(SINT maxShrinkLength) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; const SINT shrinkLength = math_min(maxShrinkLength, readableLength()); m_readableRange.shrinkBack(shrinkLength); // If the buffer has become empty reset the write head back to the start // of the available memory if (m_readableRange.empty()) { m_readableRange = IndexRange::between(0, 0); } DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; return shrinkLength; } SampleBuffer::ReadableSlice ReadAheadSampleBuffer::shrinkForReading(SINT maxReadLength) { DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; const SINT headLength = math_min(maxReadLength, readableLength()); const SampleBuffer::ReadableSlice headSlice( m_sampleBuffer, m_readableRange.start(), headLength); m_readableRange.shrinkFront(headLength); // If the buffer has become empty reset the write head back to the start // of the available memory if (m_readableRange.empty()) { m_readableRange = IndexRange::between(0, 0); } DEBUG_ASSERT_CLASS_INVARIANT_ReadAheadSampleBuffer; return headSlice; } } // namespace mixxx