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