k-l-lambda commited on
Commit
bb93f99
·
1 Parent(s): 76a2ad7

removed .old file.

Browse files
Files changed (1) hide show
  1. backend/scoreMaker.ts.old +0 -665
backend/scoreMaker.ts.old DELETED
@@ -1,665 +0,0 @@
1
- //
2
- // OBSOLETE code, only for archive
3
- //
4
-
5
- import _ from "lodash";
6
- import {DOMParser, XMLSerializer} from "xmldom";
7
- import {MusicNotation} from "@k-l-lambda/music-widgets";
8
- import {MIDI} from "@k-l-lambda/music-widgets";
9
- import {Readable} from "stream";
10
-
11
- import npmPackage from "../package.json";
12
- import {xml2ly, engraveSvg, LilyProcessOptions} from "./lilyCommands";
13
- import {LilyDocument, replaceSourceToken, LilyTerms} from "../inc/lilyParser";
14
- import * as staffSvg from "../inc/staffSvg";
15
- import {SingleLock} from "../inc/mutex";
16
- import {PitchContextTable} from "../inc/pitchContext";
17
- import * as LilyNotation from "../inc/lilyNotation";
18
- import {svgToPng} from "./canvas";
19
- import LogRecorder from "../inc/logRecorder";
20
- import ScoreJSON, {NoteLinking} from "../inc/scoreJSON";
21
- import {LilyDocumentAttribute, LilyDocumentAttributeReadOnly} from "../inc/lilyParser/lilyDocument";
22
- import {Block} from "../inc/lilyParser/lilyTerms";
23
-
24
-
25
-
26
- interface GrammarParser {
27
- parse (source: string): any;
28
- };
29
-
30
-
31
- const markupLily = (source: string, markup: string, lilyParser: GrammarParser): string => {
32
- const docMarkup = new LilyDocument(lilyParser.parse(markup));
33
- const docSource = new LilyDocument(lilyParser.parse(source));
34
-
35
- // copy attributes
36
- const attrS = docSource.globalAttributes() as LilyDocumentAttribute;
37
- const attrM = docMarkup.globalAttributes({readonly: true}) as LilyDocumentAttributeReadOnly;
38
-
39
- [
40
- "staffSize", "paperWidth", "paperHeight",
41
- "topMargin", "bottomMargin", "leftMargin", "rightMargin",
42
- "systemSpacing", "topMarkupSpacing", "raggedLast", "raggedBottom", "raggedLastBottom",
43
- "printPageNumber",
44
- ].forEach(field => {
45
- if (attrM[field] !== undefined) {
46
- if (typeof attrS[field].value === "object" && attrS[field].value && (attrS[field].value as any).set)
47
- (attrS[field].value as any).set(attrM[field]);
48
- else
49
- attrS[field].value = attrM[field];
50
- }
51
- });
52
-
53
- // execute commands list
54
- const commands = docMarkup.root.getField("LotusCommands");
55
- const cmdList = commands && commands.value && commands.value.args && commands.value.args[0].body;
56
- if (cmdList && Array.isArray(cmdList)) {
57
- for (const command of cmdList) {
58
- if (command.exp && docSource[command.exp])
59
- docSource[command.exp]();
60
- else
61
- console.warn("unexpected markup command:", command);
62
- }
63
- }
64
-
65
- // copy LotusOption assignments
66
- const assignments = docMarkup.root.entries.filter(term => term instanceof LilyTerms.Assignment && /^LotusOption\..+/.test(term.key.toString()));
67
- assignments.forEach(assignment => docSource.root.sections.push(assignment.clone()));
68
-
69
- return docSource.toString();
70
- };
71
-
72
-
73
- const xmlBufferToLy = async (xml: Buffer, options: LilyProcessOptions = {}): Promise<string> => {
74
- const bom = (xml[0] << 8 | xml[1]);
75
- const utf16 = bom === 0xfffe;
76
- const content = xml.toString(utf16 ? "utf16le" : "utf8");
77
-
78
- return await xml2ly(content, {replaceEncoding: utf16, ...options});
79
- };
80
-
81
-
82
- const unescapeStringExp = exp => exp && exp.toString();
83
-
84
-
85
- const makeScoreV1 = async (source: string, lilyParser: GrammarParser, {midi, logger}: {midi?: MIDI.MidiData, logger?: LogRecorder} = {}): Promise<ScoreJSON> => {
86
- const t0 = Date.now();
87
-
88
- const engraving = await engraveSvg(source);
89
-
90
- logger.append("scoreMaker.profile.engraving", {cost: Date.now() - t0});
91
- logger.append("lilypond.log", engraving.logs);
92
-
93
- const lilyDocument = new LilyDocument(lilyParser.parse(source));
94
- const {doc, hashTable} = staffSvg.createSheetDocumentFromSvgs(engraving.svgs, source, lilyDocument, {logger, DOMParser});
95
-
96
- const sheetNotation = staffSvg.StaffNotation.parseNotationFromSheetDocument(doc, {logger});
97
-
98
- const attributes = lilyDocument.globalAttributes({readonly: true});
99
-
100
- const meta = {
101
- title: unescapeStringExp(attributes.title),
102
- composer: unescapeStringExp(attributes.composer),
103
- pageSize: doc.pageSize,
104
- pageCount: doc.pages.length,
105
- staffSize: attributes.staffSize as number,
106
- };
107
-
108
- midi = midi || engraving.midi;
109
- const midiNotation = MusicNotation.Notation.parseMidi(midi);
110
-
111
- const t5 = Date.now();
112
-
113
- const matcher = await staffSvg.StaffNotation.matchNotations(midiNotation, sheetNotation);
114
-
115
- logger.append("scoreMaker.profile.matching", {cost: Date.now() - t5});
116
-
117
- if (logger) {
118
- const cis = new Set(Array(matcher.criterion.notes.length).keys());
119
- matcher.path.forEach(ci => cis.delete(ci));
120
-
121
- const omitC = cis.size;
122
- const omitS = matcher.path.filter(ci => ci < 0).length;
123
-
124
- const coverage = ((matcher.criterion.notes.length - omitC) / matcher.criterion.notes.length)
125
- * ((matcher.sample.notes.length - omitS) / matcher.sample.notes.length);
126
-
127
- logger.append("makeScore.match", {coverage, omitC, omitS, path: matcher.path});
128
- }
129
-
130
- const matchedIds: Set<string> = new Set();
131
- midiNotation.notes.forEach(note => note.ids && note.ids.forEach(id => matchedIds.add(id)));
132
-
133
- doc.updateMatchedTokens(matchedIds);
134
-
135
- const pitchContextGroup = PitchContextTable.createPitchContextGroup(sheetNotation.pitchContexts, midiNotation);
136
-
137
- const noteLinkings = midiNotation.notes.map(note => _.pick(note, ["ids", "staffTrack", "contextIndex"]) as NoteLinking);
138
-
139
- logger.append("scoreMaker.profile.full", {cost: Date.now() - t0});
140
-
141
- return {
142
- meta,
143
- doc,
144
- midi,
145
- hashTable,
146
- noteLinkings,
147
- pitchContextGroup,
148
- };
149
- };
150
-
151
-
152
- interface IncompleteScoreJSON {
153
- meta?: any,
154
- doc?: any;
155
- hashTable?: {[key: string]: any};
156
- midi?: MIDI.MidiData;
157
- noteLinkings?: NoteLinking;
158
- pitchContextGroup?: any;
159
- };
160
-
161
-
162
- interface SheetNotationResult extends IncompleteScoreJSON {
163
- midiNotation: MusicNotation.NotationData;
164
- sheetNotation: staffSvg.StaffNotation.SheetNotation;
165
- lilyDocument: LilyDocument;
166
- bakingImages?: Readable[];
167
- };
168
-
169
-
170
- const makeScoreV2 = async (source: string, lilyParser: GrammarParser, {midi, logger}: {midi?: MIDI.MidiData, logger?: LogRecorder} = {}): Promise<ScoreJSON | IncompleteScoreJSON> => {
171
- let midiNotation = null;
172
-
173
- const pages = [];
174
- const hashTable = {};
175
-
176
- const t0 = Date.now();
177
-
178
- const attrGen = new SingleLock<LilyDocumentAttributeReadOnly>(true);
179
-
180
- const engraving = await engraveSvg(source, {
181
- // do some work during lilypond process running to save time
182
- onProcStart: () => {
183
- //console.log("tp.0:", Date.now() - t0);
184
- const lilyDocument = new LilyDocument(lilyParser.parse(source));
185
- attrGen.release(lilyDocument.globalAttributes({readonly: true}) as LilyDocumentAttributeReadOnly);
186
- //console.log("tp.1:", Date.now() - t0);
187
- },
188
- onMidiRead: midi_ => {
189
- //console.log("tm.0:", Date.now() - t0);
190
- if (!midi) {
191
- midi = midi_;
192
- midiNotation = midi && MusicNotation.Notation.parseMidi(midi);
193
- }
194
- //console.log("tm.1:", Date.now() - t0);
195
- },
196
- onSvgRead: async svg => {
197
- //console.log("ts.0:", Date.now() - t0);
198
- const attributes = await attrGen.wait();
199
- const page = staffSvg.parseSvgPage(svg, source, {DOMParser, logger, attributes});
200
- pages.push(page.structure);
201
- Object.assign(hashTable, page.hashTable);
202
- //console.log("ts.1:", Date.now() - t0);
203
- },
204
- });
205
-
206
- //console.log("t2:", Date.now() - t0);
207
-
208
- logger.append("scoreMaker.profile.engraving", {cost: Date.now() - t0});
209
- logger.append("lilypond.log", engraving.logs);
210
-
211
- const doc = new staffSvg.SheetDocument({pages});
212
-
213
- //console.log("t3:", Date.now() - t0);
214
-
215
- const attributes = await attrGen.wait();
216
- const meta = {
217
- title: unescapeStringExp(attributes.title),
218
- composer: unescapeStringExp(attributes.composer),
219
- pageSize: doc.pageSize,
220
- pageCount: doc.pages.length,
221
- staffSize: attributes.staffSize,
222
- };
223
-
224
- if (!midiNotation) {
225
- console.warn("Neither lilypond or external arguments did not offer MIDI data, score maker finish incompletely.");
226
- return {
227
- meta,
228
- doc,
229
- midi,
230
- hashTable,
231
- };
232
- }
233
-
234
- //console.log("t4:", Date.now() - t0);
235
-
236
- const sheetNotation = staffSvg.StaffNotation.parseNotationFromSheetDocument(doc, {logger});
237
-
238
- //console.log("t5:", Date.now() - t0);
239
- const t5 = Date.now();
240
-
241
- const matcher = await staffSvg.StaffNotation.matchNotations(midiNotation, sheetNotation);
242
-
243
- //console.log("t6:", Date.now() - t0);
244
- logger.append("scoreMaker.profile.matching", {cost: Date.now() - t5});
245
-
246
- if (logger) {
247
- const cis = new Set(Array(matcher.criterion.notes.length).keys());
248
- matcher.path.forEach(ci => cis.delete(ci));
249
-
250
- const omitC = cis.size;
251
- const omitS = matcher.path.filter(ci => ci < 0).length;
252
-
253
- const coverage = ((matcher.criterion.notes.length - omitC) / matcher.criterion.notes.length)
254
- * ((matcher.sample.notes.length - omitS) / matcher.sample.notes.length);
255
-
256
- logger.append("markScore.match", {coverage, omitC, omitS, path: matcher.path});
257
- }
258
-
259
- //console.log("t7:", Date.now() - t0);
260
-
261
- const matchedIds: Set<string> = new Set();
262
- midiNotation.notes.forEach(note => note.ids && note.ids.forEach(id => matchedIds.add(id)));
263
-
264
- //console.log("t8:", Date.now() - t0);
265
-
266
- doc.updateMatchedTokens(matchedIds);
267
-
268
- //console.log("t9:", Date.now() - t0);
269
-
270
- const pitchContextGroup = PitchContextTable.createPitchContextGroup(sheetNotation.pitchContexts, midiNotation);
271
-
272
- //console.log("t10:", Date.now() - t0);
273
-
274
- const noteLinkings = midiNotation.notes.map(note => _.pick(note, ["ids", "staffTrack", "contextIndex"]));
275
-
276
- //console.log("t11:", Date.now() - t0);
277
- logger.append("scoreMaker.profile.full", {cost: Date.now() - t0});
278
-
279
- return {
280
- meta,
281
- doc,
282
- midi,
283
- hashTable,
284
- noteLinkings,
285
- pitchContextGroup,
286
- };
287
- };
288
-
289
-
290
- const makeSheetNotation = async (source: string, lilyParser: GrammarParser, {withNotation = true, logger, lilyDocument, includeFolders, baking}: {
291
- withNotation?: boolean,
292
- logger?: LogRecorder,
293
- lilyDocument?: LilyDocument,
294
- includeFolders?: string[],
295
- baking?: boolean,
296
- } = {}): Promise<SheetNotationResult> => {
297
- let midi = null;
298
- let midiNotation = null;
299
-
300
- const pages = [];
301
- const hashTable = {};
302
- const bakingImages = [];
303
-
304
- const t0 = Date.now();
305
-
306
- type ParserArguments = {attributes: LilyDocumentAttributeReadOnly, tieLocations: {[key: string]: boolean}};
307
-
308
- const argsGen = new SingleLock<ParserArguments>(true);
309
-
310
- const engraving = await engraveSvg(source, {
311
- includeFolders,
312
- // do some work during lilypond process running to save time
313
- onProcStart: () => {
314
- //console.log("tp.0:", Date.now() - t0);
315
- if (!lilyDocument) {
316
- lilyDocument = new LilyDocument(lilyParser.parse(source));
317
- lilyDocument.interpret();
318
- }
319
-
320
- const attributes = lilyDocument.globalAttributes({readonly: true}) as LilyDocumentAttributeReadOnly;
321
-
322
- //const tieLocations = lilyDocument.getTiedNoteLocations(text)
323
- const tieLocations = lilyDocument.getTiedNoteLocations2()
324
- .reduce((table, loc) => ((table[`${loc[0]}:${loc[1]}`] = true), table), {});
325
-
326
- argsGen.release({attributes, tieLocations});
327
- //console.log("tp.1:", Date.now() - t0);
328
- },
329
- onMidiRead: withNotation && (midi_ => {
330
- //console.log("tm.0:", Date.now() - t0);
331
- midi = midi_;
332
- midiNotation = midi && MusicNotation.Notation.parseMidi(midi);
333
- //console.log("tm.1:", Date.now() - t0);
334
- }),
335
- onSvgRead: async (index, svg) => {
336
- //console.log("ts.0:", Date.now() - t0);
337
- const args = await argsGen.wait();
338
- const page = staffSvg.parseSvgPage(svg, source, {DOMParser, logger, ...args});
339
- pages[index] = page.structure;
340
- Object.assign(hashTable, page.hashTable);
341
- //console.log("ts.1:", Date.now() - t0);
342
- },
343
- });
344
-
345
- logger.append("scoreMaker.profile.engraving", {cost: Date.now() - t0});
346
- logger.append("lilypond.log", engraving.logs);
347
-
348
- const doc = new staffSvg.SheetDocument({pages});
349
-
350
- staffSvg.postProcessSheetDocument(doc, lilyDocument);
351
-
352
- if (baking) {
353
- await Promise.all(engraving.svgs.map(async (svg, index) => {
354
- const svgText = staffSvg.turnRawSvgWithSheetDocument(svg, pages[index], {DOMParser, XMLSerializer});
355
- bakingImages[index] = await svgToPng(Buffer.from(svgText));
356
- }));
357
- }
358
-
359
- const {attributes} = await argsGen.wait();
360
- const meta = {
361
- title: unescapeStringExp(attributes.title),
362
- composer: unescapeStringExp(attributes.composer),
363
- pageSize: doc.pageSize,
364
- pageCount: doc.pages.length,
365
- staffSize: attributes.staffSize,
366
- };
367
-
368
- const sheetNotation = staffSvg.StaffNotation.parseNotationFromSheetDocument(doc, {logger});
369
-
370
- // correct notation time by location-tick table from lily document
371
- const tickTable = lilyDocument.getLocationTickTable();
372
- staffSvg.StaffNotation.assignTickByLocationTable(sheetNotation, tickTable);
373
-
374
- return {
375
- midi,
376
- bakingImages: baking ? bakingImages : null,
377
- midiNotation,
378
- sheetNotation,
379
- meta,
380
- doc,
381
- hashTable,
382
- lilyDocument,
383
- };
384
- };
385
-
386
-
387
- const makeScoreV3 = async (source: string, lilyParser: GrammarParser, {midi, logger, unfoldRepeats = false, includeFolders}: {
388
- midi?: MIDI.MidiData,
389
- logger?: LogRecorder,
390
- unfoldRepeats?: boolean,
391
- includeFolders?: string[],
392
- } = {}): Promise<ScoreJSON | IncompleteScoreJSON> => {
393
- const t0 = Date.now();
394
-
395
- let lilyDocument = null;
396
- let unfoldSource = null;
397
-
398
- if (unfoldRepeats) {
399
- lilyDocument = new LilyDocument(lilyParser.parse(source));
400
- lilyDocument.interpret();
401
- if (lilyDocument.containsRepeat()) {
402
- lilyDocument.unfoldRepeats();
403
- unfoldSource = lilyDocument.toString();
404
-
405
- // keep 2 version lilypond source note href uniform
406
- source = replaceSourceToken(unfoldSource, "\\unfoldRepeats");
407
- }
408
- }
409
-
410
- const foldData = await makeSheetNotation(source, lilyParser, {logger, lilyDocument, withNotation: !midi && !unfoldSource, includeFolders});
411
- const {meta, doc, hashTable} = foldData;
412
-
413
- lilyDocument = lilyDocument || foldData.lilyDocument;
414
- let midiNotation = foldData.midiNotation;
415
- let sheetNotation = foldData.sheetNotation;
416
-
417
- if (midi)
418
- midiNotation = MusicNotation.Notation.parseMidi(midi);
419
-
420
- if (unfoldSource) {
421
- const unfoldData = await makeSheetNotation(unfoldSource, lilyParser, {logger, lilyDocument, withNotation: !midi, includeFolders});
422
-
423
- midi = midi || unfoldData.midi;
424
- midiNotation = unfoldData.midiNotation;
425
- sheetNotation = unfoldData.sheetNotation;
426
- }
427
-
428
- midi = midi || foldData.midi;
429
- if (!midi || !sheetNotation) {
430
- if (!midi)
431
- console.warn("Neither lilypond or external arguments did not offer MIDI data, score maker finished incompletely.");
432
-
433
- if (!sheetNotation)
434
- console.warn("sheetNotation parsing failed, score maker finished incompletely.");
435
-
436
- return {
437
- meta,
438
- doc,
439
- midi,
440
- hashTable,
441
- };
442
- }
443
-
444
- const t5 = Date.now();
445
-
446
- const matcher = await staffSvg.StaffNotation.matchNotations(midiNotation, sheetNotation);
447
-
448
- logger.append("scoreMaker.profile.matching", {cost: Date.now() - t5});
449
-
450
- if (logger && logger.enabled) {
451
- const cis = new Set(Array(matcher.criterion.notes.length).keys());
452
- matcher.path.forEach(ci => cis.delete(ci));
453
-
454
- const omitC = cis.size;
455
- const omitS = matcher.path.filter(ci => ci < 0).length;
456
-
457
- const coverage = ((matcher.criterion.notes.length - omitC) / matcher.criterion.notes.length)
458
- * ((matcher.sample.notes.length - omitS) / matcher.sample.notes.length);
459
-
460
- logger.append("makeScore.match", {coverage, omitC, omitS, path: matcher.path});
461
- }
462
-
463
- const matchedIds: Set<string> = new Set();
464
- midiNotation.notes.forEach(note => note.ids && note.ids.forEach(id => matchedIds.add(id)));
465
-
466
- doc.updateMatchedTokens(matchedIds);
467
-
468
- const pitchContextGroup = PitchContextTable.createPitchContextGroup(sheetNotation.pitchContexts, midiNotation);
469
-
470
- const noteLinkings = midiNotation.notes.map(note => _.pick(note, ["ids", "staffTrack", "contextIndex"]) as NoteLinking);
471
-
472
- logger.append("scoreMaker.profile.full", {cost: Date.now() - t0});
473
-
474
- return {
475
- meta,
476
- doc,
477
- midi,
478
- hashTable,
479
- noteLinkings,
480
- pitchContextGroup,
481
- };
482
- };
483
-
484
-
485
- const makeScoreV4 = async (source: string, lilyParser: GrammarParser, {midi, logger, unfoldRepeats = false, baking = false, includeFolders}: {
486
- midi?: MIDI.MidiData,
487
- logger?: LogRecorder,
488
- unfoldRepeats?: boolean,
489
- includeFolders?: string[],
490
- baking?: boolean,
491
- } = {}): Promise<{
492
- bakingImages?: Readable[],
493
- score: ScoreJSON | IncompleteScoreJSON,
494
- }> => {
495
- const t0 = Date.now();
496
-
497
- let lilyDocument = null;
498
- let unfoldSource = null;
499
-
500
- if (unfoldRepeats) {
501
- lilyDocument = new LilyDocument(lilyParser.parse(source));
502
- lilyDocument.interpret();
503
- if (lilyDocument.containsRepeat()) {
504
- lilyDocument.unfoldRepeats();
505
- unfoldSource = lilyDocument.toString();
506
-
507
- // keep 2 version lilypond source note href uniform
508
- source = replaceSourceToken(unfoldSource, "\\unfoldRepeats");
509
- }
510
- }
511
-
512
- const foldData = await makeSheetNotation(source, lilyParser, {logger, lilyDocument, withNotation: !midi && !unfoldSource, includeFolders, baking});
513
- const {meta, doc, hashTable, bakingImages} = foldData;
514
-
515
- lilyDocument = lilyDocument || foldData.lilyDocument;
516
- //let sheetNotation = foldData.sheetNotation;
517
-
518
- const matchingMidi = midi || foldData.midi;
519
-
520
- if (unfoldSource) {
521
- const unfoldData = await makeSheetNotation(unfoldSource, lilyParser, {logger, lilyDocument, withNotation: !midi, includeFolders});
522
-
523
- midi = midi || unfoldData.midi;
524
- //sheetNotation = unfoldData.sheetNotation;
525
- }
526
-
527
- midi = midi || foldData.midi;
528
- const lilyNotation = lilyDocument.interpret().getNotation();
529
-
530
- if (!midi || !lilyNotation) {
531
- if (!midi)
532
- console.warn("Neither lilypond or external arguments did not offer MIDI data, score maker finished incompletely.");
533
-
534
- if (!lilyNotation)
535
- console.warn("sheetNotation parsing failed, score maker finished incompletely.");
536
-
537
- return {
538
- score: {
539
- version: npmPackage.version,
540
- meta,
541
- doc,
542
- midi,
543
- hashTable,
544
- },
545
- };
546
- }
547
-
548
- const t5 = Date.now();
549
-
550
- const matcher = await LilyNotation.matchWithMIDI(lilyNotation, matchingMidi);
551
-
552
- logger.append("scoreMaker.profile.matching", {cost: Date.now() - t5});
553
-
554
- if (logger && logger.enabled) {
555
- const cis = new Set(Array(matcher.criterion.notes.length).keys());
556
- matcher.path.forEach(ci => cis.delete(ci));
557
-
558
- const omitC = cis.size;
559
- const omitS = matcher.path.filter(ci => ci < 0).length;
560
-
561
- const coverage = ((matcher.criterion.notes.length - omitC) / matcher.criterion.notes.length)
562
- * ((matcher.sample.notes.length - omitS) / matcher.sample.notes.length);
563
-
564
- logger.append("makeScore.match", {coverage, omitC, omitS, path: matcher.path});
565
- }
566
-
567
- const midiNotation = matcher.sample;
568
-
569
- const matchedIds: Set<string> = new Set();
570
- midiNotation.notes.forEach(note => note.ids && note.ids.forEach(id => matchedIds.add(id)));
571
-
572
- doc.updateMatchedTokens(matchedIds);
573
-
574
- if (baking)
575
- doc.pruneForBakingMode();
576
-
577
- const pitchContextGroup = PitchContextTable.createPitchContextGroup(
578
- lilyNotation.pitchContextGroup.map(table => table.items.map(item => item.context)), midiNotation);
579
-
580
- const noteLinkings = midiNotation.notes.map(note => _.pick(note, ["ids", "staffTrack", "contextIndex"]) as NoteLinking);
581
-
582
- logger.append("scoreMaker.profile.full", {cost: Date.now() - t0});
583
-
584
- return {
585
- bakingImages,
586
- score: {
587
- version: npmPackage.version,
588
- meta,
589
- doc,
590
- midi,
591
- hashTable: !baking ? hashTable : null,
592
- noteLinkings,
593
- pitchContextGroup,
594
- },
595
- };
596
- };
597
-
598
-
599
- void makeScoreV1;
600
- void makeScoreV2;
601
- void makeScoreV3;
602
- const makeScore = makeScoreV4;
603
-
604
-
605
- const makeMIDI = async (source: string, lilyParser: GrammarParser, {unfoldRepeats = false, fixNestedRepeat = false, includeFolders = undefined} = {}): Promise<MIDI.MidiData> => {
606
- const lilyDocument = new LilyDocument(lilyParser.parse(source));
607
-
608
- if (fixNestedRepeat)
609
- lilyDocument.fixNestedRepeat();
610
-
611
- if (unfoldRepeats)
612
- lilyDocument.unfoldRepeats();
613
-
614
- const score = lilyDocument.root.getBlock("score");
615
- if (score) {
616
- // remove layout block to save time
617
- score.body = score.body.filter(term => !(term instanceof LilyTerms.Block && term.head === "\\layout"));
618
-
619
- // remove invalid tempo
620
- const midi: any = score.body.find(term => term instanceof LilyTerms.Block && term.head === "\\midi");
621
- if (midi)
622
- midi.body = midi.body.filter(term => !(term instanceof LilyTerms.Tempo && term.beatsPerMinute > 200));
623
- }
624
-
625
- const markupSource = lilyDocument.toString();
626
- //console.log("markupSource:", markupSource);
627
-
628
- return new Promise((resolve, reject) => engraveSvg(markupSource, {
629
- includeFolders,
630
- onMidiRead: resolve,
631
- }).catch(reject));
632
- };
633
-
634
-
635
- const makeArticulatedMIDI = async (source: string, lilyParser: GrammarParser, {ignoreRepeats = true, includeFolders = undefined} = {}): Promise<MIDI.MidiData> => {
636
- const lilyDocument = new LilyDocument(lilyParser.parse(source));
637
-
638
- if (ignoreRepeats)
639
- lilyDocument.removeRepeats();
640
-
641
- lilyDocument.articulateMIDIOutput();
642
-
643
- // remove layout block to save time
644
- lilyDocument.root.sections = lilyDocument.root.sections.filter(section => !(section instanceof Block)
645
- || !(section.head === "\\score")
646
- || section.isMIDIDedicated);
647
-
648
- const markupSource = lilyDocument.toString();
649
- //console.log("markupSource:", markupSource);
650
-
651
- return new Promise((resolve, reject) => engraveSvg(markupSource, {
652
- includeFolders,
653
- onMidiRead: resolve,
654
- }).catch(reject));
655
- };
656
-
657
-
658
-
659
- export {
660
- markupLily,
661
- xmlBufferToLy,
662
- makeScore,
663
- makeMIDI,
664
- makeArticulatedMIDI,
665
- };