Changeset 270155 in webkit
- Timestamp:
- Nov 21, 2020 7:03:46 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 4 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r270150 r270155 1 2020-11-21 Chris Dumez <cdumez@apple.com> 2 3 Unreviewed, reverting r270141. 4 5 Caused assertions on bots 6 7 Reverted changeset: 8 9 "Poor resampling quality when using AudioContext sampleRate 10 parameter" 11 https://bugs.webkit.org/show_bug.cgi?id=219201 12 https://trac.webkit.org/changeset/270141 13 1 14 2020-11-21 Antti Koivisto <antti@apple.com> 2 15 -
trunk/Source/WebCore/ChangeLog
r270154 r270155 1 2020-11-21 Chris Dumez <cdumez@apple.com> 2 3 Unreviewed, reverting r270141. 4 5 Caused assertions on bots 6 7 Reverted changeset: 8 9 "Poor resampling quality when using AudioContext sampleRate 10 parameter" 11 https://bugs.webkit.org/show_bug.cgi?id=219201 12 https://trac.webkit.org/changeset/270141 13 1 14 2020-11-21 Andres Gonzalez <andresg_22@apple.com> 2 15 -
trunk/Source/WebCore/platform/audio/MultiChannelResampler.cpp
r270141 r270155 34 34 35 35 #include "AudioBus.h" 36 #include "AudioUtilities.h"37 36 38 37 namespace WebCore { … … 40 39 // ChannelProvider provides a single channel of audio data (one channel at a time) for each channel 41 40 // of data provided to us in a multi-channel provider. 42 class MultiChannelResampler::ChannelProvider {41 class MultiChannelResampler::ChannelProvider : public AudioSourceProvider { 43 42 WTF_MAKE_FAST_ALLOCATED; 44 43 public: 45 44 explicit ChannelProvider(unsigned numberOfChannels) 46 : m_ multiChannelBus(AudioBus::create(numberOfChannels, AudioUtilities::renderQuantumSize))45 : m_numberOfChannels(numberOfChannels) 47 46 { 48 47 } … … 50 49 void setProvider(AudioSourceProvider* multiChannelProvider) 51 50 { 51 m_currentChannel = 0; 52 m_framesToProcess = 0; 52 53 m_multiChannelProvider = multiChannelProvider; 53 54 } … … 55 56 // provideInput() will be called once for each channel, starting with the first channel. 56 57 // Each time it's called, it will provide the next channel of data. 57 void provideInput ForChannel(AudioBus* bus, size_t framesToProcess, unsigned channelIndex)58 void provideInput(AudioBus* bus, size_t framesToProcess) override 58 59 { 59 ASSERT(channelIndex < m_multiChannelBus->numberOfChannels());60 ASSERT(framesToProcess <= AudioUtilities::renderQuantumSize);61 if (framesToProcess > AudioUtilities::renderQuantumSize)62 return;63 64 60 bool isBusGood = bus && bus->numberOfChannels() == 1; 65 61 ASSERT(isBusGood); … … 69 65 // Get the data from the multi-channel provider when the first channel asks for it. 70 66 // For subsequent channels, we can just dish out the channel data from that (stored in m_multiChannelBus). 71 if (! channelIndex) {67 if (!m_currentChannel) { 72 68 m_framesToProcess = framesToProcess; 69 m_multiChannelBus = AudioBus::create(m_numberOfChannels, framesToProcess); 73 70 m_multiChannelProvider->provideInput(m_multiChannelBus.get(), framesToProcess); 74 71 } 75 72 76 73 // All channels must ask for the same amount. This should always be the case, but let's just make sure. 77 bool isGood = framesToProcess == m_framesToProcess;74 bool isGood = m_multiChannelBus.get() && framesToProcess == m_framesToProcess; 78 75 ASSERT(isGood); 79 76 if (!isGood) … … 81 78 82 79 // Copy the channel data from what we received from m_multiChannelProvider. 83 memcpy(bus->channel(0)->mutableData(), m_multiChannelBus->channel(channelIndex)->data(), sizeof(float) * framesToProcess); 80 ASSERT(m_currentChannel <= m_numberOfChannels); 81 if (m_currentChannel < m_numberOfChannels) { 82 memcpy(bus->channel(0)->mutableData(), m_multiChannelBus->channel(m_currentChannel)->data(), sizeof(float) * framesToProcess); 83 ++m_currentChannel; 84 } 84 85 } 85 86 … … 87 88 AudioSourceProvider* m_multiChannelProvider { nullptr }; 88 89 RefPtr<AudioBus> m_multiChannelBus; 90 unsigned m_numberOfChannels { 0 }; 91 unsigned m_currentChannel { 0 }; 89 92 size_t m_framesToProcess { 0 }; // Used to verify that all channels ask for the same amount. 90 93 }; … … 110 113 m_channelProvider->setProvider(provider); 111 114 112 // We need to ensure that SincResampler only calls provideInput() once for each channel or it will confuse the logic 113 // inside ChannelProvider. To ensure this, we chunk the number of requested frames into SincResampler::chunkSize() 114 // sized chunks. SincResampler guarantees it will only call provideInput() once once we resample this way. 115 m_outputFramesReady = 0; 116 while (m_outputFramesReady < framesToProcess) { 117 size_t chunkSize = m_kernels[0]->chunkSize(); 118 size_t framesThisTime = std::min(framesToProcess - m_outputFramesReady, chunkSize); 119 120 for (unsigned channelIndex = 0; channelIndex < m_numberOfChannels; ++channelIndex) { 121 ASSERT(chunkSize == m_kernels[channelIndex]->chunkSize()); 122 bool wasProvideInputCalled = false; 123 m_kernels[channelIndex]->process(destination->channel(channelIndex)->mutableData() + m_outputFramesReady, framesThisTime, [this, channelIndex, &wasProvideInputCalled](AudioBus* bus, size_t framesToProcess) { 124 ASSERT_WITH_MESSAGE(!wasProvideInputCalled, "provideInputForChannel should only be called once"); 125 wasProvideInputCalled = true; 126 m_channelProvider->provideInputForChannel(bus, framesToProcess, channelIndex); 127 }); 128 } 129 130 m_outputFramesReady += framesThisTime; 115 for (unsigned channelIndex = 0; channelIndex < m_numberOfChannels; ++channelIndex) { 116 // Depending on the sample-rate scale factor, and the internal buffering used in a SincResampler 117 // kernel, this call to process() will only sometimes call provideInput() on the channelProvider. 118 // However, if it calls provideInput() for the first channel, then it will call it for the remaining 119 // channels, since they all buffer in the same way and are processing the same number of frames. 120 m_kernels[channelIndex]->process(m_channelProvider.get(), 121 destination->channel(channelIndex)->mutableData(), 122 framesToProcess); 131 123 } 132 124 -
trunk/Source/WebCore/platform/audio/MultiChannelResampler.h
r270141 r270155 60 60 class ChannelProvider; 61 61 std::unique_ptr<ChannelProvider> m_channelProvider; 62 size_t m_outputFramesReady { 0 };63 62 }; 64 63 -
trunk/Source/WebCore/platform/audio/SincResampler.cpp
r270141 r270155 116 116 constexpr unsigned numberOfKernelOffsets { 32 }; 117 117 118 static size_t calculateChunkSize(unsigned blockSize, double scaleFactor)119 {120 return blockSize / scaleFactor;121 }122 123 118 SincResampler::SincResampler(double scaleFactor, Optional<unsigned> requestFrames) 124 119 : m_scaleFactor(scaleFactor) … … 143 138 m_r4 = m_r0 + m_requestFrames - kernelSize / 2; 144 139 m_blockSize = m_r4 - m_r2; 145 m_chunkSize = calculateChunkSize(m_blockSize, m_scaleFactor);146 140 147 141 // m_r1 at the beginning of the buffer. … … 194 188 } 195 189 196 void SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames , const Function<void(AudioBus* bus, size_t framesToProcess)>& provideInput)190 void SincResampler::consumeSource(float* buffer, unsigned numberOfSourceFrames) 197 191 { 198 ASSERT( provideInput);199 if (! provideInput)192 ASSERT(m_sourceProvider); 193 if (!m_sourceProvider) 200 194 return; 201 195 … … 207 201 m_internalBus->setChannelMemory(0, buffer, numberOfSourceFrames); 208 202 209 provideInput(m_internalBus.get(), numberOfSourceFrames);203 m_sourceProvider->provideInput(m_internalBus.get(), numberOfSourceFrames); 210 204 } 211 205 212 206 namespace { 213 207 214 // BufferSourceProvider is an audio source provider wrapping an in-memory buffer.215 216 class BufferSourceProvider {208 // BufferSourceProvider is an AudioSourceProvider wrapping an in-memory buffer. 209 210 class BufferSourceProvider : public AudioSourceProvider { 217 211 public: 218 212 explicit BufferSourceProvider(const float* source, size_t numberOfSourceFrames) … … 223 217 224 218 // Consumes samples from the in-memory buffer. 225 void provideInput(AudioBus* bus, size_t framesToProcess) 219 void provideInput(AudioBus* bus, size_t framesToProcess) override 226 220 { 227 221 ASSERT(m_source && bus); … … 260 254 while (remaining) { 261 255 unsigned framesThisTime = std::min(remaining, m_requestFrames); 262 process(destination, framesThisTime, [&sourceProvider](AudioBus* bus, size_t framesToProcess) { 263 sourceProvider.provideInput(bus, framesToProcess); 264 }); 256 process(&sourceProvider, destination, framesThisTime); 265 257 266 258 destination += framesThisTime; … … 269 261 } 270 262 271 void SincResampler::process( float* destination, size_t framesToProcess, const Function<void(AudioBus* bus, size_t framesToProcess)>& provideInput)263 void SincResampler::process(AudioSourceProvider* sourceProvider, float* destination, size_t framesToProcess) 272 264 { 273 ASSERT( provideInput);274 if (! provideInput)265 ASSERT(sourceProvider); 266 if (!sourceProvider) 275 267 return; 268 269 m_sourceProvider = sourceProvider; 276 270 277 271 unsigned numberOfDestinationFrames = framesToProcess; … … 280 274 // Prime the input buffer at the start of the input stream. 281 275 if (!m_isBufferPrimed) { 282 consumeSource(m_r0, m_requestFrames , provideInput);276 consumeSource(m_r0, m_requestFrames); 283 277 m_isBufferPrimed = true; 284 278 } … … 528 522 // Step (5) 529 523 // Refresh the buffer with more input. 530 consumeSource(m_r0, m_requestFrames , provideInput);524 consumeSource(m_r0, m_requestFrames); 531 525 } 532 526 } -
trunk/Source/WebCore/platform/audio/SincResampler.h
r270141 r270155 46 46 SincResampler(double scaleFactor, Optional<unsigned> requestFrames = WTF::nullopt); 47 47 48 size_t chunkSize() const { return m_chunkSize; }49 50 48 // Processes numberOfSourceFrames from source to produce numberOfSourceFrames / scaleFactor frames in destination. 51 49 void process(const float* source, float* destination, unsigned numberOfSourceFrames); 52 50 53 // Process with provideInputcallback function for streaming applications.54 void process( float* destination, size_t framesToProcess, const Function<void(AudioBus* bus, size_t framesToProcess)>& provideInput);51 // Process with input source callback function for streaming applications. 52 void process(AudioSourceProvider*, float* destination, size_t framesToProcess); 55 53 56 54 protected: 57 55 void initializeKernel(); 58 void consumeSource(float* buffer, unsigned numberOfSourceFrames , const Function<void(AudioBus* bus, size_t framesToProcess)>& provideInput);56 void consumeSource(float* buffer, unsigned numberOfSourceFrames); 59 57 void updateRegions(bool isSecondLoad); 60 58 … … 75 73 unsigned m_blockSize { 0 }; 76 74 77 size_t m_chunkSize { 0 };78 79 75 // Source is copied into this buffer for each processing pass. 80 76 AudioFloatArray m_inputBuffer; … … 90 86 const float* m_source { nullptr }; 91 87 unsigned m_sourceFramesAvailable { 0 }; 88 89 // m_sourceProvider is used to provide the audio input stream to the resampler. 90 AudioSourceProvider* m_sourceProvider { nullptr }; 92 91 93 92 // The buffer is primed once at the very beginning of processing.
Note: See TracChangeset
for help on using the changeset viewer.