6.2 FX in Practice

# FX in Practice

Although they look deceptively simple on the outside, FX are actually
quite complex beasts internally. Their simplicity often entices people
to overuse them in their pieces. This may be fine if you have a
powerful machine, but if - like me - you use a Raspberry Pi to jam
with, you need to be careful about how much work you ask it to do if
you want to ensure the beats keep flowing.

Consider this code:

```
loop do
  with_fx :reverb do
    play 60, release: 0.1
    sleep 0.125
  end
end
```

In this code we're playing note 60 with a very short release time, so
it's a short note. We also want reverb so we've wrapped it in a reverb
block. All good so far. Except...

Let's look at what the code does. First we have a `loop` which means
everything inside of it is repeated forever. Next we have a `with_fx`
block. This means we will create a new reverb FX *every time we
loop*. This is like having a separate FX reverb pedal for every time you
pluck a string on a guitar. It's cool that you can do this, but it's not
always what you want. For example, this code will struggle to run nicely
on a Raspberry Pi. All the work of creating the reverb and then waiting
until it needs to be stopped and removed is all handled by `with_fx` for
you, but this takes CPU power which may be precious.

How do we make it more similar to a traditional setup where our
guitarist has just *one* reverb pedal which all sounds pass through?
Simple:

```
with_fx :reverb do
  loop do
    play 60, release: 0.1
    sleep 0.125
  end
end
```

We put our loop *inside* the `with_fx` block. This way we only create
a single reverb for all notes played in our loop. This code is a lot
more efficient and would work fine on a Raspberry Pi.

A compromise is to use `with_fx` over an iteration within a loop:

```
loop do
  with_fx :reverb do
    16.times do
      play 60, release: 0.1
      sleep 0.125
    end
  end
end
```

This way we've lifted the `with_fx` out of the inner part of the `loop`
and we're now creating a new reverb every 16 notes.

This is such a common pattern that `with_fx` supports an opt to do
exactly this but without having to write the `16.times` block:

```
loop do
  with_fx :reverb, reps: 16 do
    play 60, release: 0.1
    sleep 0.125
  end
end
```

Both the `reps: 16` and `16.times do` examples will behave
identically. The `reps: 16` essentially repeats the code in the `do/end`
block 16 times so you can use them both interchangeably and choose the
one that feels best for you.

Remember, there are no mistakes, just possibilities. However, some of
these approaches will have a different sound and also different
performance characteristics. So play around and use the approach that
sounds best to you whilst also working within the performance
constraints of your platform.
