├── .DS_Store ├── .gitignore ├── CQT.py ├── Constant-Q_transform_toolbox_for_music_processing.pdf ├── LICENSE ├── MATLAB ├── DEMO.m ├── cell2sparse.m ├── cqt.m ├── cqtPerfectRast.m ├── genCQTkernel.m ├── getCQT.m ├── icqt.m ├── plotCQT.m └── sparse2cell.m ├── README.md └── demo.dat /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphysresearch/CQT_toolbox_python/950a923dfa7640eb67bbe044e7189cc34e3afdd9/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /CQT.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | import numpy as np 4 | from decimal import Decimal, ROUND_HALF_UP 5 | 6 | from scipy.signal import butter, blackman, blackmanharris, upfirdn, filtfilt 7 | from scipy import sparse 8 | from scipy.interpolate import interp1d 9 | 10 | import matplotlib.pyplot as plt 11 | 12 | 13 | 14 | def upsample(s, n, phase=0): 15 | """Increase sampling rate by integer factor n with included offset phase. 16 | """ 17 | return np.roll(np.kron(s, np.r_[1, np.zeros(n-1)]), phase) 18 | 19 | 20 | def buffer(x, n, p=0, opt=None): 21 | ''' 22 | Buffer function like MATLAB. (https://www.mathworks.com/help/signal/ref/buffer.html?searchHighlight=buffer&s_tid=srchtitle) 23 | 24 | Ref: https://stackoverflow.com/a/60020929 (Your can check more buffer algorithms from this) 25 | About buffer function in Python, see also: https://github.com/aaravindravi/python-signal-segmentation/blob/master/buffer.py 26 | ''' 27 | if opt not in ('nodelay', None): 28 | raise ValueError('{} not implemented'.format(opt)) 29 | 30 | i = 0 31 | if opt == 'nodelay': 32 | # No zeros at array start 33 | result = x[:n] 34 | i = n 35 | else: 36 | # Start with `p` zeros 37 | result = np.hstack([np.zeros(p), x[:n-p]]) 38 | i = n-p 39 | # Make 2D array, cast to list for .append() 40 | result = list(np.expand_dims(result, axis=0)) 41 | 42 | while i < len(x): 43 | # Create next column, add `p` results from last col if given 44 | col = x[i:i+(n-p)] 45 | if p != 0: 46 | col = np.hstack([result[-1][-p:], col]) 47 | 48 | # Append zeros if last row and not length `n` 49 | if len(col): 50 | col = np.hstack([col, np.zeros(n - len(col))]) 51 | 52 | # Combine result with next row 53 | result.append(np.array(col)) 54 | i += (n - p) 55 | 56 | return np.vstack(result).T 57 | 58 | def cqt(x, fmin, fmax, bins, fs, **kwargs): 59 | ''' 60 | %Xcqt = cqt(x,fmin,fmax,bins,fs,varargin) calculates the constant-Q transform of the input signal x. 61 | % 62 | %INPUT: 63 | % fmin ... lowest frequency of interest 64 | % fmax ... highest frequency of interest 65 | % bins ... frequency bins per octave 66 | % fs ... sampling rate 67 | % 68 | % optional input parameters (parameter name/value pairs): 69 | % 70 | % 'atomHopFactor' ... overlap of temporal atoms in percent. Default: 0.25. 71 | % 72 | % 'q' ... the maximum value for optimal reconstruction is q=1. 73 | % For values smaller than 1 the bandwidths of the spectral 74 | % atoms (filter) are increased retaining their center 75 | % frequencies (frequency 'smearing', frequency domain redundancy 76 | % increases, time resolutin improves). Default: 1. 77 | % 'thresh' ... all values in the cqt kernel smaller than tresh are 78 | % rounded to zero. A high value for thresh yields a 79 | % very sparse kernel (fast) but introduces a bigger error. 80 | % The default value is chosen so that the error due to rounding is negligible. 81 | % 'kernel' ... if the cqt kernel structure has been precomputed 82 | % (using function 'genCQTkernel'), the computation of the kernel 83 | % will be by-passed below). 84 | % 'win' ... defines which window will be used for the CQT. Valid 85 | % values are: 'blackman','hann' and 'blackmanharris'. To 86 | % use the square root of each window use the prefix 'sqrt_' 87 | % (i.e. 'sqrt_blackman'). Default: 'sqrt_blackmanharris' 88 | % 'coeffB', 89 | % 'coeffA' ... Filter coefficients for the anti-aliasing filter, where 90 | % 'coeffB' is the numerator and 'coeffA' is the 91 | % denominator (listed in descending powers of z). 92 | % 93 | %OUTPUT: 94 | % Xcqt ... struct that comprises various fields: 95 | % spCQT: CQT coefficients in the form of a sparse matrix 96 | % (rasterized, not interpolated) 97 | % fKernel: spectral Kernel 98 | % fmin: frequency of the lowest bin 99 | % fmax: frequency of the hiqhest bin 100 | % octaveNr: number of octaves processed 101 | % bins: number of bins per octave 102 | % intParams: structure containing additional parameters for the inverse transform 103 | %He Wang, 2020/12/01 hewang@mail.bnu.edu.cn 104 | %''' 105 | 106 | # input checking 107 | if (len(x.shape) > 1) and (x.shape[0] > 1): 108 | warnings.warn('qt requires one-dimensional input!', UserWarning) 109 | if (len(x.shape) > 1): 110 | x = x.reshape(-1) # column vector 111 | 112 | # input parameters 113 | q = kwargs.get('q', 1) 114 | atomHopFactor = kwargs.get('atomHopFactor', 0.25) 115 | thresh = kwargs.get('thresh', 0.0005) 116 | cqtKernel = kwargs.get('kernel') 117 | winFlag = kwargs.get('win', 'sqrt_blackmanharris') 118 | B = kwargs.get('coeffB') 119 | A = kwargs.get('coeffA') 120 | 121 | # define 122 | octaveNr = int(np.ceil(np.log2(fmax/fmin))) 123 | fmin = (fmax/2**octaveNr) * 2**(1/bins) # set fmin to actual value 124 | xlen_init = x.size 125 | 126 | 127 | # design lowpass filter 128 | if (not B) or (not A): 129 | LPorder = 6 # order of the anti-aliasing filter 130 | cutoff = 0.5 131 | B, A = butter(LPorder, cutoff, 'low') # design f_nyquist/2-lowpass filter 132 | 133 | # design kernel for one octave 134 | if not cqtKernel: 135 | cqtKernel = genCQTkernel(fmax, bins, fs, q=q, atomHopFactor=atomHopFactor, thresh=thresh, win=winFlag) 136 | 137 | # calculate CQT 138 | cellCQT = {} #np.zeros(octaveNr) 139 | maxBlock = cqtKernel['fftLEN'] * 2**(octaveNr-1) # largest FFT Block (virtual) 140 | suffixZeros = maxBlock 141 | prefixZeros = maxBlock 142 | x = np.pad(x, (suffixZeros, prefixZeros), 'constant', constant_values=(0, 0)) 143 | OVRLP = int(cqtKernel['fftLEN'] - cqtKernel['fftHOP']) 144 | K = cqtKernel['fKernel'].conj().T # %conjugate spectral kernel for cqt transformation 145 | 146 | for i in range(1, octaveNr+1): 147 | 148 | xx = buffer(x, cqtKernel['fftLEN'], OVRLP, 'nodelay') # generating FFT blocks 149 | XX = np.fft.fft(xx.T).T # applying fft to each column (each FFT frame) 150 | cellCQT[i] = np.dot(K, XX) # calculating cqt coefficients for all FFT frames for this octave 151 | 152 | if i != octaveNr: 153 | x = filtfilt(B, A, x) # anti aliasing filter 154 | x = x[::2] # drop samplerate by 2 155 | 156 | spCQT = cell2sparse(cellCQT, octaveNr, bins, cqtKernel['firstcenter'], cqtKernel['atomHOP'], cqtKernel['atomNr']) 157 | 158 | intParam = {'sufZeros':suffixZeros,'preZeros':prefixZeros,'xlen_init':xlen_init,'fftLEN':cqtKernel['fftLEN'],'fftHOP':cqtKernel['fftHOP'], 159 | 'q':q,'filtCoeffA':A,'filtCoeffB':B,'firstcenter':cqtKernel['firstcenter'],'atomHOP':cqtKernel['atomHOP'], 160 | 'atomNr':cqtKernel['atomNr'],'Nk_max':cqtKernel['Nk_max'],'Q':cqtKernel['Q'],'rast':0} 161 | 162 | Xcqt = {'spCQT':spCQT,'fKernel':cqtKernel['fKernel'],'fmax':fmax,'fmin':fmin,'octaveNr':octaveNr,'bins':cqtKernel['bins'],'intParams':intParam} 163 | 164 | return Xcqt 165 | 166 | def round_half_up(number, ndigits=0): # 精确的四舍五入 167 | ''' 168 | Ref: https://cloud.tencent.com/developer/article/1426211 169 | ''' 170 | num = Decimal(str(number)) 171 | return float(num.quantize(Decimal('0.'+'0'*ndigits), rounding=ROUND_HALF_UP)) 172 | 173 | def nextpow2(n): 174 | ''' 175 | 求最接近数据长度的2的整数次方 176 | An integer equal to 2 that is closest to the length of the data 177 | 178 | Ref: https://github.com/BIDS-Apps/rsHRF/blob/669ceac0e347224fbce2ae5f7d99adbe2725d2db/rsHRF/processing/rest_filter.py#L6 179 | 180 | Eg: 181 | nextpow2(2) = 1 182 | nextpow2(2**10+1) = 11 183 | nextpow2(2**20+1) = 21 184 | ''' 185 | return np.ceil(np.log2(np.abs(n))).astype('long') 186 | 187 | def hann(window_length, sflag='symmetric'): 188 | """ 189 | Returns a Hann window using the window sampling specified by `sflag. 190 | 191 | Args: 192 | 193 | window_length: The number of points in the returned window. 194 | sflag: Window sampling - 'symmetric' (default) | 'periodic' 195 | Window sampling, specified as one of the following: 196 | 'symmetric' — Use this option when using windows for filter design. 197 | The Hanning window is defined as 198 | .. math:: 199 | w(n) = 0.5 - 0.5\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right) 200 | \\qquad 0 \\leq n \\leq M-1 201 | 202 | 'periodic' — This option is useful for spectral analysis because it 203 | enables a windowed signal to have the perfect periodic extension 204 | implicit in the discrete Fourier transform. When 'periodic' is specified, 205 | hann computes a window of length L + 1 and returns the first L points. 206 | 207 | Calculate a "periodic" Hann window. 208 | 209 | The classic Hann window is defined as a raised cosine that starts and 210 | ends on zero, and where every value appears twice, except the middle 211 | point for an odd-length window. Matlab calls this a "symmetric" window 212 | and np.hanning() returns it. However, for Fourier analysis, this 213 | actually represents just over one cycle of a period N-1 cosine, and 214 | thus is not compactly expressed on a length-N Fourier basis. Instead, 215 | it's better to use a raised cosine that ends just before the final 216 | zero value - i.e. a complete cycle of a period-N cosine. Matlab 217 | calls this a "periodic" window. This routine calculates it. 218 | 219 | Returns: 220 | A 1D np.array containing the periodic hann window. 221 | 222 | Ref: http://ddrv.cn/a/272066 223 | He Wang, 2020/12/01 hewang@mail.bnu.edu.cn 224 | """ 225 | if sflag == 'symmetric': 226 | return np.hanning(window_length) 227 | elif sflag == 'periodic': 228 | return 0.5 - (0.5 * np.cos(2 * np.pi / window_length * 229 | np.arange(window_length))) 230 | else: 231 | raise 232 | 233 | def genCQTkernel(fmax, bins, fs, **kwargs): 234 | ''' 235 | %Calculating the CQT Kernel for one octave. All atoms are center-stacked. 236 | %Atoms are placed so that the stacks of lower octaves are centered at the 237 | %same positions in time, however, their amount is reduced by factor two for 238 | %each octave down. 239 | % 240 | %INPUT: 241 | % fmax ... highest frequency of interest 242 | % bins ... number of bins per octave 243 | % fs ... sampling frequency 244 | % 245 | %optional input parameters (parameter name/value pairs): 246 | % 247 | % 'q' ... Q scaling factor. Default: 1. 248 | % 'atomHopFactor' ... relative hop size corresponding to the shortest 249 | % temporal atom. Default: 0.25. 250 | % 'thresh' ... values smaller than 'tresh' in the spectral kernel are rounded to 251 | % zero. Default: 0.0005. 252 | % 'win' ... defines which window will be used for the CQT. Valid 253 | % values are: 'blackman','hann' and 'blackmanharris'. To 254 | % use the square root of each window use the prefix 'sqrt_' 255 | % (i.e. 'sqrt_blackman'). Default: 'sqrt_blackmanharris' 256 | % 'perfRast' ... if set to 1 the kernel is designed in order to 257 | % enable perfect rasterization using the function 258 | % cqtPerfectRast() (Default: perRast=0). See documentation of 259 | % 'cqtPerfectRast' for further information. 260 | % 261 | %OUTPUT: 262 | % cqtKernel ... Dict that contains the spectral kernel 'fKernel' 263 | % additional design parameters used in cqt(), cqtPerfectRast() and icqt(). 264 | % 265 | %He Wang, 2020/12/01 hewang@mail.bnu.edu.cn 266 | ''' 267 | # input parameters 268 | q = kwargs.get('q', 1) 269 | atomHopFactor = kwargs.get('atomHopFactor', 0.25) 270 | thresh = kwargs.get('thresh', 0.0005) 271 | winFlag = kwargs.get('win', 'sqrt_blackmanharris') 272 | perfRast = kwargs.get('perfRast', 0) 273 | 274 | # define 275 | fmin = (fmax/2)*2**(1/bins) 276 | Q = 1/(2**(1/bins)-1) 277 | Q = Q*q 278 | Nk_max = Q * fs / fmin 279 | Nk_max = round_half_up(Nk_max) # length of the largest atom [samples] 280 | 281 | # Compute FFT size, FFT hop, atom hop, ... 282 | Nk_min = round_half_up( Q * fs / (fmin*2**((bins-1)/bins)) ) # length of the shortest atom [samples] 283 | atomHOP = round_half_up(Nk_min * atomHopFactor) # atom hop size 284 | first_center = np.ceil(Nk_max/2) # first possible center position within the frame 285 | first_center = atomHOP * np.ceil(first_center/atomHOP) # lock the first center to an integer multiple of the atom hop size 286 | FFTLen = 2**nextpow2(first_center+np.ceil(Nk_max/2)) # use smallest possible FFT size (increase sparsity) 287 | 288 | if perfRast: 289 | winNr = int(np.floor((FFTLen-np.ceil(Nk_max/2)-first_center)/atomHOP)) # number of temporal atoms per FFT Frame 290 | if winNr == 0 : 291 | FFTLen = FFTLen * 2 292 | winNr = int(np.floor((FFTLen-np.ceil(Nk_max/2)-first_center)/atomHOP)) 293 | else: 294 | winNr = int(np.floor((FFTLen-np.ceil(Nk_max/2)-first_center)/atomHOP))+1 # number of temporal atoms per FFT Frame 295 | 296 | 297 | last_center = first_center + (winNr-1)*atomHOP 298 | fftHOP = (last_center + atomHOP) - first_center # hop size of FFT frames 299 | fftOLP = (FFTLen-fftHOP/FFTLen)*100 # overlap of FFT frames in percent ***AK:needed? 300 | 301 | # init variables 302 | tempKernel= np.zeros((1, FFTLen), dtype=complex) 303 | sparKernel= np.zeros((1, FFTLen), dtype=complex)#[] 304 | 305 | # Compute kernel 306 | atomInd = 0 307 | for k in range(bins): 308 | 309 | Nk = int(round_half_up( Q * fs / (fmin*2**(k/bins)) )) # N[k] = (fs/fk)*Q. Rounding will be omitted in future versions 310 | 311 | if winFlag == 'sqrt_blackmanharris': 312 | winFct = np.sqrt(blackmanharris(Nk)) 313 | elif winFlag == 'blackmanharris': 314 | winFct = blackmanharris(Nk) 315 | elif winFlag == 'sqrt_hann': 316 | winFct = np.sqrt(hann(Nk, 'periodic')) 317 | elif winFlag == 'hann': 318 | winFct = hann(Nk, 'periodic') 319 | elif winFag == 'sqrt_blackman': 320 | winFct = np.sqrt(blackman(Nk, False)) 321 | elif winFag == 'blackman': 322 | winFct = blackman(Nk, False) 323 | else: 324 | winFct = np.sqrt(blackmanharris(Nk)) 325 | if k==1: 326 | warnings.warn('QT:INPUT','Non-existing window function. Default window is used!', UserWarning) 327 | 328 | fk = fmin*2**(k/bins) 329 | tempKernelBin = (winFct/Nk) * np.exp(2*np.pi*1j*fk*np.arange(Nk)/fs) 330 | atomOffset = first_center - np.ceil(Nk/2) 331 | 332 | for i in range(winNr): 333 | shift = int(atomOffset + (i * atomHOP)) 334 | 335 | tempKernel[:, shift: Nk+shift] = tempKernelBin 336 | 337 | atomInd += 1 338 | specKernel= np.fft.fft(tempKernel) 339 | specKernel[abs(specKernel)<=thresh] = 0 340 | sparKernel = np.append(sparKernel, specKernel, axis=0) 341 | tempKernel = np.zeros((1, FFTLen), dtype=complex) # reset window 342 | 343 | 344 | sparKernel = (sparKernel.T/FFTLen)[:,1:] 345 | 346 | # Normalize the magnitudes of the atoms 347 | wx1=np.argmax(np.abs(sparKernel)[:,0]) 348 | wx2=np.argmax(np.abs(sparKernel)[:,-1]) 349 | wK=sparKernel[wx1: wx2+1,:] 350 | 351 | wK = np.diag(np.dot(wK, wK.conj().T)) 352 | wK = wK[int(round_half_up(1/q)): -int(round_half_up(1/q))-2] 353 | weight = 1./np.mean(np.abs(wK)) 354 | weight = weight * (fftHOP/FFTLen) 355 | weight = np.sqrt(weight) # sqrt because the same weight is applied in icqt again 356 | sparKernel = weight*sparKernel 357 | 358 | return {'fKernel': sparKernel, 'fftLEN':FFTLen,'fftHOP':fftHOP,'fftOverlap':fftOLP,'perfRast':perfRast, 359 | 'bins':bins,'firstcenter':first_center,'atomHOP':atomHOP,'atomNr':winNr,'Nk_max':Nk_max,'Q':Q,'fmin':fmin } 360 | 361 | def cell2sparse(Xcq, octaves, bins, firstcenter, atomHOP, atomNr): 362 | ''' 363 | %Generates a sparse matrix containing the CQT coefficients (rasterized). 364 | % 365 | %The sparse matrix representation of the CQT coefficients contains all 366 | %computed coefficients at the corresponding time-frequency location 367 | %(similar to a spectrogram). For lower frequencies this means, that 368 | %each coefficient is followed by zeros stemming from the fact, that the time 369 | %resolution for lower frequencies decreases as the frequency resolution 370 | %increases. Due to the design of the CQT kernel, however, the coefficients 371 | %of different octaves are synchronised, meaning that for the second highest 372 | %octave each coefficient is followed by one zero, for the next octave down 373 | %two zeros are inserted, for the next octave four zeros are inserted and so 374 | %on. 375 | % 376 | %INPUT: 377 | % Xcq ... Dict array consisting of all coefficients for all octaves 378 | % octaves ... Number of octaves processed 379 | % bins ... Number of bins per octave 380 | % firstcenter ... Location of the leftmost atom-stack in the temporal 381 | % kernel 382 | % atomHOP ... Spacing of two consecutive atom stacks 383 | % atomNr ... Number of atoms per bin within the kernel 384 | % 385 | %%He Wang, 2020/12/01 hewang@mail.bnu.edu.cn 386 | ''' 387 | 388 | 389 | 390 | # this version uses less memory but is noticable slower 391 | emptyHops = firstcenter/atomHOP 392 | drops = emptyHops*np.power(2, octaves - np.arange(1, octaves + 1)) - emptyHops 393 | Len = int(np.max((np.asarray([atomNr*c.shape[1] for _,c in Xcq.items()]) - drops) * np.power(2, np.arange(octaves)))) # number of columns of output matrix 394 | spCQT = np.empty((0,Len)).astype(np.complex) 395 | 396 | for i in range(1, octaves+1)[::-1]: 397 | drop = int(emptyHops*2**(octaves-i)-emptyHops) # first coefficients of all octaves have to be in synchrony 398 | X = Xcq[i] 399 | 400 | if atomNr > 1: # more than one atom per bin --> reshape 401 | Xoct = np.zeros((bins, atomNr*X.shape[1] - drop)).astype(np.complex) 402 | for u in range(bins): # reshape to continous windows for each bin (for the case of several wins per frame) 403 | octX_bin = X[u*atomNr:(u+1)*atomNr,:] 404 | Xcont = octX_bin.T.reshape(-1) 405 | Xoct[u,:] = Xcont[drop:] 406 | X = Xoct 407 | 408 | else: 409 | X = X[:,drop:] 410 | 411 | X = np.pad(upfirdn([1], X.T, 2**(i-1), axis=0), [[0,2**(i-1)-1],[0,0]], mode='constant').T # upfirdn: upsampling with zeros insertion 412 | X = np.append(X, np.zeros((bins, Len-X.shape[1])), axis=1) 413 | 414 | spCQT = np.append(spCQT, X, axis=0) 415 | 416 | return spCQT 417 | 418 | def getCQT(Xcqt, fSlice, tSlice, iFlag): 419 | ''' 420 | %outCQ = getCQT(Xcqt,fSlice,tSlice,iFlag) computes a rasterized representation of 421 | %the amplitudes of the calculated CQT coefficients for the frequency bins definded in vector fSlice and the 422 | %points in time (time frames) defined in vector tSlice using the interpolation method defined in iFlag. 423 | %Valid values for iFlag are: 424 | % 425 | %'linear' ... linear interpolation (default) 426 | %'spline' ... spline interpolation 427 | %'nearest' ... nearest neighbor interpolation 428 | %'cubic' ... piecewise cubic interpolation 429 | % 430 | %If the entire CQT representation should be rasterized, set fSlice and 431 | %tSlice to 'all'. 432 | %The input parameter Xcqt is the structure gained using cqt(...). 433 | %The output parameter 'intCQT' is the same size as Xcqt.spCQT but is no 434 | %longer sparse since the zeros between two coefficients are replaced by 435 | %the interpolated values. The coefficients stored in 'intCQT' are now 436 | %real-valued since only the absolute values of the coefficients are 437 | %interpolated. If a spectrogram-like (rasterized) version of the CQT 438 | %coefficients including phase information is required, use the function 439 | %cqtPerfectRast() (see documentation for further information) 440 | % 441 | %%He Wang, 2020/12/01 hewang@mail.bnu.edu.cn 442 | ''' 443 | if type(fSlice) == type(''): 444 | fSlice = np.arange(Xcqt['bins'] * Xcqt['octaveNr']) 445 | if type(tSlice) == type(''): 446 | lastEnt = Xcqt['spCQT'][0,:].nonzero()[0][-1] 447 | tSlice = range(lastEnt) 448 | 449 | 450 | intCQT = np.zeros((len(fSlice),len(tSlice))) 451 | bins = Xcqt['bins'] 452 | spCQT = Xcqt['spCQT'] 453 | octaveNr = Xcqt['octaveNr'] 454 | spCQT = spCQT.T 455 | 456 | for k in range(len(fSlice)): 457 | Oct = octaveNr-np.floor((fSlice[k]-0.1)/bins) 458 | stepVec = range(0, spCQT.shape[0], int(2**(Oct-1))) 459 | Xbin = spCQT[stepVec, fSlice[k]] 460 | intCQT[k,:] = np.interp(tSlice, stepVec, abs(Xbin)) 461 | return intCQT 462 | 463 | def plotCQT(Xcqt, fs, fcomp): 464 | ''' 465 | %plotCQT(Xcqt,fs,fcomp,method) plots the magnitudes of the CQT 466 | %coefficients similar to a spectrogram using linear interpolation 467 | %between the calculated coefficients. For better illustration, the 468 | %magnitude values can be compressed using fcomp < 1 (Xmag^fcomp). 469 | % 470 | %%He Wang, 2020/12/13 hewang@mail.bnu.edu.cn 471 | ''' 472 | if Xcqt['intParams']['rast']: 473 | absCQT = np.abs(Xcqt['spCQT']) 474 | else: 475 | absCQT = getCQT(Xcqt, 'all', 'all', 'linear') 476 | 477 | 478 | emptyHops = Xcqt['intParams']['firstcenter'] / Xcqt['intParams']['atomHOP'] 479 | maxDrop = emptyHops * 2**(Xcqt['octaveNr']-1)-emptyHops 480 | droppedSamples = (maxDrop-1) * Xcqt['intParams']['atomHOP'] + Xcqt['intParams']['firstcenter'] 481 | outputTimeVec = np.arange(1, absCQT.shape[1]+1) * Xcqt['intParams']['atomHOP']-Xcqt['intParams']['preZeros']+droppedSamples 482 | 483 | xout = outputTimeVec / fs 484 | ytickarray = np.arange(1, Xcqt['octaveNr']*Xcqt['bins'], Xcqt['bins']/2) 485 | yout = Xcqt['fmin'] * 2**((ytickarray-1)/Xcqt['bins']) 486 | yTickLabel = Xcqt['fmin']*2**((ytickarray-1)/Xcqt['bins']) 487 | 488 | X_cq_rast = absCQT**fcomp # compress magnitudes 489 | fig, ax = plt.subplots(1, 1, sharex=True) 490 | ax.imshow(abs(X_cq_rast), origin='lower', vmin=np.min(X_cq_rast), vmax=np.max(X_cq_rast),) 491 | ax.axis('tight') 492 | ax.set_xlabel('time [sec]') 493 | ax.set_ylabel('frequency [Hz]') 494 | ax.set_title('Constant Q transform', fontdict={'fontsize':12}) 495 | plt.yticks(ytickarray, [int(round_half_up(i)) for i in yTickLabel]) 496 | fsp = int(1/(xout[1] - xout[0])) 497 | plt.xticks(np.arange(xout.size)[fsp//2::fsp], np.round(xout[fsp//2::fsp],1)) 498 | return (ytickarray, yout), xout 499 | 500 | def sparse2cell(spCQT,bins,octaveNr,atomNr,firstcenter,atomHOP): 501 | ''' 502 | % Maps the sparse matrix respresentation of the CQT coefficients back to 503 | % the cell representation for inverse transform 504 | % 505 | %%He Wang, 2020/12/13 hewang@mail.bnu.edu.cn 506 | ''' 507 | emptyHops = firstcenter/atomHOP # void atom hopsizes in the beginning of the temporal kernel 508 | cellCQT = {} 509 | 510 | for i in range(1, octaveNr+1): 511 | dropped = int(emptyHops*2**(octaveNr-i)-emptyHops) 512 | X = spCQT[bins*octaveNr-i*bins:bins*octaveNr-(i-1)*bins,::2**(i-1)] 513 | X = np.concatenate([np.zeros((bins,dropped)), X], axis=-1) 514 | X = np.concatenate([X, np.zeros((bins,int(np.ceil(X.shape[1]/atomNr))*atomNr-X.shape[1]))], axis=-1) 515 | if atomNr > 1: # reshape 516 | Xcell = np.zeros((bins*atomNr,int(np.ceil(X.shape[1]/atomNr)))).astype(np.complex) 517 | for u in range(1,bins+1): 518 | Xbin = np.reshape(X[u-1,:], (atomNr,int(len(X[u-1,:])/atomNr)), order='F') 519 | Xcell[(u-1)*atomNr:u*atomNr, :] = Xbin 520 | cellCQT[i] = Xcell 521 | else: 522 | cellCQT[i] = X 523 | 524 | return cellCQT 525 | 526 | 527 | 528 | def icqt(Xcqt): 529 | ''' 530 | %y = icqt(Xcqt) computes the inverse CQT of the CQT coefficients in Xcqt.spCQT 531 | % 532 | %The input structue Xcqt is the structure gained by cqt() and cqtPerfectRast(), respectively. 533 | %If the CQT coefficients in Xcqt.spCQT are not changed, the output y is the 534 | %reconstructed (near-perfect) time-domain signal of the input signal x 535 | %(cqt(x,...)) withing the frequency range [fmin fmax]. 536 | % 537 | %%He Wang, 2020/12/13 hewang@mail.bnu.edu.cn 538 | ''' 539 | cellCQT = sparse2cell(Xcqt['spCQT'],Xcqt['bins'],Xcqt['octaveNr'],Xcqt['intParams']['atomNr'], 540 | Xcqt['intParams']['firstcenter'],Xcqt['intParams']['atomHOP']) 541 | 542 | FFTLen = Xcqt['intParams']['fftLEN'] 543 | octaveNr = Xcqt['octaveNr'] 544 | HOPSZ = int(Xcqt['intParams']['fftHOP']) 545 | 546 | # Kernel for inverse transform 547 | Kinv = Xcqt['fKernel'] 548 | 549 | # inverse transform 550 | y = np.array([]) 551 | 552 | for i in np.arange(1,octaveNr+1,1)[::-1]: 553 | cellCQT_oct = cellCQT[i] 554 | Y = np.dot(Kinv, cellCQT_oct) # compute spectrum of reconstructed signal for all coefficients in this octave 555 | y_oct_temp = np.fft.ifft(Y.T).T 556 | y_oct = 2*np.real(y_oct_temp) # Y contains no negative frequencies -> keep only real part*2 to 557 | # reconstruct real valued time signal 558 | NBLOCKS = Y.shape[1] 559 | siglen = int(FFTLen + (NBLOCKS-1)*HOPSZ) 560 | y = np.append(y, np.zeros((siglen-len(y),))) if siglen-len(y)>0 else y 561 | 562 | for n in range(NBLOCKS): 563 | y[n*HOPSZ:(n*HOPSZ)+FFTLen] = y_oct[:,n] + y[n*HOPSZ:(n*HOPSZ)+FFTLen] # overlap-add 564 | 565 | if i != 1: # upsampling by factor two 566 | #y = sum(map(lambda x: [x, 0], y), []) # insert one zero between each sample 567 | y = upsample(y, 2) # insert one zero between each sample 568 | y = filtfilt(Xcqt['intParams']['filtCoeffB'], Xcqt['intParams']['filtCoeffA'],y) 569 | y *= 2 570 | return y 571 | -------------------------------------------------------------------------------- /Constant-Q_transform_toolbox_for_music_processing.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphysresearch/CQT_toolbox_python/950a923dfa7640eb67bbe044e7189cc34e3afdd9/Constant-Q_transform_toolbox_for_music_processing.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 He Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MATLAB/DEMO.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /DEMO.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / DEMO.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (1.898 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 | 543 | 547 | 548 | 549 | 552 | 556 | 557 | 558 | 561 | 565 | 566 | 567 | 570 | 574 | 575 | 576 | 579 | 583 | 584 | 585 |
145 | 1 146 | 148 |
%% Demonstration
149 | 
150 |
154 | 2 155 | 157 |
%Illustration of the use of programs to compute the
158 | 
159 |
163 | 3 164 | 166 |
%forward and inverse constant-Q transform
167 | 
168 |
172 | 4 173 | 175 |
%
176 | 
177 |
181 | 5 182 | 184 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
185 | 
186 |
190 | 6 191 | 193 |
194 | 
195 |
199 | 7 200 | 202 |
%% init values for CQT
203 | 
204 |
208 | 8 209 | 211 |
fs = 44100;
212 | 
213 |
217 | 9 218 | 220 |
bins_per_octave = 24;
221 | 
222 |
226 | 10 227 | 229 |
fmax = fs/3;     %center frequency of the highest frequency bin 
230 | 
231 |
235 | 11 236 | 238 |
fmin = fmax/512; %lower boundary for CQT (lowest frequency bin will be immediately above this): fmax/<power of two> 
239 | 
240 |
244 | 12 245 | 247 |
248 | 
249 |
253 | 13 254 | 256 |
%% generate/read input signal%
257 | 
258 |
262 | 14 263 | 265 |
x = randn(30*fs,1);
266 | 
267 |
271 | 15 272 | 274 |
% Drop frequencies outside [fmin fmax] to allow calculating 
275 | 
276 |
280 | 16 281 | 283 |
% the SNR after inverse transform
284 | 
285 |
289 | 17 290 | 292 |
x = [zeros(500,1); x; zeros(500,1)];
293 | 
294 |
298 | 18 299 | 301 |
w1 = 2*(fmin/(fs/2)); w2 = 0.8*(fmax/(fs/2));
302 | 
303 |
307 | 19 308 | 310 |
[B,A] = butter(6,[w1 w2]); x = filtfilt(B,A,x); 
311 | 
312 |
316 | 20 317 | 319 |
320 | 
321 |
325 | 21 326 | 328 |
%% CQT
329 | 
330 |
334 | 22 335 | 337 |
Xcqt = cqt(x,fmin,fmax,bins_per_octave,fs);
338 | 
339 |
343 | 23 344 | 346 |
347 | 
348 |
352 | 24 353 | 355 |
%***computing cqt with optional input parameters***********
356 | 
357 |
361 | 25 362 | 364 |
% Xcqt = cqt(x,fmin,fmax,bins_per_octave,fs,'q',1,'atomHopFactor',0.25,'thresh',0.0005,'win','sqrt_blackmanharris');
365 | 
366 |
370 | 26 371 | 373 |
374 | 
375 |
379 | 27 380 | 382 |
%***computing rasterized complex coefficients***************
383 | 
384 |
388 | 28 389 | 391 |
% Xcqt = cqtPerfectRast(x,fmin,fmax,bins_per_octave,fs,'q',1,'atomHopFactor',0.25,'thresh',0.0005,'win','sqrt_blackmanharris');
392 | 
393 |
397 | 29 398 | 400 |
401 | 
402 |
406 | 30 407 | 409 |
%***precomputing filter and kernel**************************
410 | 
411 |
415 | 31 416 | 418 |
% [B A] = butter(6,0.5,'low'); %design f_nyquist/2-lowpass filter
419 | 
420 |
424 | 32 425 | 427 |
% K = genCQTkernel(fmax,bins_per_octave,fs,'atomHopFactor',atomHopFactor);
428 | 
429 |
433 | 33 434 | 436 |
% Xcqt = cqt(x,fmin,fmax,bins_per_octave,fs,'kernel',K,'coeffB',B,'coeffA',A);
437 | 
438 |
442 | 34 443 | 445 |
446 | 
447 |
451 | 35 452 | 454 |
%***precomputing filter and kernel using cqtPerfectRast*****
455 | 
456 |
460 | 36 461 | 463 |
% [B A] = butter(6,0.5,'low'); %design f_nyquist/2-lowpass filter
464 | 
465 |
469 | 37 470 | 472 |
% K = genCQTkernel(fmax,bins_per_octave,fs,'atomHopFactor',atomHopFactor,'perfRast',1);
473 | 
474 |
478 | 38 479 | 481 |
% Xcqt = cqtPerfectRast(x,fmin,fmax,bins_per_octave,fs,'kernel',K,'coeffB',B,'coeffA',A);
482 | 
483 |
487 | 39 488 | 490 |
491 | 
492 |
496 | 40 497 | 499 |
%% inverse CQT
500 | 
501 |
505 | 41 506 | 508 |
y = icqt(Xcqt);
509 | 
510 |
514 | 42 515 | 517 |
SNR = 10*log10(sum(abs(x).^2)/sum(abs(x-y).^2)); %calculate the SNR
518 | 
519 |
523 | 43 524 | 526 |
527 | 
528 |
532 | 44 533 | 535 |
%% plot CQT
536 | 
537 |
541 | 45 542 | 544 |
% plotCQT(Xcqt,fs,0.6,'surf');
545 | 
546 |
550 | 46 551 | 553 |
554 | 
555 |
559 | 47 560 | 562 |
%% get CQT (interpolated)
563 | 
564 |
568 | 48 569 | 571 |
% intCQT = getCQT(Xcqt,'all','all');
572 | 
573 |
577 | 49 578 | 580 |
581 | 
582 |
586 |
587 | 588 | 589 | 590 | 591 |
592 |
593 |
594 |
595 | 596 | 597 | 598 | 599 | 604 |
605 |
606 | 607 | 608 | 609 | -------------------------------------------------------------------------------- /MATLAB/cell2sparse.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /cell2sparse.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / cell2sparse.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (3.512 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 | 543 | 547 | 548 | 549 | 552 | 556 | 557 | 558 | 561 | 565 | 566 | 567 | 570 | 574 | 575 | 576 | 579 | 583 | 584 | 585 | 588 | 592 | 593 | 594 | 597 | 601 | 602 | 603 | 606 | 610 | 611 | 612 | 615 | 619 | 620 | 621 | 624 | 628 | 629 | 630 | 633 | 637 | 638 | 639 | 642 | 646 | 647 | 648 | 651 | 655 | 656 | 657 | 660 | 664 | 665 | 666 | 669 | 673 | 674 | 675 | 678 | 682 | 683 | 684 | 687 | 691 | 692 | 693 | 696 | 700 | 701 | 702 | 705 | 709 | 710 | 711 | 714 | 718 | 719 | 720 | 723 | 727 | 728 | 729 | 732 | 736 | 737 | 738 | 741 | 745 | 746 | 747 | 750 | 754 | 755 | 756 | 759 | 763 | 764 | 765 | 768 | 772 | 773 | 774 | 777 | 781 | 782 | 783 | 786 | 790 | 791 | 792 | 795 | 799 | 800 | 801 | 804 | 808 | 809 | 810 | 813 | 817 | 818 | 819 | 822 | 826 | 827 | 828 | 831 | 835 | 836 | 837 | 840 | 844 | 845 | 846 |
145 | 1 146 | 148 |
function spCQT = cell2sparse(Xcq,octaves,bins,firstcenter,atomHOP,atomNr)
149 | 
150 |
154 | 2 155 | 157 |
%Generates a sparse matrix containing the CQT coefficients (rasterized).
158 | 
159 |
163 | 3 164 | 166 |
%
167 | 
168 |
172 | 4 173 | 175 |
%The sparse matrix representation of the CQT coefficients contains all
176 | 
177 |
181 | 5 182 | 184 |
%computed coefficients at the corresponding time-frequency location
185 | 
186 |
190 | 6 191 | 193 |
%(similar to a spectrogram). For lower frequencies this means, that
194 | 
195 |
199 | 7 200 | 202 |
%each coefficient is followed by zeros stemming from the fact, that the time
203 | 
204 |
208 | 8 209 | 211 |
%resolution for lower frequencies decreases as the frequency resolution
212 | 
213 |
217 | 9 218 | 220 |
%increases. Due to the design of the CQT kernel, however, the coefficients
221 | 
222 |
226 | 10 227 | 229 |
%of different octaves are synchronised, meaning that for the second highest
230 | 
231 |
235 | 11 236 | 238 |
%octave each coefficient is followed by one zero, for the next octave down
239 | 
240 |
244 | 12 245 | 247 |
%two zeros are inserted, for the next octave four zeros are inserted and so
248 | 
249 |
253 | 13 254 | 256 |
%on.
257 | 
258 |
262 | 14 263 | 265 |
%
266 | 
267 |
271 | 15 272 | 274 |
%INPUT:
275 | 
276 |
280 | 16 281 | 283 |
%   Xcq         ... Cell array consisting of all coefficients for all octaves
284 | 
285 |
289 | 17 290 | 292 |
%   octaves     ... Number of octaves processed
293 | 
294 |
298 | 18 299 | 301 |
%   bins        ... Number of bins per octave
302 | 
303 |
307 | 19 308 | 310 |
%   firstcenter ... Location of the leftmost atom-stack in the temporal
311 | 
312 |
316 | 20 317 | 319 |
%                   kernel
320 | 
321 |
325 | 21 326 | 328 |
%   atomHOP     ... Spacing of two consecutive atom stacks
329 | 
330 |
334 | 22 335 | 337 |
%   atomNr      ... Number of atoms per bin within the kernel
338 | 
339 |
343 | 23 344 | 346 |
%
347 | 
348 |
352 | 24 353 | 355 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
356 | 
357 |
361 | 25 362 | 364 |
365 | 
366 |
370 | 26 371 | 373 |
if 0
374 | 
375 |
379 | 27 380 | 382 |
%% this version has big memory consumption but is very fast
383 | 
384 |
388 | 28 389 | 391 |
    emptyHops = firstcenter/atomHOP;
392 | 
393 |
397 | 29 398 | 400 |
    drop = emptyHops*2^(octaves-1)-emptyHops; %distance between first value in highest octave and first value in lowest octave
401 | 
402 |
406 | 30 407 | 409 |
    spCQT = zeros(bins*octaves,size(Xcq{1},2)*atomNr-drop);
410 | 
411 |
415 | 31 416 | 418 |
419 | 
420 |
424 | 32 425 | 427 |
    for i=1:octaves
428 | 
429 |
433 | 33 434 | 436 |
        drop = emptyHops*2^(octaves-i)-emptyHops; %first coefficients of all octaves have to be in synchrony
437 | 
438 |
442 | 34 443 | 445 |
        X = Xcq{i}; 
446 | 
447 |
451 | 35 452 | 454 |
        if  atomNr > 1 %more than one atom per bin --> reshape
455 | 
456 |
460 | 36 461 | 463 |
            Xoct = zeros(bins,atomNr*size(X,2)-drop);
464 | 
465 |
469 | 37 470 | 472 |
            for u=1:bins %reshape to continous windows for each bin (for the case of several wins per frame)
473 | 
474 |
478 | 38 479 | 481 |
               octX_bin = X((u-1)*atomNr+1:u*atomNr,:);
482 | 
483 |
487 | 39 488 | 490 |
               Xcont = reshape(octX_bin,1,size(octX_bin,1)*size(octX_bin,2));
491 | 
492 |
496 | 40 497 | 499 |
               Xoct(u,:) = Xcont(1+drop:end);
500 | 
501 |
505 | 41 506 | 508 |
            end
509 | 
510 |
514 | 42 515 | 517 |
            X = Xoct;
518 | 
519 |
523 | 43 524 | 526 |
        else
527 | 
528 |
532 | 44 533 | 535 |
            X = X(:,1+drop:end);
536 | 
537 |
541 | 45 542 | 544 |
        end
545 | 
546 |
550 | 46 551 | 553 |
        binVec = bins*octaves-bins*i+1:bins*octaves-bins*(i-1);
554 | 
555 |
559 | 47 560 | 562 |
        spCQT(binVec,1:2^(i-1):size(X,2)*2^(i-1)) = X;
563 | 
564 |
568 | 48 569 | 571 |
572 | 
573 |
577 | 49 578 | 580 |
    end
581 | 
582 |
586 | 50 587 | 589 |
    spCQT = sparse(spCQT); %storing as sparse matrix at the end is the fastest way. Big memory consumption though!
590 | 
591 |
595 | 51 596 | 598 |
599 | 
600 |
604 | 52 605 | 607 |
else
608 | 
609 |
613 | 53 614 | 616 |
%% this version uses less memory but is noticable slower
617 | 
618 |
622 | 54 623 | 625 |
    emptyHops = firstcenter/atomHOP;
626 | 
627 |
631 | 55 632 | 634 |
    drops = emptyHops*2.^(octaves-(1:octaves))-emptyHops;
635 | 
636 |
640 | 56 641 | 643 |
    len = max(((atomNr*cellfun('size',Xcq,2)-drops).*2.^(0:octaves-1))); %number of columns of output matrix
644 | 
645 |
649 | 57 650 | 652 |
    spCQT = [];
653 | 
654 |
658 | 58 659 | 661 |
662 | 
663 |
667 | 59 668 | 670 |
    for i=octaves:-1:1
671 | 
672 |
676 | 60 677 | 679 |
        drop = emptyHops*2^(octaves-i)-emptyHops; %first coefficients of all octaves have to be in synchrony
680 | 
681 |
685 | 61 686 | 688 |
        X = Xcq{i}; 
689 | 
690 |
694 | 62 695 | 697 |
        if  atomNr > 1 %more than one atom per bin --> reshape
698 | 
699 |
703 | 63 704 | 706 |
            Xoct = zeros(bins,atomNr*size(X,2)-drop);
707 | 
708 |
712 | 64 713 | 715 |
            for u=1:bins %reshape to continous windows for each bin (for the case of several wins per frame)
716 | 
717 |
721 | 65 722 | 724 |
               octX_bin = X((u-1)*atomNr+1:u*atomNr,:);
725 | 
726 |
730 | 66 731 | 733 |
               Xcont = reshape(octX_bin,1,size(octX_bin,1)*size(octX_bin,2));
734 | 
735 |
739 | 67 740 | 742 |
               Xoct(u,:) = Xcont(1+drop:end);
743 | 
744 |
748 | 68 749 | 751 |
            end
752 | 
753 |
757 | 69 758 | 760 |
            X = Xoct;
761 | 
762 |
766 | 70 767 | 769 |
        else
770 | 
771 |
775 | 71 776 | 778 |
            X = X(:,1+drop:end);
779 | 
780 |
784 | 72 785 | 787 |
        end
788 | 
789 |
793 | 73 794 | 796 |
        X = upsample(X.',2^(i-1)).';
797 | 
798 |
802 | 74 803 | 805 |
        X = [X zeros(bins,len-size(X,2))];
806 | 
807 |
811 | 75 812 | 814 |
        spCQT = sparse([spCQT; X]);  
815 | 
816 |
820 | 76 821 | 823 |
    end
824 | 
825 |
829 | 77 830 | 832 |
833 | 
834 |
838 | 78 839 | 841 |
end
842 | 
843 |
847 |
848 | 849 | 850 | 851 | 852 |
853 |
854 |
855 |
856 | 857 | 858 | 859 | 860 | 865 |
866 |
867 | 868 | 869 | 870 | -------------------------------------------------------------------------------- /MATLAB/cqt.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /cqt.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / cqt.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (5.275 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 | 543 | 547 | 548 | 549 | 552 | 556 | 557 | 558 | 561 | 565 | 566 | 567 | 570 | 574 | 575 | 576 | 579 | 583 | 584 | 585 | 588 | 592 | 593 | 594 | 597 | 601 | 602 | 603 | 606 | 610 | 611 | 612 | 615 | 619 | 620 | 621 | 624 | 628 | 629 | 630 | 633 | 637 | 638 | 639 | 642 | 646 | 647 | 648 | 651 | 655 | 656 | 657 | 660 | 664 | 665 | 666 | 669 | 673 | 674 | 675 | 678 | 682 | 683 | 684 | 687 | 691 | 692 | 693 | 696 | 700 | 701 | 702 | 705 | 709 | 710 | 711 | 714 | 718 | 719 | 720 | 723 | 727 | 728 | 729 | 732 | 736 | 737 | 738 | 741 | 745 | 746 | 747 | 750 | 754 | 755 | 756 | 759 | 763 | 764 | 765 | 768 | 772 | 773 | 774 | 777 | 781 | 782 | 783 | 786 | 790 | 791 | 792 | 795 | 799 | 800 | 801 | 804 | 808 | 809 | 810 | 813 | 817 | 818 | 819 | 822 | 826 | 827 | 828 | 831 | 835 | 836 | 837 | 840 | 844 | 845 | 846 | 849 | 853 | 854 | 855 | 858 | 862 | 863 | 864 | 867 | 871 | 872 | 873 | 876 | 880 | 881 | 882 | 885 | 889 | 890 | 891 | 894 | 898 | 899 | 900 | 903 | 907 | 908 | 909 | 912 | 916 | 917 | 918 | 921 | 925 | 926 | 927 | 930 | 934 | 935 | 936 | 939 | 943 | 944 | 945 | 948 | 952 | 953 | 954 | 957 | 961 | 962 | 963 | 966 | 970 | 971 | 972 | 975 | 979 | 980 | 981 | 984 | 988 | 989 | 990 | 993 | 997 | 998 | 999 | 1002 | 1006 | 1007 | 1008 | 1011 | 1015 | 1016 | 1017 | 1020 | 1024 | 1025 | 1026 | 1029 | 1033 | 1034 | 1035 | 1038 | 1042 | 1043 | 1044 | 1047 | 1051 | 1052 | 1053 | 1056 | 1060 | 1061 | 1062 | 1065 | 1069 | 1070 | 1071 | 1074 | 1078 | 1079 | 1080 | 1083 | 1087 | 1088 | 1089 | 1092 | 1096 | 1097 | 1098 | 1101 | 1105 | 1106 | 1107 | 1110 | 1114 | 1115 | 1116 | 1119 | 1123 | 1124 | 1125 | 1128 | 1132 | 1133 | 1134 | 1137 | 1141 | 1142 | 1143 | 1146 | 1150 | 1151 | 1152 | 1155 | 1159 | 1160 | 1161 | 1164 | 1168 | 1169 | 1170 | 1173 | 1177 | 1178 | 1179 | 1182 | 1186 | 1187 | 1188 |
145 | 1 146 | 148 |
function Xcqt = cqt(x,fmin,fmax,bins,fs,varargin) 
 149 | 
150 |
154 | 2 155 | 157 |
%Xcqt = cqt(x,fmin,fmax,bins,fs,varargin) calculates the constant-Q transform of the input signal x.
 158 | 
159 |
163 | 3 164 | 166 |
%
 167 | 
168 |
172 | 4 173 | 175 |
%INPUT:
 176 | 
177 |
181 | 5 182 | 184 |
%   fmin      ... lowest frequency of interest
 185 | 
186 |
190 | 6 191 | 193 |
%   fmax      ... highest frequency of interest
 194 | 
195 |
199 | 7 200 | 202 |
%   bins      ... frequency bins per octave
 203 | 
204 |
208 | 8 209 | 211 |
%   fs        ... sampling rate
 212 | 
213 |
217 | 9 218 | 220 |
%
 221 | 
222 |
226 | 10 227 | 229 |
%   optional input parameters (parameter name/value pairs):
 230 | 
231 |
235 | 11 236 | 238 |
%
 239 | 
240 |
244 | 12 245 | 247 |
%   'atomHopFactor'   ... overlap of temporal atoms in percent. Default: 0.25.
 248 | 
249 |
253 | 13 254 | 256 |
%    
 257 | 
258 |
262 | 14 263 | 265 |
%   'q'       ... the maximum value for optimal reconstruction is q=1.
 266 | 
267 |
271 | 15 272 | 274 |
%                 For values smaller than 1 the bandwidths of the spectral
 275 | 
276 |
280 | 16 281 | 283 |
%                 atoms (filter) are increased retaining their center
 284 | 
285 |
289 | 17 290 | 292 |
%                 frequencies (frequency 'smearing', frequency domain redundancy 
 293 | 
294 |
298 | 18 299 | 301 |
%                 increases, time resolutin improves). Default: 1.
 302 | 
303 |
307 | 19 308 | 310 |
%   'thresh'  ... all values in the cqt kernel smaller than tresh are
 311 | 
312 |
316 | 20 317 | 319 |
%                 rounded to zero. A high value for thresh yields a
 320 | 
321 |
325 | 21 326 | 328 |
%                 very sparse kernel (fast) but introduces a bigger error. 
 329 | 
330 |
334 | 22 335 | 337 |
%                 The default value is chosen so that the error due to rounding is negligible.
 338 | 
339 |
343 | 23 344 | 346 |
%   'kernel'  ... if the cqt kernel structure has been precomputed
 347 | 
348 |
352 | 24 353 | 355 |
%                 (using function 'genCQTkernel'), the computation of the kernel
 356 | 
357 |
361 | 25 362 | 364 |
%                 will be by-passed below).
 365 | 
366 |
370 | 26 371 | 373 |
%   'win'     ... defines which window will be used for the CQT. Valid
 374 | 
375 |
379 | 27 380 | 382 |
%                 values are: 'blackman','hann' and 'blackmanharris'. To
 383 | 
384 |
388 | 28 389 | 391 |
%                 use the square root of each window use the prefix 'sqrt_'
 392 | 
393 |
397 | 29 398 | 400 |
%                 (i.e. 'sqrt_blackman'). Default: 'sqrt_blackmanharris'
 401 | 
402 |
406 | 30 407 | 409 |
%   'coeffB',
 410 | 
411 |
415 | 31 416 | 418 |
%   'coeffA'  ... Filter coefficients for the anti-aliasing filter, where
 419 | 
420 |
424 | 32 425 | 427 |
%                 'coeffB' is the numerator and 'coeffA' is the
 428 | 
429 |
433 | 33 434 | 436 |
%                 denominator (listed in descending powers of z). 
 437 | 
438 |
442 | 34 443 | 445 |
%                                                  
 446 | 
447 |
451 | 35 452 | 454 |
%OUTPUT:
 455 | 
456 |
460 | 36 461 | 463 |
%   Xcqt      ... struct that comprises various fields: 
 464 | 
465 |
469 | 37 470 | 472 |
%              spCQT: CQT coefficients in the form of a sparse matrix 
 473 | 
474 |
478 | 38 479 | 481 |
%                    (rasterized, not interpolated)
 482 | 
483 |
487 | 39 488 | 490 |
%              fKernel: spectral Kernel 
 491 | 
492 |
496 | 40 497 | 499 |
%              fmin: frequency of the lowest bin
 500 | 
501 |
505 | 41 506 | 508 |
%              fmax: frequency of the hiqhest bin
 509 | 
510 |
514 | 42 515 | 517 |
%              octaveNr: number of octaves processed
 518 | 
519 |
523 | 43 524 | 526 |
%              bins: number of bins per octave
 527 | 
528 |
532 | 44 533 | 535 |
%              intParams: structure containing additional parameters for the inverse transform   
 536 | 
537 |
541 | 45 542 | 544 |
%
 545 | 
546 |
550 | 46 551 | 553 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
 554 | 
555 |
559 | 47 560 | 562 |
%2011-03: error removed in the calculation of fmin for output in Xcqt structure
 563 | 
564 |
568 | 48 569 | 571 |
 572 | 
573 |
577 | 49 578 | 580 |
%% input checking
 581 | 
582 |
586 | 50 587 | 589 |
if size(x,2) > 1 && size(x,1) > 1, error('cqt requires one-dimensional input!'); end;
 590 | 
591 |
595 | 51 596 | 598 |
if size(x,2) > 1, x = x(:); end; %column vector
 599 | 
600 |
604 | 52 605 | 607 |
 608 | 
609 |
613 | 53 614 | 616 |
%% input parameters
 617 | 
618 |
622 | 54 623 | 625 |
q = 1; %default value
 626 | 
627 |
631 | 55 632 | 634 |
atomHopFactor = 0.25; %default value
 635 | 
636 |
640 | 56 641 | 643 |
thresh = 0.0005; %default value
 644 | 
645 |
649 | 57 650 | 652 |
winFlag = 'sqrt_blackmanharris';
 653 | 
654 |
658 | 58 659 | 661 |
 662 | 
663 |
667 | 59 668 | 670 |
for ain = 1:1:length(varargin)
 671 | 
672 |
676 | 60 677 | 679 |
    if strcmp(varargin{ain},'q'), q = varargin{ain+1}; end;
 680 | 
681 |
685 | 61 686 | 688 |
    if strcmp(varargin{ain},'atomHopFactor'), atomHopFactor = varargin{ain+1}; end;
 689 | 
690 |
694 | 62 695 | 697 |
    if strcmp(varargin{ain},'thresh'), thresh = varargin{ain+1}; end;
 698 | 
699 |
703 | 63 704 | 706 |
    if strcmp(varargin{ain},'kernel'), cqtKernel = varargin{ain+1}; end;
 707 | 
708 |
712 | 64 713 | 715 |
    if strcmp(varargin{ain},'win'), winFlag = varargin{ain+1}; end;
 716 | 
717 |
721 | 65 722 | 724 |
    if strcmp(varargin{ain},'coeffB'), B = varargin{ain+1}; end;
 725 | 
726 |
730 | 66 731 | 733 |
    if strcmp(varargin{ain},'coeffA'), A = varargin{ain+1}; end;    
 734 | 
735 |
739 | 67 740 | 742 |
end
 743 | 
744 |
748 | 68 749 | 751 |
 752 | 
753 |
757 | 69 758 | 760 |
%% define
 761 | 
762 |
766 | 70 767 | 769 |
octaveNr = ceil(log2(fmax/fmin));
 770 | 
771 |
775 | 71 776 | 778 |
fmin = (fmax/2^octaveNr) * 2^(1/bins); %set fmin to actual value
 779 | 
780 |
784 | 72 785 | 787 |
xlen_init = length(x);
 788 | 
789 |
793 | 73 794 | 796 |
 797 | 
798 |
802 | 74 803 | 805 |
%% design lowpass filter
 806 | 
807 |
811 | 75 812 | 814 |
if ~exist('B','var') || ~exist('A','var')
 815 | 
816 |
820 | 76 821 | 823 |
    LPorder = 6; %order of the anti-aliasing filter
 824 | 
825 |
829 | 77 830 | 832 |
    cutoff = 0.5;
 833 | 
834 |
838 | 78 839 | 841 |
    [B A] = butter(LPorder,cutoff,'low'); %design f_nyquist/2-lowpass filter
 842 | 
843 |
847 | 79 848 | 850 |
end
 851 | 
852 |
856 | 80 857 | 859 |
 860 | 
861 |
865 | 81 866 | 868 |
%% design kernel for one octave 
 869 | 
870 |
874 | 82 875 | 877 |
if ~exist('cqtKernel','var')
 878 | 
879 |
883 | 83 884 | 886 |
    cqtKernel = genCQTkernel(fmax, bins,fs,'q',q,'atomHopFactor',atomHopFactor,'thresh',thresh,'win',winFlag);
 887 | 
888 |
892 | 84 893 | 895 |
end
 896 | 
897 |
901 | 85 902 | 904 |
 905 | 
906 |
910 | 86 911 | 913 |
%% calculate CQT
 914 | 
915 |
919 | 87 920 | 922 |
cellCQT = cell(1,octaveNr);
 923 | 
924 |
928 | 88 929 | 931 |
maxBlock = cqtKernel.fftLEN * 2^(octaveNr-1); %largest FFT Block (virtual)
 932 | 
933 |
937 | 89 938 | 940 |
suffixZeros = maxBlock; 
 941 | 
942 |
946 | 90 947 | 949 |
prefixZeros = maxBlock;
 950 | 
951 |
955 | 91 956 | 958 |
x = [zeros(prefixZeros,1); x; zeros(suffixZeros,1)]; %zeropadding
 959 | 
960 |
964 | 92 965 | 967 |
OVRLP = cqtKernel.fftLEN - cqtKernel.fftHOP;
 968 | 
969 |
973 | 93 974 | 976 |
K = cqtKernel.fKernel'; %conjugate spectral kernel for cqt transformation
 977 | 
978 |
982 | 94 983 | 985 |
 986 | 
987 |
991 | 95 992 | 994 |
for i = 1:octaveNr
 995 | 
996 |
1000 | 96 1001 | 1003 |
    xx = buffer(x,cqtKernel.fftLEN, OVRLP,'nodelay'); %generating FFT blocks
1004 | 
1005 |
1009 | 97 1010 | 1012 |
    XX = fft(xx); %applying fft to each column (each FFT frame)
1013 | 
1014 |
1018 | 98 1019 | 1021 |
    cellCQT{i} = K*XX; %calculating cqt coefficients for all FFT frames for this octave
1022 | 
1023 |
1027 | 99 1028 | 1030 |
1031 | 
1032 |
1036 | 100 1037 | 1039 |
    if i~=octaveNr
1040 | 
1041 |
1045 | 101 1046 | 1048 |
        x = filtfilt(B,A,x); %anti aliasing filter
1049 | 
1050 |
1054 | 102 1055 | 1057 |
        x = x(1:2:end); %drop samplerate by 2
1058 | 
1059 |
1063 | 103 1064 | 1066 |
    end
1067 | 
1068 |
1072 | 104 1073 | 1075 |
end
1076 | 
1077 |
1081 | 105 1082 | 1084 |
1085 | 
1086 |
1090 | 106 1091 | 1093 |
%% map to sparse matrix representation
1094 | 
1095 |
1099 | 107 1100 | 1102 |
spCQT = cell2sparse(cellCQT,octaveNr,bins,cqtKernel.firstcenter,cqtKernel.atomHOP,cqtKernel.atomNr);
1103 | 
1104 |
1108 | 108 1109 | 1111 |
1112 | 
1113 |
1117 | 109 1118 | 1120 |
%% return
1121 | 
1122 |
1126 | 110 1127 | 1129 |
intParam = struct('sufZeros',suffixZeros,'preZeros',prefixZeros,'xlen_init',xlen_init,'fftLEN',cqtKernel.fftLEN,'fftHOP',cqtKernel.fftHOP,...
1130 | 
1131 |
1135 | 111 1136 | 1138 |
    'q',q,'filtCoeffA',A,'filtCoeffB',B,'firstcenter',cqtKernel.firstcenter,'atomHOP',cqtKernel.atomHOP,...
1139 | 
1140 |
1144 | 112 1145 | 1147 |
    'atomNr',cqtKernel.atomNr,'Nk_max',cqtKernel.Nk_max,'Q',cqtKernel.Q,'rast',0);
1148 | 
1149 |
1153 | 113 1154 | 1156 |
1157 | 
1158 |
1162 | 114 1163 | 1165 |
Xcqt = struct('spCQT',spCQT,'fKernel',cqtKernel.fKernel,'fmax',fmax,'fmin',fmin,'octaveNr',octaveNr,'bins',cqtKernel.bins,'intParams',intParam);
1166 | 
1167 |
1171 | 115 1172 | 1174 |
1175 | 
1176 |
1180 | 116 1181 | 1183 |
1184 | 
1185 |
1189 |
1190 | 1191 | 1192 | 1193 | 1194 |
1195 |
1196 |
1197 |
1198 | 1199 | 1200 | 1201 | 1202 | 1207 |
1208 |
1209 | 1210 | 1211 | 1212 | -------------------------------------------------------------------------------- /MATLAB/genCQTkernel.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /genCQTkernel.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / genCQTkernel.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (5.476 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 | 543 | 547 | 548 | 549 | 552 | 556 | 557 | 558 | 561 | 565 | 566 | 567 | 570 | 574 | 575 | 576 | 579 | 583 | 584 | 585 | 588 | 592 | 593 | 594 | 597 | 601 | 602 | 603 | 606 | 610 | 611 | 612 | 615 | 619 | 620 | 621 | 624 | 628 | 629 | 630 | 633 | 637 | 638 | 639 | 642 | 646 | 647 | 648 | 651 | 655 | 656 | 657 | 660 | 664 | 665 | 666 | 669 | 673 | 674 | 675 | 678 | 682 | 683 | 684 | 687 | 691 | 692 | 693 | 696 | 700 | 701 | 702 | 705 | 709 | 710 | 711 | 714 | 718 | 719 | 720 | 723 | 727 | 728 | 729 | 732 | 736 | 737 | 738 | 741 | 745 | 746 | 747 | 750 | 754 | 755 | 756 | 759 | 763 | 764 | 765 | 768 | 772 | 773 | 774 | 777 | 781 | 782 | 783 | 786 | 790 | 791 | 792 | 795 | 799 | 800 | 801 | 804 | 808 | 809 | 810 | 813 | 817 | 818 | 819 | 822 | 826 | 827 | 828 | 831 | 835 | 836 | 837 | 840 | 844 | 845 | 846 | 849 | 853 | 854 | 855 | 858 | 862 | 863 | 864 | 867 | 871 | 872 | 873 | 876 | 880 | 881 | 882 | 885 | 889 | 890 | 891 | 894 | 898 | 899 | 900 | 903 | 907 | 908 | 909 | 912 | 916 | 917 | 918 | 921 | 925 | 926 | 927 | 930 | 934 | 935 | 936 | 939 | 943 | 944 | 945 | 948 | 952 | 953 | 954 | 957 | 961 | 962 | 963 | 966 | 970 | 971 | 972 | 975 | 979 | 980 | 981 | 984 | 988 | 989 | 990 | 993 | 997 | 998 | 999 | 1002 | 1006 | 1007 | 1008 | 1011 | 1015 | 1016 | 1017 | 1020 | 1024 | 1025 | 1026 | 1029 | 1033 | 1034 | 1035 | 1038 | 1042 | 1043 | 1044 | 1047 | 1051 | 1052 | 1053 | 1056 | 1060 | 1061 | 1062 | 1065 | 1069 | 1070 | 1071 | 1074 | 1078 | 1079 | 1080 | 1083 | 1087 | 1088 | 1089 | 1092 | 1096 | 1097 | 1098 | 1101 | 1105 | 1106 | 1107 | 1110 | 1114 | 1115 | 1116 | 1119 | 1123 | 1124 | 1125 | 1128 | 1132 | 1133 | 1134 | 1137 | 1141 | 1142 | 1143 | 1146 | 1150 | 1151 | 1152 | 1155 | 1159 | 1160 | 1161 | 1164 | 1168 | 1169 | 1170 | 1173 | 1177 | 1178 | 1179 | 1182 | 1186 | 1187 | 1188 | 1191 | 1195 | 1196 | 1197 | 1200 | 1204 | 1205 | 1206 | 1209 | 1213 | 1214 | 1215 | 1218 | 1222 | 1223 | 1224 | 1227 | 1231 | 1232 | 1233 | 1236 | 1240 | 1241 | 1242 | 1245 | 1249 | 1250 | 1251 | 1254 | 1258 | 1259 | 1260 | 1263 | 1267 | 1268 | 1269 | 1272 | 1276 | 1277 | 1278 | 1281 | 1285 | 1286 | 1287 | 1290 | 1294 | 1295 | 1296 | 1299 | 1303 | 1304 | 1305 | 1308 | 1312 | 1313 | 1314 | 1317 | 1321 | 1322 | 1323 | 1326 | 1330 | 1331 | 1332 | 1335 | 1339 | 1340 | 1341 | 1344 | 1348 | 1349 | 1350 | 1353 | 1357 | 1358 | 1359 |
145 | 1 146 | 148 |
function cqtKernel = genCQTkernel(fmax, bins, fs, varargin)
 149 | 
150 |
154 | 2 155 | 157 |
%Calculating the CQT Kernel for one octave. All atoms are center-stacked.
 158 | 
159 |
163 | 3 164 | 166 |
%Atoms are placed so that the stacks of lower octaves are centered at the
 167 | 
168 |
172 | 4 173 | 175 |
%same positions in time, however, their amount is reduced by factor two for
 176 | 
177 |
181 | 5 182 | 184 |
%each octave down.
 185 | 
186 |
190 | 6 191 | 193 |
%
 194 | 
195 |
199 | 7 200 | 202 |
%INPUT:
 203 | 
204 |
208 | 8 209 | 211 |
%   fmax          ... highest frequency of interest
 212 | 
213 |
217 | 9 218 | 220 |
%   bins          ... number of bins per octave
 221 | 
222 |
226 | 10 227 | 229 |
%   fs            ... sampling frequency
 230 | 
231 |
235 | 11 236 | 238 |
%
 239 | 
240 |
244 | 12 245 | 247 |
%optional input parameters (parameter name/value pairs):
 248 | 
249 |
253 | 13 254 | 256 |
%
 257 | 
258 |
262 | 14 263 | 265 |
%   'q'             ... Q scaling factor. Default: 1.
 266 | 
267 |
271 | 15 272 | 274 |
%   'atomHopFactor' ... relative hop size corresponding to the shortest
 275 | 
276 |
280 | 16 281 | 283 |
%                       temporal atom. Default: 0.25.
 284 | 
285 |
289 | 17 290 | 292 |
%   'thresh'        ... values smaller than 'tresh' in the spectral kernel are rounded to
 293 | 
294 |
298 | 18 299 | 301 |
%                       zero. Default: 0.0005.
 302 | 
303 |
307 | 19 308 | 310 |
%   'win'           ... defines which window will be used for the CQT. Valid
 311 | 
312 |
316 | 20 317 | 319 |
%                       values are: 'blackman','hann' and 'blackmanharris'. To
 320 | 
321 |
325 | 21 326 | 328 |
%                       use the square root of each window use the prefix 'sqrt_'
 329 | 
330 |
334 | 22 335 | 337 |
%                      (i.e. 'sqrt_blackman'). Default: 'sqrt_blackmanharris'
 338 | 
339 |
343 | 23 344 | 346 |
%   'perfRast'      ... if set to 1 the kernel is designed in order to
 347 | 
348 |
352 | 24 353 | 355 |
%                       enable perfect rasterization using the function
 356 | 
357 |
361 | 25 362 | 364 |
%                       cqtPerfectRast() (Default: perRast=0). See documentation of
 365 | 
366 |
370 | 26 371 | 373 |
%                       'cqtPerfectRast' for further information.
 374 | 
375 |
379 | 27 380 | 382 |
%
 383 | 
384 |
388 | 28 389 | 391 |
%OUTPUT:
 392 | 
393 |
397 | 29 398 | 400 |
%   cqtKernel   ... Structure that contains the spectral kernel 'fKernel'
 401 | 
402 |
406 | 30 407 | 409 |
%                   additional design parameters used in cqt(), cqtPerfectRast() and icqt().
 410 | 
411 |
415 | 31 416 | 418 |
%
 419 | 
420 |
424 | 32 425 | 427 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
 428 | 
429 |
433 | 33 434 | 436 |
 437 | 
438 |
442 | 34 443 | 445 |
%% input parameters
 446 | 
447 |
451 | 35 452 | 454 |
q = 1; %default value
 455 | 
456 |
460 | 36 461 | 463 |
atomHopFactor = 0.25; %default value
 464 | 
465 |
469 | 37 470 | 472 |
thresh = 0.0005; %default value
 473 | 
474 |
478 | 38 479 | 481 |
winFlag = 'sqrt_blackmanharris'; %default value
 482 | 
483 |
487 | 39 488 | 490 |
perfRast = 0; %default value
 491 | 
492 |
496 | 40 497 | 499 |
 500 | 
501 |
505 | 41 506 | 508 |
for ain = 1:length(varargin)
 509 | 
510 |
514 | 42 515 | 517 |
    if strcmp(varargin{ain},'q'), q = varargin{ain+1}; end;
 518 | 
519 |
523 | 43 524 | 526 |
    if strcmp(varargin{ain},'atomHopFactor'), atomHopFactor = varargin{ain+1}; end;
 527 | 
528 |
532 | 44 533 | 535 |
    if strcmp(varargin{ain},'thresh'), thresh = varargin{ain+1}; end;
 536 | 
537 |
541 | 45 542 | 544 |
    if strcmp(varargin{ain},'win'), winFlag = varargin{ain+1}; end;
 545 | 
546 |
550 | 46 551 | 553 |
    if strcmp(varargin{ain},'perfRast'), perfRast = varargin{ain+1}; end;
 554 | 
555 |
559 | 47 560 | 562 |
end
 563 | 
564 |
568 | 48 569 | 571 |
 572 | 
573 |
577 | 49 578 | 580 |
%% define
 581 | 
582 |
586 | 50 587 | 589 |
fmin = (fmax/2)*2^(1/bins);
 590 | 
591 |
595 | 51 596 | 598 |
Q = 1/(2^(1/bins)-1);
 599 | 
600 |
604 | 52 605 | 607 |
Q = Q*q;
 608 | 
609 |
613 | 53 614 | 616 |
Nk_max = Q * fs / fmin; 
 617 | 
618 |
622 | 54 623 | 625 |
Nk_max = round(Nk_max); %length of the largest atom [samples]
 626 | 
627 |
631 | 55 632 | 634 |
 635 | 
636 |
640 | 56 641 | 643 |
 644 | 
645 |
649 | 57 650 | 652 |
%% Compute FFT size, FFT hop, atom hop, ...
 653 | 
654 |
658 | 58 659 | 661 |
Nk_min = round( Q * fs / (fmin*2^((bins-1)/bins)) ); %length of the shortest atom [samples]
 662 | 
663 |
667 | 59 668 | 670 |
atomHOP = round(Nk_min*atomHopFactor); %atom hop size
 671 | 
672 |
676 | 60 677 | 679 |
first_center = ceil(Nk_max/2); %first possible center position within the frame
 680 | 
681 |
685 | 61 686 | 688 |
first_center = atomHOP * ceil(first_center/atomHOP); %lock the first center to an integer multiple of the atom hop size
 689 | 
690 |
694 | 62 695 | 697 |
FFTLen = 2^nextpow2(first_center+ceil(Nk_max/2)); %use smallest possible FFT size (increase sparsity)
 698 | 
699 |
703 | 63 704 | 706 |
 707 | 
708 |
712 | 64 713 | 715 |
if perfRast
 716 | 
717 |
721 | 65 722 | 724 |
    winNr = floor((FFTLen-ceil(Nk_max/2)-first_center)/atomHOP); %number of temporal atoms per FFT Frame
 725 | 
726 |
730 | 66 731 | 733 |
    if winNr == 0
 734 | 
735 |
739 | 67 740 | 742 |
        FFTLen = FFTLen * 2;
 743 | 
744 |
748 | 68 749 | 751 |
        winNr = floor((FFTLen-ceil(Nk_max/2)-first_center)/atomHOP);
 752 | 
753 |
757 | 69 758 | 760 |
    end
 761 | 
762 |
766 | 70 767 | 769 |
else
 770 | 
771 |
775 | 71 776 | 778 |
    winNr = floor((FFTLen-ceil(Nk_max/2)-first_center)/atomHOP)+1; %number of temporal atoms per FFT Frame
 779 | 
780 |
784 | 72 785 | 787 |
end
 788 | 
789 |
793 | 73 794 | 796 |
 797 | 
798 |
802 | 74 803 | 805 |
last_center = first_center + (winNr-1)*atomHOP;
 806 | 
807 |
811 | 75 812 | 814 |
fftHOP = (last_center + atomHOP) - first_center; % hop size of FFT frames
 815 | 
816 |
820 | 76 821 | 823 |
fftOLP = (FFTLen-fftHOP/FFTLen)*100; %overlap of FFT frames in percent ***AK:needed?
 824 | 
825 |
829 | 77 830 | 832 |
 833 | 
834 |
838 | 78 839 | 841 |
%% init variables
 842 | 
843 |
847 | 79 848 | 850 |
tempKernel= zeros(1,FFTLen); 
 851 | 
852 |
856 | 80 857 | 859 |
sparKernel= []; 
 860 | 
861 |
865 | 81 866 | 868 |
 869 | 
870 |
874 | 82 875 | 877 |
%% Compute kernel
 878 | 
879 |
883 | 83 884 | 886 |
atomInd = 0;
 887 | 
888 |
892 | 84 893 | 895 |
for k = 1:bins
 896 | 
897 |
901 | 85 902 | 904 |
    
 905 | 
906 |
910 | 86 911 | 913 |
   Nk = round( Q * fs / (fmin*2^((k-1)/bins)) ); %N[k] = (fs/fk)*Q. Rounding will be omitted in future versions
 914 | 
915 |
919 | 87 920 | 922 |
   
 923 | 
924 |
928 | 88 929 | 931 |
   switch winFlag
 932 | 
933 |
937 | 89 938 | 940 |
       case 'sqrt_blackmanharris'
 941 | 
942 |
946 | 90 947 | 949 |
            winFct = sqrt(blackmanharris(Nk));
 950 | 
951 |
955 | 91 956 | 958 |
       case 'blackmanharris'
 959 | 
960 |
964 | 92 965 | 967 |
            winFct = blackmanharris(Nk);
 968 | 
969 |
973 | 93 974 | 976 |
       case 'sqrt_hann'
 977 | 
978 |
982 | 94 983 | 985 |
            winFct = sqrt(hann(Nk,'periodic'));
 986 | 
987 |
991 | 95 992 | 994 |
       case 'hann'
 995 | 
996 |
1000 | 96 1001 | 1003 |
            winFct = hann(Nk,'periodic');
1004 | 
1005 |
1009 | 97 1010 | 1012 |
       case 'sqrt_blackman'
1013 | 
1014 |
1018 | 98 1019 | 1021 |
            winFct = sqrt(hann(blackman,'periodic'));
1022 | 
1023 |
1027 | 99 1028 | 1030 |
       case 'blackman'
1031 | 
1032 |
1036 | 100 1037 | 1039 |
            winFct = blackman(Nk,'periodic');
1040 | 
1041 |
1045 | 101 1046 | 1048 |
       otherwise
1049 | 
1050 |
1054 | 102 1055 | 1057 |
            winFct = sqrt(blackmanharris(Nk));
1058 | 
1059 |
1063 | 103 1064 | 1066 |
            if k==1, warning('CQT:INPUT','Non-existing window function. Default window is used!'); end;
1067 | 
1068 |
1072 | 104 1073 | 1075 |
   end
1076 | 
1077 |
1081 | 105 1082 | 1084 |
   
1085 | 
1086 |
1090 | 106 1091 | 1093 |
   fk = fmin*2^((k-1)/bins);
1094 | 
1095 |
1099 | 107 1100 | 1102 |
   tempKernelBin = (winFct/Nk) .* exp(2*pi*1i*fk*(0:Nk-1)'/fs);
1103 | 
1104 |
1108 | 108 1109 | 1111 |
   atomOffset = first_center - ceil(Nk/2);
1112 | 
1113 |
1117 | 109 1118 | 1120 |
1121 | 
1122 |
1126 | 110 1127 | 1129 |
   for i = 1:winNr 
1130 | 
1131 |
1135 | 111 1136 | 1138 |
       shift = atomOffset + ((i-1) * atomHOP);
1139 | 
1140 |
1144 | 112 1145 | 1147 |
       tempKernel(1+shift:Nk+shift) = tempKernelBin; 
1148 | 
1149 |
1153 | 113 1154 | 1156 |
       atomInd = atomInd+1;
1157 | 
1158 |
1162 | 114 1163 | 1165 |
       specKernel= fft(tempKernel);
1166 | 
1167 |
1171 | 115 1172 | 1174 |
       specKernel(abs(specKernel)<=thresh)= 0;   
1175 | 
1176 |
1180 | 116 1181 | 1183 |
       sparKernel= sparse([sparKernel; specKernel]);
1184 | 
1185 |
1189 | 117 1190 | 1192 |
       tempKernel = zeros(1,FFTLen); %reset window     
1193 | 
1194 |
1198 | 118 1199 | 1201 |
   end
1202 | 
1203 |
1207 | 119 1208 | 1210 |
end
1211 | 
1212 |
1216 | 120 1217 | 1219 |
sparKernel = (sparKernel.')/FFTLen;
1220 | 
1221 |
1225 | 121 1226 | 1228 |
1229 | 
1230 |
1234 | 122 1235 | 1237 |
%% Normalize the magnitudes of the atoms
1238 | 
1239 |
1243 | 123 1244 | 1246 |
[ignore,wx1]=max(sparKernel(:,1));
1247 | 
1248 |
1252 | 124 1253 | 1255 |
[ignore,wx2]=max(sparKernel(:,end));
1256 | 
1257 |
1261 | 125 1262 | 1264 |
wK=sparKernel(wx1:wx2,:);
1265 | 
1266 |
1270 | 126 1271 | 1273 |
wK = diag(wK * wK');
1274 | 
1275 |
1279 | 127 1280 | 1282 |
wK = wK(round(1/q)+1:(end-round(1/q)-2));
1283 | 
1284 |
1288 | 128 1289 | 1291 |
weight = 1./mean(abs(wK));
1292 | 
1293 |
1297 | 129 1298 | 1300 |
weight = weight.*(fftHOP/FFTLen); 
1301 | 
1302 |
1306 | 130 1307 | 1309 |
weight = sqrt(weight); %sqrt because the same weight is applied in icqt again
1310 | 
1311 |
1315 | 131 1316 | 1318 |
sparKernel = weight.*sparKernel;
1319 | 
1320 |
1324 | 132 1325 | 1327 |
1328 | 
1329 |
1333 | 133 1334 | 1336 |
%% return
1337 | 
1338 |
1342 | 134 1343 | 1345 |
cqtKernel = struct('fKernel',sparKernel,'fftLEN',FFTLen,'fftHOP',fftHOP,'fftOverlap',fftOLP,'perfRast',perfRast,...
1346 | 
1347 |
1351 | 135 1352 | 1354 |
    'bins',bins,'firstcenter',first_center,'atomHOP',atomHOP,'atomNr',winNr,'Nk_max',Nk_max,'Q',Q,'fmin',fmin);
1355 | 
1356 |
1360 |
1361 | 1362 | 1363 | 1364 | 1365 |
1366 |
1367 |
1368 |
1369 | 1370 | 1371 | 1372 | 1373 | 1378 |
1379 |
1380 | 1381 | 1382 | 1383 | -------------------------------------------------------------------------------- /MATLAB/getCQT.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /getCQT.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / getCQT.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (1.741 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 | 543 | 547 | 548 | 549 | 552 | 556 | 557 | 558 | 561 | 565 | 566 | 567 |
145 | 1 146 | 148 |
function intCQT = getCQT(Xcqt,fSlice,tSlice,iFlag)
149 | 
150 |
154 | 2 155 | 157 |
%outCQ = getCQT(Xcqt,fSlice,tSlice,iFlag) computes a rasterized representation of 
158 | 
159 |
163 | 3 164 | 166 |
%the amplitudes of the calculated CQT coefficients for the frequency bins definded in vector fSlice and the 
167 | 
168 |
172 | 4 173 | 175 |
%points in time (time frames) defined in vector tSlice using the interpolation method defined in iFlag. 
176 | 
177 |
181 | 5 182 | 184 |
%Valid values for iFlag are:
185 | 
186 |
190 | 6 191 | 193 |
%
194 | 
195 |
199 | 7 200 | 202 |
%'linear'  ... linear interpolation (default)
203 | 
204 |
208 | 8 209 | 211 |
%'spline'  ... spline interpolation
212 | 
213 |
217 | 9 218 | 220 |
%'nearest' ... nearest neighbor interpolation
221 | 
222 |
226 | 10 227 | 229 |
%'cubic'   ... piecewise cubic interpolation
230 | 
231 |
235 | 11 236 | 238 |
%
239 | 
240 |
244 | 12 245 | 247 |
%If the entire CQT representation should be rasterized, set fSlice and
248 | 
249 |
253 | 13 254 | 256 |
%tSlice to 'all'.
257 | 
258 |
262 | 14 263 | 265 |
%The input parameter Xcqt is the structure gained using cqt(...).
266 | 
267 |
271 | 15 272 | 274 |
%The output parameter 'intCQT' is the same size as Xcqt.spCQT but is no
275 | 
276 |
280 | 16 281 | 283 |
%longer sparse since the zeros between two coefficients are replaced by
284 | 
285 |
289 | 17 290 | 292 |
%the interpolated values. The coefficients stored in 'intCQT' are now
293 | 
294 |
298 | 18 299 | 301 |
%real-valued since only the absolute values of the coefficients are
302 | 
303 |
307 | 19 308 | 310 |
%interpolated. If a spectrogram-like (rasterized) version of the CQT
311 | 
312 |
316 | 20 317 | 319 |
%coefficients including phase information is required, use the function
320 | 
321 |
325 | 21 326 | 328 |
%cqtPerfectRast() (see documentation for further information)
329 | 
330 |
334 | 22 335 | 337 |
%
338 | 
339 |
343 | 23 344 | 346 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
347 | 
348 |
352 | 24 353 | 355 |
356 | 
357 |
361 | 25 362 | 364 |
365 | 
366 |
370 | 26 371 | 373 |
if ischar(fSlice), fSlice = 1:(Xcqt.bins*Xcqt.octaveNr); end;
374 | 
375 |
379 | 27 380 | 382 |
if ischar(tSlice)
383 | 
384 |
388 | 28 389 | 391 |
    lastEnt = find(Xcqt.spCQT(1,:),1,'last');
392 | 
393 |
397 | 29 398 | 400 |
    tSlice = 1:lastEnt;
401 | 
402 |
406 | 30 407 | 409 |
end
410 | 
411 |
415 | 31 416 | 418 |
if nargin < 4, iFlag = 'linear'; end;
419 | 
420 |
424 | 32 425 | 427 |
428 | 
429 |
433 | 33 434 | 436 |
intCQT = zeros(length(fSlice),length(tSlice));
437 | 
438 |
442 | 34 443 | 445 |
bins = Xcqt.bins;
446 | 
447 |
451 | 35 452 | 454 |
spCQT = Xcqt.spCQT;
455 | 
456 |
460 | 36 461 | 463 |
octaveNr = Xcqt.octaveNr;
464 | 
465 |
469 | 37 470 | 472 |
spCQT = spCQT.';
473 | 
474 |
478 | 38 479 | 481 |
482 | 
483 |
487 | 39 488 | 490 |
for k=1:length(fSlice)
491 | 
492 |
496 | 40 497 | 499 |
   oct = octaveNr-floor((fSlice(k)-0.1)/bins);
500 | 
501 |
505 | 41 506 | 508 |
   stepVec = 1:2^(oct-1):size(spCQT,1);
509 | 
510 |
514 | 42 515 | 517 |
   Xbin = full(spCQT(stepVec,fSlice(k)));
518 | 
519 |
523 | 43 524 | 526 |
   intCQT(k,:) = interp1(stepVec,abs(Xbin),tSlice,iFlag);
527 | 
528 |
532 | 44 533 | 535 |
end
536 | 
537 |
541 | 45 542 | 544 |
545 | 
546 |
550 | 46 551 | 553 |
554 | 
555 |
559 | 47 560 | 562 |
563 | 
564 |
568 |
569 | 570 | 571 | 572 | 573 |
574 |
575 |
576 |
577 | 578 | 579 | 580 | 581 | 586 |
587 |
588 | 589 | 590 | 591 | -------------------------------------------------------------------------------- /MATLAB/icqt.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /icqt.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / icqt.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (1.735 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 |
145 | 1 146 | 148 |
function y = icqt(Xcqt)
149 | 
150 |
154 | 2 155 | 157 |
%y = icqt(Xcqt) computes the inverse CQT of the CQT coefficients in Xcqt.spCQT
158 | 
159 |
163 | 3 164 | 166 |
%
167 | 
168 |
172 | 4 173 | 175 |
%The input structue Xcqt is the structure gained by cqt() and cqtPerfectRast(), respectively. 
176 | 
177 |
181 | 5 182 | 184 |
%If the CQT coefficients in Xcqt.spCQT are not changed, the output y is the
185 | 
186 |
190 | 6 191 | 193 |
%reconstructed (near-perfect) time-domain signal of the input signal x
194 | 
195 |
199 | 7 200 | 202 |
%(cqt(x,...)) withing the frequency range [fmin fmax].
203 | 
204 |
208 | 8 209 | 211 |
%
212 | 
213 |
217 | 9 218 | 220 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
221 | 
222 |
226 | 10 227 | 229 |
230 | 
231 |
235 | 11 236 | 238 |
cellCQT = sparse2cell(Xcqt.spCQT,Xcqt.bins,Xcqt.octaveNr,Xcqt.intParams.atomNr,Xcqt.intParams.firstcenter,Xcqt.intParams.atomHOP);
239 | 
240 |
244 | 12 245 | 247 |
248 | 
249 |
253 | 13 254 | 256 |
FFTLen = Xcqt.intParams.fftLEN;
257 | 
258 |
262 | 14 263 | 265 |
octaveNr = Xcqt.octaveNr;
266 | 
267 |
271 | 15 272 | 274 |
HOPSZ = Xcqt.intParams.fftHOP;
275 | 
276 |
280 | 16 281 | 283 |
284 | 
285 |
289 | 17 290 | 292 |
%% Kernel for inverse transform
293 | 
294 |
298 | 18 299 | 301 |
Kinv = Xcqt.fKernel;
302 | 
303 |
307 | 19 308 | 310 |
311 | 
312 |
316 | 20 317 | 319 |
%% inverse transform
320 | 
321 |
325 | 21 326 | 328 |
y = [];
329 | 
330 |
334 | 22 335 | 337 |
for i = octaveNr:-1:1
338 | 
339 |
343 | 23 344 | 346 |
    cellCQT_oct = cellCQT{i};    
347 | 
348 |
352 | 24 353 | 355 |
    Y = Kinv * cellCQT_oct; %compute spectrum of reconstructed signal for all coefficients in this octave  
356 | 
357 |
361 | 25 362 | 364 |
    y_oct_temp = ifft(Y);
365 | 
366 |
370 | 26 371 | 373 |
    y_oct = 2*real(y_oct_temp); %Y contains no negative frequencies -> keep only real part*2 to 
374 | 
375 |
379 | 27 380 | 382 |
                                %reconstruct real valued time signal 
383 | 
384 |
388 | 28 389 | 391 |
    NBLOCKS = size(Y,2);      
392 | 
393 |
397 | 29 398 | 400 |
    siglen = FFTLen + (NBLOCKS-1)*HOPSZ;
401 | 
402 |
406 | 30 407 | 409 |
    y = [y;zeros(siglen-length(y),1)];
410 | 
411 |
415 | 31 416 | 418 |
    for n = 1:NBLOCKS
419 | 
420 |
424 | 32 425 | 427 |
        y((n-1)*HOPSZ+1:((n-1)*HOPSZ)+FFTLen) = y_oct(:,n) + y((n-1)*HOPSZ+1:((n-1)*HOPSZ)+FFTLen); %overlap-add
428 | 
429 |
433 | 33 434 | 436 |
    end
437 | 
438 |
442 | 34 443 | 445 |
    
446 | 
447 |
451 | 35 452 | 454 |
    if(i~=1) %upsampling by factor two
455 | 
456 |
460 | 36 461 | 463 |
         y = upsample(y,2); %insert one zero between each sample
464 | 
465 |
469 | 37 470 | 472 |
         y = filtfilt(Xcqt.intParams.filtCoeffB,Xcqt.intParams.filtCoeffA,y);
473 | 
474 |
478 | 38 479 | 481 |
         y = y * 2;
482 | 
483 |
487 | 39 488 | 490 |
    end
491 | 
492 |
496 | 40 497 | 499 |
500 | 
501 |
505 | 41 506 | 508 |
end
509 | 
510 |
514 | 42 515 | 517 |
518 | 
519 |
523 | 43 524 | 526 |
y = y(Xcqt.intParams.preZeros+1:end); %crop introduced zeros at the beginning
527 | 
528 |
532 | 44 533 | 535 |
y = y(1:Xcqt.intParams.xlen_init); %crop overhead zeros at the end
536 | 
537 |
541 |
542 | 543 | 544 | 545 | 546 |
547 |
548 |
549 |
550 | 551 | 552 | 553 | 554 | 559 |
560 |
561 | 562 | 563 | 564 | -------------------------------------------------------------------------------- /MATLAB/plotCQT.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /plotCQT.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / plotCQT.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (1.77 KB) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 | 390 | 394 | 395 | 396 | 399 | 403 | 404 | 405 | 408 | 412 | 413 | 414 | 417 | 421 | 422 | 423 | 426 | 430 | 431 | 432 | 435 | 439 | 440 | 441 | 444 | 448 | 449 | 450 | 453 | 457 | 458 | 459 | 462 | 466 | 467 | 468 | 471 | 475 | 476 | 477 | 480 | 484 | 485 | 486 | 489 | 493 | 494 | 495 | 498 | 502 | 503 | 504 | 507 | 511 | 512 | 513 | 516 | 520 | 521 | 522 | 525 | 529 | 530 | 531 | 534 | 538 | 539 | 540 | 543 | 546 | 547 | 548 |
145 | 1 146 | 148 |
function plotCQT(Xcqt,fs,fcomp,method)
149 | 
150 |
154 | 2 155 | 157 |
%plotCQT(Xcqt,fs,fcomp,method) plots the magnitudes of the CQT 
158 | 
159 |
163 | 3 164 | 166 |
%coefficients similar to a spectrogram using linear interpolation 
167 | 
168 |
172 | 4 173 | 175 |
%between the calculated coefficients. For better illustration, the
176 | 
177 |
181 | 5 182 | 184 |
%magnitude values can be compressed using fcomp < 1 (Xmag^fcomp).
185 | 
186 |
190 | 6 191 | 193 |
%For generating the figure 'method' can be set to 'surf' and
194 | 
195 |
199 | 7 200 | 202 |
%'image', respectively, whereas using 'surf' the axis are properly labeled, 
203 | 
204 |
208 | 8 209 | 211 |
%however 'image' is faster leaving all axis unlabeled (default: 'surf').
212 | 
213 |
217 | 9 218 | 220 |
%
221 | 
222 |
226 | 10 227 | 229 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
230 | 
231 |
235 | 11 236 | 238 |
239 | 
240 |
244 | 12 245 | 247 |
if Xcqt.intParams.rast == 0
248 | 
249 |
253 | 13 254 | 256 |
    absCQT = getCQT(Xcqt,'all','all','linear');
257 | 
258 |
262 | 14 263 | 265 |
else
266 | 
267 |
271 | 15 272 | 274 |
    absCQT = abs(Xcqt.spCQT);
275 | 
276 |
280 | 16 281 | 283 |
end
284 | 
285 |
289 | 17 290 | 292 |
293 | 
294 |
298 | 18 299 | 301 |
emptyHops = Xcqt.intParams.firstcenter/Xcqt.intParams.atomHOP;
302 | 
303 |
307 | 19 308 | 310 |
maxDrop = emptyHops*2^(Xcqt.octaveNr-1)-emptyHops;
311 | 
312 |
316 | 20 317 | 319 |
droppedSamples = (maxDrop-1)*Xcqt.intParams.atomHOP + Xcqt.intParams.firstcenter;
320 | 
321 |
325 | 21 326 | 328 |
outputTimeVec = (1:size(absCQT,2))*Xcqt.intParams.atomHOP-Xcqt.intParams.preZeros+droppedSamples;
329 | 
330 |
334 | 22 335 | 337 |
338 | 
339 |
343 | 23 344 | 346 |
if nargin < 4, method = 'surf'; end;
347 | 
348 |
352 | 24 353 | 355 |
356 | 
357 |
361 | 25 362 | 364 |
if strcmp(method,'surf')  
365 | 
366 |
370 | 26 371 | 373 |
    figure;
374 | 
375 |
379 | 27 380 | 382 |
    X_cq_rast = absCQT.^fcomp; %compress magnitudes
383 | 
384 |
388 | 28 389 | 391 |
    surf(outputTimeVec./fs,1:size(X_cq_rast,1),X_cq_rast,'EdgeColor','none');
392 | 
393 |
397 | 29 398 | 400 |
    caxis([min(min(X_cq_rast)) max(max(X_cq_rast))]);
401 | 
402 |
406 | 30 407 | 409 |
    axis('tight');view(0,90);
410 | 
411 |
415 | 31 416 | 418 |
    set(gca,'YTick',1:Xcqt.bins/2:Xcqt.octaveNr*Xcqt.bins);
419 | 
420 |
424 | 32 425 | 427 |
    h = get(gca); yTick = h.YTick';
428 | 
429 |
433 | 33 434 | 436 |
    yTickLabel = num2str(round(Xcqt.fmin*2.^((yTick-1)/Xcqt.bins)),5);
437 | 
438 |
442 | 34 443 | 445 |
    set(gca,'YTickLabel',yTickLabel);
446 | 
447 |
451 | 35 452 | 454 |
    xlabel('time [sec]'); ylabel('frequency [Hz]');
455 | 
456 |
460 | 36 461 | 463 |
    %load whiteblack1
464 | 
465 |
469 | 37 470 | 472 |
    %load cmapGlow
473 | 
474 |
478 | 38 479 | 481 |
    %set(gcf,'Colormap',whiteblack1)
482 | 
483 |
487 | 39 488 | 490 |
    title('Constant Q transform','FontSize',12);
491 | 
492 |
496 | 40 497 | 499 |
else    
500 | 
501 |
505 | 41 506 | 508 |
    figure;
509 | 
510 |
514 | 42 515 | 517 |
    X_cq_rast = absCQT.^fcomp;
518 | 
519 |
523 | 43 524 | 526 |
    X_cq_rast = flipud(X_cq_rast);
527 | 
528 |
532 | 44 533 | 535 |
    imagesc(abs(X_cq_rast));
536 | 
537 |
541 | 45 542 | 544 |
end
545 |
549 |
550 | 551 | 552 | 553 | 554 |
555 |
556 |
557 |
558 | 559 | 560 | 561 | 562 | 567 |
568 |
569 | 570 | 571 | 572 | -------------------------------------------------------------------------------- /MATLAB/sparse2cell.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /sparse2cell.m - Constant-Q Transform Toolbox - Sound Software .ac.uk 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 |
35 |
37 | 38 |
41 | 42 | 73 | 74 |
75 | 79 | 80 |
81 | 82 | 83 | 84 |
85 |

To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

86 |
87 | 92 | 93 | 94 |

95 |   96 |

97 | 98 | 99 |
100 |
101 |
102 | 103 | 104 |
105 | 106 | 统计 107 | 108 | Download as Zip 109 | 110 |
111 | | 分支: 112 | 114 | 115 | 116 | | 修订: 117 | 118 |
119 | 120 | 121 |
122 | 123 |

root 124 | / sparse2cell.m 125 | 126 | 127 |

128 | 129 | 130 |

131 | 历史记录 | 132 | 查看 | 133 | 追溯 | 134 | 下载 135 | (979 Bytes) 136 |

137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 147 | 151 | 152 | 153 | 156 | 160 | 161 | 162 | 165 | 169 | 170 | 171 | 174 | 178 | 179 | 180 | 183 | 187 | 188 | 189 | 192 | 196 | 197 | 198 | 201 | 205 | 206 | 207 | 210 | 214 | 215 | 216 | 219 | 223 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 241 | 242 | 243 | 246 | 250 | 251 | 252 | 255 | 259 | 260 | 261 | 264 | 268 | 269 | 270 | 273 | 277 | 278 | 279 | 282 | 286 | 287 | 288 | 291 | 295 | 296 | 297 | 300 | 304 | 305 | 306 | 309 | 313 | 314 | 315 | 318 | 322 | 323 | 324 | 327 | 331 | 332 | 333 | 336 | 340 | 341 | 342 | 345 | 349 | 350 | 351 | 354 | 358 | 359 | 360 | 363 | 367 | 368 | 369 | 372 | 376 | 377 | 378 | 381 | 385 | 386 | 387 |
145 | 1 146 | 148 |
function cellCQT = sparse2cell(spCQT,bins,octaveNr,atomNr,firstcenter,atomHOP)
149 | 
150 |
154 | 2 155 | 157 |
% Maps the sparse matrix respresentation of the CQT coefficients back to
158 | 
159 |
163 | 3 164 | 166 |
% the cell representation for inverse transform
167 | 
168 |
172 | 4 173 | 175 |
%
176 | 
177 |
181 | 5 182 | 184 |
%Christian Sch?rkhuber, Anssi Klapuri 2010-06
185 | 
186 |
190 | 6 191 | 193 |
194 | 
195 |
199 | 7 200 | 202 |
emptyHops = firstcenter/atomHOP; %void atom hopsizes in the beginning of the temporal kernel
203 | 
204 |
208 | 8 209 | 211 |
cellCQT = cell(octaveNr,1);
212 | 
213 |
217 | 9 218 | 220 |
221 | 
222 |
226 | 10 227 | 229 |
for i=1:octaveNr
230 | 
231 |
235 | 11 236 | 238 |
    dropped = emptyHops*2^(octaveNr-i)-emptyHops;
239 | 
240 |
244 | 12 245 | 247 |
    X = full(spCQT(bins*octaveNr-i*bins+1:bins*octaveNr-(i-1)*bins,1:2^(i-1):end));
248 | 
249 |
253 | 13 254 | 256 |
    X = [zeros(bins,dropped) X]; 
257 | 
258 |
262 | 14 263 | 265 |
    X = [X zeros(bins,ceil(size(X,2)/atomNr)*atomNr-size(X,2))];
266 | 
267 |
271 | 15 272 | 274 |
    if atomNr > 1 %reshape
275 | 
276 |
280 | 16 281 | 283 |
        Xcell = zeros(bins*atomNr,ceil(size(X,2)/atomNr));    
284 | 
285 |
289 | 17 290 | 292 |
        for u=1:bins;  
293 | 
294 |
298 | 18 299 | 301 |
            Xbin = reshape(X(u,:),atomNr,length(X(u,:))/atomNr);
302 | 
303 |
307 | 19 308 | 310 |
            Xcell((u-1)*atomNr+1:u*atomNr,:) = Xbin;
311 | 
312 |
316 | 20 317 | 319 |
        end      
320 | 
321 |
325 | 21 326 | 328 |
        cellCQT{i} = Xcell;
329 | 
330 |
334 | 22 335 | 337 |
    else
338 | 
339 |
343 | 23 344 | 346 |
        cellCQT{i} = full(X);
347 | 
348 |
352 | 24 353 | 355 |
    end
356 | 
357 |
361 | 25 362 | 364 |
end
365 | 
366 |
370 | 26 371 | 373 |
374 | 
375 |
379 | 27 380 | 382 |
383 | 
384 |
388 |
389 | 390 | 391 | 392 | 393 |
394 |
395 |
396 |
397 | 398 | 399 | 400 | 401 | 406 |
407 |
408 | 409 | 410 | 411 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Constant-Q Transform Toolbox for Python/MATLAB 2 | 3 | ## Introduction 4 | 5 | A Python/MATLAB reference implementation of a computationally efficient method for computing the constant-Q transform (CQT) of a time-domain signal. 6 | 7 | Note: I just translate the core original MATLAB codes (`/MATLAB/*.m`) to Python version (`/CQT.py`) with following functions: 8 | 9 | - Core: 10 | - `cqt` 11 | - `icqt` 12 | - `genCQTkernel` 13 | - `getCQT` 14 | - `cell2sparse` 15 | - `sparse2cell` 16 | - `plotCQT` 17 | 18 | - Extra bonus: 19 | - `buffer` 20 | - `upsample` 21 | - `round_half_up` 22 | - `nextpow2` 23 | - `hann` 24 | 25 | See the authors' homepage for more information and MATLAB packaged downloads: 26 | 27 | - https://code.soundsoftware.ac.uk/projects/constant-q-toolbox 28 | 29 | Or you can read my blog post (Chinese) for inspriation: 30 | 31 | - [恒 Q 变换 (Constant-Q transform)](https://iphysresearch.github.io/blog/post/signal_processing/cqt/) 32 | 33 | ## Related publications 34 | 35 | > C. Schörkhuber and A. Klapuri, “Constant-Q transform toolbox for music processing,” in Proceedings of the 7th Sound and Music Computing Conference, Barcelona, Spain, 2010. [PDF](https://www.researchgate.net/publication/228523955) or [Constant-Q_transform_toolbox_for_music_processing.pdf](./Constant-Q_transform_toolbox_for_music_processing.pdf) 36 | 37 | 38 | ## Requirements 39 | 40 | - Python 3.6+ 41 | - Numpy 42 | - Scipy 43 | - Matplotlib 44 | 45 | ## Demo 46 | 47 | Note: It might not be as efficient than the original MATLAB version, partly because the sparse property have yet to be fully utilised in this Python version. 48 | 49 | ```python 50 | from CQT import * 51 | fname = './demo.dat' 52 | data = np.loadtxt(fname) 53 | t, hp, hc = data[:,0], data[:,1], data[:,2] 54 | 55 | fs = 1/(t[1]-t[0]) 56 | print('fs =', fs) 57 | 58 | bins_per_octave = 24 59 | fmax = 400 60 | fmin = 20 61 | 62 | Xcqt = cqt(hp, fmin, fmax, bins_per_octave, fs,) 63 | _ = plotCQT(Xcqt, fs, 0.6) 64 | 65 | y = icqt(Xcqt) 66 | ``` 67 | 68 | ![](https://vip2.loli.net/2020/12/21/YDfP76rzkubgdaC.png) 69 | 70 | 71 | ## License 72 | 73 | MIT --------------------------------------------------------------------------------