|
MythTV
0.26-pre
|
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 // 00018 // Last changed : $Date$ 00019 // File revision : $Revision$ 00020 // 00021 // $Id$ 00022 // 00024 // 00025 // License : 00026 // 00027 // SoundTouch audio processing library 00028 // Copyright (c) Olli Parviainen 00029 // 00030 // This library is free software; you can redistribute it and/or 00031 // modify it under the terms of the GNU Lesser General Public 00032 // License as published by the Free Software Foundation; either 00033 // version 2.1 of the License, or (at your option) any later version. 00034 // 00035 // This library is distributed in the hope that it will be useful, 00036 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00037 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00038 // Lesser General Public License for more details. 00039 // 00040 // You should have received a copy of the GNU Lesser General Public 00041 // License along with this library; if not, write to the Free Software 00042 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00043 // 00045 00046 #include <stdlib.h> 00047 #include <memory.h> 00048 #include <string.h> 00049 #include <assert.h> 00050 #include <stdexcept> 00051 00052 #include "FIFOSampleBuffer.h" 00053 00054 using namespace soundtouch; 00055 00056 // Constructor 00057 FIFOSampleBuffer::FIFOSampleBuffer(uint numChannels) 00058 { 00059 sizeInBytes = 0; // reasonable initial value 00060 buffer = NULL; //new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE)]; 00061 bufferUnaligned = NULL; 00062 samplesInBuffer = 0; 00063 bufferPos = 0; 00064 channels = numChannels; 00065 } 00066 00067 00068 // destructor 00069 FIFOSampleBuffer::~FIFOSampleBuffer() 00070 { 00071 delete[] bufferUnaligned; 00072 } 00073 00074 00075 // Sets number of channels, 1 = mono, 2 = stereo 00076 void FIFOSampleBuffer::setChannels(const uint numChannels) 00077 { 00078 uint usedBytes; 00079 00080 usedBytes = channels * samplesInBuffer; 00081 channels = numChannels; 00082 samplesInBuffer = usedBytes / channels; 00083 } 00084 00085 00086 // if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and 00087 // zeroes this pointer by copying samples from the 'bufferPos' pointer 00088 // location on to the beginning of the buffer. 00089 void FIFOSampleBuffer::rewind() 00090 { 00091 if (bufferPos) 00092 { 00093 memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer); 00094 bufferPos = 0; 00095 } 00096 } 00097 00098 00099 // Adds 'numSamples' pcs of samples from the 'samples' memory position to 00100 // the sample buffer. 00101 void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint numSamples) 00102 { 00103 memcpy(ptrEnd(numSamples), samples, sizeof(SAMPLETYPE) * numSamples * channels); 00104 samplesInBuffer += numSamples; 00105 } 00106 00107 00108 // Increases the number of samples in the buffer without copying any actual 00109 // samples. 00110 // 00111 // This function is used to update the number of samples in the sample buffer 00112 // when accessing the buffer directly with 'ptrEnd' function. Please be 00113 // careful though! 00114 void FIFOSampleBuffer::putSamples(uint numSamples) 00115 { 00116 uint req; 00117 00118 req = samplesInBuffer + numSamples; 00119 ensureCapacity(req); 00120 samplesInBuffer += numSamples; 00121 } 00122 00123 00124 // Returns a pointer to the end of the used part of the sample buffer (i.e. 00125 // where the new samples are to be inserted). This function may be used for 00126 // inserting new samples into the sample buffer directly. Please be careful! 00127 // 00128 // Parameter 'slackCapacity' tells the function how much free capacity (in 00129 // terms of samples) there _at least_ should be, in order to the caller to 00130 // succesfully insert all the required samples to the buffer. When necessary, 00131 // the function grows the buffer size to comply with this requirement. 00132 // 00133 // When using this function as means for inserting new samples, also remember 00134 // to increase the sample count afterwards, by calling the 00135 // 'putSamples(numSamples)' function. 00136 SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity) 00137 { 00138 ensureCapacity(samplesInBuffer + slackCapacity); 00139 return buffer + samplesInBuffer * channels; 00140 } 00141 00142 00143 // Returns a pointer to the beginning of the currently non-outputted samples. 00144 // This function is provided for accessing the output samples directly. 00145 // Please be careful! 00146 // 00147 // When using this function to output samples, also remember to 'remove' the 00148 // outputted samples from the buffer by calling the 00149 // 'receiveSamples(numSamples)' function 00150 SAMPLETYPE *FIFOSampleBuffer::ptrBegin() const 00151 { 00152 return buffer + bufferPos * channels; 00153 } 00154 00155 00156 // Ensures that the buffer has enought capacity, i.e. space for _at least_ 00157 // 'capacityRequirement' number of samples. The buffer is grown in steps of 00158 // 4 kilobytes to eliminate the need for frequently growing up the buffer, 00159 // as well as to round the buffer size up to the virtual memory page size. 00160 void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement) 00161 { 00162 SAMPLETYPE *tempUnaligned, *temp; 00163 00164 if (capacityRequirement > getCapacity()) 00165 { 00166 // enlarge the buffer in 4kbyte steps (round up to next 4k boundary) 00167 sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & -4096; 00168 assert(sizeInBytes % 2 == 0); 00169 tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; 00170 if (tempUnaligned == NULL) 00171 { 00172 throw std::runtime_error("Couldn't allocate memory!\n"); 00173 } 00174 temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & -16); 00175 memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE)); 00176 delete[] bufferUnaligned; 00177 buffer = temp; 00178 bufferUnaligned = tempUnaligned; 00179 bufferPos = 0; 00180 } 00181 else 00182 { 00183 // simply rewind the buffer (if necessary) 00184 rewind(); 00185 } 00186 } 00187 00188 00189 // Returns the current buffer capacity in terms of samples 00190 uint FIFOSampleBuffer::getCapacity() const 00191 { 00192 return sizeInBytes / (channels * sizeof(SAMPLETYPE)); 00193 } 00194 00195 00196 // Returns the number of samples currently in the buffer 00197 uint FIFOSampleBuffer::numSamples() const 00198 { 00199 return samplesInBuffer; 00200 } 00201 00202 00203 // Output samples from beginning of the sample buffer. Copies demanded number 00204 // of samples to output and removes them from the sample buffer. If there 00205 // are less than 'numsample' samples in the buffer, returns all available. 00206 // 00207 // Returns number of samples copied. 00208 uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples) 00209 { 00210 uint num; 00211 00212 num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples; 00213 00214 memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num); 00215 return receiveSamples(num); 00216 } 00217 00218 00219 // Removes samples from the beginning of the sample buffer without copying them 00220 // anywhere. Used to reduce the number of samples in the buffer, when accessing 00221 // the sample buffer with the 'ptrBegin' function. 00222 uint FIFOSampleBuffer::receiveSamples(uint maxSamples) 00223 { 00224 if (maxSamples >= samplesInBuffer) 00225 { 00226 uint temp; 00227 00228 temp = samplesInBuffer; 00229 samplesInBuffer = 0; 00230 return temp; 00231 } 00232 00233 samplesInBuffer -= maxSamples; 00234 bufferPos += maxSamples; 00235 00236 return maxSamples; 00237 } 00238 00239 00240 // Returns nonzero if the sample buffer is empty 00241 int FIFOSampleBuffer::isEmpty() const 00242 { 00243 return (samplesInBuffer == 0) ? 1 : 0; 00244 } 00245 00246 00247 // Clears the sample buffer 00248 void FIFOSampleBuffer::clear() 00249 { 00250 samplesInBuffer = 0; 00251 bufferPos = 0; 00252 }
1.7.6.1