FastLED 3.9.15
Loading...
Searching...
No Matches
cq_kernel Directory Reference
+ Directory dependency graph for cq_kernel:

Files

 _kiss_fft_guts.h
 
 cq_kernel.c
 
 cq_kernel.h
 
 kiss_fft.c
 
 kiss_fft.h
 
 kiss_fftr.c
 
 kiss_fftr.h
 

Detailed Description

A fast C library that generates and applies spectral kernels on the output of an FFT, resulting in a constant Q transform overall and as specified in "An efficient algorithm for the calculation of a constant Q transform" by Brown (google it for reference). It is dependent on kissfft, so the v131 release is bundled here, but it can also be applied on the output of any FFT program.

While initalizing, this library is relatively slow and memory-heavy: it needs to execute an FFT for one band at a time, requiring two buffers for its real input and complex output. However, the library uses a little less (and not much more) at runtime by storing all the kernels as sparse arrays (throwing out the smallest values). Sparse arrays also make the library very fast at runtime, so embedded use is possible.

An example has been provided. Using #define'd parameters, it generates and dumps its kernels in a format that can be pasted into Excel or MATLAB. To get the floating-point version, in the command line run:

make example
./bin/example

To get the Q15 version, in the command line run:

make example CFLAGS="-D FIXED_POINT=16"
./bin/example

There is a Q31 version that is currently broken. To try that, in the command line run:

make example CFLAGS="-D FIXED_POINT=32"
./bin/example

Here is what that Excel plot of the kernels ("K_mag.txt") looks like. It is very similar to Figure 2 in the CQT paper:

Plot of output from example.c

Be warned, making the maximum frequency too close to half the sampling frequency causes the kernels to degenerate. Not having enough samples also causes the kernels to degenerate, so please edit, compile, then run the example to make sure your desired parameters are valid!

Now, to use this library in a project, retrieve the files

_kiss_fft_guts.h
cq_kernel.c
cq_kernel.h
kiss_fft.c
kiss_fft.h
kiss_fftr.c
kiss_fftr.h

and write something like this (if you're using the included kissfft library)

#include "kiss_fftr.h"
#include "cq_kernel.h"
int main(){
struct cq_kernel_cfg cq_cfg = {
.samples = SAMPLES,
.bands = BANDS,
.fmin = MIN_FREQUENCY,
.fmax = MAX_FREQUENCY,
.min_val = MIN_VAL
};
kiss_fft_cfg fft_cfg = kiss_fftr_alloc(SAMPLES, 0, NULL, NULL);
cq_kernels_t kernels = generate_kernels(cq_cfg);
kernels = reallocate_kernels(kernels, cq_cfg); // optional
while(1){
// <Generate/retreive "in" signal here>
kiss_fftr(fft_cfg, in, fft);
kiss_fft_cpx cq[BANDS] = {0};
apply_kernels(fft, cq, kernels, cq_cfg);
// <Process "cq" output here>
}
free(fft_cfg);
free_kernels(kernels, cq_cfg)
return 0;
}
AudioAnalyzeFFT1024 fft
void free_kernels(struct sparse_arr *kernels, struct cq_kernel_cfg cfg)
Definition cq_kernel.c:150
void apply_kernels(kiss_fft_cpx fft[], kiss_fft_cpx cq[], struct sparse_arr kernels[], struct cq_kernel_cfg cfg)
Definition cq_kernel.c:140
struct sparse_arr * generate_kernels(struct cq_kernel_cfg cfg)
Definition cq_kernel.c:88
struct sparse_arr * reallocate_kernels(struct sparse_arr *old_ptr, struct cq_kernel_cfg cfg)
Definition cq_kernel.c:128
struct sparse_arr * cq_kernels_t
Definition cq_kernel.h:59
#define MIN_VAL
Definition fft_impl.cpp:32
#define BANDS
Definition fft_impl.cpp:28
#define MAX_FREQUENCY
Definition fft_impl.cpp:30
#define SAMPLING_FREQUENCY
Definition fft_impl.cpp:29
#define SAMPLES
Definition fft_impl.cpp:27
#define MIN_FREQUENCY
Definition fft_impl.cpp:31
struct kiss_fft_state * kiss_fft_cfg
Definition kiss_fft.h:77
void kiss_fftr(kiss_fftr_cfg st, const kiss_fft_scalar *timedata, kiss_fft_cpx *freqdata)
Definition kiss_fftr.c:67
kiss_fftr_cfg kiss_fftr_alloc(int nfft, int inverse_fft, void *mem, size_t *lenmem)
Definition kiss_fftr.c:21

and compile it with the appropriate flag based on the desired format, as required by kissfft. There is no flag for floating point. For Q15, that is -D FIXED_POINT=16. For Q31, that is -D FIXED_POINT=32.