-
Notifications
You must be signed in to change notification settings - Fork 206
/
Copy pathPartConfiguration.ts
142 lines (116 loc) · 5.54 KB
/
PartConfiguration.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
import { GpBinaryHelpers } from '@src/importer/Gp3To5Importer';
import { ByteBuffer } from '@src/io/ByteBuffer';
import { IOHelper } from '@src/io/IOHelper';
import { Score } from '@src/model/Score';
import { Track } from '@src/model/Track';
// PartConfiguration File Format Notes.
// Based off Guitar Pro 8
// The file contains a serialized "Score View Collection" filled like this:
// There is always 1 ScoreView holding a TrackViewGroup for each Track contained in the file. This is the multi-track layout.
// Additionally there is 1 ScoreView individually for each track with only 1 TrackViewGroup of this Group.
// The Guitar Pro UI seem to update both the multi-track and the single-track layouts when changin the displayed staves.
// But technically it would support showing tracks different in multi-track.
// File:
// int32 (big endian) | Number of Score Views
// ScoreView[] | The individual score views
// int32 (big endian) | The index to the currently active view
// ScoreView:
// 1 byte (boolean) | "Multi Rest" - Whether multiple bars with rests should be combined (Bar > Multi Rest option)
// int32 (big endian) | Number of following tems
// TrackViewGroup[] | The individual track view groups
// TrackViewGroup:
// 1 byte | Track View Group Type Bitflag
// | 0th bit: showStandardNotation
// | 1th bit: showTablature
// | 2nd bit: showSlash
// | 3rd bit: numberedNotation (GP8 feature - jiǎnpǔ aka Chinese Number Notation)
// | if no bits set -> activate standard notation
//
export class ScoreView {
public isMultiRest: boolean = false;
public trackViewGroups: TrackViewGroup[] = [];
}
export class TrackViewGroup {
public showSlash: boolean = false;
public showStandardNotation: boolean = false;
public showTablature: boolean = false;
}
export class PartConfiguration {
public scoreViews: ScoreView[] = [];
public apply(score: Score): void {
// for now we only look at the first score view which seem to hold
// the config for all tracks.
if(this.scoreViews.length > 0) {
let trackIndex = 0;
for (let trackConfig of this.scoreViews[0].trackViewGroups) {
if (trackIndex < score.tracks.length) {
const track: Track = score.tracks[trackIndex];
for(const staff of track.staves) {
staff.showTablature = trackConfig.showTablature;
staff.showStandardNotation = trackConfig.showStandardNotation;
}
}
trackIndex++;
}
}
}
public constructor(partConfigurationData: Uint8Array) {
let readable: ByteBuffer = ByteBuffer.fromBuffer(partConfigurationData);
const scoreViewCount: number = IOHelper.readInt32BE(readable);
for (let i: number = 0; i < scoreViewCount; i++) {
const scoreView = new ScoreView();
this.scoreViews.push(scoreView);
scoreView.isMultiRest = GpBinaryHelpers.gpReadBool(readable);
const trackViewGroupCount: number = IOHelper.readInt32BE(readable);
for (let j: number = 0; j < trackViewGroupCount; j++) {
let flags: number = readable.readByte();
// enable at least standard notation
if (flags === 0) {
flags = 1;
}
let trackConfiguration = new TrackViewGroup();
trackConfiguration.showStandardNotation = (flags & 0x01) !== 0;
trackConfiguration.showTablature = (flags & 0x02) !== 0;
trackConfiguration.showSlash = (flags & 0x04) !== 0;
scoreView.trackViewGroups.push(trackConfiguration);
}
}
}
public static writeForScore(score: Score): Uint8Array {
const writer = ByteBuffer.withCapacity(128);
const scoreViews: ScoreView[] = [
new ScoreView() // Multi Track Score View
];
for (const track of score.tracks) {
const trackConfiguration = new TrackViewGroup();
// NOTE: unclear how multi staff settings are meant in this format
// in the Guitar Pro UI there is no individual staff config
trackConfiguration.showStandardNotation = track.staves[0].showStandardNotation;
trackConfiguration.showTablature = track.staves[0].showTablature;
scoreViews[0].trackViewGroups.push(trackConfiguration);
const singleTrackScoreView = new ScoreView();
singleTrackScoreView.trackViewGroups.push(trackConfiguration);
scoreViews.push(singleTrackScoreView);
}
IOHelper.writeInt32BE(writer, scoreViews.length);
for (const part of scoreViews) {
writer.writeByte(part.isMultiRest ? 1 : 0);
IOHelper.writeInt32BE(writer, part.trackViewGroups.length);
for(const track of part.trackViewGroups) {
let flags = 0;
if(track.showStandardNotation) {
flags = flags | 0x01;
}
if(track.showTablature) {
flags = flags | 0x02;
}
if(track.showSlash) {
flags = flags | 0x04;
}
writer.writeByte(flags);
}
}
IOHelper.writeInt32BE(writer, 1 /* First Single Track Layout */);
return writer.toArray();
}
}