tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

FIFOSampleBuffer.cpp (8520B)


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