Mercurial > hg > svapp
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 |