mirror of https://github.com/stenzek/duckstation
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
| 
								 
											3 years ago
										 
									 | 
							
								////////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								/// 
							 | 
						||
| 
								 | 
							
								/// 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;
							 | 
						||
| 
								 | 
							
								}
							 |