173 lines
7.0 KiB
C++
173 lines
7.0 KiB
C++
#pragma once
|
|
|
|
class FMidiMessageSequence;
|
|
//==============================================================================
|
|
/**
|
|
Reads/writes standard midi format files.
|
|
|
|
To read a midi file, create a MidiFile object and call its readFrom() method. You
|
|
can then get the individual midi tracks from it using the getTrack() method.
|
|
|
|
To write a file, create a MidiFile object, add some MidiMessageSequence objects
|
|
to it using the addTrack() method, and then call its writeTo() method to stream
|
|
it out.
|
|
|
|
@see MidiMessageSequence
|
|
|
|
@tags{Audio}
|
|
*/
|
|
class FMidiFile
|
|
{
|
|
public:
|
|
//==============================================================================
|
|
/** Creates an empty MidiFile object. */
|
|
FMidiFile();
|
|
|
|
/** Creates a copy of another MidiFile. */
|
|
FMidiFile (const FMidiFile&);
|
|
|
|
/** Copies from another MidiFile object */
|
|
FMidiFile& operator= (const FMidiFile&);
|
|
|
|
/** Creates a copy of another MidiFile. */
|
|
FMidiFile (FMidiFile&&);
|
|
|
|
/** Copies from another MidiFile object */
|
|
FMidiFile& operator= (FMidiFile&&);
|
|
|
|
//==============================================================================
|
|
/** Returns the number of tracks in the file.
|
|
@see getTrack, addTrack
|
|
*/
|
|
int getNumTracks() const noexcept;
|
|
|
|
/** Returns a pointer to one of the tracks in the file.
|
|
@returns a pointer to the track, or nullptr if the index is out-of-range
|
|
@see getNumTracks, addTrack
|
|
*/
|
|
const FMidiMessageSequence* getTrack (int index) const noexcept;
|
|
|
|
/** Adds a midi track to the file.
|
|
This will make its own internal copy of the sequence that is passed-in.
|
|
@see getNumTracks, getTrack
|
|
*/
|
|
void addTrack (const FMidiMessageSequence& trackSequence);
|
|
|
|
/** Removes all midi tracks from the file.
|
|
@see getNumTracks
|
|
*/
|
|
void clear();
|
|
|
|
/** Returns the raw time format code that will be written to a stream.
|
|
|
|
After reading a midi file, this method will return the time-format that
|
|
was read from the file's header. It can be changed using the setTicksPerQuarterNote()
|
|
or setSmpteTimeFormat() methods.
|
|
|
|
If the value returned is positive, it indicates the number of midi ticks
|
|
per quarter-note - see setTicksPerQuarterNote().
|
|
|
|
It it's negative, the upper byte indicates the frames-per-second (but negative), and
|
|
the lower byte is the number of ticks per frame - see setSmpteTimeFormat().
|
|
*/
|
|
short getTimeFormat() const noexcept;
|
|
|
|
/** Sets the time format to use when this file is written to a stream.
|
|
|
|
If this is called, the file will be written as bars/beats using the
|
|
specified resolution, rather than SMPTE absolute times, as would be
|
|
used if setSmpteTimeFormat() had been called instead.
|
|
|
|
@param ticksPerQuarterNote e.g. 96, 960
|
|
@see setSmpteTimeFormat
|
|
*/
|
|
void setTicksPerQuarterNote (int ticksPerQuarterNote) noexcept;
|
|
|
|
/** Sets the time format to use when this file is written to a stream.
|
|
|
|
If this is called, the file will be written using absolute times, rather
|
|
than bars/beats as would be the case if setTicksPerBeat() had been called
|
|
instead.
|
|
|
|
@param framesPerSecond must be 24, 25, 29 or 30
|
|
@param subframeResolution the sub-second resolution, e.g. 4 (midi time code),
|
|
8, 10, 80 (SMPTE bit resolution), or 100. For millisecond
|
|
timing, setSmpteTimeFormat (25, 40)
|
|
@see setTicksPerBeat
|
|
*/
|
|
void setSmpteTimeFormat (int framesPerSecond,
|
|
int subframeResolution) noexcept;
|
|
|
|
//==============================================================================
|
|
/** Makes a list of all the tempo-change meta-events from all tracks in the midi file.
|
|
Useful for finding the positions of all the tempo changes in a file.
|
|
@param tempoChangeEvents a list to which all the events will be added
|
|
*/
|
|
void findAllTempoEvents (FMidiMessageSequence& tempoChangeEvents) const;
|
|
|
|
/** Makes a list of all the time-signature meta-events from all tracks in the midi file.
|
|
Useful for finding the positions of all the tempo changes in a file.
|
|
@param timeSigEvents a list to which all the events will be added
|
|
*/
|
|
void findAllTimeSigEvents (FMidiMessageSequence& timeSigEvents) const;
|
|
|
|
/** Makes a list of all the key-signature meta-events from all tracks in the midi file.
|
|
@param keySigEvents a list to which all the events will be added
|
|
*/
|
|
void findAllKeySigEvents (FMidiMessageSequence& keySigEvents) const;
|
|
|
|
/** Returns the latest timestamp in any of the tracks.
|
|
(Useful for finding the length of the file).
|
|
*/
|
|
double getLastTimestamp() const;
|
|
|
|
//==============================================================================
|
|
/** Reads a midi file format stream.
|
|
|
|
After calling this, you can get the tracks that were read from the file by using the
|
|
getNumTracks() and getTrack() methods.
|
|
|
|
The timestamps of the midi events in the tracks will represent their positions in
|
|
terms of midi ticks. To convert them to seconds, use the convertTimestampTicksToSeconds()
|
|
method.
|
|
|
|
@param sourceStream the source stream
|
|
@param createMatchingNoteOffs if true, any missing note-offs for previous note-ons will
|
|
be automatically added at the end of the file by calling
|
|
MidiMessageSequence::updateMatchedPairs on each track.
|
|
@param midiFileType if not nullptr, the integer at this address will be set
|
|
to 0, 1, or 2 depending on the type of the midi file
|
|
|
|
@returns true if the stream was read successfully
|
|
*/
|
|
bool readFrom (FString FilePathName,
|
|
bool createMatchingNoteOffs = true,
|
|
int* midiFileType = nullptr);
|
|
|
|
/** Writes the midi tracks as a standard midi file.
|
|
The midiFileType value is written as the file's format type, which can be 0, 1
|
|
or 2 - see the midi file spec for more info about that.
|
|
|
|
@param destStream the destination stream
|
|
@param midiFileType the type of midi file
|
|
|
|
@returns true if the operation succeeded.
|
|
*/
|
|
bool writeTo (FArchive& destStream, int midiFileType = 1) const;
|
|
|
|
/** Converts the timestamp of all the midi events from midi ticks to seconds.
|
|
|
|
This will use the midi time format and tempo/time signature info in the
|
|
tracks to convert all the timestamps to absolute values in seconds.
|
|
*/
|
|
void convertTimestampTicksToSeconds();
|
|
|
|
private:
|
|
//==============================================================================
|
|
TArray<FMidiMessageSequence*> tracks;
|
|
short timeFormat;
|
|
|
|
void readNextTrack (const uint8*, int, bool);
|
|
bool writeTrack (FArchive&, const FMidiMessageSequence&) const;
|
|
};
|