norns: ideas

@shellfritsch feel free to take whatever you want from zxcvbn. I made a whole norns-based text editor in that script with cursor, infinite lines, copy, paste, saving, loading. the code is not as clean and simple as it could be but it is a single module here: zxcvbn/vterm.lua at main · schollz/zxcvbn · GitHub


Just messing with pixel-art. I like the suggestiveness of Dronecaster, but my mind drifts and imagines much more elaborate visuals, so I did some sketch versions of what that could look like.
I have no idea if this makes sense or people even want it (breaks the magic, just let the sounds do the work, could take away from the experience, etc…), but it’s something I would enjoy, more like a full fledged piece of generative art.


I haven’t bothered coding anything, I’m sure I could figure it out, but I don’t know how interactive they can be made easily, things like masking, blending, scrolling bitmaps might all require significant work or even be impossible


thank you so much for these tips. i do want to get into norns scripting eventually, but right now time is at a bit of a premium. hoping to start working some evening studies into the routine.

i appreciate the offer to help me build the text editor - i was about to take you up on that when i saw the reply from @infinitedigits (thanks!!) regarding vterm. perhaps that might be the fastest route to a working text editor?

lots to parse in vterm. at first glance, i’m guessing i’ll need to modify some file paths to work with my own version. i don’t think i need specific .txt read/write - as long as i can open it up with a text editor on my laptop and copy over to another document for further editing.


Is this a sacrilege? :scream:


all good - i hope you enjoy the studies when you do get to them, they are pretty rad.

thanks for sharing vterm @infinitedigits! i didn’t realise that there was already a text editor out in the wild. also how have i slept on zxcvbn?! what an incredible script, and the docs are absolutely beautiful too :heart_eyes:

i had a crack at getting vterm to work as a standalone script this evening, but ran into a few different issues. i was able to get the editor to render and display the inputted text, however the cursor, line width, and a lot of the other functionality didn’t seem to work - it looks like there is still a fair amount of dependence on other parts of zxcvbn (tracks, params, etc). i’m struggling to grok parts of it, @infinitedigits were you thinking that it would be good to import it and use it as is, or copy-paste the juicy parts out of it?

the easiest way forward from my perspective would be to take inspiration from vterm to flesh out my initial prototype into something usable. there are many wonderful extra features in vterm tho, so if there was a way to get that working that would be pretty sweet.

i have a show that i’m meant to be preparing for this weekend, but i’ll try to make time over the next week or two to pick away at it - it still feels well within reach.

1 Like

Really basic, but is there a script where i can listen to my tape files as a playlist?


I don’t think so! thats a good script to put out there though!

thanks for the kind words - I was thinking that you could copy-paste w/e you need. the main chunks should all be there. the code is not too complicated but there are a lot of “one-off” errors that I spent time getting cropped out. do let me know if you get severely stuck - the main pieces shouldn’t be too hard to plug into something new but I’m saying that after writing the code :wink:


Purely for entertainment, I fed the requirements of my script idea—Edward Slicerhands—into chatGPT, and this us what it spat out.

First, the requirements:

  1. the script shall monitor incoming sound on the Norns audio input
  2. the script shall analyze the incoming audio stream and identify percussive transient peaks
  3. the script shall slice percussive audio transients in real-time and save them as .WAV files to the following directory: /dust/audio/edwardslicerhands/
  4. the script shall use the frequency content of captured audio to name the file according to the type of percussive sound, along with a timestamp. e.g. kick-15.03.23-12.35.WAV)
  5. the script shall provide the following UI controls to the user: ‘attack threshold’, ‘attack time’, ‘release threshold’, ‘release time’, ‘maximum sample length’ (limited to 4 seconds)
  6. the script shall not include additional filters or effects
  7. the script shall include a setting that limits how much data (in MB) is written to the destination folder in one session. When this limit is reached, the scrip shall display a “sample library full” message. The maximum allowable limit is 4000 MB.
  8. the script shall be compatible with all versions of Norns
  9. the script shall be named ‘Edward Slicerhands’

And here is the code written by chatGPT:

-- Edward Slicerhands
-- An experimental script written by ChatGPT

-- UI Controls
local attack_threshold = 0.5
local attack_time = 0.01
local release_threshold = 0.2
local release_time = 0.1
local max_sample_length = 4.0

-- Maximum size of sample library
local max_library_size = 4000

-- Create directory for samples
local sample_directory = "/dust/audio/edwardslicerhands/"

if not util.file_exists(sample_directory) then

-- Initialize buffer and peak detector
local buffer_size = 8192
local buffer = {}
local peak_detector =, release_time)

-- Initialize variables for sample naming
local timestamp_format = "%y.%m.%d-%H.%M.%S"
local sample_count = 0

function write_sample(buffer, length)
    -- Create filename for sample based on frequency content
    local filename = sample_directory .. "sample-" .. sample_count .. "-" .. .. ".WAV"
    local freq =, buffer_size), buffer_size, 1.0)
    local freq_midi = midiCps(freq)

    if freq_midi < 36 then
        filename = sample_directory .. "kick-" .. .. ".WAV"
    elseif freq_midi < 48 then
        filename = sample_directory .. "snare-" .. .. ".WAV"
    elseif freq_midi < 72 then
        filename = sample_directory .. "tom-" .. .. ".WAV"
    elseif freq_midi < 84 then
        filename = sample_directory .. "hat-" .. .. ".WAV"

    -- Slice buffer and save as WAV file
    local sliced_buffer = buffer:copy()
    sliced_buffer:slice(0, length)
    sliced_buffer:write(filename, "WAV")

    -- Update sample count
    sample_count = sample_count + 1

function process_audio(input)
    -- Copy input to buffer

    -- Detect peaks
    local peak = peak_detector(input, attack_threshold, release_threshold)

    -- If peak detected, slice buffer and write to file
    if peak > 0 then
        local length = peak_detector.time * sample_rate
        if length <= max_sample_length * sample_rate then
            write_sample(buffer, length)

function limit_library_size()
    -- Get current size of directory
    local dir_size = util.directory_size(sample_directory)

    -- If directory size exceeds maximum, display message and stop recording
    if dir_size > max_library_size * 1024 * 1024 then
        print("Sample library full")

-- Set up audio input

-- Set up processing functions
local sample_rate = 48000
local recording = false

function start()
    recording = true
    sample_count = 0
    buffer = Buffer(audio.rev_channels, buffer_size)
    audio.process = process_audio

function stop()
    recording = false
    audio.process = function() end

function key(n, z)
    if n == 1 and z == 1 then
        if recording then

-- Set up screen
function redraw()
    screen.move(10, 10)
    screen.text("Edward Slicerhands")
    screen.move(10, 30)
    if recording then
        screen.text("Press KEY1 to start recording")
    screen.move(10, 50)
    screen.text("Attack threshold: " .. attack_threshold)
    screen.move(10, 60)
    screen.text("Attack time: " .. attack_time)
    screen.move(10, 70)
    screen.text("Release threshold: " .. release_threshold)
    screen.move(10, 80)
    screen.text("Release time: " .. release_time)
    screen.move(10, 90)
    screen.text("Max sample length: " .. max_sample_length)

-- Handle encoders
function enc(n, delta)
    if n == 1 then
        attack_threshold = util.clamp(attack_threshold + delta/10, 0, 1)
    elseif n == 2 then
        attack_time = util.clamp(attack_time + delta/1000, 0, 1)
        peak_detector.attack_time = attack_time
    elseif n == 3 then
        release_threshold = util.clamp(release_threshold + delta/10, 0, 1)
    elseif n == 4 then
        release_time = util.clamp(release_time + delta/1000, 0, 1)
        peak_detector.release_time = release_time
    elseif n == 5 then
        max_sample_length = util.clamp(max_sample_length + delta/10, 0, 4)

-- Handle screen refresh
function init()

-- Start recording on init
function on_resume()

-- Handle cleanup on shutdown
function cleanup()

-- Start recording on key press
function key(n, z)
    if n == 1 and z == 1 then
        if recording then

-- Run the script
function rerun()


Naturally, I did not expect this code to work right out the box, and in fact I see an ‘error: load fail’ message when I run it on Norns.

I’m curious if someone with dev chops can find where chatGPT has failed, and help me bring Edward Slicerhands to life. I tried some basic troubleshooting . . . No luck.


this is total bullshit.


If the bullshit is total, then we can consider this a failed experiment :joy:

1 Like

Thanks for this. Like ChatGPT, clearly I have no idea what’s going on. I desperately would like to teach myself how to code for SC, since I did study old-fashioned-programming a few decades ago.

The truth is, I run a home business while raising three kids, so perhaps a future version of me will have more time to get back into it. For now, I’m just hoping someone will see the value of my idea and bring it to life :joy:


sorry if that causes offense, but i am trying to use the term “technically.” :slight_smile:

This places the mathic observer in a nearly impossible position. One is forced either to use this “offensive” word and be deemed a disagreeable person and as such excluded from polite discourse, or to say the same thing in a different way, which means becoming a purveyor of bulshytt oneself and thereby lending strength to what one is trying to attack. The latter quality probably explains the uncanny stability and resiliency of bulshytt. Resolving this dilemma is beyond the scope of this Dictionary and is probably best left to hierarchs who make it their business to interact with the Sæculum.

  • Stephenson, Neal. Anathem (p. 165). HarperCollins. Kindle Edition.

chatGPT is a bullshit generator, as its creators admit.

in this case: yes, the bullshit is “total” - there is basically nothing i can see in the output that is of any value whatsoever. (there are some reasonable bits of boilerplate, but they are only reasonable because they are cribbed from the norns system code. so you are looking at a bulshyttified madlibs’d version of the system sources… better to look at the original sources which are written by humans who know what they are trying to accomplish.)

i am trying not to go on a long general rant here about chatGPT or ML-assisted source code generation in general, but it does bother me (for a couple reasons) to see chatGPT output used and shared - if not exactly uncritically, but always it seems from a position of inexperience - in the context of norns scripting. it has happened a couple of times now here and i hope the moderators consider something like stackoverflow’s policy going forward.

(the norns platform/ecosystem - of which i happen to be a primary author and architect - is built on the premise that coding interfaces are empowering, and so is sharing work - both the pedagoical and practical missions of the system are i think under attack when we try and shortcut those processes using bullshit generators… but not ranting)

anyway you can probably just imagine the rest of my rant (which is not entirely critical, i mean bullshit generators can be useful of course. maybe for artist bios or something (ha.))

more interesting to think about the actual question. so:

i don’t have a huge update but i did implement some tweaks to the demo:

  • spectral analysis parameters are now averaged over only the samples in each segment that exceed an amplitude threshold, so i think they are more statistically significant. (but i should really do more structured testing to support such a claim.)

  • the current default mode writes out only the non-silent portion of each segment, with a configurable silence gate (in addition to the configurable onsets detection algo.) i actually think that saving the full segment is more appropriate in some circumstances since the “silence detection” part is unavoidably imperfect.

i did not yet take the time to make more immediately important changes:

  • refactoring into a Class
  • implementing a “session” interface so that all analysis data frames are appended to a single file (and placing a limit on total output size/duration per session.)
  • i guess some more functions / callbacks to make the thing more norns-friendly, like firing a poll for each output.

these easy to do but i haven’t taken the time this week. (i too am a full time working parent.) maybe i’ll get to it tonight or something.

i do encourage anyone interested in the application to look at the code that i have put there (which i think is reasonably clear and well commented) and to look at the Onsets class helpfile. this tool/demo is just using off-the-shelf SC algorithms, but it is already substantially more flexible than a segmenter that looks only at amplitude: it can be tuned to slice on e.g. pitch changes and other articulations.

i thought that’s what we were doing. this is what it looks like. both the analysis and resynthesis/composition parts of your idea are complicated. i’m contributing a little bit of not-unskilled labor to the analysis part in the hopes that it will be both useful (for other projects and ideas, not just yours) and informative (to other readers / users, not just you.)


I appreciate your input, and no offence taken.

If I used GTP to invent a recipe, and then I asked a chef to cook it, I will probably get told to go F myself; so I understand how my “experiment” might seem like an insult to those who have dedicated years to mastering their craft. For that, I apologise.

Like many others here, I have a strong desire to create, but in this case I simply don’t have the tools to do it so I try to find other ways.


I’d just found my way onto this thread and was pleasantly surprised to see this idea being brought up! I’d recently been wondering about having the ability to take notes, write down thoughts, etc on norns.
Curious to hear if you make any progress, and also keen to dig into the examples from @dwtong and @infinitedigits and have a go myself (when I manage to find some time somehow), so thank you all for sharing!


I think this is less a case of a chef being offended at being given a generated recipie because of their years of honing their craft, and more like asking a chef for help with your ai generated recipie, and the chef laughing because you gave them a recipie with steps such as ’ first, pre-heat the blender to 200°’ and ‘lightly butter the inside of the hat and pour in your vegetable batter’.
People aren’t offended that you got an ai do do the thing they’ve sunk hours into learning, they’re just telling you that the thing you asked them to fix is simply nonsense confidently presenting itself as a norns script.
Chat GTP isn’t the tool You’re looking for. It’s barley a tool at all. You’d be much better served spending some time on the norns studies.


I don’t have a good citation for this, but I read somewhere that the creator of ChatGPT said it was pretty much crap (Paraphrased of course).

I found that simultaneously funny and terrifying… And somehow not at all surprising…

1 Like

I think the better take to all of this is, instead of scrutinizing and calling things bullshit, is to encourage folks who want to create but have not the time to dedicate to the art of coding to change their approach slightly. These new tools could be a boon for productivity in this community - no need to gatekeep.

@branch instead of simply prompting ChatGPT with the kitchen sink right away (a full spec of what you want), start simpler. Get it to produce no more than 10-30 lines of code at a time. This will build your knowledge and reduce chance for error - all without you needing to study Lua/general programming for hours, weeks, years, before getting started.

Ask it to produce some code that does nothing interesting, like make an audible tone or draw a simple graphic to the screen. Ask it to do something that is guaranteed to work first. Once you have that, start building upon that foundation and guiding it towards complexity, instead of just expecting it to produce a useable result right off the bat,

ChatGPT IS a tool (those saying it isn’t I would suggest could benefit from changing their approach).
But it’s up to us humans to know the difference between watering our garden with a firehose vs. a nice slow trickle. DO not blame the tool - it is doing what it is designed to do. The onus is still on the human to do the critical thinking. ChatGPT can simply help you explore these worlds quicker.

Hot take, I know. But, I just think there is a place for folks who want to use this technology to contribute to the world of software. This community is smart enough; we can figure out how to empower everyone to contribute.


** EDIT ** - while I appreciate and respect myself for my initial response here I have been educated why this stance could be problematic. This community is built on the backs of a deep reverence for the art of software engineering. This community provides all the necessary resources to get you from knowing nothing, to feeling empowered to create. While I still believe there may be a place for AI chat tools on the learning journey, they should be treated as supplemental to doing the actual work.


I think if we start with assumption that everybody is busy and managing some subset of obligations and ambitions that exclude execution of all things we’re on good footing. There aren’t many useful shortcuts toward the things we want to produce because our belief in the value of investing in them is what inspires others to participate. That said you can do a lot with a little. Scripting for norns has a fairly low cost of entry, and most of the heavy lifting has already been done. It’s also well documented and approachable. Making software is always a creative challenge, just like making music or novels.


Love this post. Thankyou for writing it!


i’m sorry but i really don’t agree with this.

if you don’t want to read my whole crazy rant, here’s the main point i’d make in response:

i haven’t seen any such thing. there is always a chance of the thing pulling up something that is just drastically wrong. this appears to be equally true in every domain of factual knowledge. for example all models of GPT seem to “think” that i was born in 1975 instead of 1981, for no “reason” whatsoever (because reasons don’t exist in the GPT universe, only dice.) i guess a tool like Codex or Copilot that is made for code completion can probably have functionally total corectness, but the chat-based tools really don’t.

in a more apropos example, gpt4 made a totally inexplicable off-by one error in a trivial lua function: “copy the top half of a table to the bottom half, ignoring last element if the size of the table is odd.” it got the size limit wrong, ignoring 1 or 2 elements. a lot of lua newcomers have issues with 1-based indexing so this is not helping anyone.

(that is the basic issue i have with this stuff as an engineer. i also have some personal preferences that are more social and about how i want to interact with collaborators and knowledge-sharers, but i suppose you’re right and i shouldn’t try to “gatekeep” according to such preferences. however, the use of these tools will depress my own willingness to engage with the ecosystem, fwiw.)

lordy, this rant is way too long.

<rant deleted>