%% Calculate Harmonic Ratio of Streaming Audio
% Create a dsp.AudioFileReader object to read in stereo audio data frame-by-frame. Create a dsp.SignalSink object to log the harmonic ratio calculation.

fileReader = dsp.AudioFileReader('RandomOscThree-24-96-stereo-13secs.aif');
logger = dsp.SignalSink;

%
% In an audio stream loop:
% Read in a frame of audio data.
% Calculate the harmonic ratio for each channel of the frame of audio.
% Log the harmonic ratio for later plotting.
% To calculate the harmonic ratio for only a given input frame, specify a window with the same number of samples as the input, and set the overlap length to zero. Plot the logged data.

win = hamming(fileReader.SamplesPerFrame,'periodic');
while ~isDone(fileReader)
    audioIn = fileReader();
    
    hr = harmonicRatio(audioIn,fileReader.SampleRate, ...
                       'Window',win, ...
                       'OverlapLength',0);
    logger(hr)
end

plot(logger.Buffer)
ylabel('Harmonic Ratio')
legend('Left Channel','Right Channel')

%
% If the input to your audio stream loop has a variable samples-per-frame, an inconsistent samples-per-frame with the analysis window size of harmonicRatio, or if you want to calculate the harmonic ratio of overlapped data, use dsp.AsyncBuffer.
% Create a dsp.AsyncBuffer object, reset the logger, and release the file reader.

buff = dsp.AsyncBuffer;
reset(logger)
release(fileReader)

%
% Calculate the harmonic ratio using 50 ms frames with a 25 ms overlap.

fs = fileReader.SampleRate;

samplesPerFrame = round(fs*0.05);
samplesOverlap = round(fs*0.025);

samplesPerHop = samplesPerFrame - samplesOverlap;

win = hamming(samplesPerFrame);

while ~isDone(fileReader)
    audioIn = fileReader();
    write(buff,audioIn);

    while buff.NumUnreadSamples >= samplesPerHop
        audioBuffered = read(buff,samplesPerFrame,samplesOverlap);

        hr = harmonicRatio(audioBuffered,fs, ...
                           'Window',win, ...
                           'OverlapLength',0);
        logger(hr)
    end

end
release(fileReader)

%
% Plot the logged data.

plot(logger.Buffer)
ylabel('Harmonic Ratio')
legend('Left Channel','Right Channel')

%
% Copyright 2018 The MathWorks, Inc.