Mercurial > hg > svapp
comparison audio/AudioGenerator.cpp @ 596:c99892f0c5c3
Proper handling for notes that end at the same frame as a subsequent note of the same pitch begins. The note-off needs to be associated with the prior note, not a spurious zero-duration version of the subsequent note.
| author | Chris Cannam | 
|---|---|
| date | Wed, 18 Apr 2018 15:19:09 +0100 | 
| parents | b23bebfdfaba | 
| children | 7da68349a0c5 | 
   comparison
  equal
  deleted
  inserted
  replaced
| 595:b23bebfdfaba | 596:c99892f0c5c3 | 
|---|---|
| 63 } | 63 } | 
| 64 | 64 | 
| 65 AudioGenerator::~AudioGenerator() | 65 AudioGenerator::~AudioGenerator() | 
| 66 { | 66 { | 
| 67 #ifdef DEBUG_AUDIO_GENERATOR | 67 #ifdef DEBUG_AUDIO_GENERATOR | 
| 68 SVDEBUG << "AudioGenerator::~AudioGenerator" << endl; | 68 cerr << "AudioGenerator::~AudioGenerator" << endl; | 
| 69 #endif | 69 #endif | 
| 70 | 70 | 
| 71 for (int i = 0; i < m_channelBufCount; ++i) { | 71 for (int i = 0; i < m_channelBufCount; ++i) { | 
| 72 delete[] m_channelBuffer[i]; | 72 delete[] m_channelBuffer[i]; | 
| 73 } | 73 } | 
| 568 | 568 | 
| 569 for (NoteList::const_iterator ni = notes.begin(); | 569 for (NoteList::const_iterator ni = notes.begin(); | 
| 570 ni != notes.end(); ++ni) { | 570 ni != notes.end(); ++ni) { | 
| 571 | 571 | 
| 572 sv_frame_t noteFrame = ni->start; | 572 sv_frame_t noteFrame = ni->start; | 
| 573 sv_frame_t noteDuration = ni->duration; | |
| 573 | 574 | 
| 574 if (noteFrame < reqStart || | 575 if (noteFrame < reqStart || | 
| 575 noteFrame >= reqStart + m_processingBlockSize) continue; | 576 noteFrame >= reqStart + m_processingBlockSize) { | 
| 577 continue; | |
| 578 } | |
| 579 | |
| 580 if (noteDuration == 0) { | |
| 581 // If we have a note-off and a note-on with the same | |
| 582 // time, then the note-off will be assumed (in the | |
| 583 // logic below that deals with two-point note-on/off | |
| 584 // events) to be switching off an earlier note before | |
| 585 // this one begins -- that's necessary in order to | |
| 586 // support adjoining notes of equal pitch. But it does | |
| 587 // mean we have to explicitly ignore zero-duration | |
| 588 // notes, otherwise they'll be played without end | |
| 589 #ifdef DEBUG_AUDIO_GENERATOR | |
| 590 cerr << "mixModel [clip]: zero-duration note found at frame " << noteFrame << ", skipping it" << endl; | |
| 591 #endif | |
| 592 continue; | |
| 593 } | |
| 576 | 594 | 
| 577 while (noteOffs.begin() != noteOffs.end() && | 595 while (noteOffs.begin() != noteOffs.end() && | 
| 578 noteOffs.begin()->frame <= noteFrame) { | 596 noteOffs.begin()->frame <= noteFrame) { | 
| 579 | 597 | 
| 580 sv_frame_t eventFrame = noteOffs.begin()->frame; | 598 sv_frame_t eventFrame = noteOffs.begin()->frame; | 
| 600 cout << "mixModel [clip]: adding note at frame " << noteFrame << ", frame offset " << on.frameOffset << " frequency " << on.frequency << ", level " << on.level << endl; | 618 cout << "mixModel [clip]: adding note at frame " << noteFrame << ", frame offset " << on.frameOffset << " frequency " << on.frequency << ", level " << on.level << endl; | 
| 601 #endif | 619 #endif | 
| 602 | 620 | 
| 603 starts.push_back(on); | 621 starts.push_back(on); | 
| 604 noteOffs.insert | 622 noteOffs.insert | 
| 605 (NoteOff(on.frequency, noteFrame + ni->duration)); | 623 (NoteOff(on.frequency, noteFrame + noteDuration)); | 
| 606 } | 624 } | 
| 607 | 625 | 
| 608 while (noteOffs.begin() != noteOffs.end() && | 626 while (noteOffs.begin() != noteOffs.end() && | 
| 609 noteOffs.begin()->frame <= reqStart + m_processingBlockSize) { | 627 noteOffs.begin()->frame <= reqStart + m_processingBlockSize) { | 
| 610 | 628 | 
