/external/pysoundtouch14/libsoundtouch/FIFOSampleBuffer.cpp

http://echo-nest-remix.googlecode.com/ · C++ · 256 lines · 121 code · 40 blank · 95 comment · 9 complexity · f6d2e6b19193a0d37ed7cb86c7cb0ef2 MD5 · raw file

  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: 2008-02-10 18:26:55 +0200 (Sun, 10 Feb 2008) $
  19. // File revision : $Revision: 4 $
  20. //
  21. // $Id: FIFOSampleBuffer.cpp 11 2008-02-10 16:26:55Z 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. ////////////////////////////////////////////////////////////////////////////////
  45. #include <stdlib.h>
  46. #include <memory.h>
  47. #include <string.h>
  48. #include <assert.h>
  49. #include <stdexcept>
  50. #include "FIFOSampleBuffer.h"
  51. using namespace soundtouch;
  52. // Constructor
  53. FIFOSampleBuffer::FIFOSampleBuffer(int numChannels)
  54. {
  55. assert(numChannels > 0);
  56. sizeInBytes = 0; // reasonable initial value
  57. buffer = NULL;
  58. bufferUnaligned = NULL;
  59. samplesInBuffer = 0;
  60. bufferPos = 0;
  61. channels = (uint)numChannels;
  62. }
  63. // destructor
  64. FIFOSampleBuffer::~FIFOSampleBuffer()
  65. {
  66. delete[] bufferUnaligned;
  67. bufferUnaligned = NULL;
  68. buffer = NULL;
  69. }
  70. // Sets number of channels, 1 = mono, 2 = stereo
  71. void FIFOSampleBuffer::setChannels(int numChannels)
  72. {
  73. uint usedBytes;
  74. assert(numChannels > 0);
  75. usedBytes = channels * samplesInBuffer;
  76. channels = (uint)numChannels;
  77. samplesInBuffer = usedBytes / channels;
  78. }
  79. // if output location pointer 'bufferPos' isn't zero, 'rewinds' the buffer and
  80. // zeroes this pointer by copying samples from the 'bufferPos' pointer
  81. // location on to the beginning of the buffer.
  82. void FIFOSampleBuffer::rewind()
  83. {
  84. if (buffer && bufferPos)
  85. {
  86. memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer);
  87. bufferPos = 0;
  88. }
  89. }
  90. // Adds 'numSamples' pcs of samples from the 'samples' memory position to
  91. // the sample buffer.
  92. void FIFOSampleBuffer::putSamples(const SAMPLETYPE *samples, uint nSamples)
  93. {
  94. memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels);
  95. samplesInBuffer += nSamples;
  96. }
  97. // Increases the number of samples in the buffer without copying any actual
  98. // samples.
  99. //
  100. // This function is used to update the number of samples in the sample buffer
  101. // when accessing the buffer directly with 'ptrEnd' function. Please be
  102. // careful though!
  103. void FIFOSampleBuffer::putSamples(uint nSamples)
  104. {
  105. uint req;
  106. req = samplesInBuffer + nSamples;
  107. ensureCapacity(req);
  108. samplesInBuffer += nSamples;
  109. }
  110. // Returns a pointer to the end of the used part of the sample buffer (i.e.
  111. // where the new samples are to be inserted). This function may be used for
  112. // inserting new samples into the sample buffer directly. Please be careful!
  113. //
  114. // Parameter 'slackCapacity' tells the function how much free capacity (in
  115. // terms of samples) there _at least_ should be, in order to the caller to
  116. // succesfully insert all the required samples to the buffer. When necessary,
  117. // the function grows the buffer size to comply with this requirement.
  118. //
  119. // When using this function as means for inserting new samples, also remember
  120. // to increase the sample count afterwards, by calling the
  121. // 'putSamples(numSamples)' function.
  122. SAMPLETYPE *FIFOSampleBuffer::ptrEnd(uint slackCapacity)
  123. {
  124. ensureCapacity(samplesInBuffer + slackCapacity);
  125. return buffer + samplesInBuffer * channels;
  126. }
  127. // Returns a pointer to the beginning of the currently non-outputted samples.
  128. // This function is provided for accessing the output samples directly.
  129. // Please be careful!
  130. //
  131. // When using this function to output samples, also remember to 'remove' the
  132. // outputted samples from the buffer by calling the
  133. // 'receiveSamples(numSamples)' function
  134. SAMPLETYPE *FIFOSampleBuffer::ptrBegin() const
  135. {
  136. return buffer + bufferPos * channels;
  137. }
  138. // Ensures that the buffer has enought capacity, i.e. space for _at least_
  139. // 'capacityRequirement' number of samples. The buffer is grown in steps of
  140. // 4 kilobytes to eliminate the need for frequently growing up the buffer,
  141. // as well as to round the buffer size up to the virtual memory page size.
  142. void FIFOSampleBuffer::ensureCapacity(uint capacityRequirement)
  143. {
  144. SAMPLETYPE *tempUnaligned, *temp;
  145. if (capacityRequirement > getCapacity())
  146. {
  147. // enlarge the buffer in 4kbyte steps (round up to next 4k boundary)
  148. sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096;
  149. assert(sizeInBytes % 2 == 0);
  150. tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)];
  151. if (tempUnaligned == NULL)
  152. {
  153. throw std::runtime_error("Couldn't allocate memory!\n");
  154. }
  155. temp = (SAMPLETYPE *)(((ulong)tempUnaligned + 15) & (ulong)-16);
  156. memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE));
  157. delete[] bufferUnaligned;
  158. buffer = temp;
  159. bufferUnaligned = tempUnaligned;
  160. bufferPos = 0;
  161. }
  162. else
  163. {
  164. // simply rewind the buffer (if necessary)
  165. rewind();
  166. }
  167. }
  168. // Returns the current buffer capacity in terms of samples
  169. uint FIFOSampleBuffer::getCapacity() const
  170. {
  171. return sizeInBytes / (channels * sizeof(SAMPLETYPE));
  172. }
  173. // Returns the number of samples currently in the buffer
  174. uint FIFOSampleBuffer::numSamples() const
  175. {
  176. return samplesInBuffer;
  177. }
  178. // Output samples from beginning of the sample buffer. Copies demanded number
  179. // of samples to output and removes them from the sample buffer. If there
  180. // are less than 'numsample' samples in the buffer, returns all available.
  181. //
  182. // Returns number of samples copied.
  183. uint FIFOSampleBuffer::receiveSamples(SAMPLETYPE *output, uint maxSamples)
  184. {
  185. uint num;
  186. num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples;
  187. memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num);
  188. return receiveSamples(num);
  189. }
  190. // Removes samples from the beginning of the sample buffer without copying them
  191. // anywhere. Used to reduce the number of samples in the buffer, when accessing
  192. // the sample buffer with the 'ptrBegin' function.
  193. uint FIFOSampleBuffer::receiveSamples(uint maxSamples)
  194. {
  195. if (maxSamples >= samplesInBuffer)
  196. {
  197. uint temp;
  198. temp = samplesInBuffer;
  199. samplesInBuffer = 0;
  200. return temp;
  201. }
  202. samplesInBuffer -= maxSamples;
  203. bufferPos += maxSamples;
  204. return maxSamples;
  205. }
  206. // Returns nonzero if the sample buffer is empty
  207. int FIFOSampleBuffer::isEmpty() const
  208. {
  209. return (samplesInBuffer == 0) ? 1 : 0;
  210. }
  211. // Clears the sample buffer
  212. void FIFOSampleBuffer::clear()
  213. {
  214. samplesInBuffer = 0;
  215. bufferPos = 0;
  216. }