| | 195 | |
| | 196 | #if 0 |
| | 197 | |
| | 198 | /* |
| | 199 | * Note: this code that follows is historic from 1992, before namespaces and bool existed in C++ |
| | 200 | * The plan is to move the concepts and algorithms from this old code into the new form. |
| | 201 | * In this old form, the EMIDITrack class inherited from MIDITrack. In the new form it ought not to, |
| | 202 | * as it breaks the 'is-a' rule. |
| | 203 | */ |
| | 204 | |
| | 205 | #include "world.h" |
| | 206 | #pragma hdrstopd |
| | 207 | |
| | 208 | |
| | 209 | |
| | 210 | #include <ETrack.hh> |
| | 211 | #include <MMatrix.hh> |
| | 212 | |
| | 213 | static int cmpmsgtime( const void *a, const void *b ) |
| | 214 | { |
| | 215 | register const TimedMIDIMessage *m1=(TimedMIDIMessage * )a; |
| | 216 | register const TimedMIDIMessage *m2=(TimedMIDIMessage * )b; |
| | 217 | |
| | 218 | |
| | 219 | // |
| | 220 | // Check if message is a NOP. if it is, then propegate them to |
| | 221 | // the end of track. |
| | 222 | // |
| | 223 | |
| | 224 | |
| | 225 | Boolean n1 = m1->IsNOP(); |
| | 226 | Boolean n2 = m2->IsNOP(); |
| | 227 | |
| | 228 | if( n1 && n2 ) |
| | 229 | return 0; |
| | 230 | |
| | 231 | if( n1 ) |
| | 232 | return 1; |
| | 233 | if( n2 ) |
| | 234 | return -1; |
| | 235 | |
| | 236 | |
| | 237 | // |
| | 238 | // Compare the event times |
| | 239 | // |
| | 240 | |
| | 241 | ulong t1,t2; |
| | 242 | |
| | 243 | t1=m1->GetTime(); |
| | 244 | t2=m2->GetTime(); |
| | 245 | |
| | 246 | if( t1<t2 ) |
| | 247 | return -1; |
| | 248 | if( t1>t2 ) |
| | 249 | return 1; |
| | 250 | |
| | 251 | // the times are the same. put note ons first. |
| | 252 | |
| | 253 | if( m1->GetStatus()==M_NOTE_ON && m1->byte2!=0 ) |
| | 254 | return -1; |
| | 255 | |
| | 256 | if( m2->GetStatus()==M_NOTE_ON && m2->byte2!=0 ) |
| | 257 | return 1; |
| | 258 | |
| | 259 | return 0; |
| | 260 | } |
| | 261 | |
| | 262 | void EMIDITrack::Sort() |
| | 263 | { |
| | 264 | // |
| | 265 | // sort all the midi messages in the buffer by time. |
| | 266 | // do not sort the last event. |
| | 267 | // |
| | 268 | |
| | 269 | qsort( buffer, last_event, sizeof( *buffer ), cmpmsgtime ); |
| | 270 | |
| | 271 | // |
| | 272 | // TO DO: Clear away all NOP's at the end of the track. |
| | 273 | // |
| | 274 | |
| | 275 | // |
| | 276 | // ok, now find the maximum time value used in the track. |
| | 277 | // this would be the maximum of buffer[last_event-1] and |
| | 278 | // buffer[last_event]. Set the last event ( the data end event) |
| | 279 | // to the maximum time. |
| | 280 | // |
| | 281 | |
| | 282 | ulong t1=buffer[last_event-1].GetTime(); |
| | 283 | ulong t2=buffer[last_event].GetTime(); |
| | 284 | |
| | 285 | if( t1>t2 ) |
| | 286 | buffer[last_event].SetTime( t1 ); |
| | 287 | } |
| | 288 | |
| | 289 | |
| | 290 | void EMIDITrack::CopyEvent( MIDITrack *t, unsigned int ev ) |
| | 291 | { |
| | 292 | |
| | 293 | // |
| | 294 | // Get the event from the other track. |
| | 295 | // |
| | 296 | |
| | 297 | TimedMIDIMessage m; |
| | 298 | |
| | 299 | t->GetEvent( ev, m ); |
| | 300 | |
| | 301 | // |
| | 302 | // is it a mark? |
| | 303 | // |
| | 304 | |
| | 305 | if( m.IsMark() ) |
| | 306 | { |
| | 307 | // |
| | 308 | // Is it Sys-Ex? |
| | 309 | // |
| | 310 | //if( m.IsSysEx() ) |
| | 311 | //{ |
| | 312 | // |
| | 313 | // yes, make a new sys-ex buffer and copy the |
| | 314 | // sysex into it. |
| | 315 | // |
| | 316 | |
| | 317 | //SysEx *e = new SysEx; |
| | 318 | |
| | 319 | // |
| | 320 | // TO DO: Copy the SysEx |
| | 321 | // |
| | 322 | |
| | 323 | //} |
| | 324 | |
| | 325 | // |
| | 326 | // Is it a Text event? |
| | 327 | // |
| | 328 | |
| | 329 | //if( m.IsText() ) |
| | 330 | //{ |
| | 331 | // |
| | 332 | // yes,make a new MIDIText event and copy the |
| | 333 | // original into it. |
| | 334 | // |
| | 335 | |
| | 336 | //MIDIText *t = new MIDIText; |
| | 337 | |
| | 338 | // |
| | 339 | // TO DO: Copy the MIDIText |
| | 340 | // |
| | 341 | //} |
| | 342 | |
| | 343 | // |
| | 344 | // Is it a DataEnd event? |
| | 345 | // |
| | 346 | |
| | 347 | if( m.IsDataEnd() ) |
| | 348 | { |
| | 349 | // |
| | 350 | // Yes, ignore it. |
| | 351 | // |
| | 352 | |
| | 353 | return; |
| | 354 | } |
| | 355 | |
| | 356 | // |
| | 357 | // All other marks are just copied over |
| | 358 | // |
| | 359 | |
| | 360 | } |
| | 361 | |
| | 362 | Put( m ); |
| | 363 | } |
| | 364 | |
| | 365 | |
| | 366 | void EMIDITrack::Compress() |
| | 367 | { |
| | 368 | unsigned int from_ev; |
| | 369 | unsigned int to_ev; |
| | 370 | unsigned int nop_count=0; |
| | 371 | |
| | 372 | // |
| | 373 | // find the first NOP |
| | 374 | // |
| | 375 | |
| | 376 | for( to_ev=0; to_ev<last_event; to_ev++ ) |
| | 377 | { |
| | 378 | if( buffer[to_ev].IsNOP() ) |
| | 379 | break; |
| | 380 | } |
| | 381 | |
| | 382 | // |
| | 383 | // if there is no NOP, then there is no way to compress |
| | 384 | // |
| | 385 | |
| | 386 | if( to_ev==last_event ) |
| | 387 | return; |
| | 388 | |
| | 389 | |
| | 390 | // |
| | 391 | // go through the buffer and compress, including the last DATA END event |
| | 392 | // |
| | 393 | |
| | 394 | for( from_ev=to_ev+1; from_ev<=last_event; from_ev++ ) |
| | 395 | { |
| | 396 | // |
| | 397 | // find the next non NOP event. |
| | 398 | // |
| | 399 | |
| | 400 | if( !buffer[from_ev].IsNOP() ) |
| | 401 | { |
| | 402 | |
| | 403 | // |
| | 404 | // keep track of how many NOP's have been replaced |
| | 405 | // |
| | 406 | |
| | 407 | nop_count++; |
| | 408 | |
| | 409 | // |
| | 410 | // copy the found event to the NOP event |
| | 411 | // |
| | 412 | |
| | 413 | buffer[to_ev]=buffer[from_ev]; |
| | 414 | |
| | 415 | // |
| | 416 | // put a NOP in the original event |
| | 417 | // |
| | 418 | |
| | 419 | buffer[from_ev].SetNOP(); |
| | 420 | |
| | 421 | // |
| | 422 | // find the next NOP event. |
| | 423 | // |
| | 424 | |
| | 425 | for( to_ev++; to_ev<last_event; to_ev++ ) |
| | 426 | { |
| | 427 | if( buffer[to_ev].IsNOP() ) |
| | 428 | break; |
| | 429 | } |
| | 430 | |
| | 431 | // |
| | 432 | // if there is no more NOP's left, |
| | 433 | // then we are done. |
| | 434 | // |
| | 435 | |
| | 436 | if( to_ev>=last_event ) |
| | 437 | break; |
| | 438 | |
| | 439 | } |
| | 440 | } |
| | 441 | |
| | 442 | // |
| | 443 | // Ok, everything is compacted; we gotta now change the |
| | 444 | // last_event to the new value |
| | 445 | // |
| | 446 | |
| | 447 | last_event-=nop_count; |
| | 448 | |
| | 449 | } |
| | 450 | |
| | 451 | |
| | 452 | void EMIDITrack::Truncate( ulong start_time ) |
| | 453 | { |
| | 454 | // find the first event at start_time or greater |
| | 455 | // or the data end event |
| | 456 | |
| | 457 | unsigned int ev; |
| | 458 | for( ev=0; ev<last_event; ev++ ) |
| | 459 | { |
| | 460 | if( buffer[ev].IsDataEnd() ) |
| | 461 | break; |
| | 462 | |
| | 463 | if( buffer[ev].GetTime() >= start_time ) |
| | 464 | break; |
| | 465 | } |
| | 466 | |
| | 467 | // |
| | 468 | // now ev contains the event number that we truncate at |
| | 469 | // |
| | 470 | |
| | 471 | |
| | 472 | // |
| | 473 | // Search through the deleted events for Sys-Ex or MIDIText events |
| | 474 | // and free the memory for those as well. |
| | 475 | // |
| | 476 | |
| | 477 | last_event=ev; |
| | 478 | buffer[ev].SetDataEnd(); |
| | 479 | buffer[ev].SetTime(start_time); |
| | 480 | |
| | 481 | FixNotes(); |
| | 482 | } |
| | 483 | |
| | 484 | |
| | 485 | void EMIDITrack::FixNotes() |
| | 486 | { |
| | 487 | MIDIMatrix *matrix=new MIDIMatrix; |
| | 488 | TimedMIDIMessage m; |
| | 489 | |
| | 490 | // |
| | 491 | // Go through the MIDIEvents, keeping track of all note on events. |
| | 492 | // |
| | 493 | |
| | 494 | |
| | 495 | for( unsigned int ev=0; ev<=last_event; ev++ ) |
| | 496 | { |
| | 497 | if( buffer[ev].IsDataEnd() ) |
| | 498 | { |
| | 499 | m.SetTime( buffer[ev].GetTime() ); |
| | 500 | break; |
| | 501 | } |
| | 502 | matrix->Process( buffer[ev] ); |
| | 503 | } |
| | 504 | |
| | 505 | |
| | 506 | // |
| | 507 | // now put a note off message for each note that was left on |
| | 508 | // at the end of the track. Do this for each channel. |
| | 509 | // |
| | 510 | |
| | 511 | for( uchar channel=0; channel<16; channel++ ) |
| | 512 | { |
| | 513 | if( matrix->GetChannelCount(channel)>0 ) |
| | 514 | { |
| | 515 | for( uchar note=0; note<128; note++ ) |
| | 516 | { |
| | 517 | uchar num=matrix->GetNoteCount( channel,note); |
| | 518 | for( uchar c=0; c<num; c++ ) |
| | 519 | { |
| | 520 | m.NoteOff( channel, note, 64 ); |
| | 521 | Put( m ); |
| | 522 | } |
| | 523 | } |
| | 524 | } |
| | 525 | } |
| | 526 | |
| | 527 | delete matrix; |
| | 528 | } |
| | 529 | |
| | 530 | |
| | 531 | |
| | 532 | |
| | 533 | |
| | 534 | void EMIDITrack::Merge( MIDITrack *trk1, MIDITrack *trk2 ) |
| | 535 | { |
| | 536 | Clear(); |
| | 537 | |
| | 538 | unsigned int trk1_ev=0; |
| | 539 | unsigned int trk2_ev=0; |
| | 540 | unsigned int trk1_max=trk1->GetNumEvents(); |
| | 541 | unsigned int trk2_max=trk2->GetNumEvents(); |
| | 542 | |
| | 543 | // |
| | 544 | // loop until all events of both tracks are transferred |
| | 545 | // |
| | 546 | |
| | 547 | while( (trk1_ev < trk1_max) || (trk2_ev < trk2_max ) ) |
| | 548 | { |
| | 549 | |
| | 550 | // |
| | 551 | // is track 1 completed and track 2 not complete? |
| | 552 | // |
| | 553 | |
| | 554 | if( (trk1_ev >= trk1_max) && (trk2_ev < trk2_max) ) |
| | 555 | { |
| | 556 | // |
| | 557 | // yes, just copy over the events from track 2 |
| | 558 | // |
| | 559 | |
| | 560 | CopyEvent( trk2, trk2_ev++ ); |
| | 561 | |
| | 562 | // |
| | 563 | // continue the loop. no reason to |
| | 564 | // check the other if's. |
| | 565 | // |
| | 566 | continue; |
| | 567 | } |
| | 568 | |
| | 569 | // |
| | 570 | // is track 2 completed and track 1 not complete? |
| | 571 | // |
| | 572 | |
| | 573 | if( (trk2_ev >= trk2_max) && (trk1_ev < trk1_max ) ) |
| | 574 | { |
| | 575 | // |
| | 576 | // yes, just copy over the events from track 1 |
| | 577 | // |
| | 578 | |
| | 579 | CopyEvent( trk1, trk1_ev++ ); |
| | 580 | |
| | 581 | |
| | 582 | // |
| | 583 | // continue the loop. |
| | 584 | // |
| | 585 | continue; |
| | 586 | |
| | 587 | } |
| | 588 | |
| | 589 | // |
| | 590 | // ok since we got here, both tracks are not completed yet. |
| | 591 | // we gotta compare times to see which event we copy over |
| | 592 | // first. |
| | 593 | // |
| | 594 | TimedMIDIMessage m1,m2; |
| | 595 | |
| | 596 | trk1->GetEvent( trk1_ev, m1 ); |
| | 597 | trk2->GetEvent( trk2_ev, m2 ); |
| | 598 | |
| | 599 | if( m1.GetTime() < m2.GetTime() ) |
| | 600 | { |
| | 601 | // |
| | 602 | // track 1 event came first. copy it over. |
| | 603 | // |
| | 604 | CopyEvent( trk1, trk1_ev++ ); |
| | 605 | } |
| | 606 | else |
| | 607 | { |
| | 608 | // |
| | 609 | // track 2 event came first. copy it over. |
| | 610 | // |
| | 611 | |
| | 612 | CopyEvent( trk2, trk2_ev++ ); |
| | 613 | } |
| | 614 | } |
| | 615 | |
| | 616 | } |
| | 617 | |
| | 618 | |
| | 619 | void EMIDITrack::Merge( MIDITrack *trk ) |
| | 620 | { |
| | 621 | for( unsigned int ev=0; ev<trk->GetNumEvents(); ev++ ) |
| | 622 | { |
| | 623 | CopyEvent( trk, ev ); |
| | 624 | } |
| | 625 | Sort(); |
| | 626 | FixNotes(); |
| | 627 | } |
| | 628 | |
| | 629 | |
| | 630 | void EMIDITrack::Erase( ulong start, ulong end, Boolean jagged ) |
| | 631 | { |
| | 632 | |
| | 633 | // |
| | 634 | // This Erase method should work fine, erasing all events |
| | 635 | // between two times, and will keep track of all note on/off |
| | 636 | // events so that there will be no hung notes. |
| | 637 | // |
| | 638 | // the edit may be jagged or sharp. if it is jagged, |
| | 639 | // any notes left on before start time and shut off during the |
| | 640 | // erase time will not have their gate times changed. |
| | 641 | // if jagged==FALSE, then the note off's will be moved to |
| | 642 | // 'start' time. |
| | 643 | // |
| | 644 | // also, any note off messages that are AFTER 'end' time |
| | 645 | // that were turned on during the erase time will be erased |
| | 646 | // as well. |
| | 647 | // |
| | 648 | // One thing, though; if a note was turned on before 'start' |
| | 649 | // time and shut off after 'end' time, it will not be affected |
| | 650 | // by this erase method no matter what jagged is set to. |
| | 651 | // |
| | 652 | // Dealing with this situation would require that all |
| | 653 | // events be sorted afterwards. |
| | 654 | // |
| | 655 | |
| | 656 | |
| | 657 | |
| | 658 | // |
| | 659 | // Make sure we got valid values for end. |
| | 660 | // |
| | 661 | |
| | 662 | if( end<=start) |
| | 663 | return; |
| | 664 | |
| | 665 | |
| | 666 | Boolean changed=FALSE; // set to TRUE if anything is erased. |
| | 667 | |
| | 668 | |
| | 669 | // |
| | 670 | // start up the MIDIMatrix objects. |
| | 671 | // we need a MIDIMatrix to keep track of the |
| | 672 | // note ON's going into the area we are deleting |
| | 673 | // as well as a MIDIMatrix to keep track of the |
| | 674 | // note ON's that we have deleted that have |
| | 675 | // note OFF's after 'end' time. |
| | 676 | // |
| | 677 | |
| | 678 | MIDIMatrix *before_matrix = new MIDIMatrix; |
| | 679 | MIDIMatrix *during_matrix = new MIDIMatrix; |
| | 680 | |
| | 681 | |
| | 682 | // |
| | 683 | // go through all the events and 'NOP' just the ones |
| | 684 | // in that time period. |
| | 685 | // |
| | 686 | |
| | 687 | for( unsigned int ev=0; ev<last_event; ev++ ) |
| | 688 | { |
| | 689 | ulong time = buffer[ev].GetTime(); |
| | 690 | |
| | 691 | // |
| | 692 | // if the event is before our erase region, |
| | 693 | // then give it to the before_matrix object |
| | 694 | // |
| | 695 | |
| | 696 | if( time<start ) |
| | 697 | { |
| | 698 | before_matrix->Process( buffer[ev] ); |
| | 699 | continue; |
| | 700 | } |
| | 701 | |
| | 702 | |
| | 703 | if( time>=start && time<end ) |
| | 704 | { |
| | 705 | // |
| | 706 | // see if this event should be ignored or |
| | 707 | // erased. |
| | 708 | // |
| | 709 | TimedMIDIMessage m=buffer[ev]; |
| | 710 | |
| | 711 | if( ! FilterEvent( m ) ) |
| | 712 | continue; |
| | 713 | |
| | 714 | |
| | 715 | |
| | 716 | // |
| | 717 | // give this event to our during_matrix object |
| | 718 | // to keep track of note on's |
| | 719 | // |
| | 720 | |
| | 721 | during_matrix->Process( buffer[ev] ); |
| | 722 | |
| | 723 | |
| | 724 | if( buffer[ev].IsMark() ) |
| | 725 | { |
| | 726 | // |
| | 727 | // Is this event a Sys-Ex event? |
| | 728 | // |
| | 729 | |
| | 730 | if( m.IsSysEx() ) |
| | 731 | { |
| | 732 | // |
| | 733 | // yep. we delete it as well as the |
| | 734 | // sys-ex message itself. |
| | 735 | // |
| | 736 | unsigned int s=m.GetSysEx(); |
| | 737 | |
| | 738 | exclusives.Delete(s); |
| | 739 | } |
| | 740 | |
| | 741 | // |
| | 742 | // is this event a MIDIText event? |
| | 743 | // |
| | 744 | |
| | 745 | if( m.IsText() ) |
| | 746 | { |
| | 747 | // |
| | 748 | // yep. delete it and the MIDIText |
| | 749 | // event itself. |
| | 750 | // |
| | 751 | unsigned int t=m.GetText(); |
| | 752 | text.Delete(t); |
| | 753 | } |
| | 754 | |
| | 755 | // |
| | 756 | // all other sequencer marks just get deleted. |
| | 757 | // |
| | 758 | |
| | 759 | changed=TRUE; |
| | 760 | buffer[ev].SetNOP(); |
| | 761 | |
| | 762 | } |
| | 763 | else |
| | 764 | { |
| | 765 | // |
| | 766 | // ok, we gotta make sure that if this is a |
| | 767 | // note off event, we do not 'NOP' it if the |
| | 768 | // corresponding note on event was before |
| | 769 | // the start time. |
| | 770 | // |
| | 771 | |
| | 772 | if( (buffer[ev].GetStatus()==M_NOTE_ON && |
| | 773 | buffer[ev].GetVelocity()==0 ) |
| | 774 | || buffer[ev].GetStatus()==M_NOTE_OFF ) |
| | 775 | { |
| | 776 | |
| | 777 | // |
| | 778 | // ok, it was a note off event. |
| | 779 | // see if it needs to be deleted. |
| | 780 | // |
| | 781 | |
| | 782 | uchar channel = buffer[ev].GetChannel(); |
| | 783 | uchar note = buffer[ev].GetNote(); |
| | 784 | |
| | 785 | if( before_matrix->GetNoteCount(channel,note)!=0 ) |
| | 786 | { |
| | 787 | // |
| | 788 | // do not delete the note off. |
| | 789 | // we need it. first process it |
| | 790 | // so we know that note is now off. |
| | 791 | // |
| | 792 | |
| | 793 | before_matrix->Process( buffer[ev] ); |
| | 794 | |
| | 795 | // |
| | 796 | // if a non-jagged edit was requested, |
| | 797 | // then we shall move this note off to |
| | 798 | // the 'start' time. |
| | 799 | // |
| | 800 | |
| | 801 | if( !jagged ) |
| | 802 | { |
| | 803 | buffer[ev].SetTime( start ); |
| | 804 | } |
| | 805 | |
| | 806 | } |
| | 807 | else |
| | 808 | { |
| | 809 | changed=TRUE; |
| | 810 | buffer[ev].SetNOP(); |
| | 811 | } |
| | 812 | } |
| | 813 | else |
| | 814 | { |
| | 815 | // |
| | 816 | // ok, it wasn't a note off message. |
| | 817 | // give it to the during_matrix object. |
| | 818 | // |
| | 819 | |
| | 820 | during_matrix->Process( buffer[ev] ); |
| | 821 | |
| | 822 | // |
| | 823 | // and now delete it. |
| | 824 | // |
| | 825 | |
| | 826 | buffer[ev].SetNOP(); |
| | 827 | changed=TRUE; |
| | 828 | } |
| | 829 | } |
| | 830 | } |
| | 831 | |
| | 832 | // |
| | 833 | // if the time of the event>end, and the event is |
| | 834 | // a note off event which was turned on in the |
| | 835 | // during_matrix object, then 'NOP' it. The note on |
| | 836 | // was deleted. |
| | 837 | // |
| | 838 | |
| | 839 | if( time>=end ) |
| | 840 | { |
| | 841 | // |
| | 842 | // make sure the message is not a mark. |
| | 843 | // |
| | 844 | |
| | 845 | if( !buffer[ev].IsMark() ) |
| | 846 | { |
| | 847 | // |
| | 848 | // is it a note off message? |
| | 849 | // |
| | 850 | |
| | 851 | if( buffer[ev].GetStatus()==M_NOTE_OFF |
| | 852 | || (buffer[ev].GetStatus()==M_NOTE_ON && |
| | 853 | buffer[ev].GetVelocity()==0 ) ) |
| | 854 | { |
| | 855 | // |
| | 856 | // ok, it is a note off message, |
| | 857 | // was the corresponding note on |
| | 858 | // deleted? |
| | 859 | // |
| | 860 | |
| | 861 | uchar channel=buffer[ev].GetChannel(); |
| | 862 | uchar note=buffer[ev].GetNote(); |
| | 863 | |
| | 864 | if( during_matrix->GetNoteCount( channel, note ) ) |
| | 865 | { |
| | 866 | // |
| | 867 | // yes, it was, so we gotta NOP this event. |
| | 868 | // give it to during_matrix so it knows |
| | 869 | // that the note is off now. |
| | 870 | |
| | 871 | during_matrix->Process( buffer[ev] ); |
| | 872 | buffer[ev].SetNOP(); |
| | 873 | changed=TRUE; |
| | 874 | } |
| | 875 | } |
| | 876 | } |
| | 877 | } |
| | 878 | |
| | 879 | } |
| | 880 | |
| | 881 | // |
| | 882 | // If there were any events NOP'd |
| | 883 | // then we gotta compress them out of the way. |
| | 884 | // |
| | 885 | |
| | 886 | if( changed ) |
| | 887 | Compress(); |
| | 888 | |
| | 889 | |
| | 890 | // |
| | 891 | // kill our helpful MIDIMatrix's |
| | 892 | // |
| | 893 | |
| | 894 | delete before_matrix; |
| | 895 | delete during_matrix; |
| | 896 | |
| | 897 | } |
| | 898 | |
| | 899 | void EMIDITrack::Delete( ulong start, ulong end, Boolean jagged ) |
| | 900 | { |
| | 901 | // |
| | 902 | // Delete is just like Erase, except afterwards |
| | 903 | // we move all the event times after 'end' from end to start. |
| | 904 | // |
| | 905 | |
| | 906 | // |
| | 907 | // Make sure we got valid values for end. |
| | 908 | // |
| | 909 | |
| | 910 | if( end<=start) |
| | 911 | return; |
| | 912 | |
| | 913 | // |
| | 914 | // Erase the events |
| | 915 | // |
| | 916 | |
| | 917 | Erase( start, end, jagged ); |
| | 918 | |
| | 919 | |
| | 920 | // |
| | 921 | // calculate the amount that we have to subtract from |
| | 922 | // each event time after 'end' time. |
| | 923 | // |
| | 924 | |
| | 925 | ulong diff= end-start; |
| | 926 | |
| | 927 | |
| | 928 | // |
| | 929 | // go through all events (including the last event, data end) |
| | 930 | // |
| | 931 | |
| | 932 | for( unsigned int ev=0; ev<=last_event; ev++ ) |
| | 933 | { |
| | 934 | // |
| | 935 | // get the event's time. |
| | 936 | // |
| | 937 | |
| | 938 | ulong time=buffer[ev].GetTime(); |
| | 939 | |
| | 940 | // |
| | 941 | // is it after the end time? |
| | 942 | // |
| | 943 | |
| | 944 | if( time>=end ) |
| | 945 | { |
| | 946 | // |
| | 947 | // yes, change the event time to what it is |
| | 948 | // supposed to be. |
| | 949 | // |
| | 950 | |
| | 951 | buffer[ev].SetTime( time-diff ); |
| | 952 | } |
| | 953 | } |
| | 954 | } |
| | 955 | |
| | 956 | void EMIDITrack::Insert( ulong start, ulong end ) |
| | 957 | { |
| | 958 | // |
| | 959 | // make sure end is after start. |
| | 960 | // |
| | 961 | |
| | 962 | if( end<start ) |
| | 963 | return; |
| | 964 | |
| | 965 | // |
| | 966 | // calculate the amount of time we gotta add to the event times |
| | 967 | // |
| | 968 | |
| | 969 | ulong diff=end-start; |
| | 970 | |
| | 971 | // |
| | 972 | // go through all the events, including the last DATA END event. |
| | 973 | // |
| | 974 | |
| | 975 | for( unsigned int ev=0; ev<=last_event; ev++ ) |
| | 976 | { |
| | 977 | |
| | 978 | // |
| | 979 | // Get the event's time. |
| | 980 | // |
| | 981 | |
| | 982 | ulong time=buffer[ev].GetTime(); |
| | 983 | |
| | 984 | // |
| | 985 | // is it after 'start' time? |
| | 986 | // |
| | 987 | |
| | 988 | if( time>=start ) |
| | 989 | { |
| | 990 | // |
| | 991 | // move the event forward in time by 'diff' clicks. |
| | 992 | // |
| | 993 | |
| | 994 | buffer[ev].SetTime( time+diff ); |
| | 995 | } |
| | 996 | } |
| | 997 | } |
| | 998 | |
| | 999 | #endif |