MusicSheetReader.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. "use strict";
  2. var MusicSheet_1 = require("../MusicSheet");
  3. var SourceMeasure_1 = require("../VoiceData/SourceMeasure");
  4. var fraction_1 = require("../../Common/DataObjects/fraction");
  5. var InstrumentReader_1 = require("./InstrumentReader");
  6. var Instrument_1 = require("../Instrument");
  7. var ITextTranslation_1 = require("../Interfaces/ITextTranslation");
  8. var Exceptions_1 = require("../Exceptions");
  9. var Logging_1 = require("../../Common/Logging");
  10. var RhythmInstruction_1 = require("../VoiceData/Instructions/RhythmInstruction");
  11. var RhythmInstruction_2 = require("../VoiceData/Instructions/RhythmInstruction");
  12. var SourceStaffEntry_1 = require("../VoiceData/SourceStaffEntry");
  13. var InstrumentalGroup_1 = require("../InstrumentalGroup");
  14. var SubInstrument_1 = require("../SubInstrument");
  15. var ClefInstruction_1 = require("../VoiceData/Instructions/ClefInstruction");
  16. var Label_1 = require("../Label");
  17. var MusicSheetReader /*implements IMusicSheetReader*/ = (function () {
  18. function MusicSheetReader /*implements IMusicSheetReader*/() {
  19. this.completeNumberOfStaves = 0;
  20. }
  21. Object.defineProperty(MusicSheetReader /*implements IMusicSheetReader*/.prototype, "CompleteNumberOfStaves", {
  22. get: function () {
  23. return this.completeNumberOfStaves;
  24. },
  25. enumerable: true,
  26. configurable: true
  27. });
  28. MusicSheetReader /*implements IMusicSheetReader*/.doCalculationsAfterDurationHasBeenSet = function (instrumentReaders) {
  29. for (var _i = 0, instrumentReaders_1 = instrumentReaders; _i < instrumentReaders_1.length; _i++) {
  30. var instrumentReader = instrumentReaders_1[_i];
  31. instrumentReader.doCalculationsAfterDurationHasBeenSet();
  32. }
  33. };
  34. MusicSheetReader /*implements IMusicSheetReader*/.prototype.createMusicSheet = function (root, path) {
  35. try {
  36. return this._createMusicSheet(root, path);
  37. }
  38. catch (e) {
  39. Logging_1.Logging.log("MusicSheetReader.CreateMusicSheet", e);
  40. }
  41. };
  42. MusicSheetReader /*implements IMusicSheetReader*/.prototype._removeFromArray = function (list, elem) {
  43. var i = list.indexOf(elem);
  44. if (i !== -1) {
  45. list.splice(i, 1);
  46. }
  47. };
  48. // Trim from a string also newlines
  49. MusicSheetReader /*implements IMusicSheetReader*/.prototype.trimString = function (str) {
  50. return str.replace(/^\s+|\s+$/g, "");
  51. };
  52. MusicSheetReader /*implements IMusicSheetReader*/.prototype._lastElement = function (list) {
  53. return list[list.length - 1];
  54. };
  55. //public SetPhonicScoreInterface(phonicScoreInterface: IPhonicScoreInterface): void {
  56. // this.phonicScoreInterface = phonicScoreInterface;
  57. //}
  58. //public ReadMusicSheetParameters(sheetObject: MusicSheetParameterObject, root: IXmlElement, path: string): MusicSheetParameterObject {
  59. // this.musicSheet = new MusicSheet();
  60. // if (root !== undefined) {
  61. // this.pushSheetLabels(root, path);
  62. // if (this.musicSheet.Title !== undefined) {
  63. // sheetObject.Title = this.musicSheet.Title.text;
  64. // }
  65. // if (this.musicSheet.Composer !== undefined) {
  66. // sheetObject.Composer = this.musicSheet.Composer.text;
  67. // }
  68. // if (this.musicSheet.Lyricist !== undefined) {
  69. // sheetObject.Lyricist = this.musicSheet.Lyricist.text;
  70. // }
  71. // let partlistNode: IXmlElement = root.element("part-list");
  72. // let partList: IXmlElement[] = partlistNode.elements();
  73. // this.createInstrumentGroups(partList);
  74. // for (let idx: number = 0, len: number = this.musicSheet.Instruments.length; idx < len; ++idx) {
  75. // let instr: Instrument = this.musicSheet.Instruments[idx];
  76. // sheetObject.InstrumentList.push(__init(new MusicSheetParameterObject.LibrarySheetInstrument(), { name: instr.name }));
  77. // }
  78. // }
  79. // return sheetObject;
  80. //}
  81. MusicSheetReader /*implements IMusicSheetReader*/.prototype._createMusicSheet = function (root, path) {
  82. var instrumentReaders = [];
  83. var sourceMeasureCounter = 0;
  84. this.musicSheet = new MusicSheet_1.MusicSheet();
  85. this.musicSheet.Path = path;
  86. if (root === undefined) {
  87. throw new Exceptions_1.MusicSheetReadingException("Undefined root element");
  88. }
  89. this.pushSheetLabels(root, path);
  90. var partlistNode = root.element("part-list");
  91. if (partlistNode === undefined) {
  92. throw new Exceptions_1.MusicSheetReadingException("Undefined partListNode");
  93. }
  94. var partInst = root.elements("part");
  95. var partList = partlistNode.elements();
  96. this.initializeReading(partList, partInst, instrumentReaders);
  97. var couldReadMeasure = true;
  98. this.currentFraction = new fraction_1.Fraction(0, 1);
  99. var guitarPro = false;
  100. var encoding = root.element("identification");
  101. if (encoding !== undefined) {
  102. encoding = encoding.element("encoding");
  103. }
  104. if (encoding !== undefined) {
  105. encoding = encoding.element("software");
  106. }
  107. if (encoding !== undefined && encoding.value === "Guitar Pro 5") {
  108. guitarPro = true;
  109. }
  110. while (couldReadMeasure) {
  111. if (this.currentMeasure !== undefined && this.currentMeasure.endsPiece) {
  112. sourceMeasureCounter = 0;
  113. }
  114. this.currentMeasure = new SourceMeasure_1.SourceMeasure(this.completeNumberOfStaves);
  115. for (var _i = 0, instrumentReaders_2 = instrumentReaders; _i < instrumentReaders_2.length; _i++) {
  116. var instrumentReader = instrumentReaders_2[_i];
  117. try {
  118. couldReadMeasure = couldReadMeasure && instrumentReader.readNextXmlMeasure(this.currentMeasure, this.currentFraction, guitarPro);
  119. }
  120. catch (e) {
  121. var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/InstrumentError", "Error while reading instruments.");
  122. throw new Exceptions_1.MusicSheetReadingException(errorMsg, e);
  123. }
  124. }
  125. if (couldReadMeasure) {
  126. this.musicSheet.addMeasure(this.currentMeasure);
  127. this.checkIfRhythmInstructionsAreSetAndEqual(instrumentReaders);
  128. this.checkSourceMeasureForundefinedEntries();
  129. this.setSourceMeasureDuration(instrumentReaders, sourceMeasureCounter);
  130. MusicSheetReader.doCalculationsAfterDurationHasBeenSet(instrumentReaders);
  131. this.currentMeasure.AbsoluteTimestamp = this.currentFraction.clone();
  132. this.musicSheet.SheetErrors.finalizeMeasure(this.currentMeasure.MeasureNumber);
  133. this.currentFraction.Add(this.currentMeasure.Duration);
  134. this.previousMeasure = this.currentMeasure;
  135. }
  136. }
  137. if (this.repetitionInstructionReader !== undefined) {
  138. this.repetitionInstructionReader.removeRedundantInstructions();
  139. if (this.repetitionCalculator !== undefined) {
  140. this.repetitionCalculator.calculateRepetitions(this.musicSheet, this.repetitionInstructionReader.RepetitionInstructions);
  141. }
  142. }
  143. this.musicSheet.checkForInstrumentWithNoVoice();
  144. this.musicSheet.fillStaffList();
  145. //this.musicSheet.DefaultStartTempoInBpm = this.musicSheet.SheetPlaybackSetting.BeatsPerMinute;
  146. //for (let idx: number = 0, len: number = this.afterSheetReadingModules.length; idx < len; ++idx) {
  147. // let afterSheetReadingModule: IAfterSheetReadingModule = this.afterSheetReadingModules[idx];
  148. // afterSheetReadingModule.calculate(this.musicSheet);
  149. //}
  150. return this.musicSheet;
  151. };
  152. MusicSheetReader /*implements IMusicSheetReader*/.prototype.initializeReading = function (partList, partInst, instrumentReaders) {
  153. var instrumentDict = this.createInstrumentGroups(partList);
  154. this.completeNumberOfStaves = this.getCompleteNumberOfStavesFromXml(partInst);
  155. if (partInst.length !== 0) {
  156. // (*) this.repetitionInstructionReader.MusicSheet = this.musicSheet;
  157. this.currentFraction = new fraction_1.Fraction(0, 1);
  158. this.currentMeasure = undefined;
  159. this.previousMeasure = undefined;
  160. }
  161. var counter = 0;
  162. for (var _i = 0, partInst_1 = partInst; _i < partInst_1.length; _i++) {
  163. var node = partInst_1[_i];
  164. var idNode = node.attribute("id");
  165. if (idNode) {
  166. var currentInstrument = instrumentDict[idNode.value];
  167. var xmlMeasureList = node.elements("measure");
  168. var instrumentNumberOfStaves = 1;
  169. try {
  170. instrumentNumberOfStaves = this.getInstrumentNumberOfStavesFromXml(node);
  171. }
  172. catch (err) {
  173. var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/InstrumentStavesNumberError", "Invalid number of staves at instrument: ");
  174. this.musicSheet.SheetErrors.push(errorMsg + currentInstrument.Name);
  175. continue;
  176. }
  177. currentInstrument.createStaves(instrumentNumberOfStaves);
  178. instrumentReaders.push(new InstrumentReader_1.InstrumentReader(this.repetitionInstructionReader, xmlMeasureList, currentInstrument));
  179. if (this.repetitionInstructionReader !== undefined) {
  180. this.repetitionInstructionReader.XmlMeasureList[counter] = xmlMeasureList;
  181. }
  182. counter++;
  183. }
  184. }
  185. };
  186. MusicSheetReader /*implements IMusicSheetReader*/.prototype.checkIfRhythmInstructionsAreSetAndEqual = function (instrumentReaders) {
  187. var rhythmInstructions = [];
  188. for (var i = 0; i < this.completeNumberOfStaves; i++) {
  189. if (this.currentMeasure.FirstInstructionsStaffEntries[i] !== undefined) {
  190. var last = this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions[this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.length - 1];
  191. if (last instanceof RhythmInstruction_1.RhythmInstruction) {
  192. rhythmInstructions.push(last);
  193. }
  194. }
  195. }
  196. var maxRhythmValue = 0.0;
  197. var index = -1;
  198. for (var idx = 0, len = rhythmInstructions.length; idx < len; ++idx) {
  199. var rhythmInstruction = rhythmInstructions[idx];
  200. if (rhythmInstruction.Rhythm.RealValue > maxRhythmValue) {
  201. if (this.areRhythmInstructionsMixed(rhythmInstructions) && rhythmInstruction.SymbolEnum !== RhythmInstruction_2.RhythmSymbolEnum.NONE) {
  202. continue;
  203. }
  204. maxRhythmValue = rhythmInstruction.Rhythm.RealValue;
  205. index = rhythmInstructions.indexOf(rhythmInstruction);
  206. }
  207. }
  208. if (rhythmInstructions.length > 0 && rhythmInstructions.length < this.completeNumberOfStaves) {
  209. var rhythmInstruction = rhythmInstructions[index].clone();
  210. for (var i = 0; i < this.completeNumberOfStaves; i++) {
  211. if (this.currentMeasure.FirstInstructionsStaffEntries[i] !== undefined &&
  212. !(this._lastElement(this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions) instanceof RhythmInstruction_1.RhythmInstruction)) {
  213. this.currentMeasure.FirstInstructionsStaffEntries[i].removeAllInstructionsOfTypeRhythmInstruction();
  214. this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(rhythmInstruction.clone());
  215. }
  216. if (this.currentMeasure.FirstInstructionsStaffEntries[i] === undefined) {
  217. this.currentMeasure.FirstInstructionsStaffEntries[i] = new SourceStaffEntry_1.SourceStaffEntry(undefined, undefined);
  218. this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(rhythmInstruction.clone());
  219. }
  220. }
  221. for (var idx = 0, len = instrumentReaders.length; idx < len; ++idx) {
  222. var instrumentReader = instrumentReaders[idx];
  223. instrumentReader.ActiveRhythm = rhythmInstruction;
  224. }
  225. }
  226. if (rhythmInstructions.length === 0 && this.currentMeasure === this.musicSheet.SourceMeasures[0]) {
  227. var rhythmInstruction = new RhythmInstruction_1.RhythmInstruction(new fraction_1.Fraction(4, 4, false), 4, 4, RhythmInstruction_2.RhythmSymbolEnum.NONE);
  228. for (var i = 0; i < this.completeNumberOfStaves; i++) {
  229. if (this.currentMeasure.FirstInstructionsStaffEntries[i] === undefined) {
  230. this.currentMeasure.FirstInstructionsStaffEntries[i] = new SourceStaffEntry_1.SourceStaffEntry(undefined, undefined);
  231. }
  232. else {
  233. this.currentMeasure.FirstInstructionsStaffEntries[i].removeAllInstructionsOfTypeRhythmInstruction();
  234. }
  235. this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(rhythmInstruction);
  236. }
  237. for (var idx = 0, len = instrumentReaders.length; idx < len; ++idx) {
  238. var instrumentReader = instrumentReaders[idx];
  239. instrumentReader.ActiveRhythm = rhythmInstruction;
  240. }
  241. }
  242. for (var idx = 0, len = rhythmInstructions.length; idx < len; ++idx) {
  243. var rhythmInstruction = rhythmInstructions[idx];
  244. if (rhythmInstruction.Rhythm.RealValue < maxRhythmValue) {
  245. if (this._lastElement(this.currentMeasure.FirstInstructionsStaffEntries[rhythmInstructions.indexOf(rhythmInstruction)].Instructions) instanceof RhythmInstruction_1.RhythmInstruction) {
  246. // TODO Test correctness
  247. var instrs = this.currentMeasure.FirstInstructionsStaffEntries[rhythmInstructions.indexOf(rhythmInstruction)].Instructions;
  248. instrs[instrs.length - 1] = rhythmInstructions[index].clone();
  249. }
  250. }
  251. if (Math.abs(rhythmInstruction.Rhythm.RealValue - maxRhythmValue) < 0.000001 &&
  252. rhythmInstruction.SymbolEnum !== RhythmInstruction_2.RhythmSymbolEnum.NONE &&
  253. this.areRhythmInstructionsMixed(rhythmInstructions)) {
  254. rhythmInstruction.SymbolEnum = RhythmInstruction_2.RhythmSymbolEnum.NONE;
  255. }
  256. }
  257. };
  258. MusicSheetReader /*implements IMusicSheetReader*/.prototype.areRhythmInstructionsMixed = function (rhythmInstructions) {
  259. for (var i = 1; i < rhythmInstructions.length; i++) {
  260. if (Math.abs(rhythmInstructions[i].Rhythm.RealValue - rhythmInstructions[0].Rhythm.RealValue) < 0.000001 &&
  261. rhythmInstructions[i].SymbolEnum !== rhythmInstructions[0].SymbolEnum) {
  262. return true;
  263. }
  264. }
  265. return false;
  266. };
  267. MusicSheetReader /*implements IMusicSheetReader*/.prototype.setSourceMeasureDuration = function (instrumentReaders, sourceMeasureCounter) {
  268. var activeRhythm = new fraction_1.Fraction(0, 1);
  269. var instrumentsMaxTieNoteFractions = [];
  270. for (var _i = 0, instrumentReaders_3 = instrumentReaders; _i < instrumentReaders_3.length; _i++) {
  271. var instrumentReader = instrumentReaders_3[_i];
  272. instrumentsMaxTieNoteFractions.push(instrumentReader.MaxTieNoteFraction);
  273. var activeRythmMeasure = instrumentReader.ActiveRhythm.Rhythm;
  274. if (activeRhythm.lt(activeRythmMeasure)) {
  275. activeRhythm = new fraction_1.Fraction(activeRythmMeasure.Numerator, activeRythmMeasure.Denominator, false);
  276. }
  277. }
  278. var instrumentsDurations = this.currentMeasure.calculateInstrumentsDuration(this.musicSheet, instrumentsMaxTieNoteFractions);
  279. var maxInstrumentDuration = new fraction_1.Fraction(0, 1);
  280. for (var _a = 0, instrumentsDurations_1 = instrumentsDurations; _a < instrumentsDurations_1.length; _a++) {
  281. var instrumentsDuration = instrumentsDurations_1[_a];
  282. if (maxInstrumentDuration.lt(instrumentsDuration)) {
  283. maxInstrumentDuration = instrumentsDuration;
  284. }
  285. }
  286. if (fraction_1.Fraction.Equal(maxInstrumentDuration, activeRhythm)) {
  287. this.checkFractionsForEquivalence(maxInstrumentDuration, activeRhythm);
  288. }
  289. else {
  290. if (maxInstrumentDuration.lt(activeRhythm)) {
  291. maxInstrumentDuration = this.currentMeasure.reverseCheck(this.musicSheet, maxInstrumentDuration);
  292. this.checkFractionsForEquivalence(maxInstrumentDuration, activeRhythm);
  293. }
  294. }
  295. this.currentMeasure.ImplicitMeasure = this.checkIfMeasureIsImplicit(maxInstrumentDuration, activeRhythm);
  296. if (!this.currentMeasure.ImplicitMeasure) {
  297. sourceMeasureCounter++;
  298. }
  299. this.currentMeasure.Duration = maxInstrumentDuration;
  300. this.currentMeasure.MeasureNumber = sourceMeasureCounter;
  301. for (var i = 0; i < instrumentsDurations.length; i++) {
  302. var instrumentsDuration = instrumentsDurations[i];
  303. if ((this.currentMeasure.ImplicitMeasure && instrumentsDuration !== maxInstrumentDuration) ||
  304. !fraction_1.Fraction.Equal(instrumentsDuration, activeRhythm) &&
  305. !this.allInstrumentsHaveSameDuration(instrumentsDurations, maxInstrumentDuration)) {
  306. var firstStaffIndexOfInstrument = this.musicSheet.getGlobalStaffIndexOfFirstStaff(this.musicSheet.Instruments[i]);
  307. for (var staffIndex = 0; staffIndex < this.musicSheet.Instruments[i].Staves.length; staffIndex++) {
  308. if (!this.staffMeasureIsEmpty(firstStaffIndexOfInstrument + staffIndex)) {
  309. this.currentMeasure.setErrorInStaffMeasure(firstStaffIndexOfInstrument + staffIndex, true);
  310. var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/MissingNotesError", "Given Notes don't correspond to measure duration.");
  311. this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
  312. }
  313. }
  314. }
  315. }
  316. };
  317. MusicSheetReader /*implements IMusicSheetReader*/.prototype.checkFractionsForEquivalence = function (maxInstrumentDuration, activeRhythm) {
  318. if (activeRhythm.Denominator > maxInstrumentDuration.Denominator) {
  319. var factor = activeRhythm.Denominator / maxInstrumentDuration.Denominator;
  320. maxInstrumentDuration.multiplyWithFactor(factor);
  321. }
  322. };
  323. MusicSheetReader /*implements IMusicSheetReader*/.prototype.checkIfMeasureIsImplicit = function (maxInstrumentDuration, activeRhythm) {
  324. if (this.previousMeasure === undefined && maxInstrumentDuration < activeRhythm) {
  325. return true;
  326. }
  327. if (this.previousMeasure !== undefined) {
  328. return fraction_1.Fraction.plus(this.previousMeasure.Duration, maxInstrumentDuration).CompareTo(activeRhythm) === 0;
  329. }
  330. return false;
  331. };
  332. MusicSheetReader /*implements IMusicSheetReader*/.prototype.allInstrumentsHaveSameDuration = function (instrumentsDurations, maxInstrumentDuration) {
  333. var counter = 0;
  334. for (var idx = 0, len = instrumentsDurations.length; idx < len; ++idx) {
  335. var instrumentsDuration = instrumentsDurations[idx];
  336. if (instrumentsDuration === maxInstrumentDuration) {
  337. counter++;
  338. }
  339. }
  340. return (counter === instrumentsDurations.length && maxInstrumentDuration !== new fraction_1.Fraction(0, 1));
  341. };
  342. MusicSheetReader /*implements IMusicSheetReader*/.prototype.staffMeasureIsEmpty = function (index) {
  343. var counter = 0;
  344. for (var i = 0; i < this.currentMeasure.VerticalSourceStaffEntryContainers.length; i++) {
  345. if (this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries[index] === undefined) {
  346. counter++;
  347. }
  348. }
  349. return (counter === this.currentMeasure.VerticalSourceStaffEntryContainers.length);
  350. };
  351. MusicSheetReader /*implements IMusicSheetReader*/.prototype.checkSourceMeasureForundefinedEntries = function () {
  352. for (var i = this.currentMeasure.VerticalSourceStaffEntryContainers.length - 1; i >= 0; i--) {
  353. for (var j = this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries.length - 1; j >= 0; j--) {
  354. var sourceStaffEntry = this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries[j];
  355. if (sourceStaffEntry !== undefined) {
  356. for (var k = sourceStaffEntry.VoiceEntries.length - 1; k >= 0; k--) {
  357. var voiceEntry = sourceStaffEntry.VoiceEntries[k];
  358. if (voiceEntry.Notes.length === 0) {
  359. this._removeFromArray(voiceEntry.ParentVoice.VoiceEntries, voiceEntry);
  360. this._removeFromArray(sourceStaffEntry.VoiceEntries, voiceEntry);
  361. }
  362. }
  363. }
  364. if (sourceStaffEntry !== undefined && sourceStaffEntry.VoiceEntries.length === 0) {
  365. this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries[j] = undefined;
  366. }
  367. }
  368. }
  369. for (var i = this.currentMeasure.VerticalSourceStaffEntryContainers.length - 1; i >= 0; i--) {
  370. var counter = 0;
  371. for (var idx = 0, len = this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries.length; idx < len; ++idx) {
  372. var sourceStaffEntry = this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries[idx];
  373. if (sourceStaffEntry === undefined) {
  374. counter++;
  375. }
  376. }
  377. if (counter === this.currentMeasure.VerticalSourceStaffEntryContainers[i].StaffEntries.length) {
  378. this._removeFromArray(this.currentMeasure.VerticalSourceStaffEntryContainers, this.currentMeasure.VerticalSourceStaffEntryContainers[i]);
  379. }
  380. }
  381. };
  382. MusicSheetReader /*implements IMusicSheetReader*/.prototype.pushSheetLabels = function (root, filePath) {
  383. this.readComposer(root);
  384. this.readTitle(root);
  385. if (this.musicSheet.Title === undefined || this.musicSheet.Composer === undefined) {
  386. this.readTitleAndComposerFromCredits(root);
  387. }
  388. if (this.musicSheet.Title === undefined) {
  389. try {
  390. var barI = Math.max(0, filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
  391. var filename = filePath.substr(barI);
  392. var filenameSplits = filename.split(".", 1);
  393. this.musicSheet.Title = new Label_1.Label(filenameSplits[0]);
  394. }
  395. catch (ex) {
  396. Logging_1.Logging.log("MusicSheetReader.pushSheetLabels: ", ex);
  397. }
  398. }
  399. };
  400. // Checks whether _elem_ has an attribute with value _val_.
  401. MusicSheetReader /*implements IMusicSheetReader*/.prototype.presentAttrsWithValue = function (elem, val) {
  402. for (var _i = 0, _a = elem.attributes(); _i < _a.length; _i++) {
  403. var attr = _a[_i];
  404. if (attr.value === val) {
  405. return true;
  406. }
  407. }
  408. return false;
  409. };
  410. MusicSheetReader /*implements IMusicSheetReader*/.prototype.readComposer = function (root) {
  411. var identificationNode = root.element("identification");
  412. if (identificationNode !== undefined) {
  413. var creators = identificationNode.elements("creator");
  414. for (var idx = 0, len = creators.length; idx < len; ++idx) {
  415. var creator = creators[idx];
  416. if (creator.hasAttributes) {
  417. if (this.presentAttrsWithValue(creator, "composer")) {
  418. this.musicSheet.Composer = new Label_1.Label(this.trimString(creator.value));
  419. continue;
  420. }
  421. if (this.presentAttrsWithValue(creator, "lyricist") || this.presentAttrsWithValue(creator, "poet")) {
  422. this.musicSheet.Lyricist = new Label_1.Label(this.trimString(creator.value));
  423. }
  424. }
  425. }
  426. }
  427. };
  428. MusicSheetReader /*implements IMusicSheetReader*/.prototype.readTitleAndComposerFromCredits = function (root) {
  429. var systemYCoordinates = this.computeSystemYCoordinates(root);
  430. if (systemYCoordinates === 0) {
  431. return;
  432. }
  433. var largestTitleCreditSize = 1;
  434. var finalTitle = undefined;
  435. var largestCreditYInfo = 0;
  436. var finalSubtitle = undefined;
  437. var possibleTitle = undefined;
  438. var creditElements = root.elements("credit");
  439. for (var idx = 0, len = creditElements.length; idx < len; ++idx) {
  440. var credit = creditElements[idx];
  441. if (!credit.attribute("page")) {
  442. return;
  443. }
  444. if (credit.attribute("page").value === "1") {
  445. var creditChild = undefined;
  446. if (credit !== undefined) {
  447. creditChild = credit.element("credit-words");
  448. if (!creditChild.attribute("justify")) {
  449. break;
  450. }
  451. var creditJustify = creditChild.attribute("justify").value;
  452. var creditY = creditChild.attribute("default-y").value;
  453. var creditYInfo = parseFloat(creditY);
  454. if (creditYInfo > systemYCoordinates) {
  455. if (this.musicSheet.Title === undefined) {
  456. var creditSize = creditChild.attribute("font-size").value;
  457. var titleCreditSizeInt = parseFloat(creditSize);
  458. if (largestTitleCreditSize < titleCreditSizeInt) {
  459. largestTitleCreditSize = titleCreditSizeInt;
  460. finalTitle = creditChild.value;
  461. }
  462. }
  463. if (this.musicSheet.Subtitle === undefined) {
  464. if (creditJustify !== "right" && creditJustify !== "left") {
  465. if (largestCreditYInfo < creditYInfo) {
  466. largestCreditYInfo = creditYInfo;
  467. if (possibleTitle) {
  468. finalSubtitle = possibleTitle;
  469. possibleTitle = creditChild.value;
  470. }
  471. else {
  472. possibleTitle = creditChild.value;
  473. }
  474. }
  475. }
  476. }
  477. if (!(this.musicSheet.Composer !== undefined && this.musicSheet.Lyricist !== undefined)) {
  478. switch (creditJustify) {
  479. case "right":
  480. this.musicSheet.Composer = new Label_1.Label(this.trimString(creditChild.value));
  481. break;
  482. case "left":
  483. this.musicSheet.Lyricist = new Label_1.Label(this.trimString(creditChild.value));
  484. break;
  485. default:
  486. break;
  487. }
  488. }
  489. }
  490. }
  491. }
  492. }
  493. if (this.musicSheet.Title === undefined && finalTitle) {
  494. this.musicSheet.Title = new Label_1.Label(this.trimString(finalTitle));
  495. }
  496. if (this.musicSheet.Subtitle === undefined && finalSubtitle) {
  497. this.musicSheet.Subtitle = new Label_1.Label(this.trimString(finalSubtitle));
  498. }
  499. };
  500. MusicSheetReader /*implements IMusicSheetReader*/.prototype.computeSystemYCoordinates = function (root) {
  501. if (root.element("defaults") === undefined) {
  502. return 0;
  503. }
  504. var paperHeight = 0;
  505. var topSystemDistance = 0;
  506. var defi = root.element("defaults").element("page-layout").element("page-height").value;
  507. paperHeight = parseFloat(defi);
  508. var found = false;
  509. var parts = root.elements("part");
  510. for (var idx = 0, len = parts.length; idx < len; ++idx) {
  511. var measures = parts[idx].elements("measure");
  512. for (var idx2 = 0, len2 = measures.length; idx2 < len2; ++idx2) {
  513. var measure = measures[idx2];
  514. if (measure.element("print") !== undefined) {
  515. var systemLayouts = measure.element("print").elements("system-layout");
  516. for (var idx3 = 0, len3 = systemLayouts.length; idx3 < len3; ++idx3) {
  517. var syslab = systemLayouts[idx3];
  518. if (syslab.element("top-system-distance") !== undefined) {
  519. var topSystemDistanceString = syslab.element("top-system-distance").value;
  520. topSystemDistance = parseFloat(topSystemDistanceString);
  521. found = true;
  522. break;
  523. }
  524. }
  525. break;
  526. }
  527. }
  528. if (found) {
  529. break;
  530. }
  531. }
  532. if (root.element("defaults").element("system-layout") !== undefined) {
  533. var syslay = root.element("defaults").element("system-layout");
  534. if (syslay.element("top-system-distance") !== undefined) {
  535. var topSystemDistanceString = root.element("defaults").element("system-layout").element("top-system-distance").value;
  536. topSystemDistance = parseFloat(topSystemDistanceString);
  537. }
  538. }
  539. if (topSystemDistance === 0) {
  540. return 0;
  541. }
  542. return paperHeight - topSystemDistance;
  543. };
  544. MusicSheetReader /*implements IMusicSheetReader*/.prototype.readTitle = function (root) {
  545. var titleNode = root.element("work");
  546. var titleNodeChild = undefined;
  547. if (titleNode !== undefined) {
  548. titleNodeChild = titleNode.element("work-title");
  549. if (titleNodeChild !== undefined && titleNodeChild.value) {
  550. this.musicSheet.Title = new Label_1.Label(this.trimString(titleNodeChild.value));
  551. }
  552. }
  553. var movementNode = root.element("movement-title");
  554. var finalSubTitle = "";
  555. if (movementNode !== undefined) {
  556. if (this.musicSheet.Title === undefined) {
  557. this.musicSheet.Title = new Label_1.Label(this.trimString(movementNode.value));
  558. }
  559. else {
  560. finalSubTitle = this.trimString(movementNode.value);
  561. }
  562. }
  563. if (titleNode !== undefined) {
  564. var subtitleNodeChild = titleNode.element("work-number");
  565. if (subtitleNodeChild !== undefined) {
  566. var workNumber = subtitleNodeChild.value;
  567. if (workNumber) {
  568. if (finalSubTitle) {
  569. finalSubTitle = workNumber;
  570. }
  571. else {
  572. finalSubTitle = finalSubTitle + ", " + workNumber;
  573. }
  574. }
  575. }
  576. }
  577. if (finalSubTitle) {
  578. this.musicSheet.Subtitle = new Label_1.Label(finalSubTitle);
  579. }
  580. };
  581. MusicSheetReader /*implements IMusicSheetReader*/.prototype.createInstrumentGroups = function (entryList) {
  582. var instrumentId = 0;
  583. var instrumentDict = {};
  584. var currentGroup;
  585. try {
  586. var entryArray = entryList;
  587. for (var idx = 0, len = entryArray.length; idx < len; ++idx) {
  588. var node = entryArray[idx];
  589. if (node.name === "score-part") {
  590. var instrIdString = node.attribute("id").value;
  591. var instrument = new Instrument_1.Instrument(instrumentId, instrIdString, this.musicSheet, currentGroup);
  592. instrumentId++;
  593. var partElements = node.elements();
  594. for (var idx2 = 0, len2 = partElements.length; idx2 < len2; ++idx2) {
  595. var partElement = partElements[idx2];
  596. try {
  597. if (partElement.name === "part-name") {
  598. instrument.Name = partElement.value;
  599. }
  600. else if (partElement.name === "score-instrument") {
  601. var subInstrument = new SubInstrument_1.SubInstrument(instrument);
  602. subInstrument.idString = partElement.firstAttribute.value;
  603. instrument.SubInstruments.push(subInstrument);
  604. var subElement = partElement.element("instrument-name");
  605. if (subElement !== undefined) {
  606. subInstrument.name = subElement.value;
  607. subInstrument.setMidiInstrument(subElement.value);
  608. }
  609. }
  610. else if (partElement.name === "midi-instrument") {
  611. var subInstrument = instrument.getSubInstrument(partElement.firstAttribute.value);
  612. for (var idx3 = 0, len3 = instrument.SubInstruments.length; idx3 < len3; ++idx3) {
  613. var subInstr = instrument.SubInstruments[idx3];
  614. if (subInstr.idString === partElement.value) {
  615. subInstrument = subInstr;
  616. break;
  617. }
  618. }
  619. var instrumentElements = partElement.elements();
  620. for (var idx3 = 0, len3 = instrumentElements.length; idx3 < len3; ++idx3) {
  621. var instrumentElement = instrumentElements[idx3];
  622. try {
  623. if (instrumentElement.name === "midi-channel") {
  624. if (parseInt(instrumentElement.value, 10) === 10) {
  625. instrument.MidiInstrumentId = ClefInstruction_1.MidiInstrument.Percussion;
  626. }
  627. }
  628. else if (instrumentElement.name === "midi-program") {
  629. if (instrument.SubInstruments.length > 0 && instrument.MidiInstrumentId !== ClefInstruction_1.MidiInstrument.Percussion) {
  630. subInstrument.midiInstrumentID = Math.max(0, parseInt(instrumentElement.value, 10) - 1);
  631. }
  632. }
  633. else if (instrumentElement.name === "midi-unpitched") {
  634. subInstrument.fixedKey = Math.max(0, parseInt(instrumentElement.value, 10));
  635. }
  636. else if (instrumentElement.name === "volume") {
  637. try {
  638. var result = parseFloat(instrumentElement.value);
  639. subInstrument.volume = result / 127.0;
  640. }
  641. catch (ex) {
  642. Logging_1.Logging.debug("ExpressionReader.readExpressionParameters", "read volume", ex);
  643. }
  644. }
  645. else if (instrumentElement.name === "pan") {
  646. try {
  647. var result = parseFloat(instrumentElement.value);
  648. subInstrument.pan = result / 64.0;
  649. }
  650. catch (ex) {
  651. Logging_1.Logging.debug("ExpressionReader.readExpressionParameters", "read pan", ex);
  652. }
  653. }
  654. }
  655. catch (ex) {
  656. Logging_1.Logging.log("MusicSheetReader.createInstrumentGroups midi settings: ", ex);
  657. }
  658. }
  659. }
  660. }
  661. catch (ex) {
  662. Logging_1.Logging.log("MusicSheetReader.createInstrumentGroups: ", ex);
  663. }
  664. }
  665. if (instrument.SubInstruments.length === 0) {
  666. var subInstrument = new SubInstrument_1.SubInstrument(instrument);
  667. instrument.SubInstruments.push(subInstrument);
  668. }
  669. instrumentDict[instrIdString] = instrument;
  670. if (currentGroup !== undefined) {
  671. currentGroup.InstrumentalGroups.push(instrument);
  672. this.musicSheet.Instruments.push(instrument);
  673. }
  674. else {
  675. this.musicSheet.InstrumentalGroups.push(instrument);
  676. this.musicSheet.Instruments.push(instrument);
  677. }
  678. }
  679. else {
  680. if ((node.name === "part-group") && (node.attribute("type").value === "start")) {
  681. var iG = new InstrumentalGroup_1.InstrumentalGroup("group", this.musicSheet, currentGroup);
  682. if (currentGroup !== undefined) {
  683. currentGroup.InstrumentalGroups.push(iG);
  684. }
  685. else {
  686. this.musicSheet.InstrumentalGroups.push(iG);
  687. }
  688. currentGroup = iG;
  689. }
  690. else {
  691. if ((node.name === "part-group") && (node.attribute("type").value === "stop")) {
  692. if (currentGroup !== undefined) {
  693. if (currentGroup.InstrumentalGroups.length === 1) {
  694. var instr = currentGroup.InstrumentalGroups[0];
  695. if (currentGroup.Parent !== undefined) {
  696. currentGroup.Parent.InstrumentalGroups.push(instr);
  697. this._removeFromArray(currentGroup.Parent.InstrumentalGroups, currentGroup);
  698. }
  699. else {
  700. this.musicSheet.InstrumentalGroups.push(instr);
  701. this._removeFromArray(this.musicSheet.InstrumentalGroups, currentGroup);
  702. }
  703. }
  704. currentGroup = currentGroup.Parent;
  705. }
  706. }
  707. }
  708. }
  709. }
  710. }
  711. catch (e) {
  712. var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/InstrumentError", "Error while reading Instruments");
  713. throw new Exceptions_1.MusicSheetReadingException(errorMsg, e);
  714. }
  715. for (var idx = 0, len = this.musicSheet.Instruments.length; idx < len; ++idx) {
  716. var instrument = this.musicSheet.Instruments[idx];
  717. if (!instrument.Name) {
  718. instrument.Name = "Instr. " + instrument.IdString;
  719. }
  720. }
  721. return instrumentDict;
  722. };
  723. MusicSheetReader /*implements IMusicSheetReader*/.prototype.getCompleteNumberOfStavesFromXml = function (partInst) {
  724. var num = 0;
  725. for (var _i = 0, partInst_2 = partInst; _i < partInst_2.length; _i++) {
  726. var partNode = partInst_2[_i];
  727. var xmlMeasureList = partNode.elements("measure");
  728. if (xmlMeasureList.length > 0) {
  729. var xmlMeasure = xmlMeasureList[0];
  730. if (xmlMeasure !== undefined) {
  731. var stavesNode = xmlMeasure.element("attributes");
  732. if (stavesNode !== undefined) {
  733. stavesNode = stavesNode.element("staves");
  734. }
  735. if (stavesNode === undefined) {
  736. num++;
  737. }
  738. else {
  739. num += parseInt(stavesNode.value, 10);
  740. }
  741. }
  742. }
  743. }
  744. if (isNaN(num) || num <= 0) {
  745. var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/StaffError", "Invalid number of staves.");
  746. throw new Exceptions_1.MusicSheetReadingException(errorMsg);
  747. }
  748. return num;
  749. };
  750. MusicSheetReader /*implements IMusicSheetReader*/.prototype.getInstrumentNumberOfStavesFromXml = function (partNode) {
  751. var num = 0;
  752. var xmlMeasure = partNode.element("measure");
  753. if (xmlMeasure !== undefined) {
  754. var attributes = xmlMeasure.element("attributes");
  755. var staves = undefined;
  756. if (attributes !== undefined) {
  757. staves = attributes.element("staves");
  758. }
  759. if (attributes === undefined || staves === undefined) {
  760. num = 1;
  761. }
  762. else {
  763. num = parseInt(staves.value, 10);
  764. }
  765. }
  766. if (isNaN(num) || num <= 0) {
  767. var errorMsg = ITextTranslation_1.ITextTranslation.translateText("ReaderErrorMessages/StaffError", "Invalid number of Staves.");
  768. throw new Exceptions_1.MusicSheetReadingException(errorMsg);
  769. }
  770. return num;
  771. };
  772. return MusicSheetReader /*implements IMusicSheetReader*/;
  773. }());
  774. exports.MusicSheetReader /*implements IMusicSheetReader*/ = MusicSheetReader /*implements IMusicSheetReader*/;