• Conditions help.

    From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Fri Nov 12 05:18:51 2021
    I've been sitting to long trying to compare and adjust notes in time got dizzy. How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same.
    while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1);
    timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luserdroog@21:1/5 to jonas.t...@gmail.com on Tue Nov 16 07:37:17 2021
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }

    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Tue Nov 16 12:56:28 2021
    tisdag 16 november 2021 kl. 21:26:27 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 21:18:04 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.
    But i remember now, the main obstacle is really the max + - "positional" that is set by the corresponding "same note value" before and after.
    I have no problem of extending length, of note but howto keep track that it stay smaller then the next note of same value.

    I solved it for the ON case looking at where "same note" **before*** end, but are somehow not bright enough to do it for the OFF case extending end.
    I have a look at it a day i feel awake and lucky...
    Why i do this if because at some point i maybe want to move, change duration, change startpos of note using drag and drop without break start ends.
    Right now i use poor mans solution slidebars where steps can be set to some milliseconds, or simply step forward backward with + and -.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Tue Nov 16 12:17:59 2021
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Tue Nov 16 12:26:23 2021
    tisdag 16 november 2021 kl. 21:18:04 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.

    But i remember now, the main obstacle is really the max + - "positional" that is set by the corresponding "same note value" before and after.
    I have no problem of extending length, of note but howto keep track that it stay smaller then the next note of same value.

    I solved it for the ON case looking at where "same note" **before*** end, but are somehow not bright enough to do it for the OFF case extending end.
    I have a look at it a day i feel awake and lucky...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Tue Nov 16 12:52:09 2021
    tisdag 16 november 2021 kl. 21:26:27 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 21:18:04 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.
    But i remember now, the main obstacle is really the max + - "positional" that is set by the corresponding "same note value" before and after.
    I have no problem of extending length, of note but howto keep track that it stay smaller then the next note of same value.

    I solved it for the ON case looking at where "same note" **before*** end, but are somehow not bright enough to do it for the OFF case extending end.
    I have a look at it a day i feel awake and lucky...

    I agree it seem real simple, but when i start doing it get quite hard to actually implement.
    Because when you move a note [x] with "some" milliseconds, you must first compare it "search for next note holding same value" [y] and should only be updated while less otherwise you create havoc.

    [start x]->[start y] ->[end x]->[end y]

    And i think that it was within using {x[ ***finding*** and comparing with element [y] my logic did crash. I got it working for ON [Moving both forward and backward] and for OFF [Moving backward].
    OFF BACKWARD simply mean do not move beyond start of note.
    ON FORWARD simple mean do not move beyond end of note.
    ON BACKWARD do not move before previous "same note" start.
    OFF FORWARD do not move beyond next "same note" value start.

    I guess that i can't solve it for OFF FORWARD mean i simply do not find correct index [y] to compare with, it seem to walk right thru next note.
    In theory it is simple find next "same note" values time to compare with.
    If x less then y update else nothing.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From luserdroog@21:1/5 to jonas.t...@gmail.com on Wed Nov 17 17:54:28 2021
    On Tuesday, November 16, 2021 at 2:56:33 PM UTC-6, jonas.t...@gmail.com wrote:
    tisdag 16 november 2021 kl. 21:26:27 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 21:18:04 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.
    But i remember now, the main obstacle is really the max + - "positional" that is set by the corresponding "same note value" before and after.
    I have no problem of extending length, of note but howto keep track that it stay smaller then the next note of same value.

    I solved it for the ON case looking at where "same note" **before*** end, but are somehow not bright enough to do it for the OFF case extending end.
    I have a look at it a day i feel awake and lucky...
    Why i do this if because at some point i maybe want to move, change duration, change startpos of note using drag and drop without break start ends.
    Right now i use poor mans solution slidebars where steps can be set to some milliseconds, or simply step forward backward with + and -.

    Ok, I'm starting to understand some of what you're trying to do. From the point of view of "abstraction" that I'm trying to present, it seems like you're doing too much with this little bit of code. If I were doing this sort of program
    I would completely separate the Output side from the Input and Data Manipulation
    parts. That is, notes get converted into midi events and then you're done messing
    with that list of midi events. Either send it out to the midi renderer, or if an edit was
    made to the notes then you just throw away the list of events and generate a new
    one.

    Maybe not for this project, but I think it would be very helpful for you to learn
    about the MVC or Model/View/Controller architecture. From the pov of MVC,
    the notes is the Model, the list of midi events is the View (or *a* View, another
    would be the boxes drawn on the screen. Then the Controller part handles all the input actions, maybe consulting with the View to find out what thing was clicked on then changing the Model and ordering the Views to re-draw themselves.

    The advantage of separating things like this is when you have a bug to find. You will be able to quickly determine which of the 3 parts is affected.
    If it's the Model that's going wrong, then you don't have to look at any of
    the code for the Views or Controller. If the Model is ok, then either the click isn't
    being handled right (Controller) or the screen or audio looks or sound wrong (Views).

    https://stackoverflow.com/questions/2613310/ive-heard-global-variables-are-bad-what-alternative-solution-should-i-use

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Thu Nov 18 08:49:58 2021
    torsdag 18 november 2021 kl. 17:42:41 UTC+1 skrev Jonas Thörnvall:
    torsdag 18 november 2021 kl. 02:54:43 UTC+1 skrev luser...@gmail.com:
    On Tuesday, November 16, 2021 at 2:56:33 PM UTC-6, jonas.t...@gmail.com wrote:
    tisdag 16 november 2021 kl. 21:26:27 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 21:18:04 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.
    But i remember now, the main obstacle is really the max + - "positional" that is set by the corresponding "same note value" before and after.
    I have no problem of extending length, of note but howto keep track that it stay smaller then the next note of same value.

    I solved it for the ON case looking at where "same note" **before*** end, but are somehow not bright enough to do it for the OFF case extending end.
    I have a look at it a day i feel awake and lucky...
    Why i do this if because at some point i maybe want to move, change duration, change startpos of note using drag and drop without break start ends.
    Right now i use poor mans solution slidebars where steps can be set to some milliseconds, or simply step forward backward with + and -.
    Ok, I'm starting to understand some of what you're trying to do. From the point of view of "abstraction" that I'm trying to present, it seems like you're
    doing too much with this little bit of code. If I were doing this sort of program
    I would completely separate the Output side from the Input and Data Manipulation
    parts. That is, notes get converted into midi events and then you're done messing
    with that list of midi events. Either send it out to the midi renderer, or if an edit was
    made to the notes then you just throw away the list of events and generate a new
    one.

    Maybe not for this project, but I think it would be very helpful for you to learn
    about the MVC or Model/View/Controller architecture. From the pov of MVC, the notes is the Model, the list of midi events is the View (or *a* View, another
    would be the boxes drawn on the screen. Then the Controller part handles all
    the input actions, maybe consulting with the View to find out what thing was
    clicked on then changing the Model and ordering the Views to re-draw themselves.

    The advantage of separating things like this is when you have a bug to find.
    You will be able to quickly determine which of the 3 parts is affected.
    If it's the Model that's going wrong, then you don't have to look at any of
    the code for the Views or Controller. If the Model is ok, then either the click isn't
    being handled right (Controller) or the screen or audio looks or sound wrong
    (Views).

    https://stackoverflow.com/questions/2613310/ive-heard-global-variables-are-bad-what-alternative-solution-should-i-use
    This project is built around least resistance principle basicly embed short code snippets into functions that acts like a pipeline from the UI.
    ***I really have global things all over the place unless it is local counters.****
    It is fast to implement and fast to change without anything break. ***You can always pass parameters between functions later***

    Regarding this specific problem you can't separate the changes you make from the structure of midi, a piano key can not be pressed twice without a release.
    And that fact effect the editing of note logic if you want to keep the structure sane.

    So basicly i tried to squeeze in alot of functionality as fast as possible and if i get stuck i go on with next thing.
    Until i feel ready todo another iteration and straight the code up, and that usually work.
    Of course such a refinement can go on forever, have not done any object oriented programming since smalltalk.

    I have a feeling though that the abstraction of a project like this would be very hard to understand without some schematic.
    Now this project just a pipeline stream of functions, without passing shit back and forth.

    Sure there is some object structure holding the notes and some arrays, but many variables is stored in place using forms.
    So the need for passing them is minimal, they are just fetched using getElementById.

    I think there is some 300 KB of actual code i am not sure if that is much or little for a sequenser project "in javascript".
    But considering it really do not seem to cludge up on my computer, the approach can't be totally of the wall.

    And what i find great is that anyone that wrote some lines in Basic can probably follow the program flow.
    I tried to avoid the things of javascript that is nonesensical, but it is hard it get more convoluted by the day.

    http://jtmidi.000webhostapp.com/
    https://www.youtube.com/watch?v=DcHKOC64KnE

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Jonas_Th=C3=B6rnvall?=@21:1/5 to All on Thu Nov 18 08:42:36 2021
    torsdag 18 november 2021 kl. 02:54:43 UTC+1 skrev luser...@gmail.com:
    On Tuesday, November 16, 2021 at 2:56:33 PM UTC-6, jonas.t...@gmail.com wrote:
    tisdag 16 november 2021 kl. 21:26:27 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 21:18:04 UTC+1 skrev Jonas Thörnvall:
    tisdag 16 november 2021 kl. 16:37:22 UTC+1 skrev luser...@gmail.com:
    On Friday, November 12, 2021 at 7:18:55 AM UTC-6, jonas.t...@gmail.com wrote:
    I've been sitting to long trying to compare and adjust notes in time got dizzy.
    How should this while be constructed to break when the two data1 is equal or it reach end of midimessages for track.

    It does not seem to enter... although data1 is the same. while(track[editTrack].midiMess[stopEvent].data1!=track[editTrack].midiMess[y].data1 && y<track[editTrack].midiMess.length){
    alert(track[editTrack].midiMess[y].data1); timeNextNote=track[editTrack].midiMess[y].time;
    y++;
    }
    Why do you need to "adjust notes in time"?
    This sounds like part of a higher-level operation that might be handled differently
    to avoid the whole issue.

    It's seems that you're translating notes (pitch, start time, duration) into a list
    of on/off events (ON pitch, time) (OFF pitch, time) and then sort them by time.

    So I'd expect a high-level function for this to look roughly like this:

    function midi_from_notes( notes ){
    var events;
    notes.forEach( note=>events.push( { type:"ON"; pitch:note.pitch; time:note.start_time } ) );
    notes.forEach( note=>events.push( { type:"OFF"; pitch:note.pitch; time:note.start_time + note.duration } ) );
    return events.sort( ev=>ev.time );
    }

    I may be forgetting some details about midi. If you need relative times, then you can do
    another loop for that, or write a helper function to do the looping.
    So you say i should just remove the note and push a new one, and sort again. That may actually be easier then update the array element, will think about it.
    But i remember now, the main obstacle is really the max + - "positional" that is set by the corresponding "same note value" before and after.
    I have no problem of extending length, of note but howto keep track that it stay smaller then the next note of same value.

    I solved it for the ON case looking at where "same note" **before*** end, but are somehow not bright enough to do it for the OFF case extending end.
    I have a look at it a day i feel awake and lucky...
    Why i do this if because at some point i maybe want to move, change duration, change startpos of note using drag and drop without break start ends.
    Right now i use poor mans solution slidebars where steps can be set to some milliseconds, or simply step forward backward with + and -.
    Ok, I'm starting to understand some of what you're trying to do. From the point of view of "abstraction" that I'm trying to present, it seems like you're
    doing too much with this little bit of code. If I were doing this sort of program
    I would completely separate the Output side from the Input and Data Manipulation
    parts. That is, notes get converted into midi events and then you're done messing
    with that list of midi events. Either send it out to the midi renderer, or if an edit was
    made to the notes then you just throw away the list of events and generate a new
    one.

    Maybe not for this project, but I think it would be very helpful for you to learn
    about the MVC or Model/View/Controller architecture. From the pov of MVC, the notes is the Model, the list of midi events is the View (or *a* View, another
    would be the boxes drawn on the screen. Then the Controller part handles all the input actions, maybe consulting with the View to find out what thing was clicked on then changing the Model and ordering the Views to re-draw themselves.

    The advantage of separating things like this is when you have a bug to find. You will be able to quickly determine which of the 3 parts is affected.
    If it's the Model that's going wrong, then you don't have to look at any of the code for the Views or Controller. If the Model is ok, then either the click isn't
    being handled right (Controller) or the screen or audio looks or sound wrong (Views).

    https://stackoverflow.com/questions/2613310/ive-heard-global-variables-are-bad-what-alternative-solution-should-i-use

    This project is built around least resistance principle basicly embed short code snippets into functions that acts like a pipeline from the UI.
    ***I really have global things all over the place unless it is local counters.****
    It is fast to implement and fast to change without anything break. ***You can always pass parameters between functions later***

    Regarding this specific problem you can't separate the changes you make from the structure of midi, a piano key can not be pressed twice without a release.
    And that fact effect the editing of note logic if you want to keep the structure sane.

    So basicly i tried to squeeze in alot of functionality as fast as possible and if i get stuck i go on with next thing.
    Until i feel ready todo another iteration and straight the code up, and that usually work.
    Of course such a refinement can go on forever, have not done any object oriented programming since smalltalk.

    I have a feeling though that the abstraction of a project like this would be very hard to understand without some schematic.
    Now this project just a pipeline stream of functions, without passing shit back and forth.

    Sure there is some object structure holding the notes and some arrays, but many variables is stored in place using forms.
    So the need for passing them is minimal, they are just fetched using getElementById.

    I think there is some 300 KB of actual code i am not sure if that is much or little for a sequenser project "in javascript".
    But considering it really do not seem to cludge up on my computer, the approach can't be totally of the wall.

    And what i find great is that anyone that wrote some lines in Basic can probably follow the program flow.
    I tried to avoid the things of javascript that is nonesensical, but it is hard it get more convoluted by the day.

    http://jtmidi.000webhostapp.com/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)