Audio interpolation (Catmull-Rom/Cubic Hermite Spline)
Matlab example for Cubic Hermite Spline audio interpolation for sample-rate conversion or variable-speed playback.
It is computationally efficient and audio quality is good.
% *****************************************************************
% Audio interpolation using Cubic Hermite Spline (Catmull-Rom)
%
% The audio file samples describe a continuous-waveform.
% The task is to interpolate between samples, for example in sample rate
% conversion or variable-speed playback.
% The cubic spline approach is one particular trade-off between
% quality and efficiency.
%
% For an efficient C-implementation, refer to fluid_rvoice_dsp.c
% in the fluidsynth project on sourceforge.
% Based on work by Olli Niemitalo:
% http://yehar.com/blog/wp-content/uploads/2009/08/deip.pdf page 11
% ******************************************************************
% build coefficient matrix
% ******************************************************************
% ideally, the interpolation coefficients would be recalculated for any possible
% value of ptrFrac below.
% example input file: http://www.elisanet.fi/mnentwig/webroot/common/in.wav
% Note: This example is written for clarity, not speed.
nPoly=
128;
x=
((0:nPoly-
1)/nPoly
)';
% column vector
c1=
(x .*
(-
0.5 + x .*
(1 -
0.5 .* x
)));
c2=
(1.0 + x .* x .*
(1.5 .* x -
2.5));
c3=
(x .*
(0.5 + x .*
(2.0 -
1.5 .* x
)));
c4=
(0.5 .* x .* x .*
(x -
1.0));
% ******************************************************************
% load input data
% ******************************************************************
[y, fs, bits
]=
wavread('in.wav');
[nSamples, nChan
]=
size(y
);
inputdata=transpose
(y
(:,
1));
% first channel if stereo
% prepare output data storage
outIndex=
1; outputData=
[]; nAlloc=
0;
% ******************************************************************
% "ptr" indicates a position in the input data.
% Loop through the whole range until end-of-data.
% ******************************************************************
ptr=
2;
while ptr < nSamples-
2
% "rate" determines the number of input samples per output sample
% rate=1.1; % faster constant-speed playback
% variable playback speed (arbitrary example)
rate=
1+
0.3*
sin(outIndex/
40000);;
% ******************************************************************
% Interpolate samples
% ******************************************************************
% ptr is the index into the input data, needed for the next output sample.
% Usually, it lies betwen points, for example ptr=1234.56
% integer part (1234)
ptrBase=
floor(ptr
);
% fractional part [0..1[, for example 0.56
ptrFrac=ptr-ptrBase;
% look up the filter for the fractional part
fIndex=
floor(ptrFrac*nPoly
)+
1;
% input samples
s1=inputdata
(ptrBase-
1);
s2=inputdata
(ptrBase
);
s3=inputdata
(ptrBase+
1);
s4=inputdata
(ptrBase+
2);
% performance optimization. Reallocate some extra space.
if outIndex>=nAlloc
nAlloc=nAlloc+
2000;
outputData
(nAlloc
)=
0;
end
% ******************************************************************
% Calculate output sample.
% ******************************************************************
outputData
(outIndex
)=s1*c1
(fIndex
)+s2*c2
(fIndex
)+s3*c3
(fIndex
)+s4*c4
(fIndex
);
% that's it. Next output sample
outIndex=outIndex+
1;
% advance the index in the source data
ptr=ptr+rate;
end
% performance optimization part II, chop extra memory
outputData=outputData
(1:outIndex-
1)';
% ******************************************************************
% Write output to file
% ******************************************************************
% wavwrite('out.wav', outputData, fs, bits); % OCTAVE version
wavwrite(outputData, fs, bits,
'out.wav');
% MATLAB version
Rate this code snippet:
4
Rating: 4 | Votes: 3
posted by Markus Nentwig
Markus received his Dipl. Ing. degree in electrical engineering / communications in 1999. Work interests include RF transceiver system design, implementation, modeling and verification. He works as senior architect for Renesas Mobile Europe in Finland.