Duplex Stepsequencer


This is a Duplex version of the Launchpad step sequencer originally posted here: http://www.renoise.c…ndpost&p=207933


  • Any size (scroll within the pattern)
  • Press an empty button to put a note down using currently selected instrument. Press a lit button to remove the note.
  • Page lines up/down with “line” spinner, tracks left/right with “track” spinner
  • Transpose note up/down with “transpose” control (4 buttons, from left: oct-, semi-, semi+, oct+)
  • Select note volume from 8 preset levels with “level” slider (right-hand trigger buttons)
  • If transpose / level controls are used while holding down grid buttons, the transpose / level will be applied to all held notes. Otherwise the base note will be adjusted.
  • Visual indication of playback position

EDIT: Added playback position indicator and fixed ‘set’ method error on app destroy
EDIT #2: The sequencer has been included as part of Duplex since v0.92 and has recieved numerous updates since then

Wow, great work! :)

An issue I realized when playing around with it (no real launchpad)

  • pressing oct- results in pasting the first 8 notes of the pattern into the currently selected grid

A suggestion:

  • possibility to set the base note to a custom value (lot’s of my samples are for example on C-4)
  • maybe it is possible to set in the Settings dialog, if the volume/oct/note changes will apply to the currently selected grid or to the whole pattern. If set to the whole pattern, holding down a grid button means to change the notes of the whole track. I think most users have a pattern length of 32 or 64 and pitching a note down/up in every grid is quite costly (and not so usable in live situations).

Definately one reason more to buy a launchpad, thanks!

PS: I will keep on work on my step sequencer and have a look at your code if you do not mind :)

Hrm yes, I just tried using it without the Launchpad and the GUI definitely does not work properly. I think this is again due to the release event not firing properly for UI buttons, so as far as the app is concerned any grid buttons you have pressed in the UI are being held down forever.

You should be able to set your base note by editing the StepSequencer.lua file - in the __init function there are options defined, for base note (i.e. C, C#, etc) and for base octave. Changing the “default” property for either of these will change the initial base note. For C-4 you would want to change the octave default to 5. I thought that Duplex would generate an “options” dialog based on these options but I can’t seem to figure out how to bring it up.

Great suggestion about applying transpose to the whole pattern. I’ve been trying to figure out how to make it much more flexible / powerful but with only those 16 buttons around the outside it’s hard to decide what’s most important. Ideally I’d like to be able to avoid using the keyboard/mouse entirely when using it, but the only way I can see to add things like instrument selection, copy/paste/repeat, track muting, per-track note selection, etc. is to make all the functions require multiple buttons presses. And with no visual “help” from the Launchpad the learning curve on something like that would be pretty steep.

Feel free to do what you like with the code - I’d love to see something as flexible as your step sequencer tie into Duplex (or at least directly to the Launchpad). Let me know if I can clarify anything, I know it’s not very well documented.


cant wait to get my launchpad back so i can test this properly

Wow, you have ‘duplexed’ cie’s script? That’s just very cool and I’ll love to help out.

Since this is the first user-contributed app for duplex, this does raise the question (as you’re pointing out) of how package such stuff. I suggest that people simply attach them to a topic like here, and it can get peer-reviewed and other people can help integrating the script into other device configurations (I beleive this script could also be made to work on the monome etc.).

As the missing release event for the virtual control surface - I’ll take care of that one :wink:

No, I haven’t touched Cie’s script (yet! :)) - I “Duplexed” my own Launchpad-based sequencer (originally posted here: Idea: Duplex Step Sequencer ). I’ll definitely be taking some inspiration from Cie’s sequencer though :)

Keep me posted on any development with the release event - Thanks!

This looks good. I’ve had a go at getting it going on my Ohm64 and have the basics working fine (I just added another duplex_configurations:insert to the end of your StepSequencer.lua, mapping the functions to my controller).

However, although I’m sure it would be trivial to somebody who actually understood lua (i.e. not me!), I can’t get the levels to work, which ideally would be on one of the faders (it works if I assign it to the grid, but obviously I need that for other things. It doesn’t seem to work work if I assign it to other buttons on the controller). Also, the grid buttons stay lit all the time, should they only light if a note is present at that position in the pattern?

I’ll keep trying but any (constructive) advice would be welcome.

Yep, the buttons should only light up if there is a note present. I wonder if it’s got something to do with the Ohm64 only being one-color buttons (only on or off, right? No brightness levels or different colors?) Although I am using a color of 0,0,0 (i.e. no lights on) for an empty grid step - I would have thought this would mean “off” to the Ohm.

I have been lusting after the Ohm64 at my local gear shop, I wonder if the desire to test this out will be enough to make me buy one. How do you like it? Any complaints?

As for the level slider - this seems to be because I don’t fully understand all the ins & outs of Duplex’s UI components, specifically the UISlider, which can be represented as a column of buttons or as a knob/fader. I’m arbitrarily setting its “ceiling” to 8 based on the 8 buttons on the Launchpad. This obviously doesn’t work so well when you move it to a fader which can go the full 0-127. I’ll try to play around a little with the “virtual” Ohm64 in Duplex and see if I can get these issues sorted out.

Thanks for the feedback!

Thanks for the reply. I only got the Ohm64 a few weeks ago, I’ve spent most of my time with it fiddling with the setup in Renoise, but it does appear to be excellent. I just had another look and I’m confident you’re spot on regarding the issues with the buttons only being on/off and the UISlider. I’m trying to figure it out myself, but I’ve very little experience of coding (and no expereince of lua) so I find it pretty hard going. If you want me to try anything out on the hardware just give me a shout.

Couldn’t we simply add daxton’s button release notifier changes to the existing button UI and then add the step sequencer as an application?
Feels wrong to add a new button UI for this, just to catch the release notification. If it does not change the controls value, this also is safe to do?

I’m absolutely loving this for “not-completely-attached-to-the-puter” drum programming. I’ve already written tons of notes on desired functionality that I’d like to integrate myself.

So I started to work on an interface for showing the current step, but half an hour into my research I came across some code which you’ve commented out in StepSequencer.lua.

The code is as follows:

 if renoise.song().transport.playing then  
 local pos = renoise.song().transport.playback_pos  
 -- if we stopped playing, turn off position  
 if(self.__playing) then  
 self.__playing = false  

So if we had a position variable available to the StepSequencer object, which could then update the side grid buttons with a brighter/lighter color or do the same with an entire row. Was this your intention? I currently don’t see the self:__update_position method, but maybe I am missing a bit of scope. I noticed that there seems to be no way to update a single value’s color using the UISlider control(I was planning on using the level slider). So my next step was to begin researching how to manually control point on the grid.

First, I don’t want to step on any toes, so if you have a planned, good solution… please feel free :) Although that won’t keep me from giving it a shot myself as the night passes. Do you and/or Danoise and/or ANYONE have any ideas on this?

Also, this brings up thoughts of version control and distribution for these tools(Duplex as a whole, and applications which extend it, but may not be part of the main release). To Danoise’s credit, I do appreciate the simplicity of forum based peer review, and single ownership/release ability.

This also gets me thinking about the ability to page through various Duplex controls. Through my brief learning/reading the codebase, I certainly don’t see a baked in way of doing this, but that of course doesn’t stop us. Pages could be incredibly useful for any app, I feel that Ableton’s default config shows a lot of what could be done here in terms of putting a lot of interface inside of 64 + 16 buttons. Holding down buttons is a more complex version of pulling of the same idea, but useful for quick edits where paging through many results could become cumbersome. The fact that we have 8 rows does allow us some paging flexibility, in that we can use equal col/row placements in order to allow the user to assume connections.

Boy this is more fun than the backend web dev I do for work.(at least I get to work from home and play with renoise from time to time =D )

I did initially just add the release event code to Duplex’s built-in toggle button, but the toggle functionality didn’t work the way I wanted it to - since there are some “press” events that shouldn’t trigger the toggle - for example when holding a button to modify the step. Personally I would prefer to work with a button that is just a button - any behavior as a result of the button should be determined by the application. Hence the “basic button”.

I think it would be great if the release event fired for the existing buttons, but I think a more general-purpose application needs more generic buttons to allow for more complex logic within the application.

That is code from the Matrix application that I thought I would try to adapt to StepSequencer but didn’t get around to. You should be able to find the __update_position method in Matrix.lua. I haven’t actually given it a good look, but I imagine you should be able to modify it to display the current line instead of the current sequence position. Looks like this is part that forces the visual indicator of the slider to a point:


In the step sequencer I guess it would be __level instead of __trigger.

If you’d rather use the grid, this is what’s working for me:

__buttons[x][y]:set_palette( { foreground = { color = { r,g,b } } } )  

This is basically what’s happening in the __draw_grid_button method. But this would mean you’d either have to force a full grid_update every step, to restore the original color of the button that you were using to indicate position. Or just remember the color you overwrote and restore that one button before moving on to the next.

Brilliant! This is exactly the direction I’d love to see the Launchpad controls go - to be able to almost entirely ignore the keyboard and mouse and work entirely on the Launchpad. Multiple Launchpads, each with this kind of multi-function paging would be amazing.

I hear that! Except the work from home part - that would be a dream come true.

IC. But then UITriggerButton should do the job (with a few modifications). It only fires events and has no value.

Perfecto! I’ll change over to the UITriggerButton next chance I get.

I tried out the sequencer yesterday. Wow, just awesome how it can track your position within the song and automatically populate the Launchpad with notes. It even has a paged scrolling mechanism. Great stuff, really!!

FYI: UITriggerButton is a “one-shot” button, that use the scheduler to turn itself off after a short while. It was needed for stuff like the Transport “stop playback” button. It’s also the button that’s used for the Transport’s scheduled pattern (next/previous) buttons - the only difference between the blinking schedule button and the one-shot stop button really is that the scheduler is driving a looped sequence. In other words: I’m not sure that it’s the UITriggerButton you’re looking for, since neither that one or the UIToggleButton has (or should have, IMHO) a release event. Really, the UIBasicButton is working great, so why change it?

Re: UITriggerButton or UIToggleButton
Yes, both can not be used for what daxton needs in the stepsequencer, but extending UITriggerButton, making it configurable to to the job, might still be better than introducing a new UI control. That was my only concern.

Has anyone else noticed that attempting to use the Duplex browser to switch between the launcpad sequencer and any of the other launchpad mappings ends in this error?

For reference, I’m on an Intel Macbook Pro running the newest version of OSX.

I can get it to work if turn off autostart config for the step sequencer and reload all tools. If I ever go into the stepseq again, I have to repeat the reload all tools process. I can go easily from the mixer and other tools to the step sequencer, but never back.

I think the call to set() that cause the error is because daxton wants to turn off all LEDs when destroying the app. This shouldn’t be necessary, as any other app would completely take over the Launchpad. Furthermore, in the newer SVN version of Duplex, closing the device will cause the Launchpad to completely wipe it’s display. So I think it’s safe to comment out the line that causes the error.

I removed the call to set() - this method doesn’t even exist for UIBasicButton, it’s just a piece of your code I never bothered to update! :wacko: I also added calls to remove_listeners() for every UIComponent in the app. Is that necessary?

And I added a visual position indicator in the “level” column. I’d prefer to not draw the position while you’re pressing one of the level buttons, but without a release event on UISlider I don’t know how I can check for that! ;)

Yes, because - AFAIK - they are only removed properly when the garbage collector comes into effect. Which means that if you create, destroy, and create an app before any loose references are collected, it can result in various strange errors.

But, this approach sucks because you have to manually remove each and every UIComponent. This can be quite hard to remember, so I’ve introduced a new method (not on SVN yet) which you simply use instead of “display:add()”. It will register the UIComponent with the application, and automatically remove references when it’s destroyed. Much better to work with IMHO.