comparison audioio/AudioCallbackPlaySource.cpp @ 193:0b3aa9b702bb

* Fix problems playing back when the target block size is close to, or greater than, the default ring-buffer size
author Chris Cannam
date Tue, 22 Jun 2010 13:48:00 +0000
parents 017206f2e4c5
children d9c21e7bff21
comparison
equal deleted inserted replaced
192:2b1869fccec1 193:0b3aa9b702bb
35 #include <cassert> 35 #include <cassert>
36 36
37 //#define DEBUG_AUDIO_PLAY_SOURCE 1 37 //#define DEBUG_AUDIO_PLAY_SOURCE 1
38 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1 38 //#define DEBUG_AUDIO_PLAY_SOURCE_PLAYING 1
39 39
40 const size_t AudioCallbackPlaySource::m_ringBufferSize = 131071; 40 static const size_t DEFAULT_RING_BUFFER_SIZE = 131071;
41 41
42 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager, 42 AudioCallbackPlaySource::AudioCallbackPlaySource(ViewManagerBase *manager,
43 QString clientName) : 43 QString clientName) :
44 m_viewManager(manager), 44 m_viewManager(manager),
45 m_audioGenerator(new AudioGenerator()), 45 m_audioGenerator(new AudioGenerator()),
60 m_trustworthyTimestamps(true), 60 m_trustworthyTimestamps(true),
61 m_lastCurrentFrame(0), 61 m_lastCurrentFrame(0),
62 m_playing(false), 62 m_playing(false),
63 m_exiting(false), 63 m_exiting(false),
64 m_lastModelEndFrame(0), 64 m_lastModelEndFrame(0),
65 m_ringBufferSize(DEFAULT_RING_BUFFER_SIZE),
65 m_outputLeft(0.0), 66 m_outputLeft(0.0),
66 m_outputRight(0.0), 67 m_outputRight(0.0),
67 m_auditioningPlugin(0), 68 m_auditioningPlugin(0),
68 m_auditioningPluginBypassed(false), 69 m_auditioningPluginBypassed(false),
69 m_playStartFrame(0), 70 m_playStartFrame(0),
527 528
528 void 529 void
529 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, size_t size) 530 AudioCallbackPlaySource::setTarget(AudioCallbackPlayTarget *target, size_t size)
530 { 531 {
531 m_target = target; 532 m_target = target;
532 // std::cout << "AudioCallbackPlaySource::setTargetBlockSize() -> " << size << std::endl; 533 std::cout << "AudioCallbackPlaySource::setTarget: Block size -> " << size << std::endl;
533 assert(size < m_ringBufferSize); 534 if (size != 0) {
534 m_blockSize = size; 535 m_blockSize = size;
536 }
537 if (size * 4 > m_ringBufferSize) {
538 std::cerr << "AudioCallbackPlaySource::setTarget: Buffer size "
539 << size << " > a quarter of ring buffer size "
540 << m_ringBufferSize << ", calling for more ring buffer"
541 << std::endl;
542 m_ringBufferSize = size * 4;
543 if (m_writeBuffers && !m_writeBuffers->empty()) {
544 clearRingBuffers();
545 }
546 }
535 } 547 }
536 548
537 size_t 549 size_t
538 AudioCallbackPlaySource::getTargetBlockSize() const 550 AudioCallbackPlaySource::getTargetBlockSize() const
539 { 551 {
682 if (m_rangeStarts.empty()) { 694 if (m_rangeStarts.empty()) {
683 // this code is only used in case of error in rebuildRangeLists 695 // this code is only used in case of error in rebuildRangeLists
684 RealTime playing_t = bufferedto_t 696 RealTime playing_t = bufferedto_t
685 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t 697 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t
686 + sincerequest_t; 698 + sincerequest_t;
699 if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
687 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate); 700 size_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
688 return m_viewManager->alignPlaybackFrameToReference(frame); 701 return m_viewManager->alignPlaybackFrameToReference(frame);
689 } 702 }
690 703
691 int inRange = 0; 704 int inRange = 0;
1031 AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer) 1044 AudioCallbackPlaySource::getSourceSamples(size_t ucount, float **buffer)
1032 { 1045 {
1033 int count = ucount; 1046 int count = ucount;
1034 1047
1035 if (!m_playing) { 1048 if (!m_playing) {
1049 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1050 std::cerr << "AudioCallbackPlaySource::getSourceSamples: Not playing" << std::endl;
1051 #endif
1036 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) { 1052 for (size_t ch = 0; ch < getTargetChannelCount(); ++ch) {
1037 for (int i = 0; i < count; ++i) { 1053 for (int i = 0; i < count; ++i) {
1038 buffer[ch][i] = 0.0; 1054 buffer[ch][i] = 0.0;
1039 } 1055 }
1040 } 1056 }
1059 size_t rs = rb->getReadSpace(); 1075 size_t rs = rb->getReadSpace();
1060 if (rs < count) { 1076 if (rs < count) {
1061 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1077 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1062 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: " 1078 std::cerr << "WARNING: AudioCallbackPlaySource::getSourceSamples: "
1063 << "Ring buffer for channel " << ch << " has only " 1079 << "Ring buffer for channel " << ch << " has only "
1064 << rs << " (of " << count << ") samples available, " 1080 << rs << " (of " << count << ") samples available ("
1081 << "ring buffer size is " << rb->getSize() << ", write "
1082 << "space " << rb->getWriteSpace() << "), "
1065 << "reducing request size" << std::endl; 1083 << "reducing request size" << std::endl;
1066 #endif 1084 #endif
1067 count = rs; 1085 count = rs;
1068 } 1086 }
1069 } 1087 }
1295 size_t f = m_writeBufferFill; 1313 size_t f = m_writeBufferFill;
1296 1314
1297 bool readWriteEqual = (m_readBuffers == m_writeBuffers); 1315 bool readWriteEqual = (m_readBuffers == m_writeBuffers);
1298 1316
1299 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1317 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1318 if (!readWriteEqual) {
1319 std::cout << "AudioCallbackPlaySourceFillThread: note read buffers != write buffers" << std::endl;
1320 }
1300 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl; 1321 std::cout << "AudioCallbackPlaySourceFillThread: filling " << space << " frames" << std::endl;
1301 #endif 1322 #endif
1302 1323
1303 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1324 #ifdef DEBUG_AUDIO_PLAY_SOURCE
1304 std::cout << "buffered to " << f << " already" << std::endl; 1325 std::cout << "buffered to " << f << " already" << std::endl;
1663 if (wb->getReadSpace() < m_blockSize * 2) { 1684 if (wb->getReadSpace() < m_blockSize * 2) {
1664 if ((m_writeBufferFill + m_blockSize * 2) < 1685 if ((m_writeBufferFill + m_blockSize * 2) <
1665 m_lastModelEndFrame) { 1686 m_lastModelEndFrame) {
1666 // OK, we don't have enough and there's more to 1687 // OK, we don't have enough and there's more to
1667 // read -- don't unify until we can do better 1688 // read -- don't unify until we can do better
1689 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1690 std::cerr << "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 << ")" << std::endl;
1691 #endif
1668 return; 1692 return;
1669 } 1693 }
1670 } 1694 }
1671 break; 1695 break;
1672 } 1696 }
1680 // std::cout << "rs = " << rs << std::endl; 1704 // std::cout << "rs = " << rs << std::endl;
1681 if (rs < rf) rf -= rs; 1705 if (rs < rf) rf -= rs;
1682 else rf = 0; 1706 else rf = 0;
1683 } 1707 }
1684 1708
1685 //std::cout << "m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << std::endl; 1709 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1710 std::cerr << "AudioCallbackPlaySource::unifyRingBuffers: m_readBufferFill = " << m_readBufferFill << ", rf = " << rf << ", m_writeBufferFill = " << m_writeBufferFill << std::endl;
1711 #endif
1686 1712
1687 size_t wf = m_writeBufferFill; 1713 size_t wf = m_writeBufferFill;
1688 size_t skip = 0; 1714 size_t skip = 0;
1689 for (size_t c = 0; c < getTargetChannelCount(); ++c) { 1715 for (size_t c = 0; c < getTargetChannelCount(); ++c) {
1690 RingBuffer<float> *wb = getWriteRingBuffer(c); 1716 RingBuffer<float> *wb = getWriteRingBuffer(c);
1708 } 1734 }
1709 1735
1710 m_bufferScavenger.claim(m_readBuffers); 1736 m_bufferScavenger.claim(m_readBuffers);
1711 m_readBuffers = m_writeBuffers; 1737 m_readBuffers = m_writeBuffers;
1712 m_readBufferFill = m_writeBufferFill; 1738 m_readBufferFill = m_writeBufferFill;
1713 // std::cout << "unified" << std::endl; 1739 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
1740 std::cerr << "unified" << std::endl;
1741 #endif
1714 } 1742 }
1715 1743
1716 void 1744 void
1717 AudioCallbackPlaySource::FillThread::run() 1745 AudioCallbackPlaySource::FillThread::run()
1718 { 1746 {
1744 1772
1745 } else { 1773 } else {
1746 1774
1747 float ms = 100; 1775 float ms = 100;
1748 if (s.getSourceSampleRate() > 0) { 1776 if (s.getSourceSampleRate() > 0) {
1749 ms = float(m_ringBufferSize) / float(s.getSourceSampleRate()) * 1000.0; 1777 ms = float(s.m_ringBufferSize) /
1778 float(s.getSourceSampleRate()) * 1000.0;
1750 } 1779 }
1751 1780
1752 if (s.m_playing) ms /= 10; 1781 if (s.m_playing) ms /= 10;
1753 1782
1754 #ifdef DEBUG_AUDIO_PLAY_SOURCE 1783 #ifdef DEBUG_AUDIO_PLAY_SOURCE