1 /**
2 * Copyright 2017 Cut Through Recordings
3 * License: MIT License
4 * Author(s): Ethan Reker
5 */
6 module ddsp.util.buffer;
7 
8 import core.stdc.stdlib;
9 
10 /// Just a simple generic circular buffer.  Should fulfill the needs of most
11 /// simple delaying tasks.
12 class Buffer(T)
13 {
14 public:
15 nothrow:
16 @nogc:
17     
18     this(const size_t size)
19     {
20         _maxSize = size;
21         mallocBuffer(_maxSize);
22         _currentSize = _maxSize;
23         _writeIndex = _currentSize - 1;
24         _readIndex = 0;
25     }
26     
27     /// Gets the element from the buffer at the current read index, and
28     /// increments the read index.
29     T read()
30     {
31         T element = _buffer[_readIndex];
32         incrementIndex(_readIndex);
33         return element;
34     }
35     
36     /// Assign the buffer element at the current write index to element and
37     /// increment the write index.
38     void write(const T element)
39     {
40         _buffer[_writeIndex] = element;
41         incrementIndex(_writeIndex);
42     }
43     
44     /// Resize the buffer. If the new size is larger than the max size, the buffer
45     /// will be reallocated so that size is the new maximum size.  It is very
46     /// inefficient to delete and allocate large amounts of memory like this so
47     /// it is recommended to give the buffer an initial max size that will never
48     /// be exceeded.
49     void setSize(const size_t size)
50     {
51         if(size > _maxSize)
52         {
53             _maxSize = size;
54             mallocBuffer(_maxSize);
55             _currentSize = _maxSize;
56         }
57         else
58         {
59             _currentSize = _maxSize;
60         }
61         _writeIndex = _currentSize - 1;
62         _readIndex = 0;
63     }
64     
65 private:
66     /// The size that the buffer is originally set to.
67     size_t _maxSize;
68     
69     /// The size that the buffer is currently set to.
70     size_t _currentSize;
71     
72     /// Array that holds the elements
73     T* _buffer;
74     
75     /// Points to the current sample to be read from
76     size_t _readIndex;
77     
78     /// Points to the current sample to be written to
79     size_t _writeIndex;
80     
81     /// Takes an index and increments it by 1, if it exceeds the size of the buffer
82     /// it will be wrapped around to 0.
83     void incrementIndex(ref size_t index)
84     {
85         if(++index >= _maxSize)
86             index = 0;
87     }
88     
89     void mallocBuffer(const size_t bufferSize)
90     {
91         if(_buffer)
92             free(_buffer);
93             
94         _buffer = cast(T*) malloc(bufferSize * T.sizeof);
95         foreach(element; 0..bufferSize)
96             _buffer[element] = cast(T) 0;
97     }
98 }