|
1 //////////////////////////////////////////////////////////////////////////////// |
|
2 /// |
|
3 /// Sample interpolation routine using 8-tap band-limited Shannon interpolation |
|
4 /// with kaiser window. |
|
5 /// |
|
6 /// Notice. This algorithm is remarkably much heavier than linear or cubic |
|
7 /// interpolation, and not remarkably better than cubic algorithm. Thus mostly |
|
8 /// for experimental purposes |
|
9 /// |
|
10 /// Author : Copyright (c) Olli Parviainen |
|
11 /// Author e-mail : oparviai 'at' iki.fi |
|
12 /// SoundTouch WWW: http://www.surina.net/soundtouch |
|
13 /// |
|
14 //////////////////////////////////////////////////////////////////////////////// |
|
15 // |
|
16 // $Id: InterpolateShannon.cpp 195 2014-04-06 15:57:21Z oparviai $ |
|
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 <math.h> |
|
42 #include "InterpolateShannon.h" |
|
43 #include "STTypes.h" |
|
44 |
|
45 using namespace soundtouch; |
|
46 |
|
47 |
|
48 /// Kaiser window with beta = 2.0 |
|
49 /// Values scaled down by 5% to avoid overflows |
|
50 static const double _kaiser8[8] = |
|
51 { |
|
52 0.41778693317814, |
|
53 0.64888025049173, |
|
54 0.83508562409944, |
|
55 0.93887857733412, |
|
56 0.93887857733412, |
|
57 0.83508562409944, |
|
58 0.64888025049173, |
|
59 0.41778693317814 |
|
60 }; |
|
61 |
|
62 |
|
63 InterpolateShannon::InterpolateShannon() |
|
64 { |
|
65 fract = 0; |
|
66 } |
|
67 |
|
68 |
|
69 void InterpolateShannon::resetRegisters() |
|
70 { |
|
71 fract = 0; |
|
72 } |
|
73 |
|
74 |
|
75 #define PI 3.1415926536 |
|
76 #define sinc(x) (sin(PI * (x)) / (PI * (x))) |
|
77 |
|
78 /// Transpose mono audio. Returns number of produced output samples, and |
|
79 /// updates "srcSamples" to amount of consumed source samples |
|
80 int InterpolateShannon::transposeMono(SAMPLETYPE *pdest, |
|
81 const SAMPLETYPE *psrc, |
|
82 int &srcSamples) |
|
83 { |
|
84 int i; |
|
85 int srcSampleEnd = srcSamples - 8; |
|
86 int srcCount = 0; |
|
87 |
|
88 i = 0; |
|
89 while (srcCount < srcSampleEnd) |
|
90 { |
|
91 double out; |
|
92 assert(fract < 1.0); |
|
93 |
|
94 out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0]; |
|
95 out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1]; |
|
96 out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2]; |
|
97 if (fract < 1e-6) |
|
98 { |
|
99 out += psrc[3] * _kaiser8[3]; // sinc(0) = 1 |
|
100 } |
|
101 else |
|
102 { |
|
103 out += psrc[3] * sinc(- fract) * _kaiser8[3]; |
|
104 } |
|
105 out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4]; |
|
106 out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5]; |
|
107 out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6]; |
|
108 out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7]; |
|
109 |
|
110 pdest[i] = (SAMPLETYPE)out; |
|
111 i ++; |
|
112 |
|
113 // update position fraction |
|
114 fract += rate; |
|
115 // update whole positions |
|
116 int whole = (int)fract; |
|
117 fract -= whole; |
|
118 psrc += whole; |
|
119 srcCount += whole; |
|
120 } |
|
121 srcSamples = srcCount; |
|
122 return i; |
|
123 } |
|
124 |
|
125 |
|
126 /// Transpose stereo audio. Returns number of produced output samples, and |
|
127 /// updates "srcSamples" to amount of consumed source samples |
|
128 int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest, |
|
129 const SAMPLETYPE *psrc, |
|
130 int &srcSamples) |
|
131 { |
|
132 int i; |
|
133 int srcSampleEnd = srcSamples - 8; |
|
134 int srcCount = 0; |
|
135 |
|
136 i = 0; |
|
137 while (srcCount < srcSampleEnd) |
|
138 { |
|
139 double out0, out1, w; |
|
140 assert(fract < 1.0); |
|
141 |
|
142 w = sinc(-3.0 - fract) * _kaiser8[0]; |
|
143 out0 = psrc[0] * w; out1 = psrc[1] * w; |
|
144 w = sinc(-2.0 - fract) * _kaiser8[1]; |
|
145 out0 += psrc[2] * w; out1 += psrc[3] * w; |
|
146 w = sinc(-1.0 - fract) * _kaiser8[2]; |
|
147 out0 += psrc[4] * w; out1 += psrc[5] * w; |
|
148 w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1 |
|
149 out0 += psrc[6] * w; out1 += psrc[7] * w; |
|
150 w = sinc( 1.0 - fract) * _kaiser8[4]; |
|
151 out0 += psrc[8] * w; out1 += psrc[9] * w; |
|
152 w = sinc( 2.0 - fract) * _kaiser8[5]; |
|
153 out0 += psrc[10] * w; out1 += psrc[11] * w; |
|
154 w = sinc( 3.0 - fract) * _kaiser8[6]; |
|
155 out0 += psrc[12] * w; out1 += psrc[13] * w; |
|
156 w = sinc( 4.0 - fract) * _kaiser8[7]; |
|
157 out0 += psrc[14] * w; out1 += psrc[15] * w; |
|
158 |
|
159 pdest[2*i] = (SAMPLETYPE)out0; |
|
160 pdest[2*i+1] = (SAMPLETYPE)out1; |
|
161 i ++; |
|
162 |
|
163 // update position fraction |
|
164 fract += rate; |
|
165 // update whole positions |
|
166 int whole = (int)fract; |
|
167 fract -= whole; |
|
168 psrc += 2*whole; |
|
169 srcCount += whole; |
|
170 } |
|
171 srcSamples = srcCount; |
|
172 return i; |
|
173 } |
|
174 |
|
175 |
|
176 /// Transpose stereo audio. Returns number of produced output samples, and |
|
177 /// updates "srcSamples" to amount of consumed source samples |
|
178 int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest, |
|
179 const SAMPLETYPE *psrc, |
|
180 int &srcSamples) |
|
181 { |
|
182 // not implemented |
|
183 assert(false); |
|
184 return 0; |
|
185 } |