PageRenderTime 386ms CodeModel.GetById 181ms app.highlight 16ms RepoModel.GetById 185ms app.codeStats 1ms

/external/pysoundtouch14/libsoundtouch/FIFOSampleBuffer.cpp

http://echo-nest-remix.googlecode.com/
C++ | 256 lines | 121 code | 40 blank | 95 comment | 9 complexity | f6d2e6b19193a0d37ed7cb86c7cb0ef2 MD5 | raw file
  1////////////////////////////////////////////////////////////////////////////////
  2///
  3/// A buffer class for temporarily storaging sound samples, operates as a 
  4/// first-in-first-out pipe.
  5///
  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.
 11///
 12/// Author        : Copyright (c) Olli Parviainen
 13/// Author e-mail : oparviai 'at' iki.fi
 14/// SoundTouch WWW: http://www.surina.net/soundtouch
 15///
 16////////////////////////////////////////////////////////////////////////////////
 17//
 18// Last changed  : $Date: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
 19// File revision : $Revision: 4 $
 20//
 21// $Id: FIFOSampleBuffer.cpp 11 2008-02-10 16:26:55Z oparviai $
 22//
 23////////////////////////////////////////////////////////////////////////////////
 24//
 25// License :
 26//
 27//  SoundTouch audio processing library
 28//  Copyright (c) Olli Parviainen
 29//
 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.
 34//
 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.
 39//
 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
 43//
 44////////////////////////////////////////////////////////////////////////////////
 45
 46#include <stdlib.h>

 47#include <memory.h>

 48#include <string.h>

 49#include <assert.h>

 50#include <stdexcept>

 51
 52#include "FIFOSampleBuffer.h"

 53
 54using namespace soundtouch;
 55
 56// Constructor
 57FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
 58{
 59    assert(numChannels > 0);
 60    sizeInBytes = 0; // reasonable initial value
 61    buffer = NULL;
 62    bufferUnaligned = NULL;
 63    samplesInBuffer = 0;
 64    bufferPos = 0;
 65    channels = (uint)numChannels;
 66}
 67
 68
 69// destructor
 70FIFOSampleBuffer::~FIFOSampleBuffer()
 71{
 72    delete[] bufferUnaligned;
 73    bufferUnaligned = NULL;
 74    buffer = NULL;
 75}
 76
 77
 78// Sets number of channels, 1 = mono, 2 = stereo
 79void FIFOSampleBuffer::setChannels(int numChannels)
 80{
 81    uint usedBytes;
 82
 83    assert(numChannels > 0);
 84    usedBytes = channels * samplesInBuffer;
 85    channels = (uint)numChannels;
 86    samplesInBuffer = usedBytes / channels;
 87}
 88
 89
 90// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
 91// zeroes this pointer by copying samples from the 'bufferPos' pointer 
 92// location on to the beginning of the buffer.
 93void FIFOSampleBuffer::rewind()
 94{
 95    if (buffer && bufferPos) 
 96    {
 97        memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
 98        bufferPos = 0;
 99    }
100}
101
102
103// Adds 'numSamples' pcs of samples from the 'samples' memory position to 
104// the sample buffer.
105void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
106{
107    memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
108    samplesInBuffer += nSamples;
109}
110
111
112// Increases the number of samples in the buffer without copying any actual
113// samples.
114//
115// This function is used to update the number of samples in the sample buffer
116// when accessing the buffer directly with 'ptrEnd' function. Please be 
117// careful though!
118void FIFOSampleBuffer::putSamples(uint nSamples)
119{
120    uint req;
121
122    req = samplesInBuffer + nSamples;
123    ensureCapacity(req);
124    samplesInBuffer += nSamples;
125}
126
127
128// Returns a pointer to the end of the used part of the sample buffer (i.e. 
129// where the new samples are to be inserted). This function may be used for 
130// inserting new samples into the sample buffer directly. Please be careful! 
131//
132// Parameter 'slackCapacity' tells the function how much free capacity (in
133// terms of samples) there _at least_ should be, in order to the caller to
134// succesfully insert all the required samples to the buffer. When necessary, 
135// the function grows the buffer size to comply with this requirement.
136//
137// When using this function as means for inserting new samples, also remember 
138// to increase the sample count afterwards, by calling  the 
139// 'putSamples(numSamples)' function.
140SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity) 
141{
142    ensureCapacity(samplesInBuffer + slackCapacity);
143    return buffer + samplesInBuffer * channels;
144}
145
146
147// Returns a pointer to the beginning of the currently non-outputted samples. 
148// This function is provided for accessing the output samples directly. 
149// Please be careful!
150//
151// When using this function to output samples, also remember to 'remove' the
152// outputted samples from the buffer by calling the 
153// 'receiveSamples(numSamples)' function
154SAMPLETYPE *FIFOSampleBuffer::ptrBegin() const
155{
156    return buffer + bufferPos * channels;
157}
158
159
160// Ensures that the buffer has enought capacity, i.e. space for _at least_
161// 'capacityRequirement' number of samples. The buffer is grown in steps of
162// 4 kilobytes to eliminate the need for frequently growing up the buffer,
163// as well as to round the buffer size up to the virtual memory page size.
164void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
165{
166    SAMPLETYPE *tempUnaligned, *temp;
167
168    if (capacityRequirement > getCapacity()) 
169    {
170        // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
171        sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
172        assert(sizeInBytes % 2 == 0);
173        tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
174        if (tempUnaligned == NULL)
175        {
176            throw std::runtime_error("Couldn't allocate memory!\n");
177        }
178        temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16);
179        memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
180        delete[] bufferUnaligned;
181        buffer = temp;
182        bufferUnaligned = tempUnaligned;
183        bufferPos = 0;
184    } 
185    else 
186    {
187        // simply rewind the buffer (if necessary)
188        rewind();
189    }
190}
191
192
193// Returns the current buffer capacity in terms of samples
194uint FIFOSampleBuffer::getCapacity() const
195{
196    return sizeInBytes / (channels * sizeof(SAMPLETYPE));
197}
198
199
200// Returns the number of samples currently in the buffer
201uint FIFOSampleBuffer::numSamples() const
202{
203    return samplesInBuffer;
204}
205
206
207// Output samples from beginning of the sample buffer. Copies demanded number
208// of samples to output and removes them from the sample buffer. If there
209// are less than 'numsample' samples in the buffer, returns all available.
210//
211// Returns number of samples copied.
212uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
213{
214    uint num;
215
216    num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
217
218    memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
219    return receiveSamples(num);
220}
221
222
223// Removes samples from the beginning of the sample buffer without copying them
224// anywhere. Used to reduce the number of samples in the buffer, when accessing
225// the sample buffer with the 'ptrBegin' function.
226uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
227{
228    if (maxSamples >= samplesInBuffer)
229    {
230        uint temp;
231
232        temp = samplesInBuffer;
233        samplesInBuffer = 0;
234        return temp;
235    }
236
237    samplesInBuffer -= maxSamples;
238    bufferPos += maxSamples;
239
240    return maxSamples;
241}
242
243
244// Returns nonzero if the sample buffer is empty
245int FIFOSampleBuffer::isEmpty() const
246{
247    return (samplesInBuffer == 0) ? 1 : 0;
248}
249
250
251// Clears the sample buffer
252void FIFOSampleBuffer::clear()
253{
254    samplesInBuffer = 0;
255    bufferPos = 0;
256}