function sola( filePath, fileName )
%--------------------------------------------------------------------------
% Synchronous OverLap Add
%
% adapted from:
% TimeScaleSOLA.m [DAFXbook, 2nd ed., chapter 6]
%
% Cooper Baker - 2014
%--------------------------------------------------------------------------
close all;
% Settings
%--------------------------------------------------------------------------
grainSize = 1024; % 2048 - default
hopSize = 256; % 256 - default
stretchFactor = 2; % >= 0.25 and <= 2
tag = 'sola';
% Initializations
%--------------------------------------------------------------------------
if any( exist( 'fileName' ) ~= 1 )
[ fileName, filePath ] = uigetfile( '*.wav', 'Audio File' );
end
overlap = ( hopSize * stretchFactor ) / 2;
[ input, sr ] = audioread( [ filePath, fileName ] );
inputTranspose = input';
grainIndex = 1;
grainMax = ceil( length( inputTranspose ) / hopSize );
hopSizeStretch = round(hopSize*stretchFactor);
inputTranspose( grainMax * hopSize + grainSize ) = 0;
output = inputTranspose( 1 : grainSize );
% create progress bar dialog box
bar = waitbar( 0, '0%', 'Name', sprintf( '%s: processing %s...', mfilename, fileName ) );
% Processing Loop
%--------------------------------------------------------------------------
while grainIndex < grainMax
% copy the input grain
grain = inputTranspose( grainIndex * hopSize + 1 : grainSize + grainIndex * hopSize );
% perform cross correlation
crossCorrelation = xcorr( grain ( 1 : overlap ), output( 1, grainIndex * hopSizeStretch : grainIndex * hopSizeStretch + ( overlap - 1 ) ) );
% find maximum in cross correlate
[ xmax( 1, grainIndex ), index( 1, grainIndex ) ] = max( crossCorrelation );
% generate fadeOut ramp
fadeOut = 1 : ( -1 / ( length( output ) - ( grainIndex * hopSizeStretch - ( overlap - 1 ) + index( 1, grainIndex ) - 1 ) ) ) : 0;
% generate fadeIn ramp
fadeIn = 0 : ( 1 / ( length( output ) - ( grainIndex * hopSizeStretch - ( overlap - 1 ) + index( 1, grainIndex ) - 1 ) ) ) : 1;
% fade out tail portion of previous grain
tail = output( 1, ( grainIndex * hopSizeStretch - ( overlap - 1 ) ) + index( 1, grainIndex ) - 1 : length( output) ) .* fadeOut;
% fade in head portion of current grain
head = grain( 1 : length( fadeIn ) ) .* fadeIn;
% mix head and tail into crossfade
crossfade = tail + head;
% concatenate result to end of output buffer
output = [ output( 1, 1 : grainIndex * hopSizeStretch - overlap + index( 1, grainIndex ) - 1 ), crossfade, grain( length( fadeIn ) + 1 : grainSize ) ];
% increment the grain index
grainIndex = grainIndex + 1;
% update the progress bar
progress = ( grainIndex / grainMax );
waitbar( progress, bar, sprintf( '%2.3f%%', progress * 100 ) )
end
% close progress bar dialog box
close( bar );
% Output
%--------------------------------------------------------------------------
% crop output buffer
output = output( 1 : length( output ) );
% normalize audio
normCoeff = 1 / max( abs( output ) );
output = output * normCoeff;
% make comments for file
commentString = sprintf( 'WinSize: %.0f,\nOverlap: %.0f,\nStretch: %.2f,\nWindow: %s', grainSize, overlap, stretchFactor, 'Hann' );
% write audio file to disk
[ a, fileName, b ] = fileparts( fileName );
outFile = sprintf( '%s.%s.wav', fileName, tag );
audiowrite( outFile, output, sr, 'BitsPerSample', 32, 'Artist', 'NormCoeff', 'Title', num2str( normCoeff ), 'Comment', commentString );
% plot output
timevector = linspace( 0, length( output )/sr, length( output ) );
plot( timevector, output );
% EOF
%--------------------------------------------------------------------------
% Synchronous OverLap Add
%
% adapted from:
% TimeScaleSOLA.m [DAFXbook, 2nd ed., chapter 6]
%
% Cooper Baker - 2014
%--------------------------------------------------------------------------
close all;
% Settings
%--------------------------------------------------------------------------
grainSize = 1024; % 2048 - default
hopSize = 256; % 256 - default
stretchFactor = 2; % >= 0.25 and <= 2
tag = 'sola';
% Initializations
%--------------------------------------------------------------------------
if any( exist( 'fileName' ) ~= 1 )
[ fileName, filePath ] = uigetfile( '*.wav', 'Audio File' );
end
overlap = ( hopSize * stretchFactor ) / 2;
[ input, sr ] = audioread( [ filePath, fileName ] );
inputTranspose = input';
grainIndex = 1;
grainMax = ceil( length( inputTranspose ) / hopSize );
hopSizeStretch = round(hopSize*stretchFactor);
inputTranspose( grainMax * hopSize + grainSize ) = 0;
output = inputTranspose( 1 : grainSize );
% create progress bar dialog box
bar = waitbar( 0, '0%', 'Name', sprintf( '%s: processing %s...', mfilename, fileName ) );
% Processing Loop
%--------------------------------------------------------------------------
while grainIndex < grainMax
% copy the input grain
grain = inputTranspose( grainIndex * hopSize + 1 : grainSize + grainIndex * hopSize );
% perform cross correlation
crossCorrelation = xcorr( grain ( 1 : overlap ), output( 1, grainIndex * hopSizeStretch : grainIndex * hopSizeStretch + ( overlap - 1 ) ) );
% find maximum in cross correlate
[ xmax( 1, grainIndex ), index( 1, grainIndex ) ] = max( crossCorrelation );
% generate fadeOut ramp
fadeOut = 1 : ( -1 / ( length( output ) - ( grainIndex * hopSizeStretch - ( overlap - 1 ) + index( 1, grainIndex ) - 1 ) ) ) : 0;
% generate fadeIn ramp
fadeIn = 0 : ( 1 / ( length( output ) - ( grainIndex * hopSizeStretch - ( overlap - 1 ) + index( 1, grainIndex ) - 1 ) ) ) : 1;
% fade out tail portion of previous grain
tail = output( 1, ( grainIndex * hopSizeStretch - ( overlap - 1 ) ) + index( 1, grainIndex ) - 1 : length( output) ) .* fadeOut;
% fade in head portion of current grain
head = grain( 1 : length( fadeIn ) ) .* fadeIn;
% mix head and tail into crossfade
crossfade = tail + head;
% concatenate result to end of output buffer
output = [ output( 1, 1 : grainIndex * hopSizeStretch - overlap + index( 1, grainIndex ) - 1 ), crossfade, grain( length( fadeIn ) + 1 : grainSize ) ];
% increment the grain index
grainIndex = grainIndex + 1;
% update the progress bar
progress = ( grainIndex / grainMax );
waitbar( progress, bar, sprintf( '%2.3f%%', progress * 100 ) )
end
% close progress bar dialog box
close( bar );
% Output
%--------------------------------------------------------------------------
% crop output buffer
output = output( 1 : length( output ) );
% normalize audio
normCoeff = 1 / max( abs( output ) );
output = output * normCoeff;
% make comments for file
commentString = sprintf( 'WinSize: %.0f,\nOverlap: %.0f,\nStretch: %.2f,\nWindow: %s', grainSize, overlap, stretchFactor, 'Hann' );
% write audio file to disk
[ a, fileName, b ] = fileparts( fileName );
outFile = sprintf( '%s.%s.wav', fileName, tag );
audiowrite( outFile, output, sr, 'BitsPerSample', 32, 'Artist', 'NormCoeff', 'Title', num2str( normCoeff ), 'Comment', commentString );
% plot output
timevector = linspace( 0, length( output )/sr, length( output ) );
plot( timevector, output );
% EOF