RepetitionCalculator.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import {SourceMeasure} from "../../VoiceData/SourceMeasure";
  2. import {RepetitionInstruction, RepetitionInstructionEnum, AlignmentType} from "../../VoiceData/Instructions/RepetitionInstruction";
  3. import {RepetitionInstructionComparer} from "../../VoiceData/Instructions/RepetitionInstruction";
  4. import {ArgumentOutOfRangeException} from "../../Exceptions";
  5. import {MusicSheet} from "../../MusicSheet";
  6. export class RepetitionCalculator {
  7. private musicSheet: MusicSheet;
  8. private repetitionInstructions: RepetitionInstruction[] = [];
  9. private currentMeasure: SourceMeasure;
  10. private currentMeasureIndex: number;
  11. /**
  12. * Is called when all repetition symbols have been read from xml.
  13. * Creates the repetition instructions and adds them to the corresponding measure.
  14. * Creates the logical repetition objects for iteration and playback.
  15. * @param musicSheet
  16. * @param repetitionInstructions
  17. */
  18. public calculateRepetitions(musicSheet: MusicSheet, repetitionInstructions: RepetitionInstruction[]): void {
  19. this.musicSheet = <MusicSheet>musicSheet;
  20. this.repetitionInstructions = repetitionInstructions;
  21. const sourceMeasures: SourceMeasure[] = this.musicSheet.SourceMeasures;
  22. for (let idx: number = 0, len: number = this.repetitionInstructions.length; idx < len; ++idx) {
  23. const instruction: RepetitionInstruction = this.repetitionInstructions[idx];
  24. this.currentMeasureIndex = instruction.measureIndex;
  25. this.currentMeasure = sourceMeasures[this.currentMeasureIndex];
  26. this.handleRepetitionInstructions(instruction);
  27. }
  28. // if there are more than one instruction at measure begin or end,
  29. // sort them according to the nesting of the repetitions:
  30. for (let idx: number = 0, len: number = this.musicSheet.SourceMeasures.length; idx < len; ++idx) {
  31. const measure: SourceMeasure = this.musicSheet.SourceMeasures[idx];
  32. if (measure.FirstRepetitionInstructions.length > 1) {
  33. measure.FirstRepetitionInstructions.sort(RepetitionInstructionComparer.Compare);
  34. }
  35. if (measure.LastRepetitionInstructions.length > 1) {
  36. measure.LastRepetitionInstructions.sort(RepetitionInstructionComparer.Compare);
  37. }
  38. }
  39. }
  40. private handleRepetitionInstructions(currentRepetitionInstruction: RepetitionInstruction): boolean {
  41. switch (currentRepetitionInstruction.type) {
  42. case RepetitionInstructionEnum.StartLine:
  43. this.currentMeasure.FirstRepetitionInstructions.push(currentRepetitionInstruction);
  44. break;
  45. case RepetitionInstructionEnum.BackJumpLine:
  46. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  47. break;
  48. case RepetitionInstructionEnum.Ending:
  49. // set ending start or end
  50. if (currentRepetitionInstruction.alignment === AlignmentType.Begin) { // ending start
  51. this.currentMeasure.FirstRepetitionInstructions.push(currentRepetitionInstruction);
  52. } else { // ending end
  53. for (let idx: number = 0, len: number = currentRepetitionInstruction.endingIndices.length; idx < len; ++idx) {
  54. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  55. }
  56. }
  57. break;
  58. case RepetitionInstructionEnum.Segno:
  59. this.currentMeasure.FirstRepetitionInstructions.push(currentRepetitionInstruction);
  60. break;
  61. case RepetitionInstructionEnum.Fine:
  62. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  63. break;
  64. case RepetitionInstructionEnum.ToCoda:
  65. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  66. break;
  67. case RepetitionInstructionEnum.Coda:
  68. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  69. break;
  70. case RepetitionInstructionEnum.DaCapo:
  71. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  72. break;
  73. case RepetitionInstructionEnum.DalSegno:
  74. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  75. break;
  76. case RepetitionInstructionEnum.DalSegnoAlFine:
  77. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  78. break;
  79. case RepetitionInstructionEnum.DaCapoAlFine:
  80. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  81. break;
  82. case RepetitionInstructionEnum.DalSegnoAlCoda:
  83. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  84. break;
  85. case RepetitionInstructionEnum.DaCapoAlCoda:
  86. this.currentMeasure.LastRepetitionInstructions.push(currentRepetitionInstruction);
  87. break;
  88. case RepetitionInstructionEnum.None:
  89. break;
  90. default:
  91. throw new ArgumentOutOfRangeException("currentRepetitionInstruction");
  92. }
  93. return true;
  94. }
  95. }