xmidi.cc

Go to the documentation of this file.
00001 /*
00002  *
00003  * This program is free software; you can redistribute it and/or
00004  * modify it under the terms of the GNU General Public License
00005  * as published by the Free Software Foundation; either version 2
00006  * of the License, or (at your option) any later version.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program; if not, write to the Free Software
00015  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00016  *
00017  */
00018 
00019 // Nope, not any more we don't
00020 #if 1
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #  include <config.h>
00024 #endif
00025 
00026 #ifndef ALPHA_LINUX_CXX
00027 #  include <cassert>
00028 #  include <cstdio>
00029 #  include <cmath>
00030 #  include <iostream>
00031 #  include <cmath>
00032 #endif
00033 #include <unistd.h>
00034 #include "../files/utils.h"
00035 #include "xmidi.h"
00036 #include "../conf/Configuration.h"
00037 extern  Configuration *config;
00038 
00039 #ifndef UNDER_CE
00040 using std::atof;
00041 using std::atoi;
00042 using std::cerr;
00043 using std::endl;
00044 using std::memcmp;
00045 using std::memcpy;
00046 using std::memset;
00047 using std::size_t;
00048 using std::string;
00049 #endif
00050 
00051 #include "gamma.h"
00052 
00053 // Here's a bit of joy: WIN32 isn't SMP safe if we use operator new and delete.
00054 // On the other hand, nothing else is thread-safe if we use malloc()/free().
00055 // So, we wrap the implementations and use malloc()/calloc()/free() for WIN32, and
00056 // the C++ thread-safe allocator for other platforms.
00057 
00058 template<class T>
00059 inline T* Malloc(size_t num=1)
00060 {
00061 #ifdef WIN32
00062   return static_cast<T*>(std::malloc(num));
00063 #else
00064   return static_cast<T*>(::operator new(num));
00065 #endif
00066 }
00067 
00068 template<class T>
00069 inline T* Calloc(size_t num=1,size_t sz=0)
00070 {
00071   if(!sz)
00072     sz=sizeof(T);
00073 #ifdef WIN32
00074   return static_cast<T*>(std::calloc(num,sz));
00075 #else
00076   size_t  total=sz*num;
00077   T *tmp=Malloc<T>(total);
00078   std::memset(tmp,0,total);
00079   return tmp;
00080 #endif
00081 }
00082 
00083 inline void Free(void *ptr)
00084 {
00085 #ifdef WIN32
00086   std::free(ptr);
00087 #else
00088   ::operator delete(ptr);
00089 #endif
00090 }
00091 
00092 // This is used to correct incorrect patch, vol and pan changes in midi files
00093 // The bias is just a value to used to work out if a vol and pan belong with a 
00094 // patch change. This is to ensure that the default state of a midi file is with
00095 // the tracks centred, unless the first patch change says otherwise.
00096 #define PATCH_VOL_PAN_BIAS  5
00097 
00098 
00099 // This is a default set of patches to convert from MT32 to GM
00100 // The index is the MT32 Patch nubmer and the value is the GM Patch
00101 // This is only suitable for music that doesn'tdo timbre changes
00102 // XMIDIs that contain Timbre changes will not convert properly
00103 const char XMIDI::mt32asgm[128] = {
00104   0,  // 0  Piano 1
00105   1,  // 1  Piano 2
00106   2,  // 2  Piano 3 (synth)
00107   4,  // 3  EPiano 1
00108   4,  // 4  EPiano 2
00109   5,  // 5  EPiano 3
00110   5,  // 6  EPiano 4
00111   3,  // 7  Honkytonk
00112   16, // 8  Organ 1
00113   17, // 9  Organ 2
00114   18, // 10 Organ 3
00115   16, // 11 Organ 4
00116   19, // 12 Pipe Organ 1
00117   19, // 13 Pipe Organ 2
00118   19, // 14 Pipe Organ 3
00119   21, // 15 Accordion
00120   6,  // 16 Harpsichord 1
00121   6,  // 17 Harpsichord 2
00122   6,  // 18 Harpsichord 3
00123   7,  // 19 Clavinet 1
00124   7,  // 20 Clavinet 2
00125   7,  // 21 Clavinet 3
00126   8,  // 22 Celesta 1
00127   8,  // 23 Celesta 2
00128   62, // 24 Synthbrass 1 (62)
00129   63, // 25 Synthbrass 2 (63)
00130   62, // 26 Synthbrass 3 Bank 8
00131   63, // 27 Synthbrass 4 Bank 8
00132   38, // 28 Synthbass 1
00133   39, // 29 Synthbass 2
00134   38, // 30 Synthbass 3 Bank 8
00135   39, // 31 Synthbass 4 Bank 8
00136   88, // 32 Fantasy
00137   90, // 33 Harmonic Pan - No equiv closest is polysynth(90) :(
00138   52, // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)???
00139   92, // 35 Glass
00140   97, // 36 Soundtrack
00141   99, // 37 Atmosphere
00142   14, // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is!
00143   54, // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111)
00144   98, // 40 EchoBell, no real equiv, sounds like Crystal(98)
00145   96, // 41 IceRain
00146   68, // 42 Oboe 2001, no equiv, just patching it to normal oboe(68)
00147   95, // 43 EchoPans, no equiv, setting to SweepPad
00148   81, // 44 DoctorSolo Bank 8
00149   87, // 45 SchoolDaze, no real equiv
00150   112,  // 46 Bell Singer
00151   80, // 47 SquareWave
00152   48, // 48 Strings 1
00153   48, // 49 Strings 2 - should be 49
00154   44, // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50
00155   45, // 51 Pizzicato Strings
00156   40, // 52 Violin 1
00157   40, // 53 Violin 2 ? Viola
00158   42, // 54 Cello 1
00159   42, // 55 Cello 2
00160   43, // 56 Contrabass
00161   46, // 57 Harp 1
00162   46, // 58 Harp 2
00163   24, // 59 Guitar 1 (Nylon)
00164   25, // 60 Guitar 2 (Steel)
00165   26, // 61 Elec Guitar 1
00166   27, // 62 Elec Guitar 2
00167   104,  // 63 Sitar
00168   32, // 64 Acou Bass 1
00169   32, // 65 Acou Bass 2
00170   33, // 66 Elec Bass 1
00171   34, // 67 Elec Bass 2
00172   36, // 68 Slap Bass 1
00173   37, // 69 Slap Bass 2
00174   35, // 70 Fretless Bass 1
00175   35, // 71 Fretless Bass 2
00176   73, // 72 Flute 1
00177   73, // 73 Flute 2
00178   72, // 74 Piccolo 1
00179   72, // 75 Piccolo 2
00180   74, // 76 Recorder
00181   75, // 77 Pan Pipes
00182   64, // 78 Sax 1
00183   65, // 79 Sax 2
00184   66, // 80 Sax 3
00185   67, // 81 Sax 4
00186   71, // 82 Clarinet 1
00187   71, // 83 Clarinet 2
00188   68, // 84 Oboe
00189   69, // 85 English Horn (Cor Anglais)
00190   70, // 86 Bassoon
00191   22, // 87 Harmonica
00192   56, // 88 Trumpet 1
00193   56, // 89 Trumpet 2
00194   57, // 90 Trombone 1
00195   57, // 91 Trombone 2
00196   60, // 92 French Horn 1
00197   60, // 93 French Horn 2
00198   58, // 94 Tuba  
00199   61, // 95 Brass Section 1
00200   61, // 96 Brass Section 2
00201   11, // 97 Vibes 1
00202   11, // 98 Vibes 2
00203   99, // 99 Syn Mallet Bank 1
00204   112,  // 100  WindBell no real equiv Set to TinkleBell(112)
00205   9,  // 101  Glockenspiel
00206   14, // 102  Tubular Bells
00207   13, // 103  Xylophone
00208   12, // 104  Marimba
00209   107,  // 105  Koto
00210   111,  // 106  Sho?? set to Shanai(111)
00211   77, // 107  Shakauhachi
00212   78, // 108  Whistle 1
00213   78, // 109  Whistle 2
00214   76, // 110  Bottle Blow
00215   76, // 111  Breathpipe no real equiv set to bottle blow(76)
00216   47, // 112  Timpani
00217   117,  // 113  Melodic Tom
00218   116,  // 114  Deap Snare no equiv, set to Taiko(116)
00219   118,  // 115  Electric Perc 1
00220   118,  // 116  Electric Perc 2
00221   116,  // 117  Taiko
00222   115,  // 118  Taiko Rim, no real equiv, set to Woodblock(115)
00223   119,  // 119  Cymbal, no real equiv, set to reverse cymbal(119)
00224   115,  // 120  Castanets, no real equiv, in GM set to Woodblock(115)
00225   112,  // 121  Triangle, no real equiv, set to TinkleBell(112)
00226   55, // 122  Orchestral Hit
00227   124,  // 123  Telephone
00228   123,  // 124  BirdTweet
00229   94, // 125  Big Notes Pad no equiv, set to halo pad (94)
00230   98, // 126  Water Bell set to Crystal Pad(98)
00231   121 // 127  Jungle Tune set to Breath Noise
00232 };
00233 
00234 // Same as above, except include patch changes
00235 // so GS instruments can be used
00236 const char XMIDI::mt32asgs[256] = {
00237   0, 0, // 0  Piano 1
00238   1, 0, // 1  Piano 2
00239   2, 0, // 2  Piano 3 (synth)
00240   4, 0, // 3  EPiano 1
00241   4, 0, // 4  EPiano 2
00242   5, 0, // 5  EPiano 3
00243   5, 0, // 6  EPiano 4
00244   3, 0, // 7  Honkytonk
00245   16, 0,  // 8  Organ 1
00246   17, 0,  // 9  Organ 2
00247   18, 0,  // 10 Organ 3
00248   16, 0,  // 11 Organ 4
00249   19, 0,  // 12 Pipe Organ 1
00250   19, 0,  // 13 Pipe Organ 2
00251   19, 0,  // 14 Pipe Organ 3
00252   21, 0,  // 15 Accordion
00253   6, 0, // 16 Harpsichord 1
00254   6, 0, // 17 Harpsichord 2
00255   6, 0, // 18 Harpsichord 3
00256   7, 0, // 19 Clavinet 1
00257   7, 0, // 20 Clavinet 2
00258   7, 0, // 21 Clavinet 3
00259   8, 0, // 22 Celesta 1
00260   8, 0, // 23 Celesta 2
00261   62, 0,  // 24 Synthbrass 1 (62)
00262   63, 0,  // 25 Synthbrass 2 (63)
00263   62, 0,  // 26 Synthbrass 3 Bank 8
00264   63, 0,  // 27 Synthbrass 4 Bank 8
00265   38, 0,  // 28 Synthbass 1
00266   39, 0,  // 29 Synthbass 2
00267   38, 0,  // 30 Synthbass 3 Bank 8
00268   39, 0,  // 31 Synthbass 4 Bank 8
00269   88, 0,  // 32 Fantasy
00270   90, 0,  // 33 Harmonic Pan - No equiv closest is polysynth(90) :(
00271   52, 0,  // 34 Choral ?? Currently set to SynthVox(54). Should it be ChoirAhhs(52)???
00272   92, 0,  // 35 Glass
00273   97, 0,  // 36 Soundtrack
00274   99, 0,  // 37 Atmosphere
00275   14, 0,  // 38 Warmbell, sounds kind of like crystal(98) perhaps Tubular Bells(14) would be better. It is!
00276   54, 0,  // 39 FunnyVox, sounds alot like Bagpipe(109) and Shania(111)
00277   98, 0,  // 40 EchoBell, no real equiv, sounds like Crystal(98)
00278   96, 0,  // 41 IceRain
00279   68, 0,  // 42 Oboe 2001, no equiv, just patching it to normal oboe(68)
00280   95, 0,  // 43 EchoPans, no equiv, setting to SweepPad
00281   81, 0,  // 44 DoctorSolo Bank 8
00282   87, 0,  // 45 SchoolDaze, no real equiv
00283   112, 0, // 46 Bell Singer
00284   80, 0,  // 47 SquareWave
00285   48, 0,  // 48 Strings 1
00286   48, 0,  // 49 Strings 2 - should be 49
00287   44, 0,  // 50 Strings 3 (Synth) - Experimental set to Tremollo Strings - should be 50
00288   45, 0,  // 51 Pizzicato Strings
00289   40, 0,  // 52 Violin 1
00290   40, 0,  // 53 Violin 2 ? Viola
00291   42, 0,  // 54 Cello 1
00292   42, 0,  // 55 Cello 2
00293   43, 0,  // 56 Contrabass
00294   46, 0,  // 57 Harp 1
00295   46, 0,  // 58 Harp 2
00296   24, 0,  // 59 Guitar 1 (Nylon)
00297   25, 0,  // 60 Guitar 2 (Steel)
00298   26, 0,  // 61 Elec Guitar 1
00299   27, 0,  // 62 Elec Guitar 2
00300   104, 0, // 63 Sitar
00301   32, 0,  // 64 Acou Bass 1
00302   32, 0,  // 65 Acou Bass 2
00303   33, 0,  // 66 Elec Bass 1
00304   34, 0,  // 67 Elec Bass 2
00305   36, 0,  // 68 Slap Bass 1
00306   37, 0,  // 69 Slap Bass 2
00307   35, 0,  // 70 Fretless Bass 1
00308   35, 0,  // 71 Fretless Bass 2
00309   73, 0,  // 72 Flute 1
00310   73, 0,  // 73 Flute 2
00311   72, 0,  // 74 Piccolo 1
00312   72, 0,  // 75 Piccolo 2
00313   74, 0,  // 76 Recorder
00314   75, 0,  // 77 Pan Pipes
00315   64, 0,  // 78 Sax 1
00316   65, 0,  // 79 Sax 2
00317   66, 0,  // 80 Sax 3
00318   67, 0,  // 81 Sax 4
00319   71, 0,  // 82 Clarinet 1
00320   71, 0,  // 83 Clarinet 2
00321   68, 0,  // 84 Oboe
00322   69, 0,  // 85 English Horn (Cor Anglais)
00323   70, 0,  // 86 Bassoon
00324   22, 0,  // 87 Harmonica
00325   56, 0,  // 88 Trumpet 1
00326   56, 0,  // 89 Trumpet 2
00327   57, 0,  // 90 Trombone 1
00328   57, 0,  // 91 Trombone 2
00329   60, 0,  // 92 French Horn 1
00330   60, 0,  // 93 French Horn 2
00331   58, 0,  // 94 Tuba  
00332   61, 0,  // 95 Brass Section 1
00333   61, 0,  // 96 Brass Section 2
00334   11, 0,  // 97 Vibes 1
00335   11, 0,  // 98 Vibes 2
00336   99, 0,  // 99 Syn Mallet Bank 1
00337   112, 0, // 100  WindBell no real equiv Set to TinkleBell(112)
00338   9, 0, // 101  Glockenspiel
00339   14, 0,  // 102  Tubular Bells
00340   13, 0,  // 103  Xylophone
00341   12, 0,  // 104  Marimba
00342   107, 0, // 105  Koto
00343   111, 0, // 106  Sho?? set to Shanai(111)
00344   77, 0,  // 107  Shakauhachi
00345   78, 0,  // 108  Whistle 1
00346   78, 0,  // 109  Whistle 2
00347   76, 0,  // 110  Bottle Blow
00348   76, 0,  // 111  Breathpipe no real equiv set to bottle blow(76)
00349   47, 0,  // 112  Timpani
00350   117, 0, // 113  Melodic Tom
00351   116, 0, // 114  Deap Snare no equiv, set to Taiko(116)
00352   118, 0, // 115  Electric Perc 1
00353   118, 0, // 116  Electric Perc 2
00354   116, 0, // 117  Taiko
00355   115, 0, // 118  Taiko Rim, no real equiv, set to Woodblock(115)
00356   119, 0, // 119  Cymbal, no real equiv, set to reverse cymbal(119)
00357   115, 0, // 120  Castanets, no real equiv, in GM set to Woodblock(115)
00358   112, 0, // 121  Triangle, no real equiv, set to TinkleBell(112)
00359   55, 0,  // 122  Orchestral Hit
00360   124, 0, // 123  Telephone
00361   123, 0, // 124  BirdTweet
00362   94, 0,  // 125  Big Notes Pad no equiv, set to halo pad (94)
00363   98, 0,  // 126  Water Bell set to Crystal Pad(98)
00364   121, 0  // 127  Jungle Tune set to Breath Noise
00365 };
00366 
00367 GammaTable<unsigned char> XMIDI::VolumeCurve(128);
00368 
00369 // Constructor
00370 XMIDI::XMIDI(DataSource *source, int pconvert) : events(NULL),
00371             convert_type(pconvert),
00372             do_reverb(false), do_chorus(false)
00373 {
00374   std::memset(bank127,0,sizeof(bank127));
00375   
00376   ExtractTracks (source);
00377 }
00378 
00379 XMIDI::~XMIDI()
00380 {
00381   if (events)
00382   {
00383     for (int i=0; i < num_tracks; i++) {
00384       events[i]->DecerementCounter();
00385       events[i] = NULL;
00386     }
00387     //delete [] events;
00388     Free(events);
00389   }
00390 }
00391 
00392 XMIDIEventList *XMIDI::GetEventList (uint32 track)
00393 {
00394   if (!events)
00395   {
00396     cerr << "No midi data in loaded." << std::endl;
00397     return 0;
00398   }
00399 
00400   if (track >= num_tracks)
00401   {
00402     cerr << "Can't retrieve MIDI data, track out of range" << endl;
00403     return 0;
00404   }
00405 
00406   return events[track];
00407 }
00408 
00409 // Sets current to the new event and updates list
00410 void XMIDI::CreateNewEvent (int time)
00411 {
00412   if (!list)
00413   {
00414     list = current = Calloc<midi_event>(); //new midi_event;
00415     if (time > 0)
00416       current->time = time;
00417     return;
00418   }
00419 
00420   if (time < 0 || list->time > time)
00421   {
00422     midi_event *event = Calloc<midi_event>(); //new midi_event;
00423     event->next = list;
00424     list = current = event;
00425     return;
00426   }
00427 
00428   if (!current || current->time > time)
00429     current = list;
00430 
00431   while (current->next)
00432   {
00433     if (current->next->time > time)
00434     {
00435       midi_event *event = Calloc<midi_event>(); //new midi_event;
00436       
00437       event->next = current->next;
00438       current->next = event;
00439       current = event;
00440       current->time = time;
00441       return;
00442     }
00443     
00444     current = current->next;
00445   }
00446 
00447   current->next = Calloc<midi_event>(); //new midi_event;
00448   current = current->next;
00449   current->time = time;
00450 }
00451 
00452 //
00453 // GetVLQ
00454 //
00455 // Get a Conventional Variable Length Quantity
00456 //
00457 int XMIDI::GetVLQ (DataSource *source, uint32 &quant)
00458 {
00459   int i;
00460   quant = 0;
00461   unsigned int data;
00462 
00463   for (i = 0; i < 4; i++)
00464   {
00465     data = source->read1();
00466     quant <<= 7;
00467     quant |= data & 0x7F;
00468 
00469     if (!(data & 0x80))
00470     {
00471       i++;
00472       break;
00473     }
00474 
00475   }
00476   return i;
00477 }
00478 
00479 //
00480 // GetVLQ2
00481 //
00482 // Get a XMIDI Variable Length Quantity
00483 //
00484 int XMIDI::GetVLQ2 (DataSource *source, uint32 &quant)
00485 {
00486   int i;
00487   quant = 0;
00488   int data = 0;
00489   
00490   for (i = 0; i < 4; i++)
00491   {
00492     data = source->read1();
00493     if (data & 0x80)
00494     {
00495       source->skip(-1);
00496       break;
00497     }
00498     quant += data;
00499   }
00500   return i;
00501 }
00502 
00503 //
00504 // MovePatchVolAndPan.
00505 //
00506 // Well, this is just a modified version of what that method used to do. This
00507 // is a massive optimization. Speed up should be quite impressive
00508 //
00509 void XMIDI::ApplyFirstState(first_state &fs, int chan_mask)
00510 {
00511   for (int channel = 0; channel < 16; channel++)
00512   {
00513     midi_event *patch = fs.patch[channel];
00514     midi_event *vol = fs.vol[channel];
00515     midi_event *pan = fs.pan[channel];
00516     midi_event *bank = fs.bank[channel];
00517     midi_event *reverb = NULL;
00518     midi_event *chorus = NULL;
00519     midi_event *temp;
00520 
00521     // Got no patch change, return and don't try fixing it
00522     if (!patch || !(chan_mask & 1 << channel)) continue;
00523 #if 0
00524     std::cout << "Channel: " << channel+1 << std::endl;
00525     std::cout << "Patch: " << (unsigned int) patch->data[0] << " @ " << patch->time << std::endl;
00526     if (bank) std::cout << " Bank: " << (unsigned int) bank->data[1] << " @ " << bank->time << std::endl;
00527     if (vol) std::cout << "  Vol: " << (unsigned int) vol->data[1] << " @ " << vol->time << std::endl;
00528     if (pan) std::cout << "  Pan: " << ((signed int) pan->data[1])-64 << " @ " << pan->time << std::endl;
00529     std::cout << std::endl;
00530 #endif
00531 
00532     // Copy Patch Change Event
00533     temp = patch;
00534     patch = Calloc<midi_event>(); //new midi_event;
00535     patch->time = temp->time;
00536     patch->status = channel|(MIDI_STATUS_PROG_CHANGE << 4);
00537     patch->data[0] = temp->data[0];
00538 
00539     // Copy Volume
00540     if (vol && (vol->time > patch->time+PATCH_VOL_PAN_BIAS || vol->time < patch->time-PATCH_VOL_PAN_BIAS))
00541       vol = NULL;
00542 
00543     temp = vol;
00544     vol = Calloc<midi_event>(); //new midi_event;
00545     vol->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00546     vol->data[0] = 7;
00547 
00548     if (!temp)
00549     {
00550       if (convert_type) vol->data[1] = VolumeCurve[90];
00551       else vol->data[1] = 90;
00552     }
00553     else
00554       vol->data[1] = temp->data[1];
00555 
00556 
00557     // Copy Bank
00558     if (bank && (bank->time > patch->time+PATCH_VOL_PAN_BIAS || bank->time < patch->time-PATCH_VOL_PAN_BIAS))
00559       bank = NULL;
00560 
00561     temp = bank;
00562     
00563     bank = Calloc<midi_event>(); //new midi_event;
00564     bank->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00565 
00566     if (!temp)
00567       bank->data[1] = 0;
00568     else
00569       bank->data[1] = temp->data[1];
00570 
00571     // Copy Pan
00572     if (pan && (pan->time > patch->time+PATCH_VOL_PAN_BIAS || pan->time < patch->time-PATCH_VOL_PAN_BIAS))
00573       pan = NULL;
00574 
00575     temp = pan;
00576     pan = Calloc<midi_event>(); //new midi_event;
00577     pan->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00578     pan->data[0] = 10;
00579 
00580     if (!temp)
00581       pan->data[1] = 64;
00582     else
00583       pan->data[1] = temp->data[1];
00584 
00585     if (do_reverb)
00586     {
00587       reverb = Calloc<midi_event>(); //new midi_event;
00588       reverb->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00589       reverb->data[0] = 91;
00590       reverb->data[1] = reverb_value;
00591     }
00592 
00593     if (do_chorus)
00594     {
00595       chorus = Calloc<midi_event>(); //new midi_event;
00596       chorus->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00597       chorus->data[0] = 93;
00598       chorus->data[1] = chorus_value;
00599     }
00600 
00601     vol->time = 0;
00602     pan->time = 0;
00603     patch->time = 0;
00604     bank->time = 0;
00605     
00606     if (do_reverb && do_chorus) reverb->next = chorus;
00607     else if (do_reverb) reverb->next = bank;
00608     if (do_chorus) chorus->next = bank;
00609     bank->next = vol;
00610     vol->next = pan;
00611     pan->next = patch;
00612     
00613     patch->next = list;
00614     if (do_reverb) list = reverb;
00615     else if (do_chorus) list = chorus;
00616     else list = bank;
00617   }
00618 }
00619 
00620 #ifndef BEOS
00621 // Unsigned 64 Bit Int emulation. Only supports SOME operations
00622 struct uint64 {
00623   uint32  low;    // Low is first so uint64 can be cast as uint32 to get low dword
00624   uint32  high;   // 
00625 
00626   uint64() : low(0), high(0) { }
00627   uint64(uint32 i) : low(i), high(0) { }
00628   uint64(uint32 h, uint32 l) : low(l), high(h) { }
00629   uint64(const uint64 &i) : low(i.low), high(i.high) { }
00630 
00631   inline void addlow(uint32 l) {
00632     uint32 mid = (low >> 16);
00633     low = (low & 0xFFFF) + (l & 0xFFFF);
00634     mid += (low >> 16) + (l >> 16);
00635     low = (low&0xFFFF) + (mid << 16);
00636     high += mid >> 16;
00637   }
00638 
00639   // uint64 operations
00640 
00641   inline uint64 & operator = (uint64 &o) {
00642     low = o.low;
00643     high = o.high;
00644     return *this;
00645   }
00646 
00647   inline uint64 & operator += (uint64 &o) {
00648     addlow(o.low);
00649     high += o.high;
00650     return *this;
00651   }
00652 
00653   inline uint64 operator + (uint64 &o) {
00654     uint64 n(*this);
00655     n.addlow(o.low);
00656     n.high += o.high;
00657     return n;
00658   }
00659 
00660   // uint32 operations
00661 
00662   inline uint64 & operator = (uint32 i) {
00663     low = i;
00664     high = 0;
00665     return *this;
00666   }
00667 
00668   inline uint64 & operator += (uint32 i) {
00669     addlow(i);
00670     return *this;
00671   }
00672 
00673   inline uint64 operator + (uint32 i) {
00674     uint64 n(*this);
00675     n.addlow(i);
00676     return n;
00677   }
00678 
00679   inline uint64 & operator *= (uint32 i) {
00680     // High 16 bits
00681     uint32 h1 =   i >> 16;
00682     uint32 h2 = low >> 16;
00683     //uint32 h3 = high >> 16;
00684 
00685     // Low 16 Bits
00686     uint32 l1 =   i & 0xFFFF;
00687     uint32 l2 = low & 0xFFFF;
00688     uint32 l3 = high & 0xFFFF;
00689 
00690     // The accumulator
00691     uint32 accum;
00692 
00693     // 0 -> 32
00694     low = l1*l2;
00695     high = 0;
00696 
00697     // 16 -> 48
00698     accum = h1*l2;
00699     addlow(accum<<16);
00700     high += accum>>16;
00701 
00702     // 16 -> 48
00703     accum = l1*h2;
00704     addlow(accum<<16);  
00705     high += accum>>16;
00706 
00707     // 32 -> 64
00708     high += h1*h2;
00709 
00710     // 32 -> 64
00711     high += l1*l3;
00712 
00713     // 48 -> 80
00714     high += (h1*l3) << 16;
00715 
00716     // 48 -> 80
00717     high += (l1*l3) << 16;
00718 
00719     return *this;
00720   }
00721 
00722   inline uint64 operator * (uint32 i) {
00723     uint64 n(*this);
00724     return n*=i;
00725   }
00726 
00727   inline uint64 & operator /= (uint32 div) {
00728 
00729     // If there isn't a high dword, we only need to work on the low dword
00730     if (!high) {
00731       low /= div;
00732       return *this;
00733     }
00734 
00735     // modulus of last division
00736     uint32 mod = high;
00737     uint32 l = low;
00738 
00739     // Low shift
00740     uint32 shift = 32;
00741     low = 0;
00742 
00743     // Only High DWORD
00744     // Can divide
00745     if (mod >= div) {
00746       high = mod / div;
00747       mod %= div;
00748     }
00749     else high = 0;
00750 
00751     // Only Both high and low
00752     while (--shift) {
00753 
00754       mod <<= 1;
00755       mod |= (l>>shift) & 1;
00756 
00757       // Can divide
00758       if (mod >= div) {
00759         uint32 v = mod / div;
00760         mod %= div;
00761         addlow(v << shift);
00762         high += v >> (32 - shift);
00763       }
00764     }
00765 
00766 
00767     // Only Low DWORD
00768     mod <<= 1;
00769     mod |= l & 1;
00770 
00771     // Can divide
00772     if (mod >= div) {
00773       uint32 v = mod / div;
00774       mod %= div;
00775       addlow(v << shift);
00776     }
00777 
00778     return *this;
00779   }
00780 
00781   inline uint64 operator / (uint32 i) {
00782     uint64 n(*this);
00783     return n/=i;
00784   }
00785 
00786   inline uint64 & operator %= (uint32 div) {
00787 
00788     // If there isn't a high dword, we only need to work on the low dword
00789     if (!high) {
00790       low %= div;
00791       return *this;
00792     }
00793 
00794     // Remainder of last division
00795     uint32 mod = high;
00796 
00797     // Low shift
00798     uint32 shift = 32;
00799 
00800     while (1) {
00801 
00802       // Can divide
00803       if (mod >= div) mod %= div;
00804 
00805       if (shift == 0) break;
00806 
00807       mod <<= 1;
00808       shift--;
00809       mod |= (low>>shift) & 1;
00810     }
00811 
00812     high = 0;
00813     low = mod;
00814 
00815     return *this;
00816   }
00817 
00818   inline uint64 operator % (uint32 i) {
00819     uint64 n(*this);
00820     return n%=i;
00821   }
00822 
00823   inline operator uint32 ()
00824   {
00825     return low;
00826   }
00827 
00828   void printx() {
00829     if (high) std::printf ("%X%08X", high, low);
00830     else std::printf ("%X", low);
00831   }
00832 };
00833 #endif
00834 
00835 //
00836 // AdjustTimings
00837 //
00838 // It converts the midi's to use 120 Hz timing, and also calcs the duration of
00839 // the notes. It also strips the tempo events, and adds it's own
00840 //
00841 // This is used by Midi's ONLY! It will do nothing with Xmidi
00842 //
00843 void XMIDI::AdjustTimings(uint32 ppqn)
00844 {
00845   uint32    tempo = 500000;
00846   uint32    time_prev = 0;
00847   uint32    hs_rem = 0;
00848   uint32    hs     = 0;
00849 
00850   ppqn *= 10000;
00851 
00852   // Virtual playing
00853   NoteStack notes;
00854 
00855   for (midi_event *event = list; event; event = event->next) {
00856 
00857       // Note 64 bit int is required because multiplication by tempo can
00858       // require 52 bits in some circumstances
00859 
00860       uint64 aim = event->time - time_prev;
00861       aim *= tempo;
00862 
00863       hs_rem += aim%ppqn;
00864       hs += aim/ppqn;
00865       hs += hs_rem/ppqn;
00866       hs_rem %= ppqn;
00867 
00868       time_prev = event->time;
00869       event->time = (hs*6)/5 + (6*hs_rem)/(5*ppqn);
00870         
00871       // Note on and note off handling
00872       if (event->status <= 0x9F) {
00873 
00874         // Add if it's a note on and remove if it's a note off
00875         if ((event->status>>4) == MIDI_STATUS_NOTE_ON && event->data[1]) 
00876           notes.Push(event);
00877         else {
00878           midi_event *prev = notes.FindAndPop(event);
00879           if (prev) prev->duration = event->time - prev->time;
00880         }
00881 
00882       }
00883       else if (event->status == 0xFF && event->data[0] == 0x51) {
00884 
00885         tempo = (event->buffer[0] << 16) +
00886           (event->buffer[1] << 8) +
00887           event->buffer[2];
00888           
00889         event->buffer[0] = 0x07;
00890         event->buffer[1] = 0xA1;
00891         event->buffer[2] = 0x20;
00892       }
00893   }
00894 
00895   //std::cout << "Max Polyphony: " << notes.GetMaxPolyphony() << std::endl;
00896   static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
00897   BufferDataSource ds((char *)tempo_buf, 5);
00898   current = list;
00899   ConvertSystemMessage (0, 0xFF,&ds);
00900 }
00901 
00902 
00903 // Converts Events
00904 //
00905 // Source is at the first data byte
00906 // size 1 is single data byte (ConvertEvent Only)
00907 // size 2 is dual data byte
00908 // size 3 is XMI Note on (ConvertNote only)
00909 // Returns bytes converted
00910 //
00911 // ConvertNote is used for Note On's and Note offs
00912 // ConvertSystemMessage is used for SysEx events and Meta events
00913 // ConvertEvent is used for everything else
00914 
00915 int XMIDI::ConvertEvent (const int time, const unsigned char status, DataSource *source, const int size, first_state &fs)
00916 {
00917   int data;
00918 
00919   data = source->read1();
00920 
00921 
00922   // Bank changes are handled here
00923   if ((status >> 4) == 0xB && data == 0)
00924   {
00925     data = source->read1();
00926     
00927     bank127[status&0xF] = false;
00928     
00929     if (convert_type == XMIDI_CONVERT_MT32_TO_GM || convert_type == XMIDI_CONVERT_MT32_TO_GS
00930       || convert_type == XMIDI_CONVERT_MT32_TO_GS127)
00931       return 2;
00932 
00933     CreateNewEvent (time);
00934     current->status = status;
00935     current->data[0] = 0;
00936     current->data[1] = data;
00937 
00938     // Set the bank
00939     if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
00940 
00941     if (convert_type == XMIDI_CONVERT_GS127_TO_GS && data == 127)
00942       bank127[status&0xF] = true;
00943 
00944     return 2;
00945   }
00946 
00947   // Handling for patch change mt32 conversion, probably should go elsewhere
00948   if ((status >> 4) == 0xC && (status&0xF) != 9 && convert_type != XMIDI_CONVERT_NOCONVERSION)
00949   {
00950     if (convert_type == XMIDI_CONVERT_MT32_TO_GM)
00951     {
00952       data = mt32asgm[data];
00953     }
00954     else if ((convert_type == XMIDI_CONVERT_GS127_TO_GS && bank127[status&0xF]) ||
00955         convert_type == XMIDI_CONVERT_MT32_TO_GS)
00956     {
00957       CreateNewEvent (time);
00958       current->status = 0xB0 | (status&0xF);
00959       current->data[0] = 0;
00960       current->data[1] = mt32asgs[data*2+1];
00961 
00962       data = mt32asgs[data*2];
00963 
00964       // Set the bank
00965       if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
00966     }
00967     else if (convert_type == XMIDI_CONVERT_MT32_TO_GS127)
00968     {
00969       CreateNewEvent (time);
00970       current->status = 0xB0 | (status&0xF);
00971       current->data[0] = 0;
00972       current->data[1] = 127;
00973 
00974       // Set the bank
00975       if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
00976     }
00977   }// Disable patch changes on Track 10 is doing a conversion
00978   else if ((status >> 4) == 0xC && (status&0xF) == 9 && convert_type != XMIDI_CONVERT_NOCONVERSION)
00979   {
00980     return size;
00981   }
00982 
00983   CreateNewEvent (time);
00984   current->status = status;
00985 
00986   current->data[0] = data;
00987 
00988   // Check for patch change, and update fs if req
00989   if ((status >> 4) == 0xC) {
00990     if (!fs.patch[status&0xF] || fs.patch[status&0xF]->time > time)
00991       fs.patch[status&0xF] = current;
00992   }
00993   // Controllers
00994   else if ((status >> 4) == 0xB) {
00995     // Volume
00996     if (current->data[0] == 7) {
00997       if (!fs.vol[status&0xF] || fs.vol[status&0xF]->time > time)
00998         fs.vol[status&0xF] = current;
00999     }
01000     // Pan
01001     else if (current->data[0] == 10) {
01002       if (!fs.pan[status&0xF] || fs.pan[status&0xF]->time > time)
01003         fs.pan[status&0xF] = current;
01004     }
01005   }
01006 
01007   if (size == 1)
01008     return 1;
01009 
01010   current->data[1] = source->read1();
01011 
01012   // Volume modify the volume controller, only if converting
01013   if (convert_type && (current->status >> 4) == MIDI_STATUS_CONTROLLER && current->data[0] == 7)
01014     current->data[1] = VolumeCurve[current->data[1]];
01015 
01016   return 2;
01017 }
01018 
01019 int XMIDI::ConvertNote (const int time, const unsigned char status, DataSource *source, const int size)
01020 {
01021   uint32  delta = 0;
01022   int data;
01023 
01024   data = source->read1();
01025 
01026   CreateNewEvent (time);
01027   current->status = status;
01028 
01029   current->data[0] = data;
01030   current->data[1] = source->read1();
01031 
01032   // Volume modify the note on's, only if converting
01033   if (convert_type && (current->status >> 4) == MIDI_STATUS_NOTE_ON && current->data[1])
01034     current->data[1] = VolumeCurve[current->data[1]];
01035 
01036   if (size == 2)
01037     return 2;
01038 
01039   // XMI Note On handling
01040 
01041   // Get the duration
01042   int i = GetVLQ (source, delta);
01043   
01044   // Set the duration
01045   current->duration = delta;
01046 
01047   // This is an optimization
01048   midi_event *prev = current;
01049     
01050   // Create a note off
01051   CreateNewEvent (time+delta);
01052 
01053   current->status = status;
01054   current->data[0] = data;
01055   current->data[1] = 0;
01056   
01057   // Optimization
01058   current = prev;
01059 
01060   return i + 2;
01061 }
01062 
01063 // Simple routine to convert system messages
01064 int XMIDI::ConvertSystemMessage (const int time, const unsigned char status, DataSource *source)
01065 {
01066   int i=0;
01067   
01068   CreateNewEvent (time);
01069   current->status = status;
01070   
01071   // Handling of Meta events
01072   if (status == 0xFF)
01073   {
01074     current->data[0] = source->read1();
01075     i++;  
01076   }
01077 
01078   i += GetVLQ (source, current->len);
01079 
01080   if (!current->len)
01081   {
01082     current->buffer = NULL;
01083     return i;
01084   }
01085   
01086   current->buffer = Malloc<unsigned char>(current->len);
01087 
01088   source->read (reinterpret_cast<char *>(current->buffer), current->len);
01089 
01090   return i+current->len;
01091 }
01092 
01093 // XMIDI and Midi to List. Returns bit mask of channels used
01094 int XMIDI::ConvertFiletoList (DataSource *source, const bool is_xmi, first_state &fs)
01095 {
01096   int   time = 0;     // 120th of a second
01097   uint32  data;
01098   int   end = 0;
01099   uint32  status = 0;
01100   int   play_size = 2;
01101   int   file_size = source->getSize();
01102   int   retval = 0;
01103 
01104   if (is_xmi) play_size = 3;
01105 
01106   while (!end && source->getPos() < file_size)
01107   {
01108     if (!is_xmi)
01109     {
01110       GetVLQ (source, data);
01111       time += data;
01112 
01113       data = source->read1();
01114     
01115       if (data >= 0x80)
01116       {
01117         status = data;
01118       }
01119       else
01120         source->skip (-1);
01121     } 
01122     else
01123     {
01124       GetVLQ2 (source, data);
01125       time += data;
01126 
01127       status = source->read1();
01128     }
01129 
01130     switch (status >> 4)
01131     {
01132       case MIDI_STATUS_NOTE_ON:
01133       retval |= 1 << (status & 0xF);
01134       ConvertNote (time, status, source, play_size);
01135       break;
01136 
01137       case MIDI_STATUS_NOTE_OFF:
01138       ConvertNote (time, status, source, 2);
01139       break;
01140 
01141       // 2 byte data
01142       case MIDI_STATUS_AFTERTOUCH:
01143       case MIDI_STATUS_CONTROLLER:
01144       case MIDI_STATUS_PITCH_WHEEL:
01145       ConvertEvent (time, status, source, 2, fs);
01146       break;
01147       
01148 
01149       // 1 byte data
01150       case MIDI_STATUS_PROG_CHANGE:
01151       case MIDI_STATUS_PRESSURE:
01152       ConvertEvent (time, status, source, 1, fs);
01153       break;
01154       
01155 
01156       case MIDI_STATUS_SYSEX:
01157       if (status == 0xFF)
01158       {
01159         int pos = source->getPos();
01160         uint32  data = source->read1();
01161         
01162         if (data == 0x2F)         // End, of track
01163           end = 1;
01164         else if (data == 0x51 && is_xmi)  // XMIDI doesn't use tempo
01165         {
01166           GetVLQ (source, data);
01167           source->skip(data);
01168           break;
01169         }
01170         
01171         source->seek (pos);
01172       }
01173       ConvertSystemMessage (time, status, source);
01174       break;
01175 
01176       default:
01177       break;
01178     }
01179 
01180   }
01181 
01182   return retval;
01183 }
01184 
01185 // Assumes correct xmidi
01186 int XMIDI::ExtractTracksFromXmi (DataSource *source)
01187 {
01188   int       num = 0;
01189   uint32      len = 0;
01190   char      buf[32];
01191 
01192   first_state fs;
01193 
01194   while (source->getPos() < source->getSize() && num != num_tracks)
01195   {
01196     // Read first 4 bytes of name
01197     source->read (buf, 4);
01198     len = source->read4high();
01199 
01200     // Skip the FORM entries
01201     if (!memcmp(buf,"FORM",4))
01202     {
01203       source->skip (4);
01204       source->read (buf, 4);
01205       len = source->read4high();
01206     }
01207 
01208     if (memcmp(buf,"EVNT",4))
01209     {
01210       source->skip ((len+1)&~1);
01211       continue;
01212     }
01213 
01214     list = NULL;
01215     memset(&fs, 0, sizeof(fs));
01216 
01217     int begin = source->getPos ();
01218 
01219     // Convert it
01220     int chan_mask = ConvertFiletoList (source, true, fs);
01221 
01222     // Apply the first state
01223     ApplyFirstState(fs, chan_mask);
01224 
01225     // Add tempo
01226     static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
01227     BufferDataSource ds((char *)tempo_buf, 5);
01228     current = list;
01229     ConvertSystemMessage (0, 0xFF,&ds);
01230 
01231     // Set the list
01232     events[num]->events = list;
01233 
01234     // Increment Counter
01235     num++;
01236 
01237     // go to start of next track
01238     source->seek (begin + ((len+1)&~1));
01239   }
01240 
01241   // Return how many were converted
01242   return num;
01243 }
01244 
01245 int XMIDI::ExtractTracksFromMid (DataSource *source, const uint32 ppqn, const int num_tracks, const bool type1)
01246 {
01247   int     num = 0;
01248   uint32    len = 0;
01249   char    buf[32];
01250   int     chan_mask = 0;
01251 
01252   first_state fs;
01253   memset(&fs, 0, sizeof(fs));
01254 
01255   list = NULL;
01256 
01257   while (source->getPos() < source->getSize() && num != num_tracks)
01258   {
01259     // Read first 4 bytes of name
01260     source->read (buf, 4);
01261     len = source->read4high();
01262 
01263     if (memcmp(buf,"MTrk",4))
01264     {
01265       source->skip (len);
01266       continue;
01267     }
01268 
01269     int begin = source->getPos ();
01270 
01271     // Convert it
01272     chan_mask |= ConvertFiletoList (source, false, fs);
01273 
01274     if (!type1) {
01275       ApplyFirstState(fs, chan_mask);
01276       AdjustTimings(ppqn);
01277       events[num]->events = list;
01278       list = NULL;
01279       memset(&fs, 0, sizeof(fs));
01280       chan_mask = 0;
01281     }
01282     
01283     // Increment Counter
01284     num++;    
01285     source->seek (begin+len);
01286   }
01287 
01288   if (type1) { 
01289     ApplyFirstState(fs, chan_mask);
01290     AdjustTimings(ppqn);
01291     events[0]->events = list;
01292     return num == num_tracks ? 1 : 0;
01293   }
01294 
01295   // Return how many were converted
01296   return num;
01297 }
01298 
01299 int XMIDI::ExtractTracks (DataSource *source)
01300 {
01301   uint32    i = 0;
01302   int   start;
01303   uint32    len;
01304   uint32    chunk_len;
01305   int     count;
01306   char    buf[32];
01307 
01308   string s;
01309   
01310   config->value("config/audio/midi/reverb/enabled",s,"no");
01311   if (s == "yes") do_reverb = true;
01312   config->set("config/audio/midi/reverb/enabled",s,true);
01313 
01314   config->value("config/audio/midi/reverb/level",s,"---");
01315   if (s == "---") config->value("config/audio/midi/reverb",s,"64");
01316   reverb_value = atoi(s.c_str());
01317   if (reverb_value > 127) reverb_value = 127;
01318   else if (reverb_value < 0) reverb_value = 0;
01319   config->set("config/audio/midi/reverb/level",reverb_value,true);
01320   
01321   config->value("config/audio/midi/chorus/enabled",s,"no");
01322   if (s == "yes") do_chorus = true;
01323   config->set("config/audio/midi/chorus/enabled",s,true);
01324 
01325   config->value("config/audio/midi/chorus/level",s,"---");
01326   if (s == "---") config->value("config/audio/midi/chorus",s,"16");
01327   chorus_value = atoi(s.c_str());
01328   if (chorus_value > 127) chorus_value = 127;
01329   else if (chorus_value < 0) chorus_value = 0;
01330   config->set("config/audio/midi/chorus/level",chorus_value,true);
01331   
01332   config->value("config/audio/midi/volume_curve",s,"---");
01333   if (s == "---") config->value("config/audio/midi/gamma",s,"1");
01334   VolumeCurve.set_gamma (atof(s.c_str()));
01335   int igam = (int) ((VolumeCurve.get_gamma()*10000)+0.5);
01336   snprintf (buf, 32, "%d.%04d", igam/10000, igam%10000);
01337   config->set("config/audio/midi/volume_curve",buf,true);
01338   
01339 
01340   // Read first 4 bytes of header
01341   source->read (buf, 4);
01342 
01343   // Could be XMIDI
01344   if (!memcmp (buf, "FORM", 4))
01345   {
01346     // Read length of 
01347     len = source->read4high();
01348 
01349     start = source->getPos();
01350     
01351     // Read 4 bytes of type
01352     source->read (buf, 4);
01353 
01354     // XDIRless XMIDI, we can handle them here.
01355     if (!memcmp (buf, "XMID", 4))
01356     { 
01357       cerr << "Warning: XMIDI doesn't have XDIR" << endl;
01358       num_tracks = 1;
01359       
01360     } // Not an XMIDI that we recognise
01361     else if (memcmp (buf, "XDIR", 4))
01362     { 
01363       cerr << "Not a recognised XMID" << endl;
01364       return 0;
01365       
01366     } // Seems Valid
01367     else 
01368     {
01369       num_tracks = 0;
01370     
01371       for (i = 4; i < len; i++)
01372       {
01373         // Read 4 bytes of type
01374         source->read (buf, 4);
01375 
01376         // Read length of chunk
01377         chunk_len = source->read4high();
01378       
01379         // Add eight bytes
01380         i+=8;
01381         
01382         if (memcmp (buf, "INFO", 4))
01383         { 
01384           // Must allign
01385           source->skip((chunk_len+1)&~1);
01386           i+= (chunk_len+1)&~1;
01387           continue;
01388         }
01389 
01390         // Must be at least 2 bytes long
01391         if (chunk_len < 2)
01392           break;
01393         
01394         num_tracks = source->read2();
01395         break;
01396       }
01397     
01398       // Didn't get to fill the header
01399       if (num_tracks == 0)
01400       {
01401         cerr << "Not a valid XMID" << endl;
01402         return 0;
01403       }
01404     
01405       // Ok now to start part 2
01406       // Goto the right place
01407       source->seek (start+((len+1)&~1));
01408     
01409       // Read 4 bytes of type
01410       source->read (buf, 4);
01411 
01412       // Not an XMID
01413       if (memcmp (buf, "CAT ", 4))
01414       {
01415         cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (CAT )" << endl;
01416         return 0; 
01417       }
01418       
01419       // Now read length of this track
01420       len = source->read4high();
01421       
01422       // Read 4 bytes of type
01423       source->read (buf, 4);
01424 
01425       // Not an XMID
01426       if (memcmp (buf, "XMID", 4))
01427       {
01428         cerr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (XMID)" << endl;
01429         return 0; 
01430       }
01431 
01432     }
01433 
01434     // Ok it's an XMID, so pass it to the ExtractCode
01435 
01436     events = Calloc<XMIDIEventList*>(num_tracks); //new midi_event *[info.tracks];
01437     
01438     for (i = 0; i < num_tracks; i++)
01439       events[i] = Calloc<XMIDIEventList>();
01440 
01441     count = ExtractTracksFromXmi (source);
01442 
01443     if (count != num_tracks)
01444     {
01445       cerr << "Error: unable to extract all (" << num_tracks << ") tracks specified from XMIDI. Only ("<< count << ")" << endl;
01446       
01447       int i = 0;
01448       
01449       for (i = 0; i < num_tracks; i++) {
01450         events[i]->DecerementCounter();
01451         events[i] = NULL;
01452       }
01453       
01454       //delete [] events;
01455       Free (events);
01456       
01457       return 0;   
01458     }
01459 
01460     return 1;
01461     
01462   }// Definately a Midi
01463   else if (!memcmp (buf, "MThd", 4))
01464   {
01465     // Simple read length of header
01466     len = source->read4high();
01467 
01468     if (len < 6)
01469     {
01470       cerr << "Not a valid MIDI" << endl;
01471       return 0;
01472     }
01473 
01474     int type = source->read2high();
01475     
01476     int actual_num = num_tracks = source->read2high();
01477 
01478     // Type 1 only has 1 track, even though it says it has more
01479     if (type == 1) num_tracks = 1;
01480 
01481     events = Calloc<XMIDIEventList*>(num_tracks); //new midi_event *[info.tracks];
01482     const uint32 ppqn = source->read2high();
01483 
01484     for (i = 0; i < num_tracks; i++)
01485       events[i] = Calloc<XMIDIEventList>();
01486     
01487     count = ExtractTracksFromMid (source, ppqn, actual_num, type == 1);
01488 
01489     if (count != num_tracks)
01490     {
01491       cerr << "Error: unable to extract all (" << num_tracks << ") tracks specified from MIDI. Only ("<< count << ")" << endl;
01492       
01493       for (i = 0; i < num_tracks; i++) {
01494         events[i]->DecerementCounter();
01495         events[i] = NULL;
01496       }
01497       
01498       Free (events);
01499       
01500       return 0;
01501         
01502     }
01503 
01504     return 1;
01505     
01506   }// A RIFF Midi, just pass the source back to this function at the start of the midi file
01507   else if (!memcmp (buf, "RIFF", 4))
01508   {
01509     // Read len
01510     len = source->read4();
01511 
01512     // Read 4 bytes of type
01513     source->read (buf, 4);
01514     
01515     // Not an RMID
01516     if (memcmp (buf, "RMID", 4))
01517     {
01518       cerr << "Invalid RMID" << endl;
01519       return 0;
01520     }
01521 
01522     // Is a RMID
01523 
01524     for (i = 4; i < len; i++)
01525     {
01526       // Read 4 bytes of type
01527       source->read (buf, 4);
01528       
01529       chunk_len = source->read4();
01530       
01531       i+=8;
01532         
01533       if (memcmp (buf, "data", 4))
01534       { 
01535         // Must allign
01536         source->skip ((chunk_len+1)&~1);
01537         i+= (chunk_len+1)&~1;
01538         continue;
01539       }
01540       
01541       return ExtractTracks (source);
01542 
01543     }
01544     
01545     cerr << "Failed to find midi data in RIFF Midi" << endl;
01546     return 0;
01547   }
01548   
01549   return 0; 
01550 }
01551 
01552 //
01553 // XMIDIEventList stuff
01554 //
01555 int XMIDIEventList::Write (const char *filename)
01556 {
01557   std::FILE *file = U7open (filename, "wb"); // DARKE FIXME
01558   FileDataSource ds(file);
01559   int ret = Write(&ds);
01560   fclose (file);
01561   return ret;
01562 }
01563 
01564 int XMIDIEventList::Write (DataSource *dest)
01565 {
01566   int len = 0;
01567   
01568   if (!events)
01569   {
01570     cerr << "No midi data in loaded." << endl;
01571     return 0;
01572   }
01573 
01574   // This is so if using buffer datasource, the caller can know how big to make the buffer
01575   if (!dest)
01576   {
01577     // Header is 14 bytes long and add the rest as well
01578     len = ConvertListToMTrk (NULL);
01579     return 14 + len;
01580   }
01581     
01582   dest->write1 ('M');
01583   dest->write1 ('T');
01584   dest->write1 ('h');
01585   dest->write1 ('d');
01586   
01587   dest->write4high (6);
01588 
01589   dest->write2high (0);
01590   dest->write2high (1);
01591   dest->write2high (60);  // The PPQN
01592     
01593   len = ConvertListToMTrk (dest);
01594 
01595   return len + 14;
01596 }
01597 
01598 //
01599 // PutVLQ
01600 //
01601 // Write a Conventional Variable Length Quantity
01602 //
01603 int XMIDIEventList::PutVLQ(DataSource *dest, uint32 value)
01604 {
01605   int buffer;
01606   int i = 1;
01607   buffer = value & 0x7F;
01608   while (value >>= 7)
01609   {
01610     buffer <<= 8;
01611     buffer |= ((value & 0x7F) | 0x80);
01612     i++;
01613   }
01614   if (!dest) return i;
01615   for (int j = 0; j < i; j++)
01616   {
01617     dest->write1(buffer & 0xFF);
01618     buffer >>= 8;
01619   }
01620   
01621   return i;
01622 }
01623 
01624 // Converts and event list to a MTrk
01625 // Returns bytes of the array
01626 // buf can be NULL
01627 uint32 XMIDIEventList::ConvertListToMTrk (DataSource *dest)
01628 {
01629   int time = 0;
01630   int lasttime = 0;
01631   midi_event  *event;
01632   uint32  delta;
01633   unsigned char last_status = 0;
01634   uint32  i = 8;
01635   uint32  j;
01636   uint32  size_pos=0;
01637 
01638   if (dest)
01639   {
01640     dest->write1('M');
01641     dest->write1('T');
01642     dest->write1('r');
01643     dest->write1('k');
01644 
01645     size_pos = dest->getPos();
01646     dest->skip(4);
01647   }
01648 
01649   for (event = events; event; event=event->next)
01650   {
01651     // We don't write the end of stream marker here, we'll do it later
01652     if (event->status == 0xFF && event->data[0] == 0x2f) {
01653       lasttime = event->time;
01654       continue;
01655     }
01656 
01657     delta = (event->time - time);
01658     time = event->time;
01659 
01660     i += PutVLQ (dest, delta);
01661 
01662     if ((event->status != last_status) || (event->status >= 0xF0))
01663     {
01664       if (dest) dest->write1(event->status);
01665       i++;
01666     }
01667     
01668     last_status = event->status;
01669     
01670     switch (event->status >> 4)
01671     {
01672       // 2 bytes data
01673       // Note off, Note on, Aftertouch, Controller and Pitch Wheel
01674       case 0x8: case 0x9: case 0xA: case 0xB: case 0xE:
01675       if (dest)
01676       {
01677         dest->write1(event->data[0]);
01678         dest->write1(event->data[1]);
01679       }
01680       i += 2;
01681       break;
01682       
01683 
01684       // 1 bytes data
01685       // Program Change and Channel Pressure
01686       case 0xC: case 0xD:
01687       if (dest) dest->write1(event->data[0]);
01688       i++;
01689       break;
01690       
01691 
01692       // Variable length
01693       // SysEx
01694       case 0xF:
01695       if (event->status == 0xFF)
01696       {
01697         if (dest) dest->write1(event->data[0]);
01698         i++;
01699       }
01700   
01701       i += PutVLQ (dest, event->len);
01702       
01703       if (event->len)
01704       {
01705         for (j = 0; j < event->len; j++)
01706         {
01707           if (dest) dest->write1(event->buffer[j]); 
01708           i++;
01709         }
01710       }
01711 
01712       break;
01713       
01714 
01715       // Never occur
01716       default:
01717       cerr << "Not supposed to see this" << endl;
01718       break;
01719     }
01720   }
01721 
01722   // Write out end of stream marker
01723   if (lasttime > time) i += PutVLQ (dest, lasttime-time);
01724   else i += PutVLQ (dest, 0);
01725   if (dest) {
01726     dest->write1(0xFF);
01727     dest->write1(0x2F);
01728   }
01729   i += 2+PutVLQ (dest, 0);
01730 
01731   if (dest)
01732   {
01733     int cur_pos = dest->getPos();
01734     dest->seek (size_pos);
01735     dest->write4high (i-8);
01736     dest->seek (cur_pos);
01737   }
01738   return i;
01739 }
01740 
01741 
01742 void XMIDIEventList::DeleteEventList (midi_event *mlist)
01743 {
01744   midi_event *event;
01745   midi_event *next;
01746   
01747   next = mlist;
01748   event = mlist;
01749 
01750   while ((event = next))
01751   {
01752     next = event->next;
01753     // We only do this with sysex
01754     if ((event->status>>4) == 0xF && event->buffer) Free (event->buffer);
01755     Free (event);
01756   }
01757 }
01758 
01759 void XMIDIEventList::DecerementCounter()
01760 {
01761   if (--counter < 0) {
01762     DeleteEventList(events);
01763     Free(this);
01764   }
01765 }
01766 
01767 #endif

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