InterpolateShannon.cpp (5461B)
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 // License : 17 // 18 // SoundTouch audio processing library 19 // Copyright (c) Olli Parviainen 20 // 21 // This library is free software; you can redistribute it and/or 22 // modify it under the terms of the GNU Lesser General Public 23 // License as published by the Free Software Foundation; either 24 // version 2.1 of the License, or (at your option) any later version. 25 // 26 // This library is distributed in the hope that it will be useful, 27 // but WITHOUT ANY WARRANTY; without even the implied warranty of 28 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 // Lesser General Public License for more details. 30 // 31 // You should have received a copy of the GNU Lesser General Public 32 // License along with this library; if not, write to the Free Software 33 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 34 // 35 //////////////////////////////////////////////////////////////////////////////// 36 37 #include <math.h> 38 #include "InterpolateShannon.h" 39 #include "STTypes.h" 40 41 using namespace soundtouch; 42 43 44 /// Kaiser window with beta = 2.0 45 /// Values scaled down by 5% to avoid overflows 46 static const double _kaiser8[8] = 47 { 48 0.41778693317814, 49 0.64888025049173, 50 0.83508562409944, 51 0.93887857733412, 52 0.93887857733412, 53 0.83508562409944, 54 0.64888025049173, 55 0.41778693317814 56 }; 57 58 59 InterpolateShannon::InterpolateShannon() 60 { 61 fract = 0; 62 } 63 64 65 void InterpolateShannon::resetRegisters() 66 { 67 fract = 0; 68 } 69 70 71 #define PI 3.1415926536 72 #define sinc(x) (sin(PI * (x)) / (PI * (x))) 73 74 /// Transpose mono audio. Returns number of produced output samples, and 75 /// updates "srcSamples" to amount of consumed source samples 76 int InterpolateShannon::transposeMono(SAMPLETYPE *pdest, 77 const SAMPLETYPE *psrc, 78 int &srcSamples) 79 { 80 int i; 81 int srcSampleEnd = srcSamples - 8; 82 int srcCount = 0; 83 84 i = 0; 85 while (srcCount < srcSampleEnd) 86 { 87 double out; 88 assert(fract < 1.0); 89 90 out = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0]; 91 out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1]; 92 out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2]; 93 if (fract < 1e-6) 94 { 95 out += psrc[3] * _kaiser8[3]; // sinc(0) = 1 96 } 97 else 98 { 99 out += psrc[3] * sinc(- fract) * _kaiser8[3]; 100 } 101 out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4]; 102 out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5]; 103 out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6]; 104 out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7]; 105 106 pdest[i] = (SAMPLETYPE)out; 107 i ++; 108 109 // update position fraction 110 fract += rate; 111 // update whole positions 112 int whole = (int)fract; 113 fract -= whole; 114 psrc += whole; 115 srcCount += whole; 116 } 117 srcSamples = srcCount; 118 return i; 119 } 120 121 122 /// Transpose stereo audio. Returns number of produced output samples, and 123 /// updates "srcSamples" to amount of consumed source samples 124 int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest, 125 const SAMPLETYPE *psrc, 126 int &srcSamples) 127 { 128 int i; 129 int srcSampleEnd = srcSamples - 8; 130 int srcCount = 0; 131 132 i = 0; 133 while (srcCount < srcSampleEnd) 134 { 135 double out0, out1, w; 136 assert(fract < 1.0); 137 138 w = sinc(-3.0 - fract) * _kaiser8[0]; 139 out0 = psrc[0] * w; out1 = psrc[1] * w; 140 w = sinc(-2.0 - fract) * _kaiser8[1]; 141 out0 += psrc[2] * w; out1 += psrc[3] * w; 142 w = sinc(-1.0 - fract) * _kaiser8[2]; 143 out0 += psrc[4] * w; out1 += psrc[5] * w; 144 w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract)); // sinc(0) = 1 145 out0 += psrc[6] * w; out1 += psrc[7] * w; 146 w = sinc( 1.0 - fract) * _kaiser8[4]; 147 out0 += psrc[8] * w; out1 += psrc[9] * w; 148 w = sinc( 2.0 - fract) * _kaiser8[5]; 149 out0 += psrc[10] * w; out1 += psrc[11] * w; 150 w = sinc( 3.0 - fract) * _kaiser8[6]; 151 out0 += psrc[12] * w; out1 += psrc[13] * w; 152 w = sinc( 4.0 - fract) * _kaiser8[7]; 153 out0 += psrc[14] * w; out1 += psrc[15] * w; 154 155 pdest[2*i] = (SAMPLETYPE)out0; 156 pdest[2*i+1] = (SAMPLETYPE)out1; 157 i ++; 158 159 // update position fraction 160 fract += rate; 161 // update whole positions 162 int whole = (int)fract; 163 fract -= whole; 164 psrc += 2*whole; 165 srcCount += whole; 166 } 167 srcSamples = srcCount; 168 return i; 169 } 170 171 172 /// Transpose stereo audio. Returns number of produced output samples, and 173 /// updates "srcSamples" to amount of consumed source samples 174 int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest, 175 const SAMPLETYPE *psrc, 176 int &srcSamples) 177 { 178 // not implemented 179 assert(false); 180 return 0; 181 }