matthiasm@8
|
1 function [chromagram,t,salience] = ...
|
matthiasm@8
|
2 mychroma(filename, nBins, fmin, used_fs, fracofsecond, calcu)
|
matthiasm@8
|
3
|
matthiasm@8
|
4 if isempty(nBins)
|
matthiasm@8
|
5 nBins = 3;
|
matthiasm@8
|
6 end
|
matthiasm@8
|
7 midbin = ceil(nBins/2);
|
matthiasm@8
|
8 if isempty(fmin)
|
matthiasm@8
|
9 fmin = 55 * 2^(-7/12-(midbin-1)/12/nBins);
|
matthiasm@8
|
10 end
|
matthiasm@8
|
11
|
matthiasm@8
|
12 if isempty(used_fs)
|
matthiasm@8
|
13 used_fs=round(44100/4);
|
matthiasm@8
|
14 end
|
matthiasm@8
|
15
|
matthiasm@8
|
16 hopspersecond = 20;
|
matthiasm@8
|
17 nFFT = 2^nextpow2(used_fs/fracofsecond);
|
matthiasm@8
|
18 hopsize = used_fs/hopspersecond/nFFT;
|
matthiasm@8
|
19 noterange = 61;
|
matthiasm@8
|
20 used_instruments = 1:2;
|
matthiasm@8
|
21 nInstrument = length(used_instruments);
|
matthiasm@8
|
22
|
matthiasm@8
|
23 %% load or generate dictionary
|
matthiasm@8
|
24 dirc = what('./data');
|
matthiasm@8
|
25 dicfilename = ['mydict-' num2str(nBins) '.mat'];
|
matthiasm@8
|
26 if ~calcu && any(strcmp(dirc.mat, dicfilename))
|
matthiasm@8
|
27 load(['data/' dicfilename])
|
matthiasm@8
|
28 else
|
matthiasm@8
|
29 % dictionary parameters
|
matthiasm@8
|
30 midbin = nBins/2 + .5;
|
matthiasm@8
|
31 %hopspersecond = 10;
|
matthiasm@8
|
32 secs = .8;
|
matthiasm@8
|
33 t = linspace(0,secs,secs*used_fs)';
|
matthiasm@8
|
34
|
matthiasm@8
|
35 % make note dictionary
|
matthiasm@8
|
36 A = zeros(noterange*nBins,nFFT/2,nInstrument);
|
matthiasm@8
|
37 for iInstrument = used_instruments
|
matthiasm@8
|
38 for iMidiNote = 1:noterange
|
matthiasm@8
|
39 for iBin = 1:nBins
|
matthiasm@8
|
40 f0 = fmin * 2^((iMidiNote-1)/12 + (iBin-1)/12/nBins);
|
matthiasm@8
|
41 %wave = zeros(size(t));
|
matthiasm@8
|
42 switch iInstrument
|
matthiasm@8
|
43 case 1
|
matthiasm@8
|
44 wave = sum([sin(t*2*pi*f0*1) ...
|
matthiasm@8
|
45 0.6^1 * sin(t*2*pi*f0*2) ...
|
matthiasm@8
|
46 0.6^2 * sin(t*2*pi*f0*3) ...
|
matthiasm@8
|
47 0.6^3 * sin(t*2*pi*f0*4)],2);
|
matthiasm@8
|
48 case 2
|
matthiasm@8
|
49 wave = sin(t*2*pi*f0*1);
|
matthiasm@8
|
50 case 3
|
matthiasm@8
|
51 wave = sum([...
|
matthiasm@8
|
52 0.6^1 * sin(t*2*pi*f0*1/2) ...
|
matthiasm@8
|
53 0.6^2 * sin(t*2*pi*f0*1/3) ...
|
matthiasm@8
|
54 0.6^3 * sin(t*2*pi*f0*1/4) ...
|
matthiasm@8
|
55 0.6^4 * sin(t*2*pi*f0*1/5) ...
|
matthiasm@8
|
56 0.6^5 * sin(t*2*pi*f0*1/6) ...
|
matthiasm@8
|
57 0.6^6 * sin(t*2*pi*f0*1/7) ...
|
matthiasm@8
|
58 0.6^7 * sin(t*2*pi*f0*1/8) ...
|
matthiasm@8
|
59 0.6^8 * sin(t*2*pi*f0*1/9)],2);
|
matthiasm@8
|
60 end
|
matthiasm@8
|
61 fftframes0 = myframefft(wave,nFFT,hopsize,'hamming');
|
matthiasm@8
|
62 A(nBins*(iMidiNote-1)+iBin,:,iInstrument) = mean(abs(fftframes0(1:round(nFFT/2),:)),2);
|
matthiasm@8
|
63 end
|
matthiasm@8
|
64 end
|
matthiasm@8
|
65 end
|
matthiasm@8
|
66 save(['data/' dicfilename], 'A', 'nFFT', 'hopsize');
|
matthiasm@8
|
67 end
|
matthiasm@8
|
68
|
matthiasm@8
|
69 %% get the fft frames from a wave file
|
matthiasm@8
|
70 fprintf(1,'%s\n',filename)
|
matthiasm@8
|
71 [audiosize,fs] = wavread(filename,'size');
|
matthiasm@8
|
72 chunk_sec = 20;
|
matthiasm@8
|
73 nChunk = ceil(audiosize(1)/fs/chunk_sec);
|
matthiasm@8
|
74 songframes = [];
|
matthiasm@8
|
75 s = [];
|
matthiasm@8
|
76 start = 1;
|
matthiasm@8
|
77
|
matthiasm@8
|
78 for iChunk = 1:nChunk
|
matthiasm@8
|
79 samplemin = (iChunk-1) * chunk_sec * fs + 1;
|
matthiasm@8
|
80 samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);
|
matthiasm@8
|
81
|
matthiasm@8
|
82 audiodata0 = wavread(filename,[samplemin samplemax]);
|
matthiasm@8
|
83
|
matthiasm@8
|
84 audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
|
matthiasm@8
|
85
|
matthiasm@8
|
86 songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
|
matthiasm@8
|
87
|
matthiasm@8
|
88 if size(songframes0,2)>=start
|
matthiasm@8
|
89 songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
|
matthiasm@8
|
90 end
|
matthiasm@8
|
91 start = round(hopspersecond/2)+1;
|
matthiasm@8
|
92 end
|
matthiasm@8
|
93 clear songframes0
|
matthiasm@8
|
94 clear audiodata
|
matthiasm@8
|
95 clear audiodata0
|
matthiasm@8
|
96
|
matthiasm@8
|
97 T = size(songframes,2);
|
matthiasm@8
|
98 t = (0:T-1)./hopspersecond;
|
matthiasm@8
|
99 fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
|
matthiasm@8
|
100
|
matthiasm@8
|
101 simpleS = zeros(noterange*nBins,T, nInstrument+1);
|
matthiasm@8
|
102 songframes(isnan(songframes)) = 0;
|
matthiasm@8
|
103
|
matthiasm@8
|
104 for iInstrument = 1:nInstrument
|
matthiasm@8
|
105 At = A(:,:,iInstrument);
|
matthiasm@8
|
106 for kFrame = 1:T
|
matthiasm@8
|
107 simpleS(:,kFrame,iInstrument) = At * songframes(:,kFrame);
|
matthiasm@8
|
108 end
|
matthiasm@8
|
109 end
|
matthiasm@8
|
110 simpleS(:,:,2) = max(0,conv2(simpleS(:,:,2), ...
|
matthiasm@8
|
111 repmat([-1 -1 4 -1 -1]',1,1),'same'));
|
matthiasm@8
|
112
|
matthiasm@8
|
113 %% add the instruments (i.e. the different partial decay bla)
|
matthiasm@8
|
114 %---------------------------------------------------------
|
matthiasm@8
|
115 note_s = (simpleS(:,:,1) .* simpleS(:,:,2));
|
matthiasm@8
|
116 clear simpleS
|
matthiasm@8
|
117
|
matthiasm@8
|
118 %% tuning
|
matthiasm@8
|
119
|
matthiasm@8
|
120 wrapped_s = zeros(nBins,T);
|
matthiasm@8
|
121 for iBin = 1:nBins
|
matthiasm@8
|
122 wrapped_s(iBin,:) = sum(note_s(iBin:nBins:end,:));
|
matthiasm@8
|
123 end
|
matthiasm@8
|
124 on_circle = exp(i * ((1:nBins)-midbin)/nBins * 2 * pi);
|
matthiasm@8
|
125 complex_tuning = on_circle * wrapped_s;
|
matthiasm@8
|
126 smooth_complex_tuning = conv2(complex_tuning,hamming(20*hopspersecond)','same');
|
matthiasm@8
|
127 tooflat = angle(mean(smooth_complex_tuning)) / (2 * pi) * nBins;
|
matthiasm@8
|
128 tooflat = repmat(tooflat,T,1);
|
matthiasm@8
|
129 tuned_s = note_s;
|
matthiasm@8
|
130 for iFrame = 1:T
|
matthiasm@8
|
131 tuned_s(:,iFrame) = interp1(1:nBins*noterange, note_s(:,iFrame), (1:nBins*noterange) + 1 * tooflat(iFrame),[],0);
|
matthiasm@8
|
132 end
|
matthiasm@8
|
133
|
matthiasm@8
|
134 %% reduce to 1 bin per semitone
|
matthiasm@8
|
135 wrapped_tuned_s = reshape(tuned_s,[nBins,noterange*T]);
|
matthiasm@8
|
136 wei = rectwin(nBins)';
|
matthiasm@8
|
137 reduced = reshape(wei * wrapped_tuned_s,noterange,T);
|
matthiasm@8
|
138
|
matthiasm@8
|
139 salience.full = s;
|
matthiasm@8
|
140 salience.reduced = reduced;
|
matthiasm@8
|
141
|
matthiasm@8
|
142 %% make chromagram
|
matthiasm@8
|
143
|
matthiasm@8
|
144 reduced = medfilt1(reduced',9)';
|
matthiasm@8
|
145 chromagen = [zeros(12,1) repmat(eye(12),1,5)];
|
matthiasm@8
|
146
|
matthiasm@8
|
147
|
matthiasm@8
|
148 treble_profile = ([0 zeros(1,24) linspace(0,1,6) linspace(1,1,6) ones(1,12) linspace(1,0,6) zeros(1,6)]);
|
matthiasm@8
|
149 bass_profile = [0 ones(1,18) linspace(1,0,12) ,zeros(1,noterange-31)];
|
matthiasm@8
|
150 wide_profile = max(treble_profile, bass_profile);
|
matthiasm@8
|
151
|
matthiasm@8
|
152 treble_salience = reduced .* repmat(treble_profile(:),1,T);
|
matthiasm@8
|
153 bass_salience = reduced .* repmat(bass_profile(:),1,T);
|
matthiasm@8
|
154 wide_salience = reduced .* repmat(wide_profile(:),1,T);
|
matthiasm@8
|
155
|
matthiasm@8
|
156 bass_chromag = circshift(chromagen * bass_salience,6);
|
matthiasm@8
|
157 wide_chromag = circshift(chromagen * wide_salience,6);
|
matthiasm@8
|
158
|
matthiasm@8
|
159 [peakindex,peakindex]=sort(treble_salience,'descend');
|
matthiasm@8
|
160 for iFrame = 1:T
|
matthiasm@8
|
161 treble_salience(peakindex(1,iFrame),iFrame) = treble_salience(peakindex(2,iFrame),iFrame);
|
matthiasm@8
|
162 end
|
matthiasm@8
|
163 treble_chromag = circshift(chromagen * treble_salience,6);
|
matthiasm@8
|
164
|
matthiasm@8
|
165 chromagram.treble = treble_chromag;
|
matthiasm@8
|
166 chromagram.bass = bass_chromag;
|
matthiasm@8
|
167 chromagram.wide = wide_chromag;
|
matthiasm@8
|
168
|
matthiasm@8
|
169 % csvwrite('chr.csv',[ones(25,1) [maxn(circshift(bass_chromag,4));ones(1,size(treble_chromag,2)); maxn(circshift(treble_chromag,4))]]');
|
matthiasm@8
|
170 % csvwrite('tuned_s.csv',[maxn(reduced)]');
|