MIDI Note-Detect, Iterator, Structures + JavaScript Issues

toneburst's picture

I'm working on a really simple MIDI note visualisation engine, and have hit a frustrating problem. I've setup a composition to to make a red square appear whenever a note in the range C1 > B1 is pressed. So, I have an Iterator with 12 iterations, each iteration corresponding to 1 note. I'm attempting to handle multiple retriggers of the same note within a short period by nesting another Iterator inside the first. The problem is, the same setup that works for a single key trigger (the inner Iterator) does not work properly when nested. It works perfectly when it's not though. I can't work out what the problem is.

I'd be really grateful if someone could have a look at the attached QTZ and tell me if it's conceptually flawed, or if I've stumbled on a bug.

Oh, I'm using MacOS 10.6.1.

Thanks a lot guys!

a|x

PS Some of you may have seen this on the Apple QC Devlist. Haven't had any luck there so far, so thought I'd try here too. Apologies for the cross-posting.

PreviewAttachmentSize
tb MIDI Detect Test 13-03-10.qtz30.31 KB

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

I doctored the item by getting rid of unrestored midi notes patch and inputting from the standard midi notes receiver, saved and reopened file - no error message - now looking to see what else needs attention.

Tried switching to mono version - got a red square - got a crash - see attached.

PreviewAttachmentSize
midi-tb-crash.zip15.87 KB

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

and now I get replicate performance in both mono and replicate versions.

see attached, all that's been done is to associate a MIDI Notes Receiver and connected that up in the Midi Notes macro and set an Interpolator to churn the Bass Note index on your script and voila a lot of iterations, starting and stopping, possibly not quite what you were looking for .

PreviewAttachmentSize
tb_MIDI_Detect_Test_13-03-10_0.qtz30.7 KB

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Wow, rapid response! Morning cybero.

Heeehee, nope, not at all what I was looking for...

Also, I get

> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 490 nodes>: Bundle at path "/Library/Graphics/Quartz Composer Patches/SafeAudioInput.plugin" is not a valid Graph Foundation plug-in
 
> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 496 nodes>: There is already a node registered with name "StructureMaker:KinemeNamedStructureMaker"
 
> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 496 nodes>: There is already a node registered with name "StructureMaker:KinemeStructureMaker"
 
> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 521 nodes>: Bundle at path "/Library/Graphics/Quartz Composer Patches/v002 Optical Flow.plugin" is not a valid Graph Foundation plug-in
 
> (null)
QCPlugIn: Cannot preflight plug-in at path "/Users/alx/Library/Graphics/Quartz Composer Plug-Ins/MatrixToParams.plugin" (Error Domain=NSCocoaErrorDomain Code=3585 UserInfo=0x15853d40 "The bundle “MatrixToParams” couldn’t be loaded because it doesn’t contain a version for the current architecture." (dlopen_preflight(/Users/alx/Library/Graphics/Quartz Composer Plug-Ins/MatrixToParams.plugin/Contents/MacOS/MatrixToParams): no suitable image found.  Did find:
   /Users/alx/Library/Graphics/Quartz Composer Plug-Ins/MatrixToParams.plugin/Contents/MacOS/MatrixToParams: mach-o, but wrong architecture))
 
> (null)
QCPlugIn: There is already a QCPlugIn registered for class "v002FilmLomoPlugIn"
 
> (null)
QCPlugIn: There is already a QCPlugIn registered for class "v002525PlugIn"
 
> (null)
QCPlugIn: There is already a QCPlugIn registered for class "v002AnalogGlitchPlugIn"
 
> (null)
QCPlugIn: There is already a QCPlugIn registered for class "v002FBOGlitchPlugIn"
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_66" @ "MidiNotes_2"] to ["note_6" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_71" @ "MidiNotes_2"] to ["note_11" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_67" @ "MidiNotes_2"] to ["note_7" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_60" @ "MidiNotes_2"] to ["note_0" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_68" @ "MidiNotes_2"] to ["note_8" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_62" @ "MidiNotes_2"] to ["note_2" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_69" @ "MidiNotes_2"] to ["note_9" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_64" @ "MidiNotes_2"] to ["note_4" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_70" @ "MidiNotes_2"] to ["note_10" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_65" @ "MidiNotes_2"] to ["note_5" @ "JavaScript_2"]
 
> Macro Patch
State restoration failed on node "Patch_1" <QCPatch = 0x1585FAF0 "(null)">
 
> (null)
State restoration failed on <QCPatch = 0x1585F1C0 "(null)">

on opening.

Let me try your other one.

a|x

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Oh, the 'other one' is a crash report. lol

a|x

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

actually left the multiplex output unattached from when checking why I got a crash, you shouldn't have any such problem on your opening that .qtz though, that's either a different .qtz, a cache related problem or something seriously weird. I've looked throughout the xml and no mention of v002 related stuff.

is the midi notes patch truncated? is it actually unattached even amputated - sans notes - ?, that's why you might have the js error messages that might be to do with the file, the copy I uploaded was meant to be good to go, I shall zip this one for safety's sake.

PreviewAttachmentSize
tb_MIDI_Detect_Test_13-03-10_0.qtz.zip10.33 KB

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Still get all the same exceptions on opening your QTZ, which is odd. Also, it crashes the Finder when trying to preview it in a window set to Column view. Odder still.

I must say I've been having a few crashes working on this. Dunno if it's JavaScript instability or something to do with the MIDI Note Receiver (which incidentally now seems to be refusing to work, for some reason).

a|x

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

This has got to be some kind of Iterator-related f^ck^p going on. It looks like for some reason all Iterator instances are getting the same data, or something inside each Iteration is.

Maybe I can work around it by combining the multi-trigger-detect JS that's currently inside the Iterator with the note-detect > structure JS attached to the Note Receiver, so it sends out a multi-dimensional struct as below, then just passing that into the nested Iterators and picking the appropriate sub-structure.

note1
   trigger1
      notenum
      velocity
      fadetime
   trigger2
      notenum
      velocity
      fadetime
   trigger3
      notenum
      velocity
      fadetime
note2
   trigger1
      notenum
      velocity
      fadetime
   trigger2
      notenum
      velocity
      fadetime
note3
   trigger1
   ... etc.

I'll give that a go. JavaScript is slow, but it should be OK for this scenario, I'd have thought.

What do you think?

a|x

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Just as a matter of interest, I hope you haven't suffered any other similar crash from any other files of mine.

QuickLook does have a .qtz issue or two in any case.

Could also be a a 10.5 to 10.6 migration issue, especially when travelling back in time , so to speak.

Try reverse engineering a Leo and a separate Snow Leo version, see if one is more stable than the other.

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 490 nodes>: Bundle at path "/Library/Graphics/Quartz Composer Patches/SafeAudioInput.plugin" is not a valid Graph Foundation plug-in
 
> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 496 nodes>: There is already a node registered with name "StructureMaker:KinemeNamedStructureMaker"
 
> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 496 nodes>: There is already a node registered with name "StructureMaker:KinemeStructureMaker"
 
> (null)
<QCNodeManager | namespace = "com.apple.QuartzComposer" | 521 nodes>: Bundle at path "/Library/Graphics/Quartz Composer Patches/v002 Optical Flow.plugin" is not a valid Graph Foundation plug-in
 
> (null)
QCPlugIn: Cannot preflight plug-in at path "/Users/alx/Library/Graphics/Quartz Composer Plug-Ins/MatrixToParams.plugin" (Error Domain=NSCocoaErrorDomain Code=3585 UserInfo=0x15853d40 "The bundle “MatrixToParams” couldn’t be loaded because it doesn’t contain a version for the current architecture." (dlopen_preflight(/Users/alx/Library/Graphics/Quartz Composer Plug-Ins/MatrixToParams.plugin/Contents/MacOS/MatrixToParams): no suitable image found.  Did find:
    /Users/alx/Library/Graphics/Quartz Composer Plug-Ins/MatrixToParams.plugin/Contents/MacOS/MatrixToParams: mach-o, but wrong architecture))
 
> (null)

I think all of the above is down to plugins that are on your system a|x

Cannot create connection from ["key_66" @ "MidiNotes_2"] to ["note_6" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_71" @ "MidiNotes_2"] to ["note_11" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_67" @ "MidiNotes_2"] to ["note_7" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_60" @ "MidiNotes_2"] to ["note_0" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_68" @ "MidiNotes_2"] to ["note_8" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_62" @ "MidiNotes_2"] to ["note_2" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_69" @ "MidiNotes_2"] to ["note_9" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_64" @ "MidiNotes_2"] to ["note_4" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_70" @ "MidiNotes_2"] to ["note_10" @ "JavaScript_2"]
 
> MIDI Note Input (Macro)
Cannot create connection from ["key_65" @ "MidiNotes_2"] to ["note_5" @ "JavaScript_2"]
 
> Macro Patch
State restoration failed on node "Patch_1" <QCPatch = 0x1585FAF0 "(null)">
 
> (null)
State restoration failed on <QCPatch = 0x1585F1C0 "(null)">

I think all that immediately above is down to the MIDI patch not being truly portable - hence why I tried zipping up the second upload of the re-tweak of your example problem case.

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Could be. I'm just using the standard MIDI Note Receiver patch here in Snow Leopard (not the Kineme version from MIDI Tools).

I don't currently have a 10.5 system to test stuff on, unfortunately. It's doubly-unfortunate because the person I'm developing these things for is still running Leopard.

I do have a lot of plugins installed, right enough. The funny thing is, I wasn't using any of them in this QTZ- 100% 'stock' patches.

Thanks for your time on this, mate. I think I'll try the JavaScript approach I outlined above, and see if it works better. Gotta go and do housework now though.

Thanks again,

a|x

cwright's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

toneburst wrote:
I don't currently have a 10.5 system to test stuff on, unfortunately. It's doubly-unfortunate because the person I'm developing these things for is still running Leopard.

False.

File Menu -> Test In Runtime -> Leopard (32 or 64bit -- 32 is most typical for Leopard).

The runtimes are the actual builds from those versions of QC -- the only changes, if any, are small tweaks to maintain compatibility (when possible).

Also, the Option key will give you Garbage Collected variants -- a handy trick for plugin developers (and app developers who insist on using GC and using QC...)

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Good point cwright. I will try that. Thanks for the tip.

a|x

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

OK, got it working!

Haven't tried it in (simulated) Leopard yet, but working in SN, anyway.

Here's the JavaScript:

///////////////////////////////////////////////
// Function to init each item in notes array //
///////////////////////////////////////////////
 
function initNoteArray(array) {
   for(i = 0; i < array.length; i++) {
      var sub = new Object();         // Init object to hold note values
      sub.NoteNumber = 0;            // MIDI Note number
      sub.Velocities = new Array();   // Velocities (array to hold multiple trigger values)
      sub.OldVelocity = 0;         // Velocity at previous frame
      sub.Triggers = 0;            // Number of triggers of this note
      sub.FadeTime = new Array();      // Fade-time (array to hold multiple trigger values)
                              // Allows animation after note-off
      array[i] = sub;               // Add object to array at index i
   }
   return array;
}
 
// Init notes array with objects
var notes = initNoteArray(new Array(12));
 
////////////////////////
// Main function loop //
////////////////////////
 
function   (__structure Notes)
         main
      (__number Note[12], __index BaseNote, __index FadeTime, __number forceRun)
{
   // Set fade-increment based on FadeTime input
   var fadeIncrement = 1 / FadeTime;
 
   //////////////////////////////
   // Loop through note inputs //
 
   for(i = 0; i < 12; i++) {
 
      // Set MIDI note number based on base note no.
      // (assumes all notes in octave detected)
      notes[i].NoteNumber = i + BaseNote;
 
      // When note-on detected
      if(Note[i] > notes[i].OldVelocity) {
         notes[i].Velocities.push(Note[i]);
         notes[i].FadeTime.push(0);
         notes[i].Triggers++;
      }
 
      // If notes have been hit
      if(notes[i].FadeTime.length > 0) {
         // Increment FadeTime for triggered notes if less than 1
         for(j = 0; j < notes[i].FadeTime.length; j++) {
            notes[i].FadeTime[j] = (notes[i].FadeTime[j] < 1) ?
               notes[i].FadeTime[j] + fadeIncrement : 1;
         }
         // Check if last item in FadeTime array is 1
         if(notes[i].FadeTime[notes[i].FadeTime.length - 1] == 1) {
            // Init Velocities and FadeTime arrays and Triggers var
            notes[i].Velocities = new Array();
            notes[i].FadeTime = new Array();
            notes[i].Triggers = 0;
         }
      }
 
      // Set OldVelocity for this note to current velocity
      // to allow detection of new note-on in subsequent frame
      notes[i].OldVelocity = Note[i];
   }
 
   // End looping through note inputs //
   /////////////////////////////////////
 
   // Output object
   var result = new Object();
   result.Notes = notes;
   return result;
}

I'm wondering now if some OO-based approach might be more elegant. Have you done much work with Object-Orientated JavaScript, cybero? I had a go at it a while back, but haven't tried it since. I'm so used to coding procedurally I find it really hard to think in terms of objects and instances. I'm going to have to get used to it though, as I'm being asked to learn ActionScript 3 at work now, and I'd really like to (finally) get properly into Objective-C coding, as my list of custom QC patch ideas keeps growing.

a|x

PreviewAttachmentSize
tb MIDI Detect Test 14-03-10.qtz27.17 KB

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Action Script 3 - what do you make of Flash GPU optimisation - a little too swift in my experience to date - flashes by in a trice - no pun intended.

Congratulations on getting the script sorted. a neat job BTW.

JS, of course, already deals with objects, they are our results.

I haven't really delved as deeply into JS prototyping in QC as elsewhere, though some of the old arguments about low speed of operation seem to fall down when weighed against the number of patches you'd have to put into place for the same sort of outcome & the fact that JS execution has generally improved with each update to that framework.

Had to replace the Midi Notes Receiver patch, the little baby didn't survive transit from your editor to mine, there wasn't much left of it, just a useless title - and consequently I got a JS error to begin with

PreviewAttachmentSize
poorlostpatch.png
poorlostpatch.png52.94 KB

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Did you get it working in the end?

Dunno why the MIDI Notes Receiver settings didn't restore correctly. That patch needs some work, I think. Being able to programmatically set input, channel and notes to detect would make it much more usable, especially if there was a 'MIDI System Info' patch to go with it.

I've not really looked into Flash GPU graphics, to be honest. When I said I'd had to learn Actionscript, I didn't say how far I'd got ;) Not very, in fact....

I knew a little ActionScript 2, but obviously, most of that's had to go out of the window now AS3 has appeared.

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

The Note structure outputs but does not contain a trigger on any note at all.

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

I guess that's because the MIDI Notes Receiver hasn't been restored properly? Or not?

This one might be better, maybe.

Oh, and it's only supposed to work with notes in the octave selected in a 1-octave range (octave selected with Octave control of MIDI detect macro).

a|x

PreviewAttachmentSize
tb MIDI Detect Test 14-03-10 02.qtz38.5 KB

cybero's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Proof positive and how :-)

[Midi Detect Script MIDI_D - like Sunny_D

As it happens I had to set the Notes Receiver to Middle C 3 /3, must be my use of keyboard, but -1 wouldn't work for me at all. Also All Midi Sources also gives the pulsing blob too.

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

MIDI Notes Receiver is definitely Not Right.

The idea was to have a single Note Receiver that received all notes, then filter then filter the notes that are actually used in the JS patch, but maybe that's not going to work out.

Having to connect 120 outports to 120 inports is no way to spend an afternoon. I was seeing afterimages of that bright pink box for several minutes afterwards....

The Kineme version is probably more reliable, but I was hoping to do this without and 3rd-party patches. The Kineme MIDI input patch seems a bit difficult to deal with, too, as it's going to require a bit of work to parse the output structures to extract usable data, as far as I can tell.

a|x

toneburst's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Radar Bug ID# 7754732 submitted after confirmation of same problem on another person's machine.

Looks like it's not just you and me, cybero.

a|x

dust's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

check this out. it started as a high score sorter. first i made a structure with key values like name is the key and score is the value. in order to sort both values and keys i needed to make a second structure that stores all the keys as values and values as keys so i could iterate through and display scores with the proper names.

so i took that and changed it to work with midi notes. there is a little obscurification going on now but basically i turned the keyed structure sorter into a midi note structure sorter by typing in char value of the note wanted.. in order to calculate the midi note number i just started from octave 0 at base note 12 and hooked and added one down the line etc... all in qc without code except for the java script that turns the chars into the respective index values of the octave and notes to display the correct note number.

just made this because i can never remember midi note numbers but am ok with c#3 notation etc.. its even harder by octave index and note index but to put that into perspective note index 0 with octave index 3 gives you c3.

maybe this will help. there is some note output which im working on a plug-in to structure osc values so i can send a midi message via osc in the corect byte format needed to play a note etc...

PreviewAttachmentSize
Structure Key Value Note Octave Sorting.qtz303.41 KB

jersmi's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

toneburst and dust -- both these patches are super nice and appreciated. just found them, and i am grateful.

jersmi's picture
Re: MIDI Note-Detect, Iterator, Structures + JavaScript ...

Hi dust, Wondering if you'd be willing to share the structure sort macros in your patch? appears to be what i am looking to do but can't get yet.