Line data Source code
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 0 : InterpolateShannon::InterpolateShannon()
64 : {
65 0 : fract = 0;
66 0 : }
67 :
68 :
69 0 : void InterpolateShannon::resetRegisters()
70 : {
71 0 : fract = 0;
72 0 : }
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 0 : int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,
81 : const SAMPLETYPE *psrc,
82 : int &srcSamples)
83 : {
84 : int i;
85 0 : int srcSampleEnd = srcSamples - 8;
86 0 : int srcCount = 0;
87 :
88 0 : i = 0;
89 0 : while (srcCount < srcSampleEnd)
90 : {
91 : double out;
92 0 : assert(fract < 1.0);
93 :
94 0 : out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0];
95 0 : out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1];
96 0 : out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2];
97 0 : if (fract < 1e-6)
98 : {
99 0 : out += psrc[3] * _kaiser8[3]; // sinc(0) = 1
100 : }
101 : else
102 : {
103 0 : out += psrc[3] * sinc(- fract) * _kaiser8[3];
104 : }
105 0 : out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4];
106 0 : out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5];
107 0 : out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6];
108 0 : out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7];
109 :
110 0 : pdest[i] = (SAMPLETYPE)out;
111 0 : i ++;
112 :
113 : // update position fraction
114 0 : fract += rate;
115 : // update whole positions
116 0 : int whole = (int)fract;
117 0 : fract -= whole;
118 0 : psrc += whole;
119 0 : srcCount += whole;
120 : }
121 0 : srcSamples = srcCount;
122 0 : 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 0 : int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,
129 : const SAMPLETYPE *psrc,
130 : int &srcSamples)
131 : {
132 : int i;
133 0 : int srcSampleEnd = srcSamples - 8;
134 0 : int srcCount = 0;
135 :
136 0 : i = 0;
137 0 : while (srcCount < srcSampleEnd)
138 : {
139 : double out0, out1, w;
140 0 : assert(fract < 1.0);
141 :
142 0 : w = sinc(-3.0 - fract) * _kaiser8[0];
143 0 : out0 = psrc[0] * w; out1 = psrc[1] * w;
144 0 : w = sinc(-2.0 - fract) * _kaiser8[1];
145 0 : out0 += psrc[2] * w; out1 += psrc[3] * w;
146 0 : w = sinc(-1.0 - fract) * _kaiser8[2];
147 0 : out0 += psrc[4] * w; out1 += psrc[5] * w;
148 0 : w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1
149 0 : out0 += psrc[6] * w; out1 += psrc[7] * w;
150 0 : w = sinc( 1.0 - fract) * _kaiser8[4];
151 0 : out0 += psrc[8] * w; out1 += psrc[9] * w;
152 0 : w = sinc( 2.0 - fract) * _kaiser8[5];
153 0 : out0 += psrc[10] * w; out1 += psrc[11] * w;
154 0 : w = sinc( 3.0 - fract) * _kaiser8[6];
155 0 : out0 += psrc[12] * w; out1 += psrc[13] * w;
156 0 : w = sinc( 4.0 - fract) * _kaiser8[7];
157 0 : out0 += psrc[14] * w; out1 += psrc[15] * w;
158 :
159 0 : pdest[2*i] = (SAMPLETYPE)out0;
160 0 : pdest[2*i+1] = (SAMPLETYPE)out1;
161 0 : i ++;
162 :
163 : // update position fraction
164 0 : fract += rate;
165 : // update whole positions
166 0 : int whole = (int)fract;
167 0 : fract -= whole;
168 0 : psrc += 2*whole;
169 0 : srcCount += whole;
170 : }
171 0 : srcSamples = srcCount;
172 0 : 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 0 : int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,
179 : const SAMPLETYPE *psrc,
180 : int &srcSamples)
181 : {
182 : // not implemented
183 0 : assert(false);
184 : return 0;
185 : }
|