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: 2006/09/18 22:29:22 $
19
// File revision : $Revision: 1.4 $
21
// $Id: FIFOSampleBuffer.cpp,v 1.4 2006/09/18 22:29:22 martynshaw Exp $
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(uint numChannels)
59
sizeInBytes = 0; // reasonable initial value
60
buffer = NULL; //new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE)];
61
bufferUnaligned = NULL;
64
channels = numChannels;
69
FIFOSampleBuffer::~FIFOSampleBuffer()
71
delete[] bufferUnaligned;
75
// Sets number of channels, 1 = mono, 2 = stereo
76
void FIFOSampleBuffer::setChannels(const uint numChannels)
80
usedBytes = channels * samplesInBuffer;
81
channels = numChannels;
82
samplesInBuffer = usedBytes / channels;
86
// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
87
// zeroes this pointer by copying samples from the 'bufferPos' pointer
88
// location on to the beginning of the buffer.
89
void FIFOSampleBuffer::rewind()
93
memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
99
// Adds 'numSamples' pcs of samples from the 'samples' memory position to
100
// the sample buffer.
101
void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint numSamples)
103
memcpy(ptrEnd(numSamples), samples, sizeof(SAMPLETYPE) * numSamples * channels);
104
samplesInBuffer += numSamples;
108
// Increases the number of samples in the buffer without copying any actual
111
// This function is used to update the number of samples in the sample buffer
112
// when accessing the buffer directly with 'ptrEnd' function. Please be
114
void FIFOSampleBuffer::putSamples(uint numSamples)
118
req = samplesInBuffer + numSamples;
120
samplesInBuffer += numSamples;
124
// Returns a pointer to the end of the used part of the sample buffer (i.e.
125
// where the new samples are to be inserted). This function may be used for
126
// inserting new samples into the sample buffer directly. Please be careful!
128
// Parameter 'slackCapacity' tells the function how much free capacity (in
129
// terms of samples) there _at least_ should be, in order to the caller to
130
// succesfully insert all the required samples to the buffer. When necessary,
131
// the function grows the buffer size to comply with this requirement.
133
// When using this function as means for inserting new samples, also remember
134
// to increase the sample count afterwards, by calling the
135
// 'putSamples(numSamples)' function.
136
SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
138
ensureCapacity(samplesInBuffer + slackCapacity);
139
return buffer + samplesInBuffer * channels;
143
// Returns a pointer to the beginning of the currently non-outputted samples.
144
// This function is provided for accessing the output samples directly.
145
// Please be careful!
147
// When using this function to output samples, also remember to 'remove' the
148
// outputted samples from the buffer by calling the
149
// 'receiveSamples(numSamples)' function
150
SAMPLETYPE *FIFOSampleBuffer::ptrBegin() const
152
return buffer + bufferPos * channels;
156
// Ensures that the buffer has enought capacity, i.e. space for _at least_
157
// 'capacityRequirement' number of samples. The buffer is grown in steps of
158
// 4 kilobytes to eliminate the need for frequently growing up the buffer,
159
// as well as to round the buffer size up to the virtual memory page size.
160
void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
162
SAMPLETYPE *tempUnaligned, *temp;
164
if (capacityRequirement > getCapacity())
166
// enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
167
sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & -4096;
168
assert(sizeInBytes % 2 == 0);
169
tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
170
if (tempUnaligned == NULL)
172
throw std::runtime_error("Couldn't allocate memory!\n");
174
temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & -16);
175
memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
176
delete[] bufferUnaligned;
178
bufferUnaligned = tempUnaligned;
183
// simply rewind the buffer (if necessary)
189
// Returns the current buffer capacity in terms of samples
190
uint FIFOSampleBuffer::getCapacity() const
192
return sizeInBytes / (channels * sizeof(SAMPLETYPE));
196
// Returns the number of samples currently in the buffer
197
uint FIFOSampleBuffer::numSamples() const
199
return samplesInBuffer;
203
// Output samples from beginning of the sample buffer. Copies demanded number
204
// of samples to output and removes them from the sample buffer. If there
205
// are less than 'numsample' samples in the buffer, returns all available.
207
// Returns number of samples copied.
208
uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
212
num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
214
memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
215
return receiveSamples(num);
219
// Removes samples from the beginning of the sample buffer without copying them
220
// anywhere. Used to reduce the number of samples in the buffer, when accessing
221
// the sample buffer with the 'ptrBegin' function.
222
uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
224
if (maxSamples >= samplesInBuffer)
228
temp = samplesInBuffer;
233
samplesInBuffer -= maxSamples;
234
bufferPos += maxSamples;
240
// Returns nonzero if the sample buffer is empty
241
int FIFOSampleBuffer::isEmpty() const
243
return (samplesInBuffer == 0) ? 1 : 0;
247
// Clears the sample buffer
248
void FIFOSampleBuffer::clear()