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 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 AudioNode::uninitialize(); | 132 AudioNode::uninitialize(); |
133 } | 133 } |
134 | 134 |
135 void ScriptProcessorNode::process(size_t framesToProcess) | 135 void ScriptProcessorNode::process(size_t framesToProcess) |
136 { | 136 { |
137 // Discussion about inputs and outputs: | 137 // Discussion about inputs and outputs: |
138 // As in other AudioNodes, ScriptProcessorNode uses an AudioBus for its inpu
t and output (see inputBus and outputBus below). | 138 // As in other AudioNodes, ScriptProcessorNode uses an AudioBus for its inpu
t and output (see inputBus and outputBus below). |
139 // Additionally, there is a double-buffering for input and output which is e
xposed directly to JavaScript (see inputBuffer and outputBuffer below). | 139 // Additionally, there is a double-buffering for input and output which is e
xposed directly to JavaScript (see inputBuffer and outputBuffer below). |
140 // This node is the producer for inputBuffer and the consumer for outputBuff
er. | 140 // This node is the producer for inputBuffer and the consumer for outputBuff
er. |
141 // The JavaScript code is the consumer of inputBuffer and the producer for o
utputBuffer. | 141 // The JavaScript code is the consumer of inputBuffer and the producer for o
utputBuffer. |
142 | 142 |
143 // Get input and output busses. | 143 // Get input and output busses. |
144 AudioBus* inputBus = this->input(0)->bus(); | 144 AudioBus* inputBus = this->input(0)->bus(); |
145 AudioBus* outputBus = this->output(0)->bus(); | 145 AudioBus* outputBus = this->output(0)->bus(); |
146 | 146 |
147 // Get input and output buffers. We double-buffer both the input and output
sides. | 147 // Get input and output buffers. We double-buffer both the input and output
sides. |
148 unsigned doubleBufferIndex = this->doubleBufferIndex(); | 148 unsigned doubleBufferIndex = this->doubleBufferIndex(); |
149 bool isDoubleBufferIndexGood = doubleBufferIndex < 2 && doubleBufferIndex <
m_inputBuffers.size() && doubleBufferIndex < m_outputBuffers.size(); | 149 bool isDoubleBufferIndexGood = doubleBufferIndex < 2 && doubleBufferIndex <
m_inputBuffers.size() && doubleBufferIndex < m_outputBuffers.size(); |
150 ASSERT(isDoubleBufferIndexGood); | 150 ASSERT(isDoubleBufferIndexGood); |
151 if (!isDoubleBufferIndexGood) | 151 if (!isDoubleBufferIndexGood) |
152 return; | 152 return; |
153 | 153 |
154 AudioBuffer* inputBuffer = m_inputBuffers[doubleBufferIndex].get(); | 154 AudioBuffer* inputBuffer = m_inputBuffers[doubleBufferIndex].get(); |
155 AudioBuffer* outputBuffer = m_outputBuffers[doubleBufferIndex].get(); | 155 AudioBuffer* outputBuffer = m_outputBuffers[doubleBufferIndex].get(); |
156 | 156 |
157 // Check the consistency of input and output buffers. | 157 // Check the consistency of input and output buffers. |
158 unsigned numberOfInputChannels = m_internalInputBus->numberOfChannels(); | 158 unsigned numberOfInputChannels = m_internalInputBus->numberOfChannels(); |
159 bool buffersAreGood = outputBuffer && bufferSize() == outputBuffer->length()
&& m_bufferReadWriteIndex + framesToProcess <= bufferSize(); | 159 bool buffersAreGood = outputBuffer && bufferSize() == outputBuffer->length()
&& m_bufferReadWriteIndex + framesToProcess <= bufferSize(); |
160 | 160 |
161 // If the number of input channels is zero, it's ok to have inputBuffer = 0. | 161 // If the number of input channels is zero, it's ok to have inputBuffer = 0. |
162 if (m_internalInputBus->numberOfChannels()) | 162 if (m_internalInputBus->numberOfChannels()) |
163 buffersAreGood = buffersAreGood && inputBuffer && bufferSize() == inputB
uffer->length(); | 163 buffersAreGood = buffersAreGood && inputBuffer && bufferSize() == inputB
uffer->length(); |
(...skipping 14 matching lines...) Expand all Loading... |
178 ASSERT(channelsAreGood); | 178 ASSERT(channelsAreGood); |
179 if (!channelsAreGood) | 179 if (!channelsAreGood) |
180 return; | 180 return; |
181 | 181 |
182 for (unsigned i = 0; i < numberOfInputChannels; i++) | 182 for (unsigned i = 0; i < numberOfInputChannels; i++) |
183 m_internalInputBus->setChannelMemory(i, inputBuffer->getChannelData(i)->
data() + m_bufferReadWriteIndex, framesToProcess); | 183 m_internalInputBus->setChannelMemory(i, inputBuffer->getChannelData(i)->
data() + m_bufferReadWriteIndex, framesToProcess); |
184 | 184 |
185 if (numberOfInputChannels) | 185 if (numberOfInputChannels) |
186 m_internalInputBus->copyFrom(*inputBus); | 186 m_internalInputBus->copyFrom(*inputBus); |
187 | 187 |
188 // Copy from the output buffer to the output. | 188 // Copy from the output buffer to the output. |
189 for (unsigned i = 0; i < numberOfOutputChannels; ++i) | 189 for (unsigned i = 0; i < numberOfOutputChannels; ++i) |
190 memcpy(outputBus->channel(i)->mutableData(), outputBuffer->getChannelDat
a(i)->data() + m_bufferReadWriteIndex, sizeof(float) * framesToProcess); | 190 memcpy(outputBus->channel(i)->mutableData(), outputBuffer->getChannelDat
a(i)->data() + m_bufferReadWriteIndex, sizeof(float) * framesToProcess); |
191 | 191 |
192 // Update the buffering index. | 192 // Update the buffering index. |
193 m_bufferReadWriteIndex = (m_bufferReadWriteIndex + framesToProcess) % buffer
Size(); | 193 m_bufferReadWriteIndex = (m_bufferReadWriteIndex + framesToProcess) % buffer
Size(); |
194 | 194 |
195 // m_bufferReadWriteIndex will wrap back around to 0 when the current input
and output buffers are full. | 195 // m_bufferReadWriteIndex will wrap back around to 0 when the current input
and output buffers are full. |
196 // When this happens, fire an event and swap buffers. | 196 // When this happens, fire an event and swap buffers. |
197 if (!m_bufferReadWriteIndex) { | 197 if (!m_bufferReadWriteIndex) { |
198 // Avoid building up requests on the main thread to fire process events
when they're not being handled. | 198 // Avoid building up requests on the main thread to fire process events
when they're not being handled. |
199 // This could be a problem if the main thread is very busy doing other t
hings and is being held up handling previous requests. | 199 // This could be a problem if the main thread is very busy doing other t
hings and is being held up handling previous requests. |
200 if (m_isRequestOutstanding) { | 200 if (m_isRequestOutstanding) { |
201 // We're late in handling the previous request. The main thread must
be very busy. | 201 // We're late in handling the previous request. The main thread must
be very busy. |
202 // The best we can do is clear out the buffer ourself here. | 202 // The best we can do is clear out the buffer ourself here. |
203 outputBuffer->zero(); | 203 outputBuffer->zero(); |
204 } else { | 204 } else { |
205 // Reference ourself so we don't accidentally get deleted before fir
eProcessEvent() gets called. | 205 // Reference ourself so we don't accidentally get deleted before fir
eProcessEvent() gets called. |
206 ref(); | 206 ref(); |
207 | 207 |
208 // Fire the event on the main thread, not this one (which is the rea
ltime audio thread). | 208 // Fire the event on the main thread, not this one (which is the rea
ltime audio thread). |
209 m_doubleBufferIndexForEvent = m_doubleBufferIndex; | 209 m_doubleBufferIndexForEvent = m_doubleBufferIndex; |
210 m_isRequestOutstanding = true; | 210 m_isRequestOutstanding = true; |
211 callOnMainThread(fireProcessEventDispatch, this); | 211 callOnMainThread(fireProcessEventDispatch, this); |
212 } | 212 } |
213 | 213 |
214 swapBuffers(); | 214 swapBuffers(); |
215 } | 215 } |
216 } | 216 } |
217 | 217 |
218 void ScriptProcessorNode::fireProcessEventDispatch(void* userData) | 218 void ScriptProcessorNode::fireProcessEventDispatch(void* userData) |
219 { | 219 { |
220 ScriptProcessorNode* jsAudioNode = static_cast<ScriptProcessorNode*>(userDat
a); | 220 ScriptProcessorNode* jsAudioNode = static_cast<ScriptProcessorNode*>(userDat
a); |
221 ASSERT(jsAudioNode); | 221 ASSERT(jsAudioNode); |
222 if (!jsAudioNode) | 222 if (!jsAudioNode) |
223 return; | 223 return; |
224 | 224 |
225 jsAudioNode->fireProcessEvent(); | 225 jsAudioNode->fireProcessEvent(); |
226 | 226 |
227 // De-reference to match the ref() call in process(). | 227 // De-reference to match the ref() call in process(). |
228 jsAudioNode->deref(); | 228 jsAudioNode->deref(); |
229 } | 229 } |
230 | 230 |
231 void ScriptProcessorNode::fireProcessEvent() | 231 void ScriptProcessorNode::fireProcessEvent() |
232 { | 232 { |
233 ASSERT(isMainThread() && m_isRequestOutstanding); | 233 ASSERT(isMainThread() && m_isRequestOutstanding); |
234 | 234 |
235 bool isIndexGood = m_doubleBufferIndexForEvent < 2; | 235 bool isIndexGood = m_doubleBufferIndexForEvent < 2; |
236 ASSERT(isIndexGood); | 236 ASSERT(isIndexGood); |
237 if (!isIndexGood) | 237 if (!isIndexGood) |
238 return; | 238 return; |
239 | 239 |
240 AudioBuffer* inputBuffer = m_inputBuffers[m_doubleBufferIndexForEvent].get()
; | 240 AudioBuffer* inputBuffer = m_inputBuffers[m_doubleBufferIndexForEvent].get()
; |
241 AudioBuffer* outputBuffer = m_outputBuffers[m_doubleBufferIndexForEvent].get
(); | 241 AudioBuffer* outputBuffer = m_outputBuffers[m_doubleBufferIndexForEvent].get
(); |
242 ASSERT(outputBuffer); | 242 ASSERT(outputBuffer); |
243 if (!outputBuffer) | 243 if (!outputBuffer) |
244 return; | 244 return; |
245 | 245 |
246 // Avoid firing the event if the document has already gone away. | 246 // Avoid firing the event if the document has already gone away. |
247 if (context()->scriptExecutionContext()) { | 247 if (context()->scriptExecutionContext()) { |
248 // Let the audio thread know we've gotten to the point where it's OK for
it to make another request. | 248 // Let the audio thread know we've gotten to the point where it's OK for
it to make another request. |
249 m_isRequestOutstanding = false; | 249 m_isRequestOutstanding = false; |
250 | 250 |
251 // Call the JavaScript event handler which will do the audio processing. | 251 // Call the JavaScript event handler which will do the audio processing. |
252 dispatchEvent(AudioProcessingEvent::create(inputBuffer, outputBuffer)); | 252 dispatchEvent(AudioProcessingEvent::create(inputBuffer, outputBuffer)); |
253 } | 253 } |
254 } | 254 } |
255 | 255 |
256 void ScriptProcessorNode::reset() | 256 void ScriptProcessorNode::reset() |
257 { | 257 { |
258 m_bufferReadWriteIndex = 0; | 258 m_bufferReadWriteIndex = 0; |
259 m_doubleBufferIndex = 0; | 259 m_doubleBufferIndex = 0; |
260 | 260 |
261 for (unsigned i = 0; i < 2; ++i) { | 261 for (unsigned i = 0; i < 2; ++i) { |
262 m_inputBuffers[i]->zero(); | 262 m_inputBuffers[i]->zero(); |
263 m_outputBuffers[i]->zero(); | 263 m_outputBuffers[i]->zero(); |
264 } | 264 } |
265 } | 265 } |
266 | 266 |
267 double ScriptProcessorNode::tailTime() const | 267 double ScriptProcessorNode::tailTime() const |
268 { | 268 { |
269 return std::numeric_limits<double>::infinity(); | 269 return std::numeric_limits<double>::infinity(); |
270 } | 270 } |
271 | 271 |
272 double ScriptProcessorNode::latencyTime() const | 272 double ScriptProcessorNode::latencyTime() const |
273 { | 273 { |
274 return std::numeric_limits<double>::infinity(); | 274 return std::numeric_limits<double>::infinity(); |
275 } | 275 } |
276 | 276 |
277 } // namespace WebCore | 277 } // namespace WebCore |
278 | 278 |
279 #endif // ENABLE(WEB_AUDIO) | 279 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |