MusicPartManagerIterator.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. import {MusicPartManager} from "./MusicPartManager";
  2. import {Fraction} from "../../Common/DataObjects/Fraction";
  3. import {Repetition} from "../MusicSource/Repetition";
  4. import {DynamicsContainer} from "../VoiceData/HelperObjects/DynamicsContainer";
  5. import {MappingSourceMusicPart} from "../MusicSource/MappingSourceMusicPart";
  6. import {SourceMeasure} from "../VoiceData/SourceMeasure";
  7. import {VoiceEntry} from "../VoiceData/VoiceEntry";
  8. import {Instrument} from "../Instrument";
  9. import {VerticalSourceStaffEntryContainer} from "../VoiceData/VerticalSourceStaffEntryContainer";
  10. import {RhythmInstruction} from "../VoiceData/Instructions/RhythmInstruction";
  11. import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
  12. import {RepetitionInstruction} from "../VoiceData/Instructions/RepetitionInstruction";
  13. import {ContinuousDynamicExpression} from "../VoiceData/Expressions/ContinuousExpressions/ContinuousDynamicExpression";
  14. import {InstantaniousDynamicExpression} from "../VoiceData/Expressions/InstantaniousDynamicExpression";
  15. import {MultiTempoExpression} from "../VoiceData/Expressions/MultiTempoExpression";
  16. import {AbstractExpression} from "../VoiceData/Expressions/AbstractExpression";
  17. import {Logging} from "../../Common/Logging";
  18. export class MusicPartManagerIterator {
  19. constructor(manager: MusicPartManager, startTimestamp?: Fraction, endTimestamp?: Fraction) {
  20. try {
  21. this.frontReached = true;
  22. this.manager = manager;
  23. this.currentVoiceEntries = undefined;
  24. this.frontReached = false;
  25. for (let rep of manager.MusicSheet.Repetitions) {
  26. this.setRepetitionIterationCount(rep, 1);
  27. }
  28. this.activeDynamicExpressions = new Array(manager.MusicSheet.getCompleteNumberOfStaves());
  29. this.currentMeasure = this.manager.MusicSheet.SourceMeasures[0];
  30. if (startTimestamp === undefined) { return; }
  31. do {
  32. this.moveToNext();
  33. } while ((this.currentVoiceEntries === undefined || this.currentTimeStamp.lt(startTimestamp)) && !this.endReached);
  34. for (let staffIndex: number = 0; staffIndex < this.activeDynamicExpressions.length; staffIndex++) {
  35. if (this.activeDynamicExpressions[staffIndex] !== undefined) {
  36. if (this.activeDynamicExpressions[staffIndex] instanceof ContinuousDynamicExpression) {
  37. let continuousDynamic: ContinuousDynamicExpression =
  38. <ContinuousDynamicExpression>this.activeDynamicExpressions[staffIndex];
  39. this.currentDynamicChangingExpressions.push(new DynamicsContainer(continuousDynamic, staffIndex));
  40. } else {
  41. let instantaniousDynamic: InstantaniousDynamicExpression =
  42. <InstantaniousDynamicExpression>this.activeDynamicExpressions[staffIndex];
  43. this.currentDynamicChangingExpressions.push(new DynamicsContainer(instantaniousDynamic, staffIndex));
  44. }
  45. }
  46. }
  47. this.currentTempoChangingExpression = this.activeTempoExpression;
  48. } catch (err) {
  49. Logging.log("MusicPartManagerIterator: " + err);
  50. }
  51. }
  52. public backJumpOccurred: boolean;
  53. public forwardJumpOccurred: boolean;
  54. private manager: MusicPartManager;
  55. private currentMappingPart: MappingSourceMusicPart;
  56. private currentMeasure: SourceMeasure;
  57. private currentMeasureIndex: number = 0;
  58. private currentPartIndex: number = 0;
  59. private currentVoiceEntryIndex: number = -1;
  60. private currentDynamicEntryIndex: number = 0;
  61. private currentTempoEntryIndex: number = 0;
  62. private currentVoiceEntries: VoiceEntry[];
  63. private currentDynamicChangingExpressions: DynamicsContainer[] = [];
  64. private currentTempoChangingExpression: MultiTempoExpression;
  65. // FIXME: replace these two with a real Dictionary!
  66. private repetitionIterationCountDictKeys: Repetition[];
  67. private repetitionIterationCountDictValues: number[];
  68. private currentRepetition: Repetition = undefined;
  69. private endReached: boolean = false;
  70. private frontReached: boolean = false;
  71. private currentTimeStamp: Fraction = new Fraction(0, 1);
  72. private currentEnrolledMeasureTimestamp: Fraction = new Fraction(0, 1);
  73. private currentVerticalContainerInMeasureTimestamp: Fraction = new Fraction(0, 1);
  74. private jumpResponsibleRepetition: Repetition = undefined;
  75. private activeDynamicExpressions: AbstractExpression[] = [];
  76. private activeTempoExpression: MultiTempoExpression;
  77. public get EndReached(): boolean {
  78. return this.endReached;
  79. }
  80. public get FrontReached(): boolean {
  81. return this.frontReached;
  82. }
  83. public get CurrentMeasure(): SourceMeasure {
  84. return this.currentMeasure;
  85. }
  86. public get CurrentRepetition(): Repetition {
  87. return this.currentRepetition;
  88. }
  89. public get CurrentRepetitionIteration(): number {
  90. if (this.CurrentRepetition !== undefined) {
  91. return this.getRepetitionIterationCount(this.CurrentRepetition);
  92. }
  93. return 0;
  94. }
  95. public get CurrentJumpResponsibleRepetitionIterationBeforeJump(): number {
  96. if (this.jumpResponsibleRepetition !== undefined) {
  97. return this.getRepetitionIterationCount(this.jumpResponsibleRepetition) - 1;
  98. }
  99. return 0;
  100. }
  101. public get CurrentVoiceEntries(): VoiceEntry[] {
  102. return this.currentVoiceEntries;
  103. }
  104. public get CurrentMeasureIndex(): number {
  105. return this.currentMeasureIndex;
  106. }
  107. public get CurrentEnrolledTimestamp(): Fraction {
  108. return Fraction.plus(this.currentEnrolledMeasureTimestamp, this.currentVerticalContainerInMeasureTimestamp);
  109. }
  110. public get CurrentSourceTimestamp(): Fraction {
  111. return this.currentTimeStamp;
  112. }
  113. public get JumpOccurred(): boolean {
  114. return this.backJumpOccurred || this.forwardJumpOccurred;
  115. }
  116. public get ActiveTempoExpression(): MultiTempoExpression {
  117. return this.activeTempoExpression;
  118. }
  119. public get ActiveDynamicExpressions(): AbstractExpression[] {
  120. return this.activeDynamicExpressions;
  121. }
  122. public get CurrentTempoChangingExpression(): MultiTempoExpression {
  123. return this.currentTempoChangingExpression;
  124. }
  125. public get JumpResponsibleRepetition(): Repetition {
  126. return this.jumpResponsibleRepetition;
  127. }
  128. public clone(): MusicPartManagerIterator {
  129. let ret: MusicPartManagerIterator = new MusicPartManagerIterator(this.manager);
  130. ret.currentVoiceEntryIndex = this.currentVoiceEntryIndex;
  131. ret.currentMappingPart = this.currentMappingPart;
  132. ret.currentPartIndex = this.currentPartIndex;
  133. ret.currentVoiceEntries = this.currentVoiceEntries;
  134. ret.endReached = this.endReached;
  135. ret.frontReached = this.frontReached;
  136. return ret;
  137. }
  138. public CurrentVisibleVoiceEntries(instrument?: Instrument): VoiceEntry[] {
  139. let voiceEntries: VoiceEntry[] = [];
  140. if (this.currentVoiceEntries === undefined) {
  141. return voiceEntries;
  142. }
  143. if (instrument !== undefined) {
  144. for (let entry of this.currentVoiceEntries) {
  145. if (entry.ParentVoice.Parent.IdString === instrument.IdString) {
  146. this.getVisibleEntries(entry, voiceEntries);
  147. return voiceEntries;
  148. }
  149. }
  150. } else {
  151. for (let entry of this.currentVoiceEntries) {
  152. this.getVisibleEntries(entry, voiceEntries);
  153. }
  154. }
  155. return voiceEntries;
  156. }
  157. public CurrentAudibleVoiceEntries(instrument?: Instrument): VoiceEntry[] {
  158. let voiceEntries: VoiceEntry[] = [];
  159. if (this.currentVoiceEntries === undefined) {
  160. return voiceEntries;
  161. }
  162. if (instrument !== undefined) {
  163. for (let entry of this.currentVoiceEntries) {
  164. if (entry.ParentVoice.Parent.IdString === instrument.IdString) {
  165. this.getAudibleEntries(entry, voiceEntries);
  166. return voiceEntries;
  167. }
  168. }
  169. } else {
  170. for (let entry of this.currentVoiceEntries) {
  171. this.getAudibleEntries(entry, voiceEntries);
  172. }
  173. }
  174. return voiceEntries;
  175. }
  176. public getCurrentDynamicChangingExpressions(): DynamicsContainer[] {
  177. return this.currentDynamicChangingExpressions;
  178. }
  179. public CurrentScoreFollowingVoiceEntries(instrument?: Instrument): VoiceEntry[] {
  180. let voiceEntries: VoiceEntry[] = [];
  181. if (this.currentVoiceEntries === undefined) {
  182. return voiceEntries;
  183. }
  184. if (instrument !== undefined) {
  185. for (let entry of this.currentVoiceEntries) {
  186. if (entry.ParentVoice.Parent.IdString === instrument.IdString) {
  187. this.getScoreFollowingEntries(entry, voiceEntries);
  188. return voiceEntries;
  189. }
  190. }
  191. } else {
  192. for (let entry of this.currentVoiceEntries) {
  193. this.getScoreFollowingEntries(entry, voiceEntries);
  194. }
  195. }
  196. return voiceEntries;
  197. }
  198. //public currentPlaybackSettings(): PlaybackSettings {
  199. // return this.manager.MusicSheet.SheetPlaybackSetting;
  200. //}
  201. public moveToNext(): void {
  202. this.forwardJumpOccurred = this.backJumpOccurred = false;
  203. if (this.endReached) { return; }
  204. if (this.currentVoiceEntries !== undefined) {
  205. this.currentVoiceEntries = [];
  206. }
  207. this.recursiveMove();
  208. if (this.currentMeasure === undefined) {
  209. this.currentTimeStamp = new Fraction(99999, 1);
  210. }
  211. }
  212. public moveToNextVisibleVoiceEntry(notesOnly: boolean): void {
  213. while (!this.endReached) {
  214. this.moveToNext();
  215. if (this.checkEntries(notesOnly)) { return; }
  216. }
  217. }
  218. private resetRepetitionIterationCount(repetition: Repetition): number {
  219. this.setRepetitionIterationCount(repetition, 1);
  220. return 1;
  221. }
  222. private incrementRepetitionIterationCount(repetition: Repetition): number {
  223. if (this.repetitionIterationCountDictKeys.indexOf(repetition) === -1) {
  224. return this.setRepetitionIterationCount(repetition, 1);
  225. } else {
  226. return this.setRepetitionIterationCount(repetition, this.getRepetitionIterationCount(repetition) + 1);
  227. }
  228. }
  229. private setRepetitionIterationCount(repetition: Repetition, iterationCount: number): number {
  230. let i: number = this.repetitionIterationCountDictKeys.indexOf(repetition);
  231. if (i === -1) {
  232. this.repetitionIterationCountDictKeys.push(repetition);
  233. this.repetitionIterationCountDictValues.push(iterationCount);
  234. } else {
  235. this.repetitionIterationCountDictValues[i] = iterationCount;
  236. }
  237. return iterationCount;
  238. }
  239. private getRepetitionIterationCount(rep: Repetition): number {
  240. let i: number = this.repetitionIterationCountDictKeys.indexOf(rep);
  241. if (i !== -1) {
  242. return this.repetitionIterationCountDictValues[i];
  243. }
  244. }
  245. /* private moveTempoIndexToTimestamp(measureNumber: number): void {
  246. for (let index: number = 0; index < this.manager.MusicSheet.TimestampSortedTempoExpressionsList.length; index++) {
  247. if (this.manager.MusicSheet.TimestampSortedTempoExpressionsList[index].SourceMeasureParent.MeasureNumber >= measureNumber) {
  248. this.currentTempoEntryIndex = Math.Max(-1, index - 1);
  249. return
  250. }
  251. }
  252. }
  253. private getNextTempoEntryTimestamp(): Fraction {
  254. if (this.currentTempoEntryIndex >= this.manager.MusicSheet.TimestampSortedTempoExpressionsList.length - 1) {
  255. return new Fraction(99999, 1);
  256. }
  257. return this.manager.MusicSheet.TimestampSortedTempoExpressionsList[this.currentTempoEntryIndex + 1].SourceMeasureParent.AbsoluteTimestamp +
  258. this.manager.MusicSheet.TimestampSortedTempoExpressionsList[this.currentTempoEntryIndex + 1].Timestamp;
  259. }
  260. private moveToNextDynamic(): void {
  261. this.currentDynamicEntryIndex++;
  262. this.currentDynamicChangingExpressions.Clear();
  263. let curDynamicEntry: DynamicsContainer = this.manager.MusicSheet.TimestampSortedDynamicExpressionsList[this.currentDynamicEntryIndex];
  264. this.currentDynamicChangingExpressions.push(curDynamicEntry);
  265. let tsNow: Fraction = curDynamicEntry.parMultiExpression().AbsoluteTimestamp;
  266. for (let i: number = this.currentDynamicEntryIndex + 1; i < this.manager.MusicSheet.TimestampSortedDynamicExpressionsList.length; i++) {
  267. curDynamicEntry = this.manager.MusicSheet.TimestampSortedDynamicExpressionsList[i];
  268. if ((curDynamicEntry.parMultiExpression().AbsoluteTimestamp !== tsNow)) { break; }
  269. this.currentDynamicEntryIndex = i;
  270. this.currentDynamicChangingExpressions.push(curDynamicEntry);
  271. }
  272. }
  273. private moveDynamicIndexToTimestamp(absoluteTimestamp: Fraction): void {
  274. let dynamics: DynamicsContainer[] = this.manager.MusicSheet.TimestampSortedDynamicExpressionsList;
  275. for (let index: number = 0; index < dynamics.length; index++) {
  276. if (dynamics[index].parMultiExpression().AbsoluteTimestamp >= absoluteTimestamp) {
  277. this.currentDynamicEntryIndex = Math.Max(0, index - 1);
  278. return
  279. }
  280. }
  281. }
  282. private getNextDynamicsEntryTimestamp(): Fraction {
  283. if (this.currentDynamicEntryIndex >= this.manager.MusicSheet.TimestampSortedDynamicExpressionsList.length - 1) {
  284. return new Fraction(99999, 1);
  285. }
  286. return this.manager.MusicSheet.TimestampSortedDynamicExpressionsList[this.currentDynamicEntryIndex + 1].parMultiExpression().AbsoluteTimestamp;
  287. }
  288. */
  289. private handleRepetitionsAtMeasureBegin(): void {
  290. for (let idx: number = 0, len: number = this.currentMeasure.FirstRepetitionInstructions.length; idx < len; ++idx) {
  291. let repetitionInstruction: RepetitionInstruction = this.currentMeasure.FirstRepetitionInstructions[idx];
  292. if (repetitionInstruction.parentRepetition === undefined) { continue; }
  293. let currentRepetition: Repetition = repetitionInstruction.parentRepetition;
  294. this.currentRepetition = currentRepetition;
  295. if (currentRepetition.StartIndex === this.currentMeasureIndex) {
  296. if (
  297. this.JumpResponsibleRepetition !== undefined &&
  298. currentRepetition !== this.JumpResponsibleRepetition &&
  299. currentRepetition.StartIndex >= this.JumpResponsibleRepetition.StartIndex &&
  300. currentRepetition.EndIndex <= this.JumpResponsibleRepetition.EndIndex
  301. ) {
  302. this.resetRepetitionIterationCount(currentRepetition);
  303. }
  304. }
  305. }
  306. }
  307. private handleRepetitionsAtMeasureEnd(): void {
  308. for (let idx: number = 0, len: number = this.currentMeasure.LastRepetitionInstructions.length; idx < len; ++idx) {
  309. let repetitionInstruction: RepetitionInstruction = this.currentMeasure.LastRepetitionInstructions[idx];
  310. let currentRepetition: Repetition = repetitionInstruction.parentRepetition;
  311. if (currentRepetition === undefined) { continue; }
  312. if (currentRepetition.BackwardJumpInstructions.indexOf(repetitionInstruction) > -1) {
  313. if (this.getRepetitionIterationCount(currentRepetition) < currentRepetition.UserNumberOfRepetitions) {
  314. this.doBackJump(currentRepetition);
  315. this.backJumpOccurred = true;
  316. return;
  317. }
  318. }
  319. if (repetitionInstruction === currentRepetition.forwardJumpInstruction) {
  320. if (
  321. this.JumpResponsibleRepetition !== undefined
  322. && currentRepetition !== this.JumpResponsibleRepetition
  323. && currentRepetition.StartIndex >= this.JumpResponsibleRepetition.StartIndex
  324. && currentRepetition.EndIndex <= this.JumpResponsibleRepetition.EndIndex
  325. ) {
  326. this.resetRepetitionIterationCount(currentRepetition);
  327. }
  328. let forwardJumpTargetMeasureIndex: number = currentRepetition.getForwardJumpTargetForIteration(
  329. this.getRepetitionIterationCount(currentRepetition)
  330. );
  331. if (forwardJumpTargetMeasureIndex >= 0) {
  332. this.currentMeasureIndex = forwardJumpTargetMeasureIndex;
  333. this.currentMeasure = this.manager.MusicSheet.SourceMeasures[this.currentMeasureIndex];
  334. this.currentVoiceEntryIndex = -1;
  335. this.jumpResponsibleRepetition = currentRepetition;
  336. this.forwardJumpOccurred = true;
  337. return;
  338. }
  339. if (forwardJumpTargetMeasureIndex === -2) {
  340. this.endReached = true;
  341. }
  342. }
  343. }
  344. this.currentMeasureIndex++;
  345. if (this.JumpResponsibleRepetition !== undefined && this.currentMeasureIndex > this.JumpResponsibleRepetition.EndIndex) {
  346. this.jumpResponsibleRepetition = undefined;
  347. }
  348. }
  349. private doBackJump(currentRepetition: Repetition): void {
  350. this.currentMeasureIndex = currentRepetition.getBackwardJumpTarget();
  351. this.currentMeasure = this.manager.MusicSheet.SourceMeasures[this.currentMeasureIndex];
  352. this.currentVoiceEntryIndex = -1;
  353. this.incrementRepetitionIterationCount(currentRepetition);
  354. this.jumpResponsibleRepetition = currentRepetition;
  355. }
  356. private activateCurrentRhythmInstructions(): void {
  357. if (
  358. this.currentMeasure !== undefined &&
  359. this.currentMeasure.FirstInstructionsStaffEntries.length > 0 &&
  360. this.currentMeasure.FirstInstructionsStaffEntries[0] !== undefined
  361. ) {
  362. let instructions: AbstractNotationInstruction[] = this.currentMeasure.FirstInstructionsStaffEntries[0].Instructions;
  363. for (let idx: number = 0, len: number = instructions.length; idx < len; ++idx) {
  364. let abstractNotationInstruction: AbstractNotationInstruction = instructions[idx];
  365. if (abstractNotationInstruction instanceof RhythmInstruction) {
  366. this.manager.MusicSheet.SheetPlaybackSetting.rhythm = (<RhythmInstruction>abstractNotationInstruction).Rhythm;
  367. }
  368. }
  369. }
  370. }
  371. private activateCurrentDynamicOrTempoInstructions(): void {
  372. let timeSortedDynamics: DynamicsContainer[] = this.manager.MusicSheet.TimestampSortedDynamicExpressionsList;
  373. while (
  374. this.currentDynamicEntryIndex > 0 && (
  375. this.currentDynamicEntryIndex >= timeSortedDynamics.length ||
  376. this.CurrentSourceTimestamp.lte(timeSortedDynamics[this.currentDynamicEntryIndex].parMultiExpression().AbsoluteTimestamp)
  377. )
  378. ) {
  379. this.currentDynamicEntryIndex--;
  380. }
  381. while (
  382. this.currentDynamicEntryIndex < timeSortedDynamics.length &&
  383. timeSortedDynamics[this.currentDynamicEntryIndex].parMultiExpression().AbsoluteTimestamp.lt(this.CurrentSourceTimestamp)
  384. ) {
  385. this.currentDynamicEntryIndex++;
  386. }
  387. while (
  388. this.currentDynamicEntryIndex < timeSortedDynamics.length
  389. && timeSortedDynamics[this.currentDynamicEntryIndex].parMultiExpression().AbsoluteTimestamp.Equals(this.CurrentSourceTimestamp)
  390. ) {
  391. let dynamicsContainer: DynamicsContainer = timeSortedDynamics[this.currentDynamicEntryIndex];
  392. let staffIndex: number = dynamicsContainer.staffNumber;
  393. if (this.CurrentSourceTimestamp.Equals(dynamicsContainer.parMultiExpression().AbsoluteTimestamp)) {
  394. if (dynamicsContainer.continuousDynamicExpression !== undefined) {
  395. this.activeDynamicExpressions[staffIndex] = dynamicsContainer.continuousDynamicExpression;
  396. } else if (dynamicsContainer.instantaneousDynamicExpression !== undefined) {
  397. this.activeDynamicExpressions[staffIndex] = dynamicsContainer.instantaneousDynamicExpression;
  398. }
  399. }
  400. this.currentDynamicEntryIndex++;
  401. }
  402. this.currentDynamicChangingExpressions = [];
  403. for (let staffIndex: number = 0; staffIndex < this.activeDynamicExpressions.length; staffIndex++) {
  404. if (this.activeDynamicExpressions[staffIndex] !== undefined) {
  405. let startTime: Fraction;
  406. let endTime: Fraction;
  407. if (this.activeDynamicExpressions[staffIndex] instanceof ContinuousDynamicExpression) {
  408. let continuousDynamic: ContinuousDynamicExpression = <ContinuousDynamicExpression>this.activeDynamicExpressions[staffIndex];
  409. startTime = continuousDynamic.StartMultiExpression.AbsoluteTimestamp;
  410. endTime = continuousDynamic.EndMultiExpression.AbsoluteTimestamp;
  411. if (startTime.lte(this.CurrentSourceTimestamp) && this.CurrentSourceTimestamp.lte(endTime)) {
  412. this.currentDynamicChangingExpressions.push(new DynamicsContainer(continuousDynamic, staffIndex));
  413. }
  414. } else {
  415. let instantaniousDynamic: InstantaniousDynamicExpression = <InstantaniousDynamicExpression>this.activeDynamicExpressions[staffIndex];
  416. if (this.CurrentSourceTimestamp.Equals(instantaniousDynamic.ParentMultiExpression.AbsoluteTimestamp)) {
  417. this.currentDynamicChangingExpressions.push(new DynamicsContainer(instantaniousDynamic, staffIndex));
  418. }
  419. }
  420. }
  421. }
  422. let timeSortedTempoExpressions: MultiTempoExpression[] = this.manager.MusicSheet.TimestampSortedTempoExpressionsList;
  423. while (this.currentTempoEntryIndex > 0 && (
  424. this.currentTempoEntryIndex >= timeSortedTempoExpressions.length
  425. || this.CurrentSourceTimestamp.lte(timeSortedTempoExpressions[this.currentTempoEntryIndex].AbsoluteTimestamp)
  426. )) {
  427. this.currentTempoEntryIndex--;
  428. }
  429. while (
  430. this.currentTempoEntryIndex < timeSortedTempoExpressions.length &&
  431. timeSortedTempoExpressions[this.currentTempoEntryIndex].AbsoluteTimestamp.lt(this.CurrentSourceTimestamp)
  432. ) {
  433. this.currentTempoEntryIndex++;
  434. }
  435. while (
  436. this.currentTempoEntryIndex < timeSortedTempoExpressions.length
  437. && timeSortedTempoExpressions[this.currentTempoEntryIndex].AbsoluteTimestamp.Equals(this.CurrentSourceTimestamp)
  438. ) {
  439. this.activeTempoExpression = timeSortedTempoExpressions[this.currentTempoEntryIndex];
  440. this.currentTempoEntryIndex++;
  441. }
  442. this.currentTempoChangingExpression = undefined;
  443. if (this.activeTempoExpression !== undefined) {
  444. let endTime: Fraction = this.activeTempoExpression.AbsoluteTimestamp;
  445. if (this.activeTempoExpression.ContinuousTempo !== undefined) {
  446. endTime = this.activeTempoExpression.ContinuousTempo.AbsoluteEndTimestamp;
  447. }
  448. if ( this.activeTempoExpression.AbsoluteTimestamp.lte(this.CurrentSourceTimestamp)
  449. || this.CurrentSourceTimestamp.lte(endTime)
  450. ) {
  451. this.currentTempoChangingExpression = this.activeTempoExpression;
  452. }
  453. }
  454. }
  455. private recursiveMove(): void {
  456. this.currentVoiceEntryIndex++;
  457. if (this.currentVoiceEntryIndex === 0) {
  458. this.handleRepetitionsAtMeasureBegin();
  459. this.activateCurrentRhythmInstructions();
  460. }
  461. if (this.currentVoiceEntryIndex >= 0 && this.currentVoiceEntryIndex < this.currentMeasure.VerticalSourceStaffEntryContainers.length) {
  462. let currentContainer: VerticalSourceStaffEntryContainer = this.currentMeasure.VerticalSourceStaffEntryContainers[this.currentVoiceEntryIndex];
  463. this.currentVoiceEntries = this.getVoiceEntries(currentContainer);
  464. this.currentVerticalContainerInMeasureTimestamp = currentContainer.Timestamp;
  465. this.currentTimeStamp = Fraction.plus(this.currentMeasure.AbsoluteTimestamp, this.currentVerticalContainerInMeasureTimestamp);
  466. if (this.currentTimeStamp >= this.manager.MusicSheet.SelectionEnd) {
  467. this.endReached = true;
  468. }
  469. this.activateCurrentDynamicOrTempoInstructions();
  470. return;
  471. }
  472. this.currentEnrolledMeasureTimestamp.Add(this.currentMeasure.Duration);
  473. this.handleRepetitionsAtMeasureEnd();
  474. if (this.currentMeasureIndex >= 0 && this.currentMeasureIndex < this.manager.MusicSheet.SourceMeasures.length) {
  475. this.currentMeasure = this.manager.MusicSheet.SourceMeasures[this.currentMeasureIndex];
  476. this.currentTimeStamp = Fraction.plus(this.currentMeasure.AbsoluteTimestamp, this.currentVerticalContainerInMeasureTimestamp);
  477. this.currentVoiceEntryIndex = -1;
  478. this.recursiveMove();
  479. return;
  480. }
  481. this.currentVerticalContainerInMeasureTimestamp = new Fraction();
  482. this.currentMeasure = undefined;
  483. this.currentVoiceEntries = undefined;
  484. this.endReached = true;
  485. }
  486. private checkEntries(notesOnly: boolean): boolean {
  487. let tlist: VoiceEntry[] = this.CurrentVisibleVoiceEntries();
  488. if (tlist.length > 0) {
  489. if (!notesOnly) { return true; }
  490. for (let idx: number = 0, len: number = tlist.length; idx < len; ++idx) {
  491. let entry: VoiceEntry = tlist[idx];
  492. if (entry.Notes[0].Pitch !== undefined) { return true; }
  493. }
  494. }
  495. return false;
  496. }
  497. private getVisibleEntries(entry: VoiceEntry, visibleEntries: VoiceEntry[]): void {
  498. if (entry.ParentVoice.Visible) {
  499. visibleEntries.push(entry);
  500. }
  501. }
  502. private getAudibleEntries(entry: VoiceEntry, audibleEntries: VoiceEntry[]): void {
  503. if (entry.ParentVoice.Audible) {
  504. audibleEntries.push(entry);
  505. }
  506. }
  507. private getScoreFollowingEntries(entry: VoiceEntry, followingEntries: VoiceEntry[]): void {
  508. if (entry.ParentVoice.Following && entry.ParentVoice.Parent.Following) {
  509. followingEntries.push(entry);
  510. }
  511. }
  512. private getVoiceEntries(container: VerticalSourceStaffEntryContainer): VoiceEntry[] {
  513. let entries: VoiceEntry[] = [];
  514. for (let sourceStaffEntry of container.StaffEntries) {
  515. if (sourceStaffEntry === undefined) { continue; }
  516. for (let voiceEntry of sourceStaffEntry.VoiceEntries) {
  517. entries.push(voiceEntry);
  518. }
  519. }
  520. return entries;
  521. }
  522. }