AudioContext.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  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. #ifndef AudioContext_h
  25. #define AudioContext_h
  26. #include "ActiveDOMObject.h"
  27. #include "AsyncAudioDecoder.h"
  28. #include "AudioBus.h"
  29. #include "AudioDestinationNode.h"
  30. #include "EventListener.h"
  31. #include "EventTarget.h"
  32. #include "MediaCanStartListener.h"
  33. #include <wtf/HashSet.h>
  34. #include <wtf/MainThread.h>
  35. #include <wtf/OwnPtr.h>
  36. #include <wtf/PassRefPtr.h>
  37. #include <wtf/RefCounted.h>
  38. #include <wtf/RefPtr.h>
  39. #include <wtf/ThreadSafeRefCounted.h>
  40. #include <wtf/Threading.h>
  41. #include <wtf/Vector.h>
  42. #include <wtf/text/AtomicStringHash.h>
  43. namespace WebCore {
  44. class AudioBuffer;
  45. class AudioBufferCallback;
  46. class AudioBufferSourceNode;
  47. class MediaElementAudioSourceNode;
  48. class MediaStreamAudioDestinationNode;
  49. class MediaStreamAudioSourceNode;
  50. class HRTFDatabaseLoader;
  51. class HTMLMediaElement;
  52. class ChannelMergerNode;
  53. class ChannelSplitterNode;
  54. class GainNode;
  55. class PannerNode;
  56. class AudioListener;
  57. class AudioSummingJunction;
  58. class BiquadFilterNode;
  59. class DelayNode;
  60. class Document;
  61. class ConvolverNode;
  62. class DynamicsCompressorNode;
  63. class AnalyserNode;
  64. class WaveShaperNode;
  65. class ScriptProcessorNode;
  66. class OscillatorNode;
  67. class WaveTable;
  68. // AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it.
  69. // For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism.
  70. class AudioContext : public ActiveDOMObject, public ThreadSafeRefCounted<AudioContext>, public EventTarget, public MediaCanStartListener {
  71. public:
  72. // Create an AudioContext for rendering to the audio hardware.
  73. static PassRefPtr<AudioContext> create(Document*, ExceptionCode&);
  74. // Create an AudioContext for offline (non-realtime) rendering.
  75. static PassRefPtr<AudioContext> createOfflineContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode&);
  76. virtual ~AudioContext();
  77. bool isInitialized() const;
  78. bool isOfflineContext() { return m_isOfflineContext; }
  79. // Returns true when initialize() was called AND all asynchronous initialization has completed.
  80. bool isRunnable() const;
  81. HRTFDatabaseLoader* hrtfDatabaseLoader() const { return m_hrtfDatabaseLoader.get(); }
  82. // Document notification
  83. virtual void stop();
  84. Document* document() const; // ASSERTs if document no longer exists.
  85. bool hasDocument();
  86. AudioDestinationNode* destination() { return m_destinationNode.get(); }
  87. size_t currentSampleFrame() const { return m_destinationNode->currentSampleFrame(); }
  88. double currentTime() const { return m_destinationNode->currentTime(); }
  89. float sampleRate() const { return m_destinationNode->sampleRate(); }
  90. unsigned long activeSourceCount() const { return static_cast<unsigned long>(m_activeSourceCount); }
  91. void incrementActiveSourceCount();
  92. void decrementActiveSourceCount();
  93. PassRefPtr<AudioBuffer> createBuffer(unsigned numberOfChannels, size_t numberOfFrames, float sampleRate, ExceptionCode&);
  94. PassRefPtr<AudioBuffer> createBuffer(ArrayBuffer*, bool mixToMono, ExceptionCode&);
  95. // Asynchronous audio file data decoding.
  96. void decodeAudioData(ArrayBuffer*, PassRefPtr<AudioBufferCallback>, PassRefPtr<AudioBufferCallback>, ExceptionCode& ec);
  97. AudioListener* listener() { return m_listener.get(); }
  98. // The AudioNode create methods are called on the main thread (from JavaScript).
  99. PassRefPtr<AudioBufferSourceNode> createBufferSource();
  100. #if ENABLE(VIDEO)
  101. PassRefPtr<MediaElementAudioSourceNode> createMediaElementSource(HTMLMediaElement*, ExceptionCode&);
  102. #endif
  103. #if ENABLE(MEDIA_STREAM)
  104. PassRefPtr<MediaStreamAudioSourceNode> createMediaStreamSource(MediaStream*, ExceptionCode&);
  105. PassRefPtr<MediaStreamAudioDestinationNode> createMediaStreamDestination();
  106. #endif
  107. PassRefPtr<GainNode> createGain();
  108. PassRefPtr<BiquadFilterNode> createBiquadFilter();
  109. PassRefPtr<WaveShaperNode> createWaveShaper();
  110. PassRefPtr<DelayNode> createDelay(ExceptionCode&);
  111. PassRefPtr<DelayNode> createDelay(double maxDelayTime, ExceptionCode&);
  112. PassRefPtr<PannerNode> createPanner();
  113. PassRefPtr<ConvolverNode> createConvolver();
  114. PassRefPtr<DynamicsCompressorNode> createDynamicsCompressor();
  115. PassRefPtr<AnalyserNode> createAnalyser();
  116. PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, ExceptionCode&);
  117. PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode&);
  118. PassRefPtr<ScriptProcessorNode> createScriptProcessor(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode&);
  119. PassRefPtr<ChannelSplitterNode> createChannelSplitter(ExceptionCode&);
  120. PassRefPtr<ChannelSplitterNode> createChannelSplitter(size_t numberOfOutputs, ExceptionCode&);
  121. PassRefPtr<ChannelMergerNode> createChannelMerger(ExceptionCode&);
  122. PassRefPtr<ChannelMergerNode> createChannelMerger(size_t numberOfInputs, ExceptionCode&);
  123. PassRefPtr<OscillatorNode> createOscillator();
  124. PassRefPtr<WaveTable> createWaveTable(Float32Array* real, Float32Array* imag, ExceptionCode&);
  125. // When a source node has no more processing to do (has finished playing), then it tells the context to dereference it.
  126. void notifyNodeFinishedProcessing(AudioNode*);
  127. // Called at the start of each render quantum.
  128. void handlePreRenderTasks();
  129. // Called at the end of each render quantum.
  130. void handlePostRenderTasks();
  131. // Called periodically at the end of each render quantum to dereference finished source nodes.
  132. void derefFinishedSourceNodes();
  133. // We schedule deletion of all marked nodes at the end of each realtime render quantum.
  134. void markForDeletion(AudioNode*);
  135. void deleteMarkedNodes();
  136. // AudioContext can pull node(s) at the end of each render quantum even when they are not connected to any downstream nodes.
  137. // These two methods are called by the nodes who want to add/remove themselves into/from the automatic pull lists.
  138. void addAutomaticPullNode(AudioNode*);
  139. void removeAutomaticPullNode(AudioNode*);
  140. // Called right before handlePostRenderTasks() to handle nodes which need to be pulled even when they are not connected to anything.
  141. void processAutomaticPullNodes(size_t framesToProcess);
  142. // Keeps track of the number of connections made.
  143. void incrementConnectionCount()
  144. {
  145. ASSERT(isMainThread());
  146. m_connectionCount++;
  147. }
  148. unsigned connectionCount() const { return m_connectionCount; }
  149. //
  150. // Thread Safety and Graph Locking:
  151. //
  152. void setAudioThread(ThreadIdentifier thread) { m_audioThread = thread; } // FIXME: check either not initialized or the same
  153. ThreadIdentifier audioThread() const { return m_audioThread; }
  154. bool isAudioThread() const;
  155. // Returns true only after the audio thread has been started and then shutdown.
  156. bool isAudioThreadFinished() { return m_isAudioThreadFinished; }
  157. // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
  158. void lock(bool& mustReleaseLock);
  159. // Returns true if we own the lock.
  160. // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
  161. bool tryLock(bool& mustReleaseLock);
  162. void unlock();
  163. // Returns true if this thread owns the context's lock.
  164. bool isGraphOwner() const;
  165. // Returns the maximum numuber of channels we can support.
  166. static unsigned maxNumberOfChannels() { return MaxNumberOfChannels;}
  167. class AutoLocker {
  168. public:
  169. AutoLocker(AudioContext* context)
  170. : m_context(context)
  171. {
  172. ASSERT(context);
  173. context->lock(m_mustReleaseLock);
  174. }
  175. ~AutoLocker()
  176. {
  177. if (m_mustReleaseLock)
  178. m_context->unlock();
  179. }
  180. private:
  181. AudioContext* m_context;
  182. bool m_mustReleaseLock;
  183. };
  184. // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.
  185. void addDeferredFinishDeref(AudioNode*);
  186. // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs().
  187. void handleDeferredFinishDerefs();
  188. // Only accessed when the graph lock is held.
  189. void markSummingJunctionDirty(AudioSummingJunction*);
  190. void markAudioNodeOutputDirty(AudioNodeOutput*);
  191. // Must be called on main thread.
  192. void removeMarkedSummingJunction(AudioSummingJunction*);
  193. // EventTarget
  194. virtual const AtomicString& interfaceName() const;
  195. virtual ScriptExecutionContext* scriptExecutionContext() const;
  196. virtual EventTargetData* eventTargetData() { return &m_eventTargetData; }
  197. virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; }
  198. DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
  199. // Reconcile ref/deref which are defined both in ThreadSafeRefCounted and EventTarget.
  200. using ThreadSafeRefCounted<AudioContext>::ref;
  201. using ThreadSafeRefCounted<AudioContext>::deref;
  202. void startRendering();
  203. void fireCompletionEvent();
  204. static unsigned s_hardwareContextCount;
  205. // Restrictions to change default behaviors.
  206. enum BehaviorRestrictionFlags {
  207. NoRestrictions = 0,
  208. RequireUserGestureForAudioStartRestriction = 1 << 0,
  209. RequirePageConsentForAudioStartRestriction = 1 << 1,
  210. };
  211. typedef unsigned BehaviorRestrictions;
  212. bool userGestureRequiredForAudioStart() const { return m_restrictions & RequireUserGestureForAudioStartRestriction; }
  213. bool pageConsentRequiredForAudioStart() const { return m_restrictions & RequirePageConsentForAudioStartRestriction; }
  214. void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; }
  215. void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
  216. protected:
  217. explicit AudioContext(Document*);
  218. AudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate);
  219. static bool isSampleRateRangeGood(float sampleRate);
  220. private:
  221. void constructCommon();
  222. void lazyInitialize();
  223. void uninitialize();
  224. // ScriptExecutionContext calls stop twice.
  225. // We'd like to schedule only one stop action for them.
  226. bool m_isStopScheduled;
  227. static void stopDispatch(void* userData);
  228. void clear();
  229. void scheduleNodeDeletion();
  230. static void deleteMarkedNodesDispatch(void* userData);
  231. virtual void mediaCanStart() OVERRIDE;
  232. bool m_isInitialized;
  233. bool m_isAudioThreadFinished;
  234. // The context itself keeps a reference to all source nodes. The source nodes, then reference all nodes they're connected to.
  235. // In turn, these nodes reference all nodes they're connected to. All nodes are ultimately connected to the AudioDestinationNode.
  236. // When the context dereferences a source node, it will be deactivated from the rendering graph along with all other nodes it is
  237. // uniquely connected to. See the AudioNode::ref() and AudioNode::deref() methods for more details.
  238. void refNode(AudioNode*);
  239. void derefNode(AudioNode*);
  240. // When the context goes away, there might still be some sources which haven't finished playing.
  241. // Make sure to dereference them here.
  242. void derefUnfinishedSourceNodes();
  243. RefPtr<AudioDestinationNode> m_destinationNode;
  244. RefPtr<AudioListener> m_listener;
  245. // Only accessed in the audio thread.
  246. Vector<AudioNode*> m_finishedNodes;
  247. // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation
  248. // with an optional argument for refType. We need to use the special refType: RefTypeConnection
  249. // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
  250. Vector<AudioNode*> m_referencedNodes;
  251. // Accumulate nodes which need to be deleted here.
  252. // This is copied to m_nodesToDelete at the end of a render cycle in handlePostRenderTasks(), where we're assured of a stable graph
  253. // state which will have no references to any of the nodes in m_nodesToDelete once the context lock is released
  254. // (when handlePostRenderTasks() has completed).
  255. Vector<AudioNode*> m_nodesMarkedForDeletion;
  256. // They will be scheduled for deletion (on the main thread) at the end of a render cycle (in realtime thread).
  257. Vector<AudioNode*> m_nodesToDelete;
  258. bool m_isDeletionScheduled;
  259. // Only accessed when the graph lock is held.
  260. HashSet<AudioSummingJunction*> m_dirtySummingJunctions;
  261. HashSet<AudioNodeOutput*> m_dirtyAudioNodeOutputs;
  262. void handleDirtyAudioSummingJunctions();
  263. void handleDirtyAudioNodeOutputs();
  264. // For the sake of thread safety, we maintain a seperate Vector of automatic pull nodes for rendering in m_renderingAutomaticPullNodes.
  265. // It will be copied from m_automaticPullNodes by updateAutomaticPullNodes() at the very start or end of the rendering quantum.
  266. HashSet<AudioNode*> m_automaticPullNodes;
  267. Vector<AudioNode*> m_renderingAutomaticPullNodes;
  268. // m_automaticPullNodesNeedUpdating keeps track if m_automaticPullNodes is modified.
  269. bool m_automaticPullNodesNeedUpdating;
  270. void updateAutomaticPullNodes();
  271. unsigned m_connectionCount;
  272. // Graph locking.
  273. Mutex m_contextGraphMutex;
  274. volatile ThreadIdentifier m_audioThread;
  275. volatile ThreadIdentifier m_graphOwnerThread; // if the lock is held then this is the thread which owns it, otherwise == UndefinedThreadIdentifier
  276. // Only accessed in the audio thread.
  277. Vector<AudioNode*> m_deferredFinishDerefList;
  278. // HRTF Database loader
  279. RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader;
  280. // EventTarget
  281. virtual void refEventTarget() { ref(); }
  282. virtual void derefEventTarget() { deref(); }
  283. EventTargetData m_eventTargetData;
  284. RefPtr<AudioBuffer> m_renderTarget;
  285. bool m_isOfflineContext;
  286. AsyncAudioDecoder m_audioDecoder;
  287. // This is considering 32 is large enough for multiple channels audio.
  288. // It is somewhat arbitrary and could be increased if necessary.
  289. enum { MaxNumberOfChannels = 32 };
  290. // Number of AudioBufferSourceNodes that are active (playing).
  291. int m_activeSourceCount;
  292. BehaviorRestrictions m_restrictions;
  293. };
  294. } // WebCore
  295. #endif // AudioContext_h