# How to implement a tranceGate control pattern in TidalCycles?

**URL:** <https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966>\
**Category:** TidalCycles\
**Tags:** questions\
**Created:** [16 October 2025 01:01 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966 "2025-10-16T01:01:08Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![a00](https://uzu.lurk.org/user_avatar/uzu.lurk.org/a00/32/3341_2.png) [@a00](https://uzu.lurk.org/u/a00)\
**Post date:** [16 October 2025 01:01 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/1 "2025-10-16T01:01:08Z")

</div>

I am trying to implement a tranceGate function in TidalCycles that applies a classic trance-style gating effect directly as a ControlPattern, to be used like this:

```haskell
d1 $ n "0" # s "supersaw" # tranceGate 0.05 "1[11]0"

```

The function should interpret a string of symbols per cycle, where each symbol represents a step in the gate:

- `1` means: gradually release the current sound’s gain down to 0 over a linear duration specified by `r` (in seconds), then immediately return its gain to the level it had before the gate affected it.
- `0` means: rest for that step, leaving the volume completely untouched — whatever sound is playing continues naturally.

The number and grouping of symbols define subdivision within the cycle. Bracketed groups like `"[11]"` should be treated as compressed steps within a single slice of the cycle (e.g., `"1[11]0"` creates a different rhythmic gate density than `"1110"`). The release time `r` should remain constant regardless of symbol density, just like a standard envelope release in melodic patterns.

My goal is not random chopping but precise, deterministic gating based on the step sequence. The resulting function should produce rapid rhythmic stutters typical of trance gates, not full-cycle silences or long sustained fades.

I have attempted several implementations, including bracket parsing and envelope construction, but so far the output results in entire-cycle fades or silence instead of step-level gating. Here is my most recent attempt:

```haskell
let
  tranceGate :: Double -> String -> Pattern Double
  tranceGate r s = cat $ map symbolToPattern (concatMap expandGroup (parseBrackets s))
    where
      symbolToPattern '1' = fast 1 $ cat [pure 1, slow (pure $ toRational r) (pure 0), pure 1]
      symbolToPattern '0' = pure 1
      symbolToPattern _ = pure 1
      parseBrackets [] = []
      parseBrackets ('[':xs) =
        let (grp, rest) = span (/= ']') xs
        in grp : parseBrackets (drop 1 rest)
      parseBrackets (x:xs) = [x] : parseBrackets xs
      expandGroup grp = if length grp > 1
                        then map id grp
                        else grp
in do
  panic
  d1 $ n "0" # s "supersaw" # gain (tranceGate 0.05 "1[11]0")
  d2 $ s "kick:8*4"

```

I have been stuck on this for days. Every variation either produces full-cycle sounds and rests or removes the sound entirely. How can I correctly implement `tranceGate` so that it:

- Interprets symbols per cycle with bracket grouping,

- Applies step-level gating with linear release (`r` seconds),

- Restores volume instantly after each gated step,

- Works as a proper `ControlPattern` chained with `#`

Any guidance or working approach would be greatly appreciated.

---

<div class="post-metadata">

**Author:** ![jwaldmann](https://uzu.lurk.org/letter_avatar_proxy/v4/letter/j/977dab/32.png) [@jwaldmann](https://uzu.lurk.org/u/jwaldmann)\
**Post date:** [16 October 2025 13:31 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/2 "2025-10-16T13:31:01Z")

</div>

> gradually release ...

so the `gain` parameter will go through a sequence of steps. if you don't want to break the structure of the original pattern (re-trigger a long-running sample, a synthesizer with long sustain), you need control busses [https://tidalcycles.org/docs/reference/control\_busses](https://tidalcycles.org/docs/reference/control_busses) .  
note that `gain` cannot be bussed, but `amp` can.

> parseBrackets ...

You are re-implementing mini-notation here. Don't. Just write patterns for the argument of `ampbus`.

Example (with long-running sample) :

```haskell
let down s = fastcat $ map (\ k -> pure $ fromRational (k % s)) $ reverse [0 .. s]
    d = down 3
    k = pure 1
in d1 $ (s "led" # end 0.21)
       # ampbus 42 (slow 4 $ cat [d, fastcat [d, d], k ])
       # lpfbus 43 (slow 3 $ cat [4000, 100, 200])

```

(I cannot test with supersaw right now since my synths seem broken. There was a Fedora package `sc3-plugins` but that's gone? [https://bugzilla.redhat.com/show\_bug.cgi?id=2154432](https://bugzilla.redhat.com/show_bug.cgi?id=2154432) Guess I need to build from source )

---

<div class="post-metadata">

**Author:** ![a00](https://uzu.lurk.org/user_avatar/uzu.lurk.org/a00/32/3341_2.png) [@a00](https://uzu.lurk.org/u/a00)\
**Post date:** [18 October 2025 08:30 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/3 "2025-10-18T08:30:39Z")

</div>

I am very interested in a programmable trance gate in **TidalCycles** similar to the effect demonstrated by **Switch Angel** in this video: [https://youtu.be/GWXCCBsOMSg?si=cibHjK\_wpuwtg3um](https://youtu.be/GWXCCBsOMSg?si=cibHjK_wpuwtg3um)

The corresponding **Strudel** implementation in **JavaScript** is available here: [https://github.com/switchangel/strudel-scripts/blob/main/allscripts.js](https://github.com/switchangel/strudel-scripts/blob/main/allscripts.js). While it works effectively, it is entirely random-driven, with gate openings and closings determined by a pseudorandom generator. What I am looking for goes beyond that: a trance gate where it is possible to explicitly control when gates open and close, how long they remain in each state, and optionally apply pseudorandom variation to any of these controls.

A fully programmable trance gate should be part of the **TidalCycles** standard library. Such a function would be a fundamental tool for rhythmic gating in electronic music and would benefit the entire community.

As someone who recently discovered **TidalCycles** and without experience in **Haskell** or **JavaScript** , I am seeking guidance, examples, or a native **Tidal** implementation that could achieve this level of control.

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [19 October 2025 11:22 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/4 "2025-10-19T11:22:01Z")

</div>

I’m not clear on what a trancegate is, but from the code it seems to be `struct` plus randomisation. So maybe if you don’t want the randomisation then you just want `struct`?

_edit_ ah reading your description I understand this a bit more.. I don’t fully understand Jade’s implementation, but I’ll have a go at it in tidal..

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [19 October 2025 11:36 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/5 "2025-10-19T11:36:17Z")

</div>

Do you mean something like this?

```haskell
trancegate :: Pattern Bool -> ControlPattern -> ControlPattern
trancegate s pat = squeezeJoin $ f <$> s
  where f False = pat
        f True = pat # (segment 32 $ ampbus 1 isaw)

d1 $ trancegate "[1 0]*2 [1 0 1]*2" $ note ("<c'major'4 c'minor'5>") # sound "supersaw"

```

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [19 October 2025 11:53 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/6 "2025-10-19T11:53:09Z")

</div>

This seems closer to your description.. The envelope is fixed rather than proportional to event duration (although in cycles, not seconds).

```haskell
let trancegate :: Pattern Time -> Pattern Bool -> ControlPattern -> ControlPattern
    trancegate r s pat = trigZeroJoin $ f <$> s
      where f False = pat
            f True = pat # (segment 32 $ ampbus 1 $ slow r envLR)
in            
  d1 $ trancegate 0.1 (slow 2 "0 [1 1 1]@2 1*6")
   $ note ("<c'major'4 c'minor'5>") # sound "supersaw"

```

It’s using an effects bus, so if this is used more than once at the same time, ampbus would need to be passed different bus numbers.

---

<div class="post-metadata">

**Author:** ![a00](https://uzu.lurk.org/user_avatar/uzu.lurk.org/a00/32/3341_2.png) [@a00](https://uzu.lurk.org/u/a00)\
**Post date:** [19 October 2025 16:01 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/7 "2025-10-19T16:01:50Z")

</div>

Thank you very much for your response, I really appreciate your time.

I wanted to clarify more precisely what I’m aiming for with a trance gate in TidalCycles:

- The default state of the gate is **open** , so the sound plays continuously.

- When a specific symbol is encountered (for example **1** ), the gate should begin to **close gradually over a given duration** _r_, with the volume decreasing linearly from the current level to silence.

- **The moment silence is reached** , the gate should **snap instantly back open** , allowing the sound to continue normally.

- When the other symbol appears (for example **0** ), it should **do nothing** , the gate remains open and the sound is passed through unchanged.

The goal is to be able to _explicitly program_ rhythmic closures, such as:  
“close the gate twice very quickly on the first beat, then keep it open for the rest of the cycle.”

Do you think such a controllable gate could be implemented in TidalCycles? Any suggestions or direction would be very helpful.

Thanks again for your support and for all your work on Tidal.

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [19 October 2025 18:50 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/8 "2025-10-19T18:50:37Z")

</div>

Did you listen to the last example? It is quite close to what you want I think.

This is closer still:

```haskell
let trancegate :: Pattern Int -> Pattern Time -> Pattern Bool -> ControlPattern -> ControlPattern
    trancegate busid r s pat = pat # (trigZeroJoin $ f <$> s)
      where snapback = when (<1) (const $ segment 8 isaw) $ pure 1
            f False = pat # ampbus busid 0.5
            f True = (ampbus busid $ slow r $ snapback)
in
  d1 $ (trancegate 1 0.05 (slow 2 "0 1*8 1*4 1*8")
   $ note ("<a3'minor'5 e4'minor'5 g3'major'5 a3'minor'5>") # sound "supersaw")
     # hpfbus 2 (segment 32 $ range 0 1000 perlin)
     # hpq 0.2

```

---

<div class="post-metadata">

**Author:** ![a00](https://uzu.lurk.org/user_avatar/uzu.lurk.org/a00/32/3341_2.png) [@a00](https://uzu.lurk.org/u/a00)\
**Post date:** [20 October 2025 16:20 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/9 "2025-10-20T16:20:23Z")

</div>

Thank you so much, @yaxu! Your `trancegate`solution is by far the best I’ve seen so far. It’s elegant, precise, and captures the step-level gating I was after.

I made a small aesthetic modification so that the `trancegate`can be applied via the `#` operator, which feels more natural in my workflow. Here’s my adapted version:

```haskell
let trancegate :: Pattern Int -> Pattern Time -> Pattern Bool -> ControlPattern
    trancegate busid r s = trigZeroJoin $ f <$> s
      where snapback = when (<1) (const $ segment 8 isaw) $ pure 1
            f False = ampbus busid 0.6
            f True = ampbus busid $ slow r snapback
in do
  d1 $ note ("-14") # sound "supersaw"
    # trancegate 1 0.05 ("1011010110011101") # gain 0.8
  d2 $ s "kick:6*4" -- 4/4 reference

panic

```

Thanks again for your generosity in sharing your knowledge and making TidalCycles such a rich, live-coding ecosystem! 🙏

---

<div class="post-metadata">

**Author:** ![Virginie\_Alison](https://uzu.lurk.org/user_avatar/uzu.lurk.org/virginie_alison/32/3471_2.png) [@Virginie\_Alison](https://uzu.lurk.org/u/Virginie_Alison)\
**Post date:** [19 December 2025 14:57 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/10 "2025-12-19T14:57:25Z")

</div>

Hi yaxu, I’am new here and just started in Strudel, could you please adapt this Transgate version in Strudel language? All my thanks in advance for your help! Virginie from France

---

<div class="post-metadata">

**Author:** ![yaxu](https://uzu.lurk.org/user_avatar/uzu.lurk.org/yaxu/32/2_2.png) [@yaxu](https://uzu.lurk.org/u/yaxu)\
**Post date:** [20 December 2025 15:40 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/11 "2025-12-20T15:40:02Z")

</div>

Hi Virginie, no need! Switch Angel has made the original version available here: [strudel-scripts/prebake.strudel at main · switchangel/strudel-scripts · GitHub](https://github.com/switchangel/strudel-scripts/blob/main/prebake.strudel)

---

<div class="post-metadata">

**Author:** ![Virginie\_Alison](https://uzu.lurk.org/user_avatar/uzu.lurk.org/virginie_alison/32/3471_2.png) [@Virginie\_Alison](https://uzu.lurk.org/u/Virginie_Alison)\
**Post date:** [21 December 2025 07:46 UTC](https://uzu.lurk.org/t/how-to-implement-a-trancegate-control-pattern-in-tidalcycles/5966/12 "2025-12-21T07:46:19Z")

</div>

Thanks a lot yaxu, I already use the Switch Angel Transgate, and il works very well, but I thougth you had made some kind of “variation” with the code above that could have been interesting. If not, I stay on Switch Angel version that is already awfull!!.

Moreover, I had question about looper in Strudel, but I an going to ask you in the correspondant topic.

Thanks a lot again!
