-
Notifications
You must be signed in to change notification settings - Fork 204
/
Copy pathMasterBar.ts
225 lines (194 loc) · 6.33 KB
/
MasterBar.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import { MidiUtils } from '@src/midi/MidiUtils';
import { Automation } from '@src/model/Automation';
import { Beat } from '@src/model/Beat';
import { Fermata } from '@src/model/Fermata';
import { KeySignature } from '@src/model/KeySignature';
import { KeySignatureType } from '@src/model/KeySignatureType';
import { RepeatGroup } from '@src/model/RepeatGroup';
import { Score } from '@src/model/Score';
import { Section } from '@src/model/Section';
import { TripletFeel } from '@src/model/TripletFeel';
import { Direction } from './Direction';
/**
* The MasterBar stores information about a bar which affects
* all tracks.
* @json
* @json_strict
*/
export class MasterBar {
public static readonly MaxAlternateEndings: number = 8;
/**
* Gets or sets the bitflag for the alternate endings. Each bit defines for which repeat counts
* the bar is played.
*/
public alternateEndings: number = 0;
/**
* Gets or sets the next masterbar in the song.
* @json_ignore
*/
public nextMasterBar: MasterBar | null = null;
/**
* Gets or sets the next masterbar in the song.
* @json_ignore
*/
public previousMasterBar: MasterBar | null = null;
/**
* Gets the zero based index of the masterbar.
* @json_ignore
*/
public index: number = 0;
/**
* Gets or sets the key signature used on all bars.
*/
public keySignature: KeySignature = KeySignature.C;
/**
* Gets or sets the type of key signature (major/minor)
*/
public keySignatureType: KeySignatureType = KeySignatureType.Major;
/**
* Gets or sets whether a double bar is shown for this masterbar.
*/
public isDoubleBar: boolean = false;
/**
* Gets or sets whether a repeat section starts on this masterbar.
*/
public isRepeatStart: boolean = false;
public get isRepeatEnd(): boolean {
return this.repeatCount > 0;
}
/**
* Gets or sets the number of repeats for the current repeat section.
*/
public repeatCount: number = 0;
/**
* Gets or sets the repeat group this bar belongs to.
* @json_ignore
*/
public repeatGroup!: RepeatGroup;
/**
* Gets or sets the time signature numerator.
*/
public timeSignatureNumerator: number = 4;
/**
* Gets or sets the time signature denominiator.
*/
public timeSignatureDenominator: number = 4;
/**
* Gets or sets whether this is bar has a common time signature.
*/
public timeSignatureCommon: boolean = false;
/**
* Gets or sets whether the bar indicates a free time playing.
*/
public isFreeTime: boolean = false;
/**
* Gets or sets the triplet feel that is valid for this bar.
*/
public tripletFeel: TripletFeel = TripletFeel.NoTripletFeel;
/**
* Gets or sets the new section information for this bar.
*/
public section: Section | null = null;
public get isSectionStart(): boolean {
return !!this.section;
}
/**
* Gets or sets the first tempo automation for this bar.
* @deprecated Use {@link tempoAutomations}.
*/
public get tempoAutomation(): Automation | null {
return this.tempoAutomations.length > 0 ? this.tempoAutomations[0] : null;
}
/**
* Gets or sets all tempo automation for this bar.
*/
public tempoAutomations: Automation[] = [];
/**
* Gets or sets the reference to the score this song belongs to.
* @json_ignore
*/
public score!: Score;
/**
* Gets or sets the fermatas for this bar. The key is the offset of the fermata in midi ticks.
* @json_add addFermata
*/
public fermata: Map<number, Fermata> | null = null;
/**
* The timeline position of the voice within the whole score. (unit: midi ticks)
*/
public start: number = 0;
/**
* Gets or sets a value indicating whether the master bar is an anacrusis (aka. pickup bar)
*/
public isAnacrusis: boolean = false;
/**
* Gets a percentual scale for the size of the bars when displayed in a multi-track layout.
*/
public displayScale: number = 1;
/**
* An absolute width of the bar to use when displaying in a multi-track layout.
*/
public displayWidth: number = -1;
/**
* The directions applied to this masterbar.
* @json_add addDirection
*/
public directions: Set<Direction> | null = null;
/**
* Calculates the time spent in this bar. (unit: midi ticks)
*/
public calculateDuration(respectAnacrusis: boolean = true): number {
if (this.isAnacrusis && respectAnacrusis) {
let duration: number = 0;
for (let track of this.score.tracks) {
for (let staff of track.staves) {
let barDuration: number =
this.index < staff.bars.length ? staff.bars[this.index].calculateDuration() : 0;
if (barDuration > duration) {
duration = barDuration;
}
}
}
return duration;
}
return this.timeSignatureNumerator * MidiUtils.valueToTicks(this.timeSignatureDenominator);
}
/**
* Adds a fermata to the masterbar.
* @param offset The offset of the fermata within the bar in midi ticks.
* @param fermata The fermata.
*/
public addFermata(offset: number, fermata: Fermata): void {
let fermataMap = this.fermata;
if (fermataMap === null) {
fermataMap = new Map<number, Fermata>();
this.fermata = fermataMap;
}
fermataMap.set(offset, fermata);
}
/**
* Adds a direction to the masterbar.
* @param direction The direction to add.
*/
public addDirection(direction:Direction):void {
if(this.directions == null){
this.directions = new Set<Direction>();
}
this.directions.add(direction);
}
/**
* Gets the fermata for a given beat.
* @param beat The beat to get the fermata for.
* @returns
*/
public getFermata(beat: Beat): Fermata | null {
const fermataMap = this.fermata;
if (fermataMap === null) {
return null;
}
if (fermataMap.has(beat.playbackStart)) {
return fermataMap.get(beat.playbackStart)!;
}
return null;
}
}