diff core/magnatagatune/xml_parse_mtt.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/magnatagatune/xml_parse_mtt.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,135 @@
+function features = xml_parse_mtt(file)
+% features = xml_parse_mtt(file)
+% 
+% parses the magnatagatune xml file to retrieve the audio
+% analysis results. The file isexpected to use the deprecated 
+% EchoNest XML format
+%
+% time always travels an the horizontal axis
+
+% ---
+% TODO: Add Error checking to certan tags as chroma number, 
+%  loudness max etc.
+% ---
+
+fdata = fileread(file);
+try
+    % ---
+    % TODO: check for other than the p-code exceptions
+    % ---
+    
+    data = xml_parseany(fdata);
+catch exception
+end
+%% ------------------------------------------------------------------------
+% ---
+% copy general track data
+% ---
+
+fields = fieldnames(data.track{1}.ATTRIBUTE);
+for i = 1:length(fields)
+    features.(fields{i}) = str2double(data.track{1}.ATTRIBUTE.(fields{i}));
+end
+
+%% ------------------------------------------------------------------------
+% ---
+% get harmonic analysis. this is stored in segments
+% ---
+dsegments = data.track{1}.segments{1}.segment;
+
+for i = 1:numel(dsegments)
+    
+    % get start and duration
+    segments(i).start = str2double(dsegments{i}.ATTRIBUTE.start);
+    segments(i).duration = str2double(dsegments{i}.ATTRIBUTE.duration);
+    
+    % ---
+    % NOTE: for the chroma and mfcc features, we assume that the classes
+    %  are always saved and parsed in correct order, thus we can afford to 
+    %  refrain from saving the class number with the class
+    % ---
+    
+    % assemble chroma features
+    segments(i).pitches = zeros(12,1);
+    for j = 1:12
+        
+        segments(i).pitches(j) = str2double(...
+            dsegments{i}.pitches{1}.pitch{j}.CONTENT);
+    end
+    
+   % assemble mfcc features;
+    segments(i).timbre = zeros(numel(dsegments{i}.timbre{1}.coeff),1);
+    for j = 1:numel(dsegments{i}.timbre{1}.coeff)
+        
+        segments(i).timbre(j) = str2double(...
+            dsegments{i}.timbre{1}.coeff{j}.CONTENT);
+    end
+    
+    % get loudness measurements in dB and time
+    segments(i).loudness = str2double(...
+        dsegments{i}.loudness{1}.dB{1}.CONTENT);
+    
+    segments(i).loudness_time = str2double(...
+        dsegments{i}.loudness{1}.dB{1}.ATTRIBUTE.time);
+    
+    segments(i).loudness_max = str2double(...
+        dsegments{i}.loudness{1}.dB{2}.CONTENT);
+    
+    segments(i).loudness_max_time = str2double(...
+        dsegments{i}.loudness{1}.dB{2}.ATTRIBUTE.time);
+end
+
+features.segments = segments;
+
+%% ------------------------------------------------------------------------
+% ---
+% get sections
+% ---
+dsections = data.track{1}.sections{1}.section;
+
+secstart = zeros(1,numel(dsections));
+secduration = zeros(1,numel(dsections));
+for i = 1:numel(dsections)
+    sections(i).start = str2double(dsections{i}.ATTRIBUTE.start);
+    sections(i).duration = str2double(dsections{i}.ATTRIBUTE.duration);
+end
+
+features.sections = sections;
+
+%% ------------------------------------------------------------------------
+% ---
+% get beat and rythm data. the metric data is structured 
+% hierarchically, as each bar contains several beats,
+% which contaisn several tatums. 
+% NOTE: Although the metrum and tempo have been evaluated and fixed
+% on a global scale, the number of bars and tatum vary greatly.
+% ---
+dbars = data.track{1}.meter{1}.bar;
+
+for i = 1:numel(dbars)
+    
+    % get bar information
+    bars(i).confidence = str2double(dbars{i}.ATTRIBUTE.conf);
+    for j = 1:numel(dbars{i}.beat)
+        
+        % get beat information
+        bars(i).beat(j).confidence = str2double(dbars{i}.beat{j}.ATTRIBUTE.conf);
+        
+        for k = 1:numel(dbars{i}.beat{j}.tatum)
+            
+            % get tatum information
+            if ~isempty(dbars{i}.beat{j}.tatum{k}.ATTRIBUTE)
+                bars(i).beat(j).tatum(k).time = str2double(dbars{i}.beat{j}.tatum{k}.CONTENT);
+                bars(i).beat(j).tatum(k).confidence = str2double(dbars{i}.beat{j}.tatum{k}.ATTRIBUTE.conf);
+            
+            else 
+                % save empty struct
+                bars(i).beat(j).tatum = struct([]);
+            end
+            
+        end
+    end
+end
+
+features.bars = bars;
+