Mercurial > hg > svapp
comparison audio/AudioGenerator.cpp @ 673:d62fd61082a1
Merge from branch tuning-difference
author | Chris Cannam |
---|---|
date | Fri, 17 May 2019 09:46:22 +0100 |
parents | ed9cb577eb7c |
children | 161063152ddd |
comparison
equal
deleted
inserted
replaced
665:e19c609a7bec | 673:d62fd61082a1 |
---|---|
20 #include "base/PlayParameterRepository.h" | 20 #include "base/PlayParameterRepository.h" |
21 #include "base/Pitch.h" | 21 #include "base/Pitch.h" |
22 #include "base/Exceptions.h" | 22 #include "base/Exceptions.h" |
23 | 23 |
24 #include "data/model/NoteModel.h" | 24 #include "data/model/NoteModel.h" |
25 #include "data/model/FlexiNoteModel.h" | |
26 #include "data/model/DenseTimeValueModel.h" | 25 #include "data/model/DenseTimeValueModel.h" |
27 #include "data/model/SparseTimeValueModel.h" | 26 #include "data/model/SparseTimeValueModel.h" |
28 #include "data/model/SparseOneDimensionalModel.h" | 27 #include "data/model/SparseOneDimensionalModel.h" |
29 #include "data/model/NoteData.h" | 28 #include "base/NoteData.h" |
30 | 29 |
31 #include "ClipMixer.h" | 30 #include "ClipMixer.h" |
32 #include "ContinuousSynth.h" | 31 #include "ContinuousSynth.h" |
33 | 32 |
34 #include <iostream> | 33 #include <iostream> |
183 bool | 182 bool |
184 AudioGenerator::usesClipMixer(const Model *model) | 183 AudioGenerator::usesClipMixer(const Model *model) |
185 { | 184 { |
186 bool clip = | 185 bool clip = |
187 (qobject_cast<const SparseOneDimensionalModel *>(model) || | 186 (qobject_cast<const SparseOneDimensionalModel *>(model) || |
188 qobject_cast<const NoteModel *>(model) || | 187 qobject_cast<const NoteModel *>(model)); |
189 qobject_cast<const FlexiNoteModel *>(model)); | |
190 return clip; | 188 return clip; |
191 } | 189 } |
192 | 190 |
193 bool | 191 bool |
194 AudioGenerator::wantsQuieterClips(const Model *model) | 192 AudioGenerator::wantsQuieterClips(const Model *model) |
195 { | 193 { |
196 // basically, anything that usually has sustain (like notes) or | 194 // basically, anything that usually has sustain (like notes) or |
197 // often has multiple sounds at once (like notes) wants to use a | 195 // often has multiple sounds at once (like notes) wants to use a |
198 // quieter level than simple click tracks | 196 // quieter level than simple click tracks |
199 bool does = | 197 bool does = (qobject_cast<const NoteModel *>(model)); |
200 (qobject_cast<const NoteModel *>(model) || | |
201 qobject_cast<const FlexiNoteModel *>(model)); | |
202 return does; | 198 return does; |
203 } | 199 } |
204 | 200 |
205 bool | 201 bool |
206 AudioGenerator::usesContinuousSynth(const Model *model) | 202 AudioGenerator::usesContinuousSynth(const Model *model) |
557 | 553 |
558 NoteOffSet ¬eOffs = m_noteOffs[model->getId()]; | 554 NoteOffSet ¬eOffs = m_noteOffs[model->getId()]; |
559 | 555 |
560 float **bufferIndexes = new float *[m_targetChannelCount]; | 556 float **bufferIndexes = new float *[m_targetChannelCount]; |
561 | 557 |
558 //!!! + for first block, prime with notes already active | |
559 | |
562 for (int i = 0; i < blocks; ++i) { | 560 for (int i = 0; i < blocks; ++i) { |
563 | 561 |
564 sv_frame_t reqStart = startFrame + i * m_processingBlockSize; | 562 sv_frame_t reqStart = startFrame + i * m_processingBlockSize; |
565 | 563 |
566 NoteList notes; | 564 NoteList notes; |
567 NoteExportable *exportable = dynamic_cast<NoteExportable *>(model); | 565 NoteExportable *exportable = dynamic_cast<NoteExportable *>(model); |
568 if (exportable) { | 566 if (exportable) { |
569 notes = exportable->getNotesWithin(reqStart, | 567 notes = exportable->getNotesStartingWithin(reqStart, |
570 reqStart + m_processingBlockSize); | 568 m_processingBlockSize); |
571 } | 569 } |
572 | 570 |
573 std::vector<ClipMixer::NoteStart> starts; | 571 std::vector<ClipMixer::NoteStart> starts; |
574 std::vector<ClipMixer::NoteEnd> ends; | 572 std::vector<ClipMixer::NoteEnd> ends; |
575 | 573 |
712 | 710 |
713 for (int c = 0; c < m_targetChannelCount; ++c) { | 711 for (int c = 0; c < m_targetChannelCount; ++c) { |
714 bufferIndexes[c] = buffer[c] + i * m_processingBlockSize; | 712 bufferIndexes[c] = buffer[c] + i * m_processingBlockSize; |
715 } | 713 } |
716 | 714 |
717 SparseTimeValueModel::PointList points = | 715 EventVector points = |
718 stvm->getPoints(reqStart, reqStart + m_processingBlockSize); | 716 stvm->getEventsStartingWithin(reqStart, m_processingBlockSize); |
719 | 717 |
720 // by default, repeat last frequency | 718 // by default, repeat last frequency |
721 float f0 = 0.f; | 719 float f0 = 0.f; |
722 | 720 |
723 // go straight to the last freq that is genuinely in this range | 721 // go straight to the last freq in this range |
724 for (SparseTimeValueModel::PointList::const_iterator itr = points.end(); | 722 if (!points.empty()) { |
725 itr != points.begin(); ) { | 723 f0 = points.rbegin()->getValue(); |
726 --itr; | 724 } |
727 if (itr->frame >= reqStart && | 725 |
728 itr->frame < reqStart + m_processingBlockSize) { | 726 // if there is no such frequency and the next point is further |
729 f0 = itr->value; | |
730 break; | |
731 } | |
732 } | |
733 | |
734 // if we found no such frequency and the next point is further | |
735 // away than twice the model resolution, go silent (same | 727 // away than twice the model resolution, go silent (same |
736 // criterion TimeValueLayer uses for ending a discrete curve | 728 // criterion TimeValueLayer uses for ending a discrete curve |
737 // segment) | 729 // segment) |
738 if (f0 == 0.f) { | 730 if (f0 == 0.f) { |
739 SparseTimeValueModel::PointList nextPoints = | 731 Event nextP; |
740 stvm->getNextPoints(reqStart + m_processingBlockSize); | 732 if (!stvm->getNearestEventMatching(reqStart + m_processingBlockSize, |
741 if (nextPoints.empty() || | 733 [](Event) { return true; }, |
742 nextPoints.begin()->frame > reqStart + 2 * stvm->getResolution()) { | 734 EventSeries::Forward, |
735 nextP) || | |
736 nextP.getFrame() > reqStart + 2 * stvm->getResolution()) { | |
743 f0 = -1.f; | 737 f0 = -1.f; |
744 } | 738 } |
745 } | 739 } |
746 | 740 |
747 // cerr << "f0 = " << f0 << endl; | 741 // cerr << "f0 = " << f0 << endl; |