update: v1.1.0

  • you can now sequence cc’s
  • cc’s are just lists of pairs of numbers, they are chain-able like everything else (see the documentation above)

here’s a quick demo with tmi sequencing the chords and ccs. the ccs are modulating the vcf cutoff and envelope depth simultaneously (at two different frequencies). i’ve never tried this before and its actually quite cool imo:

i realize typing cc’s is wonky, so there is a script you can run (~/dust/code/tmi/lib/cc_lfo.lua) which you can use to generate the tmi files with lfos from ccs (could make this easier too if it seems useful).

thank you @glia for spurring this update!

the sounds sound different, but they are actually the same voice! just with different octave and velocity. plinky has 8 voices so you can keep adding tmi scripts until you run out of voices (i think that demo used 5). the adsr/filters/effects are the same across all the voices on plinky, though it would be awesome to be able to specify individually :slight_smile: i picked two parts that sounded good with the same adsr/filter/effects.

8 Likes

just amazing
thank you for adding my request so quickly!

1 Like

ah, i would never have guessed! but looking at the demo again, i guess it’s obvious that’s what the mezzo piano (mp) command does. is there comprehensive list of other commands for someone like me whose renaissance italian needs brushing up? : )

2 Likes

haha you actually don’t really need that at all anymore. instead of a mute button there is a “scaling” slider which you can use to scale the velocity/volume for notes so that a slot can be louder/softer than others. this also will work for cc’s, the values will be scaled up/down to change the range of its values too.

however if you want to have a bunch of different dynamics, then you can use the piano/forte commands. here there are also two choices though - you can either append the fortismo/pianismo command (pp, p, mp, mf, f, ff, or fff) or you can actually just supply a velocity number (0-127). so that means the following two tmi files are equivalent (each of these both play one note louder and louder):

c_mp d_mf e_f g_ff

is equal to

c_50 d_60 e_80 g_100

the “_X” syntax is not the loveliest thing in the world, which is why you can forgo entirely if you don’t need it and just use the “scaling” slider in the parameter menu if you don’t need to have each note be different.

3 Likes

thanks for the clarification! makes sense.

1 Like

HOLY SHIT. This is killer.

1 Like

i’m testing right now and not sure what it means…do i use cli on my laptop or maiden for this?

1 Like

that command specifically is for the laptop command-line. but you can run it from maiden if you wrap it in os.execute. i.e. this should work in maiden:

> os.execute("lua /home/we/dust/code/tmi/lib/cc_lfo.lua > /home/we/dust/data/tmi/your_ccs")
1 Like

Bonkers, in a good way. Great job! Does tmi pick up file changes on its own, or does the user reload the file?

1 Like

tmi automatically detects saved changes and reloads the file and continues playing from where it was (if you delete a measure though, it will cause a change in measures).

one caveat, currently it is a little clumsy as it will stop all the currently playing notes for that track instead of calculating which notes changed - this is to prevent notes from ringing out forever if you delete them while they are playing. i plan on upgrading this really soon (a pretty easy fix). this is fixed now :slight_smile:

3 Likes

This is really wild. I love it and really appreciate the ‘out of the box’ approach here.

1 Like

to be able to just write the chords! so so useful. thank you so much for this and all the rest.

edit: trying to use this with Orca, which, of course, has midi, the TMI menu is not immediately coming up with a Volca FM or digitakt plugged in. which is probably for the best, i don’t know why I need to have absolute control over every single thing. :stuck_out_tongue:

1 Like

Would it be possible to use tmi internally - let’s say for sequencing the root note within a script, for example?

1 Like

absolutely. you can do add this to the script, anywhere…but probably near the top will work most often:

if util.file_exists(_path.code.."tmi") then 
  tmi=include("tmi/lib/tmi")
  m=tmi:new()
  m:load("op-1","/home/we/dust/data/tmi/rootnote",1)
  m:toggle_play()
end

of course, change “op-1” to the your instrument (it will match any part of the name you put in). the toggle_play will have it start playing right away (you could also put toggle_play somewhere specific, like at a button press or something).

then you can make the /home/we/dust/data/tmi/rootnote file which contains your root note(s). here’s an example which changes between c and e every 4 beats:

c1
e1

hmmm. i just tried with orca and it works for me. where did you put your tmi code? (i put it at the very top of orca.lua). do you have those two devices listed in SYSTEM > DEVICES > MIDI ?

1 Like

thank you very much for your reply. well, let me be a bit more precise: what i meant with “internally”, was sequencing the root note inside a script - flora in my specific case, not an external instrument via midi. so instead of mapping a midicontroller to the root note, i was thinking of changing that parameter via tmi (does that make sense?) but it could be, i probably misunderstood the whole concept of tmi, which works only with external gear …?

1 Like

i think i understand now - you’d like to be able to use the tmi sequencer to sequence a note from the supercollider engine of the current script you are using (in this case flora)?

1 Like

yup, exactly that. but my gut feeling is that it probably can’t be done, can it? at least i don’t know how to do that. anyway - at the moment i’m having a blast with my op-1 and your great script ; ) thanks for sharing!

1 Like

it can be done! pretty easily too.

basically i’ll add a little fix so that you can define your own function to be used with tmi. if the function is supplied it will use it as a “virtual instrument”

4 Likes

wow - that is genius! i wish, i could do such things myself and contribute to this awesome community, but i couldn’t wrap my head around coding yet. i tried a few times but failed grandiosly each time. thank you so much for making this possible. i’ll give it a try right away - has it been implemented yet?

1 Like

@moono i just added it now! i’ve tested it and it seems to work fine, but why don’t you give it a test run and let me know?

it turned out to be a little tricky to code since it needs to accommodate any possible engine function.

here’s how it works:

if you want to add your engine function (or any function for that matter!) you can use the following, an example using the polyperc engine.

engine.name = 'PolyPerc'
MusicUtil=require "musicutil"
if util.file_exists(_path.code.."tmi") then 
  tmi=include("tmi/lib/tmi")
  m=tmi:new({
    functions={
      {name="polyperc",note_on="engine.amp(<velocity>/127); engine.hz(MusicUtil.note_num_to_freq(<note>))"},
    },
  })
end

as you can see there is a functions map that you can pass to tmi now. inside that is where the magic happens.

the “name” gives your thing an identifier. the “note_on” defines some lua code to run when a note goes on. the lua code can be anything you want. the lua code can take two values - the midi note ("<note>") and the velocity ("<velocity>", ranging 0-127). its basically up to you to make sure these values fit into whatever function you want. for instance, for the PolyPerc engine you have to enter use engine.amp, so you have the scale the velocity by 127 for it work. similarly, the PolyPerc engine needs to emit notes with the frequency, not the midi note so you have to convert it using the MusicUtil.

you can also write a similar function for note_off which is emitted when notes go off, but PolyPerc doesn’t really have a note off since its one-shots.

this new syntax gives a lot of flexibility. you can write whatever lua code you want to run when notes go “on” and “off” and you can have as many functions as you want. you don’t have to include “<note>” or “<velocity>”, but if you do make sure to transform them for your own purpose within your lua code.

4 Likes