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 |