File: | root/firefox-clang/media/libsoundtouch/src/FIRFilter.cpp |
Warning: | line 81, column 12 Value stored to 'dScaler' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //////////////////////////////////////////////////////////////////////////////// |
2 | /// |
3 | /// General FIR digital filter routines with MMX optimization. |
4 | /// |
5 | /// Notes : MMX optimized functions reside in a separate, platform-specific file, |
6 | /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' |
7 | /// |
8 | /// This source file contains OpenMP optimizations that allow speeding up the |
9 | /// corss-correlation algorithm by executing it in several threads / CPU cores |
10 | /// in parallel. See the following article link for more detailed discussion |
11 | /// about SoundTouch OpenMP optimizations: |
12 | /// http://www.softwarecoven.com/parallel-computing-in-embedded-mobile-devices |
13 | /// |
14 | /// Author : Copyright (c) Olli Parviainen |
15 | /// Author e-mail : oparviai 'at' iki.fi |
16 | /// SoundTouch WWW: http://www.surina.net/soundtouch |
17 | /// |
18 | //////////////////////////////////////////////////////////////////////////////// |
19 | // |
20 | // License : |
21 | // |
22 | // SoundTouch audio processing library |
23 | // Copyright (c) Olli Parviainen |
24 | // |
25 | // This library is free software; you can redistribute it and/or |
26 | // modify it under the terms of the GNU Lesser General Public |
27 | // License as published by the Free Software Foundation; either |
28 | // version 2.1 of the License, or (at your option) any later version. |
29 | // |
30 | // This library is distributed in the hope that it will be useful, |
31 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
32 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
33 | // Lesser General Public License for more details. |
34 | // |
35 | // You should have received a copy of the GNU Lesser General Public |
36 | // License along with this library; if not, write to the Free Software |
37 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
38 | // |
39 | //////////////////////////////////////////////////////////////////////////////// |
40 | |
41 | #include <memory.h> |
42 | #include <assert.h> |
43 | #include <math.h> |
44 | #include <stdlib.h> |
45 | #include "FIRFilter.h" |
46 | #include "cpu_detect.h" |
47 | |
48 | using namespace soundtouch; |
49 | |
50 | /***************************************************************************** |
51 | * |
52 | * Implementation of the class 'FIRFilter' |
53 | * |
54 | *****************************************************************************/ |
55 | |
56 | FIRFilter::FIRFilter() |
57 | { |
58 | resultDivFactor = 0; |
59 | resultDivider = 0; |
60 | length = 0; |
61 | lengthDiv8 = 0; |
62 | filterCoeffs = NULL__null; |
63 | filterCoeffsStereo = NULL__null; |
64 | } |
65 | |
66 | |
67 | FIRFilter::~FIRFilter() |
68 | { |
69 | delete[] filterCoeffs; |
70 | delete[] filterCoeffsStereo; |
71 | } |
72 | |
73 | |
74 | // Usual C-version of the filter routine for stereo sound |
75 | uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const |
76 | { |
77 | int j, end; |
78 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES1 |
79 | // when using floating point samples, use a scaler instead of a divider |
80 | // because division is much slower operation than multiplying. |
81 | double dScaler = 1.0 / (double)resultDivider; |
Value stored to 'dScaler' during its initialization is never read | |
82 | #endif |
83 | // hint compiler autovectorization that loop length is divisible by 8 |
84 | int ilength = length & -8; |
85 | |
86 | assert((length != 0) && (length == ilength) && (src != NULL) && (dest != NULL) && (filterCoeffs != NULL))(static_cast <bool> ((length != 0) && (length == ilength) && (src != __null) && (dest != __null ) && (filterCoeffs != __null)) ? void (0) : __assert_fail ("(length != 0) && (length == ilength) && (src != NULL) && (dest != NULL) && (filterCoeffs != NULL)" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ )); |
87 | |
88 | end = 2 * (numSamples - ilength); |
89 | |
90 | #pragma omp parallel for |
91 | for (j = 0; j < end; j += 2) |
92 | { |
93 | const SAMPLETYPE *ptr; |
94 | LONG_SAMPLETYPE suml, sumr; |
95 | |
96 | suml = sumr = 0; |
97 | ptr = src + j; |
98 | |
99 | for (int i = 0; i < ilength; i ++) |
100 | { |
101 | suml += ptr[2 * i] * filterCoeffsStereo[2 * i]; |
102 | sumr += ptr[2 * i + 1] * filterCoeffsStereo[2 * i + 1]; |
103 | } |
104 | |
105 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES |
106 | suml >>= resultDivFactor; |
107 | sumr >>= resultDivFactor; |
108 | // saturate to 16 bit integer limits |
109 | suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml; |
110 | // saturate to 16 bit integer limits |
111 | sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr; |
112 | #endif // SOUNDTOUCH_INTEGER_SAMPLES |
113 | dest[j] = (SAMPLETYPE)suml; |
114 | dest[j + 1] = (SAMPLETYPE)sumr; |
115 | } |
116 | return numSamples - ilength; |
117 | } |
118 | |
119 | |
120 | // Usual C-version of the filter routine for mono sound |
121 | uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const |
122 | { |
123 | int j, end; |
124 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES1 |
125 | // when using floating point samples, use a scaler instead of a divider |
126 | // because division is much slower operation than multiplying. |
127 | double dScaler = 1.0 / (double)resultDivider; |
128 | #endif |
129 | |
130 | // hint compiler autovectorization that loop length is divisible by 8 |
131 | int ilength = length & -8; |
132 | |
133 | assert(ilength != 0)(static_cast <bool> (ilength != 0) ? void (0) : __assert_fail ("ilength != 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
134 | |
135 | end = numSamples - ilength; |
136 | #pragma omp parallel for |
137 | for (j = 0; j < end; j ++) |
138 | { |
139 | const SAMPLETYPE *pSrc = src + j; |
140 | LONG_SAMPLETYPE sum; |
141 | int i; |
142 | |
143 | sum = 0; |
144 | for (i = 0; i < ilength; i ++) |
145 | { |
146 | sum += pSrc[i] * filterCoeffs[i]; |
147 | } |
148 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES |
149 | sum >>= resultDivFactor; |
150 | // saturate to 16 bit integer limits |
151 | sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum; |
152 | #endif // SOUNDTOUCH_INTEGER_SAMPLES |
153 | dest[j] = (SAMPLETYPE)sum; |
154 | } |
155 | return end; |
156 | } |
157 | |
158 | |
159 | uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) |
160 | { |
161 | int j, end; |
162 | |
163 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES1 |
164 | // when using floating point samples, use a scaler instead of a divider |
165 | // because division is much slower operation than multiplying. |
166 | double dScaler = 1.0 / (double)resultDivider; |
167 | #endif |
168 | |
169 | assert(length != 0)(static_cast <bool> (length != 0) ? void (0) : __assert_fail ("length != 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
170 | assert(src != NULL)(static_cast <bool> (src != __null) ? void (0) : __assert_fail ("src != NULL", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
171 | assert(dest != NULL)(static_cast <bool> (dest != __null) ? void (0) : __assert_fail ("dest != NULL", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
172 | assert(filterCoeffs != NULL)(static_cast <bool> (filterCoeffs != __null) ? void (0) : __assert_fail ("filterCoeffs != NULL", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
173 | assert(numChannels < 16)(static_cast <bool> (numChannels < 16) ? void (0) : __assert_fail ("numChannels < 16", __builtin_FILE (), __builtin_LINE () , __extension__ __PRETTY_FUNCTION__)); |
174 | |
175 | // hint compiler autovectorization that loop length is divisible by 8 |
176 | int ilength = length & -8; |
177 | |
178 | end = numChannels * (numSamples - ilength); |
179 | |
180 | #pragma omp parallel for |
181 | for (j = 0; j < end; j += numChannels) |
182 | { |
183 | const SAMPLETYPE *ptr; |
184 | LONG_SAMPLETYPE sums[16]; |
185 | uint c; |
186 | int i; |
187 | |
188 | for (c = 0; c < numChannels; c ++) |
189 | { |
190 | sums[c] = 0; |
191 | } |
192 | |
193 | ptr = src + j; |
194 | |
195 | for (i = 0; i < ilength; i ++) |
196 | { |
197 | SAMPLETYPE coef=filterCoeffs[i]; |
198 | for (c = 0; c < numChannels; c ++) |
199 | { |
200 | sums[c] += ptr[0] * coef; |
201 | ptr ++; |
202 | } |
203 | } |
204 | |
205 | for (c = 0; c < numChannels; c ++) |
206 | { |
207 | #ifdef SOUNDTOUCH_INTEGER_SAMPLES |
208 | sums[c] >>= resultDivFactor; |
209 | #endif // SOUNDTOUCH_INTEGER_SAMPLES |
210 | dest[j+c] = (SAMPLETYPE)sums[c]; |
211 | } |
212 | } |
213 | return numSamples - ilength; |
214 | } |
215 | |
216 | |
217 | // Set filter coeffiecients and length. |
218 | // |
219 | // Throws an exception if filter length isn't divisible by 8 |
220 | void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor) |
221 | { |
222 | assert(newLength > 0)(static_cast <bool> (newLength > 0) ? void (0) : __assert_fail ("newLength > 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
223 | if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8"){(static_cast <bool> ((const char *)"FIR filter length not divisible by 8" ) ? void (0) : __assert_fail ("(const char *)\"FIR filter length not divisible by 8\"" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ ));}; |
224 | |
225 | #ifdef SOUNDTOUCH_FLOAT_SAMPLES1 |
226 | // scale coefficients already here if using floating samples |
227 | double scale = 1.0 / resultDivider; |
228 | #else |
229 | short scale = 1; |
230 | #endif |
231 | |
232 | lengthDiv8 = newLength / 8; |
233 | length = lengthDiv8 * 8; |
234 | assert(length == newLength)(static_cast <bool> (length == newLength) ? void (0) : __assert_fail ("length == newLength", __builtin_FILE (), __builtin_LINE () , __extension__ __PRETTY_FUNCTION__)); |
235 | |
236 | resultDivFactor = uResultDivFactor; |
237 | resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor); |
238 | |
239 | delete[] filterCoeffs; |
240 | filterCoeffs = new SAMPLETYPE[length]; |
241 | delete[] filterCoeffsStereo; |
242 | filterCoeffsStereo = new SAMPLETYPE[length*2]; |
243 | for (uint i = 0; i < length; i ++) |
244 | { |
245 | filterCoeffs[i] = (SAMPLETYPE)(coeffs[i] * scale); |
246 | // create also stereo set of filter coefficients: this allows compiler |
247 | // to autovectorize filter evaluation much more efficiently |
248 | filterCoeffsStereo[2 * i] = (SAMPLETYPE)(coeffs[i] * scale); |
249 | filterCoeffsStereo[2 * i + 1] = (SAMPLETYPE)(coeffs[i] * scale); |
250 | } |
251 | } |
252 | |
253 | |
254 | uint FIRFilter::getLength() const |
255 | { |
256 | return length; |
257 | } |
258 | |
259 | |
260 | // Applies the filter to the given sequence of samples. |
261 | // |
262 | // Note : The amount of outputted samples is by value of 'filter_length' |
263 | // smaller than the amount of input samples. |
264 | uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) |
265 | { |
266 | assert(length > 0)(static_cast <bool> (length > 0) ? void (0) : __assert_fail ("length > 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
267 | assert(lengthDiv8 * 8 == length)(static_cast <bool> (lengthDiv8 * 8 == length) ? void ( 0) : __assert_fail ("lengthDiv8 * 8 == length", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
268 | |
269 | if (numSamples < length) return 0; |
270 | |
271 | #ifndef USE_MULTICH_ALWAYS |
272 | if (numChannels == 1) |
273 | { |
274 | return evaluateFilterMono(dest, src, numSamples); |
275 | } |
276 | else if (numChannels == 2) |
277 | { |
278 | return evaluateFilterStereo(dest, src, numSamples); |
279 | } |
280 | else |
281 | #endif // USE_MULTICH_ALWAYS |
282 | { |
283 | assert(numChannels > 0)(static_cast <bool> (numChannels > 0) ? void (0) : __assert_fail ("numChannels > 0", __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__)); |
284 | return evaluateFilterMulti(dest, src, numSamples, numChannels); |
285 | } |
286 | } |
287 | |
288 | |
289 | // Operator 'new' is overloaded so that it automatically creates a suitable instance |
290 | // depending on if we've a MMX-capable CPU available or not. |
291 | void * FIRFilter::operator new(size_t s) |
292 | { |
293 | // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead! |
294 | ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!"){(static_cast <bool> ((const char *)"Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!" ) ? void (0) : __assert_fail ("(const char *)\"Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!\"" , __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__ ));}; |
295 | return newInstance(); |
296 | } |
297 | |
298 | |
299 | FIRFilter * FIRFilter::newInstance() |
300 | { |
301 | #if defined(SOUNDTOUCH_ALLOW_MMX) || defined(SOUNDTOUCH_ALLOW_SSE1) |
302 | uint uExtensions; |
303 | |
304 | uExtensions = detectCPUextensions(); |
305 | #endif |
306 | |
307 | // Check if MMX/SSE instruction set extensions supported by CPU |
308 | |
309 | #ifdef SOUNDTOUCH_ALLOW_MMX |
310 | // MMX routines available only with integer sample types |
311 | if (uExtensions & SUPPORT_MMX0x0001) |
312 | { |
313 | return ::new FIRFilterMMX; |
314 | } |
315 | else |
316 | #endif // SOUNDTOUCH_ALLOW_MMX |
317 | |
318 | #ifdef SOUNDTOUCH_ALLOW_SSE1 |
319 | if (uExtensions & SUPPORT_SSE0x0008) |
320 | { |
321 | // SSE support |
322 | return ::new FIRFilterSSE; |
323 | } |
324 | else |
325 | #endif // SOUNDTOUCH_ALLOW_SSE |
326 | |
327 | { |
328 | // ISA optimizations not supported, use plain C version |
329 | return ::new FIRFilter; |
330 | } |
331 | } |