tierneytim / btAudio

Bluetooth Audio for Arduino
211 stars 30 forks source link

Equalizer idea #3

Open Szelwin opened 3 years ago

Szelwin commented 3 years ago

Hi! First of all - thank you so much for your work. It's awesome and it's simple to use, I'm using it for my BT Speaker project. I tried to code it the normal way using ESP32 SDK, but I'm only a beginner and I couldn't handle it. I'm just curious - is there any way to use your filters as an equalizer? They already exist, someone would "just" have to add a gain setting. I'd do it myself, but I don't have any idea how to start. If you could just point me in the right direction, maybe I'd manage. Thanks again, keep up the good work!

tierneytim commented 3 years ago

Thanks, glad you like it!

You could add EQUALISE option here and then apply the highpass and lowpass filters together successively but that might get ugly. I think it would be better to directly implement the biquad bandpass filter and then write an equaliser class that would call the bandpass filter multiple times, set the gains for each band and then sum the results. You'd also need to set the Q values based on the desired bandwidth and centre frequency. The maths is described here.

If all that was implemented (which shouldn't be horrendously difficult) how do you think this would work? Would you want user control of the bands (number and frequency ranges) or would a fixed number of bands and ranges be OK? If so what would the frequency ranges be?

Szelwin commented 3 years ago

Thanks for replying so fast! I did some research. My approach would be to just use the code for biquad filters you linked. Usage of this code is: Biquad *filter = new Biquad(type, Fc, Q, gain); filter->process(data); For multiple filters, it is filter2->process(filter1->process(data)); A standard EQ only needs 3 filters - low, mid, high. In my opinion this would need to go like lowpass -> bandpass -> highpass Every stage should contain about 3 filters for different Fc if you ask me, but I don't know how this would work in terms of computing power. Imo, user usage should look like: EQ.set(lowGain, midGain, highGain); EQ.start(); The EQ.set() command would need to be called every time user wants a change. I think fixed number of bands and ranges would be OK. Also, I see one problem. When you use a lowpass filter, you suppress the higher frequencies, right? And vice versa. It makes me question going in this direction. Sorry if this is all nonsense - I'm just a PCB designer with no experience with audio whatsoever. What do you think?

tierneytim commented 3 years ago

Also, I see one problem. When you use a lowpass filter, you suppress the higher frequencies, right? And vice versa. It makes me question going in this direction.

Yes, you shouldn't apply them like that because the lowpass will eliminate the mid and high bands. instead, you can apply them each to the same input and sum the result.

low = filter1.process(data)*gain1;
mid = filter2.process(data)*gain2;
high = filter3.process(data)*gain3;
output=  low+ mid+ high // need to do an overflow check here as filters aren't independent. 

Computing should be fine as it is just 1 extra filter to what I normally do meaning it should be reasonably easy to implement.

no need to apologise I'm no audio expert either, I just like messing with microcontrollers. I might have a go at this tomorrow and see how far I get. In the meantime, if you make any developments just let me know.