media/libsoundtouch/src/InterpolateShannon.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial