Changeset 198035 in webkit
- Timestamp:
- Mar 11, 2016 11:35:15 AM (8 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r198028 r198035 1 2016-03-10 Jer Noble <jer.noble@apple.com> 2 3 Web Audio becomes distorted after sample rate changes 4 https://bugs.webkit.org/show_bug.cgi?id=154538 5 <rdar://problem/24771292> 6 7 Reviewed by Darin Adler. 8 9 When the underlying audio hardware sample rate changes, the AudioUnit render callback will begin asking 10 for fewer or more frames. For example, when the sample rate goes from 44.1kHz to 48kHz, it will ask for 11 118 samples instead of 128. (And vice-versa, 140 samples instead of 128.) But the Web Audio engine can only 12 really handle requests in multiples of 128 samples. In the case where there are requests for < 128 samples, 13 actually render 128, but save off the unrequested samples in a separate bus. Then fill that bus during the 14 next request. 15 16 * platform/audio/AudioBus.cpp: 17 (WebCore::AudioBus::copyFromRange): Added utility method. 18 * platform/audio/AudioBus.h: 19 * platform/audio/ios/AudioDestinationIOS.cpp: 20 (WebCore::AudioDestinationIOS::AudioDestinationIOS): Create a "spare" bus. 21 (WebCore::assignAudioBuffersToBus): Moved from inside render. 22 (WebCore::AudioDestinationIOS::render): Save off extra samples to the "spare" bus. 23 * platform/audio/ios/AudioDestinationIOS.h: 24 1 25 2016-03-11 Yusuke Suzuki <utatane.tea@gmail.com> 2 26 -
trunk/Source/WebCore/platform/audio/AudioBus.cpp
r194496 r198035 214 214 } 215 215 216 void AudioBus::copyFromRange(const AudioBus& sourceBus, unsigned startFrame, unsigned endFrame) 217 { 218 if (!topologyMatches(sourceBus)) { 219 ASSERT_NOT_REACHED(); 220 zero(); 221 return; 222 } 223 224 size_t numberOfSourceFrames = sourceBus.length(); 225 bool isRangeSafe = startFrame < endFrame && endFrame <= numberOfSourceFrames; 226 ASSERT(isRangeSafe); 227 if (!isRangeSafe) { 228 zero(); 229 return; 230 } 231 232 unsigned numberOfChannels = this->numberOfChannels(); 233 ASSERT(numberOfChannels <= MaxBusChannels); 234 if (numberOfChannels > MaxBusChannels) { 235 zero(); 236 return; 237 } 238 239 for (unsigned i = 0; i < numberOfChannels; ++i) 240 channel(i)->copyFromRange(sourceBus.channel(i), startFrame, endFrame); 241 } 242 216 243 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channelInterpretation) 217 244 { -
trunk/Source/WebCore/platform/audio/AudioBus.h
r177733 r198035 123 123 124 124 // Copies the samples from the source bus to this one. 125 void copyFromRange(const AudioBus& sourceBus, unsigned startFrame, unsigned endFrame); 126 127 // Copies the samples from the source bus to this one. 125 128 // This is just a simple per-channel copy if the number of channels match, otherwise an up-mix or down-mix is done. 126 129 void copyFrom(const AudioBus& sourceBus, ChannelInterpretation = Speakers); -
trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp
r197628 r198035 102 102 , m_callback(callback) 103 103 , m_renderBus(AudioBus::create(2, kRenderBufferSize, false)) 104 , m_spareBus(AudioBus::create(2, kRenderBufferSize, true)) 104 105 , m_sampleRate(sampleRate) 105 106 , m_isPlaying(false) … … 200 201 } 201 202 203 static void assignAudioBuffersToBus(AudioBuffer* buffers, AudioBus& bus, UInt32 numberOfBuffers, UInt32 numberOfFrames, UInt32 frameOffset, UInt32 framesThisTime) 204 { 205 for (UInt32 i = 0; i < numberOfBuffers; ++i) { 206 UInt32 bytesPerFrame = buffers[i].mDataByteSize / numberOfFrames; 207 UInt32 byteOffset = frameOffset * bytesPerFrame; 208 float* memory = reinterpret_cast<float*>(reinterpret_cast<char*>(buffers[i].mData) + byteOffset); 209 bus.setChannelMemory(i, memory, framesThisTime); 210 } 211 } 212 202 213 // Pulls on our provider to get rendered audio stream. 203 214 OSStatus AudioDestinationIOS::render(UInt32 numberOfFrames, AudioBufferList* ioData) 204 215 { 205 216 AudioBuffer* buffers = ioData->mBuffers; 206 for (UInt32 frameOffset = 0; frameOffset + kRenderBufferSize <= numberOfFrames; frameOffset += kRenderBufferSize) { 207 UInt32 remainingFrames = std::min<UInt32>(kRenderBufferSize, numberOfFrames - frameOffset); 208 for (UInt32 i = 0; i < ioData->mNumberBuffers; ++i) { 209 UInt32 bytesPerFrame = buffers[i].mDataByteSize / numberOfFrames; 210 UInt32 byteOffset = frameOffset * bytesPerFrame; 211 float* memory = (float*)((char*)buffers[i].mData + byteOffset); 212 m_renderBus->setChannelMemory(i, memory, remainingFrames); 217 UInt32 numberOfBuffers = ioData->mNumberBuffers; 218 UInt32 framesRemaining = numberOfFrames; 219 UInt32 frameOffset = 0; 220 while (framesRemaining > 0) { 221 if (m_firstSpareFrame && m_lastSpareFrame) { 222 ASSERT(m_firstSpareFrame < m_lastSpareFrame); 223 UInt32 framesThisTime = m_lastSpareFrame - m_firstSpareFrame; 224 assignAudioBuffersToBus(buffers, *m_renderBus, numberOfBuffers, numberOfFrames, frameOffset, framesThisTime); 225 m_renderBus->copyFromRange(*m_spareBus, m_firstSpareFrame, m_lastSpareFrame); 226 frameOffset += framesThisTime; 227 framesRemaining -= framesThisTime; 228 m_firstSpareFrame = 0; 229 m_lastSpareFrame = 0; 213 230 } 214 m_callback.render(0, m_renderBus.get(), remainingFrames); 231 232 UInt32 framesThisTime = std::min<UInt32>(kRenderBufferSize, framesRemaining); 233 assignAudioBuffersToBus(buffers, *m_renderBus, numberOfBuffers, numberOfFrames, frameOffset, framesThisTime); 234 235 if (framesThisTime < kRenderBufferSize) { 236 m_callback.render(0, m_spareBus.get(), kRenderBufferSize); 237 m_renderBus->copyFromRange(*m_spareBus, 0, framesThisTime); 238 m_firstSpareFrame = framesThisTime; 239 m_lastSpareFrame = kRenderBufferSize - 1; 240 } else 241 m_callback.render(0, m_renderBus.get(), framesThisTime); 242 frameOffset += framesThisTime; 243 framesRemaining -= framesThisTime; 215 244 } 216 245 -
trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.h
r197563 r198035 66 66 AudioIOCallback& m_callback; 67 67 RefPtr<AudioBus> m_renderBus; 68 RefPtr<AudioBus> m_spareBus; 69 unsigned m_firstSpareFrame { 0 }; 70 unsigned m_lastSpareFrame { 0 }; 68 71 69 72 double m_sampleRate;
Note: See TracChangeset
for help on using the changeset viewer.