| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 : ActiveDOMObject(document) | 104 : ActiveDOMObject(document) |
| 105 , m_isStopScheduled(false) | 105 , m_isStopScheduled(false) |
| 106 , m_isCleared(false) | 106 , m_isCleared(false) |
| 107 , m_isInitialized(false) | 107 , m_isInitialized(false) |
| 108 , m_destinationNode(nullptr) | 108 , m_destinationNode(nullptr) |
| 109 , m_isResolvingResumePromises(false) | 109 , m_isResolvingResumePromises(false) |
| 110 , m_automaticPullNodesNeedUpdating(false) | 110 , m_automaticPullNodesNeedUpdating(false) |
| 111 , m_connectionCount(0) | 111 , m_connectionCount(0) |
| 112 , m_didInitializeContextGraphMutex(false) | 112 , m_didInitializeContextGraphMutex(false) |
| 113 , m_audioThread(0) | 113 , m_audioThread(0) |
| 114 , m_lastZombie(nullptr) | |
| 115 , m_lastRemovableZombie(nullptr) | |
| 116 , m_isOfflineContext(false) | 114 , m_isOfflineContext(false) |
| 117 , m_contextState(Suspended) | 115 , m_contextState(Suspended) |
| 118 , m_cachedSampleFrame(0) | 116 , m_cachedSampleFrame(0) |
| 119 { | 117 { |
| 120 m_didInitializeContextGraphMutex = true; | 118 m_didInitializeContextGraphMutex = true; |
| 121 m_destinationNode = DefaultAudioDestinationNode::create(this); | 119 m_destinationNode = DefaultAudioDestinationNode::create(this); |
| 122 | 120 |
| 123 initialize(); | 121 initialize(); |
| 124 } | 122 } |
| 125 | 123 |
| 126 // Constructor for offline (non-realtime) rendering. | 124 // Constructor for offline (non-realtime) rendering. |
| 127 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t
numberOfFrames, float sampleRate) | 125 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t
numberOfFrames, float sampleRate) |
| 128 : ActiveDOMObject(document) | 126 : ActiveDOMObject(document) |
| 129 , m_isStopScheduled(false) | 127 , m_isStopScheduled(false) |
| 130 , m_isCleared(false) | 128 , m_isCleared(false) |
| 131 , m_isInitialized(false) | 129 , m_isInitialized(false) |
| 132 , m_destinationNode(nullptr) | 130 , m_destinationNode(nullptr) |
| 133 , m_isResolvingResumePromises(false) | 131 , m_isResolvingResumePromises(false) |
| 134 , m_automaticPullNodesNeedUpdating(false) | 132 , m_automaticPullNodesNeedUpdating(false) |
| 135 , m_connectionCount(0) | 133 , m_connectionCount(0) |
| 136 , m_didInitializeContextGraphMutex(false) | 134 , m_didInitializeContextGraphMutex(false) |
| 137 , m_audioThread(0) | 135 , m_audioThread(0) |
| 138 , m_lastZombie(nullptr) | |
| 139 , m_lastRemovableZombie(nullptr) | |
| 140 , m_isOfflineContext(true) | 136 , m_isOfflineContext(true) |
| 141 , m_contextState(Suspended) | 137 , m_contextState(Suspended) |
| 142 , m_cachedSampleFrame(0) | 138 , m_cachedSampleFrame(0) |
| 143 { | 139 { |
| 144 m_didInitializeContextGraphMutex = true; | 140 m_didInitializeContextGraphMutex = true; |
| 145 // Create a new destination for offline rendering. | 141 // Create a new destination for offline rendering. |
| 146 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl
eRate); | 142 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl
eRate); |
| 147 if (m_renderTarget.get()) | 143 if (m_renderTarget.get()) |
| 148 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa
rget.get()); | 144 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa
rget.get()); |
| 149 | 145 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 166 ASSERT(!m_suspendResolvers.size()); | 162 ASSERT(!m_suspendResolvers.size()); |
| 167 ASSERT(!m_isResolvingResumePromises); | 163 ASSERT(!m_isResolvingResumePromises); |
| 168 ASSERT(!m_resumeResolvers.size()); | 164 ASSERT(!m_resumeResolvers.size()); |
| 169 } | 165 } |
| 170 | 166 |
| 171 void AudioContext::initialize() | 167 void AudioContext::initialize() |
| 172 { | 168 { |
| 173 if (isInitialized()) | 169 if (isInitialized()) |
| 174 return; | 170 return; |
| 175 | 171 |
| 176 ThreadState::current()->addMarkingTask(this); | |
| 177 FFTFrame::initialize(); | 172 FFTFrame::initialize(); |
| 178 m_listener = AudioListener::create(); | 173 m_listener = AudioListener::create(); |
| 179 | 174 |
| 180 if (m_destinationNode.get()) { | 175 if (m_destinationNode.get()) { |
| 181 m_destinationNode->initialize(); | 176 m_destinationNode->initialize(); |
| 182 | 177 |
| 183 if (!isOfflineContext()) { | 178 if (!isOfflineContext()) { |
| 184 // This starts the audio thread. The destination node's provideInput
() method will now be called repeatedly to render audio. | 179 // This starts the audio thread. The destination node's provideInput
() method will now be called repeatedly to render audio. |
| 185 // Each time provideInput() is called, a portion of the audio stream
is rendered. Let's call this time period a "render quantum". | 180 // Each time provideInput() is called, a portion of the audio stream
is rendered. Let's call this time period a "render quantum". |
| 186 // NOTE: for now default AudioContext does not need an explicit star
tRendering() call from JavaScript. | 181 // NOTE: for now default AudioContext does not need an explicit star
tRendering() call from JavaScript. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 setContextState(Closed); | 232 setContextState(Closed); |
| 238 | 233 |
| 239 // Resolve the promise now, if any | 234 // Resolve the promise now, if any |
| 240 if (m_closeResolver) | 235 if (m_closeResolver) |
| 241 m_closeResolver->resolve(); | 236 m_closeResolver->resolve(); |
| 242 | 237 |
| 243 ASSERT(m_listener); | 238 ASSERT(m_listener); |
| 244 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); | 239 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); |
| 245 | 240 |
| 246 clear(); | 241 clear(); |
| 247 | |
| 248 ThreadState::current()->removeMarkingTask(this); | |
| 249 if (m_lastZombie) | |
| 250 ThreadState::current()->purifyZombies(); | |
| 251 m_lastZombie = nullptr; | |
| 252 m_lastRemovableZombie = nullptr; | |
| 253 } | 242 } |
| 254 | 243 |
| 255 void AudioContext::stop() | 244 void AudioContext::stop() |
| 256 { | 245 { |
| 257 // Usually ExecutionContext calls stop twice. | 246 // Usually ExecutionContext calls stop twice. |
| 258 if (m_isStopScheduled) | 247 if (m_isStopScheduled) |
| 259 return; | 248 return; |
| 260 m_isStopScheduled = true; | 249 m_isStopScheduled = true; |
| 261 | 250 |
| 262 // Don't call uninitialize() immediately here because the ExecutionContext i
s in the middle | 251 // Don't call uninitialize() immediately here because the ExecutionContext i
s in the middle |
| (...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 if (tryLock()) { | 978 if (tryLock()) { |
| 990 // Update the channel count mode. | 979 // Update the channel count mode. |
| 991 updateChangedChannelCountMode(); | 980 updateChangedChannelCountMode(); |
| 992 | 981 |
| 993 // Take care of AudioNode tasks where the tryLock() failed previously. | 982 // Take care of AudioNode tasks where the tryLock() failed previously. |
| 994 handleDeferredAudioNodeTasks(); | 983 handleDeferredAudioNodeTasks(); |
| 995 | 984 |
| 996 // Dynamically clean up nodes which are no longer needed. | 985 // Dynamically clean up nodes which are no longer needed. |
| 997 derefFinishedSourceNodes(); | 986 derefFinishedSourceNodes(); |
| 998 | 987 |
| 999 m_lastRemovableZombie = m_lastZombie; | |
| 1000 | |
| 1001 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. | 988 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu
ts. |
| 1002 handleDirtyAudioSummingJunctions(); | 989 handleDirtyAudioSummingJunctions(); |
| 1003 handleDirtyAudioNodeOutputs(); | 990 handleDirtyAudioNodeOutputs(); |
| 1004 | 991 |
| 1005 updateAutomaticPullNodes(); | 992 updateAutomaticPullNodes(); |
| 1006 resolvePromisesForSuspend(); | 993 resolvePromisesForSuspend(); |
| 1007 | 994 |
| 1008 unlock(); | 995 unlock(); |
| 1009 } | 996 } |
| 1010 } | 997 } |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 } | 1274 } |
| 1288 } | 1275 } |
| 1289 | 1276 |
| 1290 DEFINE_TRACE(AudioContext) | 1277 DEFINE_TRACE(AudioContext) |
| 1291 { | 1278 { |
| 1292 visitor->trace(m_closeResolver); | 1279 visitor->trace(m_closeResolver); |
| 1293 visitor->trace(m_offlineResolver); | 1280 visitor->trace(m_offlineResolver); |
| 1294 visitor->trace(m_renderTarget); | 1281 visitor->trace(m_renderTarget); |
| 1295 visitor->trace(m_destinationNode); | 1282 visitor->trace(m_destinationNode); |
| 1296 visitor->trace(m_listener); | 1283 visitor->trace(m_listener); |
| 1297 visitor->trace(m_referencedNodes); | 1284 // trace() can be called in AudioContext constructor, and |
| 1285 // m_contextGraphMutex might be unavailable. |
| 1286 if (m_didInitializeContextGraphMutex) { |
| 1287 AutoLocker lock(this); |
| 1288 visitor->trace(m_referencedNodes); |
| 1289 } else { |
| 1290 visitor->trace(m_referencedNodes); |
| 1291 } |
| 1298 visitor->trace(m_resumeResolvers); | 1292 visitor->trace(m_resumeResolvers); |
| 1299 visitor->trace(m_suspendResolvers); | 1293 visitor->trace(m_suspendResolvers); |
| 1300 visitor->trace(m_liveNodes); | 1294 visitor->trace(m_liveNodes); |
| 1301 visitor->trace(m_liveAudioSummingJunctions); | 1295 visitor->trace(m_liveAudioSummingJunctions); |
| 1302 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis
itor); | 1296 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis
itor); |
| 1303 ActiveDOMObject::trace(visitor); | 1297 ActiveDOMObject::trace(visitor); |
| 1304 } | 1298 } |
| 1305 | 1299 |
| 1306 void AudioContext::addChangedChannelCountMode(AudioNode* node) | 1300 void AudioContext::addChangedChannelCountMode(AudioNode* node) |
| 1307 { | 1301 { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 | 1358 |
| 1365 // Stop the audio context. This will stop the destination node from pulling
audio anymore. And | 1359 // Stop the audio context. This will stop the destination node from pulling
audio anymore. And |
| 1366 // since we have disconnected the destination from the audio graph, and thus
has no references, | 1360 // since we have disconnected the destination from the audio graph, and thus
has no references, |
| 1367 // the destination node can GCed if JS has no references. stop() will also r
esolve the Promise | 1361 // the destination node can GCed if JS has no references. stop() will also r
esolve the Promise |
| 1368 // created here. | 1362 // created here. |
| 1369 stop(); | 1363 stop(); |
| 1370 | 1364 |
| 1371 return promise; | 1365 return promise; |
| 1372 } | 1366 } |
| 1373 | 1367 |
| 1374 void AudioContext::setLastZombie(void* object) | |
| 1375 { | |
| 1376 ASSERT(isGraphOwner()); | |
| 1377 m_lastZombie = object; | |
| 1378 } | |
| 1379 | |
| 1380 void AudioContext::willStartMarking(ThreadState& threadState) | |
| 1381 { | |
| 1382 lock(); | |
| 1383 if (!m_lastRemovableZombie) | |
| 1384 return; | |
| 1385 if (m_lastZombie != m_lastRemovableZombie) | |
| 1386 return; | |
| 1387 threadState.purifyZombies(); | |
| 1388 m_lastZombie = nullptr; | |
| 1389 m_lastRemovableZombie = nullptr; | |
| 1390 } | |
| 1391 | |
| 1392 void AudioContext::didFinishMarking(ThreadState&) | |
| 1393 { | |
| 1394 unlock(); | |
| 1395 } | |
| 1396 | |
| 1397 } // namespace blink | 1368 } // namespace blink |
| 1398 | 1369 |
| 1399 #endif // ENABLE(WEB_AUDIO) | 1370 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |