OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/webaudio/AudioContext.h" | 5 #include "modules/webaudio/AudioContext.h" |
6 | 6 |
7 #include "bindings/core/v8/ExceptionMessages.h" | 7 #include "bindings/core/v8/ExceptionMessages.h" |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
10 #include "core/dom/DOMException.h" | 10 #include "core/dom/DOMException.h" |
11 #include "core/dom/ExceptionCode.h" | 11 #include "core/dom/ExceptionCode.h" |
| 12 #include "core/frame/LocalDOMWindow.h" |
| 13 #include "core/timing/DOMWindowPerformance.h" |
| 14 #include "core/timing/Performance.h" |
12 #include "modules/webaudio/AudioBufferCallback.h" | 15 #include "modules/webaudio/AudioBufferCallback.h" |
| 16 #include "modules/webaudio/AudioTimestamp.h" |
13 #include "platform/Histogram.h" | 17 #include "platform/Histogram.h" |
14 #include "platform/audio/AudioUtilities.h" | 18 #include "platform/audio/AudioUtilities.h" |
15 | 19 |
16 #if DEBUG_AUDIONODE_REFERENCES | 20 #if DEBUG_AUDIONODE_REFERENCES |
17 #include <stdio.h> | 21 #include <stdio.h> |
18 #endif | 22 #endif |
19 | 23 |
20 namespace blink { | 24 namespace blink { |
21 | 25 |
22 // Don't allow more than this number of simultaneous AudioContexts | 26 // Don't allow more than this number of simultaneous AudioContexts |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 ("WebAudio.AudioContext.HardwareSampleRate")); | 77 ("WebAudio.AudioContext.HardwareSampleRate")); |
74 maxChannelCountHistogram.sample(audioContext->destination()->maxChannelCount
()); | 78 maxChannelCountHistogram.sample(audioContext->destination()->maxChannelCount
()); |
75 sampleRateHistogram.sample(audioContext->sampleRate()); | 79 sampleRateHistogram.sample(audioContext->sampleRate()); |
76 | 80 |
77 return audioContext; | 81 return audioContext; |
78 } | 82 } |
79 | 83 |
80 AudioContext::AudioContext(Document& document) | 84 AudioContext::AudioContext(Document& document) |
81 : AbstractAudioContext(&document) | 85 : AbstractAudioContext(&document) |
82 , m_contextId(s_contextId++) | 86 , m_contextId(s_contextId++) |
| 87 , m_outputTimestampFramesOrigin(0) |
83 { | 88 { |
84 } | 89 } |
85 | 90 |
86 AudioContext::~AudioContext() | 91 AudioContext::~AudioContext() |
87 { | 92 { |
88 #if DEBUG_AUDIONODE_REFERENCES | 93 #if DEBUG_AUDIONODE_REFERENCES |
89 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); | 94 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId
); |
90 #endif | 95 #endif |
91 } | 96 } |
92 | 97 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 InvalidAccessError, | 136 InvalidAccessError, |
132 "cannot resume a closed AudioContext")); | 137 "cannot resume a closed AudioContext")); |
133 } | 138 } |
134 | 139 |
135 recordUserGestureState(); | 140 recordUserGestureState(); |
136 | 141 |
137 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 142 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
138 ScriptPromise promise = resolver->promise(); | 143 ScriptPromise promise = resolver->promise(); |
139 | 144 |
140 // Restart the destination node to pull on the audio graph. | 145 // Restart the destination node to pull on the audio graph. |
141 if (destination()) | 146 if (destination()) { |
| 147 m_outputTimestampFramesOrigin = currentSampleFrame(); |
142 startRendering(); | 148 startRendering(); |
| 149 } |
143 | 150 |
144 // Save the resolver which will get resolved when the destination node start
s pulling on the | 151 // Save the resolver which will get resolved when the destination node start
s pulling on the |
145 // graph again. | 152 // graph again. |
146 { | 153 { |
147 AutoLocker locker(this); | 154 AutoLocker locker(this); |
148 m_resumeResolvers.append(resolver); | 155 m_resumeResolvers.append(resolver); |
149 } | 156 } |
150 | 157 |
151 return promise; | 158 return promise; |
152 } | 159 } |
153 | 160 |
| 161 static double toPerformanceTime(ExecutionContext* context, double seconds) |
| 162 { |
| 163 if (!context) |
| 164 return 0.0; |
| 165 |
| 166 LocalDOMWindow* window = context->executingWindow(); |
| 167 if (!window) |
| 168 return 0.0; |
| 169 |
| 170 Performance* performance = DOMWindowPerformance::performance(*window); |
| 171 if (!performance) |
| 172 return 0.0; |
| 173 |
| 174 return performance->monotonicTimeToDOMHighResTimeStamp(seconds); |
| 175 } |
| 176 |
| 177 void AudioContext::getOutputTimestamp(AudioTimestamp& result) |
| 178 { |
| 179 DCHECK(isMainThread()); |
| 180 if (!destination()) { |
| 181 result.setContextTime(0.0); |
| 182 result.setPerformanceTime(0.0); |
| 183 return; |
| 184 } |
| 185 |
| 186 WebAudioTimestamp timestamp = outputTimestamp(); |
| 187 double sampleRate = destination()->audioDestinationHandler().sampleRate(); |
| 188 double contextTime = (m_outputTimestampFramesOrigin + timestamp.frames) / sa
mpleRate; |
| 189 double performanceTime = timestamp.seconds ? toPerformanceTime(getExecutionC
ontext(), timestamp.seconds) : 0.0; |
| 190 |
| 191 result.setContextTime(contextTime); |
| 192 result.setPerformanceTime(performanceTime); |
| 193 } |
| 194 |
154 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) | 195 ScriptPromise AudioContext::closeContext(ScriptState* scriptState) |
155 { | 196 { |
156 if (isContextClosed()) { | 197 if (isContextClosed()) { |
157 // We've already closed the context previously, but it hasn't yet been r
esolved, so just | 198 // We've already closed the context previously, but it hasn't yet been r
esolved, so just |
158 // create a new promise and reject it. | 199 // create a new promise and reject it. |
159 return ScriptPromise::rejectWithDOMException( | 200 return ScriptPromise::rejectWithDOMException( |
160 scriptState, | 201 scriptState, |
161 DOMException::create(InvalidStateError, | 202 DOMException::create(InvalidStateError, |
162 "Cannot close a context that is being closed or has already been
closed.")); | 203 "Cannot close a context that is being closed or has already been
closed.")); |
163 } | 204 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 ASSERT(destination()); | 242 ASSERT(destination()); |
202 | 243 |
203 if (contextState() == Running) { | 244 if (contextState() == Running) { |
204 destination()->audioDestinationHandler().stopRendering(); | 245 destination()->audioDestinationHandler().stopRendering(); |
205 setContextState(Suspended); | 246 setContextState(Suspended); |
206 deferredTaskHandler().clearHandlersToBeDeleted(); | 247 deferredTaskHandler().clearHandlersToBeDeleted(); |
207 } | 248 } |
208 } | 249 } |
209 | 250 |
210 } // namespace blink | 251 } // namespace blink |
OLD | NEW |