playbenny / benny

a live music environment
Other
73 stars 3 forks source link

new midi router #6

Closed jamesholdenmusic closed 1 year ago

jamesholdenmusic commented 1 year ago
jamesholdenmusic commented 1 year ago

how it currently works: midi note arrives srcvoiceno 128 + output no -> lookup in midiroute coll to get a list of destinations ^^1024 + destination voice -> lookup in conversion dict, where you get rotation scaling mute and target input number () src voice: 0-64 notes, -128 audio, 128 on are audio to midi dest voice: 0-127 pollyalloc, 128 notes 192 audio 256 hw midi outs 512 param mod buffer 1023 scopes

idea: if conversion can hold input number it could also hold dest voice. then it's not indexed by this weird sum, but by connection id, and any input (voice/outputno combined) lookup just returns a list of connection ids. this would make conversion a lot smaller, which might speed up access a little? and it solves the bug (no two conns from same obj to same target) and the lists can hopefully be efficiently stored - in a buffer?

jamesholdenmusic commented 1 year ago

midi meters could even be separate code, but you kind of may as well do them at the same time.. if separate then you could deferlow but i don't think it's a big deal.

jamesholdenmusic commented 1 year ago

poly allocators need to be able to have more outputs - the block level envelope trigger output for example.

jamesholdenmusic commented 1 year ago

ok so option A: (output no, source no) -> (small lookup array, eg 128 entries per source, holding id's - pointers to the bigger connection/conversion array) -> connection/conversion array - indexed by id's so not massive -> holds destination type, number, conversion parameters

or option B: (output no, source no) -> a single huge lookup, but all contigious. the source is multiplied up to an index and then there are 128 * 8 samples -> each group of 8(??) is a connection, with destination, conv params in a row. then if the next group of 8 has a nonzero destination you know there's more. have to rewrite every entry if one gets removed? or be smarter, just copy them along

ok B it is expand sources list to include polyrouter (block-level) output too (at the end, less used)

remember dest input is just 128* added to note

existing implementation has 'types' to specify what happens with dimensionality of io types: 1 - 1d->1d scale, offset <- remove offset 2 - 1d->2d scale, rotate, offset: x = o_x + sin(rotate) scale in, y = o_y + cos(rotate) scale in 3 - 2d ->1d project 2d to 1d via angle then scale (offset but remove it now) is out = scale (sin(rotate) x + cos(rotate) * y ) 4 - 2d->2d scale (vel), offset (both) the 1d outputs only go to the mod section. if a 2d output goes to the mod section its second value (vel) is ignored, so that seems wrong - it probably never happens?. 2d outputs go to poly/note/audio/hardware/maybe mod but surely not

maybe keep type.

but no need to do sin and cos on every event: calculate a scaling value for note and vel, and an offset value for each, do that instead. 4 values (was scale,rotate,offsx,offsy so no change)

so mute first, so you can skip the rest? from what i read that might not make much difference conversion type dest type (note, hardware, mod, etc) dest voice, dest input number scale-n,scale-v, offset-n, offset-v

it's 9 but *9 is much less work than doing some % <<>> bullshit to pack two things into one value

jamesholdenmusic commented 1 year ago

pointer is 9 ( index + max_connections_per_output (outputno + voiceno * max_outputs_per_voice ) ) where index is the connection no, for this voice/output pair. this is about 2.5million samples - 21mb. very nbd.

the gen loop needs to exit on first empty slot, otherwise it's doing a lot of looping for nothing every single note. so we need to keep the data tidy - if you remove one connection, you move the others down. therefore the current system (delete connection, rewrite connection??) when you make adjustments is way too messy. on adjust, we need to look up what the index is, from the connection number???

in old system, connections could have multiple outputs (with the same conversion parameters - scale etc). this system allows for multiple outputs in a different way, i think it's a waste to build another system on top right? so, for one connection number you may have multiple indexes. in the present design it's just multiple voices it may go to, not multiple outputs, which makes sense to keep, so we index on connection number and target voice (ie 0,1,2,3,4 - voice no of the block, not allocated voice). this improvement means you could do the rotator circle or whatever to make non-identical mappings across voices using midi

so routing_index[cno][destvoiceno] = index in the formula at the top of this post

or does it need to be indexed by destvoice, can r_i[cno] just hold a list? make connection: you make the list adjust connection: you use the list for lookups, you assume they're in the same order they were BUT: each call to set_routing is ignorant of where in the list you are, unless you say? change voices of connection: you remove it and remake remove connection: you use the list to look up which indexes to remove.

jamesholdenmusic commented 1 year ago

remaining jobs: there are a few bugs - especially around removing connections needs to be tested a lot!!!!! write documentation thin out unused calculations in make/remove connection code

you could have midi metering of the output of connections easily?

jamesholdenmusic commented 1 year ago

i'm marking this done because any new issues can be new issues. it's compatible with the polyallocs outputting stuff directly back to the router but you'll need to build that, almost entirely in the js.