matthiasm@8: function [chromagram,t,salience] = ... matthiasm@8: mychroma(filename, nBins, fmin, used_fs, fracofsecond, calcu) matthiasm@8: matthiasm@8: if isempty(nBins) matthiasm@8: nBins = 3; matthiasm@8: end matthiasm@8: midbin = ceil(nBins/2); matthiasm@8: if isempty(fmin) matthiasm@8: fmin = 55 * 2^(-7/12-(midbin-1)/12/nBins); matthiasm@8: end matthiasm@8: matthiasm@8: if isempty(used_fs) matthiasm@8: used_fs=round(44100/4); matthiasm@8: end matthiasm@8: matthiasm@8: hopspersecond = 20; matthiasm@8: nFFT = 2^nextpow2(used_fs/fracofsecond); matthiasm@8: hopsize = used_fs/hopspersecond/nFFT; matthiasm@8: noterange = 61; matthiasm@8: used_instruments = 1:2; matthiasm@8: nInstrument = length(used_instruments); matthiasm@8: matthiasm@8: %% load or generate dictionary matthiasm@8: dirc = what('./data'); matthiasm@8: dicfilename = ['mydict-' num2str(nBins) '.mat']; matthiasm@8: if ~calcu && any(strcmp(dirc.mat, dicfilename)) matthiasm@8: load(['data/' dicfilename]) matthiasm@8: else matthiasm@8: % dictionary parameters matthiasm@8: midbin = nBins/2 + .5; matthiasm@8: %hopspersecond = 10; matthiasm@8: secs = .8; matthiasm@8: t = linspace(0,secs,secs*used_fs)'; matthiasm@8: matthiasm@8: % make note dictionary matthiasm@8: A = zeros(noterange*nBins,nFFT/2,nInstrument); matthiasm@8: for iInstrument = used_instruments matthiasm@8: for iMidiNote = 1:noterange matthiasm@8: for iBin = 1:nBins matthiasm@8: f0 = fmin * 2^((iMidiNote-1)/12 + (iBin-1)/12/nBins); matthiasm@8: %wave = zeros(size(t)); matthiasm@8: switch iInstrument matthiasm@8: case 1 matthiasm@8: wave = sum([sin(t*2*pi*f0*1) ... matthiasm@8: 0.6^1 * sin(t*2*pi*f0*2) ... matthiasm@8: 0.6^2 * sin(t*2*pi*f0*3) ... matthiasm@8: 0.6^3 * sin(t*2*pi*f0*4)],2); matthiasm@8: case 2 matthiasm@8: wave = sin(t*2*pi*f0*1); matthiasm@8: case 3 matthiasm@8: wave = sum([... matthiasm@8: 0.6^1 * sin(t*2*pi*f0*1/2) ... matthiasm@8: 0.6^2 * sin(t*2*pi*f0*1/3) ... matthiasm@8: 0.6^3 * sin(t*2*pi*f0*1/4) ... matthiasm@8: 0.6^4 * sin(t*2*pi*f0*1/5) ... matthiasm@8: 0.6^5 * sin(t*2*pi*f0*1/6) ... matthiasm@8: 0.6^6 * sin(t*2*pi*f0*1/7) ... matthiasm@8: 0.6^7 * sin(t*2*pi*f0*1/8) ... matthiasm@8: 0.6^8 * sin(t*2*pi*f0*1/9)],2); matthiasm@8: end matthiasm@8: fftframes0 = myframefft(wave,nFFT,hopsize,'hamming'); matthiasm@8: A(nBins*(iMidiNote-1)+iBin,:,iInstrument) = mean(abs(fftframes0(1:round(nFFT/2),:)),2); matthiasm@8: end matthiasm@8: end matthiasm@8: end matthiasm@8: save(['data/' dicfilename], 'A', 'nFFT', 'hopsize'); matthiasm@8: end matthiasm@8: matthiasm@8: %% get the fft frames from a wave file matthiasm@8: fprintf(1,'%s\n',filename) matthiasm@8: [audiosize,fs] = wavread(filename,'size'); matthiasm@8: chunk_sec = 20; matthiasm@8: nChunk = ceil(audiosize(1)/fs/chunk_sec); matthiasm@8: songframes = []; matthiasm@8: s = []; matthiasm@8: start = 1; matthiasm@8: matthiasm@8: for iChunk = 1:nChunk matthiasm@8: samplemin = (iChunk-1) * chunk_sec * fs + 1; matthiasm@8: samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs); matthiasm@8: matthiasm@8: audiodata0 = wavread(filename,[samplemin samplemax]); matthiasm@8: matthiasm@8: audiodata = resample(mean(audiodata0,2),used_fs,fs,20); matthiasm@8: matthiasm@8: songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming'); matthiasm@8: matthiasm@8: if size(songframes0,2)>=start matthiasm@8: songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))]; matthiasm@8: end matthiasm@8: start = round(hopspersecond/2)+1; matthiasm@8: end matthiasm@8: clear songframes0 matthiasm@8: clear audiodata matthiasm@8: clear audiodata0 matthiasm@8: matthiasm@8: T = size(songframes,2); matthiasm@8: t = (0:T-1)./hopspersecond; matthiasm@8: fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T) matthiasm@8: matthiasm@8: simpleS = zeros(noterange*nBins,T, nInstrument+1); matthiasm@8: songframes(isnan(songframes)) = 0; matthiasm@8: matthiasm@8: for iInstrument = 1:nInstrument matthiasm@8: At = A(:,:,iInstrument); matthiasm@8: for kFrame = 1:T matthiasm@8: simpleS(:,kFrame,iInstrument) = At * songframes(:,kFrame); matthiasm@8: end matthiasm@8: end matthiasm@8: simpleS(:,:,2) = max(0,conv2(simpleS(:,:,2), ... matthiasm@8: repmat([-1 -1 4 -1 -1]',1,1),'same')); matthiasm@8: matthiasm@8: %% add the instruments (i.e. the different partial decay bla) matthiasm@8: %--------------------------------------------------------- matthiasm@8: note_s = (simpleS(:,:,1) .* simpleS(:,:,2)); matthiasm@8: clear simpleS matthiasm@8: matthiasm@8: %% tuning matthiasm@8: matthiasm@8: wrapped_s = zeros(nBins,T); matthiasm@8: for iBin = 1:nBins matthiasm@8: wrapped_s(iBin,:) = sum(note_s(iBin:nBins:end,:)); matthiasm@8: end matthiasm@8: on_circle = exp(i * ((1:nBins)-midbin)/nBins * 2 * pi); matthiasm@8: complex_tuning = on_circle * wrapped_s; matthiasm@8: smooth_complex_tuning = conv2(complex_tuning,hamming(20*hopspersecond)','same'); matthiasm@8: tooflat = angle(mean(smooth_complex_tuning)) / (2 * pi) * nBins; matthiasm@8: tooflat = repmat(tooflat,T,1); matthiasm@8: tuned_s = note_s; matthiasm@8: for iFrame = 1:T matthiasm@8: tuned_s(:,iFrame) = interp1(1:nBins*noterange, note_s(:,iFrame), (1:nBins*noterange) + 1 * tooflat(iFrame),[],0); matthiasm@8: end matthiasm@8: matthiasm@8: %% reduce to 1 bin per semitone matthiasm@8: wrapped_tuned_s = reshape(tuned_s,[nBins,noterange*T]); matthiasm@8: wei = rectwin(nBins)'; matthiasm@8: reduced = reshape(wei * wrapped_tuned_s,noterange,T); matthiasm@8: matthiasm@8: salience.full = s; matthiasm@8: salience.reduced = reduced; matthiasm@8: matthiasm@8: %% make chromagram matthiasm@8: matthiasm@8: reduced = medfilt1(reduced',9)'; matthiasm@8: chromagen = [zeros(12,1) repmat(eye(12),1,5)]; matthiasm@8: matthiasm@8: matthiasm@8: 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: bass_profile = [0 ones(1,18) linspace(1,0,12) ,zeros(1,noterange-31)]; matthiasm@8: wide_profile = max(treble_profile, bass_profile); matthiasm@8: matthiasm@8: treble_salience = reduced .* repmat(treble_profile(:),1,T); matthiasm@8: bass_salience = reduced .* repmat(bass_profile(:),1,T); matthiasm@8: wide_salience = reduced .* repmat(wide_profile(:),1,T); matthiasm@8: matthiasm@8: bass_chromag = circshift(chromagen * bass_salience,6); matthiasm@8: wide_chromag = circshift(chromagen * wide_salience,6); matthiasm@8: matthiasm@8: [peakindex,peakindex]=sort(treble_salience,'descend'); matthiasm@8: for iFrame = 1:T matthiasm@8: treble_salience(peakindex(1,iFrame),iFrame) = treble_salience(peakindex(2,iFrame),iFrame); matthiasm@8: end matthiasm@8: treble_chromag = circshift(chromagen * treble_salience,6); matthiasm@8: matthiasm@8: chromagram.treble = treble_chromag; matthiasm@8: chromagram.bass = bass_chromag; matthiasm@8: chromagram.wide = wide_chromag; matthiasm@8: matthiasm@8: % csvwrite('chr.csv',[ones(25,1) [maxn(circshift(bass_chromag,4));ones(1,size(treble_chromag,2)); maxn(circshift(treble_chromag,4))]]'); matthiasm@8: % csvwrite('tuned_s.csv',[maxn(reduced)]');