// -------------- // BuildNewTracks // // This is where the actual work gets done. // // Until all tracks are done, // Scan the tracks to find the next due event // Figure out where the event belongs in the new mapping // Put it there // Add end of track metas to all new tracks that now have any data // // Return TRUE on success // Prints its own error message if something goes wrong // -------------- static BOOL BuildNewTracks(VOID) { LPINTRACKSTATE pInTrack; LPINTRACKSTATE pInTrackFound; UINT idx; DWORD tkNext; TEMPEVENT me; for (;;) { // Find nearest event due // pInTrackFound = NULL; tkNext = 0xFFFFFFFFL; for (idx = 0, pInTrack = ifs.pTracks; idx < ifs.nTracks; ++idx, ++pInTrack) { if ((!(pInTrack->fdwTrack & ITS_F_ENDOFTRK)) && (pInTrack->tkNextEventDue < tkNext)) { tkNext = pInTrack->tkNextEventDue; pInTrackFound = pInTrack; } } // None found? We must be done // if (!pInTrackFound) break; // Ok, get the event header from that track // if (!GetTrackEvent(pInTrackFound, &me)) { I_OutputMsg("MIDI file is corrupt!\n"); return FALSE; } // Don't add end of track event 'til we're done // if (me.abEvent[0] == MIDI_META && me.abEvent[1] == MIDI_META_EOT) continue; if (!AddEventToStream(&me)) { I_OutputMsg("Out of memory building tracks.\n"); return FALSE; } } return TRUE; }
int ConvertToBuffer( DWORD dwFlags, LPCONVERTINFO lpciInfo ) { static INTRACKSTATE *ptsTrack, *ptsFound; static DWORD dwStatus; static DWORD tkNext; static TEMPEVENT teTemp; int nChkErr; DWORD idx; lpciInfo->dwBytesRecorded = 0; if( dwFlags & CONVERTF_RESET ) { dwProgressBytes = 0; dwStatus = 0; memset( &teTemp, 0, sizeof(TEMPEVENT)); ptsTrack = ptsFound = NULL; } // If we were already done, then return with a warning... if( dwStatus & CONVERTF_STATUS_DONE ) { if( bLooped ) { RewindConverter(); dwProgressBytes = 0; dwStatus = 0; } else { return( CONVERTERR_DONE ); } } // The caller is asking us to continue, but we're already hosed because we // previously identified something as corrupt, so complain louder this time. else if( dwStatus & CONVERTF_STATUS_STUCK ) { return( CONVERTERR_STUCK ); } else if( dwStatus & CONVERTF_STATUS_GOTEVENT ) { // Turn off this bit flag dwStatus ^= CONVERTF_STATUS_GOTEVENT; /* * The following code for this case is duplicated from below, and is * designed to handle a "straggler" event, should we have one left over * from previous processing the last time this function was called. */ // Don't add end of track event 'til we're done // if( teTemp.byShortData[0] == MIDI_META && teTemp.byShortData[1] == MIDI_META_EOT ) { if( dwMallocBlocks ) { free( teTemp.pLongData ); dwMallocBlocks--; } } else if(( nChkErr = AddEventToStreamBuffer( &teTemp, lpciInfo )) != CONVERTERR_NOERROR ) { if( nChkErr == CONVERTERR_BUFFERFULL ) { // Do some processing and tell caller that this buffer's full dwStatus |= CONVERTF_STATUS_GOTEVENT; return( CONVERTERR_NOERROR ); } else if( nChkErr == CONVERTERR_METASKIP ) { // We skip by all meta events that aren't tempo changes... } else { DebugPrint( "Unable to add event to stream buffer." ); if( dwMallocBlocks ) { free( teTemp.pLongData ); dwMallocBlocks--; } return( TRUE ); } } } for( ; ; ) { ptsFound = NULL; tkNext = 0xFFFFFFFFL; // Find nearest event due // for( idx = 0, ptsTrack = ifs.pitsTracks; idx < ifs.dwTrackCount; ++idx, ++ptsTrack ) { if(( !( ptsTrack->fdwTrack & ITS_F_ENDOFTRK )) && ( ptsTrack->tkNextEventDue < tkNext )) { tkNext = ptsTrack->tkNextEventDue; ptsFound = ptsTrack; } } // None found? We must be done, so return to the caller with a smile. // if( !ptsFound ) { dwStatus |= CONVERTF_STATUS_DONE; // Need to set return buffer members properly return( CONVERTERR_NOERROR ); } // Ok, get the event header from that track // if( GetTrackEvent( ptsFound, &teTemp )) { // Warn future calls that this converter is stuck at a corrupt spot // and can't continue dwStatus |= CONVERTF_STATUS_STUCK; return( CONVERTERR_CORRUPT ); } // Don't add end of track event 'til we're done // if( teTemp.byShortData[0] == MIDI_META && teTemp.byShortData[1] == MIDI_META_EOT ) { if( dwMallocBlocks ) { free( teTemp.pLongData ); dwMallocBlocks--; } continue; } if(( nChkErr = AddEventToStreamBuffer( &teTemp, lpciInfo )) != CONVERTERR_NOERROR ) { if( nChkErr == CONVERTERR_BUFFERFULL ) { // Do some processing and tell somebody this buffer is full... dwStatus |= CONVERTF_STATUS_GOTEVENT; return( CONVERTERR_NOERROR ); } else if( nChkErr == CONVERTERR_METASKIP ) { // We skip by all meta events that aren't tempo changes... } else { DebugPrint( "Unable to add event to stream buffer." ); if( dwMallocBlocks ) { free( teTemp.pLongData ); dwMallocBlocks--; } return( TRUE ); } } } return( CONVERTERR_NOERROR ); }
/* ConvertToBuffer * * Converts MIDI data from the track buffers setup by a previous call * to ConverterInit(). Converts data until an error is encountered * or the output buffer has been filled with as much event data as possible, * not to exceed maxlen. * * Success/failure and the number of output bytes actually converted will * be returned in the convert_buf structure. */ int ConvertToBuffer (unsigned int flags, convert_buf_t *buf) { static track_state_t *ts, *found; static DWORD status; static DWORD next_time; static temp_event_t tevent; int err; DWORD idx; buf->bytes_in = 0; if (flags & CONVERTF_RESET) { status = 0; memset(&tevent, 0, sizeof(struct _temp_event_s)); ts = found = NULL; } /* If we were already done, then return with a warning */ if (status & CONVERTF_STATUS_DONE) { if (!bgmloop) return CONVERTERR_DONE; RewindConverter(); status = 0; } /* The caller is asking us to continue, but we're already hosed because * we previously identified something as corrupt, so complain louder this * time. */ else if (status & CONVERTF_STATUS_STUCK) { return CONVERTERR_STUCK; } else if (status & CONVERTF_STATUS_GOTEVENT) { /* Turn off this bit flag */ status ^= CONVERTF_STATUS_GOTEVENT; /* The following code for this case is duplicated from below, * and is designed to handle a "straggler" event, should we * have one left over from previous processing the last time * this function was called. */ /* Don't add end of track event until we are done */ if (tevent.shortdata[0] == MIDI_META_EVENT && tevent.shortdata[1] == MIDI_META_EOT) { if (tevent.longdata) { Z_Free(tevent.longdata); tevent.longdata = NULL; } } else if ((err = AddEventToStreamBuffer(&tevent, buf)) != CONVERTERR_NOERROR) { if (err == CONVERTERR_BUFFERFULL) { /* Do some processing and tell caller that this buffer is full */ status |= CONVERTF_STATUS_GOTEVENT; return CONVERTERR_NOERROR; } else if (err == CONVERTERR_METASKIP) { /* We skip by all meta events that aren't tempo changes */ } else { DEBUG_Printf("MIDI: %s\n", err_add_event); if (tevent.longdata) { Z_Free(tevent.longdata); tevent.longdata = NULL; } return err; } } } for ( ; ; ) { found = NULL; next_time = ~(DWORD)0; /* 0xFFFFFFFFL */ /* Find nearest event due */ for (idx = 0, ts = mfs.tracks; idx < mfs.numtracks; ++idx, ++ts) { if (!(ts->status & ITS_F_ENDOFTRK) && ts->next_event_time < next_time) { next_time = ts->next_event_time; found = ts; } } /* None found? We must be done, so return to the caller with a smile. */ if (!found) { status |= CONVERTF_STATUS_DONE; return CONVERTERR_NOERROR; } /* Ok, get the event header from that track */ if (GetTrackEvent(found, &tevent)) { /* Warn future calls that this converter is stuck * at a corrupt spot and can't continue */ status |= CONVERTF_STATUS_STUCK; return CONVERTERR_CORRUPT; } /* Don't add end of track event 'til we're done */ if (tevent.shortdata[0] == MIDI_META_EVENT && tevent.shortdata[1] == MIDI_META_EOT) { if (tevent.longdata) { Z_Free(tevent.longdata); tevent.longdata = NULL; } continue; } if ((err = AddEventToStreamBuffer(&tevent, buf)) != CONVERTERR_NOERROR) { if (err == CONVERTERR_BUFFERFULL) { /* Do some processing and tell caller that this buffer is full */ status |= CONVERTF_STATUS_GOTEVENT; return CONVERTERR_NOERROR; } else if (err == CONVERTERR_METASKIP) { /* We skip by all meta events that aren't tempo changes */ } else { DEBUG_Printf("MIDI: %s\n", err_add_event); if (tevent.longdata) { Z_Free(tevent.longdata); tevent.longdata = NULL; } return err; } } } return CONVERTERR_NOERROR; /* not reached. */ }
// ------------------------- // Mid2StreamConvertToBuffer // // This function converts MIDI data from the track buffers setup by a previous // call to Mid2StreamConverterInit(). It will convert data until an error is // encountered or the output buffer has been filled with as much event data // as possible, not to exceed dwMaxLength. This function can take a couple // bit flags, passed through dwFlags. Information about the success/failure // of this operation and the number of output bytes actually converted will // be returned in the CONVERTINFO structure pointed at by lpciInfo. // ------------------------- int Mid2StreamConvertToBuffer(DWORD dwFlags, LPCONVERTINFO lpciInfo) { static LPINTRACKSTATE pInTrack, pInTrackFound; static DWORD dwStatus; static DWORD tkNext; static TEMPEVENT teTemp; int nChkErr; DWORD idx; lpciInfo->dwBytesRecorded = 0; if (dwFlags & CONVERTF_RESET) { dwProgressBytes = 0; dwStatus = 0; ZeroMemory(&teTemp, sizeof (TEMPEVENT)); pInTrack = pInTrackFound = NULL; } // If we were already done, then return with a warning... if (dwStatus & CONVERTF_STATUS_DONE) { if (bMidiLooped) { Mid2StreamRewindConverter(); dwProgressBytes = 0; dwStatus = 0; } else return CONVERTERR_DONE; } // The caller is asking us to continue, but we're already hosed because we // previously identified something as corrupt, so complain louder this time. else if (dwStatus & CONVERTF_STATUS_STUCK) return CONVERTERR_STUCK; else if (dwStatus & CONVERTF_STATUS_GOTEVENT) { // Turn off this bit flag dwStatus ^= CONVERTF_STATUS_GOTEVENT; // Don't add end of track event 'til we're done // if (teTemp.abEvent[0] == MIDI_META && teTemp.abEvent[1] == MIDI_META_EOT) { } else if ((nChkErr = AddEventToStreamBuffer(&teTemp, lpciInfo)) != CONVERTERR_NOERROR) { if (nChkErr == CONVERTERR_BUFFERFULL) { // Do some processing and tell caller that this buffer's full dwStatus |= CONVERTF_STATUS_GOTEVENT; return CONVERTERR_NOERROR; } else if (nChkErr == CONVERTERR_METASKIP) { // We skip by all meta events that aren't tempo changes... } else { I_Error("Unable to add event to stream buffer."); } } } for (; ;) { pInTrackFound = NULL; tkNext = 0xFFFFFFFFL; // Find nearest event due // for (idx = 0, pInTrack = ifs.pTracks; idx < ifs.nTracks; ++idx, ++pInTrack) { if ((!(pInTrack->fdwTrack & ITS_F_ENDOFTRK)) && (pInTrack->tkNextEventDue < tkNext)) { tkNext = pInTrack->tkNextEventDue; pInTrackFound = pInTrack; } } // None found? We must be done, so return to the caller with a smile. // if (!pInTrackFound) { dwStatus |= CONVERTF_STATUS_DONE; // Need to set return buffer members properly return CONVERTERR_NOERROR; } // Ok, get the event header from that track // if (!GetTrackEvent(pInTrackFound, &teTemp)) { // Warn future calls that this converter is stuck at a corrupt spot // and can't continue dwStatus |= CONVERTF_STATUS_STUCK; return CONVERTERR_CORRUPT; } // Don't add end of track event 'til we're done // if (teTemp.abEvent[0] == MIDI_META && teTemp.abEvent[1] == MIDI_META_EOT) continue; if ((nChkErr = AddEventToStreamBuffer(&teTemp, lpciInfo)) != CONVERTERR_NOERROR) { if (nChkErr == CONVERTERR_BUFFERFULL) { // Do some processing and tell somebody this buffer is full... dwStatus |= CONVERTF_STATUS_GOTEVENT; return CONVERTERR_NOERROR; } else if (nChkErr == CONVERTERR_METASKIP) { // We skip by all meta events that aren't tempo changes... } else { I_Error("Unable to add event to stream buffer."); } } } //return CONVERTERR_NOERROR; }