Home Forums General Programming simple sequencer


This topic contains 158 replies, has 3 voices, and was last updated by  human fly 3 days, 7 hours ago.

Viewing 20 posts - 21 through 40 (of 159 total)
  • Author
  • #73653

    local led = L(panel:getComponent(“ledtext”..i))

    As far as I know the L() macro converts a string to a Lua ‘friendly’ string – I don’t know the details of this at all, but I think getComponent(ledtext1) is a reference to an object, therefore not a const string, which is what L() is for. When you do sName=L(mod:getName()) that’s a string you are formatting with L(), but ledtext1 etc is a variable:

    Something like that!

    I read a post by Atom stating:

    text = L(panel:getLabel("nameInputLabel"):getText())
    -- we take the text from the "nameInputLabel" and convert it to Lua type of
    -- string, that's why there is the L() macro, otherwise we'd get a String()
    -- instance, that might not work well with the native Lua library


    • This reply was modified 2 months, 3 weeks ago by dnaldoog dnaldoog.

    human fly

    ok so i’ve stepped back a bit, and restored the button step progress
    display -as the XOR thing depended on that. really need a way to get
    ‘count’ progress without that. (because, if possible, would like to
    do this without hidden objects – just to be a perfectionist – )
    -have not got XOR to work again yet, and have set buttonStep method
    to ‘none’ for the time being.

    this is just so i can tidy up *my mind* a bit lol. (there’s still
    quite a bit of junk and notes in the ‘unused’ folder)

    it now ‘resets’ on stop, as i want it to. but the position is
    +1step, because runCallback says ‘count+1’, and i haven’t
    figured out a way to make leftRight/rightLeft dictate that.
    (but i know now that i can get that to work)

    would like to have startTimer get the new tempo, but it doesn’t
    like a function name there. doesn’t mind a variable (milliseconds).
    s’pose that can be figured out.. i think i will skip attempting to
    declare on startup for the time being.

    it’s a headtwister, because when something crashes, it is
    because it depends on something that may depend on another
    thing … anyway that’s as far as i’m going for today. will
    have another crack at it later.
    (time consumption guilt avoidance routine)

    You must be logged in to view attached files.

    human fly

    i keep forgetting getName() as something to use.

    anyway, it seems that ‘_G()’ gives us a global variable
    reference, right? i’ve used it to make a new ‘seqLEDS()’
    (here i had 2 options to provide the ‘count’ – i’m trying
    to eventually establish a global variable called count, or
    *something* that doesn’t need a modulator -doh…probably
    simplicity itself- and for the time being proceding with
    the buttonsteps and count1_16 modulators)
    (i can probably ditch my ‘buttonsteps’ now, use the count1_16

    so that is much shorter now (don’t know if i need to change
    the i,j references? but it seems to run so far):

    function seqLEDs()
    --[count1_16 is already declared]--
    -- count1_16 = panel:getModulatorByName("count1_16"):getModulatorValue()
    for i=1,16 do
    --[can used count1_16 instead]--
    -- _G[count..i]		= panel:getModulatorByName("buttonSTEP"..i):getValue()
    _G["ledtext"..i] 	= panel:getModulatorByName("ledtext"..i):getComponent()
    	for j=1,16 do
    	-- if _G[count..i] == _G["ledtext"..i]
    	if count1_16 == _G["ledtext"..i]
    	then _G["ledtext"..i]:setProperty("uiLabelTextColour", "FF67EF00", false)
    	else _G["ledtext"..i]:setProperty("uiLabelTextColour", "FF0E2B01", false) end
    	end -- loop
    end -- loop

    human fly

    i’ve re-instated your method for XOR, and it works great :thumbsup:

    and i’m observing something interesting with the console command:
    (maybe intentional?/educational?)
    it ‘fires’ twice.
    if i put it within the 2nd ‘for’ argument, it fires 16x.
    if i put it at the top of the method (same as anywhere else, though,
    isn’t it), it also fires twice.

    so: am i to deduce from this … ? … that a method will run all
    the way through for each loop argument ? eg: complete one operation,
    and then go back and attack the 2nd operation ?
    not that this affects anything, just an observation.

    might have a go at pre-declaring these _G() statements…
    good find, although i still have to meditate on how they
    differ from L() statements.(you said ‘string’ vs ?? ..)
    (having noted that once something is declared globally,
    with a getValue/Name/etc., that become its ??status??
    ie: number value, etc. throughout, unless made local ..)


    human fly

    sideline objective, at some point, again, is to perhaps get
    realtime updating of timer milliseconds value in the timer
    callback. not critical, but for the hell of it..


    human fly

    coupla hours tidying and tweaking, with our new friend _G() 😉
    kicked out some junk, looks like it should be possible to tighten
    this up a bit declaring _G()’s early.
    but still no viable reset(), and still want to ditch buttonSteps
    and count1_16 (for anyone interested) — [see annotations] —

    >>panel/incrementor v33

    You must be logged in to view attached files.

    Now I don’t know where I read about _G, but take this example:

       local textwindow=L(panel:getModulatorByName("RENPATCH"):getComponent():getPropertyString("uiLabelText"))
        --grab characters from textwindow's output (as dec)
        ch1 = string.byte(textwindow, 1)
        ch2 = string.byte(textwindow, 2)
        ch3 = string.byte(textwindow, 3)
        ch4 = string.byte(textwindow, 4)
        ch5 = string.byte(textwindow, 5)
        ch6 = string.byte(textwindow, 6)
        ch7 = string.byte(textwindow, 7)
        ch8 = string.byte(textwindow, 8)
        ch9 = string.byte(textwindow, 9)
        ch10 = string.byte(textwindow, 10)
        ch11 = string.byte(textwindow, 11)
        ch12 = string.byte(textwindow, 12)
        ch13 = string.byte(textwindow, 13)
        ch14 = string.byte(textwindow, 14)
        ch15 = string.byte(textwindow, 15)
        ch16 = string.byte(textwindow, 16)
        if ch1 == nil then ch1 = 32 end
        if ch2 == nil then ch2 = 32 end
        if ch3 == nil then ch3 = 32 end
        if ch4 == nil then ch4 = 32 end
        if ch5 == nil then ch5 = 32 end
        if ch6 == nil then ch6 = 32 end
        if ch7 == nil then ch7 = 32 end
        if ch8 == nil then ch8 = 32 end
        if ch9 == nil then ch9 = 32 end
        if ch10 == nil then ch10 = 32 end
        if ch11 == nil then ch11 = 32 end
        if ch12 == nil then ch12 = 32 end
        if ch13 == nil then ch13 = 32 end
        if ch14 == nil then ch14 = 32 end
        if ch15 == nil then ch15 = 32 end
        if ch16 == nil then ch16 = 32 end
        for i=1,16 do -- check for illegal characters
            if _G[val] > 127 or _G[val] < 0 then
                console(String("illegal character entry",string.byte(_G[val])))
                _G[val]=95 -- illegal character becomes an underscore
            end -- < or >

    val="ch"..i is just assigning a string to the variable ‘val’, so if you take the _G[] out, you are comparing “ch1” (a string) etc to a number when you do if val > 127 or val < 0; that will throw an error, so to reference the actual variables ch1 to ch16 for values you need to surround the l-value with _G[]. You can even do _G[“ch”..i] – it works, but I don’t really know why. Well I think you know all this anyway.

    But the L() macro is completely different and as far as I can tell just changes the formatting of a string at a byte level. You can confirm this by printing the byte value of a non ASCII character – the byte value is different, but I don’t know what it’s for or how necessary it is. See attached panel. If you enter some text like for example Düsseldorf, you’ll see the difference.


    You must be logged in to view attached files.

    human fly

    well _G[] is doing its thing so far
    …except: i’m having trouble getting values from the pitch/cv
    combos with it:

    this runs ok, but the label just displays ‘0’
    (i have cv1-cv16 combos, with 0-11 range, trying to get the value,
    and display it as text on the label)(for starters…)

    for i =1,16 do 
    _G["cv"..i] = panel:getModulatorByName("cv"..i):getModulatorValue()

    human fly

    watch out for that, it’s a whole new way to lock up Ctrlr ! 😉


    Can you post a panel file of that?


    human fly

    sure thing.. i moved the setPropertyString thing out of the loop
    before resaving there 😉

    we’re on v35 now – have reduced the startup declarations to _G()
    statements but i don’t know if they are doing anything tbh.

    have renamed ‘sequence()’ as ‘pattern’ now. so that is called in
    the runCallback, and getting the pitchCV loop wrong makes the
    timer fail, without crashing any method (? new one …)

    this will run, but when the commented-out stuff is reinstated,
    there’s an error with the timer method.

    it is returning a ‘nil’ there, and you see the label_pitch display
    has ‘0’ on it – this should be giving the *value* of the “cv”1-16
    there. i’m pretty sure i want tables for this one, as it will be
    nice to show text pitches. nb: is it because they are combos? i didn’t
    think this would make a difference, since they still have a ‘value’.

    if the console statement is put outside the loop, it runs after each
    iteration – i don’t understand this too well: thought it would run
    once there. (i figure out how an earlier ‘print’ was running twice,
    in another method: it was associated with onValueChange, and i think
    i fixed it by switching it to mouseDown ie: the method was being
    triggered twice ? )

    (bearing in mind at this point a future consideration: this is
    *A* pattern. might want multiple patterns later …. ;o) )

    note also that i have a ‘trigLED’ that goes high when Run is on.
    i really want this to flash at the clock rate – but i think i know
    i need a 2nd timer for this, eh? something that runs once per
    callback, for a short ‘n’ on-time, probably?50mS?, something like
    that. (other project – a second timer callback could be useful
    for various things. it is basically a ‘monostable’ pulse that
    will represent the clock, and can be AND-ed with whatever for
    sync purposes.)

    note also that the count resets correctly on the ‘lcd’ atm.
    haven’t managed to get the run LED to do that, but don’t think
    that’s critical, since nothing should be ‘on’ there when the
    seq is a rest – or the first step will be skipped: it has to
    run 0-1 as it starts, i think, to play the first step? or it
    will be skipped, as it steps to 2. need to think about that…
    this is where a start latency would come in if that’s wrong.
    (not that this is going any further that just a demo at this
    point … 🙂 )

    You must be logged in to view attached files.

    human fly

    figured it out – got it:
    a label is a ‘component’, rather than a modulator. thus:

    for i =1,16 do 
    _G["cv"..i]	= panel:getModulatorByName("cv"..i):getModulatorValue()
    	if count1_16 == i then 

    human fly

    and i was able to follow that, for the console readout, with:
    (gave a new local variable for the cv, getting the string – not much
    use yet, but it does it. think it would be good to put it into a table,
    the way you showed me before – if a table can be continuously updated)

    local showPitch = panel:getComponent("label_pitchCV"):getProperty("uiLabelText")
    console(String("pitchCV ="..showPitch))


    You must be logged in to view attached files.

    human fly

    ok: success:
    i made a combo called ‘pitch output’, with the same entries
    as on the step combos – as i’m doing ‘getValue’ on the _G()
    statement, i can just do setValue (G thingy, false) and it’s
    all good, i get a summed running pitch cv output – presumably
    i can do this with anything else now – ie gate length, parameters,
    whatever. heheeee … :p (wi-ii-iiiiiii…)

    still want to figure out this short trig. i reckon 100msecs is ok.
    (speed is good though)

    i saw something about how only one timer can run at any one time,
    but researching it, there was also something about how separate
    clocks could run simultaneously – if i can find that again.


    human fly

    added some stuff.
    there’s a method called ‘stepProgress’ i had to disable.
    works sometimes? have had it working, anyway: it makes
    uiGroup backgroundColour1 change like a LED with the
    count1_16/buttonSteps. … not necessary and quite nasty.
    but i don’t know why it crashes yet.

    there is also an attempt at selectable random, but it
    only randomizes the first item of the first group.

    it’s all very rough, just sketching out a bit to see
    what can be done.
    >> v41

    You must be logged in to view attached files.

    human fly

    here’s my working solution for a multi-random setup:
    – with thanks to Proton, who provided the key some time ago,
    and dnaldoog for the _G[] thing –
    (this is for randomizing individual rows, depending on whether
    the ‘random-enable’ button is ‘on’ for that row, with a master
    ‘randomize’ button)

    -regarding the ‘_G[]’ expression, errors with these refer to
    a ‘field’, returning ‘?’ or something, and do NOT crash a method …
    (from observing stuff going on as i did this..)

    function randomizer()
    -- randomize selected parameter rows
    --	-- This variable stops index issues during panel bootup
    --	if panel:getRestoreState() == true or panel:getProgramState() == true then return end
    -- --------------------------------------------------
    -- random seeder
    	local t=os.time()
    	local c=os.clock()
    -- --------------------------------------------------
    for j= 1,5 do --[check random enable buttons]--
    _G["rand"..j] = panel:getModulatorByName("rand"..j):getModulatorValue()
    	for i= 1,16 do
    	if rand1 ~= 0 then 
    	_G["octv"..i] = panel:getModulatorByName("octv"..i):setValue(rnd1, false) 
    	if rand2 ~= 0 then 
    	_G["semi"..i] = panel:getModulatorByName("semi"..i):setValue(rnd2, false) 
    	if rand3 ~= 0 then 
    	_G["velo"..i] = panel:getModulatorByName("velo"..i):setValue(rnd3, false) 
    	if rand4 ~= 0 then 
    	_G["time"..i] = panel:getModulatorByName("time"..i):setValue(rnd4, false) 
    	if rand5 ~= 0 then 
    	_G["gate"..i] = panel:getModulatorByName("gate"..i):setValue(rnd5, false) 

    human fly

    had a horrible ‘lock-out’ crash with another method in this,
    (‘stepProgress()’: runs in the runcallback, and ‘runs’ the background
    colour of the uiGroups, if ‘progress’ button is enabled)
    -this is the one that keeps causing errors, not fixed yet.
    but will still run, somehow, after the error, because it doesn’t
    crash the method. s’pose the variables are in memory/known,
    after that ..(?) –

    that uses the _G[ ] thing … had to go into notepad to rename
    the function at the top of the method, to prevent it from
    runnning (my last-ditch resort, when Ctrlr won’t run or gets
    stuck: delete Roaming Ctrlr.settings file, then edit the last
    file as text and resave).

    i think the _G[ ] only ‘gets’ modulators(variables), after which it
    should be followed by getComponent() if you want the component. s’pose
    that makes sense … looking into whether this is why i’m getting
    ‘field’ errors.

    think the crash/lockout was either a loop or a conflict, or both.


    human fly

    i’ve moved this on a bit now. i’m using table.insert to
    add together the separate rows atm. probably not the best
    way to do it, but i want to see how far i get like this.

    this works ok: i get a single table, and can print out all
    the keys and values sequentially. ( for k,v in pairs etc.)

    i can concat. and get a single string of my data and look at
    that – but then it merges decimals with above 9 of course.

    also sent this to a memory block, to produce a hexString,
    but the number of bytes varies – due to blending of values,
    as above. i suppose this would not happen if i converted to
    hex before appending all the values.

    so this is what i’m mucking about with at the moment.
    i’m thinking about making pattern memories, recalling them,
    and what format that should be.

    the other stuff seems to be working quite nicely. have once
    observed inconsistent clocking from the sequencer timer count.
    multi-random, and getting the data all works reliably.
    (still haven’t done the secondary timer for producing pulses)


    human fly

    seem to have found this, to convert a decimal value table to hex:
    (on an existing table called tabl_current)

    tabl_hexcurrent = {}
    --convert decimal table to hex
    for k,v in ipairs(tabl_current) do 
    tabl_current[k]=string.format("%.2x", v)
    hexconcat = table.concat(tabl_hexcurrent," ")

    human fly

    littering the internet again … 🙂

    here’s a new version:
    the method to look at is ‘saveCurrent’, where i’m trying out
    a few things, converting decimal table to hex table, and then
    trying to getRange on a memory block of it, with something odd
    happening getting the 2nd range.

    **edit** figured that out; silly mistake: the 2 numbers after
    getRange are not start/end, they are start, and for how many.
    sorted, working.

    hit ‘Go!’ to randomize for new values, hit ‘write’ to get them
    on the displays. (note the ‘progress’ button for switching on/off
    a running display)
    ‘incrementor v51’ >>> panel

    You must be logged in to view attached files.
Viewing 20 posts - 21 through 40 (of 159 total)

You must be logged in to reply to this topic.

Comments are closed.