Skip to content

Commit 1fde44d

Browse files
authored
play chord in music keyboard (#4563)
* play chord * semicolon added
1 parent 7a3e106 commit 1fde44d

File tree

1 file changed

+70
-27
lines changed

1 file changed

+70
-27
lines changed

js/widgets/musickeyboard.js

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)