% KAIST CS891 Special Lecture on Music Information Retrieval (MIR)
% Lab4.3: Chord recognition
% Kyogu Lee (August 2008)

clear all;
close all;

% read audio file
[x,fs] = wavread('../wav/8dayssegment.wav');
%[x,fs] = wavread('../wav/T39-piano.wav');
%[x,fs] = wavread('../wav/T08-violin.wav');
if size(x,2) > size(x,1)
    x = x'; % make a column vector
end
x = mean(x,2); % make mono
%x = x(1:2*fs); % first two seconds

% perform chroma analysis
% there are three different types of chroma analyses (by Dan Ellis)

% analysis parameters
fftlen = 2^nextpow2(round(fs*0.1)); % FFT length (100 ms)
hs = fftlen/4; % hop size
nbin = 12; % # of bins in an octave (usually 12)
f_ctr = 1000; % center frquency for weighting
f_sd = 1; % gaussian standard deviation for weighting

% compute chromagram
ch_e = chromagram_E(x,fs,fftlen,nbin,f_ctr,f_sd);
ch_e = circshift(ch_e,-3); % shift from A to C
nframe = size(ch_e,2);

% chord templates
Cmaj_temp = [1;0;0;0;1;0;0;1;0;0;0;0];
Cmin_temp = [1;0;0;1;0;0;0;1;0;0;0;0];
maj_temp = []; % major chord template
min_temp = []; % minor chord template

for i=1:12 % for each chord (maj/min)
  maj_temp = [maj_temp,circshift(Cmaj_temp,i-1)];
  min_temp = [min_temp,circshift(Cmin_temp,i-1)];
end

chord_temp = [maj_temp,min_temp]; % 12x24 chord template matrix

% chord recognition by computing correlation per frame
for i=1:nframe % for each frame
  cor = corrcoef([ch_e(:,i),chord_temp]);
  chord(i) = find(cor(1,2:end)==max(cor(1,2:end)));
% $$$   for c=1:24 % for each chord
% $$$     tmp = corrcoef(ch_e(:,i),chord_temp(:,c));
% $$$     cor(c) = tmp(1,2);
% $$$   end
% $$$   chord(i) = find(cor==max(cor));
end

% smoothing
chord_sm = medfilt1(chord,9);

% display
pitch_class = {'C','C#','D','Eb','E','F','F#','G','Ab','A','Bb','B'};
chord_label = {'C','C#','D','Eb','E','F','F#','G','Ab','A','Bb','B',...
               'c','c#','d','eb','e','f','f#','g','ab','a','bb','b'};

subplot(211); imagesc(ch_e); colormap(1-gray); set(gca,'YDir','normal');
title('chromagram'); ylabel('pitch class'); xlabel('time (frame)');
set(gca,'YTick',1:12,'YTickLabel',pitch_class);
subplot(212); plot(chord,'bo-'); hold on; plot(chord_sm,'rx-');
title('recognized chord'); ylabel('chord name'); xlabel('time (frame)'); ...
    grid on;
set(gca,'YTick',1:24,'YTickLabel',chord_label);