xmidi.h

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2000  Ryan Nunn
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 // Tab Size = 4
00020 
00021 // Nope, not any more we don't
00022 #if 1
00023 
00024 #ifndef __XMIDI_h_
00025 #define __XMIDI_h_
00026 
00027 #include <string>
00028 #include "common_types.h"
00029 #include "databuf.h"
00030 
00031 
00032 // Conversion types for Midi files
00033 #define XMIDI_CONVERT_NOCONVERSION    0
00034 #define XMIDI_CONVERT_MT32_TO_GM    1
00035 #define XMIDI_CONVERT_MT32_TO_GS    2
00036 #define XMIDI_CONVERT_MT32_TO_GS127   3
00037 #define XMIDI_CONVERT_GS127_TO_GS   4
00038 
00039 // Midi Status Bytes
00040 #define MIDI_STATUS_NOTE_OFF  0x8
00041 #define MIDI_STATUS_NOTE_ON   0x9
00042 #define MIDI_STATUS_AFTERTOUCH  0xA
00043 #define MIDI_STATUS_CONTROLLER  0xB
00044 #define MIDI_STATUS_PROG_CHANGE 0xC
00045 #define MIDI_STATUS_PRESSURE  0xD
00046 #define MIDI_STATUS_PITCH_WHEEL 0xE
00047 #define MIDI_STATUS_SYSEX   0xF
00048 
00049 // XMIDI Controllers
00050 #define XMIDI_CONTROLLER_CHAN_LOCK      0x6e  // Channel Lock
00051 #define XMIDI_CONTROLLER_CHAN_LOCK_PROT   0x6f  // Channel Lock Protect
00052 #define XMIDI_CONTROLLER_VOICE_PROT     0x70  // Voice Protect
00053 #define XMIDI_CONTROLLER_TIMBRE_PROT    0x71  // Timbre Protect
00054 #define XMIDI_CONTROLLER_BANK_CHANGE    0x72  // Bank Change
00055 #define XMIDI_CONTROLLER_IND_CTRL_PREFIX  0x73  // Indirect Controller Prefix
00056 #define XMIDI_CONTROLLER_FOR_LOOP     0x74  // For Loop
00057 #define XMIDI_CONTROLLER_NEXT_BREAK     0x75  // Next/Break
00058 #define XMIDI_CONTROLLER_CLEAR_BB_COUNT   0x76  // Clear Beat/Bar Count
00059 #define XMIDI_CONTROLLER_CALLBACK_TRIG    0x77  // Callback Trigger
00060 #define XMIDI_CONTROLLER_SEQ_BRANCH_INDEX 0x78  // Sequence Branch Index
00061 
00062 
00063 // Maximum number of for loops we'll allow (used by win_midiout)
00064 #define XMIDI_MAX_FOR_LOOP_COUNT  4
00065 
00066 template <class T> class GammaTable;
00067 
00068 struct midi_event
00069 {
00070   int       time;
00071   unsigned char status;
00072 
00073   unsigned char data[2];
00074 
00075   uint32      len;    // Length of SysEx Data
00076   unsigned char *buffer;  // SysEx Data
00077   int       duration; // Duration of note (120 Hz)
00078   midi_event    *next_note; // The next note on the stack
00079   uint32      note_time;  // Time note stops playing (6000th of second)
00080   midi_event  *next;
00081 };
00082 
00083 class NoteStack {
00084   midi_event    *notes;   // Top of the stack
00085   int       polyphony;
00086   int       max_polyphony;
00087 public:
00088 
00089   NoteStack() : notes(0), polyphony(0), max_polyphony(0) { }
00090 
00091   // Just clear it. Don't care about what's actually in it
00092   void clear() {
00093     notes=0;
00094     polyphony=0;
00095     max_polyphony=0;
00096   }
00097 
00098   // Pops the top of the stack if its off_time is <= time (6000th of second)
00099   inline midi_event *PopTime(uint32 time) {
00100     if (notes && notes->note_time <= time)  {
00101       midi_event *note = notes;
00102       notes = note->next_note;
00103       note->next_note = 0;
00104       polyphony--;
00105       return note;
00106     }
00107 
00108     return 0;
00109   }
00110 
00111   // Pops the top of the stack
00112   inline midi_event *Pop() {
00113     if (notes)  {
00114       midi_event *note = notes;
00115       notes = note->next_note;
00116       note->next_note = 0;
00117       polyphony--;
00118       return note;
00119     }
00120 
00121     return 0;
00122   }
00123 
00124   // Pops the top of the stack
00125   inline midi_event *Remove(midi_event *event) {
00126     midi_event *prev = 0;
00127     midi_event *note = notes;
00128     while (note) {
00129 
00130       if (note == event) {
00131         if (prev) prev->next_note = note->next_note;
00132         else notes = note->next_note;
00133         note->next_note = 0;
00134         polyphony--;
00135         return note;
00136       }
00137       prev = note;
00138       note = note->next_note;
00139     }
00140     return 0;
00141   }
00142 
00143   // Finds the note that has same pitch and channel, and pops it
00144   inline midi_event *FindAndPop(midi_event *event) {
00145 
00146     midi_event *prev = 0;
00147     midi_event *note = notes;
00148     while (note) {
00149 
00150       if ((note->status & 0xF) == (event->status & 0xF) && note->data[0] == event->data[0]) {
00151         if (prev) prev->next_note = note->next_note;
00152         else notes = note->next_note;
00153         note->next_note = 0;
00154         polyphony--;
00155         return note;
00156       }
00157       prev = note;
00158       note = note->next_note;
00159     }
00160     return 0;
00161   }
00162 
00163   // Pushes a note onto the top of the stack
00164   inline void Push(midi_event *event) {
00165     event->next_note = notes;
00166     notes = event;
00167     polyphony++;
00168     if (max_polyphony < polyphony) max_polyphony = polyphony;
00169   }
00170 
00171 
00172   inline void Push(midi_event *event, uint32 time) {
00173     event->note_time = time;
00174     event->next_note = 0;
00175 
00176     polyphony++;
00177     if (max_polyphony < polyphony) max_polyphony = polyphony;
00178 
00179     if (!notes || time <= notes->note_time) {
00180       event->next_note = notes;
00181       notes = event;
00182     }
00183     else {
00184       midi_event *prev = notes;
00185       while (prev) {
00186         midi_event *note = prev->next_note;
00187 
00188         if (!note || time <= note->note_time) {
00189           event->next_note = note;
00190           prev->next_note = event;
00191           return;
00192         }
00193         prev = note;
00194       }
00195     }
00196   }
00197 
00198   inline int GetPolyphony() {
00199     return polyphony;
00200   }
00201 
00202   inline int GetMaxPolyphony() {
00203     return max_polyphony;
00204   }
00205 };
00206 
00207 class XMIDIEventList 
00208 {
00209   int       counter;
00210   
00211   // Helper funcs for Write
00212   int       PutVLQ(DataSource *dest, uint32 value);
00213   uint32      ConvertListToMTrk (DataSource *dest);
00214 
00215   static void   DeleteEventList (midi_event *list);
00216 
00217 public:
00218   midi_event    *events;
00219 
00220   // Write this list to a file/buffer
00221   int       Write (const char *filename); 
00222   int       Write (DataSource *dest); 
00223 
00224   // Increments the counter
00225   void      IncerementCounter () { counter++; }
00226 
00227   // Decrement the counter and delete the event list, if possible
00228   void      DecerementCounter ();
00229 };
00230 
00231 class   XMIDI
00232 {
00233 protected:
00234   uint16        num_tracks;
00235 
00236 private:
00237   XMIDIEventList    **events;
00238 
00239   midi_event      *list;
00240   midi_event      *current;
00241   midi_event      *notes_on;
00242   
00243   const static char mt32asgm[128];
00244   const static char mt32asgs[256];
00245   bool        bank127[16];
00246   int         convert_type;
00247   
00248   bool        do_reverb;
00249   bool        do_chorus;
00250   int         chorus_value;
00251   int         reverb_value;
00252 
00253   // Midi Volume Curve Modification
00254   static GammaTable<unsigned char>  VolumeCurve;
00255 
00256 public:
00257   XMIDI(DataSource *source, int pconvert);
00258   ~XMIDI();
00259 
00260   int number_of_tracks() { return num_tracks; }
00261 
00262   // External Event list functions
00263   XMIDIEventList *GetEventList (uint32 track);
00264 
00265   // Not yet implimented
00266   // int apply_patch (int track, DataSource *source);
00267 
00268 private:
00269   XMIDI(); // No default constructor
00270     
00271     struct first_state {      // Status,  Data[0]
00272     midi_event    *patch[16]; // 0xC
00273     midi_event    *bank[16];  // 0xB,   0
00274     midi_event    *pan[16]; // 0xB,   7
00275     midi_event    *vol[16]; // 0xB,   10
00276   };
00277 
00278   // List manipulation
00279   void CreateNewEvent (int time);
00280 
00281   // Variable length quantity
00282   int GetVLQ (DataSource *source, uint32 &quant);
00283   int GetVLQ2 (DataSource *source, uint32 &quant);
00284 
00285   void AdjustTimings(uint32 ppqn);  // This is used by Midi's ONLY!
00286   void ApplyFirstState(first_state &fs, int chan_mask);
00287 
00288   int ConvertNote (const int time, const unsigned char status, DataSource *source, const int size);
00289   int ConvertEvent (const int time, const unsigned char status, DataSource *source, const int size, first_state& fs);
00290   int ConvertSystemMessage (const int time, const unsigned char status, DataSource *source);
00291 
00292   int ConvertFiletoList (DataSource *source, const bool is_xmi, first_state& fs);
00293 
00294   int ExtractTracksFromXmi (DataSource *source);
00295   int ExtractTracksFromMid (DataSource *source, const uint32 ppqn, const int num_tracks, const bool type1);
00296   
00297   int ExtractTracks (DataSource *source);
00298 };
00299 #endif
00300 
00301 #endif

Generated on Mon Jul 9 14:42:44 2007 for ExultEngine by  doxygen 1.5.1