Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_MidiFile.h 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. //==============================================================================
  20. /**
  21. Reads/writes standard midi format files.
  22. To read a midi file, create a MidiFile object and call its readFrom() method. You
  23. can then get the individual midi tracks from it using the getTrack() method.
  24. To write a file, create a MidiFile object, add some MidiMessageSequence objects
  25. to it using the addTrack() method, and then call its writeTo() method to stream
  26. it out.
  27. @see MidiMessageSequence
  28. @tags{Audio}
  29. */
  30. class JUCE_API MidiFile
  31. {
  32. public:
  33. //==============================================================================
  34. /** Creates an empty MidiFile object. */
  35. MidiFile();
  36. /** Creates a copy of another MidiFile. */
  37. MidiFile (const MidiFile&);
  38. /** Copies from another MidiFile object */
  39. MidiFile& operator= (const MidiFile&);
  40. /** Creates a copy of another MidiFile. */
  41. MidiFile (MidiFile&&);
  42. /** Copies from another MidiFile object */
  43. MidiFile& operator= (MidiFile&&);
  44. //==============================================================================
  45. /** Returns the number of tracks in the file.
  46. @see getTrack, addTrack
  47. */
  48. int getNumTracks() const noexcept;
  49. /** Returns a pointer to one of the tracks in the file.
  50. @returns a pointer to the track, or nullptr if the index is out-of-range
  51. @see getNumTracks, addTrack
  52. */
  53. const MidiMessageSequence* getTrack (int index) const noexcept;
  54. /** Adds a midi track to the file.
  55. This will make its own internal copy of the sequence that is passed-in.
  56. @see getNumTracks, getTrack
  57. */
  58. void addTrack (const MidiMessageSequence& trackSequence);
  59. /** Removes all midi tracks from the file.
  60. @see getNumTracks
  61. */
  62. void clear();
  63. /** Returns the raw time format code that will be written to a stream.
  64. After reading a midi file, this method will return the time-format that
  65. was read from the file's header. It can be changed using the setTicksPerQuarterNote()
  66. or setSmpteTimeFormat() methods.
  67. If the value returned is positive, it indicates the number of midi ticks
  68. per quarter-note - see setTicksPerQuarterNote().
  69. It it's negative, the upper byte indicates the frames-per-second (but negative), and
  70. the lower byte is the number of ticks per frame - see setSmpteTimeFormat().
  71. */
  72. short getTimeFormat() const noexcept;
  73. /** Sets the time format to use when this file is written to a stream.
  74. If this is called, the file will be written as bars/beats using the
  75. specified resolution, rather than SMPTE absolute times, as would be
  76. used if setSmpteTimeFormat() had been called instead.
  77. @param ticksPerQuarterNote e.g. 96, 960
  78. @see setSmpteTimeFormat
  79. */
  80. void setTicksPerQuarterNote (int ticksPerQuarterNote) noexcept;
  81. /** Sets the time format to use when this file is written to a stream.
  82. If this is called, the file will be written using absolute times, rather
  83. than bars/beats as would be the case if setTicksPerBeat() had been called
  84. instead.
  85. @param framesPerSecond must be 24, 25, 29 or 30
  86. @param subframeResolution the sub-second resolution, e.g. 4 (midi time code),
  87. 8, 10, 80 (SMPTE bit resolution), or 100. For millisecond
  88. timing, setSmpteTimeFormat (25, 40)
  89. @see setTicksPerBeat
  90. */
  91. void setSmpteTimeFormat (int framesPerSecond,
  92. int subframeResolution) noexcept;
  93. //==============================================================================
  94. /** Makes a list of all the tempo-change meta-events from all tracks in the midi file.
  95. Useful for finding the positions of all the tempo changes in a file.
  96. @param tempoChangeEvents a list to which all the events will be added
  97. */
  98. void findAllTempoEvents (MidiMessageSequence& tempoChangeEvents) const;
  99. /** Makes a list of all the time-signature meta-events from all tracks in the midi file.
  100. Useful for finding the positions of all the tempo changes in a file.
  101. @param timeSigEvents a list to which all the events will be added
  102. */
  103. void findAllTimeSigEvents (MidiMessageSequence& timeSigEvents) const;
  104. /** Makes a list of all the key-signature meta-events from all tracks in the midi file.
  105. @param keySigEvents a list to which all the events will be added
  106. */
  107. void findAllKeySigEvents (MidiMessageSequence& keySigEvents) const;
  108. /** Returns the latest timestamp in any of the tracks.
  109. (Useful for finding the length of the file).
  110. */
  111. double getLastTimestamp() const;
  112. //==============================================================================
  113. /** Reads a midi file format stream.
  114. After calling this, you can get the tracks that were read from the file by using the
  115. getNumTracks() and getTrack() methods.
  116. The timestamps of the midi events in the tracks will represent their positions in
  117. terms of midi ticks. To convert them to seconds, use the convertTimestampTicksToSeconds()
  118. method.
  119. @param sourceStream the source stream
  120. @param createMatchingNoteOffs if true, any missing note-offs for previous note-ons will
  121. be automatically added at the end of the file by calling
  122. MidiMessageSequence::updateMatchedPairs on each track.
  123. @param midiFileType if not nullptr, the integer at this address will be set
  124. to 0, 1, or 2 depending on the type of the midi file
  125. @returns true if the stream was read successfully
  126. */
  127. bool readFrom (InputStream& sourceStream,
  128. bool createMatchingNoteOffs = true,
  129. int* midiFileType = nullptr);
  130. /** Writes the midi tracks as a standard midi file.
  131. The midiFileType value is written as the file's format type, which can be 0, 1
  132. or 2 - see the midi file spec for more info about that.
  133. @param destStream the destination stream
  134. @param midiFileType the type of midi file
  135. @returns true if the operation succeeded.
  136. */
  137. bool writeTo (OutputStream& destStream, int midiFileType = 1) const;
  138. /** Converts the timestamp of all the midi events from midi ticks to seconds.
  139. This will use the midi time format and tempo/time signature info in the
  140. tracks to convert all the timestamps to absolute values in seconds.
  141. */
  142. void convertTimestampTicksToSeconds();
  143. private:
  144. //==============================================================================
  145. OwnedArray<MidiMessageSequence> tracks;
  146. short timeFormat;
  147. void readNextTrack (const uint8*, int, bool);
  148. bool writeTrack (OutputStream&, const MidiMessageSequence&) const;
  149. JUCE_LEAK_DETECTOR (MidiFile)
  150. };
  151. } // namespace juce