%% Apply Time Scale Modification to Streaming Audio
% To minimize artifacts caused by windowing, create a square root Hann window capable of perfect reconstruction. Use iscola to verify the design.

win = sqrt(hann(1024,'periodic'));
overlapLength = 896;
iscola(win,overlapLength)

%
% Create an audioTimeScaler with a speedup factor of 1.5. Change the value of alpha to hear the effect of the speedup factor.

alpha = 1.5;
aTS = audioTimeScaler( ...
    'SpeedupFactor',alpha, ...
    'Window',win, ...
    'OverlapLength',overlapLength);

%
% Create a dsp.AudioFileReader object to read frames from an audio file. The length of frames input to the audio time scaler must be less than or equal to the analysis hop length defined in audioTimeScaler. To minimize buffering, set the samples per frame of the file reader to the analysis hop length.

hopLength = numel(aTS.Window) - overlapLength;
fileReader = dsp.AudioFileReader('Counting-16-44p1-mono-15secs.wav', ...
    'SamplesPerFrame',hopLength);

% Create an audioDeviceWriter to write frames to your audio device. Use the same sample rate as the file reader.

deviceWriter = audioDeviceWriter('SampleRate',fileReader.SampleRate);

%
% In an audio stream loop, read a frame the file, apply time scale modification, and then write a frame to the device.

while ~isDone(fileReader)
    audioIn = fileReader();
    audioOut = aTS(audioIn);
    deviceWriter(audioOut);
end

%
% As a best practice, release your objects once done.

release(deviceWriter)
release(fileReader)
release(aTS)

%
% Copyright 2019 The MathWorks, Inc.