Fade out with the Go Button

Hello,

I am working in a musical theater setting.
I would need at some point a very short fade out (0,5 sec or so). I would like to trigger this with my foot switch that is mapped to my Go Button.

The fade out happens every time at a slightly different place, that’s why I need the flexibility. Also, after the fade out I would like that it jumps to the start of the next song, so that when I trigger the foot switch the next time, the next song starts.

Is there a way of achieving this?

Thank you very much and best,
Nathan

Hey @Nathan_Shelley,

This gets at something worth explaining.

The Go Button isn’t a single command; it’s a context-aware action that already does four different things depending on the state of your set:

  • Stopped at the end of a song → jumps to the next song
  • Stopped inside a song → starts playback
  • Playing in a loop → escapes the loop
  • Playing with a song/section queued → instantly jumps to it

Your fade-out is essentially a fifth behaviour — but it only makes sense in one specific state: playing normally, with no loop and nothing queued. So the script can’t just “be the Go Button and also fade” — while playing, Go already has a job. What it can do is replicate each of Go’s branches explicitly, and slot the fade-out into that one free state.

Here’s a MIDI mapping script you can try:

// Footswitch — Go Button behaviour + fade-out on a normal press.

// --- Tweak these to taste ---
const GROUP      = "yourgroupname";  // mixer group to fade, exact name as in the Mixer, must be lowercase
const FADE_SPEED = 0.1;       // fadeTo multiplier. lower = shorter fade. Adjust to taste.
const FADE_WAIT  = 700;       // ms to wait for the fade before stopping

const playing   = osc("/global/isPlaying");
const looping   = osc("/setlist/loopEnabled");
const queued    = osc("/setlist/queuedName", "all") ?? [];  // [song, section]
const hasQueued = queued.some(v => v);

if (!playing) {
  // Stopped → normal Go (next song / start playback)
  sendOsc("/setlist/go");
} else if (looping) {
  // Playing in a loop → escape the loop, like Go
  sendOsc("/loop/escape");
} else if (hasQueued) {
  // Playing with a queued jump → jump instantly, like Go
  sendOsc("/setlist/jumpToQueued", true);
} else {
  // Playing normally → fade out and move to the next song
  const vol = osc(`/mixer/${GROUP}/volume`);          // remember current volume
  sendOsc(`/mixer/${GROUP}/fadeTo`, 0, FADE_SPEED);   // fade group to silence
  await sleep(FADE_WAIT);                             // wait for the fade
  sendOsc("/global/stop");                            // stop playback
  await sleep(200);                                   // let AbleSet register the stop
  sendOsc("/setlist/jumpBySongs", int(1));            // cue the next song's start
  sendOsc(`/mixer/${GROUP}/volume`, vol);             // restore volume for next song
}

With this, the footswitch behaves exactly like your Go Button: escaping loops, jumping to queued songs/sections, and only does the fade-out when you’re playing a song normally.

One thing to be aware of: while a loop is active, a press escapes the loop (just like Go), so it won’t fade out at that moment. If you want to fade out from inside a loop, escape the loop first, then press again.

Would that work for your use case?

2 Likes

It works perfectly. Thank you so much.

The only thing, is there a way to control more than one group with it. When I tried to do the same fade out, with more than one group, let’s say [“tracks”, “sfx”], it didn’t work anymore…

But other than that… wow.
Thanks again.

Hey @Nathan_Shelley,

Glad it’s working! And yes, fading multiple groups is just a matter of looping over them. The /mixer/<group>/... paths only take one group name at a time, so passing an array won’t work, but you can iterate over a list and AbleSet will fade them all in parallel.

Here’s an updated version of the script you can try:

// Footswitch — Go Button behaviour + fade-out on a normal press.

// --- Tweak these to taste ---
const GROUPS     = ["PISTAS", "SFX"];  // mixer groups to fade — exact names as in the Mixer
const FADE_SPEED = 0.1;                // fadeTo multiplier — lower = shorter fade
const FADE_WAIT  = 700;                // ms to wait for the fade before stopping

const playing   = osc("/global/isPlaying");
const looping   = osc("/setlist/loopEnabled");
const queued    = osc("/setlist/queuedName", "all") ?? [];  // [song, section]
const hasQueued = queued.some(v => v);

if (!playing) {
  // Stopped → normal Go (next song / start playback)
  sendOsc("/setlist/go");
} else if (looping) {
  // Playing in a loop → escape the loop, like Go
  sendOsc("/loop/escape");
} else if (hasQueued) {
  // Playing with a queued jump → jump instantly, like Go
  sendOsc("/setlist/jumpToQueued", true);
} else {
  // Playing normally → fade out and move to the next song

  // Remember each group's current volume, then start the fade
  const volumes = {};
  for (const g of GROUPS) {
    volumes[g] = osc(`/mixer/${g}/volume`);
    sendOsc(`/mixer/${g}/fadeTo`, 0, FADE_SPEED);
  }

  await sleep(FADE_WAIT);                       // wait for the fade
  sendOsc("/global/stop");                      // stop playback
  await sleep(200);                             // let AbleSet register the stop
  sendOsc("/setlist/jumpBySongs", int(1));      // cue the next song's start

  // Restore each group's volume for the next song
  for (const g of GROUPS) {
    sendOsc(`/mixer/${g}/volume`, volumes[g]);
  }
}

Just add or remove entries in the GROUPS array, as they appear in the Mixer. All groups should fade simultaneously.

Hope that helps!