Mercurial > hg > silvet
comparison mirex2012-matlab/genCQTkernel.m @ 2:8017dd4a650d
Add MIREX 2012 code
author | Chris Cannam |
---|---|
date | Wed, 19 Mar 2014 09:09:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1:662b0a8b17b9 | 2:8017dd4a650d |
---|---|
1 function cqtKernel = genCQTkernel(fmax, bins, fs, varargin) | |
2 %Calculating the CQT Kernel for one octave. All atoms are center-stacked. | |
3 %Atoms are placed so that the stacks of lower octaves are centered at the | |
4 %same positions in time, however, their amount is reduced by factor two for | |
5 %each octave down. | |
6 % | |
7 %INPUT: | |
8 % fmax ... highest frequency of interest | |
9 % bins ... number of bins per octave | |
10 % fs ... sampling frequency | |
11 % | |
12 %optional input parameters (parameter name/value pairs): | |
13 % | |
14 % 'q' ... Q scaling factor. Default: 1. | |
15 % 'atomHopFactor' ... relative hop size corresponding to the shortest | |
16 % temporal atom. Default: 0.25. | |
17 % 'thresh' ... values smaller than 'tresh' in the spectral kernel are rounded to | |
18 % zero. Default: 0.0005. | |
19 % 'win' ... defines which window will be used for the CQT. Valid | |
20 % values are: 'blackman','hann' and 'blackmanharris'. To | |
21 % use the square root of each window use the prefix 'sqrt_' | |
22 % (i.e. 'sqrt_blackman'). Default: 'sqrt_blackmanharris' | |
23 % 'perfRast' ... if set to 1 the kernel is designed in order to | |
24 % enable perfect rasterization using the function | |
25 % cqtPerfectRast() (Default: perRast=0). See documentation of | |
26 % 'cqtPerfectRast' for further information. | |
27 % | |
28 %OUTPUT: | |
29 % cqtKernel ... Structure that contains the spectral kernel 'fKernel' | |
30 % additional design parameters used in cqt(), cqtPerfectRast() and icqt(). | |
31 % | |
32 %Christian Schörkhuber, Anssi Klapuri 2010-06 | |
33 | |
34 %% input parameters | |
35 q = 1; %default value | |
36 atomHopFactor = 0.25; %default value | |
37 thresh = 0.0005; %default value | |
38 winFlag = 'sqrt_blackmanharris'; %default value | |
39 perfRast = 0; %default value | |
40 | |
41 for ain = 1:length(varargin) | |
42 if strcmp(varargin{ain},'q'), q = varargin{ain+1}; end; | |
43 if strcmp(varargin{ain},'atomHopFactor'), atomHopFactor = varargin{ain+1}; end; | |
44 if strcmp(varargin{ain},'thresh'), thresh = varargin{ain+1}; end; | |
45 if strcmp(varargin{ain},'win'), winFlag = varargin{ain+1}; end; | |
46 if strcmp(varargin{ain},'perfRast'), perfRast = varargin{ain+1}; end; | |
47 end | |
48 | |
49 %% define | |
50 fmin = (fmax/2)*2^(1/bins); | |
51 Q = 1/(2^(1/bins)-1); | |
52 Q = Q*q; | |
53 Nk_max = Q * fs / fmin; | |
54 Nk_max = round(Nk_max); %length of the largest atom [samples] | |
55 | |
56 | |
57 %% Compute FFT size, FFT hop, atom hop, ... | |
58 Nk_min = round( Q * fs / (fmin*2^((bins-1)/bins)) ); %length of the shortest atom [samples] | |
59 atomHOP = round(Nk_min*atomHopFactor); %atom hop size | |
60 first_center = ceil(Nk_max/2); %first possible center position within the frame | |
61 first_center = atomHOP * ceil(first_center/atomHOP); %lock the first center to an integer multiple of the atom hop size | |
62 FFTLen = 2^nextpow2(first_center+ceil(Nk_max/2)); %use smallest possible FFT size (increase sparsity) | |
63 | |
64 if perfRast | |
65 winNr = floor((FFTLen-ceil(Nk_max/2)-first_center)/atomHOP); %number of temporal atoms per FFT Frame | |
66 if winNr == 0 | |
67 FFTLen = FFTLen * 2; | |
68 winNr = floor((FFTLen-ceil(Nk_max/2)-first_center)/atomHOP); | |
69 end | |
70 else | |
71 winNr = floor((FFTLen-ceil(Nk_max/2)-first_center)/atomHOP)+1; %number of temporal atoms per FFT Frame | |
72 end | |
73 | |
74 last_center = first_center + (winNr-1)*atomHOP; | |
75 fftHOP = (last_center + atomHOP) - first_center; % hop size of FFT frames | |
76 fftOLP = (FFTLen-fftHOP/FFTLen)*100; %overlap of FFT frames in percent ***AK:needed? | |
77 | |
78 %% init variables | |
79 tempKernel= zeros(1,FFTLen); | |
80 sparKernel= []; | |
81 | |
82 %% Compute kernel | |
83 atomInd = 0; | |
84 for k = 1:bins | |
85 | |
86 Nk = round( Q * fs / (fmin*2^((k-1)/bins)) ); %N[k] = (fs/fk)*Q. Rounding will be omitted in future versions | |
87 | |
88 switch winFlag | |
89 case 'sqrt_blackmanharris' | |
90 winFct = sqrt(blackmanharris(Nk)); | |
91 case 'blackmanharris' | |
92 winFct = blackmanharris(Nk); | |
93 case 'sqrt_hann' | |
94 winFct = sqrt(hann(Nk,'periodic')); | |
95 case 'hann' | |
96 winFct = hann(Nk,'periodic'); | |
97 case 'sqrt_blackman' | |
98 winFct = sqrt(hann(blackman,'periodic')); | |
99 case 'blackman' | |
100 winFct = blackman(Nk,'periodic'); | |
101 otherwise | |
102 winFct = sqrt(blackmanharris(Nk)); | |
103 if k==1, warning('CQT:INPUT','Non-existing window function. Default window is used!'); end; | |
104 end | |
105 | |
106 fk = fmin*2^((k-1)/bins); | |
107 tempKernelBin = (winFct/Nk) .* exp(2*pi*1i*fk*(0:Nk-1)'/fs); | |
108 atomOffset = first_center - ceil(Nk/2); | |
109 | |
110 for i = 1:winNr | |
111 shift = atomOffset + ((i-1) * atomHOP); | |
112 tempKernel(1+shift:Nk+shift) = tempKernelBin; | |
113 atomInd = atomInd+1; | |
114 specKernel= fft(tempKernel); | |
115 specKernel(abs(specKernel)<=thresh)= 0; | |
116 sparKernel= sparse([sparKernel; specKernel]); | |
117 tempKernel = zeros(1,FFTLen); %reset window | |
118 end | |
119 end | |
120 sparKernel = (sparKernel.')/FFTLen; | |
121 | |
122 %% Normalize the magnitudes of the atoms | |
123 [ignore,wx1]=max(sparKernel(:,1)); | |
124 [ignore,wx2]=max(sparKernel(:,end)); | |
125 wK=sparKernel(wx1:wx2,:); | |
126 wK = diag(wK * wK'); | |
127 wK = wK(round(1/q)+1:(end-round(1/q)-2)); | |
128 weight = 1./mean(abs(wK)); | |
129 weight = weight.*(fftHOP/FFTLen); | |
130 weight = sqrt(weight); %sqrt because the same weight is applied in icqt again | |
131 sparKernel = weight.*sparKernel; | |
132 | |
133 %% return | |
134 cqtKernel = struct('fKernel',sparKernel,'fftLEN',FFTLen,'fftHOP',fftHOP,'fftOverlap',fftOLP,'perfRast',perfRast,... | |
135 'bins',bins,'firstcenter',first_center,'atomHOP',atomHOP,'atomNr',winNr,'Nk_max',Nk_max,'Q',Q,'fmin',fmin); |