1 #include "MidiStore.h" 2 #include "MidiEvent.h" 3 4 #include <File.h> 5 #include <string.h> //For strcmp(...) 6 #include <stdio.h> //For printf(...) 7 #include <Debug.h> 8 #include <List.h> 9 10 //----------------------------------------------- 11 12 //----------------------------------------------- 13 //----------------------------------------------- 14 //----------------------------------------------- 15 16 int CompareEvents(const void* event1, const void* event2) 17 { 18 return ((BMidiEvent*)event1)->time - ((BMidiEvent*)event2)->time; 19 } 20 21 //----------------------------------------------- 22 23 BMidiStore::BMidiStore() 24 { 25 events = new BList(); 26 fFile = NULL; 27 fFileBuffer = NULL; 28 fFileBufferMax = 0; 29 fNeedsSorting = false; 30 fDivision = 480; 31 fNumTracks = 1; 32 fStartTime = 0; 33 fCurrEvent = 0; 34 } 35 36 //----------------------------------------------- 37 38 BMidiStore::~BMidiStore() 39 { 40 int32 count = events->CountItems(); 41 for (int i = count - 1; i >= 0; i--) 42 { 43 delete (BMidiEvent*) events->RemoveItem(i); 44 } 45 delete events; 46 } 47 48 //----------------------------------------------- 49 50 void BMidiStore::NoteOff(uchar chan, uchar note, uchar vel, uint32 time) 51 { 52 AddEvent(time, true, BMidiEvent::OP_NOTE_OFF, chan, note, vel); 53 } 54 55 //----------------------------------------------- 56 57 void BMidiStore::NoteOn(uchar chan, uchar note, uchar vel, uint32 time) 58 { 59 AddEvent(time, true, BMidiEvent::OP_NOTE_ON, chan, note, vel); 60 } 61 62 //----------------------------------------------- 63 64 void BMidiStore::KeyPressure(uchar chan, uchar note, uchar pres, uint32 time) 65 { 66 AddEvent(time, true, BMidiEvent::OP_KEY_PRESSURE, chan, note, pres); 67 } 68 69 //----------------------------------------------- 70 71 void BMidiStore::ControlChange(uchar chan, uchar ctrl_num, uchar ctrl_val, uint32 time) 72 { 73 AddEvent(time, true, BMidiEvent::OP_CONTROL_CHANGE, chan, ctrl_num, ctrl_val); 74 } 75 76 //----------------------------------------------- 77 78 void BMidiStore::ProgramChange(uchar chan, uchar prog_num, uint32 time) 79 { 80 AddEvent(time, true, BMidiEvent::OP_PROGRAM_CHANGE, chan, prog_num); 81 } 82 83 //----------------------------------------------- 84 85 void BMidiStore::ChannelPressure(uchar chan, uchar pres, uint32 time) 86 { 87 AddEvent(time, true, BMidiEvent::OP_CHANNEL_PRESSURE, chan, pres); 88 } 89 90 //----------------------------------------------- 91 92 void BMidiStore::PitchBend(uchar chan, uchar lsb, uchar msb, uint32 time) 93 { 94 AddEvent(time, true, BMidiEvent::OP_PITCH_BEND, chan, lsb, msb); 95 } 96 //----------------------------------------------- 97 98 void BMidiStore::SystemExclusive(void *data, size_t data_len, uint32 time) 99 { 100 BMidiEvent *e = new BMidiEvent; 101 e->opcode = BMidiEvent::OP_SYSTEM_EXCLUSIVE; 102 e->time = time; 103 e->systemExclusive.data = new uint8[data_len]; 104 memcpy(e->systemExclusive.data, data, data_len); 105 e->systemExclusive.dataLength = data_len; 106 AddSystemExclusive(e, sizeof(BMidiEvent)); 107 } 108 109 //----------------------------------------------- 110 111 void BMidiStore::SystemCommon(uchar stat_byte, uchar data1, uchar data2, uint32 time) 112 { 113 AddEvent(time, true, BMidiEvent::OP_SYSTEM_COMMON, stat_byte, data1, data2); 114 } 115 116 //----------------------------------------------- 117 118 void BMidiStore::SystemRealTime(uchar stat_byte, uint32 time) 119 { 120 AddEvent(time, true, BMidiEvent::OP_SYSTEM_REAL_TIME, stat_byte); 121 } 122 123 //----------------------------------------------- 124 125 void BMidiStore::TempoChange(int32 bpm, uint32 time) 126 { 127 AddEvent(time, true, BMidiEvent::OP_TEMPO_CHANGE, bpm); 128 } 129 130 //----------------------------------------------- 131 132 status_t BMidiStore::Import(const entry_ref *ref) 133 {//ToTest 134 status_t status = B_NO_ERROR; 135 136 fFile = new BFile(ref, B_READ_ONLY); 137 138 status = fFile->InitCheck(); 139 if (status != B_OK) 140 { 141 delete fFile; 142 return status; 143 } 144 145 status = ReadHeader(); 146 if (status != B_OK) 147 { 148 delete fFile; 149 return status; 150 } 151 152 Read16Bit(); //Format of the MidiFile 153 fNumTracks = Read16Bit(); 154 fDivision = Read16Bit(); 155 fDivisionFactor = 1 / fDivision; 156 157 status = B_OK; 158 for(fCurrTrack = 0; fCurrTrack < fNumTracks; fCurrTrack++) 159 { 160 char mtrk[4]; 161 if (ReadMT(mtrk) == false) 162 { 163 PRINT(("Error while reading MTrk\n")); 164 status = B_BAD_MIDI_DATA; 165 break; 166 } 167 PRINT(("Printing Track %ld\n", fCurrTrack)); 168 169 fFileBufferSize = Read32Bit(); 170 if (fFileBufferSize > fFileBufferMax) 171 { 172 fFileBufferMax = fFileBufferSize; 173 delete fFileBuffer; 174 fFileBuffer = new uchar[fFileBufferSize]; 175 } 176 if (ReadTrack() == false) 177 { 178 PRINT(("Error while reading Trak %ld\n", fCurrTrack)); 179 status = B_BAD_MIDI_DATA; 180 break; 181 } 182 } 183 184 delete fFile; 185 delete fFileBuffer; 186 fFileBuffer = NULL; 187 SortEvents(true); 188 return status; 189 } 190 191 //----------------------------------------------- 192 193 status_t BMidiStore::Export(const entry_ref *ref, int32 format) 194 {//ToDo 195 fFile = new BFile(ref, B_READ_WRITE); 196 status_t status = fFile->InitCheck(); 197 if (status != B_OK) 198 { 199 delete fFile; 200 return status; 201 } 202 203 SortEvents(true); 204 WriteHeaderChunk(format); 205 206 off_t position_of_length = 0; 207 208 if (format == 0) 209 {//Format is 0 just one track 210 position_of_length = fFile->Position() + 4; 211 WriteTrack(-1); 212 fFile->Seek(position_of_length, SEEK_SET); 213 Write32Bit(fNumBytesWritten); 214 fFile->Seek(0, SEEK_END); 215 } 216 217 if (format == 1) 218 {//Format is 1, number of track is fNumTracks initialized when import file 219 for (int32 i = 0; i < fNumTracks; i++) 220 { 221 position_of_length = fFile->Position() + 4; 222 WriteTrack(i); 223 fFile->Seek(position_of_length, SEEK_SET); 224 Write32Bit(fNumBytesWritten); 225 fFile->Seek(0, SEEK_END); 226 } 227 } 228 229 return B_OK; 230 } 231 232 //----------------------------------------------- 233 234 void BMidiStore::SortEvents(bool force) 235 { 236 events->SortItems(CompareEvents); 237 } 238 239 //----------------------------------------------- 240 241 uint32 BMidiStore::CountEvents() const 242 {//ToTest 243 return events->CountItems(); 244 } 245 246 //----------------------------------------------- 247 248 uint32 BMidiStore::CurrentEvent() const 249 {//ToTest 250 return fCurrEvent; 251 } 252 253 //----------------------------------------------- 254 255 void BMidiStore::SetCurrentEvent(uint32 event_num) 256 {//ToTest 257 fCurrEvent = event_num; 258 } 259 260 //----------------------------------------------- 261 262 uint32 BMidiStore::DeltaOfEvent(uint32 event_num) const 263 {//ToDo 264 return 0; 265 } 266 267 //----------------------------------------------- 268 269 uint32 BMidiStore::EventAtDelta(uint32 time) const 270 {//ToDo 271 return 0; 272 } 273 274 //----------------------------------------------- 275 276 uint32 BMidiStore::BeginTime() const 277 {//ToTest 278 return fStartTime; 279 } 280 281 //----------------------------------------------- 282 283 void BMidiStore::SetTempo(int32 bpm) 284 {//ToTest 285 fTempo = bpm; 286 } 287 288 //----------------------------------------------- 289 290 int32 BMidiStore::Tempo() const 291 {//ToTest 292 return fTempo; 293 } 294 295 //----------------------------------------------- 296 //----------------------------------------------- 297 //----------------------------------------------- 298 //----------------------------------------------- 299 300 void BMidiStore::Run() 301 { 302 fStartTime = B_NOW; 303 SortEvents(true); 304 while (KeepRunning()) 305 { 306 BMidiEvent* event = (BMidiEvent*)events->ItemAt(fCurrEvent); 307 308 if (event == NULL) return; 309 310 printf("Curr Event : %ld, Time : %ld\n", fCurrEvent, event->time); 311 312 fCurrTime = event->time; 313 event->time += fStartTime; 314 // SprayMidiEvent(event); 315 event->time = fCurrTime; 316 317 fCurrEvent++; 318 } 319 } 320 321 //----------------------------------------------- 322 323 void BMidiStore::AddEvent(uint32 time, bool inMS, uchar type, uchar data1 = 0, uchar data2 = 0, uchar data3 = 0, uchar data4 = 0) 324 {//ToTest 325 if (!inMS) 326 { 327 time = TicksToMilliseconds(time); 328 } 329 BMidiEvent *e = new BMidiEvent(); 330 e->time = time; 331 switch (type) 332 { 333 case BMidiEvent::OP_NOTE_OFF : 334 e->opcode = BMidiEvent::OP_NOTE_OFF; 335 e->noteOff.channel = data1; 336 e->noteOff.note = data2; 337 e->noteOff.velocity = data3; 338 break; 339 case BMidiEvent::OP_NOTE_ON : 340 e->opcode = BMidiEvent::OP_NOTE_ON; 341 e->noteOn.channel = data1; 342 e->noteOn.note = data2; 343 e->noteOn.velocity = data3; 344 break; 345 case BMidiEvent::OP_KEY_PRESSURE : 346 e->opcode = BMidiEvent::OP_KEY_PRESSURE; 347 e->keyPressure.channel = data1; 348 e->keyPressure.note = data2; 349 e->keyPressure.pressure = data3; 350 break; 351 case BMidiEvent::OP_CONTROL_CHANGE : 352 e->opcode = BMidiEvent::OP_CONTROL_CHANGE; 353 e->controlChange.channel = data1; 354 e->controlChange.controlNumber = data2; 355 e->controlChange.controlValue = data3; 356 break; 357 case BMidiEvent::OP_PROGRAM_CHANGE : 358 e->opcode = BMidiEvent::OP_PROGRAM_CHANGE; 359 e->programChange.channel = data1; 360 e->programChange.programNumber = data2; 361 break; 362 case BMidiEvent::OP_CHANNEL_PRESSURE : 363 e->opcode = BMidiEvent::OP_CHANNEL_PRESSURE; 364 e->channelPressure.channel = data1; 365 e->channelPressure.pressure = data2; 366 break; 367 case BMidiEvent::OP_PITCH_BEND : 368 e->opcode = BMidiEvent::OP_PITCH_BEND; 369 e->pitchBend.channel = data1; 370 e->pitchBend.lsb = data2; 371 e->pitchBend.msb = data3; 372 break; 373 case BMidiEvent::OP_SYSTEM_COMMON : 374 e->opcode = BMidiEvent::OP_SYSTEM_COMMON; 375 e->systemCommon.status = data1; 376 e->systemCommon.data1 = data2; 377 e->systemCommon.data2 = data3; 378 break; 379 case BMidiEvent::OP_SYSTEM_REAL_TIME : 380 e->opcode = BMidiEvent::OP_SYSTEM_REAL_TIME; 381 e->systemRealTime.status = data1; 382 break; 383 case BMidiEvent::OP_TEMPO_CHANGE : 384 e->opcode = BMidiEvent::OP_TEMPO_CHANGE; 385 e->tempoChange.beatsPerMinute = data1; 386 break; 387 case BMidiEvent::OP_ALL_NOTES_OFF : 388 e->opcode = BMidiEvent::OP_ALL_NOTES_OFF; 389 e->allNotesOff.justChannel = data1; 390 break; 391 default : 392 delete e; 393 return; 394 } 395 events->AddItem(e); 396 } 397 398 //----------------------------------------------- 399 400 void BMidiStore::AddSystemExclusive(void* data, size_t dataLength) 401 {//ToTest 402 // BMidiEvent *e = new BMidiEvent(); 403 // e->time = 0; 404 // e->systemExclusive.data = (uint8*)data; 405 // e->systemExclusive.dataLength = dataLength; 406 events->AddItem(data); 407 } 408 409 //----------------------------------------------- 410 411 status_t BMidiStore::ReadHeader() 412 {//ToTest 413 char mthd[4]; 414 if (ReadMT(mthd) == false) 415 return B_ERROR; 416 if(strncmp(mthd, "MThd", 4) != 0) 417 { 418 return B_BAD_MIDI_DATA; 419 } 420 421 int32 length = Read32Bit(); 422 if (length != 6) 423 { 424 return B_BAD_MIDI_DATA; 425 } 426 return B_OK; 427 } 428 429 //----------------------------------------------- 430 431 bool BMidiStore::ReadMT(char *data) 432 {//ToTest 433 return fFile->Read(data, 4) == 4; 434 } 435 436 //----------------------------------------------- 437 438 int32 BMidiStore::Read32Bit() 439 {//ToTest 440 uchar char32bit[4]; 441 fFile->Read(char32bit, 4); 442 return To32Bit(char32bit[0], char32bit[1], char32bit[2], char32bit[3]); 443 } 444 445 //----------------------------------------------- 446 447 int32 BMidiStore::EGetC() 448 {//ToDo 449 return 0; 450 } 451 452 //----------------------------------------------- 453 454 int32 BMidiStore::To32Bit(int32 data1, int32 data2, int32 data3, int32 data4) 455 {//ToTest 456 return data1 << 24 | data2 << 16 | data3 << 8 | data4; 457 } 458 459 //----------------------------------------------- 460 461 int32 BMidiStore::Read16Bit() 462 {//ToTest 463 uchar char16bit[2]; 464 fFile->Read(char16bit, 2); 465 return To16Bit(char16bit[0], char16bit[1]); 466 } 467 468 //----------------------------------------------- 469 470 int32 BMidiStore::To16Bit(int32 data1, int32 data2) 471 {//ToTest 472 return (uint32)data1 << 8 | (uint32)data2; 473 } 474 475 //----------------------------------------------- 476 477 bool BMidiStore::ReadTrack() 478 {//ToTest 479 if (fFile->Read(fFileBuffer, fFileBufferSize) != fFileBufferSize) 480 return false; 481 fNeedsSorting = true; 482 fFileBufferIndex = 0; 483 uint32 ticks = 0; 484 uint32 time = 0; //in ms 485 uchar data = 0; 486 uint32 ForTempo = 0; 487 //fStartTime = 0; 488 while (fFileBufferIndex < (fFileBufferSize - 3)) 489 { 490 ticks += ReadVariNum(); 491 time = /*fStartTime + */TicksToMilliseconds(ticks); 492 uchar temp = fFileBuffer[fFileBufferIndex]; 493 if (temp > 0x7F) 494 { 495 data = temp; 496 fFileBufferIndex++; 497 } 498 if (data < 0x80) 499 { 500 PRINT(("Big Problem, data : %d, Index : %ld\n", data, fFileBufferIndex)); 501 return false; 502 } 503 switch (data & 0xF0) 504 { 505 case B_NOTE_OFF : 506 NoteOff(data & 0x0F, fFileBuffer[fFileBufferIndex], 507 fFileBuffer[fFileBufferIndex + 1], time); 508 fFileBufferIndex += 2; 509 break; 510 case B_NOTE_ON : 511 NoteOn(data & 0x0F, fFileBuffer[fFileBufferIndex], 512 fFileBuffer[fFileBufferIndex + 1], time); 513 fFileBufferIndex += 2; 514 break; 515 case B_KEY_PRESSURE : 516 KeyPressure(data & 0x0F, fFileBuffer[fFileBufferIndex], 517 fFileBuffer[fFileBufferIndex + 1], time); 518 fFileBufferIndex += 2; 519 break; 520 case B_CONTROL_CHANGE : 521 ControlChange(data & 0x0F, fFileBuffer[fFileBufferIndex], 522 fFileBuffer[fFileBufferIndex + 1], time); 523 fFileBufferIndex += 2; 524 break; 525 case B_PITCH_BEND : 526 PitchBend(data & 0x0F, fFileBuffer[fFileBufferIndex], 527 fFileBuffer[fFileBufferIndex + 1], time); 528 fFileBufferIndex += 2; 529 break; 530 case B_PROGRAM_CHANGE : 531 ProgramChange(data & 0x0F, fFileBuffer[fFileBufferIndex], time); 532 fFileBufferIndex += 2; 533 break; 534 case B_CHANNEL_PRESSURE : 535 ChannelPressure(data & 0x0F, fFileBuffer[fFileBufferIndex], time); 536 fFileBufferIndex += 1; 537 break; 538 } 539 switch (data) 540 { 541 case B_SYS_EX_START : 542 temp = MsgLength(); 543 SystemExclusive(&fFileBuffer[fFileBufferIndex - 1], temp + 2, time); 544 fFileBufferIndex += temp; 545 break; 546 case B_SONG_POSITION : 547 SystemCommon(data, fFileBuffer[fFileBufferIndex], fFileBuffer[fFileBufferIndex + 1], time); 548 fFileBufferIndex += 2; 549 break; 550 case B_MIDI_TIME_CODE : 551 case B_SONG_SELECT : 552 SystemCommon(data, fFileBuffer[fFileBufferIndex], 0, time); 553 fFileBufferIndex += 1; 554 break; 555 case B_TUNE_REQUEST : 556 case B_TIMING_CLOCK : 557 SystemCommon(data, 0, 0, time); 558 break; 559 case B_START : 560 case B_CONTINUE : 561 case B_STOP : 562 case B_ACTIVE_SENSING : 563 SystemRealTime(data, time); 564 break; 565 case B_SYSTEM_RESET : 566 temp = fFileBuffer[fFileBufferIndex]; 567 if (temp == 0x2F) 568 return true; 569 if (temp == 0x51) 570 {//Calcul of the tempo is wrong 571 fFileBufferIndex +=2; 572 ForTempo = fFileBuffer[fFileBufferIndex++] << 8; 573 ForTempo |= fFileBuffer[fFileBufferIndex++]; 574 ForTempo = (ForTempo << 8) | fFileBuffer[fFileBufferIndex++]; 575 // ForTempo /= 2500; 576 TempoChange(ForTempo, time); 577 } 578 else 579 { 580 temp = fFileBuffer[fFileBufferIndex + 1] + 3; 581 SystemExclusive(&fFileBuffer[fFileBufferIndex - 1], temp, time); 582 fFileBufferIndex += temp - 1; 583 } 584 break; 585 default : 586 if (data >= 0xF0) 587 printf("Midi Data not Defined\n"); 588 } 589 } 590 return true; 591 } 592 593 //----------------------------------------------- 594 595 int32 BMidiStore::ReadVariNum() 596 {//ToTest 597 int32 result = 0; 598 uchar tempo = 0; 599 while (fFileBufferIndex < fFileBufferSize) 600 { 601 tempo = fFileBuffer[fFileBufferIndex++]; 602 result |= tempo & 0x7F; 603 if ((tempo & 0x80) == 0) 604 return result; 605 result <<= 7; 606 } 607 return B_ERROR; 608 } 609 610 //----------------------------------------------- 611 612 void BMidiStore::ChannelMessage(int32, int32, int32) 613 {//ToDo 614 615 } 616 617 //----------------------------------------------- 618 619 void BMidiStore::MsgInit() 620 {//ToDo 621 622 } 623 624 //----------------------------------------------- 625 626 void BMidiStore::MsgAdd(int32) 627 {//ToDo 628 629 } 630 631 //----------------------------------------------- 632 633 void BMidiStore::BiggerMsg() 634 {//ToDo 635 636 } 637 638 //----------------------------------------------- 639 640 void BMidiStore::MetaEvent(int32) 641 {//ToDo 642 643 } 644 645 //----------------------------------------------- 646 647 int32 BMidiStore::MsgLength() 648 {//ToTest 649 int32 t = 0; 650 while (fFileBuffer[fFileBufferIndex + t] != 0xF7) 651 { 652 if (fFileBufferIndex + t > fFileBufferSize - 3) 653 return -1; 654 else 655 t++; 656 } 657 return t; 658 } 659 660 //----------------------------------------------- 661 662 uchar *BMidiStore::Msg() 663 {//ToDo 664 return 0; 665 } 666 667 //----------------------------------------------- 668 669 void BMidiStore::BadByte(int32) 670 {//ToDo 671 672 } 673 674 //----------------------------------------------- 675 676 677 int32 BMidiStore::PutC(int32 c) 678 {//ToDo 679 return 0; 680 } 681 682 //----------------------------------------------- 683 684 bool BMidiStore::WriteTrack(int32 track) 685 {//ToTest 686 uchar temp[4] = {0x00, 0x00, 0x00, 0x00}; 687 WriteTrackChunk(track); 688 fNumBytesWritten = 0; 689 uint32 ticks = 0; 690 int32 i = 0; 691 // If track == -1 write all events 692 BMidiEvent *event = (BMidiEvent*)events->ItemAt(i++); 693 if (event != NULL) 694 fCurrTime = event->time; 695 while (event != NULL) 696 { 697 ticks = MillisecondsToTicks(event->time - fCurrTime); 698 switch(event->opcode) 699 { 700 case BMidiEvent::OP_NOTE_OFF : 701 if ((track == -1) || (track == event->noteOff.channel)) 702 { 703 temp[0] = event->noteOff.note; 704 temp[1] = event->noteOff.velocity; 705 WriteMidiEvent(ticks, B_NOTE_OFF, event->noteOff.channel, temp, 2); 706 } 707 break; 708 case BMidiEvent::OP_NOTE_ON : 709 if ((track == -1) || (track == event->noteOn.channel)) 710 { 711 temp[0] = event->noteOn.note; 712 temp[1] = event->noteOn.velocity; 713 WriteMidiEvent(ticks, B_NOTE_ON, event->noteOn.channel, temp, 2); 714 } 715 break; 716 case BMidiEvent::OP_KEY_PRESSURE : 717 if ((track == -1) || (track == event->keyPressure.channel)) 718 { 719 temp[0] = event->keyPressure.note; 720 temp[1] = event->keyPressure.pressure; 721 WriteMidiEvent(ticks, B_KEY_PRESSURE, event->keyPressure.channel, temp, 2); 722 } 723 break; 724 case BMidiEvent::OP_CONTROL_CHANGE : 725 if ((track == -1) || (track == event->controlChange.channel)) 726 { 727 temp[0] = event->controlChange.controlNumber; 728 temp[1] = event->controlChange.controlValue; 729 WriteMidiEvent(ticks, B_CONTROL_CHANGE, event->controlChange.channel, temp, 2); 730 } 731 break; 732 case BMidiEvent::OP_PROGRAM_CHANGE : 733 if ((track == -1) || (track == event->programChange.channel)) 734 { 735 temp[0] = event->programChange.programNumber; 736 WriteMidiEvent(ticks, B_PROGRAM_CHANGE, event->programChange.channel, temp, 1); 737 } 738 break; 739 case BMidiEvent::OP_CHANNEL_PRESSURE : 740 if ((track == -1) || (track == event->channelPressure.channel)) 741 { 742 temp[0] = event->channelPressure.pressure; 743 WriteMidiEvent(ticks, B_CHANNEL_PRESSURE, event->channelPressure.channel, temp, 1); 744 } 745 break; 746 case BMidiEvent::OP_PITCH_BEND : 747 if ((track == -1) || (track == event->pitchBend.channel)) 748 { 749 temp[0] = event->pitchBend.lsb; 750 temp[1] = event->pitchBend.msb; 751 WriteMidiEvent(ticks, B_PITCH_BEND, event->pitchBend.channel, temp, 2); 752 } 753 break; 754 case BMidiEvent::OP_SYSTEM_COMMON : 755 if ((track == -1) || (track == 0)) 756 { 757 temp[0] = event->systemCommon.data1; 758 temp[1] = event->systemCommon.data2; 759 WriteMetaEvent(ticks, event->systemCommon.status, temp, 2); 760 } 761 break; 762 case BMidiEvent::OP_SYSTEM_REAL_TIME : 763 if ((track == -1) || (track == 0)) 764 { 765 WriteMetaEvent(ticks, event->systemRealTime.status, temp, 0); 766 } 767 break; 768 case BMidiEvent::OP_SYSTEM_EXCLUSIVE : 769 if ((track == -1) || (track == 0)) 770 { 771 WriteSystemExclusiveEvent(ticks, event->systemExclusive.data, event->systemExclusive.dataLength); 772 } 773 break; 774 case BMidiEvent::OP_TEMPO_CHANGE : 775 if ((track == -1) || (track == 0)) 776 { 777 WriteTempo(ticks, event->tempoChange.beatsPerMinute); 778 } 779 break; 780 //Not used 781 case BMidiEvent::OP_NONE : 782 case BMidiEvent::OP_ALL_NOTES_OFF : 783 case BMidiEvent::OP_TRACK_END : 784 break; 785 } 786 // } 787 fCurrTime = event->time; 788 event = (BMidiEvent*)events->ItemAt(i++); 789 } 790 791 Write16Bit(0xFF2F); 792 EPutC(0); 793 return true; 794 } 795 796 //----------------------------------------------- 797 798 void BMidiStore::WriteTempoTrack() 799 {//ToDo 800 } 801 802 //----------------------------------------------- 803 804 bool BMidiStore::WriteTrackChunk(int32 whichTrack) 805 {//ToTest 806 Write32Bit('MTrk'); 807 Write32Bit(6); 808 return true; 809 } 810 811 //----------------------------------------------- 812 813 void BMidiStore::WriteHeaderChunk(int32 format) 814 {//ToTest 815 Write32Bit('MThd'); 816 Write32Bit(6); 817 Write16Bit(format); 818 if (format == 0) 819 fNumTracks = 1; 820 Write16Bit(fNumTracks); 821 Write16Bit(fDivision); 822 } 823 824 //----------------------------------------------- 825 826 bool BMidiStore::WriteMidiEvent(uint32 deltaTime, uint32 type, uint32 channel, uchar* data, uint32 size) 827 {//ToTest 828 WriteVarLen(deltaTime); 829 if (EPutC(type | channel) != 1) 830 return false; 831 while (size > 0) 832 { 833 if (EPutC(*data) != 1) 834 return false; 835 data++; 836 size--; 837 } 838 return true; 839 } 840 841 //----------------------------------------------- 842 843 bool BMidiStore::WriteMetaEvent(uint32 deltaTime, uint32 type, uchar* data, uint32 size) 844 {//ToTest 845 WriteVarLen(deltaTime); 846 if (EPutC(type) != 1) 847 return false; 848 while (size > 0) 849 { 850 if (EPutC(*data) != 1) 851 return false; 852 data++; 853 size--; 854 } 855 return true; 856 } 857 858 //----------------------------------------------- 859 860 bool BMidiStore::WriteSystemExclusiveEvent(uint32 deltaTime, uchar* data, uint32 size) 861 {//ToTest 862 WriteVarLen(deltaTime); 863 while (size > 0) 864 { 865 if (EPutC(*data) != 1) 866 return false; 867 data++; 868 size--; 869 } 870 return true; 871 } 872 873 //----------------------------------------------- 874 875 void BMidiStore::WriteTempo(uint32 deltaTime, int32 tempo) 876 {//ToTest 877 WriteVarLen(deltaTime); 878 Write16Bit(0xFF51); 879 EPutC(3); 880 EPutC((tempo >> 16) & 0xFF); 881 EPutC((tempo >> 8) & 0xFF); 882 EPutC(tempo & 0xFF); 883 } 884 885 //----------------------------------------------- 886 887 void BMidiStore::WriteVarLen(uint32 value) 888 {//ToTest 889 uint32 buffer = value & 0x7F; 890 while ( (value >>= 7) ) 891 { 892 buffer <<= 8; 893 buffer |= ((value & 0x7F) | 0x80); 894 } 895 while (true) 896 { 897 EPutC(buffer); 898 if (buffer & 0x80) 899 buffer >>= 8; 900 else 901 break; 902 } 903 } 904 905 //----------------------------------------------- 906 907 void BMidiStore::Write32Bit(uint32 data) 908 {//ToTest 909 EPutC((data >> 24) & 0xFF); 910 EPutC((data >> 16) & 0xFF); 911 EPutC((data >> 8) & 0xFF); 912 EPutC(data & 0xFF); 913 } 914 915 //----------------------------------------------- 916 917 void BMidiStore::Write16Bit(ushort data) 918 {//ToTest 919 EPutC((data >> 8) & 0xFF); 920 EPutC(data & 0xFF); 921 } 922 923 //----------------------------------------------- 924 925 int32 BMidiStore::EPutC(uchar c) 926 {//ToTest 927 fNumBytesWritten++; 928 return fFile->Write(&c, 1); 929 } 930 931 //----------------------------------------------- 932 933 934 uint32 BMidiStore::TicksToMilliseconds(uint32 ticks) const 935 {//ToTest 936 return ((uint64)ticks * 1000) / fDivision; 937 } 938 939 //----------------------------------------------- 940 941 uint32 BMidiStore::MillisecondsToTicks(uint32 ms) const 942 {//ToTest 943 return ((uint64)ms * fDivision) / 1000; 944 } 945 946 //----------------------------------------------- 947 948 void BMidiStore::_ReservedMidiStore1() 949 { 950 } 951 952 //----------------------------------------------- 953 954 void BMidiStore::_ReservedMidiStore2() 955 { 956 } 957 958 //----------------------------------------------- 959 960 void BMidiStore::_ReservedMidiStore3() 961 { 962 } 963 964 //----------------------------------------------- 965 //----------------------------------------------- 966 //----------------------------------------------- 967 //----------------------------------------------- 968 //----------------------------------------------- 969 //----------------------------------------------- 970 //----------------------------------------------- 971 //----------------------------------------------- 972 //----------------------------------------------- 973 //----------------------------------------------- 974