Revision 38:c2204b18f4a2 userProgramsASRforDummies
| userProgramsASRforDummies/Exp_Ray_1.m | ||
|---|---|---|
| 1 |
function Exp_Ray_1(isMasterNode) |
|
| 2 |
|
|
| 3 |
% Some description of the experiment goes here |
|
| 4 |
|
|
| 5 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 6 |
% Set up the basic folders |
|
| 7 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 8 |
expName = 'scrap6_with_eff'; |
|
| 9 |
dataFolderPrefix = 'featR'; |
|
| 10 |
if isunix |
|
| 11 |
expFolderPrefix = '/scratch/nrclark/exps/'; |
|
| 12 |
else |
|
| 13 |
expFolderPrefix = 'D:\Exps'; |
|
| 14 |
end |
|
| 15 |
|
|
| 16 |
expFolder = fullfile(expFolderPrefix,expName); |
|
| 17 |
hmmFolder = fullfile(expFolder,'hmm'); |
|
| 18 |
|
|
| 19 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 20 |
% Sort out the training (LEARNING) condition |
|
| 21 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 22 |
learnFolder = fullfile(expFolder,'featL'); |
|
| 23 |
|
|
| 24 |
xL = cJob('L', learnFolder);
|
|
| 25 |
|
|
| 26 |
xL.participant = 'Normal'; |
|
| 27 |
xL.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=0;', 'OMEParams.rateToAttenuationFactorProb=0;' };
|
|
| 28 |
xL.MAPparamChanges= {};
|
|
| 29 |
|
|
| 30 |
xL.noiseLevToUse = -200; |
|
| 31 |
xL.noiseLevToUse = 20; |
|
| 32 |
xL.speechLevToUse = 50; |
|
| 33 |
|
|
| 34 |
xL.MAPopHSR = 1; |
|
| 35 |
xL.MAPopMSR = 0; |
|
| 36 |
xL.MAPopLSR = 0; |
|
| 37 |
|
|
| 38 |
|
|
| 39 |
xL.numCoeff = 14; |
|
| 40 |
xL.removeEnergyStatic = 0; |
|
| 41 |
|
|
| 42 |
%%%%% Group of params that will influence simulation run time %%%%%%% |
|
| 43 |
xL.numWavs = 512; %MAX=8440 |
|
| 44 |
testWavs = 48; %MAX = 358 |
|
| 45 |
nzLevel = [-200 40 60]; |
|
| 46 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 47 |
|
|
| 48 |
xL.noisePreDur = 1; |
|
| 49 |
xL.noisePostDur = 0.1; |
|
| 50 |
xL.truncateDur = xL.noisePreDur-0.1; |
|
| 51 |
|
|
| 52 |
xL.noiseName = '20TalkerBabble'; |
|
| 53 |
|
|
| 54 |
if isMasterNode && ~isdir(xL.opFolder) |
|
| 55 |
mkdir(xL.opFolder); |
|
| 56 |
xL = xL.assignFiles; |
|
| 57 |
xL.storeSelf; % This is a call to a member function and is not a pointless line of code! |
|
| 58 |
end |
|
| 59 |
|
|
| 60 |
|
|
| 61 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 62 |
% Sort out the testing (RECOGNITION) conditions |
|
| 63 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 64 |
recConditions = numel(nzLevel); |
|
| 65 |
|
|
| 66 |
tmpIdx=0; |
|
| 67 |
for nn = 0*recConditions+1:1*recConditions |
|
| 68 |
tmpIdx=tmpIdx+1; |
|
| 69 |
xR{nn} = xL; %simply copy the "Learn" object and change it a bit below
|
|
| 70 |
recFolder = fullfile(expFolder,[dataFolderPrefix num2str(nn)]); |
|
| 71 |
xR{nn}.opFolder = recFolder;
|
|
| 72 |
|
|
| 73 |
%These are the interesting differences between training and testing |
|
| 74 |
xR{nn}.numWavs = testWavs; %MAX = 358
|
|
| 75 |
xR{nn}.noiseLevToUse = nzLevel(tmpIdx);
|
|
| 76 |
%xR{nn}.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=0;'};
|
|
| 77 |
|
|
| 78 |
%Now just to wrap it up ready for processing |
|
| 79 |
if isMasterNode && ~isdir(xR{nn}.opFolder)
|
|
| 80 |
mkdir(xR{nn}.opFolder);
|
|
| 81 |
xR{nn} = xR{nn}.assignWavPaths('R');
|
|
| 82 |
xR{nn} = xR{nn}.assignFiles;
|
|
| 83 |
xR{nn}.storeSelf;
|
|
| 84 |
end |
|
| 85 |
end |
|
| 86 |
|
|
| 87 |
% tmpIdx=0; |
|
| 88 |
% for nn = 1*recConditions+1:2*recConditions |
|
| 89 |
% tmpIdx=tmpIdx+1; |
|
| 90 |
% xR{nn} = xL; %simply copy the "Learn" object and change it a bit below
|
|
| 91 |
% recFolder = fullfile(expFolder,[dataFolderPrefix num2str(nn)]); |
|
| 92 |
% xR{nn}.opFolder = recFolder;
|
|
| 93 |
% |
|
| 94 |
% %These are the interesting differences between training and testing |
|
| 95 |
% xR{nn}.numWavs = testWavs; %MAX = 358
|
|
| 96 |
% xR{nn}.noiseLevToUse = nzLevel(tmpIdx);
|
|
| 97 |
% xR{nn}.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=-10^(-10/20);'};
|
|
| 98 |
% |
|
| 99 |
% |
|
| 100 |
% %Now just to wrap it up ready for processing |
|
| 101 |
% if isMasterNode && ~isdir(xR{nn}.opFolder)
|
|
| 102 |
% mkdir(xR{nn}.opFolder);
|
|
| 103 |
% xR{nn} = xR{nn}.assignWavPaths('R');
|
|
| 104 |
% xR{nn} = xR{nn}.assignFiles;
|
|
| 105 |
% xR{nn}.storeSelf;
|
|
| 106 |
% end |
|
| 107 |
% end |
|
| 108 |
|
|
| 109 |
|
|
| 110 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 111 |
% ** Generate features ** |
|
| 112 |
% This is the time consuming, processing intensive portion of the program. |
|
| 113 |
% Nodes that are not the master node are only interested in the opFolder |
|
| 114 |
% member of the jobjects. |
|
| 115 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 116 |
worker(xL.opFolder); |
|
| 117 |
maxConds = nn; |
|
| 118 |
if ~isMasterNode %dont bother wasting master node effort on generating testing features (for now) |
|
| 119 |
for nn = 1:maxConds |
|
| 120 |
worker(xR{nn}.opFolder);
|
|
| 121 |
end |
|
| 122 |
end |
|
| 123 |
|
|
| 124 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 125 |
% Train and test the recogniser - a job for the master node only |
|
| 126 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 127 |
if isMasterNode |
|
| 128 |
while(~all(xL.todoStatus==2)) |
|
| 129 |
disp('Waiting on straggler nodes to complete their jobs before HMM is trained . . .')
|
|
| 130 |
pause(30); %Wait for 30 seconds before looking again |
|
| 131 |
xL.lockJobList; |
|
| 132 |
xL = xL.loadSelf; %Reload incase changed |
|
| 133 |
xL.unlockJobList; |
|
| 134 |
end |
|
| 135 |
y = cHMM(hmmFolder); |
|
| 136 |
y.numCoeff = (xL.numCoeff-logical(xL.removeEnergyStatic)) * 3; |
|
| 137 |
y.createSCP(xL.opFolder) |
|
| 138 |
y.createMLF(xL.opFolder) |
|
| 139 |
y.train(xL.opFolder) %This node can be busy training, even if other jobs are being processed for testing |
|
| 140 |
|
|
| 141 |
% ALLOW MASTER NODE TO MUCK IN WITH GENERATING TESTING FEATURES ONCE |
|
| 142 |
% HMM HAS BEEN TRAINED |
|
| 143 |
for nn = 1:maxConds |
|
| 144 |
worker(xR{nn}.opFolder);
|
|
| 145 |
end |
|
| 146 |
|
|
| 147 |
xR{end}.lockJobList;
|
|
| 148 |
xR{end} = xR{end}.loadSelf; %Reload changes
|
|
| 149 |
xR{end}.unlockJobList;
|
|
| 150 |
while(~all(xR{end}.todoStatus==2))
|
|
| 151 |
disp('Waiting on straggler nodes to complete their jobs before HMM is tested . . .')
|
|
| 152 |
pause(30); %Wait for 30 seconds before looking again |
|
| 153 |
xR{end}.lockJobList;
|
|
| 154 |
xR{end} = xR{end}.loadSelf; %Reload incase changed
|
|
| 155 |
xR{end}.unlockJobList;
|
|
| 156 |
end |
|
| 157 |
|
|
| 158 |
for nn = 1:maxConds |
|
| 159 |
y.createSCP(xR{nn}.opFolder);
|
|
| 160 |
y.test(xR{nn}.opFolder);
|
|
| 161 |
end |
|
| 162 |
|
|
| 163 |
%Show all of the scores in the command window at the end |
|
| 164 |
for nn = 1:maxConds |
|
| 165 |
y.score(xR{nn}.opFolder);
|
|
| 166 |
end |
|
| 167 |
end |
|
| userProgramsASRforDummies/Exp_Tutorial_1.m | ||
|---|---|---|
| 1 |
function Exp_Tutorial_1(isMasterNode) |
|
| 2 |
|
|
| 3 |
% Some description of the experiment goes here |
|
| 4 |
|
|
| 5 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 6 |
% Set up the basic folders |
|
| 7 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 8 |
expName = 'Tutorial'; |
|
| 9 |
dataFolderPrefix = 'featR'; |
|
| 10 |
if isunix |
|
| 11 |
expFolderPrefix = '/scratch/nrclark/exps/'; |
|
| 12 |
else |
|
| 13 |
expFolderPrefix = 'D:\Exps'; |
|
| 14 |
end |
|
| 15 |
|
|
| 16 |
expFolder = fullfile(expFolderPrefix,expName); |
|
| 17 |
hmmFolder = fullfile(expFolder,'hmm'); |
|
| 18 |
|
|
| 19 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 20 |
% Sort out the training (LEARNING) condition |
|
| 21 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 22 |
learnFolder = fullfile(expFolder,'featL'); |
|
| 23 |
|
|
| 24 |
xL = cJob('L', learnFolder);
|
|
| 25 |
|
|
| 26 |
xL.participant = 'Normal'; |
|
| 27 |
xL.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=0;', 'OMEParams.rateToAttenuationFactorProb=0;' };
|
|
| 28 |
|
|
| 29 |
xL.noiseLevToUse = -200; |
|
| 30 |
xL.speechLevToUse = 60; |
|
| 31 |
|
|
| 32 |
xL.MAPopHSR = 1; |
|
| 33 |
xL.MAPopMSR = 0; |
|
| 34 |
xL.MAPopLSR = 0; |
|
| 35 |
|
|
| 36 |
|
|
| 37 |
xL.numCoeff = 14; |
|
| 38 |
xL.removeEnergyStatic = 0; |
|
| 39 |
|
|
| 40 |
%%%%% Group of params that will influence simulation run time %%%%%%% |
|
| 41 |
xL.numWavs = 12; %MAX=8440 |
|
| 42 |
testWavs = 6; %MAX = 358 |
|
| 43 |
nzLevel = [-200 40:10:70]; |
|
| 44 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 45 |
|
|
| 46 |
xL.noisePreDur = 1; |
|
| 47 |
xL.noisePostDur = 0.1; |
|
| 48 |
xL.truncateDur = xL.noisePreDur-0.1; |
|
| 49 |
|
|
| 50 |
xL.noiseName = 'pink_demo'; |
|
| 51 |
|
|
| 52 |
if isMasterNode && ~isdir(xL.opFolder) |
|
| 53 |
mkdir(xL.opFolder); |
|
| 54 |
xL = xL.assignFiles; |
|
| 55 |
xL.storeSelf; % This is a call to a member function and is not a pointless line of code! |
|
| 56 |
end |
|
| 57 |
|
|
| 58 |
|
|
| 59 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 60 |
% Sort out the testing (RECOGNITION) conditions |
|
| 61 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 62 |
recConditions = numel(nzLevel); |
|
| 63 |
|
|
| 64 |
tmpIdx=0; |
|
| 65 |
for nn = 0*recConditions+1:1*recConditions |
|
| 66 |
tmpIdx=tmpIdx+1; |
|
| 67 |
xR{nn} = xL; %simply copy the "Learn" object and change it a bit below
|
|
| 68 |
recFolder = fullfile(expFolder,[dataFolderPrefix num2str(nn)]); |
|
| 69 |
xR{nn}.opFolder = recFolder;
|
|
| 70 |
|
|
| 71 |
%These are the interesting differences between training and testing |
|
| 72 |
xR{nn}.numWavs = testWavs; %MAX = 358
|
|
| 73 |
xR{nn}.noiseLevToUse = nzLevel(tmpIdx);
|
|
| 74 |
xR{nn}.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=0;'};
|
|
| 75 |
|
|
| 76 |
%Now just to wrap it up ready for processing |
|
| 77 |
if isMasterNode && ~isdir(xR{nn}.opFolder)
|
|
| 78 |
mkdir(xR{nn}.opFolder);
|
|
| 79 |
xR{nn} = xR{nn}.assignWavPaths('R');
|
|
| 80 |
xR{nn} = xR{nn}.assignFiles;
|
|
| 81 |
xR{nn}.storeSelf;
|
|
| 82 |
end |
|
| 83 |
end |
|
| 84 |
|
|
| 85 |
tmpIdx=0; |
|
| 86 |
for nn = 1*recConditions+1:2*recConditions |
|
| 87 |
tmpIdx=tmpIdx+1; |
|
| 88 |
xR{nn} = xL; %simply copy the "Learn" object and change it a bit below
|
|
| 89 |
recFolder = fullfile(expFolder,[dataFolderPrefix num2str(nn)]); |
|
| 90 |
xR{nn}.opFolder = recFolder;
|
|
| 91 |
|
|
| 92 |
%These are the interesting differences between training and testing |
|
| 93 |
xR{nn}.numWavs = testWavs; %MAX = 358
|
|
| 94 |
xR{nn}.noiseLevToUse = nzLevel(tmpIdx);
|
|
| 95 |
xR{nn}.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=-10^(-10/20);'};
|
|
| 96 |
|
|
| 97 |
|
|
| 98 |
%Now just to wrap it up ready for processing |
|
| 99 |
if isMasterNode && ~isdir(xR{nn}.opFolder)
|
|
| 100 |
mkdir(xR{nn}.opFolder);
|
|
| 101 |
xR{nn} = xR{nn}.assignWavPaths('R');
|
|
| 102 |
xR{nn} = xR{nn}.assignFiles;
|
|
| 103 |
xR{nn}.storeSelf;
|
|
| 104 |
end |
|
| 105 |
end |
|
| 106 |
|
|
| 107 |
|
|
| 108 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 109 |
% ** Generate features ** |
|
| 110 |
% This is the time consuming, processing intensive portion of the program. |
|
| 111 |
% Nodes that are not the master node are only interested in the opFolder |
|
| 112 |
% member of the jobjects. |
|
| 113 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 114 |
worker(xL.opFolder); |
|
| 115 |
maxConds = nn; |
|
| 116 |
if ~isMasterNode %dont bother wasting master node effort on generating testing features (for now) |
|
| 117 |
for nn = 1:maxConds |
|
| 118 |
worker(xR{nn}.opFolder);
|
|
| 119 |
end |
|
| 120 |
end |
|
| 121 |
|
|
| 122 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 123 |
% Train and test the recogniser - a job for the master node only |
|
| 124 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 125 |
if isMasterNode |
|
| 126 |
while(~all(xL.todoStatus==2)) |
|
| 127 |
disp('Waiting on straggler nodes to complete their jobs before HMM is trained . . .')
|
|
| 128 |
pause(30); %Wait for 30 seconds before looking again |
|
| 129 |
xL.lockJobList; |
|
| 130 |
xL = xL.loadSelf; %Reload incase changed |
|
| 131 |
xL.unlockJobList; |
|
| 132 |
end |
|
| 133 |
y = cHMM(hmmFolder); |
|
| 134 |
y.numCoeff = (xL.numCoeff-logical(xL.removeEnergyStatic)) * 3; |
|
| 135 |
y.createSCP(xL.opFolder) |
|
| 136 |
y.createMLF(xL.opFolder) |
|
| 137 |
y.train(xL.opFolder) %This node can be busy training, even if other jobs are being processed for testing |
|
| 138 |
|
|
| 139 |
% ALLOW MASTER NODE TO MUCK IN WITH GENERATING TESTING FEATURES ONCE |
|
| 140 |
% HMM HAS BEEN TRAINED |
|
| 141 |
for nn = 1:maxConds |
|
| 142 |
worker(xR{nn}.opFolder);
|
|
| 143 |
end |
|
| 144 |
|
|
| 145 |
xR{end}.lockJobList;
|
|
| 146 |
xR{end} = xR{end}.loadSelf; %Reload changes
|
|
| 147 |
xR{end}.unlockJobList;
|
|
| 148 |
while(~all(xR{end}.todoStatus==2))
|
|
| 149 |
disp('Waiting on straggler nodes to complete their jobs before HMM is tested . . .')
|
|
| 150 |
pause(30); %Wait for 30 seconds before looking again |
|
| 151 |
xR{end}.lockJobList;
|
|
| 152 |
xR{end} = xR{end}.loadSelf; %Reload incase changed
|
|
| 153 |
xR{end}.unlockJobList;
|
|
| 154 |
end |
|
| 155 |
|
|
| 156 |
for nn = 1:maxConds |
|
| 157 |
y.createSCP(xR{nn}.opFolder);
|
|
| 158 |
y.test(xR{nn}.opFolder);
|
|
| 159 |
end |
|
| 160 |
|
|
| 161 |
%Show all of the scores in the command window at the end |
|
| 162 |
for nn = 1:maxConds |
|
| 163 |
y.score(xR{nn}.opFolder);
|
|
| 164 |
end |
|
| 165 |
end |
|
| userProgramsASRforDummies/Exp_Tutorial_2.m | ||
|---|---|---|
| 1 |
function Exp_Tutorial_2(isMasterNode) |
|
| 2 |
|
|
| 3 |
% This tutorial recycles a HMM |
|
| 4 |
|
|
| 5 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 6 |
% Set up the basic experiment parameters |
|
| 7 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 8 |
expName = 'Tutorial'; |
|
| 9 |
dataFolderPrefix = 'recycle_featR'; |
|
| 10 |
if isunix |
|
| 11 |
expFolderPrefix = '/scratch/nrclark/exps/'; |
|
| 12 |
else |
|
| 13 |
expFolderPrefix = 'D:\Exps'; |
|
| 14 |
end |
|
| 15 |
|
|
| 16 |
% expFolderPrefix = pwd; |
|
| 17 |
expFolder = fullfile(expFolderPrefix,expName); |
|
| 18 |
hmmFolder = fullfile(expFolder,'hmm'); |
|
| 19 |
|
|
| 20 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 21 |
% Sort out the training (LEARNING) condition |
|
| 22 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 23 |
learnFolder = fullfile(expFolder,'featL'); |
|
| 24 |
|
|
| 25 |
xL = cJob('L', learnFolder);
|
|
| 26 |
|
|
| 27 |
xL.participant = 'Normal'; |
|
| 28 |
xL.MAPparamChanges= {'DRNLParams.rateToAttenuationFactorProb=0;', 'OMEParams.rateToAttenuationFactorProb=0;' };
|
|
| 29 |
|
|
| 30 |
xL.noiseLevToUse = -200; |
|
| 31 |
xL.speechLevToUse = 60; |
|
| 32 |
|
|
| 33 |
xL.MAPopHSR = 1; |
|
| 34 |
xL.MAPopMSR = 0; |
|
| 35 |
xL.MAPopLSR = 0; |
|
| 36 |
|
|
| 37 |
|
|
| 38 |
xL.numCoeff = 14; |
|
| 39 |
xL.removeEnergyStatic = 0; |
|
| 40 |
|
|
| 41 |
%%%%% Group of params that will influence simulation run time %%%%%%% |
|
| 42 |
xL.numWavs = 12; %MAX=8440 |
|
| 43 |
testWavs = 6; %MAX = 358 |
|
| 44 |
nzLevel = [-200 40:10:70]; |
|
| 45 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 46 |
|
|
| 47 |
xL.noisePreDur = 1; |
|
| 48 |
xL.noisePostDur = 0.1; |
|
| 49 |
xL.truncateDur = xL.noisePreDur-0.1; |
|
| 50 |
xL.noiseName = 'pink_demo'; |
|
| 51 |
|
|
| 52 |
|
|
| 53 |
% if isMasterNode && ~isdir(xL.opFolder) |
|
| 54 |
% mkdir(xL.opFolder); |
|
| 55 |
% xL = xL.assignFiles; |
|
| 56 |
% xL.storeSelf; |
|
| 57 |
% end |
|
| 58 |
|
|
| 59 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 60 |
% Sort out the testing (RECOGNITION) conditions |
|
| 61 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 62 |
recConditions = numel(nzLevel); |
|
| 63 |
|
|
| 64 |
tmpIdx=0; |
|
| 65 |
for nn = 0*recConditions+1:1*recConditions |
|
| 66 |
tmpIdx=tmpIdx+1; |
|
| 67 |
xR{nn} = xL; %simply copy the "Learn" object and change it a bit below
|
|
| 68 |
recFolder = fullfile(expFolder,[dataFolderPrefix num2str(nn)]); |
|
| 69 |
xR{nn}.opFolder = recFolder;
|
|
| 70 |
|
|
| 71 |
%These are the interesting differences between training and testing |
|
| 72 |
xR{nn}.numWavs = testWavs; %MAX = 358
|
|
| 73 |
xR{nn}.noiseLevToUse = nzLevel(tmpIdx);
|
|
| 74 |
xR{nn}.MAPparamChanges= {'DRNLParams.a=400;'};
|
|
| 75 |
|
|
| 76 |
|
|
| 77 |
%Now just to wrap it up ready for processing |
|
| 78 |
if isMasterNode && ~isdir(xR{nn}.opFolder)
|
|
| 79 |
mkdir(xR{nn}.opFolder);
|
|
| 80 |
xR{nn} = xR{nn}.assignWavPaths('R');
|
|
| 81 |
xR{nn} = xR{nn}.assignFiles;
|
|
| 82 |
xR{nn}.storeSelf;
|
|
| 83 |
end |
|
| 84 |
end |
|
| 85 |
|
|
| 86 |
tmpIdx=0; |
|
| 87 |
for nn = 1*recConditions+1:2*recConditions |
|
| 88 |
tmpIdx=tmpIdx+1; |
|
| 89 |
xR{nn} = xL; %simply copy the "Learn" object and change it a bit below
|
|
| 90 |
recFolder = fullfile(expFolder,[dataFolderPrefix num2str(nn)]); |
|
| 91 |
xR{nn}.opFolder = recFolder;
|
|
| 92 |
|
|
| 93 |
%These are the interesting differences between training and testing |
|
| 94 |
xR{nn}.numWavs = testWavs; %MAX = 358
|
|
| 95 |
xR{nn}.noiseLevToUse = nzLevel(tmpIdx);
|
|
| 96 |
xR{nn}.MAPparamChanges= {'DRNLParams.a=400;'};
|
|
| 97 |
|
|
| 98 |
xR{nn}.mainGain = [27.2013; 26.0797; 26.0939; 26.7997; 26.0520];
|
|
| 99 |
xR{nn}.TCdBO = [37; 37; 37; 37; 37]; %Compression thresholds (in dB OUTPUT from 2nd filt)
|
|
| 100 |
xR{nn}.TMdBO = [20; 20; 20; 20; 20]; %MOC thresholds (in dB OUTPUT from 2nd filt)
|
|
| 101 |
xR{nn}.ARthresholddB = 85; % dB SPL (input signal level) =>200 to disable
|
|
| 102 |
xR{nn}.MOCtau = 1;
|
|
| 103 |
xR{nn}.useAid = 1;
|
|
| 104 |
|
|
| 105 |
%Now just to wrap it up ready for processing |
|
| 106 |
if isMasterNode && ~isdir(xR{nn}.opFolder)
|
|
| 107 |
mkdir(xR{nn}.opFolder);
|
|
| 108 |
xR{nn} = xR{nn}.assignWavPaths('R');
|
|
| 109 |
xR{nn} = xR{nn}.assignFiles;
|
|
| 110 |
xR{nn}.storeSelf;
|
|
| 111 |
end |
|
| 112 |
end |
|
| 113 |
|
|
| 114 |
|
|
| 115 |
|
|
| 116 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 117 |
% ** Generate features ** |
|
| 118 |
% This is the time consuming, processing intensive portion of the program. |
|
| 119 |
% Nodes that are not the master node are only interested in the opFolder |
|
| 120 |
% member of the jobjects. |
|
| 121 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 122 |
% worker(xL.opFolder); |
|
| 123 |
maxConds = nn; |
|
| 124 |
if ~isMasterNode %dont bother wasting master node effort on generating testing features (for now) |
|
| 125 |
for nn = 1:maxConds |
|
| 126 |
worker(xR{nn}.opFolder);
|
|
| 127 |
end |
|
| 128 |
end |
|
| 129 |
|
|
| 130 |
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 131 |
% Train and test the recogniser - a job for the master node only |
|
| 132 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 133 |
if isMasterNode |
|
| 134 |
% while(~all(xL.todoStatus==2)) |
|
| 135 |
% disp('Waiting on straggler nodes to complete their jobs before HMM is trained . . .')
|
|
| 136 |
% pause(30); %Wait for 30 seconds before looking again |
|
| 137 |
% xL.lockJobList; |
|
| 138 |
% xL = xL.loadSelf; %Reload incase changed |
|
| 139 |
% xL.unlockJobList; |
|
| 140 |
% end |
|
| 141 |
y = cHMM(hmmFolder); |
|
| 142 |
y.numCoeff = 14*3; |
|
| 143 |
% y.createSCP(xL.opFolder) |
|
| 144 |
% y.createMLF(xL.opFolder) |
|
| 145 |
% y.train(xL.opFolder) %This node can be busy training, even if other jobs are being processed for testing |
|
| 146 |
|
|
| 147 |
% ALLOW MASTER NODE TO MUCK IN WITH GENERATING TESTING FEATURES ONCE |
|
| 148 |
% HMM HAS BEEN TRAINED |
|
| 149 |
for nn = 1:maxConds |
|
| 150 |
worker(xR{nn}.opFolder);
|
|
| 151 |
end |
|
| 152 |
|
|
| 153 |
xR{end}.lockJobList;
|
|
| 154 |
xR{end} = xR{end}.loadSelf; %Reload changes
|
|
| 155 |
xR{end}.unlockJobList;
|
|
| 156 |
while(~all(xR{end}.todoStatus==2))
|
|
| 157 |
disp('Waiting on straggler nodes to complete their jobs before HMM is tested . . .')
|
|
| 158 |
pause(30); %Wait for 30 seconds before looking again |
|
| 159 |
xR{end}.lockJobList;
|
|
| 160 |
xR{end} = xR{end}.loadSelf; %Reload incase changed
|
|
| 161 |
xR{end}.unlockJobList;
|
|
| 162 |
end |
|
| 163 |
|
|
| 164 |
for nn = 1:maxConds |
|
| 165 |
y.createSCP(xR{nn}.opFolder);
|
|
| 166 |
y.test(xR{nn}.opFolder);
|
|
| 167 |
end |
|
| 168 |
|
|
| 169 |
%Show all of the scores in the command window at the end |
|
| 170 |
for nn = 1:maxConds |
|
| 171 |
y.score(xR{nn}.opFolder);
|
|
| 172 |
end |
|
| 173 |
end |
|
| userProgramsASRforDummies/MAPwrap.m | ||
|---|---|---|
| 1 |
% This function wraps up whatever version of MAP I want to call. It is |
|
| 2 |
% implemented partly because I want to avoid messing with jobject too much |
|
| 3 |
% and mostly because I dont want to declare globals in my class. |
|
| 4 |
|
|
| 5 |
function [myANprobRateOutput, mydt, myBF] = MAPwrap(stimulus, sampleRate, BFlist, participant, AN_spikesOrProbability, paramChanges) |
|
| 6 |
|
|
| 7 |
|
|
| 8 |
global ANprobRateOutput dt BFlist |
|
| 9 |
% disp(20*log10(sqrt(mean(stimulus.^2))/20e-6)) |
|
| 10 |
MAP1_14(stimulus, sampleRate, BFlist, participant, AN_spikesOrProbability, paramChanges); |
|
| 11 |
% disp(20*log10(sqrt(mean(stimulus.^2))/20e-6)) |
|
| 12 |
myANprobRateOutput = ANprobRateOutput; |
|
| 13 |
mydt = dt; |
|
| 14 |
myBF = BFlist; |
|
| userProgramsASRforDummies/cEssexAid.m | ||
|---|---|---|
| 1 |
classdef cEssexAid |
|
| 2 |
%ESSEXAID_WRAPCLASS Wrapper for the EssexAid - Nick Clark July 2011 |
|
| 3 |
% This class wraps up the EssexAid algorithm function that processes |
|
| 4 |
% each block of samples. This wrapper closely emulates the GUI used |
|
| 5 |
% in the lab and runs stimuli through the exact same algorithm used |
|
| 6 |
% in the lab. It even includes a helper function to generate C code |
|
| 7 |
% from the algorithm for use in a real-time framework. |
|
| 8 |
|
|
| 9 |
|
|
| 10 |
%% ********************************************************* |
|
| 11 |
% properties _ _ |
|
| 12 |
% | | (_) |
|
| 13 |
% _ __ _ __ ___ _ __ ___ _ __| |_ _ ___ ___ |
|
| 14 |
% | '_ \| '__/ _ \| '_ \ / _ \ '__| __| |/ _ \/ __| |
|
| 15 |
% | |_) | | | (_) | |_) | __/ | | |_| | __/\__ \ |
|
| 16 |
% | .__/|_| \___/| .__/ \___|_| \__|_|\___||___/ |
|
| 17 |
% | | | | |
|
| 18 |
% |_| |_| |
|
| 19 |
%************************************************************ |
|
| 20 |
|
|
| 21 |
%% ********************************************************** |
|
| 22 |
% Public properties - can be set by user |
|
| 23 |
%************************************************************ |
|
| 24 |
properties(Access = public) |
|
| 25 |
sr = 48e3; |
|
| 26 |
numSamples = 1024; %MAX=6912, LAB_USE=48 |
|
| 27 |
stimulusUSER |
|
| 28 |
|
|
| 29 |
%------------------------------------------------------------------ |
|
| 30 |
% Params for audiometric freqs 250, 500, 1000, 2000, 4000, 8000 Hz |
|
| 31 |
%------------------------------------------------------------------ |
|
| 32 |
audiometry_dB= [ 0; 0; 0; 0; 0; 0]; %Pure tone threshold in dB SPL |
|
| 33 |
mainGain_dB = [ 0; 0; 0; 0; 0; 0]; %Gain applied at audiometric frequencies |
|
| 34 |
TC_dBHL = [40; 40; 40; 40; 40; 40]; %Compression thresholds (in dB HL from 2nd filt) |
|
| 35 |
TM_dBHL = [10; 10; 10; 10; 10; 10]; %MOC thresholds (in dB OUTPUT from 2nd filt) |
|
| 36 |
DRNLc = [ 0.2; 0.2; 0.2; 0.2; 0.2; 0.2]; %Compression exponent at audiometric frequencies |
|
| 37 |
|
|
| 38 |
%------------------------------------------------------------------ |
|
| 39 |
% Dynamic compression properties |
|
| 40 |
%------------------------------------------------------------------ |
|
| 41 |
ARtau = 60e-3; %decay time constant |
|
| 42 |
ARthreshold_dB = 85; %dB SPL (input signal level) =>200 to disable |
|
| 43 |
MOCtau = 450e-3; %Time constant in Seconds |
|
| 44 |
MOCfactor = 0.5; %dB attenuation applied to the input per dB exceeding output threshold |
|
| 45 |
|
|
| 46 |
%------------------------------------------------------------------ |
|
| 47 |
% Band filtering properties |
|
| 48 |
%------------------------------------------------------------------ |
|
| 49 |
bwOct = 1/2; %1/1, 1/2, 1/3, 1/4, 1/5 |
|
| 50 |
filterOrder = 2 %BUTTER=2, GTF=3 |
|
| 51 |
useGTF = false; %If false, revert to butterworth |
|
| 52 |
end |
|
| 53 |
|
|
| 54 |
%% ********************************************************** |
|
| 55 |
% Read only properties that are not dependent |
|
| 56 |
%************************************************************ |
|
| 57 |
properties(SetAccess = private) |
|
| 58 |
MOCrecord |
|
| 59 |
end |
|
| 60 |
|
|
| 61 |
%% ********************************************************** |
|
| 62 |
% Constant properties |
|
| 63 |
%************************************************************ |
|
| 64 |
properties(Constant = true, Hidden = true) |
|
| 65 |
numAudiometricFreqs = 6; |
|
| 66 |
end |
|
| 67 |
|
|
| 68 |
%% ********************************************************** |
|
| 69 |
% Dependent visable properties - calculated at runtime |
|
| 70 |
%************************************************************ |
|
| 71 |
properties(Dependent = true, Hidden = false) |
|
| 72 |
channelBFs %= 250 * 2.^((0:fNmax)'*params.bwOct); |
|
| 73 |
numChannels %= numel(channelBFs); |
|
| 74 |
aidOPnice %aid output reformatted to be exactly the same dimensions as the input stimulus |
|
| 75 |
end |
|
| 76 |
|
|
| 77 |
%% ********************************************************** |
|
| 78 |
% Dependent invisable properties - calculated at runtime |
|
| 79 |
%************************************************************ |
|
| 80 |
properties(Dependent = true, Hidden = true) |
|
| 81 |
TC_dBO_INTERP % Compression threshold in terms of 2nd filter o/p in dB SPL |
|
| 82 |
TM_dBO_INTERP % MOC threshold in terms of 2nd filter o/p in dB SPL |
|
| 83 |
bwOct_INTERP |
|
| 84 |
DRNLb_INTERP %= ( 2e-5 .* 10.^(TCdBO/20)) .^ (1-DRNLc) ; |
|
| 85 |
DRNLc_INTERP |
|
| 86 |
mainGain_INTERP %Interp'd and in linear units |
|
| 87 |
|
|
| 88 |
ARthresholdPa %= 20e-6*10^(ARthreshold_dB/20);% Pa thresh for triggering AR |
|
| 89 |
stimulusINTERNAL %input stimulus in correct format for the Aid algo |
|
| 90 |
end |
|
| 91 |
|
|
| 92 |
%% ********************************************************** |
|
| 93 |
% Protected properties - The user never needs to set |
|
| 94 |
%************************************************************ |
|
| 95 |
properties(Access = protected) |
|
| 96 |
aidOP |
|
| 97 |
emlc_z |
|
| 98 |
|
|
| 99 |
%-------------------------------------------------------------- |
|
| 100 |
% ENUMERATIONS USED IN THE FRAME PROCESSOR |
|
| 101 |
%-------------------------------------------------------------- |
|
| 102 |
enumC_ARb = 0; |
|
| 103 |
enumC_ARa = 2; |
|
| 104 |
enumC_MOCb = 4; |
|
| 105 |
enumC_MOCa = 6; |
|
| 106 |
|
|
| 107 |
% enumC_BPb1 = 8; |
|
| 108 |
% enumC_BPa1 = 13; |
|
| 109 |
% enumC_BPb2 = 18; |
|
| 110 |
% enumC_BPa2 = 23; |
|
| 111 |
% enumC_BPb3 = 28; |
|
| 112 |
% enumC_BPa3 = 33; |
|
| 113 |
% enumC_BPb4 = 38; |
|
| 114 |
% enumC_BPa4 = 43; |
|
| 115 |
|
|
| 116 |
enumS_AR = 0; |
|
| 117 |
|
|
| 118 |
% enumS_MOC1 = 1; |
|
| 119 |
% enumS_BPin_1_1 = 2; |
|
| 120 |
% enumS_BPin_2_1 = 6; |
|
| 121 |
% enumS_BPout_1_1 = 10; |
|
| 122 |
% enumS_BPout_2_1 = 14; |
|
| 123 |
% |
|
| 124 |
% enumS_MOC2 = 18; |
|
| 125 |
% enumS_BPin_1_2 = 19; |
|
| 126 |
% enumS_BPin_2_2 = 23; |
|
| 127 |
% enumS_BPout_1_2 = 27; |
|
| 128 |
% enumS_BPout_2_2 = 31; |
|
| 129 |
% ... |
|
| 130 |
end |
|
| 131 |
|
|
| 132 |
%% ********************************************************** |
|
| 133 |
% methods _ _ _ |
|
| 134 |
% | | | | | | |
|
| 135 |
% _ __ ___ ___| |_| |__ ___ __| |___ |
|
| 136 |
%| '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __| |
|
| 137 |
%| | | | | | __/ |_| | | | (_) | (_| \__ \ |
|
| 138 |
%|_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/ |
|
| 139 |
%************************************************************ |
|
| 140 |
|
|
| 141 |
methods |
|
| 142 |
%% ********************************************************** |
|
| 143 |
% Constructor |
|
| 144 |
%************************************************************ |
|
| 145 |
function obj = EssexAid_WrapClass(sr, stimulus) |
|
| 146 |
|
|
| 147 |
if nargin > 0 |
|
| 148 |
obj.sr = sr; |
|
| 149 |
end |
|
| 150 |
|
|
| 151 |
if nargin > 1 |
|
| 152 |
obj.stimulusUSER = stimulus; |
|
| 153 |
else |
|
| 154 |
obj.stimulusUSER = obj.pipSequence(obj.sr); |
|
| 155 |
end |
|
| 156 |
end |
|
| 157 |
|
|
| 158 |
%% ********************************************************** |
|
| 159 |
% Get method for channelBFs |
|
| 160 |
%************************************************************ |
|
| 161 |
function value = get.channelBFs(obj) |
|
| 162 |
fNmax = 5/obj.bwOct; |
|
| 163 |
value = 250 * 2.^((0:fNmax)'*obj.bwOct); |
|
| 164 |
end |
|
| 165 |
|
|
| 166 |
%% ********************************************************** |
|
| 167 |
% Get method for numChannels |
|
| 168 |
%************************************************************ |
|
| 169 |
function value = get.numChannels(obj) |
|
| 170 |
value = numel(obj.channelBFs); |
|
| 171 |
end |
|
| 172 |
|
|
| 173 |
%% ********************************************************** |
|
| 174 |
% Get method for ARthresholdPa |
|
| 175 |
%************************************************************ |
|
| 176 |
function value = get.ARthresholdPa(obj) |
|
| 177 |
value = 20e-6*10^(obj.ARthreshold_dB/20);% Pa thresh for triggering AR |
|
| 178 |
end |
|
| 179 |
|
|
| 180 |
%% ********************************************************** |
|
| 181 |
% Get method for TC_dBO_INTERP |
|
| 182 |
%************************************************************ |
|
| 183 |
function value = get.TC_dBO_INTERP(obj) |
|
| 184 |
TC_dBO = obj.audiometry_dB - obj.mainGain_dB + obj.TC_dBHL; |
|
| 185 |
value = obj.interpPars(TC_dBO, obj.numChannels); |
|
| 186 |
end |
|
| 187 |
|
|
| 188 |
%% ********************************************************** |
|
| 189 |
% Get method for TM_dBO_INTERP |
|
| 190 |
%************************************************************ |
|
| 191 |
function value = get.TM_dBO_INTERP(obj) |
|
| 192 |
TM_dBO = obj.audiometry_dB - obj.mainGain_dB + obj.TM_dBHL; |
|
| 193 |
value = obj.interpPars(TM_dBO, obj.numChannels); |
|
| 194 |
end |
|
| 195 |
|
|
| 196 |
%% ********************************************************** |
|
| 197 |
% Get method for bwOct_INTERP |
|
| 198 |
%************************************************************ |
|
| 199 |
function value = get.bwOct_INTERP(obj) |
|
| 200 |
value = repmat(obj.bwOct, 1, obj.numChannels); |
|
| 201 |
end |
|
| 202 |
|
|
| 203 |
%% ********************************************************** |
|
| 204 |
% Get method for DRNLb_INTERP |
|
| 205 |
%************************************************************ |
|
| 206 |
function value = get.DRNLb_INTERP(obj) |
|
| 207 |
value = ( 2e-5 .* 10.^(obj.TC_dBO_INTERP/20)) .^ (1-obj.DRNLc_INTERP); |
|
| 208 |
end |
|
| 209 |
|
|
| 210 |
%% ********************************************************** |
|
| 211 |
% Get method for DRNLc_INTERP |
|
| 212 |
%************************************************************ |
|
| 213 |
function value = get.DRNLc_INTERP(obj) |
|
| 214 |
value = obj.interpPars(obj.DRNLc, obj.numChannels); |
|
| 215 |
end |
|
| 216 |
|
|
| 217 |
%% ********************************************************** |
|
| 218 |
% Get method for mainGain_INTERP |
|
| 219 |
%************************************************************ |
|
| 220 |
function value = get.mainGain_INTERP(obj) |
|
| 221 |
mainGainLin = 10.^(obj.mainGain_dB/20); %lin units |
|
| 222 |
value = obj.interpPars(mainGainLin, obj.numChannels); |
|
| 223 |
end |
|
| 224 |
|
|
| 225 |
%% *********************************************************** |
|
| 226 |
% Get method for stimulus |
|
| 227 |
% ----------------------- |
|
| 228 |
% The hearing aid expects a stereo signal, as the MOC control is |
|
| 229 |
% linked for left and right channels. It would be more efficient to |
|
| 230 |
% use a mono version of the aid for simulation in Matlab. However, |
|
| 231 |
% I always want to use the exact same code for the hardware in the |
|
| 232 |
% lab and current simulations. This code will make a mono signal |
|
| 233 |
% stereo if needs be and/or rotate to 2xN array. |
|
| 234 |
%************************************************************* |
|
| 235 |
function value = get.stimulusINTERNAL(obj) |
|
| 236 |
[nRows, nCols] = size(obj.stimulusUSER); |
|
| 237 |
|
|
| 238 |
% Assume that the stimulus duration is greater than 2 samples. |
|
| 239 |
% Therefore the number of channels is the min dim. |
|
| 240 |
[nChans, I] = min([nRows nCols]); |
|
| 241 |
|
|
| 242 |
if nChans == 2 |
|
| 243 |
if I == 2 |
|
| 244 |
value = obj.stimulusUSER; |
|
| 245 |
else |
|
| 246 |
value = obj.stimulusUSER'; |
|
| 247 |
end |
|
| 248 |
elseif nChans == 1 %Just to be explicit |
|
| 249 |
if I == 2 |
|
| 250 |
value = [obj.stimulusUSER obj.stimulusUSER]; |
|
| 251 |
else |
|
| 252 |
value = [obj.stimulusUSER; obj.stimulusUSER]'; |
|
| 253 |
end |
|
| 254 |
end |
|
| 255 |
end |
|
| 256 |
|
|
| 257 |
%% *********************************************************** |
|
| 258 |
% Get method for aid output |
|
| 259 |
% ----------------------- |
|
| 260 |
% This get method is linked to the above internal stimulus method |
|
| 261 |
% and allows the user to extract the hearing aid output in exactly |
|
| 262 |
% the same shape and size as the original input stimulus. This is |
|
| 263 |
% very useful for the speech recognition work and presumably |
|
| 264 |
% for multithreshold also. |
|
| 265 |
%************************************************************* |
|
| 266 |
function value = get.aidOPnice(obj) |
|
| 267 |
if ~isempty(obj.aidOP) |
|
| 268 |
[nRows, nCols] = size(obj.stimulusUSER); |
|
| 269 |
|
|
| 270 |
% Assume that the stimulus duration is greater than 2 samples. |
|
| 271 |
% Therefore the number of channels is the min dim. |
|
| 272 |
[nChans, I] = min([nRows nCols]); |
|
| 273 |
|
|
| 274 |
%** The aid output will ALWAYS be a 2xN array ** |
|
| 275 |
%The fist job is to remove trailing zeros that may have been |
|
| 276 |
%introduced by the framing process |
|
| 277 |
aidOPtruncated = obj.aidOP(:, 1:max([nRows nCols])); |
|
| 278 |
|
|
| 279 |
%The next task is to arrange the op like the ip |
|
| 280 |
if nChans == 2 |
|
| 281 |
if I == 1 |
|
| 282 |
value = aidOPtruncated; |
|
| 283 |
else |
|
| 284 |
value = aidOPtruncated'; |
|
| 285 |
end |
|
| 286 |
elseif nChans == 1 %Just to be explicit |
|
| 287 |
if I == 1 |
|
| 288 |
value = aidOPtruncated(1,:); |
|
| 289 |
else |
|
| 290 |
value = aidOPtruncated(1,:)'; |
|
| 291 |
end |
|
| 292 |
end |
|
| 293 |
else % ---- of if isempty statement |
|
| 294 |
value = []; |
|
| 295 |
end |
|
| 296 |
end |
|
| 297 |
|
|
| 298 |
%% *********************************************************** |
|
| 299 |
% *** Set methods *** |
|
| 300 |
% ----------------------- |
|
| 301 |
% This is a bunch of unexciting error hunting functions. They also |
|
| 302 |
% flush the aid output if any parameters change. Therefore, |
|
| 303 |
% processStim will have to be called explicity by the user once |
|
| 304 |
% again. |
|
| 305 |
%************************************************************* |
|
| 306 |
function obj = set.stimulusUSER(obj,value) |
|
| 307 |
[nRows, nCols] = size(value); |
|
| 308 |
|
|
| 309 |
% Assume that the stimulus duration is greater than 2 samples. |
|
| 310 |
% Therefore the number of channels is the min dim. |
|
| 311 |
nChans = min([nRows nCols]); |
|
| 312 |
assert(nChans<3 && nChans, 'Number of stimulus channels must be 1 or 2') |
|
| 313 |
|
|
| 314 |
obj = obj.flushAidData; %flush any previous hearing aid data if the input stimulus changes |
|
| 315 |
obj.stimulusUSER = value; |
|
| 316 |
end |
|
| 317 |
function obj = set.sr(obj,value) |
|
| 318 |
assert(value>=20e3 && value<=192e3, 'sr must be between 20 and 192 kHz') |
|
| 319 |
obj = obj.flushAidData; |
|
| 320 |
obj.sr = value; |
|
| 321 |
end |
|
| 322 |
function obj = set.numSamples(obj,value) |
|
| 323 |
assert(value>=48 && value<=6912, 'must be between 48 and 6912 samples') |
|
| 324 |
obj = obj.flushAidData; |
|
| 325 |
obj.numSamples = value; |
|
| 326 |
end |
|
| 327 |
function obj = set.audiometry_dB(obj,value) |
|
| 328 |
[nRows,nCols] = size(value); |
|
| 329 |
assert(nRows==obj.numAudiometricFreqs && nCols==1, 'must be 6x1 column vector') %#ok<MCSUP> |
|
| 330 |
obj = obj.flushAidData; |
|
| 331 |
obj.audiometry_dB = value; |
|
| 332 |
end |
|
| 333 |
function obj = set.mainGain_dB(obj,value) |
|
| 334 |
[nRows,nCols] = size(value); |
|
| 335 |
assert(nRows==obj.numAudiometricFreqs && nCols==1, 'must be 6x1 column vector') %#ok<MCSUP> |
|
| 336 |
obj = obj.flushAidData; |
|
| 337 |
obj.mainGain_dB = value; |
|
| 338 |
end |
|
| 339 |
function obj = set.TC_dBHL(obj,value) |
|
| 340 |
[nRows,nCols] = size(value); |
|
| 341 |
assert(nRows==obj.numAudiometricFreqs && nCols==1, 'must be 6x1 column vector') %#ok<MCSUP> |
|
| 342 |
obj = obj.flushAidData; |
|
| 343 |
obj.TC_dBHL = value; |
|
| 344 |
end |
|
| 345 |
function obj = set.TM_dBHL(obj,value) |
|
| 346 |
[nRows,nCols] = size(value); |
|
| 347 |
assert(nRows==obj.numAudiometricFreqs && nCols==1, 'must be 6x1 column vector') %#ok<MCSUP> |
|
| 348 |
obj = obj.flushAidData; |
|
| 349 |
obj.TM_dBHL = value; |
|
| 350 |
end |
|
| 351 |
function obj = set.DRNLc(obj,value) |
|
| 352 |
[nRows,nCols] = size(value); |
|
| 353 |
assert(nRows==obj.numAudiometricFreqs && nCols==1, 'must be 6x1 column vector') %#ok<MCSUP> |
|
| 354 |
assert(all(value)>=0 && all(value)<=1, 'all DRNLc values must be between 0 and 1') |
|
| 355 |
obj = obj.flushAidData; |
|
| 356 |
obj.DRNLc = value; |
|
| 357 |
end |
|
| 358 |
function obj = set.ARtau(obj,value) |
|
| 359 |
assert(value>=1e-3 && value<=1, 'must be between 1e-3 and 1s') |
|
| 360 |
obj = obj.flushAidData; |
|
| 361 |
obj.ARtau = value; |
|
| 362 |
end |
|
| 363 |
function obj = set.ARthreshold_dB(obj,value) |
|
| 364 |
assert(value>0, 'set AR to a high value to disable it') |
|
| 365 |
obj = obj.flushAidData; |
|
| 366 |
obj.ARthreshold_dB = value; |
|
| 367 |
end |
|
| 368 |
function obj = set.MOCtau(obj,value) |
|
| 369 |
assert(value>=1e-3 && value<=2, 'must be between 1e-3 and 2s') |
|
| 370 |
obj = obj.flushAidData; |
|
| 371 |
obj.MOCtau = value; |
|
| 372 |
end |
|
| 373 |
function obj = set.MOCfactor(obj,value) |
|
| 374 |
assert(value>=0 && value<=1, 'must be between 0 and 1') |
|
| 375 |
obj = obj.flushAidData; |
|
| 376 |
obj.MOCfactor = value; |
|
| 377 |
end |
|
| 378 |
function obj = set.bwOct(obj,value) |
|
| 379 |
assert(value==1/1 || value==1/2 || value==1/3 || value==1/4 || value==1/5, 'must be one of 1./(1:5)') |
|
| 380 |
obj = obj.flushAidData; |
|
| 381 |
obj.bwOct = value; |
|
| 382 |
end |
|
| 383 |
function obj = set.filterOrder(obj,value) |
|
| 384 |
assert(value>0 && value<5, 'must be one of 1:4') |
|
| 385 |
obj = obj.flushAidData; |
|
| 386 |
obj.filterOrder = value; |
|
| 387 |
end |
|
| 388 |
function obj = set.useGTF(obj,value) |
|
| 389 |
obj = obj.flushAidData; |
|
| 390 |
obj.useGTF = value; |
|
| 391 |
end |
|
| 392 |
|
|
| 393 |
%% ********************************************************** |
|
| 394 |
% flushAidData |
|
| 395 |
% This second function is a workaround allowing a set method to |
|
| 396 |
% change another property value. |
|
| 397 |
%************************************************************ |
|
| 398 |
function obj = flushAidData(obj) |
|
| 399 |
obj.aidOP = []; |
|
| 400 |
obj.MOCrecord = []; |
|
| 401 |
end |
|
| 402 |
|
|
| 403 |
|
|
| 404 |
%% ********************************************************** |
|
| 405 |
% OVERLOADED plot method |
|
| 406 |
%************************************************************ |
|
| 407 |
function plot(obj) |
|
| 408 |
clf |
|
| 409 |
sig2dBSPL = @(sig)20*log10(abs(sig/20e-6)+(1/(2^32))); |
|
| 410 |
dt = 1/obj.sr; |
|
| 411 |
tAxis = dt:dt:dt*size(obj.stimulusINTERNAL,1); |
|
| 412 |
|
|
| 413 |
subplot(2,1,1) |
|
| 414 |
plot(tAxis(1:length(obj.stimulusUSER)), sig2dBSPL(obj.stimulusUSER), 'k') |
|
| 415 |
if ~isempty(obj.aidOPnice) |
|
| 416 |
hold on |
|
| 417 |
plot(tAxis(1:length(obj.stimulusUSER)), sig2dBSPL(obj.aidOPnice), 'r') |
|
| 418 |
end |
|
| 419 |
ylim([0 100]) |
|
| 420 |
xlim([0 tAxis(length(obj.stimulusUSER))]) |
|
| 421 |
title('Level response')
|
|
| 422 |
xlabel('Time in seconds')
|
|
| 423 |
ylabel('Level in dB SPL')
|
|
| 424 |
|
|
| 425 |
subplot(2,1,2) |
|
| 426 |
if ~isempty(obj.MOCrecord) |
|
| 427 |
imagesc(tAxis, 1:obj.numChannels, flipud(-20*log10(obj.MOCrecord))) |
|
| 428 |
colorbar |
|
| 429 |
end |
|
| 430 |
title('MOC attenuation')
|
|
| 431 |
xlabel('Time in seconds')
|
|
| 432 |
ylabel('Band frequency in Hz')
|
|
| 433 |
numSpacers = 1 + (obj.numChannels-numel(obj.DRNLc)) / (numel(obj.DRNLc)-1); |
|
| 434 |
set(gca, 'YTick', 1:numSpacers:obj.numChannels); |
|
| 435 |
set(gca, 'YTickLabel', num2str(flipud([250; 500; 1000; 2000; 4000; 8000]))); |
|
| 436 |
end% ------ OVERLOADED plot method |
|
| 437 |
|
|
| 438 |
%% ********************************************************** |
|
| 439 |
% OVERLOADED soundsc method |
|
| 440 |
%************************************************************ |
|
| 441 |
function soundsc(obj) |
|
| 442 |
soundsc(obj.aidOPnice, obj.sr) |
|
| 443 |
end |
|
| 444 |
|
|
| 445 |
%% ********************************************************** |
|
| 446 |
% processStim |
|
| 447 |
%************************************************************ |
|
| 448 |
function obj = processStim(obj) |
|
| 449 |
%-------------------------------------------------------------- |
|
| 450 |
% EMULATION OF THE GUI PARAMETER CONVERSIONS |
|
| 451 |
%-------------------------------------------------------------- |
|
| 452 |
biggestNumSamples = obj.numSamples; |
|
| 453 |
|
|
| 454 |
filterStatesL = (zeros(3000,1)); |
|
| 455 |
filterStatesR = filterStatesL; |
|
| 456 |
filterCoeffs = (zeros(5000,1)); |
|
| 457 |
|
|
| 458 |
%filter coefficients |
|
| 459 |
ARcutOff=1/(2*pi*obj.ARtau); |
|
| 460 |
[b,a] = butter(1,ARcutOff/(obj.sr/2)); |
|
| 461 |
filterCoeffs(obj.enumC_ARb+1:obj.enumC_ARb+2) = b; |
|
| 462 |
filterCoeffs(obj.enumC_ARa+1:obj.enumC_ARa+2) = a; |
|
| 463 |
|
|
| 464 |
MOCcutOff=1/(2*pi*obj.MOCtau); |
|
| 465 |
[bMOC,aMOC] = butter(1,MOCcutOff/(obj.sr/2)); |
|
| 466 |
filterCoeffs(obj.enumC_MOCb+1:obj.enumC_MOCb+2) = bMOC; |
|
| 467 |
filterCoeffs(obj.enumC_MOCa+1:obj.enumC_MOCa+2) = aMOC; |
|
| 468 |
|
|
| 469 |
|
|
| 470 |
for filterCount = 1:obj.numChannels |
|
| 471 |
%----------------------------------- |
|
| 472 |
% nonlinear path - filter bws |
|
| 473 |
%----------------------------------- |
|
| 474 |
lowerCutOff=obj.channelBFs(filterCount)*2^(-obj.bwOct_INTERP(filterCount)/2); |
|
| 475 |
upperCutOff=obj.channelBFs(filterCount)*2^( obj.bwOct_INTERP(filterCount)/2); |
|
| 476 |
|
|
| 477 |
if obj.useGTF |
|
| 478 |
bwHz = upperCutOff - lowerCutOff; |
|
| 479 |
[b_DRNL,a_DRNL] = obj.gammatone(bwHz, obj.channelBFs(filterCount), 1/obj.sr); |
|
| 480 |
filterCoeffs(10*(filterCount-1)+9 :10*(filterCount-1)+10) = b_DRNL; |
|
| 481 |
filterCoeffs(10*(filterCount-1)+14:10*(filterCount-1)+16) = a_DRNL; |
|
| 482 |
else |
|
| 483 |
[b_DRNL,a_DRNL] = butter(2,[lowerCutOff upperCutOff]/(obj.sr/2)); |
|
| 484 |
filterCoeffs(10*(filterCount-1)+9 :10*(filterCount-1)+13) = b_DRNL; |
|
| 485 |
filterCoeffs(10*(filterCount-1)+14:10*(filterCount-1)+18) = a_DRNL; |
|
| 486 |
end |
|
| 487 |
end |
|
| 488 |
|
|
| 489 |
%-------------------------------------------------------------- |
|
| 490 |
% EMULATION OF THE IO CALLBACK THREAD |
|
| 491 |
%-------------------------------------------------------------- |
|
| 492 |
frameBufferL = buffer(obj.stimulusINTERNAL(:,1), obj.numSamples); |
|
| 493 |
frameBufferR = buffer(obj.stimulusINTERNAL(:,2), obj.numSamples); |
|
| 494 |
nFrames = size(frameBufferL,2); |
|
| 495 |
|
|
| 496 |
pad = zeros(1,biggestNumSamples-obj.numSamples); |
|
| 497 |
ARampL=ones(1,biggestNumSamples); |
|
| 498 |
ARampR = ARampL; |
|
| 499 |
MOCcontrol = ones(obj.numChannels, biggestNumSamples); |
|
| 500 |
|
|
| 501 |
peakIPL = zeros(5,1); |
|
| 502 |
peakOPL = peakIPL; |
|
| 503 |
rmsIPL = peakIPL; |
|
| 504 |
rmsOPL = peakIPL; |
|
| 505 |
|
|
| 506 |
peakIPR = peakIPL; |
|
| 507 |
peakOPR = peakIPL; |
|
| 508 |
rmsIPR = peakIPL; |
|
| 509 |
rmsOPR = peakIPL; |
|
| 510 |
|
|
| 511 |
MOCend = zeros(obj.numChannels,1); |
|
| 512 |
|
|
| 513 |
op = []; |
|
| 514 |
moc= []; |
|
| 515 |
for nn = 1:nFrames |
|
| 516 |
frameBufferPadL = [frameBufferL(:,nn)' pad]; |
|
| 517 |
frameBufferPadR = [frameBufferR(:,nn)' pad]; |
|
| 518 |
|
|
| 519 |
[ outBufferL, outBufferR, filterStatesL, filterStatesR, ARampL, ARampR, MOCend, peakIPL, peakOPL, rmsIPL, rmsOPL, peakIPR, peakOPR, rmsIPR, rmsOPR, MOCcontrol ] =... |
|
| 520 |
EssexAidProcessVFrameSwitchable( ... |
|
| 521 |
frameBufferPadL,... |
|
| 522 |
frameBufferPadR,... |
|
| 523 |
filterStatesL,... |
|
| 524 |
filterStatesR,... |
|
| 525 |
filterCoeffs,... |
|
| 526 |
obj.numChannels,... |
|
| 527 |
obj.numSamples,... |
|
| 528 |
ARampL,... |
|
| 529 |
ARampR,... |
|
| 530 |
obj.ARthresholdPa,... |
|
| 531 |
obj.filterOrder,... |
|
| 532 |
obj.DRNLb_INTERP,... |
|
| 533 |
obj.DRNLc_INTERP,... |
|
| 534 |
obj.TM_dBO_INTERP,... |
|
| 535 |
obj.MOCfactor,... |
|
| 536 |
peakIPL,... |
|
| 537 |
peakOPL,... |
|
| 538 |
rmsIPL,... |
|
| 539 |
rmsOPL,... |
|
| 540 |
peakIPR,... |
|
| 541 |
peakOPR,... |
|
| 542 |
rmsIPR,... |
|
| 543 |
rmsOPR,... |
|
| 544 |
MOCend,... |
|
| 545 |
MOCcontrol,... |
|
| 546 |
obj.mainGain_INTERP,... |
|
| 547 |
obj.useGTF); |
|
| 548 |
|
|
| 549 |
|
|
| 550 |
outBuffer = ( [outBufferL(:, 1:obj.numSamples); outBufferR(:, 1:obj.numSamples)] ); |
|
| 551 |
op = [op outBuffer]; %#ok<AGROW> |
|
| 552 |
moc= [moc MOCcontrol]; %#ok<AGROW> |
|
| 553 |
|
|
| 554 |
end %End of frame processing emulation loop |
|
| 555 |
obj.aidOP = op; |
|
| 556 |
obj.MOCrecord=moc; |
|
| 557 |
|
|
| 558 |
|
|
| 559 |
end %End of process stim method |
|
| 560 |
|
|
| 561 |
end %End of methods block |
|
| 562 |
|
|
| 563 |
%% ********************************************************* |
|
| 564 |
% _ _ _ _ _ _ |
|
| 565 |
% | | | | (_) | | | | | | |
|
| 566 |
% ___| |_ __ _| |_ _ ___ _ __ ___ ___| |_| |__ ___ __| |___ |
|
| 567 |
% / __| __/ _` | __| |/ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __| |
|
| 568 |
% \__ \ || (_| | |_| | (__ | | | | | | __/ |_| | | | (_) | (_| \__ \ |
|
| 569 |
% |___/\__\__,_|\__|_|\___| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/ |
|
| 570 |
%************************************************************ |
|
| 571 |
|
|
| 572 |
methods(Static) |
|
| 573 |
%% ******************************************************** |
|
| 574 |
% pipOut - sequence of tone pips at various levels |
|
| 575 |
%********************************************************** |
|
| 576 |
function pipOut = pipSequence(sampleRate, freq, dBlevs, pulseDur, silDur) |
|
| 577 |
if nargin < 5 |
|
| 578 |
silDur = 0.3; |
|
| 579 |
end |
|
| 580 |
if nargin < 4 |
|
| 581 |
pulseDur = 0.1; |
|
| 582 |
end |
|
| 583 |
if nargin < 3 |
|
| 584 |
dBlevs = 20:20:100; |
|
| 585 |
end |
|
| 586 |
if nargin < 2 |
|
| 587 |
freq = 500; |
|
| 588 |
end |
|
| 589 |
if nargin < 1 |
|
| 590 |
sampleRate = 48e3; |
|
| 591 |
end |
|
| 592 |
|
|
| 593 |
dt = 1/sampleRate; |
|
| 594 |
tAxis = dt:dt:pulseDur; |
|
| 595 |
sPulse = sin(2*pi*freq*tAxis); |
|
| 596 |
sPulse = sPulse./sqrt(mean(sPulse.^2)); |
|
| 597 |
rms2dBspl = @(dBspl)20e-6*10^(dBspl/20); %sneaky short-hand function by (ab)using function handles |
|
| 598 |
zPad = zeros(1,ceil(sampleRate*silDur)); |
|
| 599 |
|
|
| 600 |
pipOut = []; |
|
| 601 |
for nn = 1:numel(dBlevs) |
|
| 602 |
pipOut = [ pipOut sPulse*rms2dBspl(dBlevs(nn)) zPad]; %#ok<AGROW> |
|
| 603 |
end |
|
| 604 |
|
|
| 605 |
end% ------ OF pipSequence |
|
| 606 |
|
|
| 607 |
%% ******************************************************** |
|
| 608 |
% interpPars - Linear interpolation of given parameter to mimic GUI |
|
| 609 |
% fitting functionality. |
|
| 610 |
%********************************************************** |
|
| 611 |
function fullArray = interpPars(shortArray, numBands) |
|
| 612 |
nGUIbands = numel(shortArray); |
|
| 613 |
if numBands == nGUIbands |
|
| 614 |
fullArray = shortArray; |
|
| 615 |
else |
|
| 616 |
numSpacers = (numBands-nGUIbands) / (nGUIbands-1); |
|
| 617 |
fullArray = shortArray(1); |
|
| 618 |
for nn = 2:nGUIbands |
|
| 619 |
fullArray = [fullArray,... |
|
| 620 |
repmat(mean([shortArray(nn) shortArray(nn-1)]),1,numSpacers),... |
|
| 621 |
shortArray(nn)]; %#ok<AGROW> |
|
| 622 |
end |
|
| 623 |
end |
|
| 624 |
end% ----- OF interpPars |
|
| 625 |
|
|
| 626 |
%% ******************************************************** |
|
| 627 |
% gammatone - get filter coefficients |
|
| 628 |
%********************************************************** |
|
| 629 |
function [b,a] = gammatone(bw, cf, dt) |
|
| 630 |
phi = 2 * pi * bw * dt; |
|
| 631 |
theta = 2 * pi * cf * dt; |
|
| 632 |
cos_theta = cos(theta); |
|
| 633 |
sin_theta = sin(theta); |
|
| 634 |
alpha = -exp(-phi) * cos_theta; |
|
| 635 |
b0 = 1.0; |
|
| 636 |
b1 = 2 * alpha; |
|
| 637 |
b2 = exp(-2 * phi); |
|
| 638 |
z1 = (1 + alpha * cos_theta) - (alpha * sin_theta) * 1i; |
|
| 639 |
z2 = (1 + b1 * cos_theta) - (b1 * sin_theta) * 1i; |
|
| 640 |
z3 = (b2 * cos(2 * theta)) - (b2 * sin(2 * theta)) * 1i; |
|
| 641 |
tf = (z2 + z3) / z1; |
|
| 642 |
a0 = abs(tf); |
|
| 643 |
a1 = alpha * a0; |
|
| 644 |
|
|
| 645 |
a = [b0, b1, b2]; |
|
| 646 |
b = [a0, a1]; |
|
| 647 |
end% ------ OF gammatone |
|
| 648 |
end% ------ OF static methods |
|
| 649 |
|
|
| 650 |
end %End of classdef |
|
| 651 |
|
|
| userProgramsASRforDummies/cHMM.m | ||
|---|---|---|
| 1 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 2 |
% This program is free software; you can redistribute it and/or modify |
|
| 3 |
% it under the terms of the GNU General Public License as published by |
|
| 4 |
% the Free Software Foundation; either version 2 of the License, or |
|
| 5 |
% (at your option) any later version. |
|
| 6 |
% |
|
| 7 |
% This program is distributed in the hope that it will be useful, |
|
| 8 |
% but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 9 |
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 10 |
% GNU General Public License for more details. |
|
| 11 |
% |
|
| 12 |
% You can obtain a copy of the GNU General Public License from |
|
| 13 |
% http://www.gnu.org/copyleft/gpl.html or by writing to |
|
| 14 |
% Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA. |
|
| 15 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
|
| 16 |
|
|
| 17 |
classdef cHMM |
|
| 18 |
%HMMCLASS Handles all of the HTK related gubbins |
|
| 19 |
% Please see the documentation located in a separate file for further |
|
| 20 |
% information. |
|
| 21 |
|
|
| 22 |
%% ********************************************************* |
|
| 23 |
% properties _ _ |
|
| 24 |
% | | (_) |
|
| 25 |
% _ __ _ __ ___ _ __ ___ _ __| |_ _ ___ ___ |
|
| 26 |
% | '_ \| '__/ _ \| '_ \ / _ \ '__| __| |/ _ \/ __| |
|
| 27 |
% | |_) | | | (_) | |_) | __/ | | |_| | __/\__ \ |
|
| 28 |
% | .__/|_| \___/| .__/ \___|_| \__|_|\___||___/ |
|
| 29 |
% | | | | |
|
| 30 |
% |_| |_| |
|
| 31 |
%************************************************************ |
|
| 32 |
|
|
| 33 |
%% ********************************************************** |
|
| 34 |
% Public properties - can be set by user |
|
| 35 |
%************************************************************ |
|
| 36 |
properties(Access = public) |
|
| 37 |
hmmFolder |
|
| 38 |
paramType = 'USER_D_A'; %DELTAS and ACCELERATIONS |
|
| 39 |
numCoeff = 27; %9*3 THIS IS FOR PROBABILITY MODEL (not high spont+low spont which would be 18*3=54) |
|
| 40 |
|
|
| 41 |
HERestDataPath = fullfile(pwd, 'def', 'HERest_digit'); |
|
| 42 |
binPath = fullfile(pwd, 'def', 'bin'); |
|
| 43 |
configFile = fullfile(pwd, 'def', 'config_STANDARD'); |
|
| 44 |
trainWordListFile = fullfile(pwd, 'def', 'Grammar_digit', 'words3'); |
|
| 45 |
testWordListFile = fullfile(pwd, 'def', 'Grammar_digit', 'wordsNoSevenZero'); |
|
| 46 |
wordNetFile = fullfile(pwd, 'def', 'Grammar_digit', 'wdnetNoSP.slf'); |
|
| 47 |
dictFile = fullfile(pwd, 'def', 'Grammar_digit', 'noSevenZeroDict'); |
|
| 48 |
end |
|
| 49 |
|
|
| 50 |
%% ********************************************************** |
|
| 51 |
% Dependent - never set by user. Only calculated when needed |
|
| 52 |
%************************************************************ |
|
| 53 |
properties(Dependent = true) |
|
| 54 |
protoFile % = fullfile(pwd, 'def', 'proto_RobANonly_9'); %probability only |
|
| 55 |
end |
|
| 56 |
|
|
| 57 |
%% ********************************************************* |
|
| 58 |
% methods _ _ _ |
|
| 59 |
% | | | | | | |
|
| 60 |
% _ __ ___ ___| |_| |__ ___ __| |___ |
|
| 61 |
%| '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __| |
|
| 62 |
%| | | | | | __/ |_| | | | (_) | (_| \__ \ |
|
| 63 |
%|_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/ |
|
| 64 |
%************************************************************ |
|
| 65 |
|
|
| 66 |
methods |
|
| 67 |
%% ********************************************************** |
|
| 68 |
% Constructor |
|
| 69 |
%************************************************************ |
|
| 70 |
function obj = cHMM(hmmFolder) |
|
| 71 |
if nargin > 0 |
|
| 72 |
obj.hmmFolder = hmmFolder; |
|
| 73 |
end |
|
| 74 |
end % ------ OF CONSTRUCTOR |
|
| 75 |
|
|
| 76 |
%% ********************************************************** |
|
| 77 |
% genProto - generate task specific prototype |
|
| 78 |
%************************************************************ |
|
| 79 |
function genProto(obj) |
|
| 80 |
% models_1mixsil.exe - takes input (hmmdef) and copies it making a |
|
| 81 |
% basis of one, two three etc. etc. |
|
| 82 |
obj.models_1mixsilMat(fullfile(obj.hmmFolder,'hmm0','hmmdef'), fullfile(obj.hmmFolder,'hmm0','models')); |
|
| 83 |
end % ------ OF GENPROTO |
|
| 84 |
|
|
| 85 |
%% ********************************************************** |
|
| 86 |
% istrained |
|
| 87 |
%************************************************************ |
|
| 88 |
function boolans = istrained(obj) |
|
| 89 |
boolans = numel(dir(fullfile(obj.hmmFolder,'hmm36','models'))); |
|
| 90 |
end |
|
| 91 |
|
|
| 92 |
%% ********************************************************** |
|
| 93 |
% Train |
|
| 94 |
%************************************************************ |
|
| 95 |
function train(obj, trainFeatureFolder) |
|
| 96 |
|
|
| 97 |
% Most of the following code block can be replaced by doing a |
|
| 98 |
% find and replace across the code below. I didn't |
|
| 99 |
% want to mess with the working code too much, so I just |
|
| 100 |
% copied the object properties needed into the variable names |
|
| 101 |
% expected. |
|
| 102 |
|
|
| 103 |
ED_CMDFILE1 = fullfile(obj.HERestDataPath, 'sil1.hed'); |
|
| 104 |
ED_CMDFILE2 = fullfile(obj.HERestDataPath, 'mix2_16.hed'); |
|
| 105 |
ED_CMDFILE3 = fullfile(obj.HERestDataPath, 'mix3_16.hed'); |
|
| 106 |
ED_CMDFILE4 = fullfile(obj.HERestDataPath, 'mix5_16.hed'); |
|
| 107 |
ED_CMDFILE5 = fullfile(obj.HERestDataPath, 'mix7_16.hed'); |
|
| 108 |
|
|
| 109 |
NUM_COEF = obj.numCoeff; |
|
| 110 |
PAR_TYPE = obj.paramType; |
|
| 111 |
LIST_FILE = fullfile(obj.hmmFolder, 'tmp.list'); |
|
| 112 |
|
|
| 113 |
word_list = obj.trainWordListFile;%fullfile(obj.grammarPath, 'words'); |
|
| 114 |
word_listSP = word_list; % for use in hmm4 onwards - UGLY HACK NOW SP ABANDONED |
|
| 115 |
proto = obj.protoFile;%Does not exist on disk just yet probably - see a few lines down |
|
| 116 |
config = obj.configFile; |
|
| 117 |
train_list = fullfile(trainFeatureFolder, 'list.scp'); |
|
| 118 |
labels = fullfile(trainFeatureFolder, 'labels.mlf'); |
|
| 119 |
labelssp = labels; % for use in hmm4 onwards - UGLY HACK NOW SP ABANDONED |
|
| 120 |
hmm_dir = obj.hmmFolder; |
|
| 121 |
|
|
| 122 |
FEAT_ROOT = trainFeatureFolder; |
|
| 123 |
|
|
| 124 |
% Now for the actual HMM training code |
|
| 125 |
mkdir(hmm_dir) |
|
| 126 |
for I = 0:36 |
|
| 127 |
h = fullfile(hmm_dir,['hmm' num2str(I)]); |
|
| 128 |
mkdir(h); |
|
| 129 |
end |
|
| 130 |
obj.makeProtoHmm(proto, obj.paramType, obj.numCoeff, 18); |
|
| 131 |
|
|
| 132 |
fid = fopen(train_list,'r'); |
|
| 133 |
disp(train_list) |
|
| 134 |
S = textscan(fid,'%s','Delimiter','\n'); |
|
| 135 |
fclose(fid); |
|
| 136 |
|
|
| 137 |
fid = fopen(LIST_FILE,'w'); |
|
| 138 |
|
|
| 139 |
for I = 1:size(S{1},1)
|
|
| 140 |
str = fullfile(FEAT_ROOT,S{1}{I});
|
|
| 141 |
fprintf(fid,'%s\n',str); |
|
| 142 |
end; |
|
| 143 |
fclose(fid); |
|
| 144 |
|
|
| 145 |
% HCompV just gets the vfloor stuff out so we can begin approximating |
|
| 146 |
cmd = ['"HCompV" -T 2 -D -C "' config '" -o hmmdef -f 0.01 -m -S "' LIST_FILE '" -M "' hmm_dir filesep 'hmm0" "' proto '"']; |
|
| 147 |
system(cmd); |
|
| 148 |
|
|
| 149 |
%cmd = [BINDIR filesep 'macro' binExt ' ' num2str(NUM_COEF) ' ' PAR_TYPE ' ' '"' hmm_dir filesep 'hmm0' filesep 'vFloors' '" "' hmm_dir filesep 'hmm0' filesep 'macros' '"']; |
|
| 150 |
%system(cmd); |
|
| 151 |
obj.macroMat(NUM_COEF,PAR_TYPE, fullfile(hmm_dir, 'hmm0', 'vFloors'), fullfile(hmm_dir, 'hmm0', 'macros')); |
|
| 152 |
|
|
| 153 |
%MAKE THE INITIAL MODEL PROTOTYPE |
|
| 154 |
genProto(obj); |
|
| 155 |
|
|
| 156 |
disp('Seed HMM successfully Produced.....');
|
|
| 157 |
|
|
| 158 |
%Training |
|
| 159 |
for I = 1:3 |
|
| 160 |
disp(I) |
|
| 161 |
j = I-1; |
|
| 162 |
cmd = ['HERest -D -C ' config ' -I ' labels ' -t 250.0 150.0 1000.0 -S ' LIST_FILE ' -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'macros -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'models -M ' hmm_dir filesep 'hmm' num2str(I) ' ' word_list]; |
|
| 163 |
% disp(cmd) |
|
| 164 |
system(cmd); |
|
| 165 |
end |
|
| 166 |
|
|
| 167 |
disp('3 iterations complete');
|
|
| 168 |
|
|
| 169 |
rmdir ([hmm_dir filesep 'hmm4'],'s') |
|
| 170 |
copyfile ([hmm_dir filesep 'hmm3'], [hmm_dir filesep 'hmm4']) |
|
| 171 |
|
|
| 172 |
% The following command takes state 3 from the silence model |
|
| 173 |
% and appends it to the end of the model as state 2 of the |
|
| 174 |
% short pause model. |
|
| 175 |
% Original: |
|
| 176 |
% cmd = [BINDIR filesep 'spmodel_gen' binExt ' ' hmm_dir filesep 'hmm3' filesep 'models ' hmm_dir filesep 'hmm4' filesep 'models']; |
|
| 177 |
% system(cmd); |
|
| 178 |
% New: |
|
| 179 |
obj.spmodel_genMat(fullfile(hmm_dir,'hmm3','models'), fullfile(hmm_dir,'hmm4','models')); |
|
| 180 |
|
|
| 181 |
cmd = ['HHEd -T 2 -H ' hmm_dir filesep 'hmm4' filesep 'macros -H ' hmm_dir filesep 'hmm4' filesep 'models -M ' hmm_dir filesep 'hmm5 ' ED_CMDFILE1 ' ' word_listSP ]; |
|
| 182 |
system(cmd); |
|
| 183 |
disp ('SP model fixed')
|
|
| 184 |
|
|
| 185 |
% after the spmodel_gen command - the word_list is changed to |
|
| 186 |
% word_listSP. The sp model is just ignored currently |
|
| 187 |
|
|
| 188 |
for I = 6:8 |
|
| 189 |
disp(I) |
|
| 190 |
j = I-1; |
|
| 191 |
cmd = ['HERest -C ' config ' -I ' labelssp ' -S ' LIST_FILE ' -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'macros -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'models -M ' hmm_dir filesep 'hmm' num2str(I) ' ' word_listSP]; |
|
| 192 |
system(cmd); |
|
| 193 |
end |
|
| 194 |
|
|
| 195 |
disp('6 iterations complete');
|
|
| 196 |
|
|
| 197 |
cmd = ['HHEd -T 2 -H ' hmm_dir filesep 'hmm8' filesep 'macros -H ' hmm_dir filesep 'hmm8' filesep 'models -M ' hmm_dir filesep 'hmm9 ' ED_CMDFILE2 ' ' word_listSP ]; |
|
| 198 |
system(cmd); |
|
| 199 |
disp ('2 gaussians per mixture')
|
|
| 200 |
|
|
| 201 |
for I = 10:12 |
|
| 202 |
disp(I) |
|
| 203 |
j = I-1; |
|
| 204 |
cmd = ['HERest -C ' config ' -I ' labelssp ' -S ' LIST_FILE ' -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'macros -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'models -M ' hmm_dir filesep 'hmm' num2str(I) ' ' word_listSP]; |
|
| 205 |
system(cmd); |
|
| 206 |
end |
|
| 207 |
|
|
| 208 |
disp ('9 iterations completed')
|
|
| 209 |
|
|
| 210 |
cmd = ['HHEd -T 2 -H ' hmm_dir filesep 'hmm12' filesep 'macros -H ' hmm_dir filesep 'hmm12' filesep 'models -M ' hmm_dir filesep 'hmm13 ' ED_CMDFILE3 ' ' word_listSP ]; |
|
| 211 |
system(cmd); |
|
| 212 |
disp ('3 gaussians per mixture')
|
|
| 213 |
|
|
| 214 |
for I = 14:20 |
|
| 215 |
disp(I) |
|
| 216 |
j = I-1; |
|
| 217 |
cmd = ['HERest -C ' config ' -I ' labelssp ' -S ' LIST_FILE ' -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'macros -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'models -M ' hmm_dir filesep 'hmm' num2str(I) ' ' word_listSP]; |
|
| 218 |
system(cmd); |
|
| 219 |
end |
|
| 220 |
|
|
| 221 |
disp ('16 iterations completed')
|
|
| 222 |
|
|
| 223 |
cmd = ['HHEd -T 2 -H ' hmm_dir filesep 'hmm20' filesep 'macros -H ' hmm_dir filesep 'hmm20' filesep 'models -M ' hmm_dir filesep 'hmm21 ' ED_CMDFILE4 ' ' word_listSP ]; |
|
| 224 |
system(cmd); |
|
| 225 |
disp ('5 gaussians per mixture')
|
|
| 226 |
|
|
| 227 |
for I = 22:28 |
|
| 228 |
disp(I) |
|
| 229 |
j = I-1; |
|
| 230 |
cmd = ['HERest -C ' config ' -I ' labelssp ' -S ' LIST_FILE ' -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'macros -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'models -M ' hmm_dir filesep 'hmm' num2str(I) ' ' word_listSP]; |
|
| 231 |
system(cmd); |
|
| 232 |
end |
|
| 233 |
|
|
| 234 |
disp ('23 iterations completed')
|
|
| 235 |
|
|
| 236 |
cmd = ['HHEd -T 2 -H ' hmm_dir filesep 'hmm28' filesep 'macros -H ' hmm_dir filesep 'hmm28' filesep 'models -M ' hmm_dir filesep 'hmm29 ' ED_CMDFILE5 ' ' word_listSP ]; |
|
| 237 |
system(cmd); |
|
| 238 |
disp ('7 gaussians per mixture')
|
|
| 239 |
|
|
| 240 |
for I = 30:36 |
|
| 241 |
disp(I) |
|
| 242 |
j = I-1; |
|
| 243 |
cmd = ['HERest -C ' config ' -I ' labelssp ' -S ' LIST_FILE ' -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'macros -H ' hmm_dir filesep 'hmm' num2str(j) filesep 'models -M ' hmm_dir filesep 'hmm' num2str(I) ' ' word_listSP]; |
|
| 244 |
system(cmd); |
|
| 245 |
end |
|
| 246 |
|
|
| 247 |
disp ('30 iterations completed')
|
|
| 248 |
|
|
| 249 |
end % ------ OF TRAIN |
|
| 250 |
|
|
| 251 |
%% ********************************************************** |
|
| 252 |
% Test |
|
| 253 |
%************************************************************ |
|
| 254 |
function test(obj, testFeatureFolder) |
|
| 255 |
flags = '-p 0.0 -s 0.0'; |
|
| 256 |
test_word_list = obj.testWordListFile; |
|
| 257 |
|
|
| 258 |
net = obj.wordNetFile; |
|
| 259 |
dict = obj.dictFile; |
|
| 260 |
|
|
| 261 |
LIST_FILE = fullfile(testFeatureFolder, 'tmp.list'); |
|
| 262 |
config = obj.configFile; |
|
| 263 |
|
|
| 264 |
disp ('Now testing with 7 mixture HMMs')
|
|
| 265 |
mod_file = fullfile(obj.hmmFolder, 'hmm36', 'models'); |
|
| 266 |
mac_file = fullfile(obj.hmmFolder, 'hmm36', 'macros'); |
|
| 267 |
|
|
| 268 |
|
|
| 269 |
RESULTS_DIR = testFeatureFolder; |
|
| 270 |
TEST_FEAT_ROOT = testFeatureFolder; |
|
| 271 |
|
|
| 272 |
N1list = fullfile(testFeatureFolder, 'list.scp'); |
|
| 273 |
|
|
| 274 |
ftest = fopen(N1list,'r'); |
|
| 275 |
S = textscan(ftest,'%s','Delimiter','\n'); |
|
| 276 |
fclose(ftest); |
|
| 277 |
|
|
| 278 |
flist = fopen(LIST_FILE,'w'); |
|
| 279 |
for I = 1:size(S{1},1)
|
|
| 280 |
str = fullfile(TEST_FEAT_ROOT,S{1}{I});
|
|
| 281 |
fprintf(flist,'%s\n',str); |
|
| 282 |
end; |
|
| 283 |
fclose(flist); |
|
| 284 |
|
|
| 285 |
cmd = ['HVite -D -H ' mac_file ' -H ' mod_file ' -S ' LIST_FILE ' -C ' config ' -w ' net ' -l ''*'' -i ' RESULTS_DIR filesep 'result.mlf ' flags ' ' dict ' ' test_word_list]; |
|
| 286 |
system(cmd); |
|
| 287 |
end % ------ OF TEST |
|
| 288 |
|
|
| 289 |
%% ********************************************************** |
|
| 290 |
% Get methods determining feature vector related gubbins |
|
| 291 |
%************************************************************ |
|
| 292 |
function value = get.protoFile(obj) |
|
| 293 |
value = fullfile(obj.hmmFolder, 'proto_AutoGen'); |
|
| 294 |
end |
|
| 295 |
|
|
| 296 |
end % ------ OF METHODS |
|
| 297 |
|
|
| 298 |
%% ********************************************************* |
|
| 299 |
% _ _ _ _ _ _ |
|
| 300 |
% | | | | (_) | | | | | | |
|
| 301 |
% ___| |_ __ _| |_ _ ___ _ __ ___ ___| |_| |__ ___ __| |___ |
|
| 302 |
% / __| __/ _` | __| |/ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __| |
|
| 303 |
% \__ \ || (_| | |_| | (__ | | | | | | __/ |_| | | | (_) | (_| \__ \ |
|
Also available in: Unified diff