format short
format compact
echo on
% Read in Peterson-Barney Data:
fid = fopen('pb.Table1');
PB = textscan(fid, '%s %s %d %s %s %f %f %f %f', 10000);
fclose(fid);
%
% 1: m = man, w=woman, c=child
% 2: m=male, f=female
% 3: N=speaker number
% 4: V=vowel name (heed/iy, hid/ih, head/eh, had/ae, hod/aa, hawed/ao, hood/uh, who'd/uw, hud/ah, heard/er)
% 5: IPA
% 6: F0 in Hz
% 7: F1
% 8: F2
% 9: F3
%
pause
% Convert column 1 (man, woman, child) from cell array to string array:
MWC=char(PB{1});
% Make some useful binary vectors:
isman=(MWC=='m');
iswoman=(MWC=='w');
ischild=(MWC=='c');
% man/woman/child as values from 1 to 3:
MWCints = isman + 2*iswoman + 3*ischild;
% Convert column 2 (male, female) to string array:
MF=char(PB{2});
% More useful binary vectors:
ismale=(MF=='m');
isfemale=(MF=='f');
% Convert column 4 (vowel ID) to integers 1:10 in VID array
% Note that options are 'iy','ih','eh', 'ae','aa','ao','uh','uw','ah','er'
VID=zeros(length(isman),1);
VID = VID + strcmp('iy',PB{4});
VID = VID + 2*strcmp('ih',PB{4});
VID = VID + 3*strcmp('eh',PB{4});
VID = VID + 4*strcmp('ae',PB{4});
VID = VID + 5*strcmp('aa',PB{4});
VID = VID + 6*strcmp('ao',PB{4});
VID = VID + 7*strcmp('uh',PB{4});
VID = VID + 8*strcmp('uw',PB{4});
VID = VID + 9*strcmp('ah',PB{4});
VID = VID + 10*strcmp('er',PB{4});
%
pause
% Make matrix whose rows are vowels, and
%      columns are F0, F1, F2, F3:
F0123 = [PB{6} PB{7} PB{8} PB{9}];
% Make mean vectors and covariance matrices for man vs. woman vs. child:
MWCmeans = zeros(3,4);
MWCcov = cell(3,1);
for c=1:3
    MWCmeans(c,:) = mean(F0123(MWCints==c,:));
    MWCcov{c} = inv(cov(F0123(MWCints==c,:)));
end
%
pause
% Calculate MWC distances for all 1520 vowels:
MWCdist = zeros(1520,3);
MWCminvals = zeros(1520,1);
MWCchoice = zeros(1520,1);
echo off
for v=1:1520
    for c=1:3
        f = F0123(v,:)-MWCmeans(c,:);
        MWCdist(v,c) = sqrt(f*MWCcov{c}*f');
    end
    [MWCminvals(v), MWCchoice(v)] = min(MWCdist(v,:));
end
echo on
% Make confusion matrix:
MWCconfusion = zeros(3);
for v=1:1520
    i=MWCints(v); j=MWCchoice(v);
    MWCconfusion(i,j) = MWCconfusion(i,j)+1;
end
%
% Show confusion matrix:
MWCconfusion
% What's the proportion correct?
sum(diag(MWCconfusion))/1520
pause

% Make mean vectors and covariance matrices for vowels:
Vmeans = zeros(10,4);
Vcov = cell(10,1);
for v=1:10
    Vmeans(v,:) = mean(F0123(VID==v,:));
    Vcov{v} = inv(cov(F0123(VID==v,:)));
end
% Calculate V distances for all 1520 vowels:
Vdist = zeros(1520,10);
Vminvals = zeros(1520,1);
Vchoice = zeros(1520,1);
echo off
for testv=1:1520
    for refv=1:10
        f = F0123(testv,:)-Vmeans(refv,:);
        Vdist(testv,refv) = sqrt(f*Vcov{refv}*f');
    end
    [Vminvals(testv), Vchoice(testv)] = min(Vdist(testv,:));
end
echo on
% Make confusion matrix
Vconfusion = zeros(10);
for v=1:1520
    i=VID(v); j=Vchoice(v);
    Vconfusion(i,j) = Vconfusion(i,j)+1;
end
% Show confusion matrix --
% 1='iy' 2='ih' 3='eh' 4='ae' 5='aa' 6='ao' 7='uh' 8='uw' 9='ah' 10='er'
Vconfusion
% Proportion correct?

sum(diag(Vconfusion))/1520
pause
%
% Now divide data matrix into training and testing sets.
% There are 76 speakers, IDs 1 to 76:
SID = PB{3};
% 33 men (1:33), 28 women (34:61), 15 children (62:76)
% Since there are 20 vowels per speaker,
%   the start of the nth speaker's data is row (n-1)*20 + 1
%   and the end of the nth speaker's data is row n*20
%  The corresponding rows in F0123 are:
% men 1 to 33*20 = 1 to 660
% women 33*20 + 1 to 61*20 = 661 to 1240
% children 62*20 + 1 to 76*20 = 1241 to 1520
%
% If we assign the last two men, the last two women, and the last child
%    to the test set, we get:
istrainman=zeros(1520,1); istestman=zeros(1520,1);
istrainwoman=zeros(1520,1); istestwoman=zeros(1520,1);
istrainchild=zeros(1520,1); istestchild=zeros(1520,1);
%
istrainman(1:(31*20)) = 1;       % 1 to 31
istestman((31*20+1):(33*20))=1;  % 32 to 33
%
istrainwoman((33*20+1):(59*20)) = 1; % 34 to 59
istestwoman((59*20+1):(61*20)) = 1;  % 60 to 61
%
istrainchild((61*20+1):(74*20)) = 1; % 62 to 74
istestchild((74*20+1):(76*20)) = 1;  % 75 to 76
%
istrain = istrainman | istrainwoman | istrainchild;
istest = istestman | istestwoman | istestchild;
MWCtints = MWCints(istest);
VIDt = VID(istest);
pause
% Make mean vectors and covariance matrices for man vs. woman vs. child,
%   this time only from "training" data:
MWCtmeans = zeros(3,4);
MWCtcov = cell(3,1);
for c=1:3
    which = (MWCints==c) & istrain;
    MWCtmeans(c,:) = mean(F0123(which,:));
    MWCtcov{c} = inv(cov(F0123(which,:)));
end
%
pause
% Calculate MWC distances for 100 test vowels:
MWCtdist = zeros(100,3);
MWCtminvals = zeros(100,1);
MWCtchoice = zeros(100,1);
F0123t = F0123(istest,:);
echo off
for v=1:100
    for c=1:3
        f = F0123t(v,:)-MWCtmeans(c,:);
        MWCtdist(v,c) = sqrt(f*MWCtcov{c}*f');
    end
    [MWCtminvals(v), MWCtchoice(v)] = min(MWCtdist(v,:));
end
echo on
% Make confusion matrix:
MWCtconfusion = zeros(3);
for v=1:100
    i=MWCtints(v); j=MWCtchoice(v);
    MWCtconfusion(i,j) = MWCtconfusion(i,j)+1;
end
%
% Show confusion matrix:
MWCtconfusion
% What's the proportion correct?
sum(diag(MWCtconfusion))/100
pause
% Make mean vectors and covariance matrices for vowels,
%   this time only from "training" set:
Vttmeans = zeros(10,4);
Vcov = cell(10,1);
for v=1:10
    which = (VID==v) & istrain;
    Vtmeans(v,:) = mean(F0123(which,:));
    Vtcov{v} = inv(cov(F0123(which,:)));
end
% Calculate V distances for 100 test vowels:
Vtdist = zeros(1520,10);
Vtminvals = zeros(1520,1);
Vtchoice = zeros(1520,1);
echo off
for testv=1:100
    for refv=1:10
        f = F0123t(testv,:)-Vmeans(refv,:);
        Vtdist(testv,refv) = sqrt(f*Vtcov{refv}*f');
    end
    [Vtminvals(testv), Vtchoice(testv)] = min(Vtdist(testv,:));
end
echo on
% Make confusion matrix
Vtconfusion = zeros(10);
for v=1:100
    i=VIDt(v); j=Vtchoice(v);
    Vtconfusion(i,j) = Vtconfusion(i,j)+1;
end
% Show confusion matrix --
% 1='iy' 2='ih' 3='eh' 4='ae' 5='aa' 6='ao' 7='uh' 8='uw' 9='ah' 10='er'
Vtconfusion
% Proportion correct?

sum(diag(Vtconfusion))/100
pause




