media/libsoundtouch/src/FIFOSampleBuffer.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial