function audioDelayEffectsExampleApp(effectType, timeToRun)
%AUDIODELAYEFFECTSEXAMPLEAPP Apply delay-based effect to audio
%
% Inputs:
% effectType   - Effect to be applied. Must be one of: 'echo', 'chorus' or
%                'flanger'
% timeToRun    - Time duration to run audio samples (optional).
%
% This function audioDelayEffectsExampleApp is only in support of 
% audioDelayEffectsExample. It may change in a future release.

% Copyright 2015-2017 The MathWorks, Inc.

narginchk(1,2);
effectType = validatestring(effectType,{'echo','chorus','flanger'});

% Initialization
if nargin == 1
    timeToRun = inf;
end

switch effectType
    case 'echo'
        % Input file name
        fName = 'Counting-16-44p1-mono-15secs.wav';
        % Create a structure of parameters to be used by the Tuning UI
        param(1).Name = 'Delay (s)';
        param(1).InitialValue = 0.5;
        param(1).Limits = [0,1];
        param(2).Name = 'Gain';
        param(2).InitialValue = 0.5;
        param(2).Limits = [0,1];
        param(3).Name = 'Feedback level';
        param(3).InitialValue = 0.35;
        param(3).Limits = [0,0.5];
        param(4).Name = 'Wet/dry mix';
        param(4).InitialValue = 0.5;
        param(4).Limits = [0,1];
        tuningTitle = 'Echo Parameters';
        % Processing function
        clear HelperApplyEcho
        effectFcn = @HelperApplyEcho;
        
    case 'chorus'
        % Input file name
        fName = 'RockDrums-44p1-stereo-11secs.mp3';
        % Create a structure of parameters to be used by the Tuning UI
        param(1).Name = 'Delay (s)';
        param(1).InitialValue = 0.02;
        param(1).Limits = [0,0.1];
        param(2).Name = 'Depth1';
        param(2).InitialValue = 0.01;
        param(2).Limits = [0,10];
        param(3).Name = 'Rate1 (Hz)';
        param(3).InitialValue = 0.01;
        param(3).Limits = [0,10];
        param(4).Name = 'Depth2';
        param(4).InitialValue = 0.03;
        param(4).Limits = [0,10];
        param(5).Name = 'Rate2 (Hz)';
        param(5).InitialValue = 0.02;
        param(5).Limits = [0,10];
        param(6).Name = 'Wet/dry mix';
        param(6).InitialValue = 0.5;
        param(6).Limits = [0,1];
        tuningTitle = 'Chorus Parameters';
        % Processing function
        clear HelperApplyChorus
        effectFcn = @HelperApplyChorus;
        
    case 'flanger'
        % Input file name
        fName = 'FunkyDrums-44p1-stereo-25secs.mp3';
        % Create a structure of parameters to be used by the Tuning UI
        param(1).Name = 'Delay (s)';
        param(1).InitialValue = 1e-3;
        param(1).Limits = [0,0.1];
        param(2).Name = 'Depth';
        param(2).InitialValue = 30;
        param(2).Limits = [0,50];
        param(3).Name = 'Rate (Hz)';
        param(3).InitialValue = 0.25;
        param(3).Limits = [0,0.5];
        param(4).Name = 'Feedback level';
        param(4).InitialValue = 0.4;
        param(4).Limits = [0,1];
        param(5).Name = 'Wet/dry mix';
        param(5).InitialValue = 0.5;
        param(5).Limits = [0,1];
        tuningTitle = 'Flanger Parameters';
        % Processing function
        clear HelperApplyFlanger
        effectFcn = @HelperApplyFlanger;
end

% Source
reader = dsp.AudioFileReader('Filename',fName,'PlayCount',inf);
fs = reader.SampleRate;

% Sink
player = audioDeviceWriter('SampleRate',fs);

% Create Parameter Tuning UI for the above list of parameters
tuningUI = HelperCreateParamTuningUI(param,tuningTitle);

% Stream processing loop
audioIn = reader();
nIters = ceil(timeToRun*fs/reader.SamplesPerFrame);
count = 1;
while count < nIters

    S = HelperUnpackUIData(tuningUI);
    
    if ~S.Pause
        audioIn = reader();
    end

    if S.Stop     % If "Stop Simulation" button is pressed 
        break;
    end
    
    if S.Pause
        continue;
    end
    
    audioOut = effectFcn(audioIn,S,fs);
    
    play(player,audioOut);
    
    count = count + 1;
end

% Clean up
release(reader);
release(player);
clear HelperUnpackUIData
if ishghandle(tuningUI)  % If parameter tuning UI is open, then close it.
    delete(tuningUI);
    drawnow;
    clear tuningUI
end
