% Modified by Muhammad Hussain 
% to achieve Sonification of Heart Beat Data from Athletes (squash players) to guage 
% fitness levels.
% The system aims to achieve Vibrato effect through Heartrate data as one of the
% parameters.
% This code and the audio files was originally sourced from: 
% Tutorial 10 of Digital Audio Systems 9115
% by Ella Manor (2019)
% University of Sydney 

% Adding clear command to clear up previous work
clear
fs = 44100;
% Loading the four audio files: ha, hae, hi and hu to a cell array from the
% folder through a for loop.
for i = 1:4
    vs_recordings{i} = audioread(strcat('VS',num2str(i),'.wav'));
    vs_recordings{i} = (vs_recordings{i}(:,1))./max(abs((vs_recordings{i}(:,1))));
end

% Using the built-in input function to display the following message and ask for user 
% input to choose between viola or violin audio.
instrument_selection = input('\n Do you want to use viola or violin residual?\n\n >','s');

% Testing whether the user seletcted viola using an if statement.   
if strcmp(instrument_selection,'viola')

% If this condition returns true, load the audio file VIO1.wav
% Name the signal's variable instrument.
    instrument = audioread('VIO1.wav');

% Add elseif condition testing whether the user selected violin.
% Using the built-in function strcmp to compare between strings. 
elseif strcmp(instrument_selection,'violin')

% If this condition returns true, load the audio file VLN1.wav 
% Name the signal's variable instrument.
    instrument = audioread('VLN1.wav');

% Adding a final else condition that uses the built-in function error to indicate
% that the user's selection is invalid (i.e., Only viola or violin are
% accepted'
else
    error('only viola and violin are accepted by the system');
end

% Normalise the instrument signal
instrument = instrument./max(abs(instrument));

% Using the built-in input function to display the following message and ask for user 
% input as in numerical form.
polenum = input('\n Select the number of poles for the lpc filter\n\n >');

% Code taken and modified from matlab help.
% Taking input of Heartrate data from Excel files through user interface 
% command from computer files. This command will fill in for the width 
% parameter of the system. Please use excel files only. 
% Setting a directory to recieve excel file and specifying filepath and filename.
% Putting width as data input from the file.
BaseDir = 'C:\Users\hussa\Desktop';  
[FileName, FilePath] = uigetfile('*.xlsx', ...
                  'Please choose an Excel file containing Heartrate data', BaseDir);
data = fullfile(FilePath, FileName);
[width] = xlsread(data);
[width] =(width/15);

% Converting the value in the variable width from milliseconds to seconds
width = width./1000;
%width = round(width);

% Using the built-in input function to display the following message and ask for user 
% input as in numerical form for the depth which is in Hertz.
depth = input('\n Select frequency modulator depth (in Hertz), following the recommended range of 1-8 Hz\n\n >');


% Obtaining the selected instrument's LPC coefficients using the built-in
% fucntion lpc, where the input arguments are the instrument and the number
% of poles. 
polecoeff = lpc(instrument,polenum);

% Filter of original signal to obtain the residual using the
% built-in function filter. This is an all-pole filter.  
residual = filter(polecoeff,1,instrument);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Using a for loop to implement the following:
% 1) Obtaining the LPC coefficients for the vowel sound signals using the built-in
% fucntion lpc. Name the output argument polecoeff_vs.
% 2) Applying cross-synthesis between the original signal (vs_recordings)
% and the residual of the instrument using the built-in function filter.
% This is an all-zero filter. 
% 3) Normalising the signals.
for i = 1:4
    polecoeff_vs(:,i) = lpc(vs_recordings{i},polenum);
    out_filtered_vs(:,i) = filter(1,polecoeff_vs(:,i),residual);
    out_filtered_vs(:,i) = out_filtered_vs(:,i)./max(abs(out_filtered_vs(:,i)));
end


%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%% VIBRATO A %%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Use a for loop to implement the following:
% 1) Call the vibrato function to apply delay modulation.
% 2) Normalise the signals.


% Code provided by Manor, E. (2019)
% This loop applies the different width values to segments of the input
% signals to create variation in the vibrato of the output signal. The number 
% 20 is arbitrery and may be chnaged. 
% Note that if sleng is too short (<1000 samples) the processing yeilds 
% distorted signals.

sleng = floor(length(out_filtered_vs)/20);
rept = floor(length(out_filtered_vs)/sleng);

for i = 1:4
    s = 1;
    e = sleng;
    for j = 1:rept
        vibratoA{i}(s:e,1) = vibratoDAS(out_filtered_vs(s:e,i),fs,depth,width(j));
        vibratoA{i}(s:e,1) = vibratoA{i}(s:e,1)./max(abs(vibratoA{i}(s:e,1)));
        s = s+sleng;
        e = e+sleng;
    end
end


%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%% Playback %%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i = 1:4
    % Vibrato A playback
    sound(vibratoA{i},fs);
    % Writing the resulting signal as an audio file. 
    % The built-in function stract is used to concatenate multiple strings. 
    audiowrite(strcat(instrument_selection,'_vibratoA_',num2str(i),'.wav'), vibratoA{i}, fs);

end

