202 lines · 4.6 KB · Text
RawDownload
#+TITLE: Smoother* Overview.=smoother= is a one-pole smoothing filter. The smoothing filter, sometimes called a portamento filteris an indispensible tool for a sound designer. Mostlyused to smooth out steppy control signals, smoothing filtersare a particular kind of one-pole recurisve IIR filter,usually with parametric smoothing control amount. Signalsthat go through smoothing filters get a distinct syruppyresponsiveness added to it (especially if you set thesmoothing amount way up!). While smoothing filters usually have an association withsmoothing out control signals from things like MIDI CCknobs, there are a few other useful things you can do withthem. If you put audio-rate signal with note values throughit, you get a really lovely legato portamento effect. A gatesignal put through a smoothing filter produces an envelopewith the most beautiful exponential curves perfect for shortpercusive sounds.* Tangled Files=smoother.c= and =smoother.h=. =SK_SMOOTHER_PRIV= exposes thestruct. #+NAME: smoother.h#+BEGIN_SRC c :tangle smoother.h#ifndef SK_SMOOTHER_H#define SK_SMOOTHER_H #ifndef SKFLT#define SKFLT float#endif <<typedefs>> #ifdef SK_SMOOTHER_PRIV<<structs>>#endif <<funcdefs>> #endif#+END_SRC #+NAME: smoother.c#+BEGIN_SRC c :tangle smoother.c#include <math.h>#define SK_SMOOTHER_PRIV#include "smoother.h"<<funcs>>#+END_SRC* The EquationThe one pole smoothing filter employs the followingdifference equation: @!(fig "smoother_eqn"``y(n) = b_0 x(n) - a_1 y(n - 1)``)!@ Where @!(smallfig "smoother_a1" "a_1")!@ is @!(smallfig "smoother_a1_eqn" "0.5^{1/(tF_s)}")!@ and @!(smallfig "smoother_b0" "b_0")!@ is @!(smallfig "smoother_b0_eqn" "{1 - a_1}")!@. Thevariables @!(smallfig "smoother_t" "t")!@ and @!(smallfig"smoother_fs" "F_s")!@ are the smoothing half time andsampling rate, respectively. @!(smallfig "smoother_xn""x(n)")!@ is the input signal.* Struct Initialized=sk_smoother= is the struct. #+NAME: typedefs#+BEGIN_SRC ctypedef struct sk_smoother sk_smoother;#+END_SRC It is initalized with =sk_smoother_init=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_smoother_init(sk_smoother *s, int sr);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_smoother_init(sk_smoother *s, int sr){    <<init>>}#+END_SRC* Struct Contents#+NAME: structs#+BEGIN_SRC cstruct sk_smoother {    SKFLT smooth;    SKFLT a1, b0, y0, psmooth;    SKFLT onedsr;};#+END_SRC =smooth= is the smoothing parameter, with =psmooth= beinga cached variable that is used to check when the smoothparameter has changed. =smooth= is set to a reasonable default value of 10ms.=psmooth= is set to a different (and also invalid) value of-1. This will caused the filter coefficients to becalculated when the compute function is called forthe first time. #+NAME: init#+BEGIN_SRC cs->smooth = 0.01;s->psmooth = -1;#+END_SRC =a1= and =b0= are filter coefficients computed from the=smooth= time parameter, with =y0= being the filter memory. #+NAME: init#+BEGIN_SRC cs->a1 = 0;s->b0 = 0;s->y0 = 0;#+END_SRC =onedsr= is the constant =1.0/sr=. This might not actuallybe all that helpful since a divide operation is stillhappening. Hmm. #+NAME: init#+BEGIN_SRC cs->onedsr = 1.0 / sr;#+END_SRC* Setting Smoothing TimeSet the smoothinb time parameter with =sk_smoother_time=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_smoother_time(sk_smoother *s, SKFLT t);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_smoother_time(sk_smoother *s, SKFLT t){    s->smooth = t;}#+END_SRC The smoothing time, also known as the half time, is theamount of time (in seconds) it takes to go to halfway tothe trajectory value.* Resetting The Filter=sk_smoother_reset= will reset the smoothing filter, causingit to snap directly to the value =in=. #+NAME: funcdefs#+BEGIN_SRC cvoid sk_smoother_reset(sk_smoother *s, SKFLT in);#+END_SRC #+NAME: funcs#+BEGIN_SRC cvoid sk_smoother_reset(sk_smoother *s, SKFLT in){    s->y0 = in;}#+END_SRC* ComputeCompute a sample with =sk_smoother_tick=. This expects aninput signal, and returns a single output signal. #+NAME: funcdefs#+BEGIN_SRC cSKFLT sk_smoother_tick(sk_smoother *s, SKFLT in);#+END_SRC This is implementing the equation displayed above.Parameter caching is used so that filter coefficientsare only updated when the smoothing amount updates.Doing this shaves off a few redundant CPU instructions. #+NAME: funcs#+BEGIN_SRC cSKFLT sk_smoother_tick(sk_smoother *s, SKFLT in){    SKFLT out;     if (s->psmooth != s->smooth) {        s->a1 = pow(0.5, s->onedsr/s->smooth);        s->b0 = 1.0 - s->a1;        s->psmooth = s->smooth;    }     s->y0 = s->b0 * in + s->a1 * s->y0;    out = s->y0;     return out;}#+END_SRC

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t