Created
February 15, 2016 17:42
-
-
Save justinsalamon/a46923f9c6ab58237585 to your computer and use it in GitHub Desktop.
Evaluation code used for MIREX multi-f0 Note Tracking subtask. This is the "new" code by Zhiyao Duan that has been used on the "Su" dataset for this task (I think...?) Raw
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Results = ErrorRate_MF0_NoteLevel(EstNote, GTNote, bUseOffset, FreqDevTh, OnsetDiff, OffsetDiff) | |
%function Results = ErrorRate_MF0_NoteLevel(EstNote, GTNote, bUseOffset, FreqDevTh, OnsetDiff, OffsetDiff) | |
% Note-level multi-F0 estimation error rate calculation. Compare a list of estimated notes with | |
% a list of ground-truth notes. | |
% | |
% Input | |
% - EstNote : estimated notes, each cell corresponds to a note: first line is frame number, | |
% second line is frequency in MIDI number | |
% - GTNote : ground-truth notes, the same format as EstNote | |
% - bUseOffset : (optional, default 0) the flag that if using offset criterion or not | |
% - FreqDevTh : (optional, default 0.5) frequency deviation threshold for considering pitch estimation error | |
% - OnsetDiff : (optional, default 0.05) the onset time difference criterion (in second) | |
% - OffsetDiff : (optional, default 0.2) the offset time difference criterion (in ratio of the length of reference length) | |
% Output | |
% - Results : Results | |
% - MulPre : Precision | |
% - MulRec : Recall | |
% - MulFme : F-measure | |
% - MulAcc : Accuracy | |
% - MulAOR : Average overlap ratio | |
% - OctPre : Precision without considering octave errors | |
% - OctRec : Recall without considering octave errors | |
% - OctFme : F-measure without considering octave errors | |
% - OctAcc : Accuracy without considering octave errors | |
% - OctAOR : Average overlap ratio without considering octave errors | |
% | |
% Author: Zhiyao Duan | |
% Created: 5/5/2009 | |
% Last modified: 8/4/2014 | |
if nargin<6 OffsetDiff=0.2; end | |
if nargin<5 OnsetDiff=0.05; end | |
if nargin<4 FreqDevTh=0.5; end | |
if nargin<3 bUseOffset=0; end | |
EstNoteNum = length(EstNote); % number of estimated notes | |
GTNoteNum = length(GTNote); % number of ground-truth notes | |
nCorrect = 0; % number of correctly estimated notes | |
AOR = 0; % average overlap ratio between estimated and ground-truth notes | |
nChromaCorrect = 0; % number of correctly estimated notes, without counting octave errors | |
ChromaAOR = 0; % average overlap ratio between estimated and ground-truth notes, without counting octave errors | |
% normal case | |
IsUsedEst = zeros(EstNoteNum, 1); % flag indicating if an estimated note has been matched | |
for gt_note = 1:GTNoteNum | |
gt_onset = GTNote{gt_note}(1,1); % ground-truth note onset time | |
gt_offset = GTNote{gt_note}(1,end); % ground-truth note offset time | |
gt_freq = mean(GTNote{gt_note}(2,:)); % ground-truth note average frequency (in MIDI number) | |
for est_note = 1:EstNoteNum | |
if IsUsedEst(est_note) == 0 | |
est_onset = EstNote{est_note}(1,1); % estimated note onset time | |
est_offset = EstNote{est_note}(1,end); % estimated note offset time | |
est_freq = mean(EstNote{est_note}(2,:));% estimated note average frequency | |
if bUseOffset == 0 % offset difference is not involved in the criterion | |
if abs(est_freq - gt_freq) <= FreqDevTh ... | |
&& abs(est_onset - gt_onset) <= OnsetDiff | |
nCorrect = nCorrect + 1; % match | |
AOR = AOR ... | |
+ (min(est_offset, gt_offset) - max(est_onset, gt_onset)) ... | |
/ (max(est_offset, gt_offset) - min(est_onset, gt_onset)); | |
IsUsedEst(est_note) = 1; | |
break; | |
end | |
else % offset difference is involved in the criterion | |
if abs(est_freq - gt_freq) <= FreqDevTh ... | |
&& abs(est_onset - gt_onset) <= OnsetDiff ... | |
&& abs(est_offset - gt_offset) <= OffsetDiff * (gt_offset-gt_onset) | |
nCorrect = nCorrect + 1; % match | |
AOR = AOR ... | |
+ (min(est_offset, gt_offset) - max(est_onset, gt_onset)) ... | |
/ (max(est_offset, gt_offset) - min(est_onset, gt_onset)); | |
IsUsedEst(est_note) = 1; | |
break; | |
end | |
end | |
end | |
end | |
end | |
% chroma case | |
IsUsedEst = zeros(EstNoteNum, 1); | |
for gt_note = 1:GTNoteNum | |
gt_onset = GTNote{gt_note}(1,1); % ground-truth note onset time | |
gt_offset = GTNote{gt_note}(1,end); % ground-truth note offset time | |
gt_freq = mod(mean(GTNote{gt_note}(2,:)), 12); % ground-truth note average frequency (in MIDI number) | |
for est_note = 1:EstNoteNum | |
if IsUsedEst(est_note) == 0 | |
est_onset = EstNote{est_note}(1,1); % estimated note onset time | |
est_offset = EstNote{est_note}(1,end); % estimated note offset time | |
est_freq = mod(mean(EstNote{est_note}(2,:)), 12); % estimated note average frequency | |
if bUseOffset == 0 % offset difference is not involved in the criterion | |
if (mod(est_freq - gt_freq, 12) <= FreqDevTh || mod(gt_freq - est_freq, 12) <= FreqDevTh) ... | |
&& abs(est_onset - gt_onset) <= OnsetDiff | |
nChromaCorrect = nChromaCorrect + 1; % match | |
ChromaAOR = ChromaAOR ... | |
+ (min(est_offset, gt_offset) - max(est_onset, gt_onset)) ... | |
/ (max(est_offset, gt_offset) - min(est_onset, gt_onset)); | |
IsUsedEst(est_note) = 1; | |
break; | |
end | |
else % offset difference is involved in the criterion | |
if (mod(est_freq - gt_freq, 12) <= FreqDevTh || mod(gt_freq - est_freq, 12) <= FreqDevTh) ... | |
&& abs(est_onset - gt_onset) <= OnsetDiff ... | |
&& abs(est_offset - gt_offset) <= OffsetDiff * (gt_offset-gt_onset) | |
nChromaCorrect = nChromaCorrect + 1; % match | |
ChromaAOR = ChromaAOR ... | |
+ (min(est_offset, gt_offset) - max(est_onset, gt_onset)) ... | |
/ (max(est_offset, gt_offset) - min(est_onset, gt_onset)); | |
IsUsedEst(est_note) = 1; | |
break; | |
end | |
end | |
end | |
end | |
end | |
% calculate statistics | |
Results.MulPre = nCorrect/nEstNote; | |
Results.MulRec = nCorrect/nGtNote; | |
Results.MulFme = 2*Results.MulPre*Results.MulRec ... | |
/ (Results.MulPre + Results.MulRec); | |
Results.MulAcc = nCorrect / (nEstNote + nGtNote - nCorrect); | |
Results.MulAOR = AOR/nCorrect; | |
if nCorrect==0 | |
Results.MulFme = 0; | |
Results.MulAOR = 0; | |
end | |
Results.OctPre = nChromaCorrect/nEstNote; | |
Results.OctRec = nChromaCorrect/nGtNote; | |
Results.OctFme = 2*Results.OctPre*Results.OctRec ... | |
/ (Results.OctPre + Results.OctRec); | |
Results.OctAcc = nChromaCorrect / (nEstNote + nGtNote - nCorrect); | |
Results.OctAOR = ChromaAOR/nChromaCorrect; | |
if nChromaCorrect==0 | |
Results.OctFme = 0; | |
Results.OctAOR = 0; | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment