Mercurial > hg > svapp
comparison audioio/AudioCallbackPlaySource.cpp @ 102:8591a0a3d57e
* Tolerable fixes to #1903062 and #1903046
| author | Chris Cannam |
|---|---|
| date | Wed, 27 Feb 2008 18:04:10 +0000 |
| parents | cd5cbdecc82d |
| children | 2485f822dc54 |
comparison
equal
deleted
inserted
replaced
| 99:cd5cbdecc82d | 102:8591a0a3d57e |
|---|---|
| 55 m_targetSampleRate(0), | 55 m_targetSampleRate(0), |
| 56 m_playLatency(0), | 56 m_playLatency(0), |
| 57 m_target(0), | 57 m_target(0), |
| 58 m_lastRetrievalTimestamp(0.0), | 58 m_lastRetrievalTimestamp(0.0), |
| 59 m_lastRetrievedBlockSize(0), | 59 m_lastRetrievedBlockSize(0), |
| 60 m_trustworthyTimestamps(true), | |
| 61 m_lastCurrentFrame(0), | |
| 60 m_playing(false), | 62 m_playing(false), |
| 61 m_exiting(false), | 63 m_exiting(false), |
| 62 m_lastModelEndFrame(0), | 64 m_lastModelEndFrame(0), |
| 63 m_outputLeft(0.0), | 65 m_outputLeft(0.0), |
| 64 m_outputRight(0.0), | 66 m_outputRight(0.0), |
| 377 std::cerr << startFrame << std::endl; | 379 std::cerr << startFrame << std::endl; |
| 378 | 380 |
| 379 // The fill thread will automatically empty its buffers before | 381 // The fill thread will automatically empty its buffers before |
| 380 // starting again if we have not so far been playing, but not if | 382 // starting again if we have not so far been playing, but not if |
| 381 // we're just re-seeking. | 383 // we're just re-seeking. |
| 384 // NO -- we can end up playing some first -- always reset here | |
| 382 | 385 |
| 383 m_mutex.lock(); | 386 m_mutex.lock(); |
| 387 | |
| 384 if (m_timeStretcher) { | 388 if (m_timeStretcher) { |
| 385 m_timeStretcher->reset(); | 389 m_timeStretcher->reset(); |
| 386 } | 390 } |
| 387 if (m_playing) { | 391 |
| 388 std::cerr << "playing already, resetting" << std::endl; | 392 m_readBufferFill = m_writeBufferFill = startFrame; |
| 389 m_readBufferFill = m_writeBufferFill = startFrame; | 393 if (m_readBuffers) { |
| 390 if (m_readBuffers) { | 394 for (size_t c = 0; c < getTargetChannelCount(); ++c) { |
| 391 for (size_t c = 0; c < getTargetChannelCount(); ++c) { | 395 RingBuffer<float> *rb = getReadRingBuffer(c); |
| 392 RingBuffer<float> *rb = getReadRingBuffer(c); | 396 std::cerr << "reset ring buffer for channel " << c << std::endl; |
| 393 std::cerr << "reset ring buffer for channel " << c << std::endl; | 397 if (rb) rb->reset(); |
| 394 if (rb) rb->reset(); | 398 } |
| 395 } | 399 } |
| 396 } | 400 if (m_converter) src_reset(m_converter); |
| 397 if (m_converter) src_reset(m_converter); | 401 if (m_crapConverter) src_reset(m_crapConverter); |
| 398 if (m_crapConverter) src_reset(m_crapConverter); | 402 |
| 399 } else { | |
| 400 if (m_converter) src_reset(m_converter); | |
| 401 if (m_crapConverter) src_reset(m_crapConverter); | |
| 402 m_readBufferFill = m_writeBufferFill = startFrame; | |
| 403 } | |
| 404 m_mutex.unlock(); | 403 m_mutex.unlock(); |
| 405 | 404 |
| 406 m_audioGenerator->reset(); | 405 m_audioGenerator->reset(); |
| 407 | 406 |
| 408 m_playStartFrame = startFrame; | 407 m_playStartFrame = startFrame; |
| 412 m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime()); | 411 m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime()); |
| 413 } | 412 } |
| 414 | 413 |
| 415 bool changed = !m_playing; | 414 bool changed = !m_playing; |
| 416 m_lastRetrievalTimestamp = 0; | 415 m_lastRetrievalTimestamp = 0; |
| 416 m_lastCurrentFrame = 0; | |
| 417 m_playing = true; | 417 m_playing = true; |
| 418 m_condition.wakeAll(); | 418 m_condition.wakeAll(); |
| 419 if (changed) emit playStatusChanged(m_playing); | 419 if (changed) emit playStatusChanged(m_playing); |
| 420 } | 420 } |
| 421 | 421 |
| 424 { | 424 { |
| 425 bool changed = m_playing; | 425 bool changed = m_playing; |
| 426 m_playing = false; | 426 m_playing = false; |
| 427 m_condition.wakeAll(); | 427 m_condition.wakeAll(); |
| 428 m_lastRetrievalTimestamp = 0; | 428 m_lastRetrievalTimestamp = 0; |
| 429 m_lastCurrentFrame = 0; | |
| 429 if (changed) emit playStatusChanged(m_playing); | 430 if (changed) emit playStatusChanged(m_playing); |
| 430 } | 431 } |
| 431 | 432 |
| 432 void | 433 void |
| 433 AudioCallbackPlaySource::selectionChanged() | 434 AudioCallbackPlaySource::selectionChanged() |
| 552 size_t readBufferFill = m_readBufferFill; | 553 size_t readBufferFill = m_readBufferFill; |
| 553 size_t lastRetrievedBlockSize = m_lastRetrievedBlockSize; | 554 size_t lastRetrievedBlockSize = m_lastRetrievedBlockSize; |
| 554 double lastRetrievalTimestamp = m_lastRetrievalTimestamp; | 555 double lastRetrievalTimestamp = m_lastRetrievalTimestamp; |
| 555 double currentTime = 0.0; | 556 double currentTime = 0.0; |
| 556 if (m_target) currentTime = m_target->getCurrentTime(); | 557 if (m_target) currentTime = m_target->getCurrentTime(); |
| 558 | |
| 559 bool looping = m_viewManager->getPlayLoopMode(); | |
| 557 | 560 |
| 558 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate); | 561 RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate); |
| 559 | 562 |
| 560 size_t stretchlat = 0; | 563 size_t stretchlat = 0; |
| 561 double timeRatio = 1.0; | 564 double timeRatio = 1.0; |
| 577 // from being played. | 580 // from being played. |
| 578 | 581 |
| 579 RealTime sincerequest_t = RealTime::zeroTime; | 582 RealTime sincerequest_t = RealTime::zeroTime; |
| 580 RealTime lastretrieved_t = RealTime::zeroTime; | 583 RealTime lastretrieved_t = RealTime::zeroTime; |
| 581 | 584 |
| 582 if (m_target && lastRetrievalTimestamp != 0.0) { | 585 if (m_target && |
| 586 m_trustworthyTimestamps && | |
| 587 lastRetrievalTimestamp != 0.0) { | |
| 583 | 588 |
| 584 lastretrieved_t = RealTime::frame2RealTime | 589 lastretrieved_t = RealTime::frame2RealTime |
| 585 (lastRetrievedBlockSize, targetRate); | 590 (lastRetrievedBlockSize, targetRate); |
| 586 | 591 |
| 587 // calculate number of frames at target rate that have elapsed | 592 // calculate number of frames at target rate that have elapsed |
| 588 // since the end of the last call to getSourceSamples | 593 // since the end of the last call to getSourceSamples |
| 589 | 594 |
| 590 double elapsed = currentTime - lastRetrievalTimestamp; | 595 if (m_trustworthyTimestamps && !looping) { |
| 591 | 596 |
| 592 if (elapsed > 0.0) { | 597 // this adjustment seems to cause more problems when looping |
| 593 sincerequest_t = RealTime::fromSeconds(elapsed); | 598 double elapsed = currentTime - lastRetrievalTimestamp; |
| 599 | |
| 600 if (elapsed > 0.0) { | |
| 601 sincerequest_t = RealTime::fromSeconds(elapsed); | |
| 602 } | |
| 594 } | 603 } |
| 595 | 604 |
| 596 } else { | 605 } else { |
| 597 | 606 |
| 598 lastretrieved_t = RealTime::frame2RealTime | 607 lastretrieved_t = RealTime::frame2RealTime |
| 603 | 612 |
| 604 if (timeRatio != 1.0) { | 613 if (timeRatio != 1.0) { |
| 605 lastretrieved_t = lastretrieved_t / timeRatio; | 614 lastretrieved_t = lastretrieved_t / timeRatio; |
| 606 sincerequest_t = sincerequest_t / timeRatio; | 615 sincerequest_t = sincerequest_t / timeRatio; |
| 607 } | 616 } |
| 608 | |
| 609 bool looping = m_viewManager->getPlayLoopMode(); | |
| 610 | 617 |
| 611 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING | 618 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING |
| 612 std::cerr << "\nbuffered to: " << bufferedto_t << ", in buffer: " << inbuffer_t << ", time ratio " << timeRatio << "\n stretcher latency: " << stretchlat_t << ", device latency: " << latency_t << "\n since request: " << sincerequest_t << ", last retrieved: " << lastretrieved_t << std::endl; | 619 std::cerr << "\nbuffered to: " << bufferedto_t << ", in buffer: " << inbuffer_t << ", time ratio " << timeRatio << "\n stretcher latency: " << stretchlat_t << ", device latency: " << latency_t << "\n since request: " << sincerequest_t << ", last retrieved: " << lastretrieved_t << std::endl; |
| 613 #endif | 620 #endif |
| 614 | 621 |
| 716 } | 723 } |
| 717 | 724 |
| 718 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; | 725 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime; |
| 719 | 726 |
| 720 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate); | 727 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate); |
| 728 | |
| 729 if (m_lastCurrentFrame > 0 && !looping) { | |
| 730 if (frame < m_lastCurrentFrame) { | |
| 731 frame = m_lastCurrentFrame; | |
| 732 } | |
| 733 } | |
| 734 | |
| 735 m_lastCurrentFrame = frame; | |
| 736 | |
| 721 return m_viewManager->alignPlaybackFrameToReference(frame); | 737 return m_viewManager->alignPlaybackFrameToReference(frame); |
| 722 } | 738 } |
| 723 | 739 |
| 724 void | 740 void |
| 725 AudioCallbackPlaySource::rebuildRangeLists() | 741 AudioCallbackPlaySource::rebuildRangeLists() |
| 1135 // std::cerr << "plugin output count " << plugin->getAudioOutputCount() | 1151 // std::cerr << "plugin output count " << plugin->getAudioOutputCount() |
| 1136 // << " != our channel count " << getTargetChannelCount() | 1152 // << " != our channel count " << getTargetChannelCount() |
| 1137 // << std::endl; | 1153 // << std::endl; |
| 1138 return; | 1154 return; |
| 1139 } | 1155 } |
| 1140 if (plugin->getBufferSize() != count) { | 1156 if (plugin->getBufferSize() < count) { |
| 1141 // std::cerr << "plugin buffer size " << plugin->getBufferSize() | 1157 // std::cerr << "plugin buffer size " << plugin->getBufferSize() |
| 1142 // << " != our block size " << count | 1158 // << " < our block size " << count |
| 1143 // << std::endl; | 1159 // << std::endl; |
| 1144 return; | 1160 return; |
| 1145 } | 1161 } |
| 1146 | 1162 |
| 1147 float **ib = plugin->getAudioInputBuffers(); | 1163 float **ib = plugin->getAudioInputBuffers(); |
| 1151 for (size_t i = 0; i < count; ++i) { | 1167 for (size_t i = 0; i < count; ++i) { |
| 1152 ib[c][i] = buffers[c][i]; | 1168 ib[c][i] = buffers[c][i]; |
| 1153 } | 1169 } |
| 1154 } | 1170 } |
| 1155 | 1171 |
| 1156 plugin->run(Vamp::RealTime::zeroTime); | 1172 plugin->run(Vamp::RealTime::zeroTime, count); |
| 1157 | 1173 |
| 1158 for (size_t c = 0; c < getTargetChannelCount(); ++c) { | 1174 for (size_t c = 0; c < getTargetChannelCount(); ++c) { |
| 1159 for (size_t i = 0; i < count; ++i) { | 1175 for (size_t i = 0; i < count; ++i) { |
| 1160 buffers[c][i] = ob[c][i]; | 1176 buffers[c][i] = ob[c][i]; |
| 1161 } | 1177 } |
