Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| 11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
| 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| 14 * its contributors may be used to endorse or promote products derived | 14 * its contributors may be used to endorse or promote products derived |
| 15 * from this software without specific prior written permission. | 15 * from this software without specific prior written permission. |
| 16 * | 16 * |
| 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 */ | 27 */ |
| 28 | 28 |
| 29 #include "platform/audio/AudioDestination.h" | 29 #include "platform/audio/AudioDestination.h" |
| 30 | |
| 31 #include "platform/Histogram.h" | |
| 30 #include "platform/audio/AudioFIFO.h" | 32 #include "platform/audio/AudioFIFO.h" |
| 31 #include "platform/audio/AudioPullFIFO.h" | 33 #include "platform/audio/AudioPullFIFO.h" |
| 32 #include "public/platform/Platform.h" | 34 #include "public/platform/Platform.h" |
| 33 #include "public/platform/WebSecurityOrigin.h" | 35 #include "public/platform/WebSecurityOrigin.h" |
| 34 | 36 |
| 35 namespace blink { | 37 namespace blink { |
| 36 | 38 |
| 37 // Buffer size at which the web audio engine will render. | 39 // Buffer size at which the web audio engine will render. |
| 38 const unsigned renderBufferSize = 128; | 40 const unsigned renderBufferSize = 128; |
| 39 | 41 |
| 40 // Size of the FIFO | 42 // Size of the FIFO |
| 41 const size_t fifoSize = 8192; | 43 const size_t fifoSize = 8192; |
| 42 | 44 |
| 43 // Factory method: Chromium-implementation | 45 // Factory method: Chromium-implementation |
| 44 PassOwnPtr<AudioDestination> AudioDestination::create(AudioIOCallback& callback, const String& inputDeviceId, unsigned numberOfInputChannels, unsigned numberOfO utputChannels, float sampleRate, const PassRefPtr<SecurityOrigin>& securityOrigi n) | 46 PassOwnPtr<AudioDestination> AudioDestination::create(AudioIOCallback& callback, const String& inputDeviceId, unsigned numberOfInputChannels, unsigned numberOfO utputChannels, float sampleRate, const PassRefPtr<SecurityOrigin>& securityOrigi n) |
| 45 { | 47 { |
| 46 return adoptPtr(new AudioDestination(callback, inputDeviceId, numberOfInputC hannels, numberOfOutputChannels, sampleRate, securityOrigin)); | 48 return adoptPtr(new AudioDestination(callback, inputDeviceId, numberOfInputC hannels, numberOfOutputChannels, sampleRate, securityOrigin)); |
| 47 } | 49 } |
| 48 | 50 |
| 49 AudioDestination::AudioDestination(AudioIOCallback& callback, const String& inpu tDeviceId, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, floa t sampleRate, const PassRefPtr<SecurityOrigin>& securityOrigin) | 51 AudioDestination::AudioDestination(AudioIOCallback& callback, const String& inpu tDeviceId, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, floa t sampleRate, const PassRefPtr<SecurityOrigin>& securityOrigin) |
| 50 : m_callback(callback) | 52 : m_callback(callback) |
| 51 , m_numberOfOutputChannels(numberOfOutputChannels) | 53 , m_numberOfOutputChannels(numberOfOutputChannels) |
| 52 , m_inputBus(AudioBus::create(numberOfInputChannels, renderBufferSize)) | 54 , m_inputBus(AudioBus::create(numberOfInputChannels, renderBufferSize)) |
| 53 , m_renderBus(AudioBus::create(numberOfOutputChannels, renderBufferSize, fal se)) | 55 , m_renderBus(AudioBus::create(numberOfOutputChannels, renderBufferSize, fal se)) |
| 54 , m_sampleRate(sampleRate) | 56 , m_sampleRate(sampleRate) |
| 55 , m_isPlaying(false) | 57 , m_isPlaying(false) |
| 56 { | 58 { |
| 59 // Histogram for audioHardwareBufferSize | |
| 60 DEFINE_STATIC_LOCAL(SparseHistogram, hardwareBufferSizeHistogram, | |
| 61 ("WebAudio.AudioDestination.HardwareBuffersize")); | |
| 62 // Histogram for the actual callback size used. Typically, this is the same as | |
| 63 // audioHardwareBufferSize, but can be adjusted depending on some heuristics below. | |
| 64 DEFINE_STATIC_LOCAL(SparseHistogram, callbackBufferSizeHistogram, | |
|
Mark P
2016/05/03 21:35:23
Sparse histograms are slow. see here for details:
Raymond Toy
2016/05/03 21:43:20
This is updated only when the AudioContext is crea
| |
| 65 ("WebAudio.AudioDestination.CallbackBufferSize")); | |
| 66 | |
| 57 // Use the optimal buffer size recommended by the audio backend. | 67 // Use the optimal buffer size recommended by the audio backend. |
| 58 m_callbackBufferSize = Platform::current()->audioHardwareBufferSize(); | 68 size_t recommendedHardwareBufferSize = Platform::current()->audioHardwareBuf ferSize(); |
| 69 m_callbackBufferSize = recommendedHardwareBufferSize; | |
| 59 | 70 |
| 60 #if OS(ANDROID) | 71 #if OS(ANDROID) |
| 61 // The optimum low-latency hardware buffer size is usually too small on Andr oid for WebAudio to | 72 // The optimum low-latency hardware buffer size is usually too small on Andr oid for WebAudio to |
| 62 // render without glitching. So, if it is small, use a larger size. If it wa s already large, use | 73 // render without glitching. So, if it is small, use a larger size. If it wa s already large, use |
| 63 // the requested size. | 74 // the requested size. |
| 64 // | 75 // |
| 65 // Since WebAudio renders in 128-frame blocks, the small buffer sizes (144 f or a Galaxy Nexus), | 76 // Since WebAudio renders in 128-frame blocks, the small buffer sizes (144 f or a Galaxy Nexus), |
| 66 // cause significant processing jitter. Sometimes multiple blocks will proce ssed, but other | 77 // cause significant processing jitter. Sometimes multiple blocks will proce ssed, but other |
| 67 // times will not be since the FIFO can satisfy the request. By using a larg er | 78 // times will not be since the FIFO can satisfy the request. By using a larg er |
| 68 // callbackBufferSize, we smooth out the jitter. | 79 // callbackBufferSize, we smooth out the jitter. |
| 69 const size_t kSmallBufferSize = 1024; | 80 const size_t kSmallBufferSize = 1024; |
| 70 const size_t kDefaultCallbackBufferSize = 2048; | 81 const size_t kDefaultCallbackBufferSize = 2048; |
| 71 | 82 |
| 72 if (m_callbackBufferSize <= kSmallBufferSize) | 83 if (m_callbackBufferSize <= kSmallBufferSize) |
| 73 m_callbackBufferSize = kDefaultCallbackBufferSize; | 84 m_callbackBufferSize = kDefaultCallbackBufferSize; |
| 74 #endif | 85 #endif |
| 75 | 86 |
| 76 // Quick exit if the requested size is too large. | 87 // Quick exit if the requested size is too large. |
| 77 ASSERT(m_callbackBufferSize + renderBufferSize <= fifoSize); | 88 ASSERT(m_callbackBufferSize + renderBufferSize <= fifoSize); |
| 78 if (m_callbackBufferSize + renderBufferSize > fifoSize) | 89 if (m_callbackBufferSize + renderBufferSize > fifoSize) |
| 79 return; | 90 return; |
| 80 | 91 |
| 81 m_audioDevice = adoptPtr(Platform::current()->createAudioDevice(m_callbackBu fferSize, numberOfInputChannels, numberOfOutputChannels, sampleRate, this, input DeviceId, securityOrigin)); | 92 m_audioDevice = adoptPtr(Platform::current()->createAudioDevice(m_callbackBu fferSize, numberOfInputChannels, numberOfOutputChannels, sampleRate, this, input DeviceId, securityOrigin)); |
| 82 ASSERT(m_audioDevice); | 93 ASSERT(m_audioDevice); |
| 83 | 94 |
| 95 // Record the sizes if we successfully created an output device. | |
| 96 hardwareBufferSizeHistogram.sample(recommendedHardwareBufferSize); | |
| 97 callbackBufferSizeHistogram.sample(m_callbackBufferSize); | |
| 98 | |
| 84 // Create a FIFO to handle the possibility of the callback size | 99 // Create a FIFO to handle the possibility of the callback size |
| 85 // not being a multiple of the render size. If the FIFO already | 100 // not being a multiple of the render size. If the FIFO already |
| 86 // contains enough data, the data will be provided directly. | 101 // contains enough data, the data will be provided directly. |
| 87 // Otherwise, the FIFO will call the provider enough times to | 102 // Otherwise, the FIFO will call the provider enough times to |
| 88 // satisfy the request for data. | 103 // satisfy the request for data. |
| 89 m_fifo = adoptPtr(new AudioPullFIFO(*this, numberOfOutputChannels, fifoSize, renderBufferSize)); | 104 m_fifo = adoptPtr(new AudioPullFIFO(*this, numberOfOutputChannels, fifoSize, renderBufferSize)); |
| 90 | 105 |
| 91 // Input buffering. | 106 // Input buffering. |
| 92 m_inputFifo = adoptPtr(new AudioFIFO(numberOfInputChannels, fifoSize)); | 107 m_inputFifo = adoptPtr(new AudioFIFO(numberOfInputChannels, fifoSize)); |
| 93 | 108 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 if (m_inputFifo->framesInFifo() >= framesToProcess) { | 181 if (m_inputFifo->framesInFifo() >= framesToProcess) { |
| 167 m_inputFifo->consume(m_inputBus.get(), framesToProcess); | 182 m_inputFifo->consume(m_inputBus.get(), framesToProcess); |
| 168 sourceBus = m_inputBus.get(); | 183 sourceBus = m_inputBus.get(); |
| 169 } | 184 } |
| 170 | 185 |
| 171 m_callback.render(sourceBus, bus, framesToProcess); | 186 m_callback.render(sourceBus, bus, framesToProcess); |
| 172 } | 187 } |
| 173 | 188 |
| 174 } // namespace blink | 189 } // namespace blink |
| 175 | 190 |
| OLD | NEW |