Changeset 100210 in webkit
- Timestamp:
- Nov 14, 2011, 4:18:44 PM (15 years ago)
- Location:
- trunk/Source/WebKit/chromium
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
src/AudioDestinationChromium.cpp (modified) (4 diffs)
-
src/AudioDestinationChromium.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/chromium/ChangeLog
r100199 r100210 1 2011-11-14 Raymond Toy <rtoy@google.com> 2 3 Add buffering to handle mismatch between hardware buffer size and webaudio render size 4 https://bugs.webkit.org/show_bug.cgi?id=71949 5 6 Reviewed by Kenneth Russell. 7 8 * src/AudioDestinationChromium.cpp: 9 (WebCore::AudioDestinationChromium::AudioDestinationChromium): 10 Create the FIFO for buffering. 11 (WebCore::AudioDestinationChromium::render): Get rid of 12 m_renderCountPerCallback and let the FIFO consume function produce 13 the appropriate nubmer of calls to the webaudio producer. Also 14 remove the rounding of the callback size so we use whatever the 15 hardware returns. Removed maximumCallbackBufferSize and use 16 fifoSize to set the FIFO size. 17 (WebCore::AudioDestinationChromium::FIFO::FIFO): 18 (WebCore::AudioDestinationChromium::FIFO::consume): 19 (WebCore::AudioDestinationChromium::FIFO::findWrapLengths): 20 (WebCore::AudioDestinationChromium::FIFO::fillBuffer): 21 Implementation of new FIFO class. 22 * src/AudioDestinationChromium.h: 23 (WebCore::AudioDestinationChromium::FIFO::updateIndex): 24 Define new FIFO class. 25 1 26 2011-11-14 Adrienne Walker <enne@google.com> 2 27 -
trunk/Source/WebKit/chromium/src/AudioDestinationChromium.cpp
r98837 r100210 33 33 #include "AudioDestinationChromium.h" 34 34 35 #include "AudioSourceProvider.h"36 35 #include "WebKit.h" 37 36 #include "WebKitPlatformSupport.h" … … 44 43 const unsigned renderBufferSize = 128; 45 44 46 // Maximum allowed buffer size47 const size_t maximumCallbackBufferSize = 16384;45 // Size of the FIFO 46 const size_t fifoSize = 8192; 48 47 49 48 // FIXME: add support for multi-channel. … … 62 61 , m_isPlaying(false) 63 62 { 64 // Get the minimum usable buffer size. We'll round this value up 65 // to a multiple of our render size. 66 size_t callbackSize = webKitPlatformSupport()->audioHardwareBufferSize(); 67 68 // Figure out how many render calls per call back, rounding up if needed. 69 m_renderCountPerCallback = (callbackSize + renderBufferSize - 1) / renderBufferSize; 70 71 m_callbackBufferSize = m_renderCountPerCallback * renderBufferSize; 72 73 bool isSizeGood = m_callbackBufferSize >= renderBufferSize 74 && m_callbackBufferSize <= maximumCallbackBufferSize; 75 ASSERT(isSizeGood); 76 if (!isSizeGood) 77 return; 63 // Use the optimal buffer size recommended by the audio backend. 64 m_callbackBufferSize = webKitPlatformSupport()->audioHardwareBufferSize(); 65 66 // Quick exit if the requested size is too large. 67 ASSERT(m_callbackBufferSize + renderBufferSize <= fifoSize); 68 if (m_callbackBufferSize + renderBufferSize > fifoSize) 69 return; 78 70 79 71 m_audioDevice = adoptPtr(webKitPlatformSupport()->createAudioDevice(m_callbackBufferSize, numberOfChannels, sampleRate, this)); 80 72 ASSERT(m_audioDevice); 73 74 // Create a FIFO to handle the possibility of the callback size 75 // not being a multiple of the render size. If the FIFO already 76 // contains enough data, the data will be provided directly. 77 // Otherwise, the FIFO will call the provider enough times to 78 // satisfy the request for data. 79 m_fifo = adoptPtr(new FIFO(provider, numberOfChannels, fifoSize, renderBufferSize)); 81 80 } 82 81 … … 122 121 } 123 122 124 // Split up the callback buffer into smaller chunks which we'll render one after the other. 125 for (unsigned i = 0; i < m_renderCountPerCallback; ++i) { 126 m_renderBus.setChannelMemory(0, audioData[0] + i * renderBufferSize, renderBufferSize); 127 m_renderBus.setChannelMemory(1, audioData[1] + i * renderBufferSize, renderBufferSize); 128 m_provider.provideInput(&m_renderBus, renderBufferSize); 123 m_renderBus.setChannelMemory(0, audioData[0], numberOfFrames); 124 m_renderBus.setChannelMemory(1, audioData[1], numberOfFrames); 125 m_fifo->consume(&m_renderBus, numberOfFrames); 126 } 127 128 AudioDestinationChromium::FIFO::FIFO(AudioSourceProvider& provider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize) 129 : m_provider(provider) 130 , m_fifoAudioBus(numberOfChannels, fifoLength) 131 , m_fifoLength(fifoLength) 132 , m_framesInFifo(0) 133 , m_readIndex(0) 134 , m_writeIndex(0) 135 , m_providerSize(providerSize) 136 , m_tempBus(numberOfChannels, providerSize) 137 { 138 } 139 140 void AudioDestinationChromium::FIFO::consume(AudioBus* destination, size_t framesToConsume) 141 { 142 bool isGood = destination && (framesToConsume <= m_fifoLength); 143 ASSERT(isGood); 144 if (!isGood) 145 return; 146 147 if (framesToConsume > m_framesInFifo) { 148 // We don't have enough data in the FIFO to fulfill the 149 // request. Ask for more data. 150 fillBuffer(framesToConsume - m_framesInFifo); 151 } 152 153 // We have enough data now. Copy the requested number of samples 154 // to the destination. 155 156 size_t part1Length; 157 size_t part2Length; 158 findWrapLengths(m_readIndex, framesToConsume, part1Length, part2Length); 159 160 size_t numberOfChannels = m_fifoAudioBus.numberOfChannels(); 161 162 for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { 163 float* destinationData = destination->channel(channelIndex)->data(); 164 float* sourceData = m_fifoAudioBus.channel(channelIndex)->data(); 165 166 bool isCopyGood = ((m_readIndex < m_fifoLength) 167 && (m_readIndex + part1Length) <= m_fifoLength 168 && (part1Length <= destination->length()) 169 && (part1Length + part2Length) <= destination->length()); 170 ASSERT(isCopyGood); 171 if (!isCopyGood) 172 return; 173 174 memcpy(destinationData, sourceData + m_readIndex, part1Length * sizeof(*sourceData)); 175 // Handle wrap around of the FIFO, if needed. 176 if (part2Length > 0) 177 memcpy(destinationData + part1Length, sourceData, part2Length * sizeof(*sourceData)); 178 } 179 m_readIndex = updateIndex(m_readIndex, framesToConsume); 180 m_framesInFifo -= framesToConsume; 181 ASSERT(m_framesInFifo >= 0); 182 } 183 184 void AudioDestinationChromium::FIFO::findWrapLengths(size_t index, size_t size, size_t& part1Length, size_t& part2Length) 185 { 186 ASSERT(index < m_fifoLength && size <= m_fifoLength); 187 if (index < m_fifoLength && size <= m_fifoLength) { 188 if (index + size > m_fifoLength) { 189 // Need to wrap. Figure out the length of each piece. 190 part1Length = m_fifoLength - index; 191 part2Length = size - part1Length; 192 } else { 193 // No wrap needed. 194 part1Length = size; 195 part2Length = 0; 196 } 197 } else { 198 // Invalid values for index or size. Set the part lengths to 199 // zero so nothing is copied. 200 part1Length = 0; 201 part2Length = 0; 202 } 203 } 204 205 void AudioDestinationChromium::FIFO::fillBuffer(size_t numberOfFrames) 206 { 207 // Keep asking the provider to give us data until we have received 208 // at least |numberOfFrames| of data. Stuff the data into the 209 // FIFO. 210 size_t framesProvided = 0; 211 212 while (framesProvided < numberOfFrames) { 213 m_provider.provideInput(&m_tempBus, m_providerSize); 214 215 size_t part1Length; 216 size_t part2Length; 217 findWrapLengths(m_writeIndex, m_providerSize, part1Length, part2Length); 218 219 size_t numberOfChannels = m_fifoAudioBus.numberOfChannels(); 220 221 for (size_t channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) { 222 float* destination = m_fifoAudioBus.channel(channelIndex)->data(); 223 float* source = m_tempBus.channel(channelIndex)->data(); 224 225 bool isCopyGood = (part1Length <= m_providerSize 226 && (part1Length + part2Length) <= m_providerSize 227 && (m_writeIndex < m_fifoLength) 228 && (m_writeIndex + part1Length) <= m_fifoLength 229 && part2Length < m_fifoLength); 230 ASSERT(isCopyGood); 231 if (!isCopyGood) 232 return; 233 234 memcpy(destination + m_writeIndex, source, part1Length * sizeof(*destination)); 235 // Handle wrap around of the FIFO, if needed. 236 if (part2Length > 0) 237 memcpy(destination, source + part1Length, part2Length * sizeof(*destination)); 238 } 239 240 m_framesInFifo += m_providerSize; 241 ASSERT(m_framesInFifo <= m_fifoLength); 242 m_writeIndex = updateIndex(m_writeIndex, m_providerSize); 243 framesProvided += m_providerSize; 129 244 } 130 245 } -
trunk/Source/WebKit/chromium/src/AudioDestinationChromium.h
r96745 r100210 32 32 #include "AudioBus.h" 33 33 #include "AudioDestination.h" 34 #include "AudioSourceProvider.h" 34 35 #include "WebAudioDevice.h" 35 36 #include "WebVector.h" … … 56 57 57 58 private: 58 AudioSourceProvider& m_provider; 59 // A FIFO (First In First Out) buffer to handle mismatches in the 60 // audio backend hardware buffer size and the Web Audio render size. 61 class FIFO { 62 public: 63 // Create a FIFO that gets data from |provider|. The FIFO will 64 // be large enough to hold |fifoLength| frames of data of 65 // |numberOfChannels| channels. The AudioSourceProvider will 66 // be asked to produce |providerSize| frames when the FIFO 67 // needs more data. 68 FIFO(AudioSourceProvider& provider, unsigned numberOfChannels, size_t fifoLength, size_t providerSize); 69 70 // Read |framesToConsume| frames from the FIFO into the 71 // destination. If the FIFO does not have enough data, we ask 72 // the |provider| to get more data to fulfill the request. 73 void consume(AudioBus* destination, size_t framesToConsume); 74 75 private: 76 // Update the FIFO index by the step, with appropriate 77 // wrapping around the endpoint. 78 int updateIndex(int index, int step) { return (index + step) % m_fifoLength; } 79 80 void findWrapLengths(size_t index, size_t providerSize, size_t& part1Length, size_t& part2Length); 81 82 // Fill the FIFO buffer with at least |numberOfFrames| more data. 83 void fillBuffer(size_t numberOfFrames); 84 85 // The provider of the data in our FIFO. 86 AudioSourceProvider& m_provider; 87 88 // The FIFO itself. In reality, the FIFO is a circular buffer. 89 AudioBus m_fifoAudioBus; 90 91 // The total available space in the FIFO. 92 size_t m_fifoLength; 93 94 // The number of actual elements in the FIFO 95 size_t m_framesInFifo; 96 97 // Where to start reading from the FIFO. 98 size_t m_readIndex; 99 100 // Where to start writing to the FIFO. 101 size_t m_writeIndex; 102 103 // Number of frames of data that the provider will produce per call. 104 unsigned int m_providerSize; 105 106 // Temporary workspace to hold the data from the provider. 107 AudioBus m_tempBus; 108 }; 109 110 AudioSourceProvider& m_provider; 59 111 AudioBus m_renderBus; 60 112 float m_sampleRate; … … 62 114 OwnPtr<WebKit::WebAudioDevice> m_audioDevice; 63 115 size_t m_callbackBufferSize; 64 unsigned m_renderCountPerCallback;116 OwnPtr<FIFO> m_fifo; 65 117 }; 66 118
Note:
See TracChangeset
for help on using the changeset viewer.