Undoing the scale function

I love using off to create cannons with transposition, but often feel frustrated because I can only do this with absolute intervals, and unless I choose my notes very carefully, the only safe intervals to use are octaves

I’d love to be able to do step-wise transposition, for example, have a part that is a third higher, but have that third be major or minor depending on where it lands in the scale.

What I’ve been trying to do is to create a function that effectively undoes scale, applies some numerical function to those values, then reapplies scale to the modified values. So it might syntactically look like this:

d1 $ off 0.25 (underscale “dorian” (+ 2)) $ n (scale “dorian” “0 2 1 3”) # s “supervibe”

where under the hood

underscale name f  = scale name . f . undoScale name

Of course I realize that this (currently imaginary) undoScale function would need to somehow handle values that are not part of the output of its corresponding scale function. But some arbitrary yet consistent way of handling this, like rounding down to the nearest matching step, should work.

Does anyone have any thoughts on how to approach this? I’m frankly stuck on getting even a list of the scale intervals to operate on. If I had that I could probably figure out some (admittedly hacky) way of doing this.

2 Likes

As a quick fix you could apply the off before the scale like this:

d1 $ n (scale "dorian" $ off 0.25 (|+ 2) "0 2 1 3") # s "supervibe"
2 Likes

True, but I wouldn't be able compose the function with other non-numerical functions. E.g.,

d1 $ off "3s" ((|+ n 12) . (# s "superhammond")) $ n "0 3 2 5" # s "supervibe"

This post captures a problem that I always seem to run into when using tidal. @yaxu's suggestion is what I have most often done but it does force me to do all my note based thinking in one place. Later in the pattern development, when I'm thinking about stacking transformation functions on the outside of the pattern, I see an opportunity to tack on something like plyWith 6 (+| note "<2 3>") that does cool stuff to the melody but puts me in really chromatic territory with no way of getting back to diatonic land.

I've often wondered if there is some way to make an operator similar to # that transforms an existing control pattern as opposed to adding/replacing it. That way I could say: d1 $ (|~ note (scale "dorian")) $ foldEvery [2,3] (|+| note "2 1 2") $ note "0 2 <5 3> 9" #s "midi" where |~ is a made up operator that allows me to map the function scale "dorian" over the existing control pattern.

I know this made up |~ is different from |+| and the like because the |+| family are operators combining two control patterns but it does feel like forceing to scale on the "outside" of the pattern should be possible. I just can't figure out how! :slight_smile:

4 Likes

I've been searching the docs and forum for an efficient way to operate on midinotes, and I came across this discussion. It seems that, with all the rhyhmic power and variation available in tidal that it wouldn't be too far to stretch this power into harmonic and melodic territory too. I'd love to be able to input a note sequence or theme and then change it from outside in different ways without having to manually go in, change the notes and re-execute.

Am I missing something somewhere? I could see this functionality opening floodgates for incredible generative compositions but haven't found it in tidal.

A wish list would start with:

  • transposition (i.e. play one melody/set of chord changes in one key, then move it to a different key)
  • modulation (similar, but be able to change between minor and major etc. according to appropriate scale steps)
  • sequence variations (like temporarily reversing the order of just a small subset of notes in a sequence without modifying the whole sequence)
  • sequence evolutions (i.e. changing the note or octave of an isolated value within a sequence, leaving it at the new value and then changing a different note, letting the sequence morph perceptibly)

Just those four would be huge game changers, I'll leave it to cleverer people to add to it. But if there's existing functionality within tidal which does it already I'd love to know. (Or if there's a compatible language which might work like this alongside tidal I'd love to know that too...)

2 Likes

@trvrxtr try something like d1 $ (|+ n "<0 1 2 3 2 1 0 -1>") $ within (0.25,0.5) (rev) $ n (scale "minPent" "0 .. 7") # s "superpiano" to create a transposition pattern over time and apply a function (rev) to only part of the melody (the second quartile of the minor pentatonic scale).

2 Likes

Very helpful, thanks! Gonna spend some time with this.

@trvrxtr here's a try with that wish list!

-- transposition over time. Every two cycles, transpose two semitones up
d1 $  n ( "<g'min c'min>" |+ "<0!2 2>")  $ s "superpiano" 

-- modulation. I don't remember exactly the syntax (specially the operator) but I think you can do smth like:
-- Here the result would be smth like : g'maj c'min d'maj g'min c'maj d'min constrained to a major scale
d1 $ n (scale "major" ("<g c d>" |+ "<maj min>")) $ s "superpiano"

-- reversing the last half of a note sequence every 3 cycles. Note that only the order of the notes is reversed, not the rhythm.
d1 $ struct "t(7,12)" $ 
n (every 3 (within (0.5,1.0) rev) $ run 8) # s "superpiano"

-- the last one I think you can use fix, which applies a transformation to a specific value of a param
-- here I'm saying 'when the note is 3, set the octave to 4
d1 $ fix (#octave 4 ) (n 3) $
struct "t(<7 9>, 16)" $
n (run 8)
# superpiano # octave 3
3 Likes

have a look at this thread by @earthlydelight

1 Like

Thanks for these tips @kit-christopher @Tomas_Ciccola and @cleary. Will dig in!

1 Like