Audiobus: Use your music apps together.

What is Audiobus?Audiobus is an award-winning music app for iPhone and iPad which lets you use your other music apps together. Chain effects on your favourite synth, run the output of apps or Audio Units into an app like GarageBand or Loopy, or select a different audio interface output for each app. Route MIDI between apps — drive a synth from a MIDI sequencer, or add an arpeggiator to your MIDI keyboard — or sync with your external MIDI gear. And control your entire setup from a MIDI controller.

Download on the App Store

Audiobus is the app that makes the rest of your setup better.

Request Mozaic help midi output depend on chord input

24567

Comments

  • Here is a copy from MidiWrench.
    I played the following chord buttons on my accordion:

    C major, C minor, C seventh, C diminished
    G major, G minor, G seventh, G diminished

    23:10:59.828 [Note On] ch=2 note=60 velocity=60
    23:10:59.828 [Note On] ch=2 note=64 velocity=60
    23:10:59.828 [Note On] ch=2 note=67 velocity=60 [MP]
    23:11:00.098 [Note Off] ch=2 note=60 velocity=57
    23:11:00.098 [Note Off] ch=2 note=64 velocity=57
    23:11:00.098 [Note Off] ch=2 note=67 velocity=57 [MP]
    23:11:01.583 [Note On] ch=2 note=60 velocity=60
    23:11:01.583 [Note On] ch=2 note=63 velocity=60
    23:11:01.583 [Note On] ch=2 note=67 velocity=60 [MP]
    23:11:01.852 [Note Off] ch=2 note=60 velocity=44
    23:11:01.852 [Note Off] ch=2 note=63 velocity=44
    23:11:01.852 [Note Off] ch=2 note=67 velocity=44
    23:11:03.444 [Note On] ch=2 note=60 velocity=55
    23:11:03.444 [Note On] ch=2 note=64 velocity=55
    23:11:03.444 [Note On] ch=2 note=70 velocity=55 [MP]
    23:11:03.444 [Note On] ch=2 note=67 velocity=55
    23:11:03.728 [Note Off] ch=2 note=60 velocity=42
    23:11:03.728 [Note Off] ch=2 note=64 velocity=42
    23:11:03.728 [Note Off] ch=2 note=70 velocity=42
    23:11:03.728 [Note Off] ch=2 note=67 velocity=42 [MP]
    23:11:05.559 [Note On] ch=2 note=60 velocity=61
    23:11:05.559 [Note On] ch=2 note=63 velocity=61
    23:11:05.559 [Note On] ch=2 note=69 velocity=61 [MP]
    23:11:05.559 [Note On] ch=2 note=66 velocity=61
    23:11:05.887 [Note Off] ch=2 note=60 velocity=49
    23:11:05.888 [Note Off] ch=2 note=63 velocity=49
    23:11:05.888 [Note Off] ch=2 note=69 velocity=49
    23:11:05.888 [Note Off] ch=2 note=66 velocity=49 [MP]
    23:11:11.513 [Note On] ch=2 note=55 velocity=58
    23:11:11.513 [Note On] ch=2 note=71 velocity=58
    23:11:11.513 [Note On] ch=2 note=62 velocity=58
    23:11:11.873 [Note Off] ch=2 note=55 velocity=1
    23:11:11.873 [Note Off] ch=2 note=71 velocity=1
    23:11:11.873 [Note Off] ch=2 note=62 velocity=1 [MP]
    23:11:12.998 [Note On] ch=2 note=55 velocity=56
    23:11:12.998 [Note On] ch=2 note=70 velocity=56 [MP]
    23:11:12.998 [Note On] ch=2 note=62 velocity=56
    23:11:13.313 [Note Off] ch=2 note=55 velocity=39
    23:11:13.313 [Note Off] ch=2 note=70 velocity=39
    23:11:13.313 [Note Off] ch=2 note=62 velocity=39
    23:11:14.633 [Note On] ch=2 note=55 velocity=62
    23:11:14.633 [Note On] ch=2 note=71 velocity=62 [MP]
    23:11:14.633 [Note On] ch=2 note=65 velocity=62
    23:11:14.633 [Note On] ch=2 note=62 velocity=62
    23:11:14.917 [Note Off] ch=2 note=55 velocity=54
    23:11:14.917 [Note Off] ch=2 note=71 velocity=54 [MP]
    23:11:14.918 [Note Off] ch=2 note=65 velocity=54
    23:11:14.918 [Note Off] ch=2 note=62 velocity=54
    23:11:16.493 [Note On] ch=2 note=55 velocity=59
    23:11:16.493 [Note On] ch=2 note=70 velocity=59 [MP]
    23:11:16.494 [Note On] ch=2 note=64 velocity=59
    23:11:16.494 [Note On] ch=2 note=61 velocity=59
    23:11:16.839 [Note Off] ch=2 note=55 velocity=51
    23:11:16.839 [Note Off] ch=2 note=70 velocity=51
    23:11:16.839 [Note Off] ch=2 note=64 velocity=51
    23:11:16.839 [Note Off] ch=2 note=61 velocity=51 [MP]

    I hope this can be of use.

  • edited March 2020

    Not intending this to be your solution @Bellows.

    I was just experimenting with this idea and came up with this crude code.
    Maybe it might be a useful starting point for working out how to make Mozaic do what you'd like?

    I had it working using the Tonality Chord Pads to send chords to it.
    The Chord notes all have to arrive together or it doesn't work.

    I moved what I wrote below using email from my iPad to my Mac, then edited it some more in the forum post editor.
    Hopefully I didn't break it.

    I'd like to hear some of the Mozaic pros opinions about trying to use the Timer function the way I did in this script.
    It didn't behave the way I expected, but it still seems to somehow work (at least it did before I moved it off my iPad).

    // Concept Script
    // Setup Variables and Timer
    
    @OnLoad
    SetTimerInterval 1
    counter = 0
    FillArray chordnote, -1, 10
    @End 
    
    // Record Played Notes to chordnote Array
    
    @OnMidiNoteOn
    
    if counter = 0
    chordnote[0] = MIDIByte2 
    endif 
    
    if counter = 1
    chordnote[1] = MIDIByte2
    endif
    
    if counter = 2
    chordnote[2] = MIDIByte2
    endif
    
    if counter = 3
    chordnote[3] = MIDIByte2
    endif
    
    Inc counter
    
    StartTimer 
    
    @End 
    
    //Use Timer event to Trigger "ifs"
    
    @OnTimer
    
    FillArray chord, -1, 10
    
    // Assign Played Notes to Array Named "Chord"
    
    Chord = [chordnote[0] , chordnote[1] , chordnote[2] , chordnote[3]]
    
    // List all the "if tests"
    // Play only two notes for each chord
    
    // CM
    if chord[0] = 60 & chord[1] = 64 & chord[2] = 67 & chord[3] = -1
    SendMIDIOut MIDIByte1 , 60 , MIDIByte3
    SendMIDIOut MIDIByte1 , 67 , MIDIByte3
    endif
    
    //Cm
    if chord[0] = 60 & chord[1] = 63 & chord[2] = 67 & chord[3] = -1
    SendMIDIOut MIDIByte1 , 60 , MIDIByte3
    SendMIDIOut MIDIByte1 , 63 , MIDIByte3
    endif
    
    //CM7
    if chord[0] = 60 & chord[1] = 64 & chord[2] = 67 & chord[3] = 71
    SendMIDIOut MIDIByte1 , 60 , MIDIByte3
    SendMIDIOut MIDIByte1 , 71, MIDIByte3
    endif
    
    stoptimer
    resettimer
    counter = 0
    FillArray chordnote, -1, 10
    @end
    
    // Send Thur the Off Notes
    @OnMidiNoteOff
    SendMIDIThru 
    
    @End 
    
    
  • Thank you so much horse trainer for your work on this script. I tried it with my accordion and the CM and Cm worked perfectly. Very nice.
    The CM7 chord is really C7 on my accordion.In other words note# 71 should be note#70. I changed your script to reflect that but there is no output .
    I rechecked and the order of notes sent from the accordion per MidiWrench is 60-64-70-67.

  • After I sent the previous post I checked the script and realized notes# 67 and #70 were in reverse order in the script. I swapped them and now the output sounds.
    Very nicely done !

  • _ki_ki
    edited March 2020

    @horsetrainer Some remarks to your script:

    • In OnMidiNoteOn you do a StartTimer for every incoming note. A StartTimer will take about 5-100ms until the timer is up and running for the first time. Its a lot better to have the timer running the whole time and have some logic in the OnTimer checking if the precondition of three or four notes is met by testing counter (and otherwise do nothing in the timer). Having the timer already running would reduce the reaction time to a predictable 1ms for ‚simultaneous‘ incoming chords, as counter would be picked up in the next OnTimer after arrival.
    • The four IF counter = 0 .. 3 blocks in OnMidiNoteOn can be omitted and simplified to chordnote[counter] = MIDIByte2
    • If (in your code) setting up/starting the timer takes longer than the NoteOffs arrival in OnMidiNoteOff, the order of NoteOn/NoteOff is broken resulting in hanging note. Perhaps it will work better with the change suggested in my first bullet point. I would suggest decrement counter in On idiNoteOff ( if >0) to prevent starting of an chord output via OnTimer in case of arpeggiated single-notes arriving (i know the TO said this will not happen in his case, bout would make the script more general)
    • chord[] and chordNote[] arrays both contain the absolute same values in the same order - no need to have two variables - the OnTimer could just use chordNote instead of copying over to chord (and there is no FillArray, copy over needed at all)
  • I believe -Ki is right on with his analysis without even trying the script with hardware. I didn’t have any hanging notes but there was an occasional missed chord so I knew timing would become an issue sooner or later. Thank you all.

  • edited March 2020

    @_ki said:
    @horsetrainer Some remarks to your script:

    • In OnMidiNoteOn you do a StartTimer for every incoming note. A StartTimer will take about 5-100ms until the timer is up and running for the first time. Its a lot better to have the timer running the whole time and have some logic in the OnTimer checking if the precondition of three or four notes is met by testing counter (and otherwise do nothing in the timer). Having the timer already running would reduce the reaction time to a predictable 1ms for ‚simultaneous‘ incoming chords, as counter would be picked up in the next OnTimer after arrival.
    • The four IF counter = 0 .. 3 blocks in OnMidiNoteOn can be omitted and simplified to chordnote[counter] = MIDIByte2
    • If (in your code) setting up/starting the timer takes longer than the NoteOffs arrival in OnMidiNoteOff, the order of NoteOn/NoteOff is broken resulting in hanging note. Perhaps it will work better with the change suggested in my first bullet point. I would suggest decrement counter in On idiNoteOff ( if >0) to prevent starting of an chord output via OnTimer in case of arpeggiated single-notes arriving (i know the TO said this will not happen in his case, bout would make the script more general)
    • chord[] and chordNote[] arrays both contain the absolute same values in the same order - no need to have two variables - the OnTimer could just use chordNote instead of copying over to chord (and there is no FillArray, copy over needed at all)

    Thanks ki,
    That's just the helpful sort of insights I was hoping to hear.

    @Bellows
    I'm still just a beginner at Mozaic scripting, but I think this "concept script" demonstrates that the functionality of what your looking for should be possible with Mozaic.

    Maybe others with more talent than I might be able to get a working solution up and running.

    In the mean time I'm going to study how to use the Timer function in the way ki described.

    I think this is a good "learning script" for studying chord handling in Mozaic.

    If I come up with anything further I'll post it here. :)

  • _ki_ki
    edited March 2020

    @horsetrainer

    I'm still just a beginner at Mozaic scripting, but I think this "concept script" demonstrates that the functionality of what your looking for should be possible with Mozaic.

    Maybe others with more talent than I might be able to get a working solution up and running.

    I didn‘t want to discourage you at all - the script idea is already working well und it would be cool if you develop it further. It‘s on the right development path. Just wanted to hint for minor improvements, no change to the overall idea or structure.

    .

    For the OnTimer i meant something like:

    @OnLaod
      ..
      SetTimerInterval 1
      StartTimer
    @End  
    
    @OnMidiNoteOn
      chord[counter] = MIDINote
      Inc counter
    @End
    
    @OnMidiNoteOff
       Dec counter
       ..
    @End
    
    @OnTimer
      If counter < 3
        Exit
      Endif
      ...
      // Check chord[] for chords and output stuff if detected the right notes
      // set played = YES if notes were output
    @End
    

    There is still a problem with the NoteOffs if you use SendMidiTru - it would be better to only send them for notes that were started in the OnTimer, but the OnMidiNoteOff needs get a bit more complicated to handle this. The OnTimer would need to set which notes of the input were played, maybe in another array and in OnMidiNoteOff you would need to check if the noteOff note is one of these.

  • Thanks guys. I am so happy you have taken an interest in this idea. Your thoughts and efforts have propelled upstream more than I could have imagined. What a great resource this forum is thanks to people like you.
    LooseBruce

  • @_ki said:
    @horsetrainer

    I'm still just a beginner at Mozaic scripting, but I think this "concept script" demonstrates that the functionality of what your looking for should be possible with Mozaic.

    Maybe others with more talent than I might be able to get a working solution up and running.

    I didn‘t want to discourage you at all - the script idea is already working well und it would be cool if you develop it further. It‘s on the right development path. Just wanted to hint for minor improvements, no change to the overall idea or structure.

    .

    For the OnTimer i meant something like:

    @OnLaod
      ..
      SetTimerInterval 1
      StartTimer
    @End  
    
    @OnMidiNoteOn
      chord[counter] = MIDINote
      Inc counter
    @End
    
    @OnMidiNoteOff
       Dec counter
       ..
    @End
    
    @OnTimer
      If counter < 3
        Exit
      Endif
      ...
      // Check chord[] for chords and output stuff if detected the right notes
      // set played = YES if notes were output
    @End
    

    There is still a problem with the NoteOffs if you use SendMidiTru - it would be better to only send them for notes that were started in the OnTimer, but the OnMidiNoteOff needs get a bit more complicated to handle this. The OnTimer would need to set which notes of the input were played, maybe in another array and in OnMidiNoteOff you would need to check if the noteOff note is one of these.

    Thanks ki,
    I have a couple of ideas I want to experiment with.
    This is a good type of script for thinking of ways to store notes for chords, and then recall the right chord by some kind of tracking method.

    @Bellows
    Thanks for your kind words. :)

  • @horsetrainer Nice work. I think you can see that to cover all the potential input buttons it will be a matter of "If testing" all the button outputs. That's why a complete Table of Notes In to Notes Out is required to complete the task. I suspect your prototype shows the right path to "typing" out all the cases required.

    Here an idea about how a data structure might be used in a For Loop to reduce the typing as the cost of making a massive
    set of arrays.

    You could populate 8 Arrays:
    NoteIn1[]
    NoteIn2[]
    NoteIn3[]
    NoteIn4[]
    NoteOut1[]
    NoteOut2[}
    NoteOut3[]
    NoteOut4[]

    Then populate these arrays fro the table data with the Array index going from Button 1 to ButtonX.

    Then the test for an input chord match could be conducted inside a loop that executes with an increasing index
    until a match is found and the loop exits with a fixed "index" to send the correct output chord.

    You might want to use 2 loops for the 3 vs 4 note chord matching for simplicity or consider the 2 cases in your if testing
    commands.

    The amount of typing will drop significantly but will require a bit more coding skill to do without any unintended consequences. Needless to say... the Pro's can type out a solution without much pain but I suspect you'd appreciate
    the challenge of implementing a Looping solution vs the Ladder of If tests.

    Another optimization is to test the input for a chord type (Major, Minor, 7th, ...) and reduce the table to the 8 chords types
    of in and out. This requires looking at intervals between notes and the Major tests for +4 and +7 intervals from the root.
    This approach makes the 8 arrays down to a very small number of values.

    I hope you keep sharing your work if you decide to keep enhancing your application as a learning exercise.

    Here's another little option to simplify some types of chord detection.

    Mozaic offers a "Modulo" operator which divides a variable by some integer value and provides the remainder as a result.

    LetterNote = NoteIn%12

    If NoteIn = 60
    NoteIn%12 will return 0
    0 would be returned for any C on the keyboard so the octave used on input for C Major will be converted to Notes 0, 4, 7.

    This holds true for any inversion of a C Major chord... C7th reduces to 0,4,7,10.

    So all 12 notes of the chromatic scale can be detected for 8 types in this case for humans to input chords. Of course there
    are more than 8 simple chord types but that just means more testing in the detection loop. This could word for 5, 6, 7 note complex jazz chords too.

    On output you'd want to re-arrange the notes by adding 60 back to the note values and using interval magic off the root,
    3rd, 5th for consideration of inversions for detected chords. It's also great fun to distribute the chord tones across wider intervals than 1 octave...voicing a C Major as 48, 55, 64 for an open sound like an orchestra would play.

  • @McD said:
    @horsetrainer Nice work. I think you can see that to cover all the potential input buttons it will be a matter of "If testing" all the button outputs. That's why a complete Table of Notes In to Notes Out is required to complete the task. I suspect your prototype shows the right path to "typing" out all the cases required.

    Here an idea about how a data structure might be used in a For Loop to reduce the typing as the cost of making a massive
    set of arrays.

    You could populate 8 Arrays:
    NoteIn1[]
    NoteIn2[]
    NoteIn3[]
    NoteIn4[]
    NoteOut1[]
    NoteOut2[}
    NoteOut3[]
    NoteOut4[]

    Then populate these arrays fro the table data with the Array index going from Button 1 to ButtonX.

    Then the test for an input chord match could be conducted inside a loop that executes with an increasing index
    until a match is found and the loop exits with a fixed "index" to send the correct output chord.

    You might want to use 2 loops for the 3 vs 4 note chord matching for simplicity or consider the 2 cases in your if testing
    commands.

    The amount of typing will drop significantly but will require a bit more coding skill to do without any unintended consequences. Needless to say... the Pro's can type out a solution without much pain but I suspect you'd appreciate
    the challenge of implementing a Looping solution vs the Ladder of If tests.

    Another optimization is to test the input for a chord type (Major, Minor, 7th, ...) and reduce the table to the 8 chords types
    of in and out. This requires looking at intervals between notes and the Major tests for +4 and +7 intervals from the root.
    This approach makes the 8 arrays down to a very small number of values.

    I hope you keep sharing your work if you decide to keep enhancing your application as a learning exercise.

    Here's another little option to simplify some types of chord detection.

    Mozaic offers a "Modulo" operator which divides a variable by some integer value and provides the remainder as a result.

    LetterNote = NoteIn%12

    If NoteIn = 60
    NoteIn%12 will return 0
    0 would be returned for any C on the keyboard so the octave used on input for C Major will be converted to Notes 0, 4, 7.

    This holds true for any inversion of a C Major chord... C7th reduces to 0,4,7,10.

    So all 12 notes of the chromatic scale can be detected for 8 types in this case for humans to input chords. Of course there
    are more than 8 simple chord types but that just means more testing in the detection loop. This could word for 5, 6, 7 note complex jazz chords too.

    On output you'd want to re-arrange the notes by adding 60 back to the note values and using interval magic off the root,
    3rd, 5th for consideration of inversions for detected chords. It's also great fun to distribute the chord tones across wider intervals than 1 octave...voicing a C Major as 48, 55, 64 for an open sound like an orchestra would play.

    Thanks McD!

    I've been thinking about some of the concepts you're discussing.

    At this stage I still like to work out ideas block by block because I'm still learning how the Mosaic language "behaves".

    I'm intrigued by the Timer function because it might provide potential ways to incorporate forms of linear processing within the code.

    That's why I put that OnTimer event in between the note input array, and the the note output array. I wanted to give the input array time to record all of the chord notes before moving onto the output section.

    I was stunned that it actually worked, hence the sloppiness of the coding.

    I even tried to emulate a for-next loop in basic style to gain a "delay', but (expectedly) it didn't work.

    I added the extra output array only to create an illusion of separation between the input and output block. As ki stated it was totally unnecessary from an efficiency standpoint, but very helpful for me in visualizing how the script might function.

    My next experiment will be to test a timer controlled "time keeping" variable, and see if I can use that to call user events in a progression of stages. I want to see if Mozaic is capable of any kind of method for processing data in a series of procedural steps based off of clock trigger "If" events.

    Regardless of the outcome of my experimenting, it should help me better understand the way that Mozaic processes code.

    Just a random thought....

    I think it would be nice if Mozaic had the ability to run multiple "runtimes" of the program within a single AUv3 instance.
    That way the coder could choose to send Midi output and variable data through more than one internal Mozaic runtime before sending external midi output.

    This can already be done by daisy chaining multiple instances of the AU in a host.

    But it I think multiple internal instances would offer a great deal more programing flexibility by offering multi-stage Midi data processing opportunities. In essence, such a feature should allow for two or more existing scripts to be loaded side by side, and the output from one script sent (or bussed) internally to the next, to achieve a range of new capabilities by being able to send data through a series of processing steps before external output.

    The UI's could remain relative to their own scripts.

    The way I'd envision this working, is to have tabs at the top of the Mosaic AU window labeled Mosaic A, Mosaic B, Mosaic C.....
    Pressing the tab switches between individual scripts an UI's.

    There'd have to be a new set of functions with an added optional parameter to tell the script weather any output is to be sent external, or internal to the next script.

    In the mean time daisy chaining would offer the same capability.

  • @horsetrainer said:
    Thanks McD!

    You're killing it.

    At this stage I still like to work out ideas block by block because I'm still learning how the Mosaic language "behaves".

    Thats a good way to learn to run... small changes that you understand and can manage.

    I'm intrigued by the Timer function because it might provide potential ways to incorporate forms of linear processing within the code.

    The Timer here helps insure a groups which the sending instrument queues up and dispatches very quickly.

    That's why I put that OnTimer event in between the note input array, and the the note output array. I wanted to give the input array time to record all of the chord notes before moving onto the output section.

    I'd suggest you also consider the OnMetro option to time notes out as a sub-divided interval of the DAW's metronome. You can slice a DAW's BPM into reply small time intervals.

    I was stunned that it actually worked, hence the sloppiness of the coding.

    Your code uses simple easy to understand statements and are perfect to understand the code and share the concepts.
    New coders confronted with too many complex command structures get lost or confused and give up. So anything that works isn't sloppy. It's just indicative of the learning level of the coder.

    I even tried to emulate a for-next loop in basic style to gain a "delay', but (expectedly) it didn't work.

    And easy delay is to just add a delay for each SendMIDIOut

    Delay = 100
    SendMIDIOut Note, Velocity, Delay * 0
    SendMIDIOut Note, Velocity-20, Delay * 1
    SendMIDIOut Note, Velocity-40, Delay * 2

    Remember these Send are just requests for the Mozaic Executive engine to put some future task on it's To Do list.

    You can't make your code spend any idle time which is how we think of an echo... just wait. Mozaic code doesn't offer waits
    except for the SendMIDIOut Delay variable in the 4th position.

    My next experiment will be to test a timer controlled "time keeping" variable, and see if I can use that to call user events in a progression of stages. I want to see if Mozaic is capable of any kind of method for processing data in a series of procedural steps based off of clock trigger "If" events.

    That's a good plan to master more commands and concepts. I like that fact that you see things as a series of events and using the Timer to stage events is the right idea. @_Ki code assumed humans would be entering chords and he allowed for a variable Timer for cover a range of user input rates and still detect chords in the right groupings. I think he allows it to be tweaked with a Knob. (We'll get there).

    Regardless of the outcome of my experimenting, it should help me better understand the way that Mozaic processes code.

    This is how they teach programming... they expose a few commands and give the student a challenge to use them for a task that fits the use case.

    I think it would be nice if Mozaic had the ability to run multiple "runtimes" of the program within a single AUv3 instance.

    You can run more scripts at once in a DAW and have them share some variable data called a Global. So, you can do this without putting all the code in one file but splitting it into coordinated scripts running on a single DAW that support AUv3s.

    That way the coder could choose to send Midi output and variable data through more than one internal Mozaic runtime before sending external midi output.

    You can also daisy chain Mozaic scripts (run in series in contrast to parallel) in a DAW like AUM... 1 feeds 2 that feeds 3 and maybe 4 running at the same moment in another instance sharing data Globals with 1 ,2 and 3. No one has delivered anything like this yet that I can think of.

    It would be nice to see a suite of scripts that shared Globals for Transposition, PPQN values, master volumes, etc.

    But it I think multiple internal instances would offer a great deal more programing flexibility by offering multi-stage Midi data processing opportunities. In essence, such a feature should allow for two or more existing scripts to be loaded side by side, and the output from one script sent (or bussed) internally to the next, to achieve a range of new capabilities by being able to send data through a series of processing steps before external output.

    The ability to serve multiple scripts is yet another reason @Brambos focuses on not over taxing his executive commitments to a coder. His multiple engines all have to start and stop notes without a single missed event send.

    The UI's could remain relative to their own scripts.

    Multiple scripts in multiple Mozaic instances do have their own GUI windows. So, the DAW provides for this use case.

    The way I'd envision this working, is to have tabs at the top of the Mosaic AU window labeled Mosaic A, Mosaic B, Mosaic C.....
    Pressing the tab switches between individual scripts an UI's.

    It's better not to push Mozaic into doing more work on GUI events so it can deliver on the MIDI processing tasks in realtime.
    You can also keep 2-3 AUv3 UI"s open on an iPad.

    There'd have to be a new set of functions with an added optional parameter to tell the script weather any output is to be sent external, or internal to the next script.

    Probably not going to be added given other requests like allowing for character variables or text I/O in the GUI in an update.
    So, we could enter a C7#9 Chord as "C2, G2, E3, Bb3, Eb" rather than 48, 55, 64, 70, 75.

    In the mean time daisy chaining would offer the same capability.

    It's there if you run multiple scripts and if you need to share any data use the Global Variables for that. Timers of the same intervals will all be more than close enough. The MIDINoteON events can be routed to every running Moaziac instance in a DAW like AUM.

    The features are there for what you seem to want but they are handled by the DAW for GUI, Parallel/Series instances and coordination with Global Data. They would all have a coordinate clock speed in the multiple instances as a feature of Mozaic's
    runtime engine using it's precise clocking coordinated with IOS'es clock services.

  • Another hint for future development:

    If an OnTimer or OnMetroPulse runs more than 20-25 Ifs (e.g. in an IF-cascade) or loops with a higher number of passes containing single IFs, CPU spikes may occur and thus crackles in the audio stream.

    It is therefore advised to significantly limit the number of IFs for such regular events and to change the algorithm to more complex ideas. For instance use binary nesting for the IF to reduce the average number of IFs.

    .

    In my (unpublished) chord detection script mentioned above, the pre-computation took too long. Since it is re-triggered when some settings change in the GUI, i needed to divide the pre-computation in seven independent shorter computational loops which then were triggered in a deferred manner by a mini-scheduler run in an OnTimer to prevent the crackles.

  • @McD said:
    @horsetrainer Nice work. I think you can see that to cover all the potential input buttons it will be a matter of "If testing" all the button outputs. That's why a complete Table of Notes In to Notes Out is required to complete the task. I suspect your prototype shows the right path to "typing" out all the cases required.

    Here an idea about how a data structure might be used in a For Loop to reduce the typing as the cost of making a massive
    set of arrays.

    You could populate 8 Arrays:
    NoteIn1[]
    NoteIn2[]
    NoteIn3[]
    NoteIn4[]
    NoteOut1[]
    NoteOut2[}
    NoteOut3[]
    NoteOut4[]

    Then populate these arrays fro the table data with the Array index going from Button 1 to ButtonX.

    Then the test for an input chord match could be conducted inside a loop that executes with an increasing index
    until a match is found and the loop exits with a fixed "index" to send the correct output chord.

    You might want to use 2 loops for the 3 vs 4 note chord matching for simplicity or consider the 2 cases in your if testing
    commands.

    The amount of typing will drop significantly but will require a bit more coding skill to do without any unintended consequences. Needless to say... the Pro's can type out a solution without much pain but I suspect you'd appreciate
    the challenge of implementing a Looping solution vs the Ladder of If tests.

    Another optimization is to test the input for a chord type (Major, Minor, 7th, ...) and reduce the table to the 8 chords types
    of in and out. This requires looking at intervals between notes and the Major tests for +4 and +7 intervals from the root.
    This approach makes the 8 arrays down to a very small number of values.

    I hope you keep sharing your work if you decide to keep enhancing your application as a learning exercise.

    Here's another little option to simplify some types of chord detection.

    Mozaic offers a "Modulo" operator which divides a variable by some integer value and provides the remainder as a result.

    LetterNote = NoteIn%12

    If NoteIn = 60
    NoteIn%12 will return 0
    0 would be returned for any C on the keyboard so the octave used on input for C Major will be converted to Notes 0, 4, 7.

    This holds true for any inversion of a C Major chord... C7th reduces to 0,4,7,10.

    So all 12 notes of the chromatic scale can be detected for 8 types in this case for humans to input chords. Of course there
    are more than 8 simple chord types but that just means more testing in the detection loop. This could word for 5, 6, 7 note complex jazz chords too.

    On output you'd want to re-arrange the notes by adding 60 back to the note values and using interval magic off the root,
    3rd, 5th for consideration of inversions for detected chords. It's also great fun to distribute the chord tones across wider intervals than 1 octave...voicing a C Major as 48, 55, 64 for an open sound like an orchestra would play.

  • heshes
    edited March 2020

    I was fooling around a bit with the good ideas here, and building on some of them
    I think there may be an easier way to do things.

    If you grok the relationships in the chord table and use the modulo operator,
    and (importantly) if there are regular rules about how you're modifying the input chords,
    then you can theoretically do all your processing without hard coding any of the note values
    at all.

    The two main things that I used to make this work (if it does) are
    1. idea that you know the type of chord you're working with after you've
    received the 3rd note, even for 4 note chords.
    2. regularities in the chord table can be easily worked with using modulo operator
    3. Also, I think use of OnMidiNote event for processing works for both MidiOn and
    MidiOff purposes in this case, and I'm hoping there will be no issues doing
    it this way if accordion processing is single-threaded, i.e., accordion always
    sends all Off notes or all On notes for a chord in a row, with no interruptions.

    It's not easy to test with the little AUM keyboard, where it's hard to control
    chords at all, much less ensure you're pressing and unpressing in the proper order,
    but I think the script below will recognize all the chords and:

    -- play only root and 3rds of minor chords
    -- play root and 5ths of major chords
    -- play root, 3rd, and 7th of 7th chords
    -- play all notes of dim7 chords
    -- send midi off only for notes that midi on has been sent for
    -- have zero timing issues, because timing is not used
    -- have no problems with playing multiple chords(??)
    -- allow for hardcoding custom translations for specific chords, if you want

    If anybody gives it a try, let me know if anything works. . . . or not.

    //==============================
    // Concept Script
    
    @OnLoad
        counter = 0
        chordtype=0
        FillArray chordnote, -1, 10
        dim=1
        maj=2
        min=3
        seventh=4
    @End
    
    @OnMidiNote
    
      if counter = 0
          chordnote[0] = MIDIByte2
      endif
    
      if counter = 1
          chordnote[1] = MIDIByte2
      endif
    
    
      if counter = 2
         chordtype=0
    
         chordnote[2] = MIDIByte2
         interval1 = chordnote[1] - chordnote[0]
         interval2 = chordnote[2] - chordnote[1]
         // I think logic below works, but
         // could be fleshed out with redundancies
         // to make things clearer
         if (interval1 % 3 = 0) and (interval2 % 4 = 0)
            chordtype=min
         elseif (interval1 % 3 = 0)
            chordtype=dim
         elseif (interval2 % 6 = 0)
            chordtype=seventh
         else
            chordtype=maj
         endif   
    
      endif
    
      if counter = 3
          chordnote[3] = MIDIByte2
      endif
    
      // we know if we've got a 7th or dim7 chord when
      // counter=2, but we want to wait until counter=3 for those
      if (chordtype=min) or (chordtype=maj) or (counter = 3)
            // We have all the notes of the chord,
            // whether it's 3 notes or 4 notes
            call @ProcessChord     
            // reset, we won't know type of
            //next chord until we get next chord's chordnote[2]
            chordtype=0
            counter = 0
      else
           inc counter // we don't have a full chord yet
      endif
    
    @END
    
    
    @ProcessChord
    
      if chordtype=min   //  root and 3rd
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
      elseif chordtype=maj  //  root and 5th
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
      elseif chordtype=seventh //  root, 3rd, 7th
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
      elseif chordtype=dim
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[3] , MIDIByte3
      else
          log { we're not supposed to get here }
      endif
    
    @END
    
  • @hes said:
    I was fooling around a bit with the good ideas here, and building on some of them
    I think there may be an easier way to do things.

    Very clever optimizations and planning for the optimal path to a solution building on the commands discussed.
    An A+ solution. Excellent formatting as well. It reads well... I hope some newbies are following along and if they have questions will ask for clarifications.

  • The programming ideas being bandied about are way above my pay grade. I am learning from them but bit by bit so to speak. The idea of spreading the chord tones across a wider range however is near and dear to my heart. I have wanted to remove thirds to create power chords for a long time. U have also wanted to spread out the voicing.I can see that I can do that now. The idea of talking these close voiced block chords and expanding them is certainly possible as I can see the light at the end of the tunnel. This is much appreciated.
    The FLY system emulation is much more challenging but that is why we are here.
    Thanks all.
    LooseBruce

  • @hes said:
    I was fooling around a bit with the good ideas here, and building on some of them
    I think there may be an easier way to do things.

    If you grok the relationships in the chord table and use the modulo operator,
    and (importantly) if there are regular rules about how you're modifying the input chords,
    then you can theoretically do all your processing without hard coding any of the note values
    at all.

    The two main things that I used to make this work (if it does) are
    1. idea that you know the type of chord you're working with after you've
    received the 3rd note, even for 4 note chords.
    2. regularities in the chord table can be easily worked with using modulo operator
    3. Also, I think use of OnMidiNote event for processing works for both MidiOn and
    MidiOff purposes in this case, and I'm hoping there will be no issues doing
    it this way if accordion processing is single-threaded, i.e., accordion always
    sends all Off notes or all On notes for a chord in a row, with no interruptions.

    It's not easy to test with the little AUM keyboard, where it's hard to control
    chords at all, much less ensure you're pressing and unpressing in the proper order,
    but I think the script below will recognize all the chords and:

    -- play only root and 3rds of minor chords
    -- play root and 5ths of major chords
    -- play root, 3rd, and 7th of 7th chords
    -- play all notes of dim7 chords
    -- send midi off only for notes that midi on has been sent for
    -- have zero timing issues, because timing is not used
    -- have no problems with playing multiple chords(??)
    -- allow for hardcoding custom translations for specific chords, if you want

    If anybody gives it a try, let me know if anything works. . . . or not.

    //==============================
    // Concept Script
    
    @OnLoad
        counter = 0
        chordtype=0
        FillArray chordnote, -1, 10
        dim=1
        maj=2
        min=3
        seventh=4
    @End
    
    @OnMidiNote
    
      if counter = 0
          chordnote[0] = MIDIByte2
      endif
    
      if counter = 1
          chordnote[1] = MIDIByte2
      endif
    
    
      if counter = 2
         chordtype=0
    
         chordnote[2] = MIDIByte2
         interval1 = chordnote[1] - chordnote[0]
         interval2 = chordnote[2] - chordnote[1]
         // I think logic below works, but
         // could be fleshed out with redundancies
         // to make things clearer
         if (interval1 % 3 = 0) and (interval2 % 4 = 0)
            chordtype=min
         elseif (interval1 % 3 = 0)
            chordtype=dim
         elseif (interval2 % 6 = 0)
            chordtype=seventh
         else
            chordtype=maj
         endif   
    
      endif
    
      if counter = 3
          chordnote[3] = MIDIByte2
      endif
    
      // we know if we've got a 7th or dim7 chord when
      // counter=2, but we want to wait until counter=3 for those
      if (chordtype=min) or (chordtype=maj) or (counter = 3)
            // We have all the notes of the chord,
            // whether it's 3 notes or 4 notes
            call @ProcessChord     
            // reset, we won't know type of
            //next chord until we get next chord's chordnote[2]
            chordtype=0
            counter = 0
      else
           inc counter // we don't have a full chord yet
      endif
    
    @END
    
    
    @ProcessChord
    
      if chordtype=min   //  root and 3rd
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
      elseif chordtype=maj  //  root and 5th
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
      elseif chordtype=seventh //  root, 3rd, 7th
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
      elseif chordtype=dim
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[3] , MIDIByte3
      else
          log { we're not supposed to get here }
      endif
    
    @END
    

    Hi He’s,
    When I load this script I get seven syntax errors that read:

    [OnLoad] Syntax Error : unknown or invalid argument “ “

    Any clue on what I should do. To my eyes the code is the same in my Mozaic as what you have posted.
    Thanks

  • I tried to run the script with the syntax errors. It did not work and I also got syntax errors for OnMidiNote.
    Could it be because I copied your text on my iPhone and then transferred to my iPad via notes app?

  • heshes
    edited March 2020

    @Bellow, not sure what problem is. You could try copying and pasting clean version from this link:
    https://gist.github.com/hsitz/d169f84f60acd1cdaa59cd0650d87471/raw/3e4743b41993d9c4f49032ec0b302117e9e3b0a8/acc-translate-mozaic.txt

    or you can download as a zip using this link, I think:
    https://gist.github.com/hsitz/d169f84f60acd1cdaa59cd0650d87471/archive/3e4743b41993d9c4f49032ec0b302117e9e3b0a8.zip

    If I understand things correctly, there's no added difficulty in programming the FLY system. I made a couple small changes so the version in above links so it should now implement the FLY Chord System. If that works, it would be fairly trivial to add the FLY Single Note System and have a knob on the Mozaic UI that lets you switch between the two.

    EDIT: Actually, I was too optimistic. It won't do FLY system correctly right now, I need to find chart of what chords the basic (untranslated) accordion chordbutton bank sends. . . Is this it?:

    https://en.wikipedia.org/wiki/Stradella_bass_system

    I now also see the octave indications are important, but I don't see those on the Stradella chart. Need some indication of what octave the notes in your chordbutton chart are in (e.g., C1, E3, Bb2). Will it be same as standard piano notation, going off pitch numbers in your handwritten chord chart?

  • heshes
    edited March 2020

    @Bellows, another possible complication. I clearly don't fully understand the charts of the chordbutton banks. I think you said that there are 20 buttons for each chordtype (maj, min, 7th, dim), but you included only 12 in your written chordchart because they start repeating after the first 12. Problem is, I wonder whether the pitches are the same for the last eight chords, or whether they're sounding the same chord up an octave from identical chords earlier in the button row. If so, we may need to take that into account when processing the notes received from the accordion (or maybe part of it will be automatically handled by current chord checking).

  • Hes,
    You have done a wonderfully creative job of coding.So much progress in a short time. I downloaded the clean version and it working very well with single button presses.
    It is amazing to me.

    I had to put the chord buttons on a separate channel from other sent notes because any other notes confused the system.

    Also as expected two buttons at the same time can cause problems. Hanging notes and wrong intervals were observed. After such an event Mozaic had to be reloaded to work correctly.

    More to follow but you have done a wonderful job.
    Bruce

  • Regarding your question about only 12 notes in a 20 note row. The other buttons beyond the 12 are duplicates. They are exactly the same as the 12 in my chart. It may seem wasteful to a non accordionist but they make it possible to avoid large movements of your hand. Mozaic should see no difference between duplicate or enharmonic notes.

    You may have noticed that the chord rows are a Major fifth apart. This puts the chords I-IV-V right next to each other and made simple chord progressions very easy to play and that is how Stradella Bass was created.
    More to follow
    Bruce

  • Hi Hes,
    You will not be able to find Correct octave voicing of chords anywhere. The reasons are complex but mostly based on the fact that on an acoustic accordion many of the varieties of timbres are created by multiple reeds playing the same note often detuned slightly. Just like multiple detuned oscillators on a synth.
    HOWEVER, the midi output is simply one output of each note in the chord. The actual octave output may vary between manufacturers.
    I can play more or all of my chord buttons into MidiWrench if you wish to see what these midi note numbers are.

    One more detail which you may have noticed. The diminished chords are actually diminished 6 chords. In other words C dim is actually C Eb. Gb A.
    Eb diminished is actually made up of the same notes as C dim.
    Fortunately the designers used different octaves for some of the notes so there are 12 unique dim 6 chords.
    Looks like accordions are almost as complicated as programming.
    Thanks again for all of your creative work.
    Bruce

  • heshes
    edited March 2020

    Hmm. The exact duplicate chordbuttons cause a problem. Unless you can reconfigure what the last eight buttons are sending, I don't see any way to implement the FLY system. (Would be perfect if they sent same notes an octave up.) Note that on the FLY system those last eight buttons are not duplicates. Thus, you need some way for your accordion to indicate to Mozaic when a button from first 12 is being sent, and when a button from last 8 is being sent. Without that (i.e, if accordion sends identical midi for both buttons), there's no way for Mozaic to know that and no way to implement FLY system.

    For example, on FLY system for Minor chord row the first button is (Fb3+Abb3). Then in last eight buttons is same chord, but up seemingly up an octave (E4+G4). Or are the FLY system last 8 exact duplicates? I'm still not sure how to read the numeric octave designations, (e.g., Ab2, D#3). Are those numbers different from standard piano pitch notation?: https://daniels-orchestral.com/other-resources/pitch-chart/

    I don't offhand see why there would be a problem with two buttons at the same time. Would it be possible to get a midiwrench recording of a combination that causes the problems, all midi from first note on to last note off? Even better would be to inserting some appropriate 'log ' commands into the Mozaic project and then get a copy of the text it sends to the log output pane. I'll try to update the program with those log commands and get you link sometime today.

  • You are a fast study. I have never used the FLY system and did not realize there was this difference. I see you learned about the other single note mode which I did not pay attention to also. My thought is that it is not important to me.
    I will experiment some more and try to determine what is happening with dual buttons pushes.

    BTW,
    I have limited time for the next few days. I am from NY, USA but live in a motorhome in Florida for the winter.I just picked a gig with a Blues Band that I play with occasionally when I am in Florida. They just released a new CD and I want to be proficient on the new tunes.
    Thanks,
    Bruce

  • For future reference C row is considered the middle of the chord buttons. The 12 rows centered around C are the most used in normal playing. The duplicate rows toward the top and bottom are seldom used. My accordion is a 120 bass instrument meaning it has 120 buttons. There are many smaller accordions with 72, 48, and even 12 bass buttons. Many accordions do not have any duplicate notes .
    If you play in the keys of C# or F# you are forced toward these extremes. These however are quite rare keys for performance.

  • What is the model of your accordion and/or do you have link to a user manual online?

    If there's no way to distinguish the rightmost 8 keys on your bank, it could still be trivial to change current code to play a kind of "FLY system lite", which would play the same notes as FLY system, but not have the raised octaves for the rightmost 8 keys.

    That would depend on the multi-button issue being easy to solve, though. I expect it will be, unless the accordion is mixing up the order of chord notes (i..e, not completely sending notes for one chord before it starts another), in which case the current approach is not likely to work at all. And probably no approach would work in that case. Generalized midi chord detection is difficult enough for single chords, if your controller is sending two different chords intermixed it's practically (and maybe theoretically) impossible to identify them accurately.

    One question I have is what the '[MP]' notations are on some lines of the midi wrench output. I wonder whether that's some extra bit of data that might help somehow in decoding things.

    FLY System (maybe "lite") or bust.

  • edited March 2020

    @hes
    That's some really cool logic!
    I have to spend some more time understanding what a modulo is and does.

    @hes said:
    I was fooling around a bit with the good ideas here, and building on some of them
    I think there may be an easier way to do things.

    If you grok the relationships in the chord table and use the modulo operator,
    and (importantly) if there are regular rules about how you're modifying the input chords,
    then you can theoretically do all your processing without hard coding any of the note values
    at all.

    The two main things that I used to make this work (if it does) are
    1. idea that you know the type of chord you're working with after you've
    received the 3rd note, even for 4 note chords.
    2. regularities in the chord table can be easily worked with using modulo operator
    3. Also, I think use of OnMidiNote event for processing works for both MidiOn and
    MidiOff purposes in this case, and I'm hoping there will be no issues doing
    it this way if accordion processing is single-threaded, i.e., accordion always
    sends all Off notes or all On notes for a chord in a row, with no interruptions.

    It's not easy to test with the little AUM keyboard, where it's hard to control
    chords at all, much less ensure you're pressing and unpressing in the proper order,
    but I think the script below will recognize all the chords and:

    -- play only root and 3rds of minor chords
    -- play root and 5ths of major chords
    -- play root, 3rd, and 7th of 7th chords
    -- play all notes of dim7 chords
    -- send midi off only for notes that midi on has been sent for
    -- have zero timing issues, because timing is not used
    -- have no problems with playing multiple chords(??)
    -- allow for hardcoding custom translations for specific chords, if you want

    If anybody gives it a try, let me know if anything works. . . . or not.

    //==============================
    // Concept Script
    
    @OnLoad
        counter = 0
        chordtype=0
        FillArray chordnote, -1, 10
        dim=1
        maj=2
        min=3
        seventh=4
    @End
    
    @OnMidiNote
    
      if counter = 0
          chordnote[0] = MIDIByte2
      endif
    
      if counter = 1
          chordnote[1] = MIDIByte2
      endif
    
    
      if counter = 2
         chordtype=0
    
         chordnote[2] = MIDIByte2
         interval1 = chordnote[1] - chordnote[0]
         interval2 = chordnote[2] - chordnote[1]
         // I think logic below works, but
         // could be fleshed out with redundancies
         // to make things clearer
         if (interval1 % 3 = 0) and (interval2 % 4 = 0)
            chordtype=min
         elseif (interval1 % 3 = 0)
            chordtype=dim
         elseif (interval2 % 6 = 0)
            chordtype=seventh
         else
            chordtype=maj
         endif   
    
      endif
    
      if counter = 3
          chordnote[3] = MIDIByte2
      endif
    
      // we know if we've got a 7th or dim7 chord when
      // counter=2, but we want to wait until counter=3 for those
      if (chordtype=min) or (chordtype=maj) or (counter = 3)
            // We have all the notes of the chord,
            // whether it's 3 notes or 4 notes
            call @ProcessChord     
            // reset, we won't know type of
            //next chord until we get next chord's chordnote[2]
            chordtype=0
            counter = 0
      else
           inc counter // we don't have a full chord yet
      endif
    
    @END
    
    
    @ProcessChord
    
      if chordtype=min   //  root and 3rd
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
      elseif chordtype=maj  //  root and 5th
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
      elseif chordtype=seventh //  root, 3rd, 7th
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
      elseif chordtype=dim
          SendMIDIOut MIDIByte1 , chordnote[0] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[1] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[2] , MIDIByte3
          SendMIDIOut MIDIByte1 , chordnote[3] , MIDIByte3
      else
          log { we're not supposed to get here }
      endif
    
    @END
    

    There are lots of concepts in this script that I can study and learn from.

    I also like the way the @OnMidiNote is used for both "note on" and "note off" messages.

    It's also a clever way of distinguishing between a 3 or 4 note chord, before making the user call to send the midi output.

    @McD
    Do have any recommendations for any "not extremely complex"... Mozaic scripts on PatchStorage.... That process "user played chords" in ways to achieve various types of outputs?

    I'd like to study the different ways Mozaic can work with live played chord input.
    I think this subject is interesting.

    I'm currently racking my brain thinking about ways to put incoming Midi chord notes into ascending order within an array.

    Hand played chord notes could arrive in any order the fingers happen to fall.
    I could do a 16 steps of if statements to test every four note sequence possibility, but I'm contemplating if there may be a simpler way to go about testing note order. I also like to figure a way to simutainiously test for 3 note chords in the same process.

    I'm still working in the rhelm of using timing as a tool for determining which notes are all part of one chord.

    But playing two chords at the same time creates another set of challenges.

    How does one build an algorithm that can distinguish which notes belong to one chord, vs another chord played at the same time?

    For Accordion use..... Since the chord notes ought to be pretty simultaneous.... Maybe a round robin script that sequentially rotates the output midi channel for each individual Accordion chord pressed.... ?

    Then send each Midi channel into a different instance of Mozaic each running the script @hes wrote... Each script running each Mozaic instance could be modified to send its Midi output to the same Midi Channel ???

    Might make for an interesting experiment?

Sign In or Register to comment.