1
////////////////////////////////////////////////////////////////////////////////
3
/// A buffer class for temporarily storaging sound samples, operates as a
4
/// first-in-first-out pipe.
6
/// Samples are added to the end of the sample buffer with the 'putSamples'
7
/// function, and are received from the beginning of the buffer by calling
8
/// the 'receiveSamples' function. The class automatically removes the
9
/// outputted samples from the buffer, as well as grows the buffer size
10
/// whenever necessary.
12
/// Author : Copyright (c) Olli Parviainen
13
/// Author e-mail : oparviai 'at' iki.fi
14
/// SoundTouch WWW: http://www.surina.net/soundtouch
16
////////////////////////////////////////////////////////////////////////////////
18
// Last changed : $Date: 2009-02-27 19:24:42 +0200 (Fri, 27 Feb 2009) $
19
// File revision : $Revision: 4 $
21
// $Id: FIFOSampleBuffer.cpp 68 2009-02-27 17:24:42Z oparviai $
23
////////////////////////////////////////////////////////////////////////////////
27
// SoundTouch audio processing library
28
// Copyright (c) Olli Parviainen
30
// This library is free software; you can redistribute it and/or
31
// modify it under the terms of the GNU Lesser General Public
32
// License as published by the Free Software Foundation; either
33
// version 2.1 of the License, or (at your option) any later version.
35
// This library is distributed in the hope that it will be useful,
36
// but WITHOUT ANY WARRANTY; without even the implied warranty of
37
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38
// Lesser General Public License for more details.
40
// You should have received a copy of the GNU Lesser General Public
41
// License along with this library; if not, write to the Free Software
42
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44
////////////////////////////////////////////////////////////////////////////////
52
#include "FIFOSampleBuffer.h"
54
using namespace soundtouch;
57
FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
59
assert(numChannels > 0);
60
sizeInBytes = 0; // reasonable initial value
62
bufferUnaligned = NULL;
65
channels = (uint)numChannels;
66
ensureCapacity(32); // allocate initial capacity
71
FIFOSampleBuffer::~FIFOSampleBuffer()
73
delete[] bufferUnaligned;
74
bufferUnaligned = NULL;
79
// Sets number of channels, 1 = mono, 2 = stereo
80
void FIFOSampleBuffer::setChannels(int numChannels)
84
assert(numChannels > 0);
85
usedBytes = channels * samplesInBuffer;
86
channels = (uint)numChannels;
87
samplesInBuffer = usedBytes / channels;
91
// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
92
// zeroes this pointer by copying samples from the 'bufferPos' pointer
93
// location on to the beginning of the buffer.
94
void FIFOSampleBuffer::rewind()
96
if (buffer && bufferPos)
98
memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
104
// Adds 'numSamples' pcs of samples from the 'samples' memory position to
105
// the sample buffer.
106
void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
108
memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
109
samplesInBuffer += nSamples;
113
// Increases the number of samples in the buffer without copying any actual
116
// This function is used to update the number of samples in the sample buffer
117
// when accessing the buffer directly with 'ptrEnd' function. Please be
119
void FIFOSampleBuffer::putSamples(uint nSamples)
123
req = samplesInBuffer + nSamples;
125
samplesInBuffer += nSamples;
129
// Returns a pointer to the end of the used part of the sample buffer (i.e.
130
// where the new samples are to be inserted). This function may be used for
131
// inserting new samples into the sample buffer directly. Please be careful!
133
// Parameter 'slackCapacity' tells the function how much free capacity (in
134
// terms of samples) there _at least_ should be, in order to the caller to
135
// succesfully insert all the required samples to the buffer. When necessary,
136
// the function grows the buffer size to comply with this requirement.
138
// When using this function as means for inserting new samples, also remember
139
// to increase the sample count afterwards, by calling the
140
// 'putSamples(numSamples)' function.
141
SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
143
ensureCapacity(samplesInBuffer + slackCapacity);
144
return buffer + samplesInBuffer * channels;
148
// Returns a pointer to the beginning of the currently non-outputted samples.
149
// This function is provided for accessing the output samples directly.
150
// Please be careful!
152
// When using this function to output samples, also remember to 'remove' the
153
// outputted samples from the buffer by calling the
154
// 'receiveSamples(numSamples)' function
155
SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
158
return buffer + bufferPos * channels;
162
// Ensures that the buffer has enought capacity, i.e. space for _at least_
163
// 'capacityRequirement' number of samples. The buffer is grown in steps of
164
// 4 kilobytes to eliminate the need for frequently growing up the buffer,
165
// as well as to round the buffer size up to the virtual memory page size.
166
void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
168
SAMPLETYPE *tempUnaligned, *temp;
170
if (capacityRequirement > getCapacity())
172
// enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
173
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
174
assert(sizeInBytes % 2 == 0);
175
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
176
if (tempUnaligned == NULL)
178
throw std::runtime_error("Couldn't allocate memory!\n");
180
// Align the buffer to begin at 16byte cache line boundary for optimal performance
181
temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16);
184
memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
186
delete[] bufferUnaligned;
188
bufferUnaligned = tempUnaligned;
193
// simply rewind the buffer (if necessary)
199
// Returns the current buffer capacity in terms of samples
200
uint FIFOSampleBuffer::getCapacity() const
202
return sizeInBytes / (channels * sizeof(SAMPLETYPE));
206
// Returns the number of samples currently in the buffer
207
uint FIFOSampleBuffer::numSamples() const
209
return samplesInBuffer;
213
// Output samples from beginning of the sample buffer. Copies demanded number
214
// of samples to output and removes them from the sample buffer. If there
215
// are less than 'numsample' samples in the buffer, returns all available.
217
// Returns number of samples copied.
218
uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
222
num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
224
memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
225
return receiveSamples(num);
229
// Removes samples from the beginning of the sample buffer without copying them
230
// anywhere. Used to reduce the number of samples in the buffer, when accessing
231
// the sample buffer with the 'ptrBegin' function.
232
uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
234
if (maxSamples >= samplesInBuffer)
238
temp = samplesInBuffer;
243
samplesInBuffer -= maxSamples;
244
bufferPos += maxSamples;
250
// Returns nonzero if the sample buffer is empty
251
int FIFOSampleBuffer::isEmpty() const
253
return (samplesInBuffer == 0) ? 1 : 0;
257
// Clears the sample buffer
258
void FIFOSampleBuffer::clear()