media/libsoundtouch/src/FIFOSampleBuffer.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libsoundtouch/src/FIFOSampleBuffer.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,274 @@
     1.4 +////////////////////////////////////////////////////////////////////////////////
     1.5 +///
     1.6 +/// A buffer class for temporarily storaging sound samples, operates as a 
     1.7 +/// first-in-first-out pipe.
     1.8 +///
     1.9 +/// Samples are added to the end of the sample buffer with the 'putSamples' 
    1.10 +/// function, and are received from the beginning of the buffer by calling
    1.11 +/// the 'receiveSamples' function. The class automatically removes the 
    1.12 +/// outputted samples from the buffer, as well as grows the buffer size 
    1.13 +/// whenever necessary.
    1.14 +///
    1.15 +/// Author        : Copyright (c) Olli Parviainen
    1.16 +/// Author e-mail : oparviai 'at' iki.fi
    1.17 +/// SoundTouch WWW: http://www.surina.net/soundtouch
    1.18 +///
    1.19 +////////////////////////////////////////////////////////////////////////////////
    1.20 +//
    1.21 +// Last changed  : $Date: 2012-11-08 12:53:01 -0600 (Thu, 08 Nov 2012) $
    1.22 +// File revision : $Revision: 4 $
    1.23 +//
    1.24 +// $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
    1.25 +//
    1.26 +////////////////////////////////////////////////////////////////////////////////
    1.27 +//
    1.28 +// License :
    1.29 +//
    1.30 +//  SoundTouch audio processing library
    1.31 +//  Copyright (c) Olli Parviainen
    1.32 +//
    1.33 +//  This library is free software; you can redistribute it and/or
    1.34 +//  modify it under the terms of the GNU Lesser General Public
    1.35 +//  License as published by the Free Software Foundation; either
    1.36 +//  version 2.1 of the License, or (at your option) any later version.
    1.37 +//
    1.38 +//  This library is distributed in the hope that it will be useful,
    1.39 +//  but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.40 +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.41 +//  Lesser General Public License for more details.
    1.42 +//
    1.43 +//  You should have received a copy of the GNU Lesser General Public
    1.44 +//  License along with this library; if not, write to the Free Software
    1.45 +//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.46 +//
    1.47 +////////////////////////////////////////////////////////////////////////////////
    1.48 +
    1.49 +#include <stdlib.h>
    1.50 +#include <memory.h>
    1.51 +#include <string.h>
    1.52 +#include <assert.h>
    1.53 +
    1.54 +#include "FIFOSampleBuffer.h"
    1.55 +
    1.56 +using namespace soundtouch;
    1.57 +
    1.58 +// Constructor
    1.59 +FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
    1.60 +{
    1.61 +    assert(numChannels > 0);
    1.62 +    sizeInBytes = 0; // reasonable initial value
    1.63 +    buffer = NULL;
    1.64 +    bufferUnaligned = NULL;
    1.65 +    samplesInBuffer = 0;
    1.66 +    bufferPos = 0;
    1.67 +    channels = (uint)numChannels;
    1.68 +    ensureCapacity(32);     // allocate initial capacity 
    1.69 +}
    1.70 +
    1.71 +
    1.72 +// destructor
    1.73 +FIFOSampleBuffer::~FIFOSampleBuffer()
    1.74 +{
    1.75 +    delete[] bufferUnaligned;
    1.76 +    bufferUnaligned = NULL;
    1.77 +    buffer = NULL;
    1.78 +}
    1.79 +
    1.80 +
    1.81 +// Sets number of channels, 1 = mono, 2 = stereo
    1.82 +void FIFOSampleBuffer::setChannels(int numChannels)
    1.83 +{
    1.84 +    uint usedBytes;
    1.85 +
    1.86 +    assert(numChannels > 0);
    1.87 +    usedBytes = channels * samplesInBuffer;
    1.88 +    channels = (uint)numChannels;
    1.89 +    samplesInBuffer = usedBytes / channels;
    1.90 +}
    1.91 +
    1.92 +
    1.93 +// if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
    1.94 +// zeroes this pointer by copying samples from the 'bufferPos' pointer 
    1.95 +// location on to the beginning of the buffer.
    1.96 +void FIFOSampleBuffer::rewind()
    1.97 +{
    1.98 +    if (buffer && bufferPos) 
    1.99 +    {
   1.100 +        memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
   1.101 +        bufferPos = 0;
   1.102 +    }
   1.103 +}
   1.104 +
   1.105 +
   1.106 +// Adds 'numSamples' pcs of samples from the 'samples' memory position to 
   1.107 +// the sample buffer.
   1.108 +void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
   1.109 +{
   1.110 +    memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
   1.111 +    samplesInBuffer += nSamples;
   1.112 +}
   1.113 +
   1.114 +
   1.115 +// Increases the number of samples in the buffer without copying any actual
   1.116 +// samples.
   1.117 +//
   1.118 +// This function is used to update the number of samples in the sample buffer
   1.119 +// when accessing the buffer directly with 'ptrEnd' function. Please be 
   1.120 +// careful though!
   1.121 +void FIFOSampleBuffer::putSamples(uint nSamples)
   1.122 +{
   1.123 +    uint req;
   1.124 +
   1.125 +    req = samplesInBuffer + nSamples;
   1.126 +    ensureCapacity(req);
   1.127 +    samplesInBuffer += nSamples;
   1.128 +}
   1.129 +
   1.130 +
   1.131 +// Returns a pointer to the end of the used part of the sample buffer (i.e. 
   1.132 +// where the new samples are to be inserted). This function may be used for 
   1.133 +// inserting new samples into the sample buffer directly. Please be careful! 
   1.134 +//
   1.135 +// Parameter 'slackCapacity' tells the function how much free capacity (in
   1.136 +// terms of samples) there _at least_ should be, in order to the caller to
   1.137 +// succesfully insert all the required samples to the buffer. When necessary, 
   1.138 +// the function grows the buffer size to comply with this requirement.
   1.139 +//
   1.140 +// When using this function as means for inserting new samples, also remember 
   1.141 +// to increase the sample count afterwards, by calling  the 
   1.142 +// 'putSamples(numSamples)' function.
   1.143 +SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity) 
   1.144 +{
   1.145 +    ensureCapacity(samplesInBuffer + slackCapacity);
   1.146 +    return buffer + samplesInBuffer * channels;
   1.147 +}
   1.148 +
   1.149 +
   1.150 +// Returns a pointer to the beginning of the currently non-outputted samples. 
   1.151 +// This function is provided for accessing the output samples directly. 
   1.152 +// Please be careful!
   1.153 +//
   1.154 +// When using this function to output samples, also remember to 'remove' the
   1.155 +// outputted samples from the buffer by calling the 
   1.156 +// 'receiveSamples(numSamples)' function
   1.157 +SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
   1.158 +{
   1.159 +    assert(buffer);
   1.160 +    return buffer + bufferPos * channels;
   1.161 +}
   1.162 +
   1.163 +
   1.164 +// Ensures that the buffer has enought capacity, i.e. space for _at least_
   1.165 +// 'capacityRequirement' number of samples. The buffer is grown in steps of
   1.166 +// 4 kilobytes to eliminate the need for frequently growing up the buffer,
   1.167 +// as well as to round the buffer size up to the virtual memory page size.
   1.168 +void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
   1.169 +{
   1.170 +    SAMPLETYPE *tempUnaligned, *temp;
   1.171 +
   1.172 +    if (capacityRequirement > getCapacity()) 
   1.173 +    {
   1.174 +        // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
   1.175 +        sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
   1.176 +        assert(sizeInBytes % 2 == 0);
   1.177 +        tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
   1.178 +        if (tempUnaligned == NULL)
   1.179 +        {
   1.180 +            ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
   1.181 +        }
   1.182 +        // Align the buffer to begin at 16byte cache line boundary for optimal performance
   1.183 +        temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned);
   1.184 +        if (samplesInBuffer)
   1.185 +        {
   1.186 +            memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
   1.187 +        }
   1.188 +        delete[] bufferUnaligned;
   1.189 +        buffer = temp;
   1.190 +        bufferUnaligned = tempUnaligned;
   1.191 +        bufferPos = 0;
   1.192 +    } 
   1.193 +    else 
   1.194 +    {
   1.195 +        // simply rewind the buffer (if necessary)
   1.196 +        rewind();
   1.197 +    }
   1.198 +}
   1.199 +
   1.200 +
   1.201 +// Returns the current buffer capacity in terms of samples
   1.202 +uint FIFOSampleBuffer::getCapacity() const
   1.203 +{
   1.204 +    return sizeInBytes / (channels * sizeof(SAMPLETYPE));
   1.205 +}
   1.206 +
   1.207 +
   1.208 +// Returns the number of samples currently in the buffer
   1.209 +uint FIFOSampleBuffer::numSamples() const
   1.210 +{
   1.211 +    return samplesInBuffer;
   1.212 +}
   1.213 +
   1.214 +
   1.215 +// Output samples from beginning of the sample buffer. Copies demanded number
   1.216 +// of samples to output and removes them from the sample buffer. If there
   1.217 +// are less than 'numsample' samples in the buffer, returns all available.
   1.218 +//
   1.219 +// Returns number of samples copied.
   1.220 +uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
   1.221 +{
   1.222 +    uint num;
   1.223 +
   1.224 +    num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
   1.225 +
   1.226 +    memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
   1.227 +    return receiveSamples(num);
   1.228 +}
   1.229 +
   1.230 +
   1.231 +// Removes samples from the beginning of the sample buffer without copying them
   1.232 +// anywhere. Used to reduce the number of samples in the buffer, when accessing
   1.233 +// the sample buffer with the 'ptrBegin' function.
   1.234 +uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
   1.235 +{
   1.236 +    if (maxSamples >= samplesInBuffer)
   1.237 +    {
   1.238 +        uint temp;
   1.239 +
   1.240 +        temp = samplesInBuffer;
   1.241 +        samplesInBuffer = 0;
   1.242 +        return temp;
   1.243 +    }
   1.244 +
   1.245 +    samplesInBuffer -= maxSamples;
   1.246 +    bufferPos += maxSamples;
   1.247 +
   1.248 +    return maxSamples;
   1.249 +}
   1.250 +
   1.251 +
   1.252 +// Returns nonzero if the sample buffer is empty
   1.253 +int FIFOSampleBuffer::isEmpty() const
   1.254 +{
   1.255 +    return (samplesInBuffer == 0) ? 1 : 0;
   1.256 +}
   1.257 +
   1.258 +
   1.259 +// Clears the sample buffer
   1.260 +void FIFOSampleBuffer::clear()
   1.261 +{
   1.262 +    samplesInBuffer = 0;
   1.263 +    bufferPos = 0;
   1.264 +}
   1.265 +
   1.266 +
   1.267 +/// allow trimming (downwards) amount of samples in pipeline.
   1.268 +/// Returns adjusted amount of samples
   1.269 +uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
   1.270 +{
   1.271 +    if (numSamples < samplesInBuffer)
   1.272 +    {
   1.273 +        samplesInBuffer = numSamples;
   1.274 +    }
   1.275 +    return samplesInBuffer;
   1.276 +}
   1.277 +

mercurial