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 CustomTuning;
24 class FeatureExtractor;
25 class InstrDef;
26 class Timemap;
27 
28 //----------------------------------------------------------------------------
29 // InitOnsetOffsetFunctor
30 //----------------------------------------------------------------------------
31 
36 public:
42  virtual ~InitOnsetOffsetFunctor() = default;
44 
45  /*
46  * Abstract base implementation
47  */
48  bool ImplementsEndInterface() const override { return true; }
49 
50  /*
51  * Functor interface
52  */
54  FunctorCode VisitChordEnd(Chord *chord) override;
55  FunctorCode VisitLayer(Layer *layer) override;
56  FunctorCode VisitLayerElement(LayerElement *layerElement) override;
57  FunctorCode VisitMeasure(Measure *measure) override;
58  FunctorCode VisitStaff(Staff *staff) override;
59  FunctorCode VisitTabGrpEnd(TabGrp *tabGrp) override;
61 
62 protected:
63  //
64 private:
65  //
66 public:
67  //
68 private:
69  // The current score time in the measure (incremented by each element)
70  Fraction m_currentScoreTime;
71  // The current real time in seconds in the measure (incremented by each element)
72  double m_currentRealTimeSeconds;
73  // The current time alignment parameters
74  AlignMeterParams m_meterParams;
75  // The current notation type
76  data_NOTATIONTYPE m_notationType;
77  // The current tempo
78  double m_currentTempo;
79 };
80 
81 //----------------------------------------------------------------------------
82 // InitMaxMeasureDurationFunctor
83 //----------------------------------------------------------------------------
84 
89 public:
95  virtual ~InitMaxMeasureDurationFunctor() = default;
97 
98  /*
99  * Abstract base implementation
100  */
101  bool ImplementsEndInterface() const override { return true; }
102 
103  /*
104  * Set the tempo
105  */
107  void SetCurrentTempo(double tempo) { m_currentTempo = tempo; }
108  void SetTempoAdjustment(double adjustment) { m_tempoAdjustment = adjustment; }
110 
111  /*
112  * Functor interface
113  */
115  FunctorCode VisitLayerElement(LayerElement *layerElement) override;
116  FunctorCode VisitMeasure(Measure *measure) override;
117  FunctorCode VisitMeasureEnd(Measure *measure) override;
118  FunctorCode VisitScoreDef(ScoreDef *scoreDef) override;
119  FunctorCode VisitTempo(Tempo *tempo) override;
121 
122 protected:
123  //
124 private:
125  // Returns the current tempo with adjustment
126  double GetAdjustedTempo() const { return m_currentTempo * m_tempoAdjustment; }
127 
128 public:
129  //
130 private:
131  // The current score time
132  Fraction m_currentScoreTime;
133  // The current time in seconds
134  double m_currentRealTimeSeconds;
135  // The current tempo
136  double m_currentTempo;
137  // The tempo adjustment
138  double m_tempoAdjustment;
139  // The factor for multibar rests
140  int m_multiRestFactor;
141 };
142 
143 //----------------------------------------------------------------------------
144 // InitTimemapTiesFunctor
145 //----------------------------------------------------------------------------
146 
151 public:
157  virtual ~InitTimemapTiesFunctor() = default;
159 
160  /*
161  * Abstract base implementation
162  */
163  bool ImplementsEndInterface() const override { return false; }
164 
165  /*
166  * Functor interface
167  */
169  FunctorCode VisitTie(Tie *tie) override;
171 
172 protected:
173  //
174 private:
175  //
176 public:
177  //
178 private:
179  //
180 };
181 //----------------------------------------------------------------------------
182 // InitTimemapAdjustNotesFunctor
183 //----------------------------------------------------------------------------
184 
189 public:
195  virtual ~InitTimemapAdjustNotesFunctor() = default;
197 
198  /*
199  * Abstract base implementation
200  */
201  bool ImplementsEndInterface() const override { return true; }
202 
203  /*
204  * Setter for various properties
205  */
207  void SetNoCue(bool noCue) { m_noCue = noCue; }
209 
210  /*
211  * Functor interface
212  */
214  FunctorCode VisitArpeg(Arpeg *arpeg) override;
215  FunctorCode VisitChord(Chord *chord) override;
216  FunctorCode VisitGraceGrpEnd(GraceGrp *graceGrp) override;
217  FunctorCode VisitLayerEnd(Layer *layer) override;
218  FunctorCode VisitMeasure(Measure *measure) override;
219  FunctorCode VisitNote(Note *note) override;
221 
222 protected:
223  //
224 private:
228  struct Grace {
229  std::list<Note *> notes;
230  data_DURATION duration;
231  data_PERCENT time;
232  };
233 
237  void SetGraceNotesFor(Note *refNote);
238 
242  void SetNoteOrChordStartStop(Note *note, const Fraction &startTime, const Fraction &stopTime = VRV_UNSET);
243  void SetNoteStartStop(Note *note, const Fraction &startTime, const Fraction &stopTime = VRV_UNSET);
244 
245 public:
246  //
247 private:
248  // Indicates whether cue notes should be included
249  bool m_noCue;
250  // Grace note/chord sequence
251  std::list<Grace> m_graces;
252  // Indicates whether the last grace note/chord was accented
253  bool m_accentedGraceNote;
254  // The current tempo
255  double m_currentTempo;
256  // The last (non grace) note
257  Note *m_lastNote;
258 };
259 
260 //----------------------------------------------------------------------------
261 // InitMIDIFunctor
262 //----------------------------------------------------------------------------
263 
267 struct OctaveInfo {
268  const Octave *octave;
269  int staffN;
270  int layerN;
271  int octaveShift;
272  bool isActive;
273 };
274 
281 public:
286  InitMIDIFunctor();
287  virtual ~InitMIDIFunctor() = default;
289 
290  /*
291  * Abstract base implementation
292  */
293  bool ImplementsEndInterface() const override { return false; }
294 
295  /*
296  * Setter and getter for properties
297  */
299  void SetCurrentTempo(double tempo) { m_currentTempo = tempo; }
300  const std::list<OctaveInfo> &GetOctaves() const { return m_octaves; }
302 
303  /*
304  * Functor interface
305  */
307  FunctorCode VisitMeasure(const Measure *measure) override;
308  FunctorCode VisitOctave(const Octave *octave) override;
310 
311 protected:
312  //
313 private:
314  //
315 public:
316  //
317 private:
318  // The current tempo
319  double m_currentTempo;
320  // Octave info which is collected
321  std::list<OctaveInfo> m_octaves;
322 };
323 
324 //----------------------------------------------------------------------------
325 // GenerateMIDIFunctor
326 //----------------------------------------------------------------------------
327 
331 struct MIDINote {
332  int pitch;
333  double duration;
334 };
335 
336 using MIDINoteSequence = std::list<MIDINote>;
337 
341 struct MIDIHeldNote {
342  int m_pitch = 0;
343  double m_stopTime = 0;
344 };
345 
350 public:
355  GenerateMIDIFunctor(smf::MidiFile *midiFile);
356  virtual ~GenerateMIDIFunctor() = default;
358 
359  /*
360  * Abstract base implementation
361  */
362  bool ImplementsEndInterface() const override { return true; }
363 
364  /*
365  * Getter for properties
366  */
368  std::set<int> GetTempoEventTicks() const { return m_tempoEventTicks; }
370 
371  /*
372  * Setter for various properties
373  */
375  void SetChannel(int channel) { m_midiChannel = channel; }
376  void SetControlEvents(bool controlEvents) { m_controlEvents = controlEvents; }
377  void SetNoCue(bool noCue) { m_noCue = noCue; }
378  void SetCurrentTempo(double tempo) { m_currentTempo = tempo; }
379  void SetDeferredNotes(const std::map<const Note *, double> &deferredNotes) { m_deferredNotes = deferredNotes; }
380  void SetLayerN(int layerN) { m_layerN = layerN; }
381  void SetOctaves(const std::list<OctaveInfo> &octaves) { m_octaves = octaves; }
382  void SetStaffN(int staffN) { m_staffN = staffN; }
383  void SetTempoEventTicks(const std::set<int> &ticks) { m_tempoEventTicks = ticks; }
384  void SetTrack(int track) { m_midiTrack = track; }
385  void SetTransSemi(int transSemi) { m_transSemi = transSemi; }
386  void SetInstrDef(const InstrDef *instrDef) { m_instrDef = instrDef; }
387  void SetCustomTuning(const CustomTuning *customTuning) { m_customTuning = customTuning; }
389 
390  /*
391  * Functor interface
392  */
394  FunctorCode VisitBeatRpt(const BeatRpt *beatRpt) override;
395  FunctorCode VisitBTrem(const BTrem *bTrem) override;
396  FunctorCode VisitChord(const Chord *chord) override;
397  FunctorCode VisitFTrem(const FTrem *fTrem) override;
398  FunctorCode VisitHalfmRpt(const HalfmRpt *halfmRpt) override;
399  FunctorCode VisitLayer(const Layer *layer) override;
400  FunctorCode VisitLayerEnd(const Layer *layer) override;
401  FunctorCode VisitLayerElement(const LayerElement *layerElement) override;
402  FunctorCode VisitMeasure(const Measure *measure) override;
403  FunctorCode VisitMRpt(const MRpt *mRpt) override;
404  FunctorCode VisitNote(const Note *note) override;
405  FunctorCode VisitPedal(const Pedal *pedal) override;
406  FunctorCode VisitScoreDef(const ScoreDef *scoreDef) override;
407  FunctorCode VisitStaff(const Staff *staff) override;
408  FunctorCode VisitStaffDef(const StaffDef *staffDef) override;
409  FunctorCode VisitSyl(const Syl *syl) override;
410  FunctorCode VisitVerse(const Verse *verse) override;
412 
413 protected:
414  //
415 private:
419  void DeferMIDINote(const Note *refNote, double shift, bool includeChordSiblings);
420 
424  void HandleOctave(const LayerElement *layerElement);
425 
429  int GetMIDIPitch(const Note *note);
430 
431 public:
432  //
433 private:
434  // The MidiFile we are writing to
435  smf::MidiFile *m_midiFile;
436  // The MIDI track number
437  int m_midiTrack;
438  // The MIDI channel number
439  int m_midiChannel;
440  // The score time from the start of the music to the start of the current measure
441  double m_totalTime;
442  // The current staff number
443  int m_staffN;
444  // The current layer number
445  int m_layerN;
446  // The semi tone transposition for the current track
447  int m_transSemi;
448  // The octave shift for the current track
449  int m_octaveShift;
450  // The current tempo
451  double m_currentTempo;
452  // Tempo events are always added on track 0
453  // This set contains the ticks of all added tempo events to avoid multiple events at the same time
454  std::set<int> m_tempoEventTicks;
455  // The last (non grace) note that was performed
456  const Note *m_lastNote;
457  // Expanded notes due to ornaments and tremolandi
458  std::map<const Note *, MIDINoteSequence> m_expandedNotes;
459  // Deferred notes which start slightly later
460  std::map<const Note *, double> m_deferredNotes;
461  // Octave info which is used to determine the octave shift
462  std::list<OctaveInfo> m_octaves;
463  // Indicates whether cue notes should be included
464  bool m_noCue;
465  // Tablature held notes indexed by (course - 1)
466  std::vector<MIDIHeldNote> m_heldNotes;
467  // A flag indicating we want to process control events
468  bool m_controlEvents;
469  // Current instrument definition
470  const InstrDef *m_instrDef;
471  // Current custom tuning
472  const CustomTuning *m_customTuning;
473 };
474 
475 //----------------------------------------------------------------------------
476 // GenerateTimemapFunctor
477 //----------------------------------------------------------------------------
478 
483 public:
489  virtual ~GenerateTimemapFunctor() = default;
491 
492  /*
493  * Abstract base implementation
494  */
495  bool ImplementsEndInterface() const override { return false; }
496 
497  /*
498  * Set the cue exclusion flag
499  */
500  void SetNoCue(bool noCue) { m_noCue = noCue; }
501 
502  /*
503  * Functor interface
504  */
506  FunctorCode VisitLayerElement(const LayerElement *layerElement) override;
507  FunctorCode VisitMeasure(const Measure *measure) override;
508  FunctorCode VisitMRest(const MRest *mRest) override;
509  FunctorCode VisitMultiRest(const MultiRest *multiRest) override;
510  FunctorCode VisitNote(const Note *note) override;
511  FunctorCode VisitRest(const Rest *rest) override;
512  FunctorCode VisitStaff(const Staff *staff) override;
514 
515 protected:
516  //
517 private:
521  void AddTimemapEntry(const Object *object);
522 
523 public:
524  //
525 private:
526  // The score time from the start of the piece to the previous barline in quarter notes
527  Fraction m_currentScoreTime;
528  // Real time from the start of the piece to the previous barline in ms
529  double m_currentRealTimeMilliseconds;
530  // The current tempo
531  double m_currentTempo;
532  // Indicates whether cue notes should be included
533  bool m_noCue;
534  // The timemap
535  Timemap *m_timemap;
536 };
537 
538 //----------------------------------------------------------------------------
539 // GenerateFeaturesFunctor
540 //----------------------------------------------------------------------------
541 
546 public:
552  virtual ~GenerateFeaturesFunctor() = default;
554 
555  /*
556  * Abstract base implementation
557  */
558  bool ImplementsEndInterface() const override { return false; }
559 
560  /*
561  * Functor interface
562  */
564  FunctorCode VisitObject(const Object *object) override;
566 
567 protected:
568  //
569 private:
570  //
571 public:
572  //
573 private:
574  // The FeatureExtractor to which extraction is delegated
575  FeatureExtractor *m_extractor;
576 };
577 
578 } // namespace vrv
579 
580 #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:545
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:558
This class performs the export to a MidiFile.
Definition: midifunctor.h:349
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:362
This class exports the object to a JSON timemap file.
Definition: midifunctor.h:482
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:495
This class initializes the MIDI export.
Definition: midifunctor.h:280
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:293
This class calculates the maximum duration of each measure.
Definition: midifunctor.h:88
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:101
This class prepares Note onsets.
Definition: midifunctor.h:35
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:48
This class adjusts note duration for grace notes and arpeggios.
Definition: midifunctor.h:188
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:201
This class adjusts note timings based on ties.
Definition: midifunctor.h:150
bool ImplementsEndInterface() const override
Return true if the functor implements the end interface.
Definition: midifunctor.h:163
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:64
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:110
This class models the MEI <tabGrp> element.
Definition: tabgrp.h:24
This class models the MEI <tie> element.
Definition: tie.h:32
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:341
Helper struct to store note sequences which replace notes in MIDI output due to expanded ornaments an...
Definition: midifunctor.h:331
Helper struct to store octave data.
Definition: midifunctor.h:267