(mod edit: to preserve the purpose of the code review, which is to be a repository of links [discussion taking place on a script’s gist], recent SoftCut-specific dialogue was migrated to Norns: SoftCut engine)

2 Likes

Sway: live processing environment for norns

Here is the single-channel version of Sway that I’m making public for norns. This code is open for review, suggestions, problems, or critiques. This is a simplified version of the SuperCollider code I’m currently using with my sextet and other ensembles for live processing. Note that some of the processing types listed in the video are not in the script anymore as I decided to take them out for the time being.

preview video: https://youtu.be/w9RZHmo4JAs
gist: https://gist.github.com/carltesta/7529749349d934e410fe30d4fac29561
live performance audio: https://soundcloud.com/carltesta/bloom-sway-solo/s-imhYV
general link: http://sway.carltesta.net

Thanks!
Carl

18 Likes

Thanks Carl for this amazing script! Looking forward to experimenting with it today.

1 Like

I was thinking about trying to make an apeggiator and just found your post.

Any further development on this?

I’ll fiddle around with what you have any report back

hey! so that was the first musical thing i’ve coded and i didn’t realize how much would have to be changed to adapt to different engines (polyphony…), so i started over on one based on loom, and instead of getting chords based on midi in i am changing the sequencer based on major/minor tonality and the circle of fifths. so it went a bit left.

that code is probably broken because of the params update but should be easy to tweak. the trickiest bit is dealing with filling out the notes for step sequencer correctly, that one is just arbitrarily adding octaves for some reason. in spite of this it actually sounds pretty cool, but it’s more like a drum machine than an arpegiator.

i can put up my new WIP code if interested, but broadly here is how i’m fixing those issues:

-the active chord/scale gets defined as all the notes in in the scale in the music util library, something like 70 notes. the app then picks the the notes to put on the grid based on separately determined octave variable. advantage of doing it this way is you don’t have to tell the app how to fill out the scale, you can just pull from every single note in key.

-a message to change to new chord/scale generates a new 70 something note bank, then a third note bank that is comprised of all of the common tones between the two scales. then for notes that aren’t common it finds the closest common semitone. (i think, don’t have the script in front of me)

-the scale is then reduced to the grid size, and it checks for duplicate pitches between steps. if found it replaces duplicate with the closest note to it from previous step and resets the duplicate check.

-the snap note to array command in the library doesn’t equally distribute the notes so i had to write this up instead.

kind of a word bomb but hopefully some useful info in there. let me know if i can help at all!

1 Like

I’m posting the code for a beta version of QUENCE, a MIDI sequencer for Norns and Grid. I’m very new to Lua and a programming hack generally, so please feel free to pound me with constructive criticism on how to make the code more efficient. Thanks in advance!

In case this is helpful to any other newbies: I’m used to being able to copy a table and have it be a true copy, not a direct reference. This caused me a lot of suffering trying to figure out why my Lua code wasn’t working. Using deepcopy was extremely helpful.

Another random thought: Using a Box Muller transform was a neat trick to convert uniform random numbers into normally distributed random numbers.

17 Likes

@spunoza can’t wait to try this out, looks great

ok i promise to figure out how to use github soon, but in the meantime here is my new take on sequencing key changes in a musical way. i’ve stripped down loom (thanks mark!) to only include the major/minor scales. losing all the modes/weird scales opens room up to control the tonal center independently from the root note.

how it works:
-random scale is assigned on launch
-encoders 1/2 move the key center but do not adjust the root note.
-key 2 + enc 2 adjusts the position of the notes

since the notes in the sequence are never moving more than a whole step between modulations you can get away with some pretty weird changes (button 3 picks a random scale). but you have to be careful, it crosses into jazz fusiony excess pretty quickly.

two big problems i am stuck on:
-sometimes redraw only gets 15 notes of the scale instead of the full 16 and refuses to draw. the scale is definitely sending 16 notes. probably some inefficiency somewhere is not letting it get all the notes in time
-the functions to change key only go a half step up (should go up or down or stay within some predetermined range). this should be easy to fix but for some reason i have not been able to do it.

next up:
-rewrite this all again to try to find/fix those two problems
-add in concept of measures, allow pattern recording of scale changes over measures to create chord progressions of x length
-add midi in to set scales based on keyboard, old 2000s yamaha backing track style

@okyeron here is the code i was referring to last week.

13 Likes

work in progress of meadowphysics port. mostly looking for feedback on if my library type implementation is correct. also any suggestions on the design are welcome.

create new mp like this

local meadowphysics = equire "ansible/meadowphysics"

mp = meadowphysics.new()

when a meadowphysics trigger occurs there is a callback function mp_event. user can implement their own function for this. passed in parameter is the row where the trigger occurred.

mp.mp_event = play_note

function play_note(i)
  --do something
end

user implements their own clock, and calls the mp clock function at each tick. this might need updating as I haven’t gotten too much into the meadowphysics speed code.

clk = metro.alloc()
clk.time = 60 / 240
clk.count = -1
clk.callback = tick
clk:start()

function tick()
  mp:clock()
end

user calls the gridredraw method passing the grid object g. maybe there’s no need for this

mp:gridredraw(g)

user calls the grid event method passing x, y, and z

function g.event(x, y, z)
  mp:gridevent(x, y, z)
end

library implementation

new

local mp = {}
mp.__index = mp

function mp.new()
  local m = {}
  setmetatable(m, mp)
  m.foo = bar

  return m
end

function mp:clock()
  --do clock stuff
end

function mp:gridevent(x, y, z)
  --do grid stuff
end

function mp:gridredraw(g)
  gridbuf:render(g)
  g.refresh()
end

return mp
4 Likes

Im sure that could be done much more elegant, but anyway -

https://gist.github.com/w30n/84b5512012aef967fd1b7c10f56fcd56

Any tips appreciated!

edit: updated gist

4 Likes

looking forward to this - you seem to have gone a similar way than I did with Kria (presumably intentionally) which is cool

After the Kria epic I’ve had to get back to paid work - need to earn a living :wink: - but will hopefully get some more Norns/code time soon and will dive in

I’ve got a couple of things I want to make with Meadowphysics!

2 Likes

yes! tried to keep the design consistent with the good work you did for kria. bit of a ways to go until it’s finished, but your kria library has and will be a great help.

1 Like

Here is a simple isomorphic “in-key” MIDI keyboard for Norns and Grid. There are two MIDI channels, one for each hand. Only notes in the selected scale are shown, with the tonic highlighted. The notes are arranged with five semitones between each row (each note is a fourth from the note below it).

Of course you’ll need a midi interface (something like this) to send the MIDI to an external synth or DAW.

11 Likes

I made a really vanilla 16 step sample sequencer!

The main thing I was trying to achieve is a clean decoupling of state, actions, and UI (my limited front-end js experience definitely guiding here).

I also actually developed the whole script as in the literate programming style with org-babel. So you can see the code interspersed with my thoughts/motivations here.

I’d love feedback on the architecture of the script (though it is pretty tiny) as well as on the format of the blog post. Also if you have any feature ideas that would be interesting or challenging to implement, they’re also very welcome.

9 Likes

Thanks very much for this, very helpful for a newbie like me!

Glad to hear it’s useful :smiley: Please reach out if anythings unclear or if there’s anything you’re interested in implementing or digging into.

1 Like

Still struggling with this in pairs function, so I wanted to ask if my following understanding is correct.

In “Running our beat” you are using
for instrument, triggered in pairs(state.steps[state.position]) do
without having defined instrument and triggered before. I assume this works because:

pairs looks at the four values in the array state.steps (e.g. false, true, true, false) at the current state.position (e.g. 2), and returns each of these values as a key-value pair (e.g. key 1 = value false, key 2 = value true, key 3 = value true, key 4 = value false). Then for each of these key-value pairs the local variable instrument is set to key and the local variable triggered is set to value, and the code block between do and end is executed. Both instrument and triggered are only valid inside this for…do statement.

Did I understand this correctly?

1 Like

I haven’t looked through all of the code, but I am fairly sure that in this case, instrument and triggered are just variables for the loop. You could write it this way too…

for i, j in pairs(some table of stuff)

or, if you do not need the index…

for _, j in pairs(blah blah)

It just looks at the index ( i in my case, instrument in the example) and the value (j or triggered) in pairs.

3 Likes

In regards to variable scoping yes, instrument and triggered are only valid inside this for loop, and will be replaced each iteration of the loop.

To be honest I haven’t totally grokked variable scoping in lua yet :sweat_smile:

update on traffic.lua, my reworking of loom to decouple a sequence from its harmonic content.

the recent changes to the app have produced some music that’s got me feeling introspective so this will be needlessly long.

awhile ago i read that when pt anderson decided to adapt pynchon’s ‘inherent vice’, the first thing he did was type up the entire book, line by line, in screenplay format, to get a feel of what it had felt like to write the book. i thought this seemed like a good idea for my next version of loom, to teach myself vim and “truly understand” how the script worked.

this in retrospect was probably not a good use of my time because i almost immediately forgot how the app worked after i was done and i also introduced a bunch of typos that took forever to find.

but i’ve got 98% of the kinks worked out with my scale changing functions. i’ve added in tehn’s pattern recording to allow for the repetition of a sequence of scales of transpositions of arbitrary length, and i’ve added support for transposing within the key via midi.

i also tried to decouple the triggers from the notes but this proved to be both a lot harder and less useful than i thought, so i only wound up including 4 modes for trigger speed: normal, slower, paused, reverse.

i have gotten to the point where i don’t actually know where to go next with this code, aside from tweaking some edge case bugs as they pop up i am probably done with this idea in its current form.

the impulse with this project was to handle changing chords and modulations in a more dynamic way without interrupting flow (eg during a performance). but i’m not a performer, and what i find most handy about the script is its ability to quickly generate motifs and then refine them using harmony until until they’re something interesting. so for my next exploration, i want push the refinement possibilities further without losing the immediacy of the generative aspects.

some broad design goals:
—design a new grid sequencer that facilitates easy reassignment of individual notes and triggers without breaking a chord tone.
—bring wacom integration to sequencer. if the information can be processed without too big of a cpu hit this seems like an ideal way of refining sequences. map grid to tablet 1:1, select notes with pen, process with arc…
—if you hear a happy accident it should be possible to get back to it. on the norns screen, some abstraction of a timeline with options to set loop points within the previous events, ala the party van. maybe should be able to set sequencer to rewind mode to undo changes.
—should be a tab on norns’ display for synth paramaters.
—synth scenes that can be morphed between over a defined period of time.
—never use the brightest LED level for more than, say, 8 LEDs at a time. LED noise on this was a constant battle but too closely entwined with the sequencer for me to wrap my head around.

anyway here’s the script!

if you try it out and something isn’t working or is unclear please let me know! thanks again everyone.

19 Likes

Great music - looking forward to trying out the code :thinking:

1 Like