/src/mozilla-central/media/libsoundtouch/src/FIFOSampleBuffer.cpp
Line | Count | Source (jump to first uncovered line) |
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 18:53:01 +0000 (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 | | //////////////////////////////////////////////////////////////////////////////// |
45 | | |
46 | | #include <stdlib.h> |
47 | | #include <memory.h> |
48 | | #include <string.h> |
49 | | #include <assert.h> |
50 | | |
51 | | #include "FIFOSampleBuffer.h" |
52 | | |
53 | | using namespace soundtouch; |
54 | | |
55 | | // Constructor |
56 | | FIFOSampleBuffer::FIFOSampleBuffer(int numChannels) |
57 | 0 | { |
58 | 0 | assert(numChannels > 0); |
59 | 0 | sizeInBytes = 0; // reasonable initial value |
60 | 0 | buffer = NULL; |
61 | 0 | bufferUnaligned = NULL; |
62 | 0 | samplesInBuffer = 0; |
63 | 0 | bufferPos = 0; |
64 | 0 | channels = (uint)numChannels; |
65 | 0 | ensureCapacity(32); // allocate initial capacity |
66 | 0 | } |
67 | | |
68 | | |
69 | | // destructor |
70 | | FIFOSampleBuffer::~FIFOSampleBuffer() |
71 | 0 | { |
72 | 0 | delete[] bufferUnaligned; |
73 | 0 | bufferUnaligned = NULL; |
74 | 0 | buffer = NULL; |
75 | 0 | } |
76 | | |
77 | | |
78 | | // Sets number of channels, 1 = mono, 2 = stereo |
79 | | void FIFOSampleBuffer::setChannels(int numChannels) |
80 | 0 | { |
81 | 0 | uint usedBytes; |
82 | 0 |
|
83 | 0 | assert(numChannels > 0); |
84 | 0 | usedBytes = channels * samplesInBuffer; |
85 | 0 | channels = (uint)numChannels; |
86 | 0 | samplesInBuffer = usedBytes / channels; |
87 | 0 | } |
88 | | |
89 | | |
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 | 0 | { |
95 | 0 | if (buffer && bufferPos) |
96 | 0 | { |
97 | 0 | memmove(buffer, ptrBegin(), sizeof(SAMPLETYPE) * channels * samplesInBuffer); |
98 | 0 | bufferPos = 0; |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | |
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 | 0 | { |
107 | 0 | memcpy(ptrEnd(nSamples), samples, sizeof(SAMPLETYPE) * nSamples * channels); |
108 | 0 | samplesInBuffer += nSamples; |
109 | 0 | } |
110 | | |
111 | | |
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 | 0 | { |
120 | 0 | uint req; |
121 | 0 |
|
122 | 0 | req = samplesInBuffer + nSamples; |
123 | 0 | ensureCapacity(req); |
124 | 0 | samplesInBuffer += nSamples; |
125 | 0 | } |
126 | | |
127 | | |
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 | 0 | { |
142 | 0 | ensureCapacity(samplesInBuffer + slackCapacity); |
143 | 0 | return buffer + samplesInBuffer * channels; |
144 | 0 | } |
145 | | |
146 | | |
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 | 0 | { |
156 | 0 | assert(buffer); |
157 | 0 | return buffer + bufferPos * channels; |
158 | 0 | } |
159 | | |
160 | | |
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 | 0 | { |
167 | 0 | SAMPLETYPE *tempUnaligned, *temp; |
168 | 0 |
|
169 | 0 | if (capacityRequirement > getCapacity()) |
170 | 0 | { |
171 | 0 | // enlarge the buffer in 4kbyte steps (round up to next 4k boundary) |
172 | 0 | sizeInBytes = (capacityRequirement * channels * sizeof(SAMPLETYPE) + 4095) & (uint)-4096; |
173 | 0 | assert(sizeInBytes % 2 == 0); |
174 | 0 | tempUnaligned = new SAMPLETYPE[sizeInBytes / sizeof(SAMPLETYPE) + 16 / sizeof(SAMPLETYPE)]; |
175 | 0 | if (tempUnaligned == NULL) |
176 | 0 | { |
177 | 0 | ST_THROW_RT_ERROR("Couldn't allocate memory!\n"); |
178 | 0 | } |
179 | 0 | // Align the buffer to begin at 16byte cache line boundary for optimal performance |
180 | 0 | temp = (SAMPLETYPE *)SOUNDTOUCH_ALIGN_POINTER_16(tempUnaligned); |
181 | 0 | if (samplesInBuffer) |
182 | 0 | { |
183 | 0 | memcpy(temp, ptrBegin(), samplesInBuffer * channels * sizeof(SAMPLETYPE)); |
184 | 0 | } |
185 | 0 | delete[] bufferUnaligned; |
186 | 0 | buffer = temp; |
187 | 0 | bufferUnaligned = tempUnaligned; |
188 | 0 | bufferPos = 0; |
189 | 0 | } |
190 | 0 | else |
191 | 0 | { |
192 | 0 | // simply rewind the buffer (if necessary) |
193 | 0 | rewind(); |
194 | 0 | } |
195 | 0 | } |
196 | | |
197 | | |
198 | | // Returns the current buffer capacity in terms of samples |
199 | | uint FIFOSampleBuffer::getCapacity() const |
200 | 0 | { |
201 | 0 | return sizeInBytes / (channels * sizeof(SAMPLETYPE)); |
202 | 0 | } |
203 | | |
204 | | |
205 | | // Returns the number of samples currently in the buffer |
206 | | uint FIFOSampleBuffer::numSamples() const |
207 | 0 | { |
208 | 0 | return samplesInBuffer; |
209 | 0 | } |
210 | | |
211 | | |
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 | 0 | { |
219 | 0 | uint num; |
220 | 0 |
|
221 | 0 | num = (maxSamples > samplesInBuffer) ? samplesInBuffer : maxSamples; |
222 | 0 |
|
223 | 0 | memcpy(output, ptrBegin(), channels * sizeof(SAMPLETYPE) * num); |
224 | 0 | return receiveSamples(num); |
225 | 0 | } |
226 | | |
227 | | |
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 | 0 | { |
233 | 0 | if (maxSamples >= samplesInBuffer) |
234 | 0 | { |
235 | 0 | uint temp; |
236 | 0 |
|
237 | 0 | temp = samplesInBuffer; |
238 | 0 | samplesInBuffer = 0; |
239 | 0 | return temp; |
240 | 0 | } |
241 | 0 | |
242 | 0 | samplesInBuffer -= maxSamples; |
243 | 0 | bufferPos += maxSamples; |
244 | 0 |
|
245 | 0 | return maxSamples; |
246 | 0 | } |
247 | | |
248 | | |
249 | | // Returns nonzero if the sample buffer is empty |
250 | | int FIFOSampleBuffer::isEmpty() const |
251 | 0 | { |
252 | 0 | return (samplesInBuffer == 0) ? 1 : 0; |
253 | 0 | } |
254 | | |
255 | | |
256 | | // Clears the sample buffer |
257 | | void FIFOSampleBuffer::clear() |
258 | 0 | { |
259 | 0 | samplesInBuffer = 0; |
260 | 0 | bufferPos = 0; |
261 | 0 | } |
262 | | |
263 | | |
264 | | /// allow trimming (downwards) amount of samples in pipeline. |
265 | | /// Returns adjusted amount of samples |
266 | | uint FIFOSampleBuffer::adjustAmountOfSamples(uint numSamples) |
267 | 0 | { |
268 | 0 | if (numSamples < samplesInBuffer) |
269 | 0 | { |
270 | 0 | samplesInBuffer = numSamples; |
271 | 0 | } |
272 | 0 | return samplesInBuffer; |
273 | 0 | } |
274 | | |