mirror of
				https://github.com/RetroDECK/Duckstation.git
				synced 2025-04-10 19:15:14 +00:00 
			
		
		
		
	
		
			
	
	
		
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | ////////////////////////////////////////////////////////////////////////////////
 | ||
|  | /// 
 | ||
|  | /// Sample interpolation routine using 8-tap band-limited Shannon interpolation 
 | ||
|  | /// with kaiser window.
 | ||
|  | ///
 | ||
|  | /// Notice. This algorithm is remarkably much heavier than linear or cubic
 | ||
|  | /// interpolation, and not remarkably better than cubic algorithm. Thus mostly
 | ||
|  | /// for experimental purposes
 | ||
|  | ///
 | ||
|  | /// Author        : Copyright (c) Olli Parviainen
 | ||
|  | /// Author e-mail : oparviai 'at' iki.fi
 | ||
|  | /// SoundTouch WWW: http://www.surina.net/soundtouch
 | ||
|  | ///
 | ||
|  | ////////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | // License :
 | ||
|  | //
 | ||
|  | //  SoundTouch audio processing library
 | ||
|  | //  Copyright (c) Olli Parviainen
 | ||
|  | //
 | ||
|  | //  This library is free software; you can redistribute it and/or
 | ||
|  | //  modify it under the terms of the GNU Lesser General Public
 | ||
|  | //  License as published by the Free Software Foundation; either
 | ||
|  | //  version 2.1 of the License, or (at your option) any later version.
 | ||
|  | //
 | ||
|  | //  This library is distributed in the hope that it will be useful,
 | ||
|  | //  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|  | //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | ||
|  | //  Lesser General Public License for more details.
 | ||
|  | //
 | ||
|  | //  You should have received a copy of the GNU Lesser General Public
 | ||
|  | //  License along with this library; if not, write to the Free Software
 | ||
|  | //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | ||
|  | //
 | ||
|  | ////////////////////////////////////////////////////////////////////////////////
 | ||
|  | 
 | ||
|  | #include <math.h>
 | ||
|  | #include "InterpolateShannon.h"
 | ||
|  | #include "STTypes.h"
 | ||
|  | 
 | ||
|  | using namespace soundtouch; | ||
|  | 
 | ||
|  | 
 | ||
|  | /// Kaiser window with beta = 2.0
 | ||
|  | /// Values scaled down by 5% to avoid overflows
 | ||
|  | static const double _kaiser8[8] =  | ||
|  | { | ||
|  |    0.41778693317814, | ||
|  |    0.64888025049173, | ||
|  |    0.83508562409944, | ||
|  |    0.93887857733412, | ||
|  |    0.93887857733412, | ||
|  |    0.83508562409944, | ||
|  |    0.64888025049173, | ||
|  |    0.41778693317814 | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | InterpolateShannon::InterpolateShannon() | ||
|  | { | ||
|  |     fract = 0; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | void InterpolateShannon::resetRegisters() | ||
|  | { | ||
|  |     fract = 0; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | #define PI 3.1415926536
 | ||
|  | #define sinc(x) (sin(PI * (x)) / (PI * (x)))
 | ||
|  | 
 | ||
|  | /// Transpose mono audio. Returns number of produced output samples, and 
 | ||
|  | /// updates "srcSamples" to amount of consumed source samples
 | ||
|  | int InterpolateShannon::transposeMono(SAMPLETYPE *pdest,  | ||
|  |                     const SAMPLETYPE *psrc,  | ||
|  |                     int &srcSamples) | ||
|  | { | ||
|  |     int i; | ||
|  |     int srcSampleEnd = srcSamples - 8; | ||
|  |     int srcCount = 0; | ||
|  | 
 | ||
|  |     i = 0; | ||
|  |     while (srcCount < srcSampleEnd) | ||
|  |     { | ||
|  |         double out; | ||
|  |         assert(fract < 1.0); | ||
|  | 
 | ||
|  |         out  = psrc[0] * sinc(-3.0 - fract) * _kaiser8[0]; | ||
|  |         out += psrc[1] * sinc(-2.0 - fract) * _kaiser8[1]; | ||
|  |         out += psrc[2] * sinc(-1.0 - fract) * _kaiser8[2]; | ||
|  |         if (fract < 1e-6) | ||
|  |         { | ||
|  |             out += psrc[3] * _kaiser8[3];     // sinc(0) = 1
 | ||
|  |         } | ||
|  |         else | ||
|  |         { | ||
|  |             out += psrc[3] * sinc(- fract) * _kaiser8[3]; | ||
|  |         } | ||
|  |         out += psrc[4] * sinc( 1.0 - fract) * _kaiser8[4]; | ||
|  |         out += psrc[5] * sinc( 2.0 - fract) * _kaiser8[5]; | ||
|  |         out += psrc[6] * sinc( 3.0 - fract) * _kaiser8[6]; | ||
|  |         out += psrc[7] * sinc( 4.0 - fract) * _kaiser8[7]; | ||
|  | 
 | ||
|  |         pdest[i] = (SAMPLETYPE)out; | ||
|  |         i ++; | ||
|  | 
 | ||
|  |         // update position fraction
 | ||
|  |         fract += rate; | ||
|  |         // update whole positions
 | ||
|  |         int whole = (int)fract; | ||
|  |         fract -= whole; | ||
|  |         psrc += whole; | ||
|  |         srcCount += whole; | ||
|  |     } | ||
|  |     srcSamples = srcCount; | ||
|  |     return i; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /// Transpose stereo audio. Returns number of produced output samples, and 
 | ||
|  | /// updates "srcSamples" to amount of consumed source samples
 | ||
|  | int InterpolateShannon::transposeStereo(SAMPLETYPE *pdest,  | ||
|  |                     const SAMPLETYPE *psrc,  | ||
|  |                     int &srcSamples) | ||
|  | { | ||
|  |     int i; | ||
|  |     int srcSampleEnd = srcSamples - 8; | ||
|  |     int srcCount = 0; | ||
|  | 
 | ||
|  |     i = 0; | ||
|  |     while (srcCount < srcSampleEnd) | ||
|  |     { | ||
|  |         double out0, out1, w; | ||
|  |         assert(fract < 1.0); | ||
|  | 
 | ||
|  |         w = sinc(-3.0 - fract) * _kaiser8[0]; | ||
|  |         out0 = psrc[0] * w; out1 = psrc[1] * w; | ||
|  |         w = sinc(-2.0 - fract) * _kaiser8[1]; | ||
|  |         out0 += psrc[2] * w; out1 += psrc[3] * w; | ||
|  |         w = sinc(-1.0 - fract) * _kaiser8[2]; | ||
|  |         out0 += psrc[4] * w; out1 += psrc[5] * w; | ||
|  |         w = _kaiser8[3] * ((fract < 1e-5) ? 1.0 : sinc(- fract));   // sinc(0) = 1
 | ||
|  |         out0 += psrc[6] * w; out1 += psrc[7] * w; | ||
|  |         w = sinc( 1.0 - fract) * _kaiser8[4]; | ||
|  |         out0 += psrc[8] * w; out1 += psrc[9] * w; | ||
|  |         w = sinc( 2.0 - fract) * _kaiser8[5]; | ||
|  |         out0 += psrc[10] * w; out1 += psrc[11] * w; | ||
|  |         w = sinc( 3.0 - fract) * _kaiser8[6]; | ||
|  |         out0 += psrc[12] * w; out1 += psrc[13] * w; | ||
|  |         w = sinc( 4.0 - fract) * _kaiser8[7]; | ||
|  |         out0 += psrc[14] * w; out1 += psrc[15] * w; | ||
|  | 
 | ||
|  |         pdest[2*i]   = (SAMPLETYPE)out0; | ||
|  |         pdest[2*i+1] = (SAMPLETYPE)out1; | ||
|  |         i ++; | ||
|  | 
 | ||
|  |         // update position fraction
 | ||
|  |         fract += rate; | ||
|  |         // update whole positions
 | ||
|  |         int whole = (int)fract; | ||
|  |         fract -= whole; | ||
|  |         psrc += 2*whole; | ||
|  |         srcCount += whole; | ||
|  |     } | ||
|  |     srcSamples = srcCount; | ||
|  |     return i; | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /// Transpose stereo audio. Returns number of produced output samples, and 
 | ||
|  | /// updates "srcSamples" to amount of consumed source samples
 | ||
|  | int InterpolateShannon::transposeMulti(SAMPLETYPE *pdest,  | ||
|  |                     const SAMPLETYPE *psrc,  | ||
|  |                     int &srcSamples) | ||
|  | { | ||
|  |     // not implemented
 | ||
|  |     assert(false); | ||
|  |     return 0; | ||
|  | } |