comparison audio/AudioCallbackPlaySource.cpp @ 595:b23bebfdfaba

Untabify
author Chris Cannam
date Thu, 01 Mar 2018 18:02:22 +0000
parents 298d864113f0
children 5bc9f9144505
comparison
equal deleted inserted replaced
594:72b4870f0e6b 595:b23bebfdfaba
88 m_resamplerWrapper(0) 88 m_resamplerWrapper(0)
89 { 89 {
90 m_viewManager->setAudioPlaySource(this); 90 m_viewManager->setAudioPlaySource(this);
91 91
92 connect(m_viewManager, SIGNAL(selectionChanged()), 92 connect(m_viewManager, SIGNAL(selectionChanged()),
93 this, SLOT(selectionChanged())); 93 this, SLOT(selectionChanged()));
94 connect(m_viewManager, SIGNAL(playLoopModeChanged()), 94 connect(m_viewManager, SIGNAL(playLoopModeChanged()),
95 this, SLOT(playLoopModeChanged())); 95 this, SLOT(playLoopModeChanged()));
96 connect(m_viewManager, SIGNAL(playSelectionModeChanged()), 96 connect(m_viewManager, SIGNAL(playSelectionModeChanged()),
97 this, SLOT(playSelectionModeChanged())); 97 this, SLOT(playSelectionModeChanged()));
98 98
99 connect(this, SIGNAL(playStatusChanged(bool)), 99 connect(this, SIGNAL(playStatusChanged(bool)),
100 m_viewManager, SLOT(playStatusChanged(bool))); 100 m_viewManager, SLOT(playStatusChanged(bool)));
101 101
102 connect(PlayParameterRepository::getInstance(), 102 connect(PlayParameterRepository::getInstance(),
103 SIGNAL(playParametersChanged(PlayParameters *)), 103 SIGNAL(playParametersChanged(PlayParameters *)),
104 this, SLOT(playParametersChanged(PlayParameters *))); 104 this, SLOT(playParametersChanged(PlayParameters *)));
105 105
106 connect(Preferences::getInstance(), 106 connect(Preferences::getInstance(),
107 SIGNAL(propertyChanged(PropertyContainer::PropertyName)), 107 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
108 this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); 108 this, SLOT(preferenceChanged(PropertyContainer::PropertyName)));
109 } 109 }
118 if (m_fillThread) { 118 if (m_fillThread) {
119 #ifdef DEBUG_AUDIO_PLAY_SOURCE 119 #ifdef DEBUG_AUDIO_PLAY_SOURCE
120 cout << "AudioCallbackPlaySource dtor: awakening thread" << endl; 120 cout << "AudioCallbackPlaySource dtor: awakening thread" << endl;
121 #endif 121 #endif
122 m_condition.wakeAll(); 122 m_condition.wakeAll();
123 m_fillThread->wait(); 123 m_fillThread->wait();
124 delete m_fillThread; 124 delete m_fillThread;
125 } 125 }
126 126
127 clearModels(); 127 clearModels();
128 128
129 if (m_readBuffers != m_writeBuffers) { 129 if (m_readBuffers != m_writeBuffers) {
130 delete m_readBuffers; 130 delete m_readBuffers;
131 } 131 }
132 132
133 delete m_writeBuffers; 133 delete m_writeBuffers;
134 134
135 delete m_audioGenerator; 135 delete m_audioGenerator;
159 159
160 m_mutex.lock(); 160 m_mutex.lock();
161 161
162 m_models.insert(model); 162 m_models.insert(model);
163 if (model->getEndFrame() > m_lastModelEndFrame) { 163 if (model->getEndFrame() > m_lastModelEndFrame) {
164 m_lastModelEndFrame = model->getEndFrame(); 164 m_lastModelEndFrame = model->getEndFrame();
165 } 165 }
166 166
167 bool buffersIncreased = false, srChanged = false; 167 bool buffersIncreased = false, srChanged = false;
168 168
169 int modelChannels = 1; 169 int modelChannels = 1;
170 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model); 170 ReadOnlyWaveFileModel *rowfm = qobject_cast<ReadOnlyWaveFileModel *>(model);
171 if (rowfm) modelChannels = rowfm->getChannelCount(); 171 if (rowfm) modelChannels = rowfm->getChannelCount();
172 if (modelChannels > m_sourceChannelCount) { 172 if (modelChannels > m_sourceChannelCount) {
173 m_sourceChannelCount = modelChannels; 173 m_sourceChannelCount = modelChannels;
174 } 174 }
175 175
176 #ifdef DEBUG_AUDIO_PLAY_SOURCE 176 #ifdef DEBUG_AUDIO_PLAY_SOURCE
177 cout << "AudioCallbackPlaySource: Adding model with " << modelChannels << " channels at rate " << model->getSampleRate() << endl; 177 cout << "AudioCallbackPlaySource: Adding model with " << modelChannels << " channels at rate " << model->getSampleRate() << endl;
178 #endif 178 #endif
180 if (m_sourceSampleRate == 0) { 180 if (m_sourceSampleRate == 0) {
181 181
182 SVDEBUG << "AudioCallbackPlaySource::addModel: Source rate changing from 0 to " 182 SVDEBUG << "AudioCallbackPlaySource::addModel: Source rate changing from 0 to "
183 << model->getSampleRate() << endl; 183 << model->getSampleRate() << endl;
184 184
185 m_sourceSampleRate = model->getSampleRate(); 185 m_sourceSampleRate = model->getSampleRate();
186 srChanged = true; 186 srChanged = true;
187 187
188 } else if (model->getSampleRate() != m_sourceSampleRate) { 188 } else if (model->getSampleRate() != m_sourceSampleRate) {
189 189
190 // If this is a read-only wave file model and we have no 190 // If this is a read-only wave file model and we have no
191 // other, we can just switch to this model's sample rate 191 // other, we can just switch to this model's sample rate
236 } 236 }
237 237
238 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) { 238 if (!m_writeBuffers || (int)m_writeBuffers->size() < getTargetChannelCount()) {
239 cerr << "m_writeBuffers size = " << (m_writeBuffers ? m_writeBuffers->size() : 0) << endl; 239 cerr << "m_writeBuffers size = " << (m_writeBuffers ? m_writeBuffers->size() : 0) << endl;
240 cerr << "target channel count = " << (getTargetChannelCount()) << endl; 240 cerr << "target channel count = " << (getTargetChannelCount()) << endl;
241 clearRingBuffers(true, getTargetChannelCount()); 241 clearRingBuffers(true, getTargetChannelCount());
242 buffersIncreased = true; 242 buffersIncreased = true;
243 } else { 243 } else {
244 if (willPlay) clearRingBuffers(true); 244 if (willPlay) clearRingBuffers(true);
245 } 245 }
246 246
247 if (srChanged) { 247 if (srChanged) {
248 248
249 SVCERR << "AudioCallbackPlaySource: Source rate changed" << endl; 249 SVCERR << "AudioCallbackPlaySource: Source rate changed" << endl;
281 SVDEBUG << "AudioCallbackPlaySource::addModel: This is no more than the device channel count (" << getDeviceChannelCount() << "), so taking no action" << endl; 281 SVDEBUG << "AudioCallbackPlaySource::addModel: This is no more than the device channel count (" << getDeviceChannelCount() << "), so taking no action" << endl;
282 } 282 }
283 } 283 }
284 284
285 if (!m_fillThread) { 285 if (!m_fillThread) {
286 m_fillThread = new FillThread(*this); 286 m_fillThread = new FillThread(*this);
287 m_fillThread->start(); 287 m_fillThread->start();
288 } 288 }
289 289
290 #ifdef DEBUG_AUDIO_PLAY_SOURCE 290 #ifdef DEBUG_AUDIO_PLAY_SOURCE
291 SVDEBUG << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl; 291 SVDEBUG << "AudioCallbackPlaySource::addModel: now have " << m_models.size() << " model(s)" << endl;
292 #endif 292 #endif
336 // in addModel and the rate will be updated without problems; but 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 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 338 // last one, then we save work by not having reset this here
339 // 339 //
340 // if (m_models.empty()) { 340 // if (m_models.empty()) {
341 // m_sourceSampleRate = 0; 341 // m_sourceSampleRate = 0;
342 // } 342 // }
343 343
344 sv_frame_t lastEnd = 0; 344 sv_frame_t lastEnd = 0;
345 for (std::set<Model *>::const_iterator i = m_models.begin(); 345 for (std::set<Model *>::const_iterator i = m_models.begin();
346 i != m_models.end(); ++i) { 346 i != m_models.end(); ++i) {
347 #ifdef DEBUG_AUDIO_PLAY_SOURCE 347 #ifdef DEBUG_AUDIO_PLAY_SOURCE
348 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl; 348 cout << "AudioCallbackPlaySource::removeModel(" << model << "): checking end frame on model " << *i << endl;
349 #endif 349 #endif
350 if ((*i)->getEndFrame() > lastEnd) { 350 if ((*i)->getEndFrame() > lastEnd) {
351 lastEnd = (*i)->getEndFrame(); 351 lastEnd = (*i)->getEndFrame();
352 } 352 }
353 #ifdef DEBUG_AUDIO_PLAY_SOURCE 353 #ifdef DEBUG_AUDIO_PLAY_SOURCE
354 cout << "(done, lastEnd now " << lastEnd << ")" << endl; 354 cout << "(done, lastEnd now " << lastEnd << ")" << endl;
355 #endif 355 #endif
356 } 356 }
357 m_lastModelEndFrame = lastEnd; 357 m_lastModelEndFrame = lastEnd;
358 358
359 m_audioGenerator->removeModel(model); 359 m_audioGenerator->removeModel(model);
395 #endif 395 #endif
396 396
397 rebuildRangeLists(); 397 rebuildRangeLists();
398 398
399 if (count == 0) { 399 if (count == 0) {
400 if (m_writeBuffers) count = int(m_writeBuffers->size()); 400 if (m_writeBuffers) count = int(m_writeBuffers->size());
401 } 401 }
402 402
403 #ifdef DEBUG_AUDIO_PLAY_SOURCE 403 #ifdef DEBUG_AUDIO_PLAY_SOURCE
404 cout << "current playing frame = " << getCurrentPlayingFrame() << endl; 404 cout << "current playing frame = " << getCurrentPlayingFrame() << endl;
405 405
411 #ifdef DEBUG_AUDIO_PLAY_SOURCE 411 #ifdef DEBUG_AUDIO_PLAY_SOURCE
412 cout << "current buffered frame = " << m_writeBufferFill << endl; 412 cout << "current buffered frame = " << m_writeBufferFill << endl;
413 #endif 413 #endif
414 414
415 if (m_readBuffers != m_writeBuffers) { 415 if (m_readBuffers != m_writeBuffers) {
416 delete m_writeBuffers; 416 delete m_writeBuffers;
417 } 417 }
418 418
419 m_writeBuffers = new RingBufferVector; 419 m_writeBuffers = new RingBufferVector;
420 420
421 for (int i = 0; i < count; ++i) { 421 for (int i = 0; i < count; ++i) {
422 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize)); 422 m_writeBuffers->push_back(new RingBuffer<float>(m_ringBufferSize));
423 } 423 }
424 424
425 m_audioGenerator->reset(); 425 m_audioGenerator->reset();
426 426
427 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created " 427 // cout << "AudioCallbackPlaySource::clearRingBuffers: Created "
428 // << count << " write buffers" << endl; 428 // << count << " write buffers" << endl;
429 429
430 if (!haveLock) { 430 if (!haveLock) {
431 m_mutex.unlock(); 431 m_mutex.unlock();
432 } 432 }
433 } 433 }
434 434
435 void 435 void
436 AudioCallbackPlaySource::play(sv_frame_t startFrame) 436 AudioCallbackPlaySource::play(sv_frame_t startFrame)
441 SVCERR << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl; 441 SVCERR << "AudioCallbackPlaySource::play: No source sample rate available, not playing" << endl;
442 return; 442 return;
443 } 443 }
444 444
445 if (m_viewManager->getPlaySelectionMode() && 445 if (m_viewManager->getPlaySelectionMode() &&
446 !m_viewManager->getSelections().empty()) { 446 !m_viewManager->getSelections().empty()) {
447 447
448 #ifdef DEBUG_AUDIO_PLAY_SOURCE 448 #ifdef DEBUG_AUDIO_PLAY_SOURCE
449 cout << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = "; 449 cout << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = ";
450 #endif 450 #endif
451 451
457 457
458 } else { 458 } else {
459 if (startFrame < 0) { 459 if (startFrame < 0) {
460 startFrame = 0; 460 startFrame = 0;
461 } 461 }
462 if (startFrame >= m_lastModelEndFrame) { 462 if (startFrame >= m_lastModelEndFrame) {
463 startFrame = 0; 463 startFrame = 0;
464 } 464 }
465 } 465 }
466 466
467 #ifdef DEBUG_AUDIO_PLAY_SOURCE 467 #ifdef DEBUG_AUDIO_PLAY_SOURCE
468 cout << "play(" << startFrame << ") -> aligned playback model "; 468 cout << "play(" << startFrame << ") -> aligned playback model ";
469 #endif 469 #endif
554 554
555 void 555 void
556 AudioCallbackPlaySource::selectionChanged() 556 AudioCallbackPlaySource::selectionChanged()
557 { 557 {
558 if (m_viewManager->getPlaySelectionMode()) { 558 if (m_viewManager->getPlaySelectionMode()) {
559 clearRingBuffers(); 559 clearRingBuffers();
560 } 560 }
561 } 561 }
562 562
563 void 563 void
564 AudioCallbackPlaySource::playLoopModeChanged() 564 AudioCallbackPlaySource::playLoopModeChanged()
568 568
569 void 569 void
570 AudioCallbackPlaySource::playSelectionModeChanged() 570 AudioCallbackPlaySource::playSelectionModeChanged()
571 { 571 {
572 if (!m_viewManager->getSelections().empty()) { 572 if (!m_viewManager->getSelections().empty()) {
573 clearRingBuffers(); 573 clearRingBuffers();
574 } 574 }
575 } 575 }
576 576
577 void 577 void
578 AudioCallbackPlaySource::playParametersChanged(PlayParameters *) 578 AudioCallbackPlaySource::playParametersChanged(PlayParameters *)
710 if (rate == 0) return 0; 710 if (rate == 0) return 0;
711 711
712 int inbuffer = 0; // at target rate 712 int inbuffer = 0; // at target rate
713 713
714 for (int c = 0; c < getTargetChannelCount(); ++c) { 714 for (int c = 0; c < getTargetChannelCount(); ++c) {
715 RingBuffer<float> *rb = getReadRingBuffer(c); 715 RingBuffer<float> *rb = getReadRingBuffer(c);
716 if (rb) { 716 if (rb) {
717 int here = rb->getReadSpace(); 717 int here = rb->getReadSpace();
718 if (c == 0 || here < inbuffer) inbuffer = here; 718 if (c == 0 || here < inbuffer) inbuffer = here;
719 } 719 }
720 } 720 }
721 721
722 sv_frame_t readBufferFill = m_readBufferFill; 722 sv_frame_t readBufferFill = m_readBufferFill;
723 sv_frame_t lastRetrievedBlockSize = m_lastRetrievedBlockSize; 723 sv_frame_t lastRetrievedBlockSize = m_lastRetrievedBlockSize;
724 double lastRetrievalTimestamp = m_lastRetrievalTimestamp; 724 double lastRetrievalTimestamp = m_lastRetrievalTimestamp;
1142 if (!m_playing) { 1142 if (!m_playing) {
1143 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1143 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1144 cout << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl; 1144 cout << "AudioCallbackPlaySource::getSourceSamples: Not playing" << endl;
1145 #endif 1145 #endif
1146 v_zero_channels(buffer, requestedChannels, count); 1146 v_zero_channels(buffer, requestedChannels, count);
1147 return 0; 1147 return 0;
1148 } 1148 }
1149 if (requestedChannels < channels) { 1149 if (requestedChannels < channels) {
1150 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not enough device channels (" << requestedChannels << ", need " << channels << "); hoping device is about to be reopened" << endl; 1150 SVDEBUG << "AudioCallbackPlaySource::getSourceSamples: Not enough device channels (" << requestedChannels << ", need " << channels << "); hoping device is about to be reopened" << endl;
1151 v_zero_channels(buffer, requestedChannels, count); 1151 v_zero_channels(buffer, requestedChannels, count);
1152 return 0; 1152 return 0;
1221 m_lastRetrievalTimestamp = m_target->getCurrentTime(); 1221 m_lastRetrievalTimestamp = m_target->getCurrentTime();
1222 } 1222 }
1223 1223
1224 if (!ts || ratio == 1.f) { 1224 if (!ts || ratio == 1.f) {
1225 1225
1226 int got = 0; 1226 int got = 0;
1227 1227
1228 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1228 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1229 cout << "channels == " << channels << endl; 1229 cout << "channels == " << channels << endl;
1230 #endif 1230 #endif
1231 1231
1232 for (int ch = 0; ch < channels; ++ch) { 1232 for (int ch = 0; ch < channels; ++ch) {
1233 1233
1234 RingBuffer<float> *rb = getReadRingBuffer(ch); 1234 RingBuffer<float> *rb = getReadRingBuffer(ch);
1235 1235
1236 if (rb) { 1236 if (rb) {
1237 1237
1238 // this is marginally more likely to leave our channels in 1238 // this is marginally more likely to leave our channels in
1239 // sync after a processing failure than just passing "count": 1239 // sync after a processing failure than just passing "count":
1240 sv_frame_t request = count; 1240 sv_frame_t request = count;
1241 if (ch > 0) request = got; 1241 if (ch > 0) request = got;
1242 1242
1243 got = rb->read(buffer[ch], int(request)); 1243 got = rb->read(buffer[ch], int(request));
1244 1244
1245 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1245 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1246 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl; 1246 cout << "AudioCallbackPlaySource::getSamples: got " << got << " (of " << count << ") samples on channel " << ch << ", signalling for more (possibly)" << endl;
1247 #endif 1247 #endif
1248 } 1248 }
1249 1249
1250 for (int ch = 0; ch < channels; ++ch) { 1250 for (int ch = 0; ch < channels; ++ch) {
1251 for (int i = got; i < count; ++i) { 1251 for (int i = got; i < count; ++i) {
1252 buffer[ch][i] = 0.0; 1252 buffer[ch][i] = 0.0;
1253 } 1253 }
1254 } 1254 }
1255 } 1255 }
1256 1256
1257 applyAuditioningEffect(count, buffer); 1257 applyAuditioningEffect(count, buffer);
1258 1258
1259 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1259 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1260 cout << "AudioCallbackPlaySource::getSamples: awakening thread" << endl; 1260 cout << "AudioCallbackPlaySource::getSamples: awakening thread" << endl;
1261 #endif 1261 #endif
1262 1262
1263 m_condition.wakeAll(); 1263 m_condition.wakeAll();
1264 1264
1265 return got; 1265 return got;
1266 } 1266 }
1267 1267
1268 sv_frame_t available; 1268 sv_frame_t available;
1269 sv_frame_t fedToStretcher = 0; 1269 sv_frame_t fedToStretcher = 0;
1270 int warned = 0; 1270 int warned = 0;
1403 static float *tmp = 0; 1403 static float *tmp = 0;
1404 static sv_frame_t tmpSize = 0; 1404 static sv_frame_t tmpSize = 0;
1405 1405
1406 sv_frame_t space = 0; 1406 sv_frame_t space = 0;
1407 for (int c = 0; c < getTargetChannelCount(); ++c) { 1407 for (int c = 0; c < getTargetChannelCount(); ++c) {
1408 RingBuffer<float> *wb = getWriteRingBuffer(c); 1408 RingBuffer<float> *wb = getWriteRingBuffer(c);
1409 if (wb) { 1409 if (wb) {
1410 sv_frame_t spaceHere = wb->getWriteSpace(); 1410 sv_frame_t spaceHere = wb->getWriteSpace();
1411 if (c == 0 || spaceHere < space) space = spaceHere; 1411 if (c == 0 || spaceHere < space) space = spaceHere;
1412 } 1412 }
1413 } 1413 }
1414 1414
1415 if (space == 0) { 1415 if (space == 0) {
1416 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1416 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1417 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl; 1417 cout << "AudioCallbackPlaySourceFillThread: no space to fill" << endl;
1421 1421
1422 // space is now the number of samples that can be written on each 1422 // space is now the number of samples that can be written on each
1423 // channel's write ringbuffer 1423 // channel's write ringbuffer
1424 1424
1425 sv_frame_t f = m_writeBufferFill; 1425 sv_frame_t f = m_writeBufferFill;
1426 1426
1427 bool readWriteEqual = (m_readBuffers == m_writeBuffers); 1427 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1428 1428
1429 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1429 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1430 if (!readWriteEqual) { 1430 if (!readWriteEqual) {
1431 cout << "AudioCallbackPlaySourceFillThread: note read buffers != write buffers" << endl; 1431 cout << "AudioCallbackPlaySourceFillThread: note read buffers != write buffers" << endl;
1441 1441
1442 static float **bufferPtrs = 0; 1442 static float **bufferPtrs = 0;
1443 static int bufferPtrCount = 0; 1443 static int bufferPtrCount = 0;
1444 1444
1445 if (bufferPtrCount < channels) { 1445 if (bufferPtrCount < channels) {
1446 if (bufferPtrs) delete[] bufferPtrs; 1446 if (bufferPtrs) delete[] bufferPtrs;
1447 bufferPtrs = new float *[channels]; 1447 bufferPtrs = new float *[channels];
1448 bufferPtrCount = channels; 1448 bufferPtrCount = channels;
1449 } 1449 }
1450 1450
1451 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize(); 1451 sv_frame_t generatorBlockSize = m_audioGenerator->getBlockSize();
1452 1452
1453 // space must be a multiple of generatorBlockSize 1453 // space must be a multiple of generatorBlockSize
1469 } 1469 }
1470 1470
1471 for (int c = 0; c < channels; ++c) { 1471 for (int c = 0; c < channels; ++c) {
1472 1472
1473 bufferPtrs[c] = tmp + c * space; 1473 bufferPtrs[c] = tmp + c * space;
1474 1474
1475 for (int i = 0; i < space; ++i) { 1475 for (int i = 0; i < space; ++i) {
1476 tmp[c * space + i] = 0.0f; 1476 tmp[c * space + i] = 0.0f;
1477 } 1477 }
1478 } 1478 }
1479 1479
1519 sv_frame_t selectionSize = 0; 1519 sv_frame_t selectionSize = 0;
1520 sv_frame_t nextChunkStart = chunkStart + chunkSize; 1520 sv_frame_t nextChunkStart = chunkStart + chunkSize;
1521 1521
1522 bool looping = m_viewManager->getPlayLoopMode(); 1522 bool looping = m_viewManager->getPlayLoopMode();
1523 bool constrained = (m_viewManager->getPlaySelectionMode() && 1523 bool constrained = (m_viewManager->getPlaySelectionMode() &&
1524 !m_viewManager->getSelections().empty()); 1524 !m_viewManager->getSelections().empty());
1525 1525
1526 int channels = getTargetChannelCount(); 1526 int channels = getTargetChannelCount();
1527 1527
1528 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1528 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1529 cout << "mixModels: start " << frame << ", size " << count << ", channels " << channels << endl; 1529 cout << "mixModels: start " << frame << ", size " << count << ", channels " << channels << endl;
1541 1541
1542 static float **chunkBufferPtrs = 0; 1542 static float **chunkBufferPtrs = 0;
1543 static int chunkBufferPtrCount = 0; 1543 static int chunkBufferPtrCount = 0;
1544 1544
1545 if (chunkBufferPtrCount < channels) { 1545 if (chunkBufferPtrCount < channels) {
1546 if (chunkBufferPtrs) delete[] chunkBufferPtrs; 1546 if (chunkBufferPtrs) delete[] chunkBufferPtrs;
1547 chunkBufferPtrs = new float *[channels]; 1547 chunkBufferPtrs = new float *[channels];
1548 chunkBufferPtrCount = channels; 1548 chunkBufferPtrCount = channels;
1549 } 1549 }
1550 1550
1551 for (int c = 0; c < channels; ++c) { 1551 for (int c = 0; c < channels; ++c) {
1552 chunkBufferPtrs[c] = buffers[c]; 1552 chunkBufferPtrs[c] = buffers[c];
1553 } 1553 }
1554 1554
1555 while (processed < count) { 1555 while (processed < count) {
1556 1556
1557 chunkSize = count - processed; 1557 chunkSize = count - processed;
1558 nextChunkStart = chunkStart + chunkSize; 1558 nextChunkStart = chunkStart + chunkSize;
1559 selectionSize = 0; 1559 selectionSize = 0;
1560 1560
1561 sv_frame_t fadeIn = 0, fadeOut = 0; 1561 sv_frame_t fadeIn = 0, fadeOut = 0;
1562 1562
1563 if (constrained) { 1563 if (constrained) {
1564 1564
1565 sv_frame_t rChunkStart = 1565 sv_frame_t rChunkStart =
1566 m_viewManager->alignPlaybackFrameToReference(chunkStart); 1566 m_viewManager->alignPlaybackFrameToReference(chunkStart);
1567 1567
1568 Selection selection = 1568 Selection selection =
1569 m_viewManager->getContainingSelection(rChunkStart, true); 1569 m_viewManager->getContainingSelection(rChunkStart, true);
1570 1570
1571 if (selection.isEmpty()) { 1571 if (selection.isEmpty()) {
1572 if (looping) { 1572 if (looping) {
1573 selection = *m_viewManager->getSelections().begin(); 1573 selection = *m_viewManager->getSelections().begin();
1574 chunkStart = m_viewManager->alignReferenceToPlaybackFrame 1574 chunkStart = m_viewManager->alignReferenceToPlaybackFrame
1575 (selection.getStartFrame()); 1575 (selection.getStartFrame());
1576 fadeIn = 50; 1576 fadeIn = 50;
1577 } 1577 }
1578 } 1578 }
1579 1579
1580 if (selection.isEmpty()) { 1580 if (selection.isEmpty()) {
1581 1581
1582 chunkSize = 0; 1582 chunkSize = 0;
1583 nextChunkStart = chunkStart; 1583 nextChunkStart = chunkStart;
1584 1584
1585 } else { 1585 } else {
1586 1586
1587 sv_frame_t sf = m_viewManager->alignReferenceToPlaybackFrame 1587 sv_frame_t sf = m_viewManager->alignReferenceToPlaybackFrame
1588 (selection.getStartFrame()); 1588 (selection.getStartFrame());
1589 sv_frame_t ef = m_viewManager->alignReferenceToPlaybackFrame 1589 sv_frame_t ef = m_viewManager->alignReferenceToPlaybackFrame
1590 (selection.getEndFrame()); 1590 (selection.getEndFrame());
1591 1591
1592 selectionSize = ef - sf; 1592 selectionSize = ef - sf;
1593 1593
1594 if (chunkStart < sf) { 1594 if (chunkStart < sf) {
1595 chunkStart = sf; 1595 chunkStart = sf;
1596 fadeIn = 50; 1596 fadeIn = 50;
1597 } 1597 }
1598 1598
1599 nextChunkStart = chunkStart + chunkSize; 1599 nextChunkStart = chunkStart + chunkSize;
1600 1600
1601 if (nextChunkStart >= ef) { 1601 if (nextChunkStart >= ef) {
1602 nextChunkStart = ef; 1602 nextChunkStart = ef;
1603 fadeOut = 50; 1603 fadeOut = 50;
1604 } 1604 }
1605 1605
1606 chunkSize = nextChunkStart - chunkStart; 1606 chunkSize = nextChunkStart - chunkStart;
1607 } 1607 }
1608 1608
1609 } else if (looping && m_lastModelEndFrame > 0) { 1609 } else if (looping && m_lastModelEndFrame > 0) {
1610 1610
1611 if (chunkStart >= m_lastModelEndFrame) { 1611 if (chunkStart >= m_lastModelEndFrame) {
1612 chunkStart = 0; 1612 chunkStart = 0;
1613 } 1613 }
1614 if (chunkSize > m_lastModelEndFrame - chunkStart) { 1614 if (chunkSize > m_lastModelEndFrame - chunkStart) {
1615 chunkSize = m_lastModelEndFrame - chunkStart; 1615 chunkSize = m_lastModelEndFrame - chunkStart;
1616 } 1616 }
1617 nextChunkStart = chunkStart + chunkSize; 1617 nextChunkStart = chunkStart + chunkSize;
1618 } 1618 }
1619 1619
1620 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1620 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1621 cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << endl; 1621 cout << "chunkStart " << chunkStart << ", chunkSize " << chunkSize << ", nextChunkStart " << nextChunkStart << ", frame " << frame << ", count " << count << ", processed " << processed << endl;
1622 #endif 1622 #endif
1623 1623
1624 if (!chunkSize) { 1624 if (!chunkSize) {
1625 // We need to maintain full buffers so that the other 1625 // We need to maintain full buffers so that the other
1626 // thread can tell where it's got to in the playback -- so 1626 // thread can tell where it's got to in the playback -- so
1627 // return the full amount here 1627 // return the full amount here
1628 frame = frame + count; 1628 frame = frame + count;
1629 if (frame < nextChunkStart) { 1629 if (frame < nextChunkStart) {
1630 frame = nextChunkStart; 1630 frame = nextChunkStart;
1631 } 1631 }
1632 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1632 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1633 cout << "mixModels: ending at " << nextChunkStart << ", returning frame as " 1633 cout << "mixModels: ending at " << nextChunkStart << ", returning frame as "
1634 << frame << endl; 1634 << frame << endl;
1635 #endif 1635 #endif
1636 return count; 1636 return count;
1637 } 1637 }
1638 1638
1639 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1639 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1640 cout << "mixModels: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << endl; 1640 cout << "mixModels: chunk at " << chunkStart << " -> " << nextChunkStart << " (size " << chunkSize << ")" << endl;
1641 #endif 1641 #endif
1642 1642
1643 if (selectionSize < 100) { 1643 if (selectionSize < 100) {
1644 fadeIn = 0; 1644 fadeIn = 0;
1645 fadeOut = 0; 1645 fadeOut = 0;
1646 } else if (selectionSize < 300) { 1646 } else if (selectionSize < 300) {
1647 if (fadeIn > 0) fadeIn = 10; 1647 if (fadeIn > 0) fadeIn = 10;
1648 if (fadeOut > 0) fadeOut = 10; 1648 if (fadeOut > 0) fadeOut = 10;
1649 } 1649 }
1650 1650
1651 if (fadeIn > 0) { 1651 if (fadeIn > 0) {
1652 if (processed * 2 < fadeIn) { 1652 if (processed * 2 < fadeIn) {
1653 fadeIn = processed * 2; 1653 fadeIn = processed * 2;
1654 } 1654 }
1655 } 1655 }
1656 1656
1657 if (fadeOut > 0) { 1657 if (fadeOut > 0) {
1658 if ((count - processed - chunkSize) * 2 < fadeOut) { 1658 if ((count - processed - chunkSize) * 2 < fadeOut) {
1659 fadeOut = (count - processed - chunkSize) * 2; 1659 fadeOut = (count - processed - chunkSize) * 2;
1660 } 1660 }
1661 } 1661 }
1662 1662
1663 for (std::set<Model *>::iterator mi = m_models.begin(); 1663 for (std::set<Model *>::iterator mi = m_models.begin();
1664 mi != m_models.end(); ++mi) { 1664 mi != m_models.end(); ++mi) {
1665 1665
1666 (void) m_audioGenerator->mixModel(*mi, chunkStart, 1666 (void) m_audioGenerator->mixModel(*mi, chunkStart,
1667 chunkSize, chunkBufferPtrs, 1667 chunkSize, chunkBufferPtrs,
1668 fadeIn, fadeOut); 1668 fadeIn, fadeOut);
1669 } 1669 }
1670 1670
1671 for (int c = 0; c < channels; ++c) { 1671 for (int c = 0; c < channels; ++c) {
1672 chunkBufferPtrs[c] += chunkSize; 1672 chunkBufferPtrs[c] += chunkSize;
1673 } 1673 }
1674 1674
1675 processed += chunkSize; 1675 processed += chunkSize;
1676 chunkStart = nextChunkStart; 1676 chunkStart = nextChunkStart;
1677 } 1677 }
1678 1678
1679 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1679 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1680 cout << "mixModels returning " << processed << " frames to " << nextChunkStart << endl; 1680 cout << "mixModels returning " << processed << " frames to " << nextChunkStart << endl;
1681 #endif 1681 #endif
1689 { 1689 {
1690 if (m_readBuffers == m_writeBuffers) return; 1690 if (m_readBuffers == m_writeBuffers) return;
1691 1691
1692 // only unify if there will be something to read 1692 // only unify if there will be something to read
1693 for (int c = 0; c < getTargetChannelCount(); ++c) { 1693 for (int c = 0; c < getTargetChannelCount(); ++c) {
1694 RingBuffer<float> *wb = getWriteRingBuffer(c); 1694 RingBuffer<float> *wb = getWriteRingBuffer(c);
1695 if (wb) { 1695 if (wb) {
1696 if (wb->getReadSpace() < m_blockSize * 2) { 1696 if (wb->getReadSpace() < m_blockSize * 2) {
1697 if ((m_writeBufferFill + m_blockSize * 2) < 1697 if ((m_writeBufferFill + m_blockSize * 2) <
1698 m_lastModelEndFrame) { 1698 m_lastModelEndFrame) {
1699 // OK, we don't have enough and there's more to 1699 // OK, we don't have enough and there's more to
1700 // read -- don't unify until we can do better 1700 // read -- don't unify until we can do better
1701 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1701 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1702 cout << "AudioCallbackPlaySource::unifyRingBuffers: Not unifying: write buffer has less (" << wb->getReadSpace() << ") than " << m_blockSize*2 << " to read and write buffer fill (" << m_writeBufferFill << ") is not close to end frame (" << m_lastModelEndFrame << ")" << endl; 1702 cout << "AudioCallbackPlaySource::unifyRingBuffers: Not unifying: write buffer has less (" << wb->getReadSpace() << ") than " << m_blockSize*2 << " to read and write buffer fill (" << m_writeBufferFill << ") is not close to end frame (" << m_lastModelEndFrame << ")" << endl;
1703 #endif 1703 #endif
1704 return; 1704 return;
1705 } 1705 }
1706 } 1706 }
1707 break; 1707 break;
1708 } 1708 }
1709 } 1709 }
1710 1710
1711 sv_frame_t rf = m_readBufferFill; 1711 sv_frame_t rf = m_readBufferFill;
1712 RingBuffer<float> *rb = getReadRingBuffer(0); 1712 RingBuffer<float> *rb = getReadRingBuffer(0);
1713 if (rb) { 1713 if (rb) {
1714 int rs = rb->getReadSpace(); 1714 int rs = rb->getReadSpace();
1715 //!!! incorrect when in non-contiguous selection, see comments elsewhere 1715 //!!! incorrect when in non-contiguous selection, see comments elsewhere
1716 // cout << "rs = " << rs << endl; 1716 // cout << "rs = " << rs << endl;
1717 if (rs < rf) rf -= rs; 1717 if (rs < rf) rf -= rs;
1718 else rf = 0; 1718 else rf = 0;
1719 } 1719 }
1720 1720
1721 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1721 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1722 cout << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl; 1722 cout << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << endl;
1723 #endif 1723 #endif
1724 1724
1725 sv_frame_t wf = m_writeBufferFill; 1725 sv_frame_t wf = m_writeBufferFill;
1726 sv_frame_t skip = 0; 1726 sv_frame_t skip = 0;
1727 for (int c = 0; c < getTargetChannelCount(); ++c) { 1727 for (int c = 0; c < getTargetChannelCount(); ++c) {
1728 RingBuffer<float> *wb = getWriteRingBuffer(c); 1728 RingBuffer<float> *wb = getWriteRingBuffer(c);
1729 if (wb) { 1729 if (wb) {
1730 if (c == 0) { 1730 if (c == 0) {
1731 1731
1732 int wrs = wb->getReadSpace(); 1732 int wrs = wb->getReadSpace();
1733 // cout << "wrs = " << wrs << endl; 1733 // cout << "wrs = " << wrs << endl;
1734 1734
1735 if (wrs < wf) wf -= wrs; 1735 if (wrs < wf) wf -= wrs;
1736 else wf = 0; 1736 else wf = 0;
1737 // cout << "wf = " << wf << endl; 1737 // cout << "wf = " << wf << endl;
1738 1738
1739 if (wf < rf) skip = rf - wf; 1739 if (wf < rf) skip = rf - wf;
1740 if (skip == 0) break; 1740 if (skip == 0) break;
1741 } 1741 }
1742 1742
1743 // cout << "skipping " << skip << endl; 1743 // cout << "skipping " << skip << endl;
1744 wb->skip(int(skip)); 1744 wb->skip(int(skip));
1745 } 1745 }
1746 } 1746 }
1747 1747
1748 m_bufferScavenger.claim(m_readBuffers); 1748 m_bufferScavenger.claim(m_readBuffers);
1749 m_readBuffers = m_writeBuffers; 1749 m_readBuffers = m_writeBuffers;
1750 m_readBufferFill = m_writeBufferFill; 1750 m_readBufferFill = m_writeBufferFill;
1751 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1751 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1752 cout << "unified" << endl; 1752 cout << "unified" << endl;
1767 bool previouslyPlaying = s.m_playing; 1767 bool previouslyPlaying = s.m_playing;
1768 bool work = false; 1768 bool work = false;
1769 1769
1770 while (!s.m_exiting) { 1770 while (!s.m_exiting) {
1771 1771
1772 s.unifyRingBuffers(); 1772 s.unifyRingBuffers();
1773 s.m_bufferScavenger.scavenge(); 1773 s.m_bufferScavenger.scavenge();
1774 s.m_pluginScavenger.scavenge(); 1774 s.m_pluginScavenger.scavenge();
1775 1775
1776 if (work && s.m_playing && s.getSourceSampleRate()) { 1776 if (work && s.m_playing && s.getSourceSampleRate()) {
1777 1777
1778 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1778 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1779 cout << "AudioCallbackPlaySourceFillThread: not waiting" << endl; 1779 cout << "AudioCallbackPlaySourceFillThread: not waiting" << endl;
1780 #endif 1780 #endif
1781 1781
1782 s.m_mutex.unlock(); 1782 s.m_mutex.unlock();
1783 s.m_mutex.lock(); 1783 s.m_mutex.lock();
1784 1784
1785 } else { 1785 } else {
1786 1786
1787 double ms = 100; 1787 double ms = 100;
1788 if (s.getSourceSampleRate() > 0) { 1788 if (s.getSourceSampleRate() > 0) {
1789 ms = double(s.m_ringBufferSize) / s.getSourceSampleRate() * 1000.0; 1789 ms = double(s.m_ringBufferSize) / s.getSourceSampleRate() * 1000.0;
1790 } 1790 }
1791 1791
1792 if (s.m_playing) ms /= 10; 1792 if (s.m_playing) ms /= 10;
1793 1793
1794 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1794 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1795 if (!s.m_playing) cout << endl; 1795 if (!s.m_playing) cout << endl;
1796 cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << endl; 1796 cout << "AudioCallbackPlaySourceFillThread: waiting for " << ms << "ms..." << endl;
1797 #endif 1797 #endif
1798 1798
1799 s.m_condition.wait(&s.m_mutex, int(ms)); 1799 s.m_condition.wait(&s.m_mutex, int(ms));
1800 } 1800 }
1801 1801
1802 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1802 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1803 cout << "AudioCallbackPlaySourceFillThread: awoken" << endl; 1803 cout << "AudioCallbackPlaySourceFillThread: awoken" << endl;
1804 #endif 1804 #endif
1805 1805
1806 work = false; 1806 work = false;
1807 1807
1808 if (!s.getSourceSampleRate()) { 1808 if (!s.getSourceSampleRate()) {
1809 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1809 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1810 cout << "AudioCallbackPlaySourceFillThread: source sample rate is zero" << endl; 1810 cout << "AudioCallbackPlaySourceFillThread: source sample rate is zero" << endl;
1811 #endif 1811 #endif
1812 continue; 1812 continue;
1813 } 1813 }
1814 1814
1815 bool playing = s.m_playing; 1815 bool playing = s.m_playing;
1816 1816
1817 if (playing && !previouslyPlaying) { 1817 if (playing && !previouslyPlaying) {
1818 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1818 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1819 cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << endl; 1819 cout << "AudioCallbackPlaySourceFillThread: playback state changed, resetting" << endl;
1820 #endif 1820 #endif
1821 for (int c = 0; c < s.getTargetChannelCount(); ++c) { 1821 for (int c = 0; c < s.getTargetChannelCount(); ++c) {
1822 RingBuffer<float> *rb = s.getReadRingBuffer(c); 1822 RingBuffer<float> *rb = s.getReadRingBuffer(c);
1823 if (rb) rb->reset(); 1823 if (rb) rb->reset();
1824 } 1824 }
1825 } 1825 }
1826 previouslyPlaying = playing; 1826 previouslyPlaying = playing;
1827 1827
1828 work = s.fillBuffers(); 1828 work = s.fillBuffers();
1829 } 1829 }
1830 1830
1831 s.m_mutex.unlock(); 1831 s.m_mutex.unlock();
1832 } 1832 }
1833 1833