Verovio
Source code documentation
midifunctor.h
1 // Name: midifunctor.h
3 // Author: David Bauer
4 // Created: 2023
5 // Copyright (c) Authors and others. All rights reserved.
7 
8 #ifndef __VRV_MIDIFUNCTOR_H__
9 #define __VRV_MIDIFUNCTOR_H__
10 
11 #include "functor.h"
12 
13 //----------------------------------------------------------------------------
14 
15 #include "alignfunctor.h"
16 
17 namespace smf {
18 class MidiFile;
19 }
20 
21 namespace vrv {
22 
23 class FeatureExtractor;
24 class Timemap;
25 
26 //----------------------------------------------------------------------------
27 // InitOnsetOffsetFunctor
28 //----------------------------------------------------------------------------
29 
34 public:
40  virtual ~InitOnsetOffsetFunctor() = default;
42 
43  /*
44  * Abstract base implementation
45  */
46  bool ImplementsEndInterface() const override { return true; }
47 
48  /*
49  * Functor interface
50  */
52  FunctorCode VisitChordEnd(Chord *chord) override;
53  FunctorCode VisitLayer(Layer *layer) override;
54  FunctorCode VisitLayerElement(LayerElement *layerElement) override;
55  FunctorCode VisitMeasure(Measure *measure) override;
56  FunctorCode VisitStaff(Staff *staff) override;
57  FunctorCode VisitTabGrpEnd(TabGrp *tabGrp) override;
59 
60 protected:
61  //
62 private:
63  //
64 public:
65  //
66 private:
67  // The current score time in the measure (incremented by each element)
68  Fraction m_currentScoreTime;
69  // The current real time in seconds in the measure (incremented by each element)
70  double m_currentRealTimeSeconds;
71  // The current time alignment parameters
72  AlignMeterParams m_meterParams;
73  // The current notation type
74  data_NOTATIONTYPE m_notationType;
75  // The current tempo
76  double m_currentTempo;
77 };
78 
79 //----------------------------------------------------------------------------
80 // InitMaxMeasureDurationFunctor
81 //----------------------------------------------------------------------------
82 
87 public:
93  virtual ~InitMaxMeasureDurationFunctor() = default;
95 
96  /*
97  * Abstract base implementation
98  */
99  bool ImplementsEndInterface() const override { return true; }
100 
101  /*
102  * Set the tempo
103  */
105  void SetCurrentTempo(double tempo) { m_currentTempo = tempo; }
106  void SetTempoAdjustment(double adjustment) { m_tempoAdjustment = adjustment; }
108 
109  /*
110  * Functor interface
111  */
113  FunctorCode VisitLayerElement(LayerElement *layerElement) override;
114  FunctorCode VisitMeasure(Measure *measure) override;
115  FunctorCode VisitMeasureEnd(Measure *measure) override;
116  FunctorCode VisitScoreDef(ScoreDef *scoreDef) override;
117  FunctorCode VisitTempo(Tempo *tempo) override;
119 
120 protected:
121  //
122 private:
123  // Returns the current tempo with adjustment
124  double GetAdjustedTempo() const { return m_currentTempo * m_tempoAdjustment; }
125 
126 public:
127  //
128 private:
129  // The current score time
130  Fraction m_currentScoreTime;
131  // The current time in seconds
132  double m_currentRealTimeSeconds;
133  // The current tempo
134  double m_currentTempo;
135  // The tempo adjustment
136  double m_tempoAdjustment;
137  // The factor for multibar rests
138  int m_multiRestFactor;
139 };
140 
141 //----------------------------------------------------------------------------
142 // InitTimemapTiesFunctor
143 //----------------------------------------------------------------------------
144 
149 public:
155  virtual ~InitTimemapTiesFunctor() = default;
157 
158  /*
159  * Abstract base implementation
160  */
161  bool ImplementsEndInterface() const override { return false; }
162 
163  /*
164  * Functor interface
165  */
167  FunctorCode VisitTie(Tie *tie) override;
169 
170 protected:
171  //
172 private:
173  //
174 public:
175  //
176 private:
177  //
178 };
179 //----------------------------------------------------------------------------
180 // InitTimemapAdjustNotesFunctor
181 //----------------------------------------------------------------------------
182 
187 public:
193  virtual ~InitTimemapAdjustNotesFunctor() = default;
195 
196  /*
197  * Abstract base implementation
198  */
199  bool ImplementsEndInterface() const override { return true; }
200 
201  /*
202  * Setter for various properties
203  */
205  void SetNoCue(bool noCue) { m_noCue = noCue; }
207 
208  /*
209  * Functor interface
210  */
212  FunctorCode VisitArpeg(Arpeg *arpeg) override;
213  FunctorCode VisitChord(Chord *chord) override;
214  FunctorCode VisitGraceGrpEnd(GraceGrp *graceGrp) override;
215  FunctorCode VisitLayerEnd(Layer *layer) override;
216  FunctorCode VisitMeasure(Measure *measure) override;
217  FunctorCode VisitNote(Note *note) override;
219 
220 protected:
221  //
222 private:
226  struct Grace {
227  std::list<Note *> notes;
228  data_DURATION duration;
229  data_PERCENT time;
230  };
231 
235  void SetGraceNotesFor(Note *refNote);
236 
240  void SetNoteStartStop(Note *note, const Fraction &startTime, const Fraction &stopTime);
241  void SetNoteStart(Note *note, const Fraction &startTime);
242 
243 public:
244  //
245 private:
246  // Indicates whether cue notes should be included
247  bool m_noCue;
248  // Grace note/chord sequence
249  std::list<Grace> m_graces;
250  // Indicates whether the last grace note/chord was accented
251  bool m_accentedGraceNote;
252  // The current tempo
253  double m_currentTempo;
254  // The last (non grace) note
255  Note *m_lastNote;
256 };
257 
258 //----------------------------------------------------------------------------
259 // InitMIDIFunctor
260 //----------------------------------------------------------------------------
261 
265 struct OctaveInfo {
266  const Octave *octave;
267  int staffN;
268  int layerN;
269  int octaveShift;
270  bool isActive;
271 };
272 
279 public:
284  InitMIDIFunctor();
285  virtual ~InitMIDIFunctor() = default;
287 
288  /*
289  * Abstract base implementation
290  */
291  bool ImplementsEndInterface() const override { return false; }
292 
293  /*
294  * Setter and getter for properties
295  */
297  void SetCurrentTempo(double tempo) { m_currentTempo = tempo; }
298  const std::list<OctaveInfo> &GetOctaves() const { return m_octaves; }
300 
301  /*
302  * Functor interface
303  */
305  FunctorCode VisitMeasure(const Measure *measure) override;
306  FunctorCode VisitOctave(const Octave *octave) override;
308 
309 protected:
310  //
311 private:
312  //
313 public:
314  //
315 private:
316  // The current tempo
317  double m_currentTempo;
318  // Octave info which is collected
319  std::list<OctaveInfo> m_octaves;
320 };
321 
322 //----------------------------------------------------------------------------
323 // GenerateMIDIFunctor
324 //----------------------------------------------------------------------------
325 
329 struct MIDINote {
330  int pitch;
331  double duration;
332 };
333 
334 using MIDINoteSequence = std::list<MIDINote>;
335 
339 struct MIDIHeldNote {
340  int m_pitch = 0;
341  double m_stopTime = 0;
342 };
343 
348 public:
353  GenerateMIDIFunctor(smf::MidiFile *midiFile);
354  virtual ~GenerateMIDIFunctor() = default;
356 
357  /*
358  * Abstract base implementation
359  */
360  bool ImplementsEndInterface() const override { return true; }
361 
362  /*
363  * Getter for properties
364  */
366  std::set<int> GetTempoEventTicks() const { return m_tempoEventTicks; }
368 
369  /*
370  * Setter for various properties
371  */
373  void SetChannel(int channel) { m_midiChannel = channel; }
374  void SetControlEvents(bool controlEvents) { m_controlEvents = controlEvents; }
375  void SetNoCue(bool noCue) { m_noCue = noCue; }
376  void SetCurrentTempo(double tempo) { m_currentTempo = tempo; }
377  void SetDeferredNotes(const std::map<const Note *, double> &deferredNotes) { m_deferredNotes = deferredNotes; }
378  void SetLayerN(int layerN) { m_layerN = layerN; }
379  void SetOctaves(const std::list<OctaveInfo> &octaves) { m_octaves = octaves; }
380  void SetStaffN(int staffN) { m_staffN = staffN; }
381  void SetTempoEventTicks(const std::set<int> &ticks) { m_tempoEventTicks = ticks; }
382  void SetTrack(int track) { m_midiTrack = track; }
383  void SetTransSemi(int transSemi) { m_transSemi = transSemi; }
385 
386  /*
387  * Functor interface
388  */
390  FunctorCode VisitBeatRpt(const BeatRpt *beatRpt) override;
391  FunctorCode VisitBTrem(const BTrem *bTrem) override;
392  FunctorCode VisitChord(const Chord *chord) override;
393  FunctorCode VisitFTrem(const FTrem *fTrem) override;
394  FunctorCode VisitHalfmRpt(const HalfmRpt *halfmRpt) override;
395  FunctorCode VisitLayer(const Layer *layer) override;
396  FunctorCode VisitLayerEnd(const Layer *layer) override;
397  FunctorCode VisitLayerElement(const LayerElement *layerElement) override;
398  FunctorCode VisitMeasure(const Measure *measure) override;
399  FunctorCode VisitMRpt(const MRpt *mRpt) override;
400  FunctorCode VisitNote(const Note *note) override;
401  FunctorCode VisitPedal(const Pedal *pedal) override;
402  FunctorCode VisitScoreDef(const ScoreDef *scoreDef) override;
403  FunctorCode VisitStaff(const Staff *staff) override;
404  FunctorCode VisitStaffDef(const StaffDef *staffDef) override;
405  FunctorCode VisitSyl(const Syl *syl) override;
406  FunctorCode VisitVerse(const Verse *verse) override;
408 
409 protected:
410  //
411 private:
415  void DeferMIDINote(const Note *refNote, double shift, bool includeChordSiblings);
416 
420  void HandleOctave(const LayerElement *layerElement);
421 
425  int GetMIDIPitch(const Note *note) { return note->GetMIDIPitch(m_transSemi, m_octaveShift); }
426 
427 public:
428  //
429 private:
430  // The MidiFile we are writing to
431  smf::MidiFile *m_midiFile;
432  // The MIDI track number
433  int m_midiTrack;
434  // The MIDI channel number
435  int m_midiChannel;
436  // The score time from the start of the music to the start of the current measure
437  double m_totalTime;
438  // The current staff number
439  int m_staffN;
440  // The current layer number
441  int m_layerN;
442  // The semi tone transposition for the current track
443  int m_transSemi;
444  // The octave shift for the current track
445  int m_octaveShift;
446  // The current tempo
447  double m_currentTempo;
448  // Tempo events are always added on track 0
449  // This set contains the ticks of all added tempo events to avoid multiple events at the same time
450  std::set<int> m_tempoEventTicks;
451  // The last (non grace) note that was performed
452  const Note *m_lastNote;
453  // Expanded notes due to ornaments and tremolandi
454  std::map<const Note *, MIDINoteSequence> m_expandedNotes;
455  // Deferred notes which start slightly later
456  std::map<const Note *, double> m_deferredNotes;
457  // Octave info which is used to determine the octave shift
458  std::list<OctaveInfo> m_octaves;
459  // Indicates whether cue notes should be included
460  bool m_noCue;
461  // Tablature held notes indexed by (course - 1)
462  std::vector<MIDIHeldNote> m_heldNotes;
463  // A flag indicating we want to process control events
464  bool m_controlEvents;
465 };
466 
467 //----------------------------------------------------------------------------
468 // GenerateTimemapFunctor
469 //----------------------------------------------------------------------------
470 
475 public:
481  virtual ~GenerateTimemapFunctor() = default;
483 
484  /*
485  * Abstract base implementation
486  */
487  bool ImplementsEndInterface() const override { return false; }
488 
489  /*
490  * Set the cue exclusion flag
491  */
492  void SetNoCue(bool noCue) { m_noCue = noCue; }
493 
494  /*
495  * Functor interface
496  */
498  FunctorCode VisitLayerElement(const LayerElement *layerElement) override;
499  FunctorCode VisitMeasure(const Measure *measure) override;
500  FunctorCode VisitMRest(const MRest *mRest) override;
501  FunctorCode VisitMultiRest(const MultiRest *multiRest) override;
502  FunctorCode VisitNote(const Note *note) override;
503  FunctorCode VisitRest(const Rest *rest) override;
505 
506 protected:
507  //
508 private:
512  void AddTimemapEntry(const Object *object);
513 
514 public:
515  //
516 private:
517  // The score time from the start of the piece to the previous barline in quarter notes
518  Fraction m_currentScoreTime;
519  // Real time from the start of the piece to the previous barline in ms
520  double m_currentRealTimeMilliseconds;
521  // The current tempo
522  double m_currentTempo;
523  // Indicates whether cue notes should be included
524  bool m_noCue;
525  // The timemap
526  Timemap *m_timemap;
527 };
528 
529 //----------------------------------------------------------------------------
530 // GenerateFeaturesFunctor
531 //----------------------------------------------------------------------------
532 
537 public:
543  virtual ~GenerateFeaturesFunctor() = default;
545 
546  /*
547  * Abstract base implementation
548  */
549  bool ImplementsEndInterface() const override { return false; }
550 
551  /*
552  * Functor interface
553  */
555  FunctorCode VisitObject(const Object *object) override;
557 
558 protected:
559  //
560 private:
561  //
562 public:
563  //
564 private:
565  // The FeatureExtractor to which extraction is delegated
566  FeatureExtractor *m_extractor;
567 };
568 
569 } // namespace vrv
570 
571 #endif // __VRV_MIDIFUNCTOR_H__
This class represents a collection of notes in the same layer with the same onset time.
Definition: chord.h:44
This abstract class is the base class for all const functors.
Definition: functor.h:126
This abstract class is the base class for all mutable functors that need access to the document.
Definition: functor.h:151
This class is a hold the data and corresponds to the model of a MVC design pattern.
Definition: doc.h:41
Definition: featureextractor.h:21
Definition: fraction.h:19
This abstract class is the base class for all mutable functors.
Definition: functor.h:101
This class exports the object to a JSON feature file.
Definition: midifunctor.h:536
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:549
This class performs the export to a MidiFile.
Definition: midifunctor.h:347
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:360
This class exports the object to a JSON timemap file.
Definition: midifunctor.h:474
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:487
This class initializes the MIDI export.
Definition: midifunctor.h:278
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:291
This class calculates the maximum duration of each measure.
Definition: midifunctor.h:86
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:99
This class prepares Note onsets.
Definition: midifunctor.h:33
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:46
This class adjusts note duration for grace notes and arpeggios.
Definition: midifunctor.h:186
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:199
This class adjusts note timings based on ties.
Definition: midifunctor.h:148
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:161
This class is a base class for the Layer (<layer>) content.
Definition: layerelement.h:51
This class represents a layer in a laid-out score (Doc).
Definition: layer.h:39
This class represents a measure in a page-based score (Doc).
Definition: measure.h:46
This class represents a basic object.
Definition: object.h:61
This class models the MEI <octave> element.
Definition: octave.h:31
This class represents a staff in a laid-out score (Doc).
Definition: staff.h:107
This class models the MEI <tabGrp> element.
Definition: tabgrp.h:23
This class models the MEI <tie> element.
Definition: tie.h:27
This class holds a timemap for exporting onset / offset values.
Definition: timemap.h:52
Regroup pointers to meterSig, mensur and proport objects.
Definition: alignfunctor.h:21
Helper struct for held notes in tablature.
Definition: midifunctor.h:339
Helper struct to store note sequences which replace notes in MIDI output due to expanded ornaments an...
Definition: midifunctor.h:329
Helper struct to store octave data.
Definition: midifunctor.h:265