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 &noteOffs = m_noteOffs[model->getId()]; 554 NoteOffSet &noteOffs = 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;