Dimitrios@0: function spCQT = cell2sparse(Xcq,octaves,bins,firstcenter,atomHOP,atomNr) Dimitrios@0: %Generates a sparse matrix containing the CQT coefficients (rasterized). Dimitrios@0: % Dimitrios@0: %The sparse matrix representation of the CQT coefficients contains all Dimitrios@0: %computed coefficients at the corresponding time-frequency location Dimitrios@0: %(similar to a spectrogram). For lower frequencies this means, that Dimitrios@0: %each coefficient is followed by zeros stemming from the fact, that the time Dimitrios@0: %resolution for lower frequencies decreases as the frequency resolution Dimitrios@0: %increases. Due to the design of the CQT kernel, however, the coefficients Dimitrios@0: %of different octaves are synchronised, meaning that for the second highest Dimitrios@0: %octave each coefficient is followed by one zero, for the next octave down Dimitrios@0: %two zeros are inserted, for the next octave four zeros are inserted and so Dimitrios@0: %on. Dimitrios@0: % Dimitrios@0: %INPUT: Dimitrios@0: % Xcq ... Cell array consisting of all coefficients for all octaves Dimitrios@0: % octaves ... Number of octaves processed Dimitrios@0: % bins ... Number of bins per octave Dimitrios@0: % firstcenter ... Location of the leftmost atom-stack in the temporal Dimitrios@0: % kernel Dimitrios@0: % atomHOP ... Spacing of two consecutive atom stacks Dimitrios@0: % atomNr ... Number of atoms per bin within the kernel Dimitrios@0: % Dimitrios@0: %Christian Schörkhuber, Anssi Klapuri 2010-06 Dimitrios@0: Dimitrios@0: if 0 Dimitrios@0: %% this version has big memory consumption but is very fast Dimitrios@0: emptyHops = firstcenter/atomHOP; Dimitrios@0: drop = emptyHops*2^(octaves-1)-emptyHops; %distance between first value in highest octave and first value in lowest octave Dimitrios@0: spCQT = zeros(bins*octaves,size(Xcq{1},2)*atomNr-drop); Dimitrios@0: Dimitrios@0: for i=1:octaves Dimitrios@0: drop = emptyHops*2^(octaves-i)-emptyHops; %first coefficients of all octaves have to be in synchrony Dimitrios@0: X = Xcq{i}; Dimitrios@0: if atomNr > 1 %more than one atom per bin --> reshape Dimitrios@0: Xoct = zeros(bins,atomNr*size(X,2)-drop); Dimitrios@0: for u=1:bins %reshape to continous windows for each bin (for the case of several wins per frame) Dimitrios@0: octX_bin = X((u-1)*atomNr+1:u*atomNr,:); Dimitrios@0: Xcont = reshape(octX_bin,1,size(octX_bin,1)*size(octX_bin,2)); Dimitrios@0: Xoct(u,:) = Xcont(1+drop:end); Dimitrios@0: end Dimitrios@0: X = Xoct; Dimitrios@0: else Dimitrios@0: X = X(:,1+drop:end); Dimitrios@0: end Dimitrios@0: binVec = bins*octaves-bins*i+1:bins*octaves-bins*(i-1); Dimitrios@0: spCQT(binVec,1:2^(i-1):size(X,2)*2^(i-1)) = X; Dimitrios@0: Dimitrios@0: end Dimitrios@0: spCQT = sparse(spCQT); %storing as sparse matrix at the end is the fastest way. Big memory consumption though! Dimitrios@0: Dimitrios@0: else Dimitrios@0: %% this version uses less memory but is noticable slower Dimitrios@0: emptyHops = firstcenter/atomHOP; Dimitrios@0: drops = emptyHops*2.^(octaves-(1:octaves))-emptyHops; Dimitrios@0: len = max(((atomNr*cellfun('size',Xcq,2)-drops).*2.^(0:octaves-1))); %number of columns of output matrix Dimitrios@0: spCQT = []; Dimitrios@0: Dimitrios@0: for i=octaves:-1:1 Dimitrios@0: drop = emptyHops*2^(octaves-i)-emptyHops; %first coefficients of all octaves have to be in synchrony Dimitrios@0: X = Xcq{i}; Dimitrios@0: if atomNr > 1 %more than one atom per bin --> reshape Dimitrios@0: Xoct = zeros(bins,atomNr*size(X,2)-drop); Dimitrios@0: for u=1:bins %reshape to continous windows for each bin (for the case of several wins per frame) Dimitrios@0: octX_bin = X((u-1)*atomNr+1:u*atomNr,:); Dimitrios@0: Xcont = reshape(octX_bin,1,size(octX_bin,1)*size(octX_bin,2)); Dimitrios@0: Xoct(u,:) = Xcont(1+drop:end); Dimitrios@0: end Dimitrios@0: X = Xoct; Dimitrios@0: else Dimitrios@0: X = X(:,1+drop:end); Dimitrios@0: end Dimitrios@0: X = upsample(X.',2^(i-1)).'; Dimitrios@0: X = [X zeros(bins,len-size(X,2))]; Dimitrios@0: spCQT = sparse([spCQT; X]); Dimitrios@0: end Dimitrios@0: Dimitrios@0: end