lokki just some quick questions
In the video 16 bands.
Yes, the code is easily adjustable for more or less bands and specific frequencies and Q. You can do all of this from within setup()
in render.cpp
.
For number of bands just change these lines in setup()
:
int bands = 16;
float fstart = 150.0;
float fstop = 4000.0;
vcd = make_vocoder(vcd, fs, nsamps, bands, fstart, fstop);
fstart and fstop don't matter if you are going to set these explicitly (default behavior is to log-space the bands from fstart to fstop)
Setting specific frequencies is also easy but I doubt it is intuitive how to do this unless you understand the code. Here's a crash course: To select a specific frequency and Q for a specific band, you need to make a call to the following explicitly on the band of interest after you have created the filterbanks with make_vocoder(vcd, fs, nsamps, bands, fstart, fstop);
:
// from eq.h, eq.cpp
void
eq_compute_coeffs(eq_coeffs* cf, int type, float fs, float f0, float Q, float G)
You access the pointer to the eq coefficients from the vocoder struct like this:
//Make sure you do _m and _c alike or you will have mismatch between carrier and modulator (which could be a somewhat cool effect if you did it on purpose)
eq_compute_coeffs(vcd->filterbank_m->band[n], BPF, SAMPLE_RATE, f0, Q, Gain);
eq_compute_coeffs(vcd->filterbank_c->band[n], BPF, SAMPLE_RATE, f0, Q, Gain);
Header file"eq.h"
is included from render.cpp
, so you can make this call in setup()
without having to drill deeper or create helper functions in vocoder.cpp
.
I'm working in the background to try to rework it into something a little more neat and efficient.
One of the untidy things in the code is the bandpass does not give zero dB at pass-band so you will notice the gain is a bit hot. It gets hotter as you increase Q. I have got out the mechanical pencil and paper to work this out from the basics but for now you can work around it by adding manual filter gain control. Center frequency and Q are correct.
I have been looking at more analog vocoder circuits. It appears to be more common that vocoder circuits use 8th order filters (I am only using 2nd order). One example I found recently is the Jurgen Haible vocoder:
http://www.jhaible.info/vocoder/living_vocoder.html
Also a really cool discovery I made is @andrew McPherson was involved in the design and construction of what appears to be very ambitious analog vocoder and harmonizer unit. This one also uses 8th order filters.
http://www.eecs.qmul.ac.uk/~andrewm/composer/media/vocoder.pdf
My current implementation uses roughly 30% CPU, so I can't possibly run 8th order filters on this many channels with the current implementation, so I'm refactoring for better efficiency and make it so I can run the audio analysis chain at lower processing sample rates.
I have succeeded in developing the formulae for correct stagger-tuned filters, so this is the first step toward creating well-behaved higher order filters. Below is the 4rth order but, going to 8th-order is a simple matter of cascading two 4rth-order stages.

I'm thinking it may be possible to do 8th-order filters if I improve code efficiency, run analysis bands and envelope detectors at lower processing sample rates. I suppose I will find out when I get to that point.
In the meantime, this implementation still sounds good enough to be fun.