# HG changeset patch # User Matti Hamalainen # Date 1209551396 -10800 # Node ID a4c8552268741e369fbfda910d7b6a6eab721233 # Parent 585f2fc4134e9689d308cdb59a70aa5444fcd7c9# Parent 7591d7534eb87c6d2152e5b54bbff4c9231b5ae5 Automated merge with ssh://hg.atheme.org//hg/audacious-plugins diff -r 7591d7534eb8 -r a4c855226874 src/modplug/Makefile --- a/src/modplug/Makefile Mon Apr 28 18:24:46 2008 +0300 +++ b/src/modplug/Makefile Wed Apr 30 13:29:56 2008 +0300 @@ -22,7 +22,6 @@ load_mtm.cxx \ load_mod.cxx \ load_med.cxx \ - load_mid.cxx \ load_mdl.cxx \ load_it.cxx \ load_far.cxx \ diff -r 7591d7534eb8 -r a4c855226874 src/modplug/load_mid.cxx --- a/src/modplug/load_mid.cxx Mon Apr 28 18:24:46 2008 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1126 +0,0 @@ -/* - * This program is free software; you can redistribute it and modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the license or (at your - * option) any later version. - * - * Authors: Olivier Lapicque -*/ - -////////////////////////////////////////////// -// MIDI loader // -////////////////////////////////////////////// -#include "stdafx.h" -#include "sndfile.h" - -#define MIDI_DRUMCHANNEL 10 -#define MIDI_MAXTRACKS 64 - -UINT gnMidiImportSpeed = 3; -UINT gnMidiPatternLen = 128; - -#pragma pack(1) - -typedef struct MIDIFILEHEADER -{ - CHAR id[4]; // "MThd" = 0x6468544D - DWORD len; // 6 - WORD w1; // 1? - WORD wTrks; // 2? - WORD wDivision; // F0 -} MIDIFILEHEADER; - - -typedef struct MIDITRACKHEADER -{ - CHAR id[4]; // "MTrk" = 0x6B72544D - DWORD len; -} MIDITRACKHEADER; - -static LONG midivolumetolinear(UINT nMidiVolume) -{ - return (nMidiVolume * nMidiVolume << 16) / (127*127); -} - -////////////////////////////////////////////////////////////////////// -// Midi Loader Internal Structures - -#define CHNSTATE_NOTEOFFPENDING 0x0001 - -// MOD Channel State description (current volume, panning, etc...) -typedef struct MODCHANNELSTATE -{ - DWORD flags; // Channel Flags - WORD idlecount; - WORD pitchsrc, pitchdest; // Pitch Bend (current position/new position) - BYTE parent; // Midi Channel parent - BYTE pan; // Channel Panning 0-255 - BYTE note; // Note On # (0=available) -} MODCHANNELSTATE; - -// MIDI Channel State (Midi Channels 0-15) -typedef struct MIDICHANNELSTATE -{ - DWORD flags; // Channel Flags - WORD pitchbend; // Pitch Bend Amount (14-bits unsigned) - BYTE note_on[128]; // If note=on -> MOD channel # + 1 (0 if note=off) - BYTE program; // Channel Midi Program - WORD bank; // 0-16383 - // -- Controllers --------- function ---------- CC# --- range --- init (midi) --- - BYTE pan; // Channel Panning CC10 [0-255] 128 (64) - BYTE expression; // Channel Expression CC11 0-128 128 (127) - BYTE volume; // Channel Volume CC7 0-128 80 (100) - BYTE modulation; // Modulation CC1 0-127 0 - BYTE pitchbendrange;// Pitch Bend Range 64 -} MIDICHANNELSTATE; - -typedef struct MIDITRACK -{ - LPCBYTE ptracks, ptrmax; - DWORD status; - LONG nexteventtime; -} MIDITRACK; - -#pragma pack() - - - -LPCSTR szMidiGroupNames[17] = -{ - "Piano", - "Chromatic Percussion", - "Organ", - "Guitar", - "Bass", - "Strings", - "Ensemble", - "Brass", - "Reed", - "Pipe", - "Synth Lead", - "Synth Pad", - "Synth Effects", - "Ethnic", - "Percussive", - "Sound Effects", - "Percussions" -}; - - -LPCSTR szMidiProgramNames[128] = -{ - // 1-8: Piano - "Acoustic Grand Piano", - "Bright Acoustic Piano", - "Electric Grand Piano", - "Honky-tonk Piano", - "Electric Piano 1", - "Electric Piano 2", - "Harpsichord", - "Clavi", - // 9-16: Chromatic Percussion - "Celesta", - "Glockenspiel", - "Music Box", - "Vibraphone", - "Marimba", - "Xylophone", - "Tubular Bells", - "Dulcimer", - // 17-24: Organ - "Drawbar Organ", - "Percussive Organ", - "Rock Organ", - "Church Organ", - "Reed Organ", - "Accordion", - "Harmonica", - "Tango Accordion", - // 25-32: Guitar - "Acoustic Guitar (nylon)", - "Acoustic Guitar (steel)", - "Electric Guitar (jazz)", - "Electric Guitar (clean)", - "Electric Guitar (muted)", - "Overdriven Guitar", - "Distortion Guitar", - "Guitar harmonics", - // 33-40 Bass - "Acoustic Bass", - "Electric Bass (finger)", - "Electric Bass (pick)", - "Fretless Bass", - "Slap Bass 1", - "Slap Bass 2", - "Synth Bass 1", - "Synth Bass 2", - // 41-48 Strings - "Violin", - "Viola", - "Cello", - "Contrabass", - "Tremolo Strings", - "Pizzicato Strings", - "Orchestral Harp", - "Timpani", - // 49-56 Ensemble - "String Ensemble 1", - "String Ensemble 2", - "SynthStrings 1", - "SynthStrings 2", - "Choir Aahs", - "Voice Oohs", - "Synth Voice", - "Orchestra Hit", - // 57-64 Brass - "Trumpet", - "Trombone", - "Tuba", - "Muted Trumpet", - "French Horn", - "Brass Section", - "SynthBrass 1", - "SynthBrass 2", - // 65-72 Reed - "Soprano Sax", - "Alto Sax", - "Tenor Sax", - "Baritone Sax", - "Oboe", - "English Horn", - "Bassoon", - "Clarinet", - // 73-80 Pipe - "Piccolo", - "Flute", - "Recorder", - "Pan Flute", - "Blown Bottle", - "Shakuhachi", - "Whistle", - "Ocarina", - // 81-88 Synth Lead - "Lead 1 (square)", - "Lead 2 (sawtooth)", - "Lead 3 (calliope)", - "Lead 4 (chiff)", - "Lead 5 (charang)", - "Lead 6 (voice)", - "Lead 7 (fifths)", - "Lead 8 (bass + lead)", - // 89-96 Synth Pad - "Pad 1 (new age)", - "Pad 2 (warm)", - "Pad 3 (polysynth)", - "Pad 4 (choir)", - "Pad 5 (bowed)", - "Pad 6 (metallic)", - "Pad 7 (halo)", - "Pad 8 (sweep)", - // 97-104 Synth Effects - "FX 1 (rain)", - "FX 2 (soundtrack)", - "FX 3 (crystal)", - "FX 4 (atmosphere)", - "FX 5 (brightness)", - "FX 6 (goblins)", - "FX 7 (echoes)", - "FX 8 (sci-fi)", - // 105-112 Ethnic - "Sitar", - "Banjo", - "Shamisen", - "Koto", - "Kalimba", - "Bag pipe", - "Fiddle", - "Shanai", - // 113-120 Percussive - "Tinkle Bell", - "Agogo", - "Steel Drums", - "Woodblock", - "Taiko Drum", - "Melodic Tom", - "Synth Drum", - "Reverse Cymbal", - // 121-128 Sound Effects - "Guitar Fret Noise", - "Breath Noise", - "Seashore", - "Bird Tweet", - "Telephone Ring", - "Helicopter", - "Applause", - "Gunshot" -}; - - -// Notes 25-85 -LPCSTR szMidiPercussionNames[61] = -{ - "Seq Click", - "Brush Tap", - "Brush Swirl", - "Brush Slap", - "Brush Swirl W/Attack", - "Snare Roll", - "Castanet", - "Snare Lo", - "Sticks", - "Bass Drum Lo", - "Open Rim Shot", - "Acoustic Bass Drum", - "Bass Drum 1", - "Side Stick", - "Acoustic Snare", - "Hand Clap", - "Electric Snare", - "Low Floor Tom", - "Closed Hi Hat", - "High Floor Tom", - "Pedal Hi-Hat", - "Low Tom", - "Open Hi-Hat", - "Low-Mid Tom", - "Hi Mid Tom", - "Crash Cymbal 1", - "High Tom", - "Ride Cymbal 1", - "Chinese Cymbal", - "Ride Bell", - "Tambourine", - "Splash Cymbal", - "Cowbell", - "Crash Cymbal 2", - "Vibraslap", - "Ride Cymbal 2", - "Hi Bongo", - "Low Bongo", - "Mute Hi Conga", - "Open Hi Conga", - "Low Conga", - "High Timbale", - "Low Timbale", - "High Agogo", - "Low Agogo", - "Cabasa", - "Maracas", - "Short Whistle", - "Long Whistle", - "Short Guiro", - "Long Guiro", - "Claves", - "Hi Wood Block", - "Low Wood Block", - "Mute Cuica", - "Open Cuica", - "Mute Triangle", - "Open Triangle", - "Shaker", - "Jingle Bell", - "Bell Tree", -}; - - -const WORD kMidiChannelPriority[16] = -{ - 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0xFF80, 0xFF00, - 0xFE00, 0xFDFF, 0xF800, 0xF000, 0xE000, 0xC000, 0x8000, 0x0000, -}; - - -/////////////////////////////////////////////////////////////////////////// -// Helper functions - -static LONG getmidilong(LPCBYTE &p, LPCBYTE pmax) -//---------------------------------------------------------- -{ - DWORD n; - UINT a; - - a = (p < pmax) ? *(p++) : 0; - n = 0; - while (a&0x80) - { - n = (n<<7)|(a&0x7F); - a = (p < pmax) ? *(p++) : 0; - } - return (n<<7)|(LONG)a; -} - - -// Returns MOD tempo and tick multiplier -static int ConvertMidiTempo(int tempo_us, int *pTickMultiplier) -//------------------------------------------------------------- -{ - int nBestModTempo = 120; - int nBestError = 1000000; // 1s - int nBestMultiplier = 1; - int nSpeed = gnMidiImportSpeed; - for (int nModTempo=110; nModTempo<=240; nModTempo++) - { - int tick_us = (2500000) / nModTempo; - int nFactor = (tick_us+tempo_us/2) / tempo_us; - if (!nFactor) nFactor = 1; - int nError = tick_us - tempo_us * nFactor; - if (nError < 0) nError = -nError; - if (nError < nBestError) - { - nBestError = nError; - nBestModTempo = nModTempo; - nBestMultiplier = nFactor; - } - if ((!nError) || ((nError<=1) && (nFactor==64))) break; - } - *pTickMultiplier = nBestMultiplier * nSpeed; - return nBestModTempo; -} - - -//////////////////////////////////////////////////////////////////////////////// -// Maps a midi instrument - returns the instrument number in the file -UINT CSoundFile::MapMidiInstrument(DWORD dwBankProgram, UINT nChannel, UINT nNote) -//-------------------------------------------------------------------------------- -{ - INSTRUMENTHEADER *penv; - UINT nProgram = dwBankProgram & 0x7F; - UINT nBank = dwBankProgram >> 7; - - nNote &= 0x7F; - if (nNote >= 120) return 0; - for (UINT i=1; i<=m_nInstruments; i++) if (Headers[i]) - { - INSTRUMENTHEADER *p = Headers[i]; - // Drum Kit ? - if (nChannel == MIDI_DRUMCHANNEL) - { - if (nNote == p->nMidiDrumKey) return i; - } else - // Melodic Instrument - { - if (nProgram == p->nMidiProgram) return i; - } - } - if ((m_nInstruments + 1 >= MAX_INSTRUMENTS) || (m_nSamples + 1 >= MAX_SAMPLES)) return 0; - penv = new INSTRUMENTHEADER; - if (!penv) return 0; - memset(penv, 0, sizeof(INSTRUMENTHEADER)); - m_nSamples++; - m_nInstruments++; - Headers[m_nInstruments] = penv; - penv->wMidiBank = nBank; - penv->nMidiProgram = nProgram; - penv->nMidiChannel = nChannel; - if (nChannel == MIDI_DRUMCHANNEL) penv->nMidiDrumKey = nNote; - penv->nGlobalVol = 128; - penv->nFadeOut = 1024; - penv->nPan = 128; - penv->nPPC = 5*12; - penv->nNNA = NNA_NOTEOFF; - penv->nDCT = (nChannel == MIDI_DRUMCHANNEL) ? DCT_SAMPLE : DCT_NOTE; - penv->nDNA = DNA_NOTEFADE; - for (UINT j=0; j<120; j++) - { - int mapnote = j+1; - if (nChannel == MIDI_DRUMCHANNEL) - { - mapnote = 61; - /*mapnote = 61 + j - nNote; - if (mapnote < 1) mapnote = 1; - if (mapnote > 120) mapnote = 120;*/ - } - penv->Keyboard[j] = m_nSamples; - penv->NoteMap[j] = (BYTE)mapnote; - } - penv->dwFlags |= ENV_VOLUME; - if (nChannel != MIDI_DRUMCHANNEL) penv->dwFlags |= ENV_VOLSUSTAIN; - penv->VolEnv.nNodes=4; - penv->VolEnv.Ticks[0]=0; - penv->VolEnv.Values[0] = 64; - penv->VolEnv.Ticks[1] = 10; - penv->VolEnv.Values[1] = 64; - penv->VolEnv.Ticks[2] = 15; - penv->VolEnv.Values[2] = 48; - penv->VolEnv.Ticks[3] = 20; - penv->VolEnv.Values[3] = 0; - penv->VolEnv.nSustainStart=1; - penv->VolEnv.nSustainEnd=1; - // Sample - Ins[m_nSamples].nPan = 128; - Ins[m_nSamples].nVolume = 256; - Ins[m_nSamples].nGlobalVol = 64; - if (nChannel != MIDI_DRUMCHANNEL) - { - // GM Midi Name - strcpy((char*)penv->name, (char*)szMidiProgramNames[nProgram]); - strcpy((char*)m_szNames[m_nSamples], (char*)szMidiProgramNames[nProgram]); - } else - { - strcpy((char*)penv->name, "Percussions"); - if ((nNote >= 24) && (nNote <= 84)) - strcpy((char*)m_szNames[m_nSamples], (char*)szMidiPercussionNames[nNote-24]); - else - strcpy((char*)m_szNames[m_nSamples], "Percussions"); - } - return m_nInstruments; -} - - -///////////////////////////////////////////////////////////////// -// Loader Status -#define MIDIGLOBAL_SONGENDED 0x0001 -#define MIDIGLOBAL_FROZEN 0x0002 -#define MIDIGLOBAL_UPDATETEMPO 0x0004 -#define MIDIGLOBAL_UPDATEMASTERVOL 0x0008 -// Midi Globals -#define MIDIGLOBAL_GMSYSTEMON 0x0100 -#define MIDIGLOBAL_XGSYSTEMON 0x0200 - - -BOOL CSoundFile::ReadMID(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- -{ - const MIDIFILEHEADER *pmfh = (const MIDIFILEHEADER *)lpStream; - const MIDITRACKHEADER *pmth; - MODCHANNELSTATE chnstate[MAX_BASECHANNELS]; - MIDICHANNELSTATE midichstate[16]; - MIDITRACK miditracks[MIDI_MAXTRACKS]; - DWORD dwMemPos, dwGlobalFlags, tracks, tempo; - UINT row, pat, midimastervol; - short int division; - int midi_clock, nTempoUsec, nPPQN, nTickMultiplier; - - // Fix import parameters - if (gnMidiImportSpeed < 2) gnMidiImportSpeed = 2; - if (gnMidiImportSpeed > 6) gnMidiImportSpeed = 6; - if (gnMidiPatternLen < 64) gnMidiPatternLen = 64; - if (gnMidiPatternLen > 256) gnMidiPatternLen = 256; - // Detect RMI files - if ((dwMemLength > 12) - && (memcmp(lpStream, "RIFF",4) == 0) - && (memcmp(lpStream, "RMID",4) == 0)) - { - lpStream += 12; - dwMemLength -= 12; - while (dwMemLength > 8) - { - char *id = (char*)lpStream; - DWORD len = *(DWORD *)(lpStream+4); - lpStream += 8; - dwMemLength -= 8; - if ((memcmp(id, "data",4) == 0) && (len < dwMemLength)) - { - dwMemLength = len; - pmfh = (const MIDIFILEHEADER *)lpStream; - break; - } - if (len >= dwMemLength) return FALSE; - lpStream += len; - dwMemLength -= len; - } - } - // MIDI File Header - if ((dwMemLength < sizeof(MIDIFILEHEADER)+8) || (memcmp(pmfh->id, "MThd",4) != 0)) return FALSE; - dwMemPos = 8 + bswapBE32(pmfh->len); - if (dwMemPos >= dwMemLength - 8) return FALSE; - pmth = (MIDITRACKHEADER *)(lpStream+dwMemPos); - tracks = bswapBE16(pmfh->wTrks); - if ((!tracks) || (memcmp(pmth->id, "MTrk", 4) != 0)) return FALSE; - if (tracks > MIDI_MAXTRACKS) tracks = MIDI_MAXTRACKS; - // Reading File... - m_nType = MOD_TYPE_MID; - m_nChannels = 32; - m_nSamples = 0; - m_nInstruments = 0; - m_dwSongFlags |= (SONG_LINEARSLIDES | SONG_INSTRUMENTMODE); - m_szNames[0][0] = 0; - // MIDI->MOD Tempo Conversion - division = bswapBE16(pmfh->wDivision); - if (division < 0) - { - int nFrames = -(division>>8); - int nSubFrames = (division & 0xff); - nPPQN = nFrames * nSubFrames / 2; - if (!nPPQN) nPPQN = 1; - } else - { - nPPQN = (division) ? division : 96; - } - nTempoUsec = 500000 / nPPQN; - tempo = ConvertMidiTempo(nTempoUsec, &nTickMultiplier); - m_nDefaultTempo = tempo; - m_nDefaultSpeed = gnMidiImportSpeed; - m_nDefaultGlobalVolume = 256; - midimastervol = m_nDefaultGlobalVolume; - - // Initializing - memset(Order, 0xFF, sizeof(Order)); - memset(chnstate, 0, sizeof(chnstate)); - memset(miditracks, 0, sizeof(miditracks)); - memset(midichstate, 0, sizeof(midichstate)); - // Initializing Patterns - Order[0] = 0; - for (UINT ipat=0; ipat= dwMemLength) break; - DWORD len = bswapBE32(pmth->len); - if ((memcmp(pmth->id, "MTrk", 4) == 0) && (dwMemPos + 8 + len <= dwMemLength)) - { - // Initializing midi tracks - miditracks[itrk].ptracks = lpStream+dwMemPos+8; - miditracks[itrk].ptrmax = miditracks[itrk].ptracks + len; - miditracks[itrk].nexteventtime = getmidilong(miditracks[itrk].ptracks, miditracks[itrk].ptrmax); - } - dwMemPos += 8 + len; - } - // Initializing midi channels state - for (UINT imidi=0; imidi<16; imidi++) - { - midichstate[imidi].pan = 128; // middle - midichstate[imidi].expression = 128; // no attenuation - midichstate[imidi].volume = 80; // GM specs defaults to 100 - midichstate[imidi].pitchbend = 0x2000; // Pitch Bend Amount - midichstate[imidi].pitchbendrange = 64; // Pitch Bend Range: +/- 2 semitones - } - //////////////////////////////////////////////////////////////////////////// - // Main Midi Sequencer Loop - pat = 0; - row = 0; - midi_clock = 0; - dwGlobalFlags = MIDIGLOBAL_UPDATETEMPO | MIDIGLOBAL_FROZEN; - do - { - // Allocate current pattern if not allocated yet - if (!Patterns[pat]) - { - Patterns[pat] = AllocatePattern(PatternSize[pat], m_nChannels); - if (!Patterns[pat]) break; - } - dwGlobalFlags |= MIDIGLOBAL_SONGENDED; - MODCOMMAND *m = Patterns[pat] + row * m_nChannels; - // Parse Tracks - for (UINT trk=0; trkptracks) && (ptrk->nexteventtime >= 0) && (midi_clock+(nTickMultiplier>>2) >= ptrk->nexteventtime)) - { - if (ptrk->ptracks[0] & 0x80) ptrk->status = *(ptrk->ptracks++); - switch(ptrk->status) - { - ///////////////////////////////////////////////////////////////////// - // End Of Track - case 0x2F: - // End Of Song - case 0xFC: - ptrk->ptracks = NULL; - break; - - ///////////////////////////////////////////////////////////////////// - // SYSEX messages - case 0xF0: - case 0xF7: - { - LONG len = getmidilong(ptrk->ptracks, ptrk->ptrmax); - if ((len > 1) && (ptrk->ptracks + len ptrmax) && (ptrk->ptracks[len-1] == 0xF7)) - { - DWORD dwSysEx1 = 0, dwSysEx2 = 0; - if (len >= 4) dwSysEx1 = (*((DWORD *)(ptrk->ptracks))) & 0x7F7F7F7F; - if (len >= 8) dwSysEx2 = (*((DWORD *)(ptrk->ptracks+4))) & 0x7F7F7F7F; - // GM System On - if ((len == 5) && (dwSysEx1 == 0x01097F7E)) - { - dwGlobalFlags |= MIDIGLOBAL_GMSYSTEMON; - } else - // XG System On - if ((len == 8) && ((dwSysEx1 & 0xFFFFF0FF) == 0x004c1043) && (dwSysEx2 == 0x77007e00)) - { - dwGlobalFlags |= MIDIGLOBAL_XGSYSTEMON; - } else - // Midi Master Volume - if ((len == 7) && (dwSysEx1 == 0x01047F7F)) - { - midimastervol = midivolumetolinear(ptrk->ptracks[5] & 0x7F) >> 8; - if (midimastervol < 16) midimastervol = 16; - dwGlobalFlags |= MIDIGLOBAL_UPDATEMASTERVOL; - } - } - ptrk->ptracks += len; - } - break; - - ////////////////////////////////////////////////////////////////////// - // META-events: FF.code.len.data[len] - case 0xFF: - { - UINT i = *(ptrk->ptracks++); - LONG len = getmidilong(ptrk->ptracks, ptrk->ptrmax); - if (ptrk->ptracks+len > ptrk->ptrmax) - { - // EOF - ptrk->ptracks = NULL; - } else - switch(i) - { - // FF.01 [text]: Song Information - case 0x01: - if (!len) break; - if ((len < 32) && (!m_szNames[0][0])) - { - memcpy(m_szNames[0], ptrk->ptracks, len); - m_szNames[0][len] = 0; - } else - if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F)) - { - m_lpszSongComments = new char [len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, ptrk->ptracks, len); - m_lpszSongComments[len] = 0; - } - } - break; - // FF.02 [text]: Song Copyright - case 0x02: - if (!len) break; - if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F) && (len > 7)) - { - m_lpszSongComments = new char [len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, ptrk->ptracks, len); - m_lpszSongComments[len] = 0; - } - } - break; - // FF.03: Sequence Name - case 0x03: - // FF.06: Sequence Text (->Pattern names) - case 0x06: - if ((len > 1) && (!trk)) - { - UINT k = (len < 32) ? len : 31; - CHAR s[32]; - memcpy(s, ptrk->ptracks, k); - s[k] = 0; - if ((!strnicmp((char*)s, "Copyri", 6)) || (!s[0])) break; - if (i == 0x03) - { - if (!m_szNames[0][0]) strcpy((char*)m_szNames[0], (char*)s); - } - } - break; - // FF.07: Cue Point (marker) - // FF.20: Channel Prefix - // FF.2F: End of Track - case 0x2F: - ptrk->status = 0x2F; - ptrk->ptracks = NULL; - break; - // FF.51 [tttttt]: Set Tempo - case 0x51: - { - LONG l = ptrk->ptracks[0]; - l = (l << 8) | ptrk->ptracks[1]; - l = (l << 8) | ptrk->ptracks[2]; - if (l <= 0) break; - nTempoUsec = l / nPPQN; - if (nTempoUsec < 100) nTempoUsec = 100; - tempo = ConvertMidiTempo(nTempoUsec, &nTickMultiplier); - dwGlobalFlags |= MIDIGLOBAL_UPDATETEMPO; - } - break; - // FF.58: Time Signature - // FF.7F: Sequencer-Specific - } - if (ptrk->ptracks) ptrk->ptracks += len; - } - break; - - ////////////////////////////////////////////////////////////////////////// - // Regular Voice Events - default: - { - UINT midich = (ptrk->status & 0x0F)+1; - UINT midist = ptrk->status & 0xF0; - MIDICHANNELSTATE *pmidich = &midichstate[midich-1]; - UINT note, velocity; - - switch(midist) - { - ////////////////////////////////// - // Note Off: 80.note.velocity - case 0x80: - // Note On: 90.note.velocity - case 0x90: - note = ptrk->ptracks[0] & 0x7F; - velocity = (midist == 0x90) ? (ptrk->ptracks[1] & 0x7F) : 0; - ptrk->ptracks += 2; - // Note On: 90.note.velocity - if (velocity) - { - // Start counting rows - dwGlobalFlags &= ~MIDIGLOBAL_FROZEN; - // if the note is already playing, we reuse this channel - UINT nchn = pmidich->note_on[note]; - if ((nchn) && (chnstate[nchn-1].parent != midich)) nchn = 0; - // or else, we look for an available child channel - if (!nchn) - { - for (UINT i=0; inote_on[note] = nchn; - nchn--; - chnstate[nchn].pitchsrc = pmidich->pitchbend; - chnstate[nchn].pitchdest = pmidich->pitchbend; - chnstate[nchn].flags &= ~CHNSTATE_NOTEOFFPENDING; - chnstate[nchn].idlecount = 0; - chnstate[nchn].note = note+1; - int realnote = note; - if (midich != 10) - { - realnote += (((int)pmidich->pitchbend - 0x2000) * pmidich->pitchbendrange) / (0x2000*32); - if (realnote < 0) realnote = 0; - if (realnote > 119) realnote = 119; - } - m[nchn].note = realnote+1; - m[nchn].instr = MapMidiInstrument(pmidich->program + ((UINT)pmidich->bank << 7), midich, note); - m[nchn].volcmd = VOLCMD_VOLUME; - LONG vol = midivolumetolinear(velocity) >> 8; - vol = (vol * (LONG)pmidich->volume * (LONG)pmidich->expression) >> 13; - if (vol > 256) vol = 256; - if (vol < 4) vol = 4; - m[nchn].vol = (BYTE)(vol>>2); - // Channel Panning - if ((!m[nchn].command) && (pmidich->pan != chnstate[nchn].pan)) - { - chnstate[nchn].pan = pmidich->pan; - m[nchn].param = pmidich->pan; - m[nchn].command = CMD_PANNING8; - } - } - } else - // Note Off; 90.note.00 - if (!(dwGlobalFlags & MIDIGLOBAL_FROZEN)) - { - UINT nchn = pmidich->note_on[note]; - if (nchn) - { - nchn--; - chnstate[nchn].flags |= CHNSTATE_NOTEOFFPENDING; - chnstate[nchn].note = 0; - pmidich->note_on[note] = 0; - } else - { - for (UINT i=0; iptracks += 2; - } - break; - - /////////////////////////////////// - // B0: Control Change - case 0xB0: - { - UINT controller = ptrk->ptracks[0]; - UINT value = ptrk->ptracks[1] & 0x7F; - ptrk->ptracks += 2; - switch(controller) - { - // Bn.00.xx: Bank Select MSB (GS) - case 0x00: - pmidich->bank &= 0x7F; - pmidich->bank |= (value << 7); - break; - // Bn.01.xx: Modulation Depth - case 0x01: - pmidich->pitchbendrange = value; - break; - // Bn.07.xx: Volume - case 0x07: - pmidich->volume = (BYTE)(midivolumetolinear(value) >> 9); - break; - // Bn.0B.xx: Expression - case 0x0B: - pmidich->expression = (BYTE)(midivolumetolinear(value) >> 9); - break; - // Bn.0A.xx: Pan - case 0x0A: - pmidich->pan = value * 2; - break; - // Bn.20.xx: Bank Select LSB (GS) - case 0x20: - pmidich->bank &= (0x7F << 7); - pmidich->bank |= value; - break; - // Bn.79.00: Reset All Controllers (GM) - case 0x79: - pmidich->modulation = 0; - pmidich->expression = 128; - pmidich->pitchbend = 0x2000; - pmidich->pitchbendrange = 64; - // Should also reset pedals (40h-43h), NRP, RPN, aftertouch - break; - // Bn.78.00: All Sound Off (GS) - // Bn.7B.00: All Notes Off (GM) - case 0x78: - case 0x7B: - if (value == 0x00) - { - // All Notes Off - for (UINT k=0; kprogram = ptrk->ptracks[0] & 0x7F; - ptrk->ptracks++; - } - break; - - //////////////////////////////// - // D0: Channel Aftertouch (Polyphonic Key Pressure) - case 0xD0: - { - ptrk->ptracks++; - } - break; - - //////////////////////////////// - // E0: Pitch Bend - case 0xE0: - { - pmidich->pitchbend = (WORD)(((UINT)ptrk->ptracks[1] << 7) + (ptrk->ptracks[0] & 0x7F)); - for (UINT i=0; i<128; i++) if (pmidich->note_on[i]) - { - UINT nchn = pmidich->note_on[i]-1; - if (chnstate[nchn].parent == midich) - { - chnstate[nchn].pitchdest = pmidich->pitchbend; - } - } - ptrk->ptracks+=2; - } - break; - - ////////////////////////////////////// - // F0 & Unsupported commands: skip it - default: - ptrk->ptracks++; - } - }} // switch+default - // Process to next event - if (ptrk->ptracks) - { - ptrk->nexteventtime += getmidilong(ptrk->ptracks, ptrk->ptrmax); - } - if (ptrk->ptracks >= ptrk->ptrmax) ptrk->ptracks = NULL; - } - // End reached? - if (ptrk->ptracks >= ptrk->ptrmax) ptrk->ptracks = NULL; - } - - //////////////////////////////////////////////////////////////////// - // Move to next row - if (!(dwGlobalFlags & MIDIGLOBAL_FROZEN)) - { - // Check MOD channels status - for (UINT ichn=0; ichn= 0x80) param = 0x80; - if (param > 0) - { - m[ichn].param = (BYTE)param; - m[ichn].command = CMD_PORTAMENTODOWN; - } - } else - { - int param = (slideamount * pitchbendrange + ppdiv/2) / ppdiv; - if (param >= 0x80) param = 0x80; - if (param > 0) - { - m[ichn].param = (BYTE)param; - m[ichn].command = CMD_PORTAMENTOUP; - } - } - } - chnstate[ichn].pitchsrc = (WORD)newpitch; - - } else - if (dwGlobalFlags & MIDIGLOBAL_UPDATETEMPO) - { - m[ichn].command = CMD_TEMPO; - m[ichn].param = (BYTE)tempo; - dwGlobalFlags &= ~MIDIGLOBAL_UPDATETEMPO; - } else - if (dwGlobalFlags & MIDIGLOBAL_UPDATEMASTERVOL) - { - m[ichn].command = CMD_GLOBALVOLUME; - m[ichn].param = midimastervol >> 1; // 0-128 - dwGlobalFlags &= ~MIDIGLOBAL_UPDATEMASTERVOL; - } - } - // Check pending noteoff events for m[ichn] - if (!m[ichn].note) - { - if (chnstate[ichn].flags & CHNSTATE_NOTEOFFPENDING) - { - chnstate[ichn].flags &= ~CHNSTATE_NOTEOFFPENDING; - m[ichn].note = 0xFF; - } - // Check State of channel - chnstate[ichn].idlecount++; - if ((chnstate[ichn].note) && (chnstate[ichn].idlecount >= 50)) - { - chnstate[ichn].note = 0; - m[ichn].note = 0xFF; // only if not drum channel ? - } else - if (chnstate[ichn].idlecount >= 500) // 20secs of inactivity - { - chnstate[ichn].idlecount = 0; - chnstate[ichn].parent = 0; - } - } - } - - if ((++row) >= PatternSize[pat]) - { - pat++; - if (pat >= MAX_PATTERNS-1) break; - Order[pat] = pat; - Order[pat+1] = 0xFF; - row = 0; - } - } - - // Increase midi clock - midi_clock += nTickMultiplier; - } while (!(dwGlobalFlags & MIDIGLOBAL_SONGENDED)); - return TRUE; -} - - diff -r 7591d7534eb8 -r a4c855226874 src/modplug/plugin.cxx --- a/src/modplug/plugin.cxx Mon Apr 28 18:24:46 2008 +0300 +++ b/src/modplug/plugin.cxx Wed Apr 30 13:29:56 2008 +0300 @@ -89,6 +89,7 @@ InputPlugin gModPlug = { + /* Common plugin fields */ NULL, NULL, (gchar *)"ModPlug Audio Plugin", @@ -97,6 +98,8 @@ ShowAboutBox, ShowConfigureBox, FALSE, + + /* Input plugin fields */ NULL, NULL, PlayFile, diff -r 7591d7534eb8 -r a4c855226874 src/modplug/sndfile.cxx --- a/src/modplug/sndfile.cxx Mon Apr 28 18:24:46 2008 +0300 +++ b/src/modplug/sndfile.cxx Wed Apr 30 13:29:56 2008 +0300 @@ -165,7 +165,6 @@ && (!ReadAMF(lpStream, dwMemLength)) && (!ReadPSM(lpStream, dwMemLength)) && (!ReadMT2(lpStream, dwMemLength)) - && (!ReadMID(lpStream, dwMemLength)) && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE; #ifdef MMCMP_SUPPORT if (bMMCmp) diff -r 7591d7534eb8 -r a4c855226874 src/modplug/sndfile.h --- a/src/modplug/sndfile.h Mon Apr 28 18:24:46 2008 +0300 +++ b/src/modplug/sndfile.h Wed Apr 30 13:29:56 2008 +0300 @@ -649,9 +649,7 @@ BOOL ReadAMF(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadMT2(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength); BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength); - BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength); // MOD Convert function UINT GetBestSaveFormat() const; UINT GetSaveFormats() const;