Mercurial > hg > svapp
comparison audio/AudioCallbackPlaySource.cpp @ 682:161063152ddd by-id
Overhaul audio generator for ModelById
author | Chris Cannam |
---|---|
date | Tue, 02 Jul 2019 21:10:25 +0100 |
parents | a82b9d410393 |
children | e0b0f3e163ca |
comparison
equal
deleted
inserted
replaced
681:c7406ebcd51c | 682:161063152ddd |
---|---|
149 SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource finishing" << endl; | 149 SVDEBUG << "AudioCallbackPlaySource::~AudioCallbackPlaySource finishing" << endl; |
150 #endif | 150 #endif |
151 } | 151 } |
152 | 152 |
153 void | 153 void |
154 AudioCallbackPlaySource::addModel(Model *model) | 154 AudioCallbackPlaySource::addModel(ModelId modelId) |
155 { | 155 { |
156 if (m_models.find(model) != m_models.end()) return; | 156 if (m_models.find(modelId) != m_models.end()) return; |
157 | 157 |
158 bool willPlay = m_audioGenerator->addModel(model); | 158 bool willPlay = m_audioGenerator->addModel(modelId); |
159 | |
160 auto model = ModelById::get(modelId); | |
161 if (!model) return; | |
159 | 162 |
160 m_mutex.lock(); | 163 m_mutex.lock(); |
161 | 164 |
162 m_models.insert(model); | 165 m_models.insert(modelId); |
166 | |
163 if (model->getEndFrame() > m_lastModelEndFrame) { | 167 if (model->getEndFrame() > m_lastModelEndFrame) { |
164 m_lastModelEndFrame = model->getEndFrame(); | 168 m_lastModelEndFrame = model->getEndFrame(); |
165 } | 169 } |
166 | 170 |
167 bool buffersIncreased = false, srChanged = false; | 171 bool buffersIncreased = false, srChanged = false; |
168 | 172 |
169 int modelChannels = 1; | 173 int modelChannels = 1; |
170 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model); | 174 auto rowfm = std::dynamic_pointer_cast<ReadOnlyWaveFileModel>(model); |
171 if (rowfm) modelChannels = rowfm->getChannelCount(); | 175 if (rowfm) modelChannels = rowfm->getChannelCount(); |
172 if (modelChannels > m_sourceChannelCount) { | 176 if (modelChannels > m_sourceChannelCount) { |
173 m_sourceChannelCount = modelChannels; | 177 m_sourceChannelCount = modelChannels; |
174 } | 178 } |
175 | 179 |
192 | 196 |
193 if (rowfm) { | 197 if (rowfm) { |
194 | 198 |
195 bool conflicting = false; | 199 bool conflicting = false; |
196 | 200 |
197 for (std::set<Model *>::const_iterator i = m_models.begin(); | 201 for (ModelId otherId: m_models) { |
198 i != m_models.end(); ++i) { | |
199 // Only read-only wave file models should be | 202 // Only read-only wave file models should be |
200 // considered conflicting -- writable wave file models | 203 // considered conflicting -- writable wave file models |
201 // are derived and we shouldn't take their rates into | 204 // are derived and we shouldn't take their rates into |
202 // account. Also, don't give any particular weight to | 205 // account. Also, don't give any particular weight to |
203 // a file that's already playing at the wrong rate | 206 // a file that's already playing at the wrong rate |
204 // anyway | 207 // anyway |
205 ReadOnlyWaveFileModel *other = | 208 if (otherId == modelId) continue; |
206 qobject_cast<ReadOnlyWaveFileModel *>(*i); | 209 auto other = ModelById::getAs<ReadOnlyWaveFileModel>(otherId); |
207 if (other && other != rowfm && | 210 if (other && |
208 other->getSampleRate() != model->getSampleRate() && | 211 other->getSampleRate() != model->getSampleRate() && |
209 other->getSampleRate() == m_sourceSampleRate) { | 212 other->getSampleRate() == m_sourceSampleRate) { |
210 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << *i << " found" << endl; | 213 SVDEBUG << "AudioCallbackPlaySource::addModel: Conflicting wave file model " << otherId << " found" << endl; |
211 conflicting = true; | 214 conflicting = true; |
212 break; | 215 break; |
213 } | 216 } |
214 } | 217 } |
215 | 218 |
289 | 292 |
290 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 293 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
291 SVDEBUG << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl; | 294 SVDEBUG << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl; |
292 #endif | 295 #endif |
293 | 296 |
294 connect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | 297 connect(model.get(), SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), |
295 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); | 298 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); |
296 | 299 |
297 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 300 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
298 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl; | 301 cout << "AudioCallbackPlaySource::addModel: awakening thread" << endl; |
299 #endif | 302 #endif |
316 rebuildRangeLists(); | 319 rebuildRangeLists(); |
317 } | 320 } |
318 } | 321 } |
319 | 322 |
320 void | 323 void |
321 AudioCallbackPlaySource::removeModel(Model *model) | 324 AudioCallbackPlaySource::removeModel(ModelId modelId) |
322 { | 325 { |
326 auto model = ModelById::get(modelId); | |
327 if (!model) return; | |
328 | |
323 m_mutex.lock(); | 329 m_mutex.lock(); |
324 | 330 |
325 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 331 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
326 cout << "AudioCallbackPlaySource::removeModel(" << model << ")" << endl; | 332 cout << "AudioCallbackPlaySource::removeModel(" << modelId << ")" << endl; |
327 #endif | 333 #endif |
328 | 334 |
329 disconnect(model, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), | 335 disconnect(model.get(), SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), |
330 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); | 336 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t))); |
331 | 337 |
332 m_models.erase(model); | 338 m_models.erase(modelId); |
333 | |
334 // I don't think we have to do this any more: if a new model is | |
335 // loaded at a different rate, we'll hit the non-conflicting path | |
336 // in addModel and the rate will be updated without problems; but | |
337 // if a new model is loaded at the rate that we were using for the | |
338 // last one, then we save work by not having reset this here | |
339 // | |
340 // if (m_models.empty()) { | |
341 // m_sourceSampleRate = 0; | |
342 // } | |
343 | 339 |
344 sv_frame_t lastEnd = 0; | 340 sv_frame_t lastEnd = 0; |
345 for (std::set<Model *>::const_iterator i = m_models.begin(); | 341 for (ModelId otherId: m_models) { |
346 i != m_models.end(); ++i) { | 342 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
347 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 343 cout << "AudioCallbackPlaySource::removeModel(" << modelId << "): checking end frame on model " << otherId << endl; |
348 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl; | 344 #endif |
349 #endif | 345 if (auto other = ModelById::get(otherId)) { |
350 if ((*i)->getEndFrame() > lastEnd) { | 346 if (other->getEndFrame() > lastEnd) { |
351 lastEnd = (*i)->getEndFrame(); | 347 lastEnd = other->getEndFrame(); |
348 } | |
352 } | 349 } |
353 #ifdef DEBUG_AUDIO_PLAY_SOURCE | 350 #ifdef DEBUG_AUDIO_PLAY_SOURCE |
354 cout << "(done, lastEnd now " << lastEnd << ")" << endl; | 351 cout << "(done, lastEnd now " << lastEnd << ")" << endl; |
355 #endif | 352 #endif |
356 } | 353 } |
357 m_lastModelEndFrame = lastEnd; | 354 m_lastModelEndFrame = lastEnd; |
358 | 355 |
359 m_audioGenerator->removeModel(model); | 356 m_audioGenerator->removeModel(modelId); |
360 | 357 |
361 if (m_models.empty()) { | 358 if (m_models.empty()) { |
362 m_sourceSampleRate = 0; | 359 m_sourceSampleRate = 0; |
363 } | 360 } |
364 | 361 |
1012 m_auditioningPluginBypassed = false; | 1009 m_auditioningPluginBypassed = false; |
1013 m_mutex.unlock(); | 1010 m_mutex.unlock(); |
1014 } | 1011 } |
1015 | 1012 |
1016 void | 1013 void |
1017 AudioCallbackPlaySource::setSoloModelSet(std::set<Model *> s) | 1014 AudioCallbackPlaySource::setSoloModelSet(std::set<ModelId> s) |
1018 { | 1015 { |
1019 m_audioGenerator->setSoloModelSet(s); | 1016 m_audioGenerator->setSoloModelSet(s); |
1020 clearRingBuffers(); | 1017 clearRingBuffers(); |
1021 } | 1018 } |
1022 | 1019 |
1662 if ((count - processed - chunkSize) * 2 < fadeOut) { | 1659 if ((count - processed - chunkSize) * 2 < fadeOut) { |
1663 fadeOut = (count - processed - chunkSize) * 2; | 1660 fadeOut = (count - processed - chunkSize) * 2; |
1664 } | 1661 } |
1665 } | 1662 } |
1666 | 1663 |
1667 for (std::set<Model *>::iterator mi = m_models.begin(); | 1664 for (std::set<ModelId>::iterator mi = m_models.begin(); |
1668 mi != m_models.end(); ++mi) { | 1665 mi != m_models.end(); ++mi) { |
1669 | 1666 |
1670 (void) m_audioGenerator->mixModel(*mi, chunkStart, | 1667 (void) m_audioGenerator->mixModel(*mi, chunkStart, |
1671 chunkSize, chunkBufferPtrs, | 1668 chunkSize, chunkBufferPtrs, |
1672 fadeIn, fadeOut); | 1669 fadeIn, fadeOut); |