annotate aux/mat2xml.m @ 15:24be5e9ce25b tip

Update README
author Brecht De Man <brecht.deman@bcu.ac.uk>
date Thu, 20 Sep 2018 12:23:20 +0200
parents 866c5da4d357
children
rev   line source
b@12 1 % Script to convert APE toolbox [1] (MATLAB) .mat output files to WAET
b@12 2 % toolbox [2] (HTML5/JavaScript) XML output files.
b@12 3 %
b@12 4 % [1] B. De Man and Joshua D. Reiss, ?APE: Audio Perceptual Evaluation
b@12 5 % toolbox for MATLAB,? 136th Convention of the Audio Engineering Society,
b@12 6 % 2014.
b@12 7 %
b@12 8 % [2] Nicholas Jillings, Brecht De Man, David Moffat and Joshua D. Reiss,
b@12 9 % "Web Audio Evaluation Tool: A Browser-Based Listening Test Environment,"
b@12 10 % 12th Sound and Music Computing Conference, July 2015.
b@11 11
b@11 12 % CONFIGURATION:
b@11 13 location = 'CIRMMT Critical Listening Lab';
b@12 14 day = 5;
b@12 15 month = 2;
b@12 16 year = 2015;
b@11 17
b@12 18 % IMPORT FILES
b@12 19 sourcefolder = ... %'.';
b@12 20 '/Users/Brecht/Google Drive/Writings/Mixing experiments/McGill/results/2015spring/mat';
b@12 21 outputfolder = [sourcefolder '/../xml'];
b@12 22 list = dir([sourcefolder '/*.mat']); % find all '.mat' files in this folder
b@11 23
b@12 24 % remove hidden files from list
b@12 25 % see http://www.mathworks.co.uk/matlabcentral/newsreader/view_thread/258220
b@12 26 for k = length(list):-1:1
b@12 27 fname = list(k).name;
b@12 28 if fname(1) == '.'
b@12 29 list(k) = [ ];
b@11 30 end
b@11 31 end
b@11 32
b@12 33 aliastable = {{'JohnSmith', 'anon1'};
b@12 34 {'JaneDoe', 'anon2'}};
b@12 35
b@12 36 % TODO: create output folder if doesn't exist yet
b@11 37
b@12 38 for i = 1:length(list) % for every file in the list
b@12 39 matfile = load([sourcefolder '/' list(i).name]);
b@12 40 name = fieldnames(matfile);
b@12 41 test = matfile.(char(name)); % store loaded file in 'test'
b@12 42
b@12 43 docNode = com.mathworks.xml.XMLUtils.createDocument('browserevaluationresult');
b@12 44 docRootNode = docNode.getDocumentElement;
b@12 45
b@12 46 % DATE AND TIME
b@12 47 datetime = docNode.createElement('datetime'); % create 'datetime' child
b@12 48 docRootNode.appendChild(datetime);
b@12 49 date = docNode.createElement('date'); % create 'date' child
b@12 50 datetime.appendChild(date);
b@12 51 date.setAttribute('year', num2str(year)); % add 'year' as attribute
b@12 52 date.setAttribute('month', num2str(month)); % add 'month' as attribute
b@12 53 date.setAttribute('day', num2str(day)); % add 'day' as attribute
b@12 54 datestr = sprintf('%i/%i/%i', year, month, day);
b@12 55 date.appendChild(docNode.createTextNode(datestr));
b@12 56
b@12 57 % PRETEST
b@12 58 pretest = docNode.createElement('pretest');
b@12 59 docRootNode.appendChild(pretest);
b@12 60 sessionID_comment = docNode.createElement('comment');
b@12 61 pretest.appendChild(sessionID_comment);
b@12 62
b@12 63 % Session ID: entered id or file name
b@12 64 sessionID_comment.setAttribute('id', 'SessionID');
b@12 65 %sessionID_comment.appendChild(docNode.createTextNode(test.id));
b@12 66 str = anonymise(list(i).name(1:end-4), aliastable);
b@12 67 sessionID_comment.appendChild(docNode.createTextNode(str));
b@12 68
b@12 69 location_comment = docNode.createElement('comment');
b@12 70 pretest.appendChild(location_comment);
b@12 71 location_comment.setAttribute('id', 'location');
b@12 72 location_comment.appendChild(docNode.createTextNode(location));
b@12 73
b@12 74
b@12 75 % AUDIOHOLDER
b@12 76 % for each song in the test:
b@12 77 for song = 1:length(test.tstDat)/2 % 2 structs for every song
b@12 78 song_id = song*2; % every second field corresponds with a song
b@12 79
b@12 80 % only add song if 'rsl' present
b@12 81 if isfield(test.tstDat{1,song_id}, 'rsl')
b@12 82 % create audioholder
b@12 83 audioholder = docNode.createElement('audioholder');
b@12 84 docRootNode.appendChild(audioholder);
b@12 85 % save song name
b@12 86 songname = test.tstDat{1,song_id-1}.tstFile(2:end-4); % chop off '_*.txt'
b@12 87 audioholder.setAttribute('id', songname);
b@12 88 % add pretest (empty)
b@12 89 pretest = docNode.createElement('pretest');
b@12 90 audioholder.appendChild(pretest);
b@12 91 % add posttest (empty)
b@12 92 posttest = docNode.createElement('posttest');
b@12 93 audioholder.appendChild(posttest);
b@12 94 % add metric
b@12 95 metric = docNode.createElement('metric');
b@12 96 audioholder.appendChild(metric);
b@12 97 metricresult = docNode.createElement('metricresult');
b@12 98 metric.appendChild(metricresult);
b@12 99 metricresult.setAttribute('id', 'testTime');
b@12 100 testduration = 60*test.tstDat{1,song_id}.rsl.duration; % minutes to seconds
b@12 101 metricresult.appendChild(docNode.createTextNode(num2str(testduration)));
b@12 102
b@12 103 % go over audio files in the order they were presented
b@12 104 permVec = test.tstDat{1,song_id}.rsl.permVec;
b@12 105 Naudioelements = length(permVec);
b@12 106 invPermVec(permVec(1:Naudioelements)) = 1:Naudioelements;
b@12 107 for index=1:length(permVec) % ('index' is presented id)
b@12 108 actualID = invPermVec(index);
b@12 109 % create audioelement and attach to audioholder
b@12 110 audioelement = docNode.createElement('audioelement');
b@12 111 audioholder.appendChild(audioelement);
b@12 112 % save mix name
b@12 113 mixname = ...
b@12 114 anonymise(test.tstDat{1,song_id-1}.rsl.sounds(actualID).name, ...
b@12 115 aliastable);
b@12 116 % distinguish between pro1 and pro2 (Spring 2014)
b@12 117 if strcmp(mixname, 'McG-pro')
b@12 118 if strcmp(songname, 'PouringRoom')
b@12 119 mixname = [mixname '1'];
b@12 120 else if strcmp(songname, 'InTheMeantime')
b@12 121 mixname = [mixname '2'];
b@12 122 end
b@12 123 end
b@12 124 end
b@12 125 audioelement.setAttribute('id', mixname);
b@12 126 %...strcat('McG-', mixname)); % Prefix 'McG-'
b@12 127 % add presented id
b@12 128 audioelement.setAttribute('presentedid', num2str(index));
b@12 129 % add comment
b@12 130 comment = docNode.createElement('comment');
b@12 131 audioelement.appendChild(comment);
b@12 132 % add comment question and response
b@12 133 question = docNode.createElement('question');
b@12 134 comment.appendChild(question);
b@12 135 str = sprintf('Comment on track %i', index);
b@12 136 question.appendChild(docNode.createTextNode(str));
b@12 137 response = docNode.createElement('response');
b@12 138 comment.appendChild(response);
b@12 139 % comment order as shown
b@12 140 str = char(test.tstDat{1,song_id}.rsl.hcom(index));
b@12 141 % avoid errors due to multiline strings:
b@12 142 str_t = str'; % transpose str
b@12 143 str = str_t(:)'; % concatenate columns and transpose again
b@12 144 if length(str)<4% get rid of shot, meaningless comments
b@12 145 if length(str)>1
b@12 146 if strncmp(str(2), ':', 1) % if a number and a column
b@12 147 str = ''; % omit entirely
b@12 148 end
b@12 149 else % if just a number
b@12 150 str = ''; % omit
b@12 151 end
b@12 152 else % strip numbers off comments
b@12 153 if strncmp(str(2:3), ': ', 2)
b@12 154 str = str(4:end); % strip '1: ' off string
b@12 155 else if strncmp(str(2), ':', 1)
b@12 156 str = str(3:end); % strip '1:' off string
b@12 157 else if strncmp(str(3:4), ': ', 2) % strip '10: ' off string
b@12 158 str = str(5:end);
b@12 159 else if strncmp(str(3), ':', 1) % strip '10:' off string
b@12 160 str = str(4:end);
b@12 161 end
b@12 162 end
b@12 163 end
b@12 164 end
b@12 165 end
b@12 166 response.appendChild(docNode.createTextNode(str));
b@12 167 % add rating
b@12 168 value = docNode.createElement('value');
b@12 169 audioelement.appendChild(value);
b@12 170 % divide by 100 to be within 0-1
b@12 171 rating = test.tstDat{1,song_id}.rsl.mat(actualID)/100;
b@12 172 value.appendChild(docNode.createTextNode(num2str(rating)));
b@12 173 % add metric (only 'has been played')
b@12 174 metric = docNode.createElement('metric');
b@12 175 audioelement.appendChild(metric);
b@12 176 metricresult = docNode.createElement('metricresult');
b@12 177 metric.appendChild(metricresult);
b@12 178 hasbeenplayed = test.tstDat{1,song_id}.rsl.playVec(actualID); % I guess?
b@12 179 if hasbeenplayed
b@12 180 metricresult.appendChild(docNode.createTextNode('true'));
b@12 181 else
b@12 182 metricresult.appendChild(docNode.createTextNode('false'));
b@12 183 end
b@12 184 end
b@12 185 end
b@12 186 end
b@12 187
b@12 188 xmlFileName = [outputfolder '/' anonymise(list(i).name(1:end-4), aliastable) '.xml'];
b@12 189 xmlwrite(xmlFileName,docNode);
b@12 190 % type(xmlFileName); % display XML in CLI
b@12 191 end