jtackaberry / reaticulate

An articulation management system for REAPER
Other
101 stars 46 forks source link

Filter programs combined with art output events can recurse infinitely #44

Closed Levitanus closed 5 years ago

Levitanus commented 6 years ago

Well, another question, related to FableSounds BBB and SampleModeling brass. There're many of cases with using second-level articulations (e.g. "hold C0 + hold D#1") And till I mapped fable everything was fine. But with samplemodeling there is only one optional key C2. So when articulation within C2 is held follows another the same, C2 (as written in manual of Reaticulate) is being released after it was pressed by the new articulation.

I can't avoid this conflict. Tried to make two additional positions in separate group: pressed and released. And press the note only if pressed is not active, but it produces some sort of recursion or infinite loop, as I have to turn the pressed art if released is active :) And all crashes

Bank file to reproduce the "crash":

//--------------------------------------------------------------------------
//! g="SampleModeling" n="Trumpet"
Bank 19 2 USER SMBrass/Trumpet
//! g=2
100 released
//! g=2
101 pressed

//! c=legato-light i=legato o=art:100
1 ART 1 Norm 
//! c=legato-light i=legato-portamento o=note-hold:36,100/note-hold:48,100%100/art:101%100
7 ART 7 chromatic
//! c=legato-light i=legato o=note-hold:37,100/note-hold:48,100%100/art:101%100
Levitanus commented 6 years ago

By the way, it produces the same issue (getting the note off without "crashing magic") if cursor moved on stop in the range of one articulation bank

jtackaberry commented 6 years ago

I think I'm not too surprised that this causes some infinite loop. It's a clever use of output filtering and articulation output events and quite a bit too clever for the intended uses. :)

Of course it shouldn't hang. So I'll need figure out how to detect this case and avoid the infinite loop.

In the meantime, back to the original problem you were trying to solve, are you saying with the Samplemodeling Trumpet example that you need to keep C2 (note 48) held between articulations?

I have the Samplemodeling Trumpet but unfortunately for some reason the different portamento types aren't working for me. Still, looking at the docs, it's not clear there should be a problem with retriggering the C2 between different articulations.

So wouldn't something like this work?

//! c=legato-light i=legato
1 normal portamento
//! c=legato-light i=legato-portamento o=note-hold:48/note-hold:36,100
7 chromatic portamento
//! c=legato-light i=legato o=note-hold:48/note-hold:37,100
8 mixed portamento

Program 1 has no output events, so this will serve to release any held notes from the other programs.

jtackaberry commented 6 years ago

BTW in your example note 48 was listed second, but I think it needs to be first, because C2 initiates the second-level keyswitch.

Levitanus commented 6 years ago

Jack, yep, it also worked for me. The problem is going through the arrange. If somewhere 7 or 8 has been used, with moving the cursor to the other one active articulation causes releasing of note 48. Here is the point: there is no way to avoid manual switching to the 1st pr change. And when you have 7-8 instruments in the stack...

Levitanus commented 6 years ago

ohhh... It seems, there is a bug inside the trumpet itself :-O I need to fing the fisrt version to check if it's systematic) But it is not taking the question about "moving cursor" cases back...

jtackaberry commented 5 years ago

Reduced test case:

//! g=2
100 released

//! c=legato-light i=legato o=art:100
1 Norm
//! c=legato-light i=legato-portamento o=art:101%100
7 chromatic

Sequence of events:

  1. User triggers Norm
  2. art output event implicitly activates art 100
  3. The internal logic notices that art 100 acts as a filter and therefore retriggers the active articulations on all groups.
  4. This causes Norm to get re-triggered and loop back to 2.

Technically step 3 could simply check the output events of the active articulation in group 1 and notice that none of them are filtered, and therefore doesn't need to be retriggered. But this doesn't fundamentally fix the infinite recursion which could take different (and more indirect) paths.

The more permanent fix is to keep track of emitted art output events (by means of 4 32-bit bitmaps) and refuse to re-emit anything that was already emitted. This should prevent all forms of recursion shenanigans.