@@ -277,6 +277,9 @@ function MusicKeyboard(activity) {
277277 const temp1 = { } ;
278278 const temp2 = { } ;
279279 const current = new Set ( ) ;
280+ let chordBuffer = { } ;
281+ let extraNoteCount = 0 ;
282+ let startTimeNotes = 0 ;
280283
281284 /**
282285 * Gets the ID of the musical note associated with a keyboard event.
@@ -333,6 +336,18 @@ function MusicKeyboard(activity) {
333336 return ;
334337 }
335338
339+ // Check if it is a chord
340+ if ( Object . keys ( chordBuffer ) . length === 0 ) {
341+ chordBuffer [ id ] = temp2 [ id ] ;
342+ startTimeNotes = Math . floor ( startTime [ id ] / 100 ) ;
343+ } else if ( startTimeNotes === Math . floor ( startTime [ id ] / 100 ) ) {
344+ chordBuffer [ id ] = temp2 [ id ] ;
345+ extraNoteCount ++ ;
346+ } else {
347+ extraNoteCount = 0 ;
348+ chordBuffer = { } ;
349+ }
350+
336351 this . activity . logo . synth . trigger (
337352 0 ,
338353 temp2 [ id ] ,
@@ -415,15 +430,37 @@ function MusicKeyboard(activity) {
415430 } ) ;
416431 } else {
417432 this . activity . logo . synth . stopSound ( 0 , this . instrumentMapper [ id ] , temp2 [ id ] ) ;
418- this . _notesPlayed . push ( {
419- startTime : startTime [ id ] ,
420- noteOctave : temp2 [ id ] ,
421- objId : id ,
422- duration : processedDuration ,
423- voice : this . instrumentMapper [ id ] ,
424- blockNumber : this . blockNumberMapper [ id ]
425- } ) ;
433+ // Handle Chord
434+ if ( id in chordBuffer ) {
435+ Object . entries ( chordBuffer ) . forEach ( ( [ id , noteOctave ] ) => {
436+ this . _notesPlayed . push ( {
437+ startTime : startTimeNotes * 100 ,
438+ noteOctave : noteOctave ,
439+ objId : id ,
440+ duration : processedDuration ,
441+ voice : this . instrumentMapper [ id ] ,
442+ blockNumber : this . blockNumberMapper [ id ]
443+ } ) ;
444+ delete chordBuffer [ id ] ;
445+ } ) ;
446+ }
447+ else if ( extraNoteCount > 0 ) {
448+ extraNoteCount -- ;
449+ }
450+ // Handle Single Notes
451+ else {
452+ this . _notesPlayed . push ( {
453+ startTime : startTime [ id ] ,
454+ noteOctave : temp2 [ id ] ,
455+ objId : id ,
456+ duration : processedDuration ,
457+ voice : this . instrumentMapper [ id ] ,
458+ blockNumber : this . blockNumberMapper [ id ]
459+ } ) ;
460+ chordBuffer = { } ;
461+ }
426462 }
463+
427464 this . _createTable ( ) ;
428465 if ( this . widgetWindow . _maximized ) {
429466 this . widgetWindow . getWidgetBody ( ) . style . position = "absolute" ;
@@ -450,6 +487,7 @@ function MusicKeyboard(activity) {
450487 docById ( "mkbInnerDiv" ) . style . height = "100%" ;
451488 }
452489 this . endTime = noteEndTime ;
490+ startTimeNotes = 0 ;
453491 delete startTime [ id ] ;
454492 delete temp1 [ id ] ;
455493 delete temp2 [ id ] ;
@@ -700,6 +738,9 @@ function MusicKeyboard(activity) {
700738 this . playButton = widgetWindow . addButton ( "play-button.svg" , ICONSIZE , _ ( "Play" ) ) ;
701739
702740 this . playButton . onclick = ( ) => {
741+ if ( this . metronomeInterval || this . metronomeON ) {
742+ this . stopMetronome ( ) ;
743+ }
703744 this . activity . logo . turtleDelay = 0 ;
704745 this . processSelected ( ) ;
705746 this . playAll ( ) ;
@@ -766,27 +807,29 @@ function MusicKeyboard(activity) {
766807 * @type {HTMLElement }
767808 */
768809 this . tickButton = widgetWindow . addButton ( "metronome.svg" , ICONSIZE , _ ( "Metronome" ) ) ;
769- this . tickButton . onclick = ( ) => {
770- if ( this . metronomeInterval || this . metronomeON ) {
771- // Turn off metronome
772- this . tickButton . style . removeProperty ( "background" ) ;
773-
774- if ( this . tick && this . loopTick ) {
775- this . loopTick . stop ( ) ;
776- }
777- this . tick = false ;
778- this . firstNote = false ;
779- this . metronomeON = false ;
780810
781- const countdownContainer = docById ( "countdownContainer" ) ;
782- if ( countdownContainer ) {
783- countdownContainer . remove ( ) ;
784- }
785- if ( this . metronomeInterval ) {
786- clearInterval ( this . metronomeInterval ) ;
787- this . metronomeInterval = null ;
788- }
811+ // Turn off metronome
812+ this . stopMetronome = ( ) => {
813+ this . tickButton . style . removeProperty ( "background" ) ;
814+ if ( this . tick && this . loopTick ) {
815+ this . loopTick . stop ( ) ;
816+ }
817+ this . tick = false ;
818+ this . firstNote = false ;
819+ this . metronomeON = false ;
820+ const countdownContainer = docById ( "countdownContainer" ) ;
821+ if ( countdownContainer ) {
822+ countdownContainer . remove ( ) ;
823+ }
824+ if ( this . metronomeInterval ) {
825+ clearInterval ( this . metronomeInterval ) ;
826+ this . metronomeInterval = null ;
827+ }
828+ } ;
789829
830+ this . tickButton . onclick = ( ) => {
831+ if ( this . metronomeInterval || this . metronomeON ) {
832+ this . stopMetronome ( ) ;
790833 } else {
791834 // Turn on metronome
792835 this . metronomeON = true ;
0 commit comments