OpenTTD Source 20241224-master-gee860a5c8e
MpsMachine Struct Reference

Decoder for "MPS MIDI" format data. More...

Data Structures

struct  Channel
 Starting parameter and playback status for one channel/track. More...
 

Public Types

enum  MpsMidiStatus { MPSMIDIST_SEGMENT_RETURN = 0xFD , MPSMIDIST_SEGMENT_CALL = 0xFE , MPSMIDIST_ENDSONG = 0xFF }
 Overridden MIDI status codes used in the data format. More...
 

Public Member Functions

 MpsMachine (const uint8_t *data, size_t length, MidiFile &target)
 Construct a TTD DOS music format decoder.
 
uint16_t ReadVariableLength (uint32_t &pos)
 Read an SMF-style variable length value (note duration) from songdata.
 
void RestartSong ()
 Prepare for playback from the beginning.
 
uint16_t PlayChannelFrame (MidiFile::DataBlock &outblock, int channel)
 Play one frame of data from one channel.
 
bool PlayFrame (MidiFile::DataBlock &block)
 Play one frame of data into a block.
 
bool PlayInto ()
 Perform playback of whole song.
 

Static Public Member Functions

static void AddMidiData (MidiFile::DataBlock &block, uint8_t b1, uint8_t b2)
 
static void AddMidiData (MidiFile::DataBlock &block, uint8_t b1, uint8_t b2, uint8_t b3)
 

Data Fields

Channel channels [16]
 playback status for each MIDI channel
 
std::vector< uint32_t > segments
 pointers into songdata to repeatable data segments
 
int16_t tempo_ticks
 ticker that increments when playing a frame, decrements before playing a frame
 
int16_t current_tempo
 threshold for actually playing a frame
 
int16_t initial_tempo
 starting tempo of song
 
bool shouldplayflag
 not-end-of-song flag
 
const uint8_t * songdata
 raw data array
 
size_t songdatalen
 length of song data
 
MidiFiletarget
 recipient of data
 

Static Public Attributes

static const int TEMPO_RATE = 148
 Frames/ticks per second for music playback.
 
static const uint8_t programvelocities [128]
 Base note velocities for various GM programs.
 

Detailed Description

Decoder for "MPS MIDI" format data.

This format for MIDI music is also used in a few other Microprose games contemporary with Transport Tycoon.

The song data are usually packed inside a CAT file, with one CAT chunk per song. The song titles are used as names for the CAT chunks.

Unlike the Standard MIDI File format, which is based on the IFF structure, the MPS MIDI format is best described as two linked lists of sub-tracks, the first list contains a number of reusable "segments", and the second list contains the "master tracks". Each list is prefixed with a byte giving the number of elements in the list, and the actual list is just a byte count (BE16 format) for the segment/track followed by the actual data, there is no index as such, so the entire data must be seeked through to build an index.

The actual MIDI data inside each track is almost standard MIDI, prefixing every event with a delay, encoded using the same variable-length format used in SMF. A few status codes have changed meaning in MPS MIDI: 0xFE changes control from master track to a segment, 0xFD returns from a segment to the master track, and 0xFF is used to end the song. (In Standard MIDI all those values must only occur in real-time data.)

As implemented in the original decoder, there is no support for recursively calling segments from segments, i.e. code 0xFE must only occur in a master track, and code 0xFD must only occur in a segment. There are no checks made for this, it's assumed that the only input data will ever be the original game music, not music from other games, or new productions.

Additionally, some program change and controller events are given special meaning, see comments in the code.

Definition at line 497 of file midifile.cpp.

Member Enumeration Documentation

◆ MpsMidiStatus

Overridden MIDI status codes used in the data format.

Enumerator
MPSMIDIST_SEGMENT_RETURN 

resume playing master track from stored position

MPSMIDIST_SEGMENT_CALL 

store current position of master track playback, and begin playback of a segment

MPSMIDIST_ENDSONG 

immediately end the song

Definition at line 523 of file midifile.cpp.

Constructor & Destructor Documentation

◆ MpsMachine()

MpsMachine::MpsMachine ( const uint8_t *  data,
size_t  length,
MidiFile target 
)
inline

Construct a TTD DOS music format decoder.

Parameters
dataBuffer of song data from CAT file, ownership remains with caller
lengthLength of the data buffer in bytes
targetMidiFile object to add decoded data to

Definition at line 547 of file midifile.cpp.

References MpsMachine::Channel::startpos.

Member Function Documentation

◆ AddMidiData() [1/2]

static void MpsMachine::AddMidiData ( MidiFile::DataBlock block,
uint8_t  b1,
uint8_t  b2 
)
inlinestatic

Definition at line 529 of file midifile.cpp.

◆ AddMidiData() [2/2]

static void MpsMachine::AddMidiData ( MidiFile::DataBlock block,
uint8_t  b1,
uint8_t  b2,
uint8_t  b3 
)
inlinestatic

Definition at line 534 of file midifile.cpp.

◆ PlayChannelFrame()

uint16_t MpsMachine::PlayChannelFrame ( MidiFile::DataBlock outblock,
int  channel 
)
inline

◆ PlayFrame()

bool MpsMachine::PlayFrame ( MidiFile::DataBlock block)
inline

Play one frame of data into a block.

Definition at line 744 of file midifile.cpp.

References current_tempo, MpsMachine::Channel::delay, PlayChannelFrame(), MpsMachine::Channel::playpos, shouldplayflag, and TEMPO_RATE.

Referenced by PlayInto().

◆ PlayInto()

bool MpsMachine::PlayInto ( )
inline

Perform playback of whole song.

Definition at line 770 of file midifile.cpp.

References MidiFile::blocks, current_tempo, PlayFrame(), RestartSong(), TEMPO_RATE, MidiFile::tempos, MidiFile::tickdiv, and MidiFile::DataBlock::ticktime.

Referenced by MidiFile::LoadMpsData().

◆ ReadVariableLength()

uint16_t MpsMachine::ReadVariableLength ( uint32_t &  pos)
inline

Read an SMF-style variable length value (note duration) from songdata.

Parameters
posPosition to read from, updated to point to next byte after the value read
Returns
Value read from data stream

Definition at line 586 of file midifile.cpp.

Referenced by PlayChannelFrame(), and RestartSong().

◆ RestartSong()

void MpsMachine::RestartSong ( )
inline

Prepare for playback from the beginning.

Resets the song pointer for every track to the beginning.

Definition at line 600 of file midifile.cpp.

References MpsMachine::Channel::delay, MpsMachine::Channel::playpos, ReadVariableLength(), and MpsMachine::Channel::startpos.

Referenced by PlayInto().

Field Documentation

◆ channels

Channel MpsMachine::channels[16]

playback status for each MIDI channel

Definition at line 508 of file midifile.cpp.

◆ current_tempo

int16_t MpsMachine::current_tempo

threshold for actually playing a frame

Definition at line 511 of file midifile.cpp.

Referenced by PlayFrame(), and PlayInto().

◆ initial_tempo

int16_t MpsMachine::initial_tempo

starting tempo of song

Definition at line 512 of file midifile.cpp.

◆ programvelocities

const uint8_t MpsMachine::programvelocities
static
Initial value:
= {
100, 100, 100, 100, 100, 90, 100, 100, 100, 100, 100, 90, 100, 100, 100, 100,
100, 100, 85, 100, 100, 100, 100, 100, 100, 100, 100, 100, 90, 90, 110, 80,
100, 100, 100, 90, 70, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 90, 100, 100, 100, 100, 100, 100, 120, 100, 100, 100, 120, 100, 127,
100, 100, 90, 100, 100, 100, 100, 100, 100, 95, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 115, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
}

Base note velocities for various GM programs.

Definition at line 805 of file midifile.cpp.

Referenced by PlayChannelFrame().

◆ segments

std::vector<uint32_t> MpsMachine::segments

pointers into songdata to repeatable data segments

Definition at line 509 of file midifile.cpp.

◆ shouldplayflag

bool MpsMachine::shouldplayflag

not-end-of-song flag

Definition at line 513 of file midifile.cpp.

Referenced by PlayFrame().

◆ songdata

const uint8_t* MpsMachine::songdata

raw data array

Definition at line 518 of file midifile.cpp.

◆ songdatalen

size_t MpsMachine::songdatalen

length of song data

Definition at line 519 of file midifile.cpp.

◆ target

MidiFile& MpsMachine::target

recipient of data

Definition at line 520 of file midifile.cpp.

◆ TEMPO_RATE

const int MpsMachine::TEMPO_RATE = 148
static

Frames/ticks per second for music playback.

Definition at line 515 of file midifile.cpp.

Referenced by PlayFrame(), and PlayInto().

◆ tempo_ticks

int16_t MpsMachine::tempo_ticks

ticker that increments when playing a frame, decrements before playing a frame

Definition at line 510 of file midifile.cpp.


The documentation for this struct was generated from the following file: