function extractFeaturesAndTrain(trainFileList, scratchDir, skip)
% extractFeaturesAndTrain(trainFileList, scratchDir, skip)
%      First part of MIREX08 chord recognition.
% 2008-08-21 Dan Ellis dpwe@ee.columbia.edu  based on recog_chords_1fold.m

if nargin < 3; skip = 0; end

trnf = calcbeatchroma(trainFileList,'','',scratchDir,'-400.mat', skip, 400);
trnf2 = calcbeatchroma(trainFileList,'','',scratchDir,'-100.mat', skip, 100);
labf = rewrite_chordlabs_mirex(trainFileList,'','.txt',scratchDir,'lab.mat',scratchDir,'-400.mat');

% output list of written files
fl = [trnf,labf];

%function [S,C,M,T] = chord_recog_1fold(trnf,tstf)
% [S,C,M,T] = chord_recog_1fold(trnf,tstf)
%     Train and test chord recognition system using data specified
%     in file named trnf for training and tstf for test.
% 2008-08-12 Dan Ellis dpwe@ee.columbia.edu after recog_chords.m


% could stop here and leave training models to test, but...

% load training data
F = loadftrs_mirex(trnf);
L = loadlabs_mirex(labf);

disp([trainFileList,': ',num2str(length(F)),' frames']);

luul2 = 25;  % num models

% build models
% 3 models - major, minor, N
majdat = zeros(size(F,1),0);
mindat = zeros(size(F,1),0);
for i = 1:12;
  zz=find(L==i);
  majdat = [majdat,chromrot2(F(:,zz),i-1)];
  zz=find(L==i+12);
  mindat = [mindat,chromrot2(F(:,zz),i-1)];
end
MAJ = build_model(majdat);
MIN = build_model(mindat);
for i = 1:12
  r = -(i-1);
  M(i) = transpose_model(MAJ,r);
  M(i+12) = transpose_model(MIN,r);
end
% state 25 is the N model (which we don't use anyway)
M(25) = build_model(F(:,find(L==25)));

    
% With HMM transition matrix
% Make a list of all transitions
gtt = 100*L(1:end-1)+L(2:end);
tx = zeros(luul2,luul2);
for i = 1:luul2; 
  for j = 1:luul2; 
    nn = 100*i+j; 
    tx(i,j)=sum(gtt==nn);
  end;
end
% normalize each row
stx = sum(tx')';
stx = stx + (stx==0);
txn = tx./repmat(stx,1,luul2);
stxn = sum(tx(1:end-1,1:end-1)')';
stxn = stxn+(stxn==0);
txnn = tx(1:end-1,1:end-1)./repmat(stxn,1,luul2-1);

% get rid of zeros in tx matrix
minnz = min(txnn(txnn(:)>0));
txnn(txnn(:)==0) = minnz/2;

% Save models
modelfile = fullfile(scratchDir,'MODELS');
save(modelfile, 'M', 'txnn');



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Y = chromrot2(X,N)
% Y = chromrot2(X,N)
%    Rotate each column of chroma feature matrix X down by N
%    semitones.
%    If X has 24 rows, rotate each block of 12 separately
% 2006-07-15, 2008-08-12 dpwe@ee.columbia.edu

[nr,nc] = size(X);

if nr <= 12
  Y = X(1+rem([0:(nr-1)]+N+nr,nr),:);
else
  X1 = X(1:12,:);
  X2 = X(13:end,:);
  nr1 = 12;
  Y1 = X1(1+rem([0:(nr1-1)]+N+nr1,nr1),:);
  nr2 = nr - nr1;
  Y2 = X2(1+rem([0:(nr2-1)]+N+nr2,nr2),:);
  Y = [Y1;Y2];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function M = build_model(D)
% M = build_model(D)
%    D is a matrix of data columns.
%    Return structure M that describes it.
% 2008-10-12 Dan Ellis dpwe@ee.columbia.edu

M.mean = mean(D');
M.cov  = cov(D');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function N = transpose_model(M,R)
% N = transpose_model(M,R)
%    Transpose a chroma model down R semitones
% 2008-10-12 Dan Ellis dpwe@ee.columbia.edu

N.mean = chromrot2(M.mean',R)';
N.cov  = chromrot2(chromrot2(M.cov',R)',R);

