Skip to content

Commit 767a0af

Browse files
author
laurent
committed
Corrected spanning-measure patterns
1 parent fd1ec25 commit 767a0af

File tree

1 file changed

+218
-49
lines changed

1 file changed

+218
-49
lines changed

workoutbuilder.qml

Lines changed: 218 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,10 @@ MuseScore {
368368
}
369369

370370
property var _ddNotes: { {
371-
var dd = [''];
372-
dd = dd.concat(_degrees);
371+
var dd=_degrees.map(function (e) { return {text: e, step: e}});
372+
// dd.unshift({text: '<html><span style="font-family:\'MScore Text\'; font-size: 20px; text-align: center; vertical-align: middle">\uE4E5</span></html>', step: 'R'});
373+
dd.unshift({text: '(R)', step: 'R'});
374+
dd.unshift({text: '', step: ''});
373375
return dd;
374376
}
375377
}
@@ -679,14 +681,18 @@ MuseScore {
679681
// 2.4.0 adding in reverse order
680682
for (var j = (_max_steps-1); j >=0 ; j--) {
681683
var sn = raw.steps.get(j);
682-
if (sn.note !== '') {
684+
if (sn.note === 'R') {
685+
p.unshift({"note": null, "duration": sn.duration});
686+
}
687+
else if (sn.note !== '') {
683688
var d = _degrees.indexOf(sn.note);
684689
if (d > -1)
685690
p.unshift({"note": d, "duration": sn.duration});
686691
} else if (p.length===0) {
687692
continue;
688-
} else
689-
p.unshift({"note": null, "duration": sn.duration});
693+
}
694+
// else
695+
// p.unshift({"note": null, "duration": sn.duration});
690696
}
691697

692698

@@ -695,14 +701,25 @@ MuseScore {
695701
}
696702

697703
// 1.2) Completing the pattern to have a round duration
698-
var total=p.map(function(e) {return e.duration}).reduce(function(t,n) { return t+n; });
699-
if ((chkAdaptativeMeasure.checked && chkStrictLayout.checked) && total<Math.ceil(total)) {
700-
var inc=Math.ceil(total)-total;
701-
console.log("adding a rest of "+inc);
702-
p.push({"note": null, "duration": inc});
703-
}
704-
705-
debugO("after cleaning",p);
704+
if (chkAdaptativeMeasure.checked && chkStrictLayout.checked) {
705+
var total = p.map(function (e) {
706+
return e.duration
707+
}).reduce(function (t, n) {
708+
return t + n;
709+
});
710+
if (total < Math.ceil(total)) {
711+
var inc = Math.ceil(total) - total;
712+
console.log("adding a rest of " + inc);
713+
p.push({
714+
"note": null,
715+
"duration": inc
716+
});
717+
} else
718+
console.log("!! Measure is complete. Don't need to add some rests");
719+
} else
720+
console.log("!! Don't need to check for measure completness");
721+
722+
debugO("after cleaning", p);
706723

707724
// 1.3) Retrieving loop mode
708725
var mode = raw.loopMode;
@@ -721,8 +738,6 @@ MuseScore {
721738
} else {
722739
cText = m3 ? "m" : "M";
723740
}
724-
725-
console.log("No Chord Text => will use "+cText+" (because notes are: "+JSON.stringify(nn));
726741

727742
}
728743
var cSymb = _chordTypes[cText];
@@ -1064,18 +1079,53 @@ MuseScore {
10641079
if (adaptativeMeasure) {
10651080
// beatsByMeasure = (pages[i][j].gridType!=="grid")?pages[i][j].notes.length:signatureForPattern(pages[i][j].notes.length);
10661081
beatsByMeasure = (pages[i][j].gridType!==undefined && pages[i][j].gridType!=="grid")?pages[i][j].notes.length:signatureForPattern(pages[i][j].notes);
1067-
console.log("recomputing beatsByMeasure to "+beatsByMeasure+" (#2) / gridType: "+pages[i][j].gridType);
1082+
console.log("recomputing beatsByMeasure to "+beatsByMeasure+" (#2) / gridType: "+pages[i][j].gridType);
10681083
} else {
10691084
beatsByMeasure = 4;
1070-
console.log("forcing beatsByMeasure to "+beatsByMeasure+" (#2) / gridType: "+pages[i][j].gridType);
1085+
console.log("forcing beatsByMeasure to "+beatsByMeasure+" (#2) / gridType: "+pages[i][j].gridType);
10711086
}
10721087
debugO("before print",pages[i][j].notes);
10731088

10741089
for (var k = 0; k < pages[i][j].notes.length; k++, counter++) {
1075-
if (counter > 0) {
1090+
1091+
var duration = pages[i][j].notes[k].duration;
1092+
var fduration = durations.find(function(e) {return e.duration===duration;});
1093+
console.log("duration = "+duration+" => fduration = "+((fduration!==undefined)?fduration.fraction.str:"undefined"));
1094+
fduration=(fduration!==undefined)?fduration.fraction:fraction(1,4);
1095+
1096+
console.log("--["+k+"] NEXT 0");
1097+
1098+
if (counter > 0) { // the first time (ie counter===0, we don't need to move to the next one)
10761099
cursor.rewindToTick(cur_time); // be sure to move to the next rest, as now defined
1077-
var success = cursor.next();
1100+
1101+
1102+
// looking for a next rest
1103+
var success = cursor.next();
1104+
while(success && (cursor.element.type!==Element.REST)) {
1105+
console.log("--["+k+"] NEXT 1: next: "+cursor.element.userName()+" at "+cursor.segment.tick);
1106+
success = cursor.next();
1107+
}
1108+
1109+
1110+
1111+
if(success) {
1112+
// if we have found a next rest, we check if
1113+
// - either this rest is enough for the duration of what we have to write
1114+
// - there is a measure following
1115+
// In the contrary, we add a new measure
1116+
console.log("--["+k+"] NEXT 2: last next: "+cursor.element.userName()+" at "+cursor.segment.tick);
1117+
var remaining=computeRemainingRest(cursor.measure, cursor.track); //, cursor.segment.tick);
1118+
var needed = durationTo64(fduration);
1119+
success=((cursor.measure.nextMeasure!==null) || (needed<=remaining));
1120+
1121+
console.log("?? could move to next segment, ==> checking if enough place or a next measure ("+(cursor.measure.nextMeasure?"next measure":"null")+" -- "+needed+"<>"+remaining+") => "+success);
1122+
} else {
1123+
console.log("--["+k+"] NEXT 2: last next: not found");
1124+
}
1125+
10781126
if (!success) {
1127+
// If the measure is full or doesn't have enough place, we add a new measure
1128+
console.log("--["+k+"] NEXT 3: adding a new measure");
10791129
score.appendMeasures(1);
10801130
cursor.rewindToTick(cur_time);
10811131

@@ -1086,19 +1136,16 @@ MuseScore {
10861136
}
10871137

10881138
cursor.next();
1089-
}
1139+
console.log("--["+k+"] NEXT 4: after new measure: "+cursor.element.userName()+" at "+cursor.segment.tick);
1140+
}
10901141
}
10911142

10921143
var note = cursor.element;
10931144
cur_time = cursor.segment.tick;
10941145

1146+
console.log("--["+k+"] NEXT 5: adding note/rest at "+cursor.segment.tick);
10951147

10961148
var delta = pages[i][j].notes[k].note;
1097-
var duration = pages[i][j].notes[k].duration;
1098-
var fduration = durations.find(function(e) {return e.duration===duration;});
1099-
console.log("duration = "+duration+" => fduration = "+((fduration!==undefined)?fduration.fraction.str:"undefined"));
1100-
console.log(" --> adding as "+((delta!==null)?"note":"rest"));
1101-
fduration=(fduration!==undefined)?fduration.fraction:fraction(1,4);
11021149

11031150
if (delta !== null) {
11041151
// Note
@@ -2614,7 +2661,7 @@ MuseScore {
26142661
}
26152662

26162663
implicitHeight: 30
2617-
implicitWidth: 70
2664+
implicitWidth: 60
26182665

26192666
font.family: 'MScore Text'
26202667
font.pointSize: 9
@@ -2653,6 +2700,7 @@ MuseScore {
26532700
Layout.row: _row
26542701
Layout.column: _column
26552702
Layout.preferredHeight: 30
2703+
// Layout.maximumHeight: 30
26562704
Layout.preferredWidth: 50
26572705

26582706
// spacing: 2 // specific to "Row"
@@ -2661,34 +2709,55 @@ MuseScore {
26612709
// width: 60
26622710

26632711
currentIndex: modeIndex()
2664-
// implicitWidth: 60
2665-
2666-
2667-
// property int stepIndex: index % _max_steps
2668-
// property int patternIndex: Math.floor(index / _max_steps)
26692712

2670-
26712713
ComboBox {
2672-
id: lstStep
2673-
model: _ddNotes
2714+
id: lstStep
2715+
model: _ddNotes
2716+
2717+
textRole: "text"
2718+
property var valueRole: "step"
2719+
2720+
onActivated: {
2721+
note = model[currentIndex][valueRole];
2722+
console.log(note);
2723+
}
2724+
2725+
Binding on currentIndex {
2726+
// value: model.map(function (e) {
2727+
// return e[lstStep.valueRole]
2728+
// }).indexOf(note);
2729+
value: {
2730+
_ddNotes.map(function (e) {
2731+
return e[lstStep.valueRole]
2732+
}).indexOf(note);
2733+
}
2734+
}
2735+
2736+
editable: false
2737+
implicitWidth: 30
2738+
2739+
delegate: ItemDelegate {
2740+
contentItem: Text {
2741+
text: modelData[lstStep.textRole]
2742+
// textFormat: Text.RichText
2743+
anchors.verticalCenter: parent.verticalCenter
2744+
font: lstStep.font
2745+
}
2746+
highlighted: lstStep.highlightedIndex === index
2747+
2748+
}
2749+
2750+
contentItem: Text {
2751+
text: lstStep.displayText
2752+
// textFormat: Text.RichText
2753+
verticalAlignment: Text.AlignVCenter
2754+
anchors.verticalCenter: parent.verticalCenter
2755+
horizontalAlignment: Qt.AlignHCenter
2756+
}
26742757

2675-
onActivated: {
2676-
note = model[currentIndex];
2677-
workoutName = undefined; // resetting the name of the
2678-
}
2679-
2680-
Binding on currentIndex {
2681-
value: lstStep.model.indexOf(note)
2682-
}
2683-
2684-
Layout.alignment: Qt.AlignLeft | Qt.QtAlignBottom
2685-
editable: false
2686-
implicitWidth: 30
26872758
}
2688-
2689-
26902759
ComboBox {
2691-
id: lstGStep
2760+
id: lstGStep
26922761

26932762
model: _ddGridNotes
26942763

@@ -4341,5 +4410,105 @@ MuseScore {
43414410
console.log(label + ": " + element);
43424411
}
43434412
}
4413+
4414+
4415+
// -----------------------------
4416+
/**
4417+
* Computes the duration of the rests at the end of the measure.
4418+
* If the track is empty (no chords, no rests) return an arbitrary value of -1
4419+
*/
4420+
function computeRemainingRest(measure, track, abovetick) {
4421+
var last = measure.lastSegment;
4422+
var duration = 0;
4423+
4424+
console.log("Analyzing track " + (((track !== undefined) && (track != null)) ? track : "all") + ", above " + (abovetick ? abovetick : "-1"));
4425+
4426+
if ((track !== undefined) && (track != null)) {
4427+
duration = _computeRemainingRest(measure, track, abovetick);
4428+
return duration;
4429+
4430+
} else {
4431+
duration = 999;
4432+
// Analyze made on all tracks
4433+
for (var t = 0; t < curScore.ntracks; t++) {
4434+
console.log(">>>> " + t + "/" + curScore.ntracks + " <<<<");
4435+
var localavailable = _computeRemainingRest(measure, t, abovetick);
4436+
console.log("Available at track " + t + ": " + localavailable + " (" + duration + ")");
4437+
duration = Math.min(duration, localavailable);
4438+
if (duration == 0)
4439+
break;
4440+
}
4441+
return duration;
4442+
}
4443+
4444+
}
4445+
4446+
/*
4447+
* Instead of counting the rests at the end of measure, we count what's inside the measure beyond the last rests.
4448+
* That way, we take into account the fact that changing the time signature of a measure doesn't fill it with rests, but leaves an empty space.
4449+
*/
4450+
function _computeRemainingRest(measure, track, abovetick) {
4451+
var last = measure.lastSegment;
4452+
var duration = sigTo64(measure.timesigActual);
4453+
4454+
// setting the limit until which to look for rests
4455+
abovetick = (abovetick === undefined) ? -1 : abovetick;
4456+
4457+
console.log("_computeRemainingRest: " + (((track !== undefined) && (track != null)) ? track : "all") + ", above tick " + (abovetick ? abovetick : "-1"));
4458+
4459+
if ((track !== undefined) && (track != null)) {
4460+
// Analyze limited to one track
4461+
var inTail = true;
4462+
while ((last != null)) {
4463+
var element = _d(last, track);
4464+
// if ((element != null) && ((element.type == Element.CHORD) )) {
4465+
if ((element != null) && ((element.type == Element.CHORD) || (last.tick <= abovetick))) { // 16/3/22
4466+
if (inTail)
4467+
console.log("switching outside of available buffer");
4468+
// As soon as we encounter a Chord, we leave the "rest-tail"
4469+
inTail = false;
4470+
}
4471+
if ((element != null) && ((element.type == Element.REST) || (element.type == Element.CHORD)) && !inTail) {
4472+
// When not longer in the "rest-tail" we decrease the remaing length by the element duration
4473+
// var eldur=durationTo64(element.duration);
4474+
// 1.3.0 take into account the effective dur of the element when within a tuplet
4475+
var eldur = elementTo64Effective(element);
4476+
duration -= eldur;
4477+
}
4478+
last = last.prevInMeasure;
4479+
}
4480+
}
4481+
4482+
duration = Math.round(duration);
4483+
return duration;
4484+
}
4485+
4486+
/**
4487+
* Effective duration of an element (so taking into account the tuplet it belongs to)
4488+
*/
4489+
function elementTo64Effective(element) {
4490+
// if (!element.duration)
4491+
// return 0;
4492+
var dur = durationTo64(element.duration);
4493+
if (element.tuplet !== null) {
4494+
dur = dur * element.tuplet.normalNotes / element.tuplet.actualNotes;
4495+
}
4496+
return dur;
4497+
}
4498+
function durationTo64(duration) {
4499+
return 64 * duration.numerator / duration.denominator;
4500+
}
4501+
4502+
function sigTo64(sig) {
4503+
return 64 * sig.numerator / sig.denominator;
4504+
}
4505+
4506+
4507+
function _d(last, track) {
4508+
var el = last.elementAt(track);
4509+
console.log(" At " + last.tick + "/" + track + ": " + ((el !== null) ? el.userName() : " / "));
4510+
return el;
4511+
}
4512+
43444513

43454514
}

0 commit comments

Comments
 (0)