smoosic 1.0.37 → 1.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/build/smoosic.js +89 -29
- package/changes.md +9 -1
- package/package.json +1 -1
- package/release/smoosic.js +89 -29
- package/src/application/exports.ts +4 -4
- package/src/render/audio/musicCursor.ts +1 -1
- package/src/render/sui/NoteEntryCaret.ts +4 -1
- package/src/render/sui/formatter.ts +3 -3
- package/src/render/sui/mapper.ts +1 -1
- package/src/render/sui/scoreView.ts +4 -4
- package/src/render/sui/scoreViewOperations.ts +10 -10
- package/src/render/sui/textEdit.ts +3 -1
- package/src/render/vex/vxMeasure.ts +12 -6
- package/src/smo/data/measure.ts +37 -37
- package/src/smo/data/measureModifiers.ts +106 -71
- package/src/smo/data/note.ts +4 -1
- package/src/smo/data/score.ts +50 -11
- package/src/smo/data/systemStaff.ts +2 -2
- package/src/smo/midi/midiToSmo.ts +28 -29
- package/src/smo/midi/smoToMidi.ts +3 -3
- package/src/smo/mxml/smoToXml.ts +11 -11
- package/src/smo/mxml/xmlState.ts +3 -3
- package/src/smo/mxml/xmlToSmo.ts +9 -9
- package/src/smo/xform/copypaste.ts +3 -3
- package/src/smo/xform/operations.ts +9 -6
- package/src/smo/xform/tickDuration.ts +10 -2
- package/src/ui/buttons/display.ts +2 -2
- package/src/ui/buttons/ribbon.ts +2 -2
- package/src/ui/components/dialogs/timeSignature.vue +223 -0
- package/src/ui/dialogs/fileDialogs.ts +1 -1
- package/src/ui/dialogs/keySignature.ts +1 -1
- package/src/ui/dialogs/tempo.ts +38 -38
- package/src/ui/dialogs/timeSignature.ts +45 -116
- package/src/ui/menus/timeSignature.ts +2 -2
- package/tools/smoosic-schema.json +4 -4
|
@@ -37,7 +37,7 @@ import { SuiTransposeScoreDialogVue} from '../ui/dialogs/transposeScore';
|
|
|
37
37
|
import { SuiMeasureFormatDialogVue } from '../ui/dialogs/measureFormat';
|
|
38
38
|
import { SuiInsertMeasuresVue } from '../ui/dialogs/addMeasure';
|
|
39
39
|
import { SuiInstrumentDialogVue } from '../ui/dialogs/instrument';
|
|
40
|
-
import {
|
|
40
|
+
import { SuiTimeSignatureDialogVue } from '../ui/dialogs/timeSignature';
|
|
41
41
|
import { SuiTempoDialog } from '../ui/dialogs/tempo';
|
|
42
42
|
import { SuiNoteHeadDialog } from '../ui/dialogs/noteHead';
|
|
43
43
|
import { SuiEndingsDialogVue } from '../ui/dialogs/endings';
|
|
@@ -153,7 +153,7 @@ import { SmoOperation } from '../smo/xform/operations';
|
|
|
153
153
|
import { ScoreRoadMapBuilder } from '../smo/xform/roadmap';
|
|
154
154
|
import {
|
|
155
155
|
SmoRehearsalMark, SmoMeasureFormat, SmoBarline, SmoRepeatSymbol,
|
|
156
|
-
SmoVolta, SmoMeasureText,
|
|
156
|
+
SmoVolta, SmoMeasureText, SmoTempo, SmoTimeSignature, measureModifierDynamicCtorInit
|
|
157
157
|
} from '../smo/data/measureModifiers';
|
|
158
158
|
import { SmoToXml } from '../smo/mxml/smoToXml';
|
|
159
159
|
import { MidiToSmo } from '../smo/midi/midiToSmo';
|
|
@@ -357,7 +357,7 @@ export const Smo = {
|
|
|
357
357
|
GlobalLayoutNumberAttributesArray,
|
|
358
358
|
SuiTransposeScoreDialogVue,
|
|
359
359
|
SuiScoreFontDialogVue, SuiPageLayoutDialogVue, SuiMeasureFormatDialogVue, SuiInsertMeasuresVue,
|
|
360
|
-
|
|
360
|
+
SuiTimeSignatureDialogVue,SuiTextBlockDialog, SuiLyricDialog, SuiChordChangeDialog,
|
|
361
361
|
SuiSlurAttributesDialog, SuiPedalMarkingDialog, SuiTieAttributesDialog, SuiVoltaAttributeDialog,
|
|
362
362
|
SuiHairpinAttributesDialog, SuiStaffGroupDialogVue,
|
|
363
363
|
SuiScorePreferencesDialogVue,
|
|
@@ -400,7 +400,7 @@ SuiPitchComposite,
|
|
|
400
400
|
// score modifiers
|
|
401
401
|
SmoSystemGroup, SmoAudioPlayerSettings, SmoTextGroup,
|
|
402
402
|
// measure modifiers
|
|
403
|
-
SmoRehearsalMark, SmoMeasureFormat, SmoBarline, SmoRepeatSymbol, SmoVolta, SmoMeasureText,
|
|
403
|
+
SmoRehearsalMark, SmoMeasureFormat, SmoBarline, SmoRepeatSymbol, SmoVolta, SmoMeasureText, SmoTempo, SmoTimeSignature,
|
|
404
404
|
measureModifierDynamicCtorInit,
|
|
405
405
|
// note modifiers
|
|
406
406
|
SmoOrnament, noteModifierDynamicCtorInit,
|
|
@@ -72,7 +72,7 @@ export const defaultClearAudioAnimationHandler = (delay: number) => {
|
|
|
72
72
|
}
|
|
73
73
|
const screenBox = SvgHelpers.boxPoints(x, y, width, height);
|
|
74
74
|
const fillParams: Record<string, string> = {};
|
|
75
|
-
console.log(`topbox xy ${measure.svg.logicalBox.x}, ${measure.svg.logicalBox.y} x ${x}, ${y}`);
|
|
75
|
+
// console.log(`topbox xy ${measure.svg.logicalBox.x}, ${measure.svg.logicalBox.y} x ${x}, ${y}`);
|
|
76
76
|
fillParams['fill-opacity'] = '0.5';
|
|
77
77
|
fillParams['fill'] = '#4444ff';
|
|
78
78
|
const ctx = context.getContext();
|
|
@@ -203,7 +203,10 @@ export class NoteEntryCaret {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
const staveNote = vexNote as StaveNote;
|
|
206
|
-
|
|
206
|
+
if (!staveNote.noteHeads) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const noteHeads = staveNote.noteHeads;
|
|
207
210
|
|
|
208
211
|
this.vexNoteLeftDisplacedHeadPx = staveNote.getMetrics().leftDisplacedHeadPx;
|
|
209
212
|
this.vexNoteRightDisplacedHeadPx = staveNote.getMetrics().rightDisplacedHeadPx;
|
|
@@ -16,7 +16,7 @@ import { SmoStaffHairpin, SmoStaffTextBracket, SmoTabStave } from '../../smo/dat
|
|
|
16
16
|
import { layoutDebug } from './layoutDebug';
|
|
17
17
|
import { ScaledPageLayout, SmoLayoutManager, SmoPageLayout } from '../../smo/data/scoreModifiers';
|
|
18
18
|
import { SmoMeasure, ISmoBeamGroup } from '../../smo/data/measure';
|
|
19
|
-
import {
|
|
19
|
+
import { SmoTimeSignature, SmoTempo } from '../../smo/data//measureModifiers';
|
|
20
20
|
import { SvgPageMap } from './svgPageMap';
|
|
21
21
|
import { VexFlow, defaultMeasurePadding } from '../../common/vex';
|
|
22
22
|
import { TextFormatter } from '../../common/textformatter';
|
|
@@ -831,7 +831,7 @@ export class SuiLayoutFormatter {
|
|
|
831
831
|
* @param score
|
|
832
832
|
*/
|
|
833
833
|
calculateBeginningSymbols(systemIndex: number, measure: SmoMeasure,
|
|
834
|
-
clefLast: string, keySigLast: string, timeSigLast:
|
|
834
|
+
clefLast: string, keySigLast: string, timeSigLast: SmoTimeSignature, tempoLast: SmoTempo) {
|
|
835
835
|
// The key signature is set based on the transpose index already, i.e. an Eb part in concert C already has 3 sharps.
|
|
836
836
|
const xposeScore = this.score?.preferences?.transposingScore && (this.score?.isPartExposed() === false);
|
|
837
837
|
// const xposeOffset = xposeScore ? measure.transposeIndex : 0;
|
|
@@ -850,7 +850,7 @@ export class SuiLayoutFormatter {
|
|
|
850
850
|
measure.svg.forceTempo = tempo.display && measure.svg.rowInSystem === 0;
|
|
851
851
|
} else if (tempo && tempoLast) {
|
|
852
852
|
// otherwise get tempo from the measure prior. But only one tempo per system.
|
|
853
|
-
if (!
|
|
853
|
+
if (!SmoTempo.eq(tempo, tempoLast) && measure.svg.rowInSystem === 0) {
|
|
854
854
|
measure.svg.forceTempo = tempo.display;
|
|
855
855
|
}
|
|
856
856
|
} else if (tempo) {
|
package/src/render/sui/mapper.ts
CHANGED
|
@@ -159,7 +159,7 @@ export abstract class SuiMapper {
|
|
|
159
159
|
this.localModifiers.push({ index, selection: sel, modifier: volta, box: volta.logicalBox ?? SvgBox.default });
|
|
160
160
|
index += 1;
|
|
161
161
|
});
|
|
162
|
-
sel.measure.getModifiersByType('
|
|
162
|
+
sel.measure.getModifiersByType('SmoTempo').forEach((tempo) => {
|
|
163
163
|
this.localModifiers.push({ index, selection: sel, modifier: tempo, box: tempo.logicalBox ?? SvgBox.default });
|
|
164
164
|
index += 1;
|
|
165
165
|
});
|
|
@@ -23,8 +23,8 @@ import { ScoreRenderParams } from './scoreRender';
|
|
|
23
23
|
import { SmoOperation } from '../../smo/xform/operations';
|
|
24
24
|
import { SuiAudioPlayer } from '../audio/player';
|
|
25
25
|
import { SuiAudioAnimationParams } from '../audio/musicCursor';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
26
|
+
import { SmoTempo } from '../../smo/data/measureModifiers';
|
|
27
|
+
import { SmoTimeSignature } from '../../smo/data/measureModifiers';
|
|
28
28
|
import { ref, Ref } from 'vue';
|
|
29
29
|
import { SvgBox, SvgPoint } from '../../smo/data/common';
|
|
30
30
|
import { layoutDebug } from './layoutDebug';
|
|
@@ -685,8 +685,8 @@ export abstract class SuiScoreView implements layoutProvider {
|
|
|
685
685
|
}
|
|
686
686
|
nStave.measures.forEach((measure: SmoMeasure, ix) => {
|
|
687
687
|
const srcMeasure = srcStave.measures[ix];
|
|
688
|
-
measure.tempo = new
|
|
689
|
-
measure.timeSignature = new
|
|
688
|
+
measure.tempo = new SmoTempo(srcMeasure.tempo.serialize());
|
|
689
|
+
measure.timeSignature = new SmoTimeSignature(srcMeasure.timeSignature);
|
|
690
690
|
measure.keySignature = srcMeasure.keySignature;
|
|
691
691
|
});
|
|
692
692
|
staffMap.push(i);
|
|
@@ -14,8 +14,8 @@ import { SmoTextGroup } from '../../smo/data/scoreText';
|
|
|
14
14
|
import { SmoDynamicText, SmoNoteModifierBase, SmoGraceNote, SmoArticulation,
|
|
15
15
|
SmoOrnament, SmoLyric, SmoMicrotone, SmoArpeggio, SmoArpeggioType, SmoClefChange,
|
|
16
16
|
SmoTabNote} from '../../smo/data/noteModifiers';
|
|
17
|
-
import {
|
|
18
|
-
SmoRehearsalMark, SmoMeasureFormat,
|
|
17
|
+
import { SmoTempo, SmoVolta, SmoBarline, SmoRepeatSymbol,
|
|
18
|
+
SmoRehearsalMark, SmoMeasureFormat, SmoTimeSignature } from '../../smo/data/measureModifiers';
|
|
19
19
|
import { UndoBuffer } from '../../smo/xform/undo';
|
|
20
20
|
import {
|
|
21
21
|
SmoOperation, createStaffModifierType, MakeTupletOperation
|
|
@@ -525,7 +525,7 @@ export class SuiScoreViewOperations extends SuiScoreView {
|
|
|
525
525
|
* Set the time signature for a selection
|
|
526
526
|
* @param timeSignature actual time signature
|
|
527
527
|
*/
|
|
528
|
-
async setTimeSignature(timeSignature:
|
|
528
|
+
async setTimeSignature(timeSignature: SmoTimeSignature): Promise<void> {
|
|
529
529
|
this._undoScore('Set time signature');
|
|
530
530
|
const selections = this.tracker.selections;
|
|
531
531
|
const altSelections = this._getEquivalentSelections(selections);
|
|
@@ -627,9 +627,9 @@ export class SuiScoreViewOperations extends SuiScoreView {
|
|
|
627
627
|
* @param scoreMode if true, update whole score. Else selections
|
|
628
628
|
* @returns
|
|
629
629
|
*/
|
|
630
|
-
async updateTempoScore(measure: SmoMeasure, tempo:
|
|
630
|
+
async updateTempoScore(measure: SmoMeasure, tempo: SmoTempo, scoreMode: boolean, selectionMode: boolean): Promise<void> {
|
|
631
631
|
let measureIndex = 0;
|
|
632
|
-
const originalTempo = new
|
|
632
|
+
const originalTempo = new SmoTempo(measure.tempo);
|
|
633
633
|
this._undoColumn('update tempo', measure.measureNumber.measureIndex);
|
|
634
634
|
let startMeasure = measure.measureNumber.measureIndex;
|
|
635
635
|
let endMeasure = this.score.staves[0].measures.length;
|
|
@@ -641,14 +641,14 @@ export class SuiScoreViewOperations extends SuiScoreView {
|
|
|
641
641
|
}
|
|
642
642
|
}
|
|
643
643
|
// If we are only changing the position of the text, it only affects the tempo measure.
|
|
644
|
-
if (
|
|
644
|
+
if (SmoTempo.eq(originalTempo, tempo) && tempo.yOffset !== originalTempo.yOffset && endMeasure > startMeasure) {
|
|
645
645
|
endMeasure = startMeasure + 1;
|
|
646
646
|
}
|
|
647
647
|
for (measureIndex = startMeasure; measureIndex < endMeasure; ++measureIndex) {
|
|
648
648
|
if (!scoreMode && !selectionMode) {
|
|
649
649
|
// If not whole score or selections, change until the tempo doesn't match previous measure's tempo (next tempo change)
|
|
650
650
|
const compMeasure = this.score.staves[0].measures[measureIndex];
|
|
651
|
-
if (
|
|
651
|
+
if (SmoTempo.eq(originalTempo, compMeasure.tempo) || displayed === false) {
|
|
652
652
|
const sel = SmoSelection.measureSelection(this.score, 0, measureIndex);
|
|
653
653
|
const altSel = SmoSelection.measureSelection(this.storeScore, 0, measureIndex);
|
|
654
654
|
if (sel && sel.measure.tempo.display && !displayed) {
|
|
@@ -706,17 +706,17 @@ export class SuiScoreViewOperations extends SuiScoreView {
|
|
|
706
706
|
* default tempo, or the previously-set tempo.
|
|
707
707
|
* @param scoreMode whether to reset entire score
|
|
708
708
|
*/
|
|
709
|
-
async removeTempo(measure: SmoMeasure, tempo:
|
|
709
|
+
async removeTempo(measure: SmoMeasure, tempo: SmoTempo, scoreMode: boolean, selectionMode: boolean): Promise<void> {
|
|
710
710
|
const startSelection = this.tracker.selections[0];
|
|
711
711
|
if (startSelection.selector.measure > 0) {
|
|
712
712
|
const measureIx = startSelection.selector.measure - 1;
|
|
713
713
|
const target = startSelection.staff.measures[measureIx];
|
|
714
714
|
const tempo = target.getTempo();
|
|
715
|
-
const newTempo = new
|
|
715
|
+
const newTempo = new SmoTempo(tempo);
|
|
716
716
|
newTempo.display = false;
|
|
717
717
|
this.updateTempoScore(measure, newTempo, scoreMode, selectionMode);
|
|
718
718
|
} else {
|
|
719
|
-
this.updateTempoScore(measure, new
|
|
719
|
+
this.updateTempoScore(measure, new SmoTempo(SmoTempo.defaults), scoreMode, selectionMode);
|
|
720
720
|
}
|
|
721
721
|
await this.renderer.updatePromise();
|
|
722
722
|
}
|
|
@@ -850,7 +850,9 @@ export class SuiChordEditor extends SuiTextEditor {
|
|
|
850
850
|
if (this.svgText !== null && this.svgText.blocks.length > this.textPos && this.textPos >= 0) {
|
|
851
851
|
this.textType = this.svgText.blocks[this.textPos].textType;
|
|
852
852
|
}
|
|
853
|
-
evdata.preventDefault
|
|
853
|
+
if (typeof(evdata.preventDefault) === 'function') {
|
|
854
|
+
evdata.preventDefault(); // prevent browser scroll
|
|
855
|
+
}
|
|
854
856
|
|
|
855
857
|
return edited;
|
|
856
858
|
}
|
|
@@ -543,15 +543,21 @@ export class VxMeasure implements VxMeasureIf {
|
|
|
543
543
|
this.stave = createStave(smoVexStaveParams);
|
|
544
544
|
if (this.smoMeasure.svg.forceTimeSignature) {
|
|
545
545
|
const ts = this.smoMeasure.timeSignature;
|
|
546
|
-
|
|
546
|
+
|
|
547
547
|
if (this.smoMeasure.timeSignature.useSymbol && ts.actualBeats === 4 && ts.beatDuration === 4) {
|
|
548
|
-
|
|
548
|
+
this.stave.addTimeSignature('C');
|
|
549
549
|
} else if (this.smoMeasure.timeSignature.useSymbol && ts.actualBeats === 2 && ts.beatDuration === 4) {
|
|
550
|
-
|
|
551
|
-
} else
|
|
552
|
-
tsString = this.smoMeasure.timeSignature.displayString;
|
|
550
|
+
this.stave.addTimeSignature('C|');
|
|
551
|
+
} else {
|
|
552
|
+
let tsString = this.smoMeasure.timeSignature.displayString.length ? this.smoMeasure.timeSignature.displayString : ts.timeSignature;
|
|
553
|
+
const tsStrings = tsString.split('+');
|
|
554
|
+
for (let i = 0; i < tsStrings.length; i++) {
|
|
555
|
+
const tsString = tsStrings[i].trim();
|
|
556
|
+
if (tsString.length) {
|
|
557
|
+
this.stave.addTimeSignature(tsStrings[i].trim());
|
|
558
|
+
}
|
|
559
|
+
}
|
|
553
560
|
}
|
|
554
|
-
this.stave.addTimeSignature(tsString);
|
|
555
561
|
}
|
|
556
562
|
// Connect it to the rendering context and draw!
|
|
557
563
|
this.stave.setContext(this.context.getContext());
|
package/src/smo/data/measure.ts
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
import { smoSerialize } from '../../common/serializationHelpers';
|
|
13
13
|
import { SmoMusic } from './music';
|
|
14
14
|
import {
|
|
15
|
-
SmoBarline, SmoMeasureModifierBase, SmoRepeatSymbol,
|
|
16
|
-
SmoVolta, SmoRehearsalMarkParams, SmoRehearsalMark,
|
|
17
|
-
TimeSignatureParametersSer, SmoMeasureFormatParamsSer,
|
|
15
|
+
SmoBarline, SmoMeasureModifierBase, SmoRepeatSymbol, SmoTempo, SmoMeasureFormat,
|
|
16
|
+
SmoVolta, SmoRehearsalMarkParams, SmoRehearsalMark, SmoTempoParams, SmoTimeSignature,
|
|
17
|
+
TimeSignatureParametersSer, SmoMeasureFormatParamsSer, SmoTempoParamsSer
|
|
18
18
|
} from './measureModifiers';
|
|
19
19
|
import { SmoNote, NoteType, SmoNoteParamsSer } from './note';
|
|
20
20
|
import { SmoTuplet, SmoTupletParamsSer, SmoTupletParams, SmoTupletTreeParamsSer, SmoTupletTree } from './tuplet';
|
|
@@ -148,7 +148,7 @@ export const SmoMeasureStringParams: SmoMeasureStringParam[] = ['keySignature'];
|
|
|
148
148
|
* @category SmoObject
|
|
149
149
|
*/
|
|
150
150
|
export interface SmoMeasureParams {
|
|
151
|
-
timeSignature:
|
|
151
|
+
timeSignature: SmoTimeSignature,
|
|
152
152
|
keySignature: string,
|
|
153
153
|
tupletTrees: SmoTupletTree[],
|
|
154
154
|
transposeIndex: number,
|
|
@@ -158,7 +158,7 @@ export interface SmoMeasureParams {
|
|
|
158
158
|
clef: Clef,
|
|
159
159
|
voices: SmoVoice[],
|
|
160
160
|
activeVoice: number,
|
|
161
|
-
tempo:
|
|
161
|
+
tempo: SmoTempo,
|
|
162
162
|
format: SmoMeasureFormat | null,
|
|
163
163
|
modifiers: SmoMeasureModifierBase[],
|
|
164
164
|
repeatSymbol: boolean,
|
|
@@ -218,7 +218,7 @@ export interface SmoMeasureParamsSer {
|
|
|
218
218
|
/**
|
|
219
219
|
* tempo at this point
|
|
220
220
|
*/
|
|
221
|
-
tempo:
|
|
221
|
+
tempo: SmoTempoParamsSer
|
|
222
222
|
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -244,8 +244,8 @@ function isSmoMeasureParamsSer(params: Partial<SmoMeasureParamsSer>):params is S
|
|
|
244
244
|
* @category SmoObject
|
|
245
245
|
*/
|
|
246
246
|
export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
247
|
-
static get timeSignatureDefault():
|
|
248
|
-
return new
|
|
247
|
+
static get timeSignatureDefault(): SmoTimeSignature {
|
|
248
|
+
return new SmoTimeSignature(SmoTimeSignature.defaults);
|
|
249
249
|
}
|
|
250
250
|
static defaultDupleDuration: number = 4096;
|
|
251
251
|
static defaultTripleDuration: number = 2048 * 3;
|
|
@@ -268,7 +268,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
268
268
|
voices: [],
|
|
269
269
|
format: new SmoMeasureFormat(SmoMeasureFormat.defaults),
|
|
270
270
|
activeVoice: 0,
|
|
271
|
-
tempo: new
|
|
271
|
+
tempo: new SmoTempo(SmoTempo.defaults),
|
|
272
272
|
repeatSymbol: false,
|
|
273
273
|
repeatCount: 0
|
|
274
274
|
}
|
|
@@ -281,7 +281,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
281
281
|
static get defaults(): SmoMeasureParams {
|
|
282
282
|
const proto: any = JSON.parse(JSON.stringify(SmoMeasure._defaults));
|
|
283
283
|
proto.format = new SmoMeasureFormat(SmoMeasureFormat.defaults);
|
|
284
|
-
proto.tempo = new
|
|
284
|
+
proto.tempo = new SmoTempo(SmoTempo.defaults);
|
|
285
285
|
proto.modifiers.push(new SmoBarline({
|
|
286
286
|
position: SmoBarline.positions.start,
|
|
287
287
|
barline: SmoBarline.barlines.singleBar
|
|
@@ -294,11 +294,11 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
294
294
|
}
|
|
295
295
|
// @ignore
|
|
296
296
|
static convertLegacyTimeSignature(ts: string) {
|
|
297
|
-
const rv = new
|
|
297
|
+
const rv = new SmoTimeSignature(SmoTimeSignature.defaults);
|
|
298
298
|
rv.timeSignature = ts;
|
|
299
299
|
return rv;
|
|
300
300
|
}
|
|
301
|
-
timeSignature:
|
|
301
|
+
timeSignature: SmoTimeSignature = SmoMeasure.timeSignatureDefault;
|
|
302
302
|
/**
|
|
303
303
|
* Overrides display of actual time signature, in the case of
|
|
304
304
|
* pick-up notes where the actual and displayed durations are different
|
|
@@ -329,7 +329,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
329
329
|
* the active voice in the editor, if there are multiple voices
|
|
330
330
|
* */
|
|
331
331
|
activeVoice: number = 0;
|
|
332
|
-
tempo:
|
|
332
|
+
tempo: SmoTempo;
|
|
333
333
|
beamGroups: ISmoBeamGroup[] = [];
|
|
334
334
|
lines: number = 5;
|
|
335
335
|
/**
|
|
@@ -351,7 +351,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
351
351
|
* @param params
|
|
352
352
|
*/
|
|
353
353
|
constructor(params: SmoMeasureParams) {
|
|
354
|
-
this.tempo = new
|
|
354
|
+
this.tempo = new SmoTempo(SmoTempo.defaults);
|
|
355
355
|
this.svg = {
|
|
356
356
|
staffWidth: 0,
|
|
357
357
|
unjustifiedWidth: 0,
|
|
@@ -392,7 +392,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
392
392
|
this.repeatSymbol = params.repeatSymbol;
|
|
393
393
|
this.measureNumber = JSON.parse(JSON.stringify(params.measureNumber));
|
|
394
394
|
if (params.tempo) {
|
|
395
|
-
this.tempo = new
|
|
395
|
+
this.tempo = new SmoTempo(params.tempo);
|
|
396
396
|
}
|
|
397
397
|
// Handle legacy time signature format
|
|
398
398
|
if (params.timeSignature) {
|
|
@@ -400,7 +400,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
400
400
|
if (typeof (tsAny) === 'string') {
|
|
401
401
|
this.timeSignature = SmoMeasure.convertLegacyTimeSignature(tsAny);
|
|
402
402
|
} else {
|
|
403
|
-
this.timeSignature =
|
|
403
|
+
this.timeSignature = SmoTimeSignature.createFromPartial(tsAny);
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
406
|
this.voices = params.voices ? params.voices : [];
|
|
@@ -454,7 +454,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
454
454
|
// Return true if the time signatures are the same, for display purposes (e.g. if a time sig change
|
|
455
455
|
// is required)
|
|
456
456
|
*/
|
|
457
|
-
static timeSigEqual(o1:
|
|
457
|
+
static timeSigEqual(o1: SmoTimeSignature, o2: SmoTimeSignature) {
|
|
458
458
|
return o1.timeSignature === o2.timeSignature && o1.useSymbol === o2.useSymbol;
|
|
459
459
|
}
|
|
460
460
|
/**
|
|
@@ -568,7 +568,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
568
568
|
} else if (modifier.ctor === 'SmoBarline' && (modifier as SmoBarline).position === SmoBarline.positions.end
|
|
569
569
|
&& (modifier as SmoBarline).barline === SmoBarline.barlines.singleBar) {
|
|
570
570
|
ser = false;
|
|
571
|
-
} else if (modifier.ctor === '
|
|
571
|
+
} else if (modifier.ctor === 'SmoTempo') {
|
|
572
572
|
// we don't save tempo text as a modifier anymore
|
|
573
573
|
ser = false;
|
|
574
574
|
} else if ((modifier as SmoRepeatSymbol).ctor === 'SmoRepeatSymbol' && (modifier as SmoRepeatSymbol).position === SmoRepeatSymbol.positions.start
|
|
@@ -639,9 +639,9 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
639
639
|
|
|
640
640
|
// explode column-mapped
|
|
641
641
|
if (jsonObj.tempo) {
|
|
642
|
-
params.tempo =
|
|
642
|
+
params.tempo = SmoTempo.deserialize(jsonObj.tempo);
|
|
643
643
|
} else {
|
|
644
|
-
params.tempo = new
|
|
644
|
+
params.tempo = new SmoTempo(SmoTempo.defaults);
|
|
645
645
|
}
|
|
646
646
|
|
|
647
647
|
// timeSignatureString is now part of timeSignature. upconvert old scores
|
|
@@ -654,13 +654,14 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
654
654
|
if (timeSignatureString.length) {
|
|
655
655
|
jsonObj.timeSignature.displayString = timeSignatureString;
|
|
656
656
|
}
|
|
657
|
-
|
|
657
|
+
jsonObj.timeSignature.ctor = 'SmoTimeSignature';
|
|
658
|
+
params.timeSignature = SmoTimeSignature.deserialize(jsonObj.timeSignature);
|
|
658
659
|
} else {
|
|
659
|
-
const tparams =
|
|
660
|
+
const tparams = SmoTimeSignature.defaults;
|
|
660
661
|
if (timeSignatureString.length) {
|
|
661
662
|
tparams.displayString = timeSignatureString;
|
|
662
663
|
}
|
|
663
|
-
params.timeSignature = new
|
|
664
|
+
params.timeSignature = new SmoTimeSignature(tparams);
|
|
664
665
|
}
|
|
665
666
|
params.keySignature = jsonObj.keySignature ?? 'C';
|
|
666
667
|
params.voices = voices;
|
|
@@ -725,12 +726,12 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
725
726
|
const measure = new SmoMeasure(params);
|
|
726
727
|
// Handle migration for measure-mapped parameters
|
|
727
728
|
measure.modifiers.forEach((mod) => {
|
|
728
|
-
if (mod.ctor === '
|
|
729
|
-
measure.tempo = (mod as
|
|
729
|
+
if (mod.ctor === 'SmoTempo') {
|
|
730
|
+
measure.tempo = (mod as SmoTempo);
|
|
730
731
|
}
|
|
731
732
|
});
|
|
732
733
|
if (!measure.tempo) {
|
|
733
|
-
measure.tempo = new
|
|
734
|
+
measure.tempo = new SmoTempo(SmoTempo.defaults);
|
|
734
735
|
}
|
|
735
736
|
|
|
736
737
|
|
|
@@ -747,8 +748,8 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
747
748
|
// Ordinarily, the key/tempo/time is mapped to the stave, but since we are pasting measure-by
|
|
748
749
|
// measure here, we want to preserve it.
|
|
749
750
|
clonedMeasure.keySignature = measure.keySignature;
|
|
750
|
-
clonedMeasure.timeSignature = new
|
|
751
|
-
clonedMeasure.tempo = new
|
|
751
|
+
clonedMeasure.timeSignature = new SmoTimeSignature(measure.timeSignature);
|
|
752
|
+
clonedMeasure.tempo = new SmoTempo(measure.tempo);
|
|
752
753
|
return clonedMeasure;
|
|
753
754
|
}
|
|
754
755
|
hasNonRestNotes(): boolean {
|
|
@@ -834,7 +835,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
834
835
|
static get emptyMeasureNoteType(): NoteType {
|
|
835
836
|
return SmoMeasure._emptyMeasureNoteType;
|
|
836
837
|
}
|
|
837
|
-
static timeSignatureNotes(timeSignature:
|
|
838
|
+
static timeSignatureNotes(timeSignature: SmoTimeSignature, clef: Clef) {
|
|
838
839
|
const pitch = SmoMeasure.defaultPitchForClef[clef];
|
|
839
840
|
const maxTicks = SmoMusic.timeSignatureToTicks(timeSignature.timeSignature);
|
|
840
841
|
const noteTick = 8192 / (timeSignature.beatDuration / 2);
|
|
@@ -869,7 +870,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
869
870
|
* @returns
|
|
870
871
|
*/
|
|
871
872
|
static getDefaultNotes(params: SmoMeasureParams): SmoNote[] {
|
|
872
|
-
return SmoMeasure.timeSignatureNotes(new
|
|
873
|
+
return SmoMeasure.timeSignatureNotes(new SmoTimeSignature(params.timeSignature), params.clef);
|
|
873
874
|
}
|
|
874
875
|
|
|
875
876
|
/**
|
|
@@ -888,7 +889,7 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
888
889
|
smoSerialize.serializedMerge(SmoMeasure.defaultAttributes, params, obj);
|
|
889
890
|
// Don't copy column-formatting options to new measure in new column
|
|
890
891
|
smoSerialize.serializedMerge(SmoMeasure.formattingOptions, SmoMeasure.defaults, obj);
|
|
891
|
-
obj.timeSignature = new
|
|
892
|
+
obj.timeSignature = new SmoTimeSignature(params.timeSignature);
|
|
892
893
|
// The measure expects to get concert KS in constructor and adjust for instrument. So do the
|
|
893
894
|
// opposite.
|
|
894
895
|
obj.keySignature = SmoMusic.vexKeySigWithOffset(obj.keySignature, -1 * obj.transposeIndex);
|
|
@@ -1019,7 +1020,6 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
1019
1020
|
}
|
|
1020
1021
|
}
|
|
1021
1022
|
const voices: SmoVoice[] = [];
|
|
1022
|
-
const tuplets: SmoTuplet[] = [];
|
|
1023
1023
|
for (var i = 0; i < this.voices.length; ++i) {
|
|
1024
1024
|
const voice = this.voices[i];
|
|
1025
1025
|
const newNotes: SmoNote[] = [];
|
|
@@ -1529,18 +1529,18 @@ export class SmoMeasure implements SmoMeasureParams, TickMappable {
|
|
|
1529
1529
|
return this.modifiers.filter((mm) => type === mm.attrs.type);
|
|
1530
1530
|
}
|
|
1531
1531
|
|
|
1532
|
-
setTempo(params:
|
|
1533
|
-
this.tempo = new
|
|
1532
|
+
setTempo(params: SmoTempoParams) {
|
|
1533
|
+
this.tempo = new SmoTempo(params);
|
|
1534
1534
|
}
|
|
1535
1535
|
/**
|
|
1536
|
-
* Set measure tempo to the default {@link
|
|
1536
|
+
* Set measure tempo to the default {@link SmoTempo}
|
|
1537
1537
|
*/
|
|
1538
1538
|
resetTempo() {
|
|
1539
|
-
this.tempo = new
|
|
1539
|
+
this.tempo = new SmoTempo(SmoTempo.defaults);
|
|
1540
1540
|
}
|
|
1541
1541
|
getTempo() {
|
|
1542
1542
|
if (typeof (this.tempo) === 'undefined') {
|
|
1543
|
-
this.tempo = new
|
|
1543
|
+
this.tempo = new SmoTempo(SmoTempo.defaults);
|
|
1544
1544
|
}
|
|
1545
1545
|
return this.tempo;
|
|
1546
1546
|
}
|