repl-looper

REPL-LOOPER

Mash up of REPL and Looper/Sequencer (Updated 2023-11-08)

The idea here starts with building a code-analogy to a guitar looper pedal. Or maybe a step sequencer that runs commands instead of synth/samples directly. Start recording, execute commands, and those commands get recorded along a loop timeline. Each row of the grid is one loop (aliased to single-letter variables ‘a’-‘h’). The medium lends itself to further exploration around generating sequences, commands stopping/starting other loops, loop lengths dynamically changing, merging/splitting loops, etc.

The bundled engine is a mash up of Timber, Molly The Poly, and Goldeneye. Sounds are routed into per-loop controls for volume and pan. You can live record and slice and dice too.

I developed this to perform at FlashCrash, which went smashingly, and I put this out to share ideas. The README lists a lot of inspirations and ideas.

Tech – Lua, Lattice, Grid, Norns, a midi-pedal.

Assumes mostly norns+grid+keyboard.

Documentation & Download

;install https://github.com/awwaiid/repl-looper

Under active experimentation as of 2023-11-06. You can follow along and try running through the README at GitHub - awwaiid/repl-looper: Anagogically integrated UI for Norns / Matron / Grid

31 Likes

I made a bunch of updates to the README and setup so it will prooobbbbabbbbllyyyy work for people who are not-me now. Installation should work using

;install https://github.com/awwaiid/repl-looper

I’ll do a video walk through soon!

5 Likes

UPDATE v0.2

The biggest change is that the three sub-engines (Timber, Molly, Goldeneye) now route to per-loop mixers. So if you have a loop d with a variety of events you can do d:amp(0, 10) to fade them all out over 10 seconds.

The second biggest, and related, thing is that now you can have several Molly instances (8 are predefined). You can do molly:note('c') and then molly2:note('d') and they are completely independent.

I recorded a video walk-through!

4 Likes

UPDATE v0.3

More loop utils, timing fixes, bug fixes

  • Generate key-off events
  • Fix Timber slicing
  • loop:pan(-0.5) to pan the whole loop
  • loop:noLoop() to stop looping
  • loop:once() to play once
  • loop:align(other_loop) to slide events into alignment
  • loop:slice(s1) now takes sample-variable instead of sample-variable-name
  • Fix loop:split(other_loop) to work more reliably and take a base-command
  • Fix loop:merge(other_loop) to keep relative timings (using the new loop:align)
  • Embedded Goldeneye - add pan, lowpass; fix rate
  • Lay out long loops on the grid by zooming-out (more steps-per-button)
  • Rename ALL to all

Next thing I’ll probably work on is to live record into samples that then get sliced so you can use this as like … a normal audio looper. Then I’ll hook it up to a midi pedal to start/stop recording.

8 Likes

I made some changes but then forgot to tell anyone hah. Mostly I have abandoned the super cool web UI and now have a fully on-norns grid+keyboard experience.

image

v0.4 (2023-03-18) - On-norns UI, live sample recording, midi-pedal

  • New on-norns UI
  • New on-norns keyboard input
  • Using softcut, live record a sample and then slice it into a loop
  • Add the ability to select a current-loop and record via midi-pedal
  • If the current loop is loop-1, then stretch the BPM to match the sample at 16 steps

v0.5 (2023-11-06) - Editor

  • Add cursor, arrow keys, home/end, and dynamic height to input editor
  • On-screen grid mirror
  • Abandon web UI

An example of the on-norns UI and an attempt at the midi-pedal is available in the delightful hot mess of a performance I did in one of the glorious Flash Crash sessions last year – https://www.youtube.com/watch?v=3IQq8WURehc

Next up I’m going to mash the SuperCollider engine from granchild in and see what happens.

12 Likes

I had no idea there was a grid interface even before this! Always thought this was cool but hadn’t tried myself

I’m much more keenly interested with the latest additions

thanks for sharing with us!!

1 Like

Well it would help if a refactor hadn’t actually BROKEN the grid keypresses! I just pushed an update, now on 0.5.1, so when you press grid keys then it triggers the code recorded on that step.

If you get it up and running (and I’d love to hear if you do), you can run “p” to get a piano sound, “p(62)” to play midi-key-62 on the piano. Then try this:

h:gen("p(`60+m`)")
a:rec()

That will “generate” a macro-expanded piano on the bottom grid row (row-h). Those back-ticks make it so the m turns into the grid column number. Press those keys to trigger different piano notes. the a:rec() started recording on the top grid row (row-a). Use a:stop() to stop recording, and a:stop() again to stop playing! :slight_smile:

I’m not sure about the macro thing – now that I’ve had it for a while I suspect there are other ways to get the same effect (like a global that includes the current step number). Maybe.

There is a tutorial/techniques document if you want more ideas.

2 Likes

Thanks for the feedback again – I realized that there was very little about the grid in the documentation. I’ve now added an initial diagram and some docs on grid usage!

The Grid visualizes the loops, their content, and their current status.

  • Each row is a loop (ah)
  • Each step that has commands is lit up (dimly)
  • Press a button to execute all the commands at that step
  • You will see the command go into the REPL execution history exactly as if you had run it by hand
  • The current step is lit up brightly
  • When you are playing a loop (like a:play()) you will see the current step move across and then loop back around
  • If you are recording one loop, like a:rec() and you press buttons on any loop those events are executed and recorded!
  • So you can create an adhoc piano on loop h, start recording on loop a, and then jam the piano buttons
    • h:gen("p(`50+m`)") – put a piano note on each step
    • You could also put some 808 stuff on a loop like g:gen(keys(s808))
    • a:rec() – start recording, jamming, looping!!!
1 Like