Extension

Calculate a single DFT bin, to detect presence of a frequency

Source: MCLDFilterUGens.sc

The Goertzel algorithm is a way to calculate the magnitude and phase of a signal's content at a single specified frequency. It's the equivalent of running an FFT, and then only looking at the output corresponding to a single bin. If you're only interested in a small number of bins then it is more efficient; if you're interested in the majority of bins, you typically want to do an FFT instead.

in | |

bufsize |
used in the same way as an FFT buffer size - the larger this value, the better the frequency resolution, but the worse the time resolution. |

freq |
target frequency. This can not be modulated. |

hop |
same meaning as in the FFT UGen. Supply a value between zero and one, for the amount of overlap between Goertzel "frames". The default is a hop of 1 (meaning no overlap between frames). If you specify 0.5 then the analysis value will be produced twice as often; 0.25, four times as often. |

s.boot ( x = { var freq, amp, sig, real, imag, mag, bufsize=4096; // try changing freq to a matching or nonmatching frequency to what we're looking for freq = 220; // or try MouseY.kr(110, 440, 1); amp = MouseX.kr; sig = SinOsc.ar(freq, 0, amp); # real, imag = Goertzel.kr(sig, bufsize, 220); // Calc the magnitude. We also normalise it against buffer size here. mag = (real.squared + imag.squared).sqrt * (bufsize / 2).reciprocal; amp.poll(label: "Input amplitude"); mag.poll(label: "Measured amplitude"); (sig * 0.1).dup }.play ) // This one is similar but on control-rate data: ( x = { var freq, amp, sig, real, imag, mag, bufsize=100; // try changing freq to a matching or nonmatching frequency to what we're looking for freq = 22; // or try MouseY.kr(11, 44, 1); amp = MouseX.kr; sig = SinOsc.kr(freq, 0, amp); # real, imag = Goertzel.kr(sig, bufsize, 22); // Calc the magnitude. We also normalise it against buffer size here. mag = (real.squared + imag.squared).sqrt * (bufsize / 2).reciprocal; amp.poll(label: "Input amplitude"); mag.poll(label: "Measured amplitude"); (sig * 0.1).dup }.play ) // OK, now let's do a kind of spectrogram, but focused on a specific frequency region of interest ( ~binfreqs = (300, 310 .. 400); w = Window.new.front; m = MultiSliderView(w,Rect(10,10,~binfreqs.size*13+2,100)); //default thumbWidth is 13 ~bus = Bus.control(s, ~binfreqs.size); x = { var sig, mags, bufsize=4096, real, imag; sig = SinOsc.ar(MouseX.kr(~binfreqs.first, ~binfreqs.last)); mags = ~binfreqs.collect{|binfreq| # real, imag = Goertzel.kr(sig, bufsize, binfreq); (real.squared + imag.squared).sqrt * (bufsize / 2).reciprocal; }; Out.kr(~bus, mags); (sig * 0.1).dup }.play; t = Task{ loop{ 0.1.wait; ~bus.getn(~binfreqs.size, {|vals| {m.value = vals}.defer; }) } }.play; w.onClose_{~bus.free; x.free; t.stop; }; ) w.close;

helpfile source: /usr/local/share/SuperCollider/Extensions/SC3plugins/MCLDUGens/HelpSource/Classes/Goertzel.schelp

link::Classes/Goertzel::

link::Classes/Goertzel::