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 +