/[pcsx2_0.9.7]/trunk/3rdparty/SoundTouch/FIRFilter.cpp
ViewVC logotype

Contents of /trunk/3rdparty/SoundTouch/FIRFilter.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 4 months ago) by william
File size: 8106 byte(s)
exported r3113 from ./upstream/trunk
1 ////////////////////////////////////////////////////////////////////////////////
2 ///
3 /// General FIR digital filter routines with MMX optimization.
4 ///
5 /// Note : MMX optimized functions reside in a separate, platform-specific file,
6 /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
7 ///
8 /// Author : Copyright (c) Olli Parviainen
9 /// Author e-mail : oparviai 'at' iki.fi
10 /// SoundTouch WWW: http://www.surina.net/soundtouch
11 ///
12 ////////////////////////////////////////////////////////////////////////////////
13 //
14 // Last changed : $Date: 2009-02-25 19:13:51 +0200 (Wed, 25 Feb 2009) $
15 // File revision : $Revision: 4 $
16 //
17 // $Id: FIRFilter.cpp 67 2009-02-25 17:13:51Z oparviai $
18 //
19 ////////////////////////////////////////////////////////////////////////////////
20 //
21 // License :
22 //
23 // SoundTouch audio processing library
24 // Copyright (c) Olli Parviainen
25 //
26 // This library is free software; you can redistribute it and/or
27 // modify it under the terms of the GNU Lesser General Public
28 // License as published by the Free Software Foundation; either
29 // version 2.1 of the License, or (at your option) any later version.
30 //
31 // This library is distributed in the hope that it will be useful,
32 // but WITHOUT ANY WARRANTY; without even the implied warranty of
33 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 // Lesser General Public License for more details.
35 //
36 // You should have received a copy of the GNU Lesser General Public
37 // License along with this library; if not, write to the Free Software
38 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 //
40 ////////////////////////////////////////////////////////////////////////////////
41
42 #include <memory.h>
43 #include <assert.h>
44 #include <math.h>
45 #include <stdlib.h>
46 #include <stdexcept>
47 #include "FIRFilter.h"
48 #include "cpu_detect.h"
49
50 using namespace soundtouch;
51
52 /*****************************************************************************
53 *
54 * Implementation of the class 'FIRFilter'
55 *
56 *****************************************************************************/
57
58 FIRFilter::FIRFilter()
59 {
60 resultDivFactor = 0;
61 resultDivider = 0;
62 length = 0;
63 lengthDiv8 = 0;
64 filterCoeffs = NULL;
65 }
66
67
68 FIRFilter::~FIRFilter()
69 {
70 delete[] filterCoeffs;
71 }
72
73 // Usual C-version of the filter routine for stereo sound
74 uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
75 {
76 uint i, j, end;
77 LONG_SAMPLETYPE suml, sumr;
78 #ifdef FLOAT_SAMPLES
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;
82 #endif
83
84 assert(length != 0);
85 assert(src != NULL);
86 assert(dest != NULL);
87 assert(filterCoeffs != NULL);
88
89 end = 2 * (numSamples - length);
90
91 for (j = 0; j < end; j += 2)
92 {
93 const SAMPLETYPE *ptr;
94
95 suml = sumr = 0;
96 ptr = src + j;
97
98 for (i = 0; i < length; i += 4)
99 {
100 // loop is unrolled by factor of 4 here for efficiency
101 suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
102 ptr[2 * i + 2] * filterCoeffs[i + 1] +
103 ptr[2 * i + 4] * filterCoeffs[i + 2] +
104 ptr[2 * i + 6] * filterCoeffs[i + 3];
105 sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
106 ptr[2 * i + 3] * filterCoeffs[i + 1] +
107 ptr[2 * i + 5] * filterCoeffs[i + 2] +
108 ptr[2 * i + 7] * filterCoeffs[i + 3];
109 }
110
111 #ifdef INTEGER_SAMPLES
112 suml >>= resultDivFactor;
113 sumr >>= resultDivFactor;
114 // saturate to 16 bit integer limits
115 suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
116 // saturate to 16 bit integer limits
117 sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
118 #else
119 suml *= dScaler;
120 sumr *= dScaler;
121 #endif // INTEGER_SAMPLES
122 dest[j] = (SAMPLETYPE)suml;
123 dest[j + 1] = (SAMPLETYPE)sumr;
124 }
125 return numSamples - length;
126 }
127
128
129
130
131 // Usual C-version of the filter routine for mono sound
132 uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
133 {
134 uint i, j, end;
135 LONG_SAMPLETYPE sum;
136 #ifdef FLOAT_SAMPLES
137 // when using floating point samples, use a scaler instead of a divider
138 // because division is much slower operation than multiplying.
139 double dScaler = 1.0 / (double)resultDivider;
140 #endif
141
142
143 assert(length != 0);
144
145 end = numSamples - length;
146 for (j = 0; j < end; j ++)
147 {
148 sum = 0;
149 for (i = 0; i < length; i += 4)
150 {
151 // loop is unrolled by factor of 4 here for efficiency
152 sum += src[i + 0] * filterCoeffs[i + 0] +
153 src[i + 1] * filterCoeffs[i + 1] +
154 src[i + 2] * filterCoeffs[i + 2] +
155 src[i + 3] * filterCoeffs[i + 3];
156 }
157 #ifdef INTEGER_SAMPLES
158 sum >>= resultDivFactor;
159 // saturate to 16 bit integer limits
160 sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
161 #else
162 sum *= dScaler;
163 #endif // INTEGER_SAMPLES
164 dest[j] = (SAMPLETYPE)sum;
165 src ++;
166 }
167 return end;
168 }
169
170
171 // Set filter coeffiecients and length.
172 //
173 // Throws an exception if filter length isn't divisible by 8
174 void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
175 {
176 assert(newLength > 0);
177 if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8");
178
179 lengthDiv8 = newLength / 8;
180 length = lengthDiv8 * 8;
181 assert(length == newLength);
182
183 resultDivFactor = uResultDivFactor;
184 resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
185
186 delete[] filterCoeffs;
187 filterCoeffs = new SAMPLETYPE[length];
188 memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
189 }
190
191
192 uint FIRFilter::getLength() const
193 {
194 return length;
195 }
196
197
198
199 // Applies the filter to the given sequence of samples.
200 //
201 // Note : The amount of outputted samples is by value of 'filter_length'
202 // smaller than the amount of input samples.
203 uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
204 {
205 assert(numChannels == 1 || numChannels == 2);
206
207 assert(length > 0);
208 assert(lengthDiv8 * 8 == length);
209 if (numSamples < length) return 0;
210 if (numChannels == 2)
211 {
212 return evaluateFilterStereo(dest, src, numSamples);
213 } else {
214 return evaluateFilterMono(dest, src, numSamples);
215 }
216 }
217
218
219
220 // Operator 'new' is overloaded so that it automatically creates a suitable instance
221 // depending on if we've a MMX-capable CPU available or not.
222 void * FIRFilter::operator new(size_t s)
223 {
224 // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
225 throw std::runtime_error("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
226 return NULL;
227 }
228
229
230 FIRFilter * FIRFilter::newInstance()
231 {
232 uint uExtensions;
233
234 uExtensions = detectCPUextensions();
235
236 // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
237
238 #ifdef ALLOW_MMX
239 // MMX routines available only with integer sample types
240 if (uExtensions & SUPPORT_MMX)
241 {
242 return ::new FIRFilterMMX;
243 }
244 else
245 #endif // ALLOW_MMX
246
247 #ifdef ALLOW_SSE
248 if (uExtensions & SUPPORT_SSE)
249 {
250 // SSE support
251 return ::new FIRFilterSSE;
252 }
253 else
254 #endif // ALLOW_SSE
255
256 #ifdef ALLOW_3DNOW
257 if (uExtensions & SUPPORT_3DNOW)
258 {
259 // 3DNow! support
260 return ::new FIRFilter3DNow;
261 }
262 else
263 #endif // ALLOW_3DNOW
264
265 {
266 // ISA optimizations not supported, use plain C version
267 return ::new FIRFilter;
268 }
269 }

  ViewVC Help
Powered by ViewVC 1.1.22