How to insert a chord?

• Jun 30, 2015 - 22:40

Hi

How do I insert a chord using javascript in a plugin for Musescore 2+?

I would expect the following code to output a CEG triad but instead I get two side-by-side B notes with no stems with what looks like a quarter tone accidental.

var cursor = curScore.newCursor();
cursor.rewind(0); 
curScore.startCmd();
cursor.setDuration(1, 4);
 
var c = newElement(Element.CHORD);
c.duration = 480;                 
c.visible = true;  
 
var n1 = newElement(Element.NOTE);
n1.pitch=60;
c.add(n1);
 
var n2 = newElement(Element.NOTE);
n2.pitch=64;
c.add(n2);
 
var n3 = newElement(Element.NOTE);
n3.pitch=67;
c.add(n3);
 
cursor.add(c);
 
curScore.doLayout();
curScore.endCmd();
Qt.quit()

example output

What's the right way to insert a chord at the cursor's current position?

Thanks in advance.

Attachment Size
not a triad.png 1.99 KB

Comments

Check how the plugin 'random.qml' is doing this.
That note(s) you got are actually Bbb (same pitch as an A) and the accidental is a double b

I made a few tests:

1) Cursor.setDuration(x, y); seems to do nothing: a plug-in with just this command leaves the chord/rest at the cursor unchanged.

2) By setting the tpc1 and the tpc2 of each note added, it is possible to obtain a chord:

		var n1		= newElement(Element.NOTE);
		n1.pitch	= 60;		// C4 pitch
		n1.tpc1		= 14;		// C tonal pitch class (non transposed)
		n1.tpc2		= 14;		// C tonal pitch class (transposed)
		c.add(n1);
 
		var n2		= newElement(Element.NOTE);
		n2.pitch	= 64;		// E4 pitch
		n2.tpc1		= 18;
		n2.tpc2		= 18;
		c.add(n2);
 
		var n3		= newElement(Element.NOTE);
		n3.pitch	= 67;		// G4 pitch
		n3.tpc1		= 15;
		n3.tpc2		= 15;
		c.add(n3);

No duration is set, assuming the chord will keep the duration of the element it replaces (i.e. the whole measure rest).

3) HOWEVER: this creates a no-duration chord (the debugger tells its duration is "0/1", whatever this may mean, the actual ticks are 0 and its duration type is empty) and the measure the chord is in is corrupted. This is rendered as a crochet-headed, unstemmed chord:
NOT FOUND: 1

4) if c.duration = 480; is used, the debugger reports the correct chord duration (1/4) and ticks (480), but the duration type is still empty and the measure is corrupted, as it contains only one crochet but its total duration is still 4/4. The visual rendering is the same as above. There does not seem to be any way to set the duration type.

So, unless I dramatically overlooked something very obvious, I would assume either something is wrong or some necessary step is missing in the plug-in framework.

Attachment Size
test_plugin_chord_2.png 1.98 KB

Cursor.addNote() seems to have problems as well.

I tried to find a work-around to add chords by using cursor.addNote() for the first note and adding the remaining notes to the new chord, but I couldn't retrieve a valid pointer to the Chord created by addNote():
After a call to cursor.addNote(), cursor.element == null and cursor.segment also seems outdated (while not null).

This also leads to unexpected results when calling Cursor.next() after Cursor.addNote(). I ran the following on an empty score:

      var cursor = curScore.newCursor();
      cursor.rewind(0);
      cursor.setDuration(1, 4);

      for(var i=0;i<20;i++) {
            cursor.addNote(60);
            cursor.next();
      }

This is what I got:
NOT FOUND: 01

Cursor.next() jumps to the element following the one, that was replaced by the note created by addNote().

Attachment Size
AddNotes.png 3.02 KB

Things are getting more and more complex: now Chord.duration property no longer accepts an int as value: it requires a FractionWrapper, but I am not sure there is a way to create one with the desired numerator and denominator.

(According to gihub, the change happened on April 7th, but I am pretty sure it was working with int at the time of the OP)

In reply to by Jojo-Schmitz

Thanks. Yes I meant within a plugin. Actually I just found a method to insert a non-corrupted chord, but this is not straightforward, the plugin framework is really not easy to work with and the documentation is poor ...
Here is the code if someone is interested:
{syntaxhighlighter class="brush: js"}
// create and return a new Note element with given (midi) pitch, tpc1, tpc2 and headtype
function createNote(pitch, tpc1, tpc2, head){
var note = newElement(Element.NOTE);
note.pitch = pitch;
var pitch2tpc=[14,21,16,23,18,13,20,15,22,17,24,19]; //get tpc from pitch...
if (tpc1){
note.tpc1 = tpc1;
note.tpc2 = tpc2;
}else{
note.tpc1 = pitch2tpc[pitch%12];
note.tpc2 = pitch2tpc[pitch%12];
}
if (head) note.headType = head;
else note.headType = NoteHead.HEAD_AUTO;
//console.log(" created note with tpc: ",tpc1," ",tpc2," pitch: ",pitch);
return note;
}

function setCursorToTime(cursor, time){
cursor.rewind(0);
while (cursor.segment) {
var current_time = cursor.tick;
if(current_time>=time){
return true;
}
cursor.next();
}
cursor.rewind(0);
return false;
}

//adds chord at current position. chord_notes is an array with pitch of notes.
function addChord(cursor, chord_notes, duration){
if(chord_notes.length==0) return -1;
var cur_time=cursor.tick;
cursor.setDuration(1, duration);
cursor.addNote(chord_notes[0]); //add 1st note
setCursorToTime(cursor, cur_time); //rewind to this note
var chord = cursor.element; //get the chord created when 1st note was inserted
for(var i=1; i

In reply to by rousselmanu

I made a demo plugin to insert chords (well it's more like a library), you can download it here: //github.com/rousselmanu/msc_plugins , the file is "addChord.qml "
The example code to generate chords is:
{syntaxhighlighter class="brush: js"}
addChord(cursor, [n2p('D',4)], 2); //add a D4 note
addChord(cursor, [n2p('D',4), n2p('A',4), n2p('D',5), n2p('F',5)], 4); //add a Dm chord with 2 roots
addChord(cursor, [n2p('A#',3), n2p('D',4), n2p('G',4)], 4);
addChord(cursor, [n2p('A',3), n2p('G',4), n2p('C#',5)], 4);
addChord(cursor, [n2p('D',4), n2p('D',5), n2p('F',4), n2p('A',4)], 2);
addChord(cursor, [62], 1); //other method to add note: give the pitch

addChord(cursor, [60, 65, 69, 72, 69], 8); //duplicate note is automatically removed
addChord(cursor, [60], 8);
var chord = [60, 64, 67];
addChord(cursor, shift_notes(chord,5), 8); //shift the chord by 5 semi-tones
addChord(cursor, chord, 2);
{/syntaxhighlighter}
And the result is attached:

Attachment Size
addChord_result.png 7.85 KB

In reply to by rousselmanu

Hi,

I've been struggling with the same thing and came up with a very similar solution. You can also add rests in a similar manner. Once you have added the note at the cursor, you can replace it with a rest.

This works without corrupting the file.

Rewind to the created note then do :

var rest = newElement(Element.REST);
rest.durationType = cursor.element.durationType;
cursor.add(rest);

I am currently testing a plugin that uses this, and it seems to work without a problem. (sorry I don't know how to add a code block. I will find out for future posts).

In reply to by stevel05

I also found that using this method does not work reliably if the target measure already contains notes or rests (other than a full measure rest). So the notes have to be deleted and the measure set to a full-measure-rest. Have you found this, or have you overcome it another way?

In reply to by rousselmanu

Thanks for the feedback, a little digging and I found the reason. The code to add a rest needs to be:
{syntaxhighlighter class="brush: js"}
var rest = newElement(Element.REST);
rest.durationType = cursor.element.durationType;
rest.duration = cursor.element.duration;
cursor.add(rest);
{/syntaxhighlighter}

It now works like a charm without deleting the existing notes, and the workflow will be much easier.

Do you still have an unanswered question? Please log in first to post your question.