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 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 } | 57 } |
| 58 | 58 |
| 59 AudioDestination::AudioDestination(AudioIOCallback& callback, | 59 AudioDestination::AudioDestination(AudioIOCallback& callback, |
| 60 const String& inputDeviceId, | 60 const String& inputDeviceId, |
| 61 unsigned numberOfInputChannels, | 61 unsigned numberOfInputChannels, |
| 62 unsigned numberOfOutputChannels, | 62 unsigned numberOfOutputChannels, |
| 63 float sampleRate, | 63 float sampleRate, |
| 64 PassRefPtr<SecurityOrigin> securityOrigin) | 64 PassRefPtr<SecurityOrigin> securityOrigin) |
| 65 : m_callback(callback), | 65 : m_callback(callback), |
| 66 m_numberOfOutputChannels(numberOfOutputChannels), | 66 m_numberOfOutputChannels(numberOfOutputChannels), |
| 67 m_inputBus(AudioBus::create(numberOfInputChannels, | |
| 68 AudioUtilities::kRenderQuantumFrames)), | |
| 69 m_renderBus(AudioBus::create(numberOfOutputChannels, | 67 m_renderBus(AudioBus::create(numberOfOutputChannels, |
| 70 AudioUtilities::kRenderQuantumFrames, | 68 AudioUtilities::kRenderQuantumFrames, |
| 71 false)), | 69 false)), |
| 72 m_sampleRate(sampleRate), | 70 m_sampleRate(sampleRate), |
| 73 m_isPlaying(false), | 71 m_isPlaying(false), |
| 74 m_framesElapsed(0), | 72 m_framesElapsed(0), |
| 75 m_outputPosition() { | 73 m_outputPosition() { |
| 76 // Histogram for audioHardwareBufferSize | 74 // Histogram for audioHardwareBufferSize |
| 77 DEFINE_STATIC_LOCAL(SparseHistogram, hardwareBufferSizeHistogram, | 75 DEFINE_STATIC_LOCAL(SparseHistogram, hardwareBufferSizeHistogram, |
| 78 ("WebAudio.AudioDestination.HardwareBufferSize")); | 76 ("WebAudio.AudioDestination.HardwareBufferSize")); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 callbackBufferSizeHistogram.sample(m_callbackBufferSize); | 121 callbackBufferSizeHistogram.sample(m_callbackBufferSize); |
| 124 | 122 |
| 125 // Create a FIFO to handle the possibility of the callback size | 123 // Create a FIFO to handle the possibility of the callback size |
| 126 // not being a multiple of the render size. If the FIFO already | 124 // not being a multiple of the render size. If the FIFO already |
| 127 // contains enough data, the data will be provided directly. | 125 // contains enough data, the data will be provided directly. |
| 128 // Otherwise, the FIFO will call the provider enough times to | 126 // Otherwise, the FIFO will call the provider enough times to |
| 129 // satisfy the request for data. | 127 // satisfy the request for data. |
| 130 m_fifo = | 128 m_fifo = |
| 131 WTF::wrapUnique(new AudioPullFIFO(*this, numberOfOutputChannels, fifoSize, | 129 WTF::wrapUnique(new AudioPullFIFO(*this, numberOfOutputChannels, fifoSize, |
| 132 AudioUtilities::kRenderQuantumFrames)); | 130 AudioUtilities::kRenderQuantumFrames)); |
| 133 | |
| 134 // Input buffering. | |
| 135 m_inputFifo = WTF::makeUnique<AudioFIFO>(numberOfInputChannels, fifoSize); | |
| 136 | |
| 137 // If the callback size does not match the render size, then we need to | |
| 138 // buffer some extra silence for the input. Otherwise, we can over-consume | |
| 139 // the input FIFO. | |
| 140 if (m_callbackBufferSize != AudioUtilities::kRenderQuantumFrames) { | |
| 141 // FIXME: handle multi-channel input and don't hard-code to stereo. | |
| 142 RefPtr<AudioBus> silence = | |
| 143 AudioBus::create(2, AudioUtilities::kRenderQuantumFrames); | |
| 144 m_inputFifo->push(silence.get()); | |
| 145 } | |
| 146 } | 131 } |
| 147 | 132 |
| 148 AudioDestination::~AudioDestination() { | 133 AudioDestination::~AudioDestination() { |
| 149 stop(); | 134 stop(); |
| 150 } | 135 } |
| 151 | 136 |
| 152 void AudioDestination::start() { | 137 void AudioDestination::start() { |
| 153 if (!m_isPlaying && m_audioDevice) { | 138 if (!m_isPlaying && m_audioDevice) { |
| 154 m_audioDevice->start(); | 139 m_audioDevice->start(); |
| 155 m_isPlaying = true; | 140 m_isPlaying = true; |
| 156 } | 141 } |
| 157 } | 142 } |
| 158 | 143 |
| 159 void AudioDestination::stop() { | 144 void AudioDestination::stop() { |
| 160 if (m_isPlaying && m_audioDevice) { | 145 if (m_isPlaying && m_audioDevice) { |
| 161 m_audioDevice->stop(); | 146 m_audioDevice->stop(); |
| 162 m_isPlaying = false; | 147 m_isPlaying = false; |
| 163 } | 148 } |
| 164 } | 149 } |
| 165 | 150 |
| 166 float AudioDestination::hardwareSampleRate() { | 151 float AudioDestination::hardwareSampleRate() { |
| 167 return static_cast<float>(Platform::current()->audioHardwareSampleRate()); | 152 return static_cast<float>(Platform::current()->audioHardwareSampleRate()); |
| 168 } | 153 } |
| 169 | 154 |
| 170 unsigned long AudioDestination::maxChannelCount() { | 155 unsigned long AudioDestination::maxChannelCount() { |
| 171 return static_cast<float>(Platform::current()->audioHardwareOutputChannels()); | 156 return static_cast<float>(Platform::current()->audioHardwareOutputChannels()); |
| 172 } | 157 } |
| 173 | 158 |
| 174 void AudioDestination::render(const WebVector<float*>& sourceData, | 159 void AudioDestination::render(const WebVector<float*>& audioData, |
| 175 const WebVector<float*>& audioData, | |
| 176 size_t numberOfFrames, | 160 size_t numberOfFrames, |
| 177 double delay, | 161 double delay, |
| 178 double delayTimestamp, | 162 double delayTimestamp, |
| 179 size_t priorFramesSkipped) { | 163 size_t priorFramesSkipped) { |
| 180 bool isNumberOfChannelsGood = audioData.size() == m_numberOfOutputChannels; | 164 bool isNumberOfChannelsGood = audioData.size() == m_numberOfOutputChannels; |
| 181 if (!isNumberOfChannelsGood) { | 165 if (!isNumberOfChannelsGood) { |
| 182 ASSERT_NOT_REACHED(); | 166 ASSERT_NOT_REACHED(); |
| 183 return; | 167 return; |
| 184 } | 168 } |
| 185 | 169 |
| 186 bool isBufferSizeGood = numberOfFrames == m_callbackBufferSize; | 170 bool isBufferSizeGood = numberOfFrames == m_callbackBufferSize; |
| 187 if (!isBufferSizeGood) { | 171 if (!isBufferSizeGood) { |
| 188 ASSERT_NOT_REACHED(); | 172 ASSERT_NOT_REACHED(); |
| 189 return; | 173 return; |
| 190 } | 174 } |
| 191 | 175 |
| 192 m_framesElapsed -= std::min(m_framesElapsed, priorFramesSkipped); | 176 m_framesElapsed -= std::min(m_framesElapsed, priorFramesSkipped); |
| 193 double outputPosition = | 177 double outputPosition = |
| 194 m_framesElapsed / static_cast<double>(m_sampleRate) - delay; | 178 m_framesElapsed / static_cast<double>(m_sampleRate) - delay; |
| 195 m_outputPosition.position = outputPosition; | 179 m_outputPosition.position = outputPosition; |
| 196 m_outputPosition.timestamp = delayTimestamp; | 180 m_outputPosition.timestamp = delayTimestamp; |
| 197 m_outputPositionReceivedTimestamp = base::TimeTicks::Now(); | 181 m_outputPositionReceivedTimestamp = base::TimeTicks::Now(); |
| 198 | 182 |
| 199 // Buffer optional live input. | |
| 200 if (sourceData.size() >= 2) { | |
| 201 // FIXME: handle multi-channel input and don't hard-code to stereo. | |
| 202 RefPtr<AudioBus> wrapperBus = AudioBus::create(2, numberOfFrames, false); | |
| 203 wrapperBus->setChannelMemory(0, sourceData[0], numberOfFrames); | |
| 204 wrapperBus->setChannelMemory(1, sourceData[1], numberOfFrames); | |
| 205 m_inputFifo->push(wrapperBus.get()); | |
| 206 } | |
| 207 | |
| 208 for (unsigned i = 0; i < m_numberOfOutputChannels; ++i) | 183 for (unsigned i = 0; i < m_numberOfOutputChannels; ++i) |
| 209 m_renderBus->setChannelMemory(i, audioData[i], numberOfFrames); | 184 m_renderBus->setChannelMemory(i, audioData[i], numberOfFrames); |
| 210 | 185 |
| 211 m_fifo->consume(m_renderBus.get(), numberOfFrames); | 186 m_fifo->consume(m_renderBus.get(), numberOfFrames); |
| 212 | 187 |
| 213 m_framesElapsed += numberOfFrames; | 188 m_framesElapsed += numberOfFrames; |
| 214 } | 189 } |
| 215 | 190 |
| 216 void AudioDestination::provideInput(AudioBus* bus, size_t framesToProcess) { | 191 void AudioDestination::provideInput(AudioBus* bus, size_t framesToProcess) { |
| 217 AudioBus* sourceBus = nullptr; | |
| 218 if (m_inputFifo->framesInFifo() >= framesToProcess) { | |
| 219 m_inputFifo->consume(m_inputBus.get(), framesToProcess); | |
| 220 sourceBus = m_inputBus.get(); | |
| 221 } | |
| 222 | |
| 223 AudioIOPosition outputPosition = m_outputPosition; | 192 AudioIOPosition outputPosition = m_outputPosition; |
| 224 | 193 |
| 225 // If platfrom buffer is more than two times longer than |framesToProcess| | 194 // If platfrom buffer is more than two times longer than |framesToProcess| |
| 226 // we do not want output position to get stuck so we promote it | 195 // we do not want output position to get stuck so we promote it |
| 227 // using the elapsed time from the moment it was initially obtained. | 196 // using the elapsed time from the moment it was initially obtained. |
| 228 if (m_callbackBufferSize > framesToProcess * 2) { | 197 if (m_callbackBufferSize > framesToProcess * 2) { |
| 229 double delta = (base::TimeTicks::Now() - m_outputPositionReceivedTimestamp) | 198 double delta = (base::TimeTicks::Now() - m_outputPositionReceivedTimestamp) |
| 230 .InSecondsF(); | 199 .InSecondsF(); |
| 231 outputPosition.position += delta; | 200 outputPosition.position += delta; |
| 232 outputPosition.timestamp += delta; | 201 outputPosition.timestamp += delta; |
| 233 } | 202 } |
| 234 | 203 |
| 235 // Some implementations give only rough estimation of |delay| so | 204 // Some implementations give only rough estimation of |delay| so |
| 236 // we might have negative estimation |outputPosition| value. | 205 // we might have negative estimation |outputPosition| value. |
| 237 if (outputPosition.position < 0.0) | 206 if (outputPosition.position < 0.0) |
| 238 outputPosition.position = 0.0; | 207 outputPosition.position = 0.0; |
| 239 | 208 |
| 240 m_callback.render(sourceBus, bus, framesToProcess, outputPosition); | 209 m_callback.render(nullptr, bus, framesToProcess, outputPosition); |
|
Raymond Toy
2016/12/20 21:46:49
Can this be updated to remove the first arg?
| |
| 241 } | 210 } |
| 242 | 211 |
| 243 } // namespace blink | 212 } // namespace blink |
| OLD | NEW |