51#define IMF_NOTE_OFF( channel ) 0xe0 | ( ( 1 << ( ( channel ) % ( MAX_AUDIO_CHANNELS ) ) ) )
58#define IMF_NOTE_ON_CHANNEL( channel ) 0xc0 | ( ( 1 << ( ( channel ) % ( MAX_AUDIO_CHANNELS ) ) ) )
59#define IMF_NOTE_ON_NOTE( note ) ( ( note ) & 0xff )
60#define IMF_SET_VOLUME_VALUE( value ) ( ( value ) & 0xff )
66#define IMF_SET_PROGRAM_CHANNEL( channel ) 0x80 | ( ( 1 << ( ( channel ) % ( MAX_AUDIO_CHANNELS ) ) ) )
67#define IMF_SET_PROGRAM_PROGRAM( program ) ( ( program ) & 0xff )
70#define IMF_DELAY( jiffies ) ( ( jiffies ) & 0x7f )
73#define IMF_MAX_STREAM_SIZE ( 16 * MAX_TEMPORARY_STORAGE );
76#define MAX_MIDI_CHANNELS 127
79static int imfStreamPos = 0;
82static int numMidiTracks;
85static int * finishedTrack;
88static int * usedTrack;
91static int * lastNoteOnChannel;
97static int * lastProgramOnMIDITrack;
106static int tempo = 81;
109static char * imfBuffer = NULL;
114static int decode_midi_inside_memory_limits( ) {
146 if ( usedChannel[ imfChannelIndex ] && lastNoteOnChannel[ imfChannelIndex ] == _payload->
MsgData.
NoteOff.
iNote ) {
149 lastNoteOnChannel[ imfChannelIndex ] = 0;
152 usedChannel[ imfChannelIndex ] = 0;
155 imfBuffer[imfStreamPos++] =
IMF_NOTE_OFF( imfChannelIndex );
194 int imfChannelIndex = 0;
201 (lastProgramOnMIDITrack[ _payload->
MsgData.
NoteOn.
iChannel ] != -1) && (lastProgramOnChannel[ imfChannelIndex ] != -1) && (lastProgramOnMIDITrack[ _payload->
MsgData.
NoteOn.
iChannel ] == lastProgramOnChannel[ imfChannelIndex ]) ) {
202 alreadyAllocated = imfChannelIndex;
214 if ( (lastProgramOnMIDITrack[ _payload->
MsgData.
NoteOn.
iChannel ] != -1) && (lastProgramOnChannel[ imfChannelIndex ] != -1) && (lastProgramOnMIDITrack[ _payload->
MsgData.
NoteOn.
iChannel ] == lastProgramOnChannel[ imfChannelIndex ]) ) {
216 if ( ! usedChannel[ imfChannelIndex ] ) {
229 if ( ! usedChannel[ imfChannelIndex ] ) {
237 imfChannelIndex = alreadyAllocated;
245 usedChannel[ imfChannelIndex ] = 1;
247 if ( lastProgramOnMIDITrack[ _payload->
MsgData.
NoteOn.
iChannel ] != lastProgramOnChannel[ imfChannelIndex ] ) {
255 lastProgramOnChannel[ imfChannelIndex ] = lastProgramOnMIDITrack[ _payload->
MsgData.
NoteOn.
iChannel ];
292 return decode_midi_payload_note_off( _payload );
342 ev = _payload->
iType;
349 if ( !_control_only ) {
350 return decode_midi_payload_note_off( _payload );
357 if ( !_control_only ) {
358 return decode_midi_payload_note_on( _payload );
365 return decode_midi_payload_set_program( _payload );
426 return decode_midi_payload_set_tempo( _payload );
442static Variable * midi_load_to_variable(
Environment * _environment,
char * _filename,
char * _alias,
int _bank_expansion ) {
447 finishedTrack = NULL;
449 lastNoteOnChannel = NULL;
451 lastProgramOnMIDITrack = NULL;
468 int midiConversionDone = 0;
479 for( track=0; track<numMidiTracks; ++track ) {
484 finishedTrack =
malloc( numMidiTracks *
sizeof(
int ) );
485 memset( finishedTrack, 0, numMidiTracks *
sizeof(
int ) );
488 usedTrack =
malloc( numMidiTracks *
sizeof(
int ) );
489 memset( usedTrack, 0xff, numMidiTracks *
sizeof(
int ) );
505 int midiPosition = 0;
508 while( ! midiConversionDone ) {
518 for( track=0; track<numMidiTracks; ++track ) {
523 if ( ! finishedTrack[ track ] ) {
530 if ( msg[track].dwAbsPos < midiPosition ) {
534 while( msg[track].dwAbsPos < midiPosition ) {
540 decode_midi_payload( &msg[track], 1 );
546 finishedTrack[track] = 1;
553 if ( !finishedTrack[track] ) {
554 usedTrack[track] = 0;
559 }
else if ( msg[track].dwAbsPos == midiPosition && usedTrack[ track ] ) {
565 decode_midi_payload( &msg[track], 1 );
571 finishedTrack[track] = 1;
577 if ( !finishedTrack[track] ) {
578 usedTrack[track] = 0;
587 for(track=0; track<numMidiTracks; ++track ) {
588 if ( !finishedTrack[track] )
591 if ( track >= numMidiTracks ) {
592 midiConversionDone = 1;
596 if ( ! midiConversionDone ) {
599 for( track=0; track<numMidiTracks; ++track ) {
604 if ( usedTrack[track] ) {
610 if ( msg[track].dwAbsPos > midiPosition ) {
615 decode_midi_payload( &msg[track], 0 );
617 usedTrack[track] = 1;
619 if ( !decode_midi_inside_memory_limits() ) {
627 int midiMinPosition = midiPosition + 0xffffff;
628 for( track=0; track<numMidiTracks; ++track ) {
629 if ( !finishedTrack[track] && msg[track].dwAbsPos < midiMinPosition ) {
630 midiMinPosition = msg[track].
dwAbsPos;
637 if ( midiMinPosition >= midiPosition && midiMinPosition < (midiPosition + 0xffffff) ) {
643 float kMillisecondsPerBPM = (float)( 60 * 1000 ) / (float)tempo;
644 float kMillisecondsPerTick = kMillisecondsPerBPM / ppq;
645 float deltaTimeInMilliseconds = ( midiMinPosition - midiPosition ) * kMillisecondsPerTick;
650 int jiffies = deltaTimeInMilliseconds / 20;
662 while( jiffies > 127 ) {
663 imfBuffer[imfStreamPos++] =
IMF_DELAY( 127 );
666 if ( !decode_midi_inside_memory_limits( ) ) {
671 imfBuffer[imfStreamPos++] =
IMF_DELAY( jiffies );
673 if ( !decode_midi_inside_memory_limits( ) ) {
680 midiPosition = midiMinPosition;
693 for( track=0; track<numMidiTracks; ++track ) {
734 int sidFormat = 0, midiFormat = 0;
746 if ( !sidFormat && !midiFormat ) {
747 result = midi_load_to_variable( _environment, _filename, _alias, _bank_expansion );
754 }
else if ( sidFormat ) {
759 }
else if ( midiFormat ) {
760 result = midi_load_to_variable( _environment, _filename, _alias, _bank_expansion );
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
const char * strstrcase(const char *_x, const char *_y)
Variable * variable_store_buffer(Environment *_environment, char *_destination, unsigned char *_buffer, int _size, int _at)
#define IMF_DELAY(jiffies)
Variable * sid_load_to_variable(Environment *_environment, char *_filename, char *_alias, int _bank_expansion)
#define IMF_SET_PROGRAM_PROGRAM(program)
#define MAX_MIDI_CHANNELS
#define IMF_SET_VOLUME_VALUE(value)
#define IMF_NOTE_ON_NOTE(note)
#define IMF_SET_PROGRAM_CHANNEL(channel)
#define IMF_NOTE_OFF(channel)
Variable * music_load_to_variable(Environment *_environment, char *_filename, char *_alias, int _bank_expansion)
#define IMF_NOTE_ON_CHANNEL(channel)
#define IMF_MAX_STREAM_SIZE
#define MAX_AUDIO_CHANNELS
int midiFileGetPPQN(const MidiFile *_pMF)
MidiFile * midiFileOpen(const char *pFilename)
int midiReadGetNextMessage(const MidiFile *_pMF, int iTrack, MidiMessagePayload *pMsg)
void midiReadInitMessage(MidiMessagePayload *pMsg)
int midiReadGetNumTracks(const MidiFile *_pMF)
void midiReadFreeMessage(MidiMessagePayload *pMsg)
int midiFileClose(MidiFile *_pMF)
struct _MidiMessagePayload MidiMessagePayload
@ metaInfoSequencerSpecific
SIDFILE * sid_file_read(char *_filename, int _reloc_address)
char * sid_file_get_lasterror_string()
union _MidiMessagePayload::_MsgData MsgData
#define MAX_TEMPORARY_STORAGE
#define CRITICAL_CANNOT_LOAD_MIDI_FILE(f)
#define CRITICAL_CANNOT_LOAD_MUSIC(f)
struct _Variable Variable
Structure of a single variable.
#define IMF_INSTRUMENT_CELLO
struct _Environment Environment
Structure of compilation environment.
#define CRITICAL_MIDI_OUT_OF_MEMORY(f)
struct _MidiMessagePayload::_MsgData::_NoteOff NoteOff
struct _MidiMessagePayload::_MsgData::_MetaEvent MetaEvent
struct _MidiMessagePayload::_MsgData::_ChangeProgram ChangeProgram
struct _MidiMessagePayload::_MsgData::_NoteOn NoteOn