Mercurial > hg > svapp
changeset 615:755fc02a1565
Associate a note-on time with each pending note-off as well, so we can check whether a rewind action (or looping) has caused us to jump to before the note began. Also improve implementation of note-off structure comparator
author | Chris Cannam |
---|---|
date | Mon, 13 Aug 2018 14:13:38 +0100 |
parents | 0aee6ff48018 |
children | 7d3a6357ce64 e98a42e94d90 |
files | audio/AudioGenerator.cpp audio/AudioGenerator.h |
diffstat | 2 files changed, 42 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/audio/AudioGenerator.cpp Mon Aug 13 11:44:33 2018 +0100 +++ b/audio/AudioGenerator.cpp Mon Aug 13 14:13:38 2018 +0100 @@ -568,6 +568,24 @@ std::vector<ClipMixer::NoteStart> starts; std::vector<ClipMixer::NoteEnd> ends; + while (noteOffs.begin() != noteOffs.end() && + noteOffs.begin()->onFrame > reqStart) { + + // We must have jumped back in time, as there is a + // note-off pending for a note that hasn't begun yet. Emit + // the note-off now and discard + + off.frameOffset = 0; + off.frequency = noteOffs.begin()->frequency; + +#ifdef DEBUG_AUDIO_GENERATOR + cerr << "mixModel [clip]: adding rewind-caused note-off at frame offset 0 frequency " << off.frequency << endl; +#endif + + ends.push_back(off); + noteOffs.erase(noteOffs.begin()); + } + for (NoteList::const_iterator ni = notes.begin(); ni != notes.end(); ++ni) { @@ -595,9 +613,9 @@ } while (noteOffs.begin() != noteOffs.end() && - noteOffs.begin()->frame <= noteFrame) { + noteOffs.begin()->offFrame <= noteFrame) { - sv_frame_t eventFrame = noteOffs.begin()->frame; + sv_frame_t eventFrame = noteOffs.begin()->offFrame; if (eventFrame < reqStart) eventFrame = reqStart; off.frameOffset = eventFrame - reqStart; @@ -622,13 +640,14 @@ starts.push_back(on); noteOffs.insert - (NoteOff(on.frequency, noteFrame + noteDuration)); + (NoteOff(on.frequency, noteFrame + noteDuration, noteFrame)); } while (noteOffs.begin() != noteOffs.end() && - noteOffs.begin()->frame <= reqStart + m_processingBlockSize) { + noteOffs.begin()->offFrame <= + reqStart + m_processingBlockSize) { - sv_frame_t eventFrame = noteOffs.begin()->frame; + sv_frame_t eventFrame = noteOffs.begin()->offFrame; if (eventFrame < reqStart) eventFrame = reqStart; off.frameOffset = eventFrame - reqStart;
--- a/audio/AudioGenerator.h Mon Aug 13 11:44:33 2018 +0100 +++ b/audio/AudioGenerator.h Mon Aug 13 14:13:38 2018 +0100 @@ -112,15 +112,29 @@ struct NoteOff { - NoteOff(float _freq, sv_frame_t _frame) : - frequency(_freq), frame(_frame) { } + NoteOff(float _freq, sv_frame_t _offFrame, sv_frame_t _onFrame) : + frequency(_freq), offFrame(_offFrame), onFrame(_onFrame) { } float frequency; - sv_frame_t frame; + sv_frame_t offFrame; + + // This is the frame at which the note whose note-off appears + // here began. It is used to determine when we should silence + // a note because the playhead has jumped back in time - if + // the current frame for rendering is earlier than this one, + // then we should end and discard the note + // + sv_frame_t onFrame; struct Comparator { bool operator()(const NoteOff &n1, const NoteOff &n2) const { - return n1.frame < n2.frame; + if (n1.offFrame != n2.offFrame) { + return n1.offFrame < n2.offFrame; + } else if (n1.onFrame != n2.onFrame) { + return n1.onFrame < n2.onFrame; + } else { + return n1.frequency < n2.frequency; + } } }; };