media/libsoundtouch/src/FIFOSampleBuffer.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 ////////////////////////////////////////////////////////////////////////////////
michael@0 2 ///
michael@0 3 /// A buffer class for temporarily storaging sound samples, operates as a
michael@0 4 /// first-in-first-out pipe.
michael@0 5 ///
michael@0 6 /// Samples are added to the end of the sample buffer with the 'putSamples'
michael@0 7 /// function, and are received from the beginning of the buffer by calling
michael@0 8 /// the 'receiveSamples' function. The class automatically removes the
michael@0 9 /// outputted samples from the buffer, as well as grows the buffer size
michael@0 10 /// whenever necessary.
michael@0 11 ///
michael@0 12 /// Author : Copyright (c) Olli Parviainen
michael@0 13 /// Author e-mail : oparviai 'at' iki.fi
michael@0 14 /// SoundTouch WWW: http://www.surina.net/soundtouch
michael@0 15 ///
michael@0 16 ////////////////////////////////////////////////////////////////////////////////
michael@0 17 //
michael@0 18 // Last changed : $Date: 2012-11-08 12:53:01 -0600 (Thu, 08 Nov 2012) $
michael@0 19 // File revision : $Revision: 4 $
michael@0 20 //
michael@0 21 // $Id: FIFOSampleBuffer.cpp 160 2012-11-08 18:53:01Z oparviai $
michael@0 22 //
michael@0 23 ////////////////////////////////////////////////////////////////////////////////
michael@0 24 //
michael@0 25 // License :
michael@0 26 //
michael@0 27 // SoundTouch audio processing library
michael@0 28 // Copyright (c) Olli Parviainen
michael@0 29 //
michael@0 30 // This library is free software; you can redistribute it and/or
michael@0 31 // modify it under the terms of the GNU Lesser General Public
michael@0 32 // License as published by the Free Software Foundation; either
michael@0 33 // version 2.1 of the License, or (at your option) any later version.
michael@0 34 //
michael@0 35 // This library is distributed in the hope that it will be useful,
michael@0 36 // but WITHOUT ANY WARRANTY; without even the implied warranty of
michael@0 37 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
michael@0 38 // Lesser General Public License for more details.
michael@0 39 //
michael@0 40 // You should have received a copy of the GNU Lesser General Public
michael@0 41 // License along with this library; if not, write to the Free Software
michael@0 42 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
michael@0 43 //
michael@0 44 ////////////////////////////////////////////////////////////////////////////////
michael@0 45
michael@0 46 #include <stdlib.h>
michael@0 47 #include <memory.h>
michael@0 48 #include <string.h>
michael@0 49 #include <assert.h>
michael@0 50
michael@0 51 #include "FIFOSampleBuffer.h"
michael@0 52
michael@0 53 using namespace soundtouch;
michael@0 54
michael@0 55 // Constructor
michael@0 56 FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
michael@0 57 {
michael@0 58 assert(numChannels > 0);
michael@0 59 sizeInBytes = 0; // reasonable initial value
michael@0 60 buffer = NULL;
michael@0 61 bufferUnaligned = NULL;
michael@0 62 samplesInBuffer = 0;
michael@0 63 bufferPos = 0;
michael@0 64 channels = (uint)numChannels;
michael@0 65 ensureCapacity(32); // allocate initial capacity
michael@0 66 }
michael@0 67
michael@0 68
michael@0 69 // destructor
michael@0 70 FIFOSampleBuffer::~FIFOSampleBuffer()
michael@0 71 {
michael@0 72 delete[] bufferUnaligned;
michael@0 73 bufferUnaligned = NULL;
michael@0 74 buffer = NULL;
michael@0 75 }
michael@0 76
michael@0 77
michael@0 78 // Sets number of channels, 1 = mono, 2 = stereo
michael@0 79 void FIFOSampleBuffer::setChannels(int numChannels)
michael@0 80 {
michael@0 81 uint usedBytes;
michael@0 82
michael@0 83 assert(numChannels > 0);
michael@0 84 usedBytes = channels * samplesInBuffer;
michael@0 85 channels = (uint)numChannels;
michael@0 86 samplesInBuffer = usedBytes / channels;
michael@0 87 }
michael@0 88
michael@0 89
michael@0 90 // if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
michael@0 91 // zeroes this pointer by copying samples from the 'bufferPos' pointer
michael@0 92 // location on to the beginning of the buffer.
michael@0 93 void FIFOSampleBuffer::rewind()
michael@0 94 {
michael@0 95 if (buffer && bufferPos)
michael@0 96 {
michael@0 97 memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
michael@0 98 bufferPos = 0;
michael@0 99 }
michael@0 100 }
michael@0 101
michael@0 102
michael@0 103 // Adds 'numSamples' pcs of samples from the 'samples' memory position to
michael@0 104 // the sample buffer.
michael@0 105 void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
michael@0 106 {
michael@0 107 memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
michael@0 108 samplesInBuffer += nSamples;
michael@0 109 }
michael@0 110
michael@0 111
michael@0 112 // Increases the number of samples in the buffer without copying any actual
michael@0 113 // samples.
michael@0 114 //
michael@0 115 // This function is used to update the number of samples in the sample buffer
michael@0 116 // when accessing the buffer directly with 'ptrEnd' function. Please be
michael@0 117 // careful though!
michael@0 118 void FIFOSampleBuffer::putSamples(uint nSamples)
michael@0 119 {
michael@0 120 uint req;
michael@0 121
michael@0 122 req = samplesInBuffer + nSamples;
michael@0 123 ensureCapacity(req);
michael@0 124 samplesInBuffer += nSamples;
michael@0 125 }
michael@0 126
michael@0 127
michael@0 128 // Returns a pointer to the end of the used part of the sample buffer (i.e.
michael@0 129 // where the new samples are to be inserted). This function may be used for
michael@0 130 // inserting new samples into the sample buffer directly. Please be careful!
michael@0 131 //
michael@0 132 // Parameter 'slackCapacity' tells the function how much free capacity (in
michael@0 133 // terms of samples) there _at least_ should be, in order to the caller to
michael@0 134 // succesfully insert all the required samples to the buffer. When necessary,
michael@0 135 // the function grows the buffer size to comply with this requirement.
michael@0 136 //
michael@0 137 // When using this function as means for inserting new samples, also remember
michael@0 138 // to increase the sample count afterwards, by calling the
michael@0 139 // 'putSamples(numSamples)' function.
michael@0 140 SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
michael@0 141 {
michael@0 142 ensureCapacity(samplesInBuffer + slackCapacity);
michael@0 143 return buffer + samplesInBuffer * channels;
michael@0 144 }
michael@0 145
michael@0 146
michael@0 147 // Returns a pointer to the beginning of the currently non-outputted samples.
michael@0 148 // This function is provided for accessing the output samples directly.
michael@0 149 // Please be careful!
michael@0 150 //
michael@0 151 // When using this function to output samples, also remember to 'remove' the
michael@0 152 // outputted samples from the buffer by calling the
michael@0 153 // 'receiveSamples(numSamples)' function
michael@0 154 SAMPLETYPE *FIFOSampleBuffer::ptrBegin()
michael@0 155 {
michael@0 156 assert(buffer);
michael@0 157 return buffer + bufferPos * channels;
michael@0 158 }
michael@0 159
michael@0 160
michael@0 161 // Ensures that the buffer has enought capacity, i.e. space for _at least_
michael@0 162 // 'capacityRequirement' number of samples. The buffer is grown in steps of
michael@0 163 // 4 kilobytes to eliminate the need for frequently growing up the buffer,
michael@0 164 // as well as to round the buffer size up to the virtual memory page size.
michael@0 165 void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
michael@0 166 {
michael@0 167 SAMPLETYPE *tempUnaligned, *temp;
michael@0 168
michael@0 169 if (capacityRequirement > getCapacity())
michael@0 170 {
michael@0 171 // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
michael@0 172 sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
michael@0 173 assert(sizeInBytes % 2 == 0);
michael@0 174 tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
michael@0 175 if (tempUnaligned == NULL)
michael@0 176 {
michael@0 177 ST_THROW_RT_ERROR("Couldn't allocate memory!\n");
michael@0 178 }
michael@0 179 // Align the buffer to begin at 16byte cache line boundary for optimal performance
michael@0 180 temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned);
michael@0 181 if (samplesInBuffer)
michael@0 182 {
michael@0 183 memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
michael@0 184 }
michael@0 185 delete[] bufferUnaligned;
michael@0 186 buffer = temp;
michael@0 187 bufferUnaligned = tempUnaligned;
michael@0 188 bufferPos = 0;
michael@0 189 }
michael@0 190 else
michael@0 191 {
michael@0 192 // simply rewind the buffer (if necessary)
michael@0 193 rewind();
michael@0 194 }
michael@0 195 }
michael@0 196
michael@0 197
michael@0 198 // Returns the current buffer capacity in terms of samples
michael@0 199 uint FIFOSampleBuffer::getCapacity() const
michael@0 200 {
michael@0 201 return sizeInBytes / (channels * sizeof(SAMPLETYPE));
michael@0 202 }
michael@0 203
michael@0 204
michael@0 205 // Returns the number of samples currently in the buffer
michael@0 206 uint FIFOSampleBuffer::numSamples() const
michael@0 207 {
michael@0 208 return samplesInBuffer;
michael@0 209 }
michael@0 210
michael@0 211
michael@0 212 // Output samples from beginning of the sample buffer. Copies demanded number
michael@0 213 // of samples to output and removes them from the sample buffer. If there
michael@0 214 // are less than 'numsample' samples in the buffer, returns all available.
michael@0 215 //
michael@0 216 // Returns number of samples copied.
michael@0 217 uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
michael@0 218 {
michael@0 219 uint num;
michael@0 220
michael@0 221 num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
michael@0 222
michael@0 223 memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
michael@0 224 return receiveSamples(num);
michael@0 225 }
michael@0 226
michael@0 227
michael@0 228 // Removes samples from the beginning of the sample buffer without copying them
michael@0 229 // anywhere. Used to reduce the number of samples in the buffer, when accessing
michael@0 230 // the sample buffer with the 'ptrBegin' function.
michael@0 231 uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
michael@0 232 {
michael@0 233 if (maxSamples >= samplesInBuffer)
michael@0 234 {
michael@0 235 uint temp;
michael@0 236
michael@0 237 temp = samplesInBuffer;
michael@0 238 samplesInBuffer = 0;
michael@0 239 return temp;
michael@0 240 }
michael@0 241
michael@0 242 samplesInBuffer -= maxSamples;
michael@0 243 bufferPos += maxSamples;
michael@0 244
michael@0 245 return maxSamples;
michael@0 246 }
michael@0 247
michael@0 248
michael@0 249 // Returns nonzero if the sample buffer is empty
michael@0 250 int FIFOSampleBuffer::isEmpty() const
michael@0 251 {
michael@0 252 return (samplesInBuffer == 0) ? 1 : 0;
michael@0 253 }
michael@0 254
michael@0 255
michael@0 256 // Clears the sample buffer
michael@0 257 void FIFOSampleBuffer::clear()
michael@0 258 {
michael@0 259 samplesInBuffer = 0;
michael@0 260 bufferPos = 0;
michael@0 261 }
michael@0 262
michael@0 263
michael@0 264 /// allow trimming (downwards) amount of samples in pipeline.
michael@0 265 /// Returns adjusted amount of samples
michael@0 266 uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples)
michael@0 267 {
michael@0 268 if (numSamples < samplesInBuffer)
michael@0 269 {
michael@0 270 samplesInBuffer = numSamples;
michael@0 271 }
michael@0 272 return samplesInBuffer;
michael@0 273 }
michael@0 274

mercurial