summaryrefslogtreecommitdiffstats
path: root/src/util/readaheadsamplebuffer.h
blob: fbf07688dd87ce482cd1b18d9600dd9cbce9ec65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#pragma once


#include "util/indexrange.h"
#include "util/samplebuffer.h"


namespace mixxx {

// A FIFO sample buffer with fixed capacity and range checking.
//
// Samples are written at the tail and read from the head (FIFO).
// It is intended to consume all buffered samples before writing
// any new samples. A full featured ring buffer is not needed for
// this purpose.
//
// The API is not designed for concurrent readers and writers!
// Samples reserved for writing are immediately available for
// reading, even if the writer has not not yet written any samples.
// With this in mind the implementation does not make any attempts
// to be thread-safe!
class ReadAheadSampleBuffer final {
  public:
    explicit ReadAheadSampleBuffer(
            SINT capacity = 0);
    ReadAheadSampleBuffer(
            const ReadAheadSampleBuffer& that)
        : ReadAheadSampleBuffer(that, that.capacity()) {
    }
    ReadAheadSampleBuffer(
            ReadAheadSampleBuffer&&) = default;

    ReadAheadSampleBuffer& operator=(
            const ReadAheadSampleBuffer& that) {
        *this = ReadAheadSampleBuffer(that); // copy ctor + move assignment
        return *this;
    }
    ReadAheadSampleBuffer& operator=(
            ReadAheadSampleBuffer&& that) {
        swap(that);
        return *this;
    }
    
    void swap(
            ReadAheadSampleBuffer& that);

    // The capacity is limited by the size of the underlying buffer.
    SINT capacity() const {
        return m_sampleBuffer.size();
    }

    // Tries to adjust the capacity taking into account the
    // current contents of the buffer. The resulting capacity
    // may therefore be higher than requested when trying to
    // reduce the current capacity.
    void adjustCapacity(SINT capacity);

    // Discards all buffered samples.
    void clear();

    bool empty() const {
        return m_readableRange.empty();
    }

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

    // The number of samples that could be written instantly without
    // internal reorganization, i.e. the remaining capacity of the
    // buffer.
    // Only the space between the end of the slice occupied by
    // written (= readable) samples and the end of the allocated
    // buffer is available for writing!
    SINT writableLength() const {
        return capacity() - m_readableRange.end();
    }

    // Reserves space for writing samples by growing the readable
    // range at the back towards the end of the underlying buffer.
    //
    // Returns a pointer to the continuous memory region and the
    // actual number of samples that have been reserved as a slice.
    // The maximum length is limited by writableLength() and the
    // returned slice might be shorter than requested.
    //
    // The returned slice is only valid until the next non-const
    // operation on this buffer.
    SampleBuffer::WritableSlice growForWriting(SINT maxWriteLength);

    // Discards the last samples that have been written by shrinking
    // the readable range from the back.
    //
    // Returns the number of samples that have actually been discarded.
    // The number of samples that can be discarded is limited by
    // readableLength() and the returned length might be shorter than
    // requested.
    SINT shrinkAfterWriting(SINT maxShrinkLength);

    // Consumes buffered samples from the front of the readable range
    // thereby shrinking it.
    //
    // Returns a pointer to the continuous memory region and the actual
    // number of readable samples as a slice. The maximum length is
    // limited by readableLength() and the returned slice might be
    // shorter than requested.
    //
    // The returned slice is only valid until the next non-const
    // operation on this buffer.
    SampleBuffer::ReadableSlice shrinkForReading(SINT maxReadLength);

  private:
    ReadAheadSampleBuffer(
            const ReadAheadSampleBuffer& that,
            SINT capacity);

    SampleBuffer m_sampleBuffer;
    IndexRange m_readableRange;
};

} // namespace mixxx

namespace std {
    
// Template specialization of std::swap() for ReadAheadSampleBuffer
template<>
inline void swap(::mixxx::ReadAheadSampleBuffer& lhs, ::mixxx::ReadAheadSampleBuffer& rhs) {
    lhs.swap(rhs);
}

}  // namespace std