ScriptProcessorNode.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * Copyright (C) 2010, Google Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "config.h"
  25. #if ENABLE(WEB_AUDIO)
  26. #include "ScriptProcessorNode.h"
  27. #include "AudioBuffer.h"
  28. #include "AudioBus.h"
  29. #include "AudioContext.h"
  30. #include "AudioNodeInput.h"
  31. #include "AudioNodeOutput.h"
  32. #include "AudioProcessingEvent.h"
  33. #include "Document.h"
  34. #include <wtf/Float32Array.h>
  35. #include <wtf/MainThread.h>
  36. namespace WebCore {
  37. const size_t DefaultBufferSize = 4096;
  38. PassRefPtr<ScriptProcessorNode> ScriptProcessorNode::create(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels)
  39. {
  40. // Check for valid buffer size.
  41. switch (bufferSize) {
  42. case 256:
  43. case 512:
  44. case 1024:
  45. case 2048:
  46. case 4096:
  47. case 8192:
  48. case 16384:
  49. break;
  50. default:
  51. return 0;
  52. }
  53. if (!numberOfInputChannels && !numberOfOutputChannels)
  54. return 0;
  55. if (numberOfInputChannels > AudioContext::maxNumberOfChannels())
  56. return 0;
  57. if (numberOfOutputChannels > AudioContext::maxNumberOfChannels())
  58. return 0;
  59. return adoptRef(new ScriptProcessorNode(context, sampleRate, bufferSize, numberOfInputChannels, numberOfOutputChannels));
  60. }
  61. ScriptProcessorNode::ScriptProcessorNode(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels)
  62. : AudioNode(context, sampleRate)
  63. , m_doubleBufferIndex(0)
  64. , m_doubleBufferIndexForEvent(0)
  65. , m_bufferSize(bufferSize)
  66. , m_bufferReadWriteIndex(0)
  67. , m_isRequestOutstanding(false)
  68. , m_numberOfInputChannels(numberOfInputChannels)
  69. , m_numberOfOutputChannels(numberOfOutputChannels)
  70. , m_internalInputBus(AudioBus::create(numberOfInputChannels, AudioNode::ProcessingSizeInFrames, false))
  71. , m_hasAudioProcessListener(false)
  72. {
  73. // Regardless of the allowed buffer sizes, we still need to process at the granularity of the AudioNode.
  74. if (m_bufferSize < AudioNode::ProcessingSizeInFrames)
  75. m_bufferSize = AudioNode::ProcessingSizeInFrames;
  76. ASSERT(numberOfInputChannels <= AudioContext::maxNumberOfChannels());
  77. addInput(adoptPtr(new AudioNodeInput(this)));
  78. addOutput(adoptPtr(new AudioNodeOutput(this, numberOfOutputChannels)));
  79. setNodeType(NodeTypeJavaScript);
  80. initialize();
  81. }
  82. ScriptProcessorNode::~ScriptProcessorNode()
  83. {
  84. uninitialize();
  85. }
  86. void ScriptProcessorNode::initialize()
  87. {
  88. if (isInitialized())
  89. return;
  90. float sampleRate = context()->sampleRate();
  91. // Create double buffers on both the input and output sides.
  92. // These AudioBuffers will be directly accessed in the main thread by JavaScript.
  93. for (unsigned i = 0; i < 2; ++i) {
  94. RefPtr<AudioBuffer> inputBuffer = m_numberOfInputChannels ? AudioBuffer::create(m_numberOfInputChannels, bufferSize(), sampleRate) : 0;
  95. RefPtr<AudioBuffer> outputBuffer = m_numberOfOutputChannels ? AudioBuffer::create(m_numberOfOutputChannels, bufferSize(), sampleRate) : 0;
  96. m_inputBuffers.append(inputBuffer);
  97. m_outputBuffers.append(outputBuffer);
  98. }
  99. AudioNode::initialize();
  100. }
  101. void ScriptProcessorNode::uninitialize()
  102. {
  103. if (!isInitialized())
  104. return;
  105. m_inputBuffers.clear();
  106. m_outputBuffers.clear();
  107. AudioNode::uninitialize();
  108. }
  109. void ScriptProcessorNode::process(size_t framesToProcess)
  110. {
  111. // Discussion about inputs and outputs:
  112. // As in other AudioNodes, ScriptProcessorNode uses an AudioBus for its input and output (see inputBus and outputBus below).
  113. // Additionally, there is a double-buffering for input and output which is exposed directly to JavaScript (see inputBuffer and outputBuffer below).
  114. // This node is the producer for inputBuffer and the consumer for outputBuffer.
  115. // The JavaScript code is the consumer of inputBuffer and the producer for outputBuffer.
  116. // Check if audioprocess listener is set.
  117. if (!m_hasAudioProcessListener)
  118. return;
  119. // Get input and output busses.
  120. AudioBus* inputBus = this->input(0)->bus();
  121. AudioBus* outputBus = this->output(0)->bus();
  122. // Get input and output buffers. We double-buffer both the input and output sides.
  123. unsigned doubleBufferIndex = this->doubleBufferIndex();
  124. bool isDoubleBufferIndexGood = doubleBufferIndex < 2 && doubleBufferIndex < m_inputBuffers.size() && doubleBufferIndex < m_outputBuffers.size();
  125. ASSERT(isDoubleBufferIndexGood);
  126. if (!isDoubleBufferIndexGood)
  127. return;
  128. AudioBuffer* inputBuffer = m_inputBuffers[doubleBufferIndex].get();
  129. AudioBuffer* outputBuffer = m_outputBuffers[doubleBufferIndex].get();
  130. // Check the consistency of input and output buffers.
  131. unsigned numberOfInputChannels = m_internalInputBus->numberOfChannels();
  132. bool buffersAreGood = outputBuffer && bufferSize() == outputBuffer->length() && m_bufferReadWriteIndex + framesToProcess <= bufferSize();
  133. // If the number of input channels is zero, it's ok to have inputBuffer = 0.
  134. if (m_internalInputBus->numberOfChannels())
  135. buffersAreGood = buffersAreGood && inputBuffer && bufferSize() == inputBuffer->length();
  136. ASSERT(buffersAreGood);
  137. if (!buffersAreGood)
  138. return;
  139. // We assume that bufferSize() is evenly divisible by framesToProcess - should always be true, but we should still check.
  140. bool isFramesToProcessGood = framesToProcess && bufferSize() >= framesToProcess && !(bufferSize() % framesToProcess);
  141. ASSERT(isFramesToProcessGood);
  142. if (!isFramesToProcessGood)
  143. return;
  144. unsigned numberOfOutputChannels = outputBus->numberOfChannels();
  145. bool channelsAreGood = (numberOfInputChannels == m_numberOfInputChannels) && (numberOfOutputChannels == m_numberOfOutputChannels);
  146. ASSERT(channelsAreGood);
  147. if (!channelsAreGood)
  148. return;
  149. for (unsigned i = 0; i < numberOfInputChannels; i++)
  150. m_internalInputBus->setChannelMemory(i, inputBuffer->getChannelData(i)->data() + m_bufferReadWriteIndex, framesToProcess);
  151. if (numberOfInputChannels)
  152. m_internalInputBus->copyFrom(*inputBus);
  153. // Copy from the output buffer to the output.
  154. for (unsigned i = 0; i < numberOfOutputChannels; ++i)
  155. memcpy(outputBus->channel(i)->mutableData(), outputBuffer->getChannelData(i)->data() + m_bufferReadWriteIndex, sizeof(float) * framesToProcess);
  156. // Update the buffering index.
  157. m_bufferReadWriteIndex = (m_bufferReadWriteIndex + framesToProcess) % bufferSize();
  158. // m_bufferReadWriteIndex will wrap back around to 0 when the current input and output buffers are full.
  159. // When this happens, fire an event and swap buffers.
  160. if (!m_bufferReadWriteIndex) {
  161. // Avoid building up requests on the main thread to fire process events when they're not being handled.
  162. // This could be a problem if the main thread is very busy doing other things and is being held up handling previous requests.
  163. if (m_isRequestOutstanding) {
  164. // We're late in handling the previous request. The main thread must be very busy.
  165. // The best we can do is clear out the buffer ourself here.
  166. outputBuffer->zero();
  167. } else {
  168. // Reference ourself so we don't accidentally get deleted before fireProcessEvent() gets called.
  169. ref();
  170. // Fire the event on the main thread, not this one (which is the realtime audio thread).
  171. m_doubleBufferIndexForEvent = m_doubleBufferIndex;
  172. m_isRequestOutstanding = true;
  173. callOnMainThread(fireProcessEventDispatch, this);
  174. }
  175. swapBuffers();
  176. }
  177. }
  178. void ScriptProcessorNode::setOnaudioprocess(PassRefPtr<EventListener> listener)
  179. {
  180. m_hasAudioProcessListener = listener;
  181. setAttributeEventListener(eventNames().audioprocessEvent, listener);
  182. }
  183. void ScriptProcessorNode::fireProcessEventDispatch(void* userData)
  184. {
  185. ScriptProcessorNode* jsAudioNode = static_cast<ScriptProcessorNode*>(userData);
  186. ASSERT(jsAudioNode);
  187. if (!jsAudioNode)
  188. return;
  189. jsAudioNode->fireProcessEvent();
  190. // De-reference to match the ref() call in process().
  191. jsAudioNode->deref();
  192. }
  193. void ScriptProcessorNode::fireProcessEvent()
  194. {
  195. ASSERT(isMainThread() && m_isRequestOutstanding);
  196. bool isIndexGood = m_doubleBufferIndexForEvent < 2;
  197. ASSERT(isIndexGood);
  198. if (!isIndexGood)
  199. return;
  200. AudioBuffer* inputBuffer = m_inputBuffers[m_doubleBufferIndexForEvent].get();
  201. AudioBuffer* outputBuffer = m_outputBuffers[m_doubleBufferIndexForEvent].get();
  202. ASSERT(outputBuffer);
  203. if (!outputBuffer)
  204. return;
  205. // Avoid firing the event if the document has already gone away.
  206. if (context()->scriptExecutionContext()) {
  207. // Let the audio thread know we've gotten to the point where it's OK for it to make another request.
  208. m_isRequestOutstanding = false;
  209. // Call the JavaScript event handler which will do the audio processing.
  210. dispatchEvent(AudioProcessingEvent::create(inputBuffer, outputBuffer));
  211. }
  212. }
  213. void ScriptProcessorNode::reset()
  214. {
  215. m_bufferReadWriteIndex = 0;
  216. m_doubleBufferIndex = 0;
  217. for (unsigned i = 0; i < 2; ++i) {
  218. m_inputBuffers[i]->zero();
  219. m_outputBuffers[i]->zero();
  220. }
  221. }
  222. double ScriptProcessorNode::tailTime() const
  223. {
  224. return std::numeric_limits<double>::infinity();
  225. }
  226. double ScriptProcessorNode::latencyTime() const
  227. {
  228. return std::numeric_limits<double>::infinity();
  229. }
  230. } // namespace WebCore
  231. #endif // ENABLE(WEB_AUDIO)