I’m taking very baby steps with my learning. I’ve been finding my way around softcut by trial and error and made this very basic looper. It works but it’s a bit unpredictable. I’d really welcome any ways to improve it.
following up on my post from a couple days ago, i’ve got a somewhat working script!
demo video:
there are a bunch of bugs, including one that prevents it from starting after sleep. something with the default chord not being able to be displayed or set. i don’t know how to get it to distribute octaves equally between played notes. would really appreciate any input on how clean this thing up.
i have no experience using code for anything other than automating repetitive tasks in my video editing job, so i am way over my head. it’s pretty insane how quickly i was able to get something somewhat working and even somewhat fun. thanks to everyone who has helped build out this environment!
edit, fixed the error that crept into the beginning between saving and posting, script should actually work now
(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)
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
Thanks Carl for this amazing script! Looking forward to experimenting with it today.
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!
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.
@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.
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
Im sure that could be done much more elegant, but anyway -
https://gist.github.com/w30n/84b5512012aef967fd1b7c10f56fcd56
Any tips appreciated!
edit: updated gist
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 - 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!
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.
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.
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.
Thanks very much for this, very helpful for a newbie like me!
Glad to hear it’s useful Please reach out if anythings unclear or if there’s anything you’re interested in implementing or digging into.
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?
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.