Source/WebCore/ChangeLog

 12011-04-01 Chris Rogers <crogers@google.com>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Add support for offline audio rendering to AudioContext API
 6 https://bugs.webkit.org/show_bug.cgi?id=57676
 7
 8 No new tests since audio API is not yet implemented.
 9
 10 * WebCore.gypi:
 11 * bindings/js/JSEventCustom.cpp:
 12 (WebCore::toJS):
 13 * bindings/js/JSEventTarget.cpp:
 14 (WebCore::toJS):
 15 * bindings/v8/V8DOMWrapper.cpp:
 16 (WebCore::V8DOMWrapper::convertEventTargetToV8Object):
 17 * bindings/v8/custom/V8AudioContextCustom.cpp:
 18 (WebCore::V8AudioContext::constructorCallback):
 19 * bindings/v8/custom/V8EventCustom.cpp:
 20 (WebCore::toV8):
 21 * dom/Event.cpp:
 22 (WebCore::Event::isOfflineAudioCompletionEvent):
 23 * dom/Event.h:
 24 * dom/EventTarget.cpp:
 25 (WebCore::EventTarget::toAudioContext):
 26 * dom/EventTarget.h:
 27 * platform/audio/HRTFDatabaseLoader.cpp:
 28 (WebCore::HRTFDatabaseLoader::waitForLoaderThreadCompletion):
 29 * platform/audio/HRTFDatabaseLoader.h:
 30 (WebCore::HRTFDatabaseLoader::loader):
 31 * webaudio/AudioContext.cpp:
 32 (WebCore::AudioContext::createOfflineContext):
 33 (WebCore::AudioContext::AudioContext):
 34 (WebCore::AudioContext::constructCommon):
 35 (WebCore::AudioContext::document):
 36 (WebCore::AudioContext::scriptExecutionContext):
 37 (WebCore::AudioContext::toAudioContext):
 38 (WebCore::AudioContext::startRendering):
 39 (WebCore::AudioContext::fireCompletionEvent):
 40 * webaudio/AudioContext.h:
 41 (WebCore::AudioContext::isOfflineContext):
 42 (WebCore::AudioContext::eventTargetData):
 43 (WebCore::AudioContext::ensureEventTargetData):
 44 (WebCore::AudioContext::refEventTarget):
 45 (WebCore::AudioContext::derefEventTarget):
 46 * webaudio/AudioContext.idl:
 47 * webaudio/AudioDestinationNode.cpp:
 48 (WebCore::AudioDestinationNode::AudioDestinationNode):
 49 * webaudio/AudioDestinationNode.h:
 50 (WebCore::AudioDestinationNode::reset):
 51 (WebCore::AudioDestinationNode::numberOfChannels):
 52 * webaudio/ConvolverNode.cpp:
 53 (WebCore::ConvolverNode::setBuffer):
 54
1552011-04-01 Jer Noble <jer.noble@apple.com>
256
357 Reviewed by Darin Adler.
82733

Source/WebCore/WebCore.gypi

13871387 'webaudio/HighPass2FilterNode.idl',
13881388 'webaudio/JavaScriptAudioNode.idl',
13891389 'webaudio/LowPass2FilterNode.idl',
 1390 'webaudio/OfflineAudioCompletionEvent.idl',
13901391 'webaudio/RealtimeAnalyserNode.idl',
13911392 'websockets/WebSocket.idl',
13921393 'workers/AbstractWorker.idl',

58785879 'webaudio/BiquadProcessor.h',
58795880 'webaudio/ConvolverNode.cpp',
58805881 'webaudio/ConvolverNode.h',
 5882 'webaudio/DefaultAudioDestinationNode.cpp',
 5883 'webaudio/DefaultAudioDestinationNode.h',
58815884 'webaudio/DelayDSPKernel.cpp',
58825885 'webaudio/DelayDSPKernel.h',
58835886 'webaudio/DelayNode.cpp',

58905893 'webaudio/JavaScriptAudioNode.h',
58915894 'webaudio/LowPass2FilterNode.cpp',
58925895 'webaudio/LowPass2FilterNode.h',
 5896 'webaudio/OfflineAudioCompletionEvent.cpp',
 5897 'webaudio/OfflineAudioCompletionEvent.h',
 5898 'webaudio/OfflineAudioDestinationNode.cpp',
 5899 'webaudio/OfflineAudioDestinationNode.h',
58935900 'webaudio/RealtimeAnalyser.cpp',
58945901 'webaudio/RealtimeAnalyser.h',
58955902 'webaudio/RealtimeAnalyserNode.cpp',
82476

Source/WebCore/bindings/js/JSEventCustom.cpp

101101#if ENABLE(WEB_AUDIO)
102102#include "AudioProcessingEvent.h"
103103#include "JSAudioProcessingEvent.h"
 104#include "JSOfflineAudioCompletionEvent.h"
 105#include "OfflineAudioCompletionEvent.h"
104106#endif
105107
106108using namespace JSC;

@@JSValue toJS(ExecState* exec, JSDOMGloba
190192#if ENABLE(WEB_AUDIO)
191193 else if (event->isAudioProcessingEvent())
192194 wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, AudioProcessingEvent, event);
 195 else if (event->isOfflineAudioCompletionEvent())
 196 wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, OfflineAudioCompletionEvent, event);
193197#endif
194198#if ENABLE(INPUT_SPEECH)
195199 else if (event->isSpeechInputEvent())
82476

Source/WebCore/bindings/js/JSEventTarget.cpp

8484#endif
8585
8686#if ENABLE(WEB_AUDIO)
 87#include "AudioContext.h"
 88#include "JSAudioContext.h"
8789#include "JSJavaScriptAudioNode.h"
8890#include "JavaScriptAudioNode.h"
8991#endif

@@JSValue toJS(ExecState* exec, JSDOMGloba
173175#if ENABLE(WEB_AUDIO)
174176 if (JavaScriptAudioNode* jsAudioNode = target->toJavaScriptAudioNode())
175177 return toJS(exec, globalObject, jsAudioNode);
 178 if (AudioContext* audioContext = target->toAudioContext())
 179 return toJS(exec, globalObject, audioContext);
176180#endif
177181
178182#if ENABLE(WEB_SOCKETS)
82476

Source/WebCore/bindings/v8/V8DOMWrapper.cpp

8484#endif
8585
8686#if ENABLE(WEB_AUDIO)
 87#include "V8AudioContext.h"
8788#include "V8JavaScriptAudioNode.h"
8889#endif
8990

@@v8::Handle<v8::Value> V8DOMWrapper::conv
444445#if ENABLE(WEB_AUDIO)
445446 if (JavaScriptAudioNode* jsAudioNode = target->toJavaScriptAudioNode())
446447 return toV8(jsAudioNode);
 448 if (AudioContext* audioContext = target->toAudioContext())
 449 return toV8(audioContext);
447450#endif
448451
449452 ASSERT(0);
82476

Source/WebCore/bindings/v8/custom/V8AudioContextCustom.cpp

@@v8::Handle<v8::Value> V8AudioContext::co
5151 if (!document)
5252 return throwError("AudioContext constructor associated document is unavailable", V8Proxy::ReferenceError);
5353
54  RefPtr<AudioContext> audioContext = AudioContext::create(document);
 54 RefPtr<AudioContext> audioContext;
 55
 56 if (!args.Length()) {
 57 // Construct for default AudioContext which talks to audio hardware.
 58 audioContext = AudioContext::create(document);
 59 } else {
 60 // Construct for offline (render-target) AudioContext which renders into an AudioBuffer.
 61 // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
 62 if (args.Length() < 3)
 63 return throwError("Not enough arguments", V8Proxy::SyntaxError);
 64
 65 bool ok = false;
 66
 67 unsigned numberOfChannels = toInt32(args[0], ok);
 68 if (!ok)
 69 return throwError("Invalid number of channels", V8Proxy::SyntaxError);
 70
 71 unsigned numberOfFrames = toInt32(args[1], ok);
 72 if (!ok)
 73 return throwError("Invalid number of frames", V8Proxy::SyntaxError);
 74
 75 float sampleRate = toFloat(args[2]);
 76
 77 audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate);
 78 }
 79
 80 if (!audioContext.get())
 81 return throwError("Error creating AudioContext", V8Proxy::SyntaxError);
5582
5683 // Transform the holder into a wrapper object for the audio context.
5784 V8DOMWrapper::setDOMWrapper(args.Holder(), &info, audioContext.get());
82476

Source/WebCore/bindings/v8/custom/V8EventCustom.cpp

7070
7171#if ENABLE(WEB_AUDIO)
7272#include "V8AudioProcessingEvent.h"
 73#include "V8OfflineAudioCompletionEvent.h"
7374#endif
7475
7576namespace WebCore {

@@v8::Handle<v8::Value> toV8(Event* impl)
169170#if ENABLE(WEB_AUDIO)
170171 if (impl->isAudioProcessingEvent())
171172 return toV8(static_cast<AudioProcessingEvent*>(impl));
 173 if (impl->isOfflineAudioCompletionEvent())
 174 return toV8(static_cast<OfflineAudioCompletionEvent*>(impl));
172175#endif
173176#if ENABLE(INPUT_SPEECH)
174177 if (impl->isSpeechInputEvent())
82476

Source/WebCore/dom/Event.cpp

@@bool Event::isAudioProcessingEvent() con
229229{
230230 return false;
231231}
 232
 233bool Event::isOfflineAudioCompletionEvent() const
 234{
 235 return false;
 236}
232237#endif
233238
234239#if ENABLE(INPUT_SPEECH)
82476

Source/WebCore/dom/Event.h

@@namespace WebCore {
131131#endif
132132#if ENABLE(WEB_AUDIO)
133133 virtual bool isAudioProcessingEvent() const;
 134 virtual bool isOfflineAudioCompletionEvent() const;
134135#endif
135136 virtual bool isErrorEvent() const;
136137#if ENABLE(TOUCH_EVENTS)
82476

Source/WebCore/dom/EventTarget.cpp

@@SVGElementInstance* EventTarget::toSVGEl
119119#endif
120120
121121#if ENABLE(WEB_AUDIO)
 122AudioContext* EventTarget::toAudioContext()
 123{
 124 return 0;
 125}
 126
122127JavaScriptAudioNode* EventTarget::toJavaScriptAudioNode()
123128{
124129 return 0;
82476

Source/WebCore/dom/EventTarget.h

4040
4141namespace WebCore {
4242
 43 class AudioContext;
4344 class AbstractWorker;
4445 class DedicatedWorkerContext;
4546 class DOMApplicationCache;

@@namespace WebCore {
122123#endif
123124
124125#if ENABLE(WEB_AUDIO)
 126 virtual AudioContext* toAudioContext();
125127 virtual JavaScriptAudioNode* toJavaScriptAudioNode();
126128#endif
127129
82476

Source/WebCore/platform/audio/HRTFDatabaseLoader.cpp

@@bool HRTFDatabaseLoader::isLoaded() cons
120120 return m_hrtfDatabase.get();
121121}
122122
 123
 124void HRTFDatabaseLoader::waitForLoaderThreadCompletion()
 125{
 126 ASSERT(!isMainThread());
 127 ASSERT(m_databaseLoaderThread);
 128 waitForThreadCompletion(m_databaseLoaderThread, 0);
 129}
 130
123131HRTFDatabase* HRTFDatabaseLoader::defaultHRTFDatabase()
124132{
125133 if (!s_loader)
82476

Source/WebCore/platform/audio/HRTFDatabaseLoader.h

@@public:
4646 // Must be called from the main thread.
4747 static PassRefPtr<HRTFDatabaseLoader> createAndLoadAsynchronouslyIfNecessary(double sampleRate);
4848
 49 // Returns the singleton HRTFDatabaseLoader.
 50 static HRTFDatabaseLoader* loader() { return s_loader; }
 51
4952 // Both constructor and destructor must be called from the main thread.
5053 ~HRTFDatabaseLoader();
5154
5255 // Returns true once the default database has been completely loaded.
5356 bool isLoaded() const;
 57
 58 // May not be called on the main thread.
 59 // This is so a different background thread may synchronize with the loader thread.
 60 void waitForLoaderThreadCompletion();
5461
5562 HRTFDatabase* database() { return m_hrtfDatabase.get(); }
5663
82476

Source/WebCore/webaudio/AudioContext.cpp

3939#include "AudioNodeOutput.h"
4040#include "AudioPannerNode.h"
4141#include "ConvolverNode.h"
 42#include "DefaultAudioDestinationNode.h"
4243#include "DelayNode.h"
4344#include "Document.h"
4445#include "FFTFrame.h"

4748#include "HighPass2FilterNode.h"
4849#include "JavaScriptAudioNode.h"
4950#include "LowPass2FilterNode.h"
 51#include "OfflineAudioCompletionEvent.h"
 52#include "OfflineAudioDestinationNode.h"
5053#include "PlatformString.h"
5154#include "RealtimeAnalyserNode.h"
5255

@@PassRefPtr<AudioContext> AudioContext::c
6669 return adoptRef(new AudioContext(document));
6770}
6871
 72PassRefPtr<AudioContext> AudioContext::createOfflineContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
 73{
 74 return adoptRef(new AudioContext(document, numberOfChannels, numberOfFrames, sampleRate));
 75}
 76
6977AudioContext::AudioContext(Document* document)
7078 : ActiveDOMObject(document, this)
7179 , m_isInitialized(false)

@@AudioContext::AudioContext(Document* doc
7583 , m_connectionCount(0)
7684 , m_audioThread(0)
7785 , m_graphOwnerThread(UndefinedThreadIdentifier)
 86 , m_isOfflineContext(false)
 87{
 88 constructCommon();
 89
 90 m_destinationNode = DefaultAudioDestinationNode::create(this);
 91
 92 // This sets in motion an asynchronous loading mechanism on another thread.
 93 // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded.
 94 // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph
 95 // when this has finished (see AudioDestinationNode).
 96 m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate());
 97
 98 // FIXME: for now default AudioContext does not need an explicit startRendering() call.
 99 // We may want to consider requiring it for symmetry with OfflineAudioContext
 100 m_destinationNode->startRendering();
 101}
 102
 103AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
 104 : ActiveDOMObject(document, this)
 105 , m_isInitialized(false)
 106 , m_isAudioThreadFinished(false)
 107 , m_document(document)
 108 , m_destinationNode(0)
 109 , m_connectionCount(0)
 110 , m_audioThread(0)
 111 , m_graphOwnerThread(UndefinedThreadIdentifier)
 112 , m_isOfflineContext(true)
 113{
 114 constructCommon();
 115
 116 // FIXME: the passed in sampleRate MUST match the hardware sample-rate since HRTFDatabaseLoader is a singleton.
 117 m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate);
 118
 119 // Create a new destination for offline rendering.
 120 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
 121 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get());
 122}
 123
 124void AudioContext::constructCommon()
78125{
79126 // Note: because adoptRef() won't be called until we leave this constructor, but code in this constructor needs to reference this context,
80127 // relax the check.

@@AudioContext::AudioContext(Document* doc
82129
83130 FFTFrame::initialize();
84131
85  m_destinationNode = AudioDestinationNode::create(this);
86132 m_listener = AudioListener::create();
87133 m_temporaryMonoBus = adoptPtr(new AudioBus(1, AudioNode::ProcessingSizeInFrames));
88134 m_temporaryStereoBus = adoptPtr(new AudioBus(2, AudioNode::ProcessingSizeInFrames));
89 
90  // This sets in motion an asynchronous loading mechanism on another thread.
91  // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded.
92  // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph
93  // when this has finished (see AudioDestinationNode).
94  m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate());
95135}
96136
97137AudioContext::~AudioContext()

@@void AudioContext::stop()
167207 uninitialize();
168208}
169209
170 Document* AudioContext::document()
 210Document* AudioContext::document() const
171211{
172212 ASSERT(m_document);
173213 return m_document;

@@void AudioContext::handleDirtyAudioNodeO
526566 m_dirtyAudioNodeOutputs.clear();
527567}
528568
 569ScriptExecutionContext* AudioContext::scriptExecutionContext() const
 570{
 571 return document();
 572}
 573
 574AudioContext* AudioContext::toAudioContext()
 575{
 576 return this;
 577}
 578
 579void AudioContext::startRendering()
 580{
 581 destination()->startRendering();
 582}
 583
 584void AudioContext::fireCompletionEvent()
 585{
 586 ASSERT(isMainThread());
 587 if (!isMainThread())
 588 return;
 589
 590 AudioBuffer* renderedBuffer = m_renderTarget.get();
 591
 592 ASSERT(renderedBuffer);
 593 if (!renderedBuffer)
 594 return;
 595
 596 // Avoid firing the event if the document has already gone away.
 597 if (hasDocument()) {
 598 // Call the offline rendering completion event listener.
 599 dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
 600 }
 601}
529602
530603} // namespace WebCore
531604
82476

Source/WebCore/webaudio/AudioContext.h

2828#include "ActiveDOMObject.h"
2929#include "AudioBus.h"
3030#include "AudioDestinationNode.h"
 31#include "EventListener.h"
 32#include "EventTarget.h"
3133#include "HRTFDatabaseLoader.h"
3234#include <wtf/HashSet.h>
3335#include <wtf/OwnPtr.h>

@@class JavaScriptAudioNode;
5961// AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it.
6062// For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism.
6163
62 class AudioContext : public ActiveDOMObject, public RefCounted<AudioContext> {
 64class AudioContext : public ActiveDOMObject, public RefCounted<AudioContext>, public EventTarget {
6365public:
6466 static PassRefPtr<AudioContext> create(Document*);
 67 static PassRefPtr<AudioContext> createOfflineContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate);
6568
6669 virtual ~AudioContext();
6770
6871 bool isInitialized() const;
 72
 73 bool isOfflineContext() { return m_isOfflineContext; }
6974
7075 // Returns true when initialize() was called AND all asynchronous initialization has completed.
7176 bool isRunnable() const;

@@public:
7378 // Document notification
7479 virtual void stop();
7580
76  Document* document(); // ASSERTs if document no longer exists.
 81 Document* document() const; // ASSERTs if document no longer exists.
7782 bool hasDocument();
7883
7984 AudioDestinationNode* destination() { return m_destinationNode.get(); }

@@public:
180185 // Only accessed when the graph lock is held.
181186 void markAudioNodeInputDirty(AudioNodeInput*);
182187 void markAudioNodeOutputDirty(AudioNodeOutput*);
 188
 189 // EventTarget
 190 virtual ScriptExecutionContext* scriptExecutionContext() const;
 191 virtual AudioContext* toAudioContext();
 192 virtual EventTargetData* eventTargetData() { return &m_eventTargetData; }
 193 virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; }
 194
 195 DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
 196
 197 // Reconcile ref/deref which are defined both in AudioNode and EventTarget.
 198 using RefCounted<AudioContext>::ref;
 199 using RefCounted<AudioContext>::deref;
 200
 201 void startRendering();
 202 void fireCompletionEvent();
183203
184204private:
185205 AudioContext(Document*);
 206 AudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate);
 207 void constructCommon();
 208
186209 void lazyInitialize();
187210 void uninitialize();
188211

@@private:
252275
253276 // HRTF Database loader
254277 RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader;
 278
 279 // EventTarget
 280 virtual void refEventTarget() { ref(); }
 281 virtual void derefEventTarget() { deref(); }
 282 EventTargetData m_eventTargetData;
 283
 284 RefPtr<AudioBuffer> m_renderTarget;
 285
 286 bool m_isOfflineContext;
255287};
256288
257289} // WebCore
82476

Source/WebCore/webaudio/AudioContext.idl

@@module webaudio {
2727 Conditional=WEB_AUDIO,
2828 CanBeConstructed,
2929 CustomConstructFunction,
30  V8CustomConstructor
 30 V8CustomConstructor,
 31#if defined(V8_BINDING) && V8_BINDING
 32 EventTarget
 33#endif
3134 ] AudioContext {
3235 // All rendered audio ultimately connects to destination, which represents the audio hardware.
3336 readonly attribute AudioDestinationNode destination;

@@module webaudio {
6265 // Channel splitting and merging
6366 AudioChannelSplitter createChannelSplitter();
6467 AudioChannelMerger createChannelMerger();
 68
 69 // Offline rendering
 70 // void prepareOfflineBufferRendering(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
 71 attribute EventListener oncomplete;
 72 void startRendering();
 73
6574 };
6675}
82476

Source/WebCore/webaudio/AudioDestinationNode.cpp

3232#include "AudioContext.h"
3333#include "AudioNodeInput.h"
3434#include "AudioNodeOutput.h"
35 #include <wtf/Threading.h>
3635
3736namespace WebCore {
38 
39 AudioDestinationNode::AudioDestinationNode(AudioContext* context)
40  : AudioNode(context, AudioDestination::hardwareSampleRate())
 37
 38AudioDestinationNode::AudioDestinationNode(AudioContext* context, double sampleRate)
 39 : AudioNode(context, sampleRate)
4140 , m_currentTime(0.0)
4241{
4342 addInput(adoptPtr(new AudioNodeInput(this)));
4443
4544 setType(NodeTypeDestination);
46 
47  initialize();
4845}
4946
5047AudioDestinationNode::~AudioDestinationNode()

@@AudioDestinationNode::~AudioDestinationN
5249 uninitialize();
5350}
5451
55 void AudioDestinationNode::initialize()
56 {
57  if (isInitialized())
58  return;
59 
60  double hardwareSampleRate = AudioDestination::hardwareSampleRate();
61 #ifndef NDEBUG
62  fprintf(stderr, ">>>> hardwareSampleRate = %f\n", hardwareSampleRate);
63 #endif
64 
65  m_destination = AudioDestination::create(*this, hardwareSampleRate);
66  m_destination->start();
67 
68  AudioNode::initialize();
69 }
70 
71 void AudioDestinationNode::uninitialize()
72 {
73  if (!isInitialized())
74  return;
75 
76  m_destination->stop();
77 
78  AudioNode::uninitialize();
79 }
80 
8152// The audio hardware calls us back here to gets its input stream.
8253void AudioDestinationNode::provideInput(AudioBus* destinationBus, size_t numberOfFrames)
8354{
82476

Source/WebCore/webaudio/AudioDestinationNode.h

2525#ifndef AudioDestinationNode_h
2626#define AudioDestinationNode_h
2727
28 #include "AudioDestination.h"
 28#include "AudioBuffer.h"
2929#include "AudioNode.h"
3030#include "AudioSourceProvider.h"
31 #include <wtf/OwnPtr.h>
32 #include <wtf/PassRefPtr.h>
3331
3432namespace WebCore {
3533

@@class AudioContext;
3836
3937class AudioDestinationNode : public AudioNode, public AudioSourceProvider {
4038public:
41  static PassRefPtr<AudioDestinationNode> create(AudioContext* context)
42  {
43  return adoptRef(new AudioDestinationNode(context));
44  }
45 
 39 AudioDestinationNode(AudioContext*, double sampleRate);
4640 virtual ~AudioDestinationNode();
4741
4842 // AudioNode
4943 virtual void process(size_t) { }; // we're pulled by hardware so this is never called
5044 virtual void reset() { m_currentTime = 0.0; };
51  virtual void initialize();
52  virtual void uninitialize();
5345
5446 // The audio hardware calls here periodically to gets its input stream.
5547 virtual void provideInput(AudioBus*, size_t numberOfFrames);
5648
5749 double currentTime() { return m_currentTime; }
5850
59  double sampleRate() const { return m_destination->sampleRate(); }
 51 virtual double sampleRate() const = 0;
6052
61  unsigned numberOfChannels() const { return 2; } // FIXME: update when multi-channel (more than stereo) is supported
62 
63 private:
64  AudioDestinationNode(AudioContext*);
 53 virtual unsigned numberOfChannels() const { return 2; } // FIXME: update when multi-channel (more than stereo) is supported
6554
66  OwnPtr<AudioDestination> m_destination;
 55 virtual void startRendering() = 0;
 56
 57protected:
6758 double m_currentTime;
6859};
6960
82476

Source/WebCore/webaudio/ConvolverNode.cpp

2929#include "ConvolverNode.h"
3030
3131#include "AudioBuffer.h"
 32#include "AudioContext.h"
3233#include "AudioNodeInput.h"
3334#include "AudioNodeOutput.h"
3435#include "Reverb.h"

@@void ConvolverNode::setBuffer(AudioBuffe
131132 bufferBus.setChannelMemory(i, buffer->getChannelData(i)->data(), bufferLength);
132133
133134 // Create the reverb with the given impulse response.
134  OwnPtr<Reverb> reverb = adoptPtr(new Reverb(&bufferBus, AudioNode::ProcessingSizeInFrames, MaxFFTSize, 2, true));
 135 bool useBackgroundThreads = !context()->isOfflineContext();
 136 OwnPtr<Reverb> reverb = adoptPtr(new Reverb(&bufferBus, AudioNode::ProcessingSizeInFrames, MaxFFTSize, 2, useBackgroundThreads));
135137
136138 {
137139 // Synchronize with process().
82476

Source/WebCore/webaudio/DefaultAudioDestinationNode.cpp

 1/*
 2 * Copyright (C) 2011, 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
 25#include "config.h"
 26
 27#if ENABLE(WEB_AUDIO)
 28
 29#include "DefaultAudioDestinationNode.h"
 30
 31namespace WebCore {
 32
 33DefaultAudioDestinationNode::DefaultAudioDestinationNode(AudioContext* context)
 34 : AudioDestinationNode(context, AudioDestination::hardwareSampleRate())
 35{
 36 initialize();
 37}
 38
 39DefaultAudioDestinationNode::~DefaultAudioDestinationNode()
 40{
 41 uninitialize();
 42}
 43
 44void DefaultAudioDestinationNode::initialize()
 45{
 46 if (isInitialized())
 47 return;
 48
 49 double hardwareSampleRate = AudioDestination::hardwareSampleRate();
 50#ifndef NDEBUG
 51 fprintf(stderr, ">>>> hardwareSampleRate = %f\n", hardwareSampleRate);
 52#endif
 53
 54 m_destination = AudioDestination::create(*this, hardwareSampleRate);
 55
 56 AudioNode::initialize();
 57}
 58
 59void DefaultAudioDestinationNode::uninitialize()
 60{
 61 if (!isInitialized())
 62 return;
 63
 64 m_destination->stop();
 65
 66 AudioNode::uninitialize();
 67}
 68
 69void DefaultAudioDestinationNode::startRendering()
 70{
 71 ASSERT(isInitialized());
 72 if (isInitialized())
 73 m_destination->start();
 74}
 75
 76} // namespace WebCore
 77
 78#endif // ENABLE(WEB_AUDIO)
0

Source/WebCore/webaudio/DefaultAudioDestinationNode.h

 1/*
 2 * Copyright (C) 2011, 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
 25#ifndef DefaultAudioDestinationNode_h
 26#define DefaultAudioDestinationNode_h
 27
 28#include "AudioDestination.h"
 29#include "AudioDestinationNode.h"
 30#include <wtf/OwnPtr.h>
 31
 32namespace WebCore {
 33
 34class AudioContext;
 35
 36class DefaultAudioDestinationNode : public AudioDestinationNode {
 37public:
 38 static PassRefPtr<DefaultAudioDestinationNode> create(AudioContext* context)
 39 {
 40 return adoptRef(new DefaultAudioDestinationNode(context));
 41 }
 42
 43 virtual ~DefaultAudioDestinationNode();
 44
 45 // AudioNode
 46 virtual void initialize();
 47 virtual void uninitialize();
 48
 49 double sampleRate() const { return m_destination->sampleRate(); }
 50
 51 virtual void startRendering();
 52
 53private:
 54 DefaultAudioDestinationNode(AudioContext*);
 55
 56 OwnPtr<AudioDestination> m_destination;
 57};
 58
 59} // namespace WebCore
 60
 61#endif // DefaultAudioDestinationNode_h
0

Source/WebCore/webaudio/OfflineAudioCompletionEvent.cpp

 1/*
 2 * Copyright (C) 2011, 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
 25#include "config.h"
 26
 27#if ENABLE(WEB_AUDIO)
 28
 29#include "OfflineAudioCompletionEvent.h"
 30
 31#include "AudioBuffer.h"
 32#include "EventNames.h"
 33
 34namespace WebCore {
 35
 36PassRefPtr<OfflineAudioCompletionEvent> OfflineAudioCompletionEvent::create(PassRefPtr<AudioBuffer> renderedBuffer)
 37{
 38 return adoptRef(new OfflineAudioCompletionEvent(renderedBuffer));
 39}
 40
 41OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(PassRefPtr<AudioBuffer> renderedBuffer)
 42 : Event(eventNames().completeEvent, true, false)
 43 , m_renderedBuffer(renderedBuffer)
 44{
 45}
 46
 47OfflineAudioCompletionEvent::~OfflineAudioCompletionEvent()
 48{
 49}
 50
 51bool OfflineAudioCompletionEvent::isOfflineAudioCompletionEvent() const
 52{
 53 return true;
 54}
 55
 56} // namespace WebCore
 57
 58#endif // ENABLE(WEB_AUDIO)
0

Source/WebCore/webaudio/OfflineAudioCompletionEvent.h

 1/*
 2 * Copyright (C) 2011, 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
 25#ifndef OfflineAudioCompletionEvent_h
 26#define OfflineAudioCompletionEvent_h
 27
 28#include "AudioBuffer.h"
 29#include "Event.h"
 30#include <wtf/PassRefPtr.h>
 31#include <wtf/RefPtr.h>
 32
 33namespace WebCore {
 34
 35class AudioBuffer;
 36
 37class OfflineAudioCompletionEvent : public Event {
 38public:
 39 static PassRefPtr<OfflineAudioCompletionEvent> create(PassRefPtr<AudioBuffer> renderedBuffer);
 40
 41 virtual ~OfflineAudioCompletionEvent();
 42
 43 virtual bool isOfflineAudioCompletionEvent() const;
 44
 45 AudioBuffer* renderedBuffer() { return m_renderedBuffer.get(); }
 46
 47private:
 48 OfflineAudioCompletionEvent(PassRefPtr<AudioBuffer> renderedBuffer);
 49
 50 RefPtr<AudioBuffer> m_renderedBuffer;
 51};
 52
 53} // namespace WebCore
 54
 55#endif // OfflineAudioCompletionEvent_h
0

Source/WebCore/webaudio/OfflineAudioCompletionEvent.idl

 1/*
 2 * Copyright (C) 2011, 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
 25module audio {
 26 interface [
 27 Conditional=WEB_AUDIO,
 28 GenerateToJS
 29 ] OfflineAudioCompletionEvent : Event {
 30 readonly attribute AudioBuffer renderedBuffer;
 31 };
 32}
0

Source/WebCore/webaudio/OfflineAudioDestinationNode.cpp

 1/*
 2 * Copyright (C) 2011, 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
 25#include "config.h"
 26
 27#if ENABLE(WEB_AUDIO)
 28
 29#include "OfflineAudioDestinationNode.h"
 30
 31#include "AudioBus.h"
 32#include "AudioContext.h"
 33#include "HRTFDatabaseLoader.h"
 34#include <algorithm>
 35#include <wtf/Threading.h>
 36
 37using namespace std;
 38
 39namespace WebCore {
 40
 41const size_t renderQuantumSize = 128;
 42
 43OfflineAudioDestinationNode::OfflineAudioDestinationNode(AudioContext* context, AudioBuffer* renderTarget)
 44 : AudioDestinationNode(context, renderTarget->sampleRate())
 45 , m_renderTarget(renderTarget)
 46 , m_startedRendering(false)
 47{
 48 m_renderBus = adoptPtr(new AudioBus(renderTarget->numberOfChannels(), renderQuantumSize));
 49
 50 initialize();
 51}
 52
 53OfflineAudioDestinationNode::~OfflineAudioDestinationNode()
 54{
 55 uninitialize();
 56}
 57
 58void OfflineAudioDestinationNode::initialize()
 59{
 60 if (isInitialized())
 61 return;
 62
 63 AudioNode::initialize();
 64}
 65
 66void OfflineAudioDestinationNode::uninitialize()
 67{
 68 if (!isInitialized())
 69 return;
 70
 71 AudioNode::uninitialize();
 72}
 73
 74void OfflineAudioDestinationNode::startRendering()
 75{
 76 ASSERT(isMainThread());
 77 ASSERT(m_renderTarget.get());
 78 if (!m_renderTarget.get())
 79 return;
 80
 81 if (!m_startedRendering) {
 82 m_startedRendering = true;
 83 m_renderThread = createThread(OfflineAudioDestinationNode::renderEntry, this, "offline renderer");
 84 }
 85}
 86
 87// Do offline rendering in this thread.
 88void* OfflineAudioDestinationNode::renderEntry(void* threadData)
 89{
 90 OfflineAudioDestinationNode* destinationNode = reinterpret_cast<OfflineAudioDestinationNode*>(threadData);
 91 ASSERT(destinationNode);
 92 destinationNode->render();
 93
 94 return 0;
 95}
 96
 97void OfflineAudioDestinationNode::render()
 98{
 99 ASSERT(!isMainThread());
 100 ASSERT(m_renderBus.get());
 101 if (!m_renderBus.get())
 102 return;
 103
 104 bool channelsMatch = m_renderBus->numberOfChannels() == m_renderTarget->numberOfChannels();
 105 ASSERT(channelsMatch);
 106 if (!channelsMatch)
 107 return;
 108
 109 bool isRenderBusAllocated = m_renderBus->length() >= renderQuantumSize;
 110 ASSERT(isRenderBusAllocated);
 111 if (!isRenderBusAllocated)
 112 return;
 113
 114 // Synchronize with HRTFDatabaseLoader.
 115 // The database must be loaded before we can proceed.
 116 HRTFDatabaseLoader* loader = HRTFDatabaseLoader::loader();
 117 ASSERT(loader);
 118 if (!loader)
 119 return;
 120
 121 loader->waitForLoaderThreadCompletion();
 122
 123 // Break up the render target into smaller "render quantize" sized pieces.
 124 // Render until we're finished.
 125 size_t framesToProcess = m_renderTarget->length();
 126 unsigned numberOfChannels = m_renderTarget->numberOfChannels();
 127
 128 unsigned n = 0;
 129 while (framesToProcess > 0) {
 130 // Render one render quantum.
 131 provideInput(m_renderBus.get(), renderQuantumSize);
 132
 133 size_t framesAvailableToCopy = min(framesToProcess, renderQuantumSize);
 134
 135 for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
 136 float* source = m_renderBus->channel(channelIndex)->data();
 137 float* destination = m_renderTarget->getChannelData(channelIndex)->data();
 138 memcpy(destination + n, source, sizeof(float) * framesAvailableToCopy);
 139 }
 140
 141 n += framesAvailableToCopy;
 142 framesToProcess -= framesAvailableToCopy;
 143 }
 144
 145 // Our work is done. Let the AudioContext know.
 146 callOnMainThread(notifyCompleteDispatch, this);
 147}
 148
 149void OfflineAudioDestinationNode::notifyCompleteDispatch(void* userData)
 150{
 151 OfflineAudioDestinationNode* destinationNode = static_cast<OfflineAudioDestinationNode*>(userData);
 152 ASSERT(destinationNode);
 153 if (!destinationNode)
 154 return;
 155
 156 destinationNode->notifyComplete();
 157}
 158
 159void OfflineAudioDestinationNode::notifyComplete()
 160{
 161 context()->fireCompletionEvent();
 162}
 163
 164} // namespace WebCore
 165
 166#endif // ENABLE(WEB_AUDIO)
0

Source/WebCore/webaudio/OfflineAudioDestinationNode.h

 1/*
 2 * Copyright (C) 2011, 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
 25#ifndef OfflineAudioDestinationNode_h
 26#define OfflineAudioDestinationNode_h
 27
 28#include "AudioBuffer.h"
 29#include "AudioDestinationNode.h"
 30#include <wtf/PassRefPtr.h>
 31#include <wtf/RefPtr.h>
 32#include <wtf/Threading.h>
 33
 34namespace WebCore {
 35
 36class AudioBus;
 37class AudioContext;
 38
 39class OfflineAudioDestinationNode : public AudioDestinationNode {
 40public:
 41 static PassRefPtr<OfflineAudioDestinationNode> create(AudioContext* context, AudioBuffer* renderTarget)
 42 {
 43 return adoptRef(new OfflineAudioDestinationNode(context, renderTarget));
 44 }
 45
 46 virtual ~OfflineAudioDestinationNode();
 47
 48 // AudioNode
 49 virtual void initialize();
 50 virtual void uninitialize();
 51
 52 double sampleRate() const { return m_renderTarget->sampleRate(); }
 53
 54 void startRendering();
 55
 56private:
 57 OfflineAudioDestinationNode(AudioContext*, AudioBuffer* renderTarget);
 58
 59 // This AudioNode renders into this AudioBuffer.
 60 RefPtr<AudioBuffer> m_renderTarget;
 61
 62 // Temporary AudioBus for each render quantum.
 63 OwnPtr<AudioBus> m_renderBus;
 64
 65 // Rendering thread.
 66 ThreadIdentifier m_renderThread;
 67 bool m_startedRendering;
 68 static void* renderEntry(void* threadData);
 69 void render();
 70
 71 // For completion callback on main thread.
 72 static void notifyCompleteDispatch(void* userData);
 73 void notifyComplete();
 74};
 75
 76} // namespace WebCore
 77
 78#endif // OfflineAudioDestinationNode_h
0