00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00054
00055
00056
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
00093
00094
00095
00096 #define PATCH_VOL_PAN_BIAS 5
00097
00098
00099
00100
00101
00102
00103 const char XMIDI::mt32asgm[128] = {
00104 0,
00105 1,
00106 2,
00107 4,
00108 4,
00109 5,
00110 5,
00111 3,
00112 16,
00113 17,
00114 18,
00115 16,
00116 19,
00117 19,
00118 19,
00119 21,
00120 6,
00121 6,
00122 6,
00123 7,
00124 7,
00125 7,
00126 8,
00127 8,
00128 62,
00129 63,
00130 62,
00131 63,
00132 38,
00133 39,
00134 38,
00135 39,
00136 88,
00137 90,
00138 52,
00139 92,
00140 97,
00141 99,
00142 14,
00143 54,
00144 98,
00145 96,
00146 68,
00147 95,
00148 81,
00149 87,
00150 112,
00151 80,
00152 48,
00153 48,
00154 44,
00155 45,
00156 40,
00157 40,
00158 42,
00159 42,
00160 43,
00161 46,
00162 46,
00163 24,
00164 25,
00165 26,
00166 27,
00167 104,
00168 32,
00169 32,
00170 33,
00171 34,
00172 36,
00173 37,
00174 35,
00175 35,
00176 73,
00177 73,
00178 72,
00179 72,
00180 74,
00181 75,
00182 64,
00183 65,
00184 66,
00185 67,
00186 71,
00187 71,
00188 68,
00189 69,
00190 70,
00191 22,
00192 56,
00193 56,
00194 57,
00195 57,
00196 60,
00197 60,
00198 58,
00199 61,
00200 61,
00201 11,
00202 11,
00203 99,
00204 112,
00205 9,
00206 14,
00207 13,
00208 12,
00209 107,
00210 111,
00211 77,
00212 78,
00213 78,
00214 76,
00215 76,
00216 47,
00217 117,
00218 116,
00219 118,
00220 118,
00221 116,
00222 115,
00223 119,
00224 115,
00225 112,
00226 55,
00227 124,
00228 123,
00229 94,
00230 98,
00231 121
00232 };
00233
00234
00235
00236 const char XMIDI::mt32asgs[256] = {
00237 0, 0,
00238 1, 0,
00239 2, 0,
00240 4, 0,
00241 4, 0,
00242 5, 0,
00243 5, 0,
00244 3, 0,
00245 16, 0,
00246 17, 0,
00247 18, 0,
00248 16, 0,
00249 19, 0,
00250 19, 0,
00251 19, 0,
00252 21, 0,
00253 6, 0,
00254 6, 0,
00255 6, 0,
00256 7, 0,
00257 7, 0,
00258 7, 0,
00259 8, 0,
00260 8, 0,
00261 62, 0,
00262 63, 0,
00263 62, 0,
00264 63, 0,
00265 38, 0,
00266 39, 0,
00267 38, 0,
00268 39, 0,
00269 88, 0,
00270 90, 0,
00271 52, 0,
00272 92, 0,
00273 97, 0,
00274 99, 0,
00275 14, 0,
00276 54, 0,
00277 98, 0,
00278 96, 0,
00279 68, 0,
00280 95, 0,
00281 81, 0,
00282 87, 0,
00283 112, 0,
00284 80, 0,
00285 48, 0,
00286 48, 0,
00287 44, 0,
00288 45, 0,
00289 40, 0,
00290 40, 0,
00291 42, 0,
00292 42, 0,
00293 43, 0,
00294 46, 0,
00295 46, 0,
00296 24, 0,
00297 25, 0,
00298 26, 0,
00299 27, 0,
00300 104, 0,
00301 32, 0,
00302 32, 0,
00303 33, 0,
00304 34, 0,
00305 36, 0,
00306 37, 0,
00307 35, 0,
00308 35, 0,
00309 73, 0,
00310 73, 0,
00311 72, 0,
00312 72, 0,
00313 74, 0,
00314 75, 0,
00315 64, 0,
00316 65, 0,
00317 66, 0,
00318 67, 0,
00319 71, 0,
00320 71, 0,
00321 68, 0,
00322 69, 0,
00323 70, 0,
00324 22, 0,
00325 56, 0,
00326 56, 0,
00327 57, 0,
00328 57, 0,
00329 60, 0,
00330 60, 0,
00331 58, 0,
00332 61, 0,
00333 61, 0,
00334 11, 0,
00335 11, 0,
00336 99, 0,
00337 112, 0,
00338 9, 0,
00339 14, 0,
00340 13, 0,
00341 12, 0,
00342 107, 0,
00343 111, 0,
00344 77, 0,
00345 78, 0,
00346 78, 0,
00347 76, 0,
00348 76, 0,
00349 47, 0,
00350 117, 0,
00351 116, 0,
00352 118, 0,
00353 118, 0,
00354 116, 0,
00355 115, 0,
00356 119, 0,
00357 115, 0,
00358 112, 0,
00359 55, 0,
00360 124, 0,
00361 123, 0,
00362 94, 0,
00363 98, 0,
00364 121, 0
00365 };
00366
00367 GammaTable<unsigned char> XMIDI::VolumeCurve(128);
00368
00369
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
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
00410 void XMIDI::CreateNewEvent (int time)
00411 {
00412 if (!list)
00413 {
00414 list = current = Calloc<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>();
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>();
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>();
00448 current = current->next;
00449 current->time = time;
00450 }
00451
00452
00453
00454
00455
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
00481
00482
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
00505
00506
00507
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
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
00533 temp = patch;
00534 patch = Calloc<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
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>();
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
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>();
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
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>();
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>();
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>();
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
00622 struct uint64 {
00623 uint32 low;
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
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
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
00681 uint32 h1 = i >> 16;
00682 uint32 h2 = low >> 16;
00683
00684
00685
00686 uint32 l1 = i & 0xFFFF;
00687 uint32 l2 = low & 0xFFFF;
00688 uint32 l3 = high & 0xFFFF;
00689
00690
00691 uint32 accum;
00692
00693
00694 low = l1*l2;
00695 high = 0;
00696
00697
00698 accum = h1*l2;
00699 addlow(accum<<16);
00700 high += accum>>16;
00701
00702
00703 accum = l1*h2;
00704 addlow(accum<<16);
00705 high += accum>>16;
00706
00707
00708 high += h1*h2;
00709
00710
00711 high += l1*l3;
00712
00713
00714 high += (h1*l3) << 16;
00715
00716
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
00730 if (!high) {
00731 low /= div;
00732 return *this;
00733 }
00734
00735
00736 uint32 mod = high;
00737 uint32 l = low;
00738
00739
00740 uint32 shift = 32;
00741 low = 0;
00742
00743
00744
00745 if (mod >= div) {
00746 high = mod / div;
00747 mod %= div;
00748 }
00749 else high = 0;
00750
00751
00752 while (--shift) {
00753
00754 mod <<= 1;
00755 mod |= (l>>shift) & 1;
00756
00757
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
00768 mod <<= 1;
00769 mod |= l & 1;
00770
00771
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
00789 if (!high) {
00790 low %= div;
00791 return *this;
00792 }
00793
00794
00795 uint32 mod = high;
00796
00797
00798 uint32 shift = 32;
00799
00800 while (1) {
00801
00802
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
00837
00838
00839
00840
00841
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
00853 NoteStack notes;
00854
00855 for (midi_event *event = list; event; event = event->next) {
00856
00857
00858
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
00872 if (event->status <= 0x9F) {
00873
00874
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
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
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
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
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
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
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
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
00975 if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
00976 }
00977 }
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
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
00994 else if ((status >> 4) == 0xB) {
00995
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
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
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
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
01040
01041
01042 int i = GetVLQ (source, delta);
01043
01044
01045 current->duration = delta;
01046
01047
01048 midi_event *prev = current;
01049
01050
01051 CreateNewEvent (time+delta);
01052
01053 current->status = status;
01054 current->data[0] = data;
01055 current->data[1] = 0;
01056
01057
01058 current = prev;
01059
01060 return i + 2;
01061 }
01062
01063
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
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
01094 int XMIDI::ConvertFiletoList (DataSource *source, const bool is_xmi, first_state &fs)
01095 {
01096 int time = 0;
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
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
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)
01163 end = 1;
01164 else if (data == 0x51 && is_xmi)
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
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
01197 source->read (buf, 4);
01198 len = source->read4high();
01199
01200
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
01220 int chan_mask = ConvertFiletoList (source, true, fs);
01221
01222
01223 ApplyFirstState(fs, chan_mask);
01224
01225
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
01232 events[num]->events = list;
01233
01234
01235 num++;
01236
01237
01238 source->seek (begin + ((len+1)&~1));
01239 }
01240
01241
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
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
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
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
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
01341 source->read (buf, 4);
01342
01343
01344 if (!memcmp (buf, "FORM", 4))
01345 {
01346
01347 len = source->read4high();
01348
01349 start = source->getPos();
01350
01351
01352 source->read (buf, 4);
01353
01354
01355 if (!memcmp (buf, "XMID", 4))
01356 {
01357 cerr << "Warning: XMIDI doesn't have XDIR" << endl;
01358 num_tracks = 1;
01359
01360 }
01361 else if (memcmp (buf, "XDIR", 4))
01362 {
01363 cerr << "Not a recognised XMID" << endl;
01364 return 0;
01365
01366 }
01367 else
01368 {
01369 num_tracks = 0;
01370
01371 for (i = 4; i < len; i++)
01372 {
01373
01374 source->read (buf, 4);
01375
01376
01377 chunk_len = source->read4high();
01378
01379
01380 i+=8;
01381
01382 if (memcmp (buf, "INFO", 4))
01383 {
01384
01385 source->skip((chunk_len+1)&~1);
01386 i+= (chunk_len+1)&~1;
01387 continue;
01388 }
01389
01390
01391 if (chunk_len < 2)
01392 break;
01393
01394 num_tracks = source->read2();
01395 break;
01396 }
01397
01398
01399 if (num_tracks == 0)
01400 {
01401 cerr << "Not a valid XMID" << endl;
01402 return 0;
01403 }
01404
01405
01406
01407 source->seek (start+((len+1)&~1));
01408
01409
01410 source->read (buf, 4);
01411
01412
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
01420 len = source->read4high();
01421
01422
01423 source->read (buf, 4);
01424
01425
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
01435
01436 events = Calloc<XMIDIEventList*>(num_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
01455 Free (events);
01456
01457 return 0;
01458 }
01459
01460 return 1;
01461
01462 }
01463 else if (!memcmp (buf, "MThd", 4))
01464 {
01465
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
01479 if (type == 1) num_tracks = 1;
01480
01481 events = Calloc<XMIDIEventList*>(num_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 }
01507 else if (!memcmp (buf, "RIFF", 4))
01508 {
01509
01510 len = source->read4();
01511
01512
01513 source->read (buf, 4);
01514
01515
01516 if (memcmp (buf, "RMID", 4))
01517 {
01518 cerr << "Invalid RMID" << endl;
01519 return 0;
01520 }
01521
01522
01523
01524 for (i = 4; i < len; i++)
01525 {
01526
01527 source->read (buf, 4);
01528
01529 chunk_len = source->read4();
01530
01531 i+=8;
01532
01533 if (memcmp (buf, "data", 4))
01534 {
01535
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
01554
01555 int XMIDIEventList::Write (const char *filename)
01556 {
01557 std::FILE *file = U7open (filename, "wb");
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
01575 if (!dest)
01576 {
01577
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);
01592
01593 len = ConvertListToMTrk (dest);
01594
01595 return len + 14;
01596 }
01597
01598
01599
01600
01601
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
01625
01626
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
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
01673
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
01685
01686 case 0xC: case 0xD:
01687 if (dest) dest->write1(event->data[0]);
01688 i++;
01689 break;
01690
01691
01692
01693
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
01716 default:
01717 cerr << "Not supposed to see this" << endl;
01718 break;
01719 }
01720 }
01721
01722
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
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