MythTV  0.26-pre
FIFOSampleBuffer.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends