Chromium Code Reviews| 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 12 matching lines...) Expand all Loading... | |
| 23 */ | 23 */ |
| 24 | 24 |
| 25 #include "config.h" | 25 #include "config.h" |
| 26 | 26 |
| 27 #if ENABLE(WEB_AUDIO) | 27 #if ENABLE(WEB_AUDIO) |
| 28 | 28 |
| 29 #include "modules/webaudio/AudioContext.h" | 29 #include "modules/webaudio/AudioContext.h" |
| 30 | 30 |
| 31 #include "bindings/core/v8/ExceptionMessages.h" | 31 #include "bindings/core/v8/ExceptionMessages.h" |
| 32 #include "bindings/core/v8/ExceptionState.h" | 32 #include "bindings/core/v8/ExceptionState.h" |
| 33 #include "bindings/core/v8/ScriptState.h" | |
| 33 #include "core/dom/Document.h" | 34 #include "core/dom/Document.h" |
| 34 #include "core/dom/ExceptionCode.h" | 35 #include "core/dom/ExceptionCode.h" |
| 35 #include "core/html/HTMLMediaElement.h" | 36 #include "core/html/HTMLMediaElement.h" |
| 36 #include "core/inspector/ScriptCallStack.h" | 37 #include "core/inspector/ScriptCallStack.h" |
| 37 #include "platform/audio/FFTFrame.h" | 38 #include "platform/audio/FFTFrame.h" |
| 38 #include "platform/audio/HRTFPanner.h" | 39 #include "platform/audio/HRTFPanner.h" |
| 39 #include "modules/mediastream/MediaStream.h" | 40 #include "modules/mediastream/MediaStream.h" |
| 40 #include "modules/webaudio/AnalyserNode.h" | 41 #include "modules/webaudio/AnalyserNode.h" |
| 41 #include "modules/webaudio/AudioBuffer.h" | 42 #include "modules/webaudio/AudioBuffer.h" |
| 42 #include "modules/webaudio/AudioBufferCallback.h" | 43 #include "modules/webaudio/AudioBufferCallback.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 return audioContext; | 95 return audioContext; |
| 95 } | 96 } |
| 96 | 97 |
| 97 // Constructor for rendering to the audio hardware. | 98 // Constructor for rendering to the audio hardware. |
| 98 AudioContext::AudioContext(Document* document) | 99 AudioContext::AudioContext(Document* document) |
| 99 : ActiveDOMObject(document) | 100 : ActiveDOMObject(document) |
| 100 , m_isStopScheduled(false) | 101 , m_isStopScheduled(false) |
| 101 , m_isCleared(false) | 102 , m_isCleared(false) |
| 102 , m_isInitialized(false) | 103 , m_isInitialized(false) |
| 103 , m_destinationNode(nullptr) | 104 , m_destinationNode(nullptr) |
| 105 , m_isResolvingResumePromises(false) | |
| 104 , m_automaticPullNodesNeedUpdating(false) | 106 , m_automaticPullNodesNeedUpdating(false) |
| 105 , m_connectionCount(0) | 107 , m_connectionCount(0) |
| 106 , m_audioThread(0) | 108 , m_audioThread(0) |
| 107 , m_isOfflineContext(false) | 109 , m_isOfflineContext(false) |
| 108 { | 110 { |
| 109 m_destinationNode = DefaultAudioDestinationNode::create(this); | 111 m_destinationNode = DefaultAudioDestinationNode::create(this); |
| 110 | 112 |
| 111 initialize(); | 113 initialize(); |
| 112 #if DEBUG_AUDIONODE_REFERENCES | 114 #if DEBUG_AUDIONODE_REFERENCES |
| 113 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext ::s_hardwareContextCount); | 115 fprintf(stderr, "%p: AudioContext::AudioContext() #%u\n", this, AudioContext ::s_hardwareContextCount); |
| 114 #endif | 116 #endif |
| 115 } | 117 } |
| 116 | 118 |
| 117 // Constructor for offline (non-realtime) rendering. | 119 // Constructor for offline (non-realtime) rendering. |
| 118 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) | 120 AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, float sampleRate) |
| 119 : ActiveDOMObject(document) | 121 : ActiveDOMObject(document) |
| 120 , m_isStopScheduled(false) | 122 , m_isStopScheduled(false) |
| 121 , m_isCleared(false) | 123 , m_isCleared(false) |
| 122 , m_isInitialized(false) | 124 , m_isInitialized(false) |
| 123 , m_destinationNode(nullptr) | 125 , m_destinationNode(nullptr) |
| 126 , m_isResolvingResumePromises(false) | |
| 124 , m_automaticPullNodesNeedUpdating(false) | 127 , m_automaticPullNodesNeedUpdating(false) |
| 125 , m_connectionCount(0) | 128 , m_connectionCount(0) |
| 126 , m_audioThread(0) | 129 , m_audioThread(0) |
| 127 , m_isOfflineContext(true) | 130 , m_isOfflineContext(true) |
| 128 { | 131 { |
| 129 // Create a new destination for offline rendering. | 132 // Create a new destination for offline rendering. |
| 130 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); | 133 m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampl eRate); |
| 131 if (m_renderTarget.get()) | 134 if (m_renderTarget.get()) |
| 132 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); | 135 m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTa rget.get()); |
| 133 | 136 |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 exceptionState.throwDOMException( | 527 exceptionState.throwDOMException( |
| 525 IndexSizeError, | 528 IndexSizeError, |
| 526 "length of imaginary array (" + String::number(imag->length()) | 529 "length of imaginary array (" + String::number(imag->length()) |
| 527 + ") exceeds allowed maximum of 4096"); | 530 + ") exceeds allowed maximum of 4096"); |
| 528 return 0; | 531 return 0; |
| 529 } | 532 } |
| 530 | 533 |
| 531 return PeriodicWave::create(sampleRate(), real, imag); | 534 return PeriodicWave::create(sampleRate(), real, imag); |
| 532 } | 535 } |
| 533 | 536 |
| 537 void AudioContext::suspendContext() | |
| 538 { | |
| 539 ASSERT(isMainThread()); | |
| 540 AutoLocker locker(this); | |
| 541 | |
| 542 if (m_destinationNode && !isOfflineContext()) | |
| 543 m_destinationNode->stop(); | |
| 544 } | |
| 545 | |
| 546 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState) | |
| 547 { | |
| 548 ASSERT(isMainThread()); | |
| 549 AutoLocker locker(this); | |
| 550 | |
| 551 RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scrip tState); | |
| 552 | |
| 553 ScriptPromise promise = resolver->promise(); | |
| 554 | |
| 555 if (isOfflineContext()) { | |
| 556 // For offline context, just resolve the promise now. | |
| 557 resolver->resolve(); | |
| 558 } else { | |
| 559 // Restart the destination node to pull on the audio graph. | |
| 560 if (m_destinationNode) | |
| 561 m_destinationNode->startRendering(); | |
| 562 | |
| 563 // Save the promise which will get resolved when the destination node st arts pulling on the | |
| 564 // graph again. | |
| 565 m_resumePromises.append(resolver); | |
| 566 } | |
| 567 | |
| 568 return promise; | |
| 569 } | |
| 570 | |
| 534 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) | 571 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) |
| 535 { | 572 { |
| 536 ASSERT(isAudioThread()); | 573 ASSERT(isAudioThread()); |
| 537 m_finishedNodes.append(node); | 574 m_finishedNodes.append(node); |
| 538 } | 575 } |
| 539 | 576 |
| 540 void AudioContext::derefFinishedSourceNodes() | 577 void AudioContext::derefFinishedSourceNodes() |
| 541 { | 578 { |
| 542 ASSERT(isGraphOwner()); | 579 ASSERT(isGraphOwner()); |
| 543 ASSERT(isAudioThread()); | 580 ASSERT(isAudioThread()); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes. | 667 // It's OK if the tryLock() fails, we'll just take slightly longer to pick u p the changes. |
| 631 if (tryLock()) { | 668 if (tryLock()) { |
| 632 // Update the channel count mode. | 669 // Update the channel count mode. |
| 633 updateChangedChannelCountMode(); | 670 updateChangedChannelCountMode(); |
| 634 | 671 |
| 635 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts. | 672 // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutpu ts. |
| 636 handleDirtyAudioSummingJunctions(); | 673 handleDirtyAudioSummingJunctions(); |
| 637 handleDirtyAudioNodeOutputs(); | 674 handleDirtyAudioNodeOutputs(); |
| 638 | 675 |
| 639 updateAutomaticPullNodes(); | 676 updateAutomaticPullNodes(); |
| 677 resolvePromisesForResume(); | |
| 678 | |
| 640 unlock(); | 679 unlock(); |
| 641 } | 680 } |
| 642 } | 681 } |
| 643 | 682 |
| 644 void AudioContext::handlePostRenderTasks() | 683 void AudioContext::handlePostRenderTasks() |
| 645 { | 684 { |
| 646 ASSERT(isAudioThread()); | 685 ASSERT(isAudioThread()); |
| 647 | 686 |
| 648 // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. | 687 // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently. |
| 649 // The worst that can happen is that there will be some nodes which will tak e slightly longer than usual to be deleted or removed | 688 // The worst that can happen is that there will be some nodes which will tak e slightly longer than usual to be deleted or removed |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 } | 834 } |
| 796 | 835 |
| 797 void AudioContext::processAutomaticPullNodes(size_t framesToProcess) | 836 void AudioContext::processAutomaticPullNodes(size_t framesToProcess) |
| 798 { | 837 { |
| 799 ASSERT(isAudioThread()); | 838 ASSERT(isAudioThread()); |
| 800 | 839 |
| 801 for (unsigned i = 0; i < m_renderingAutomaticPullNodes.size(); ++i) | 840 for (unsigned i = 0; i < m_renderingAutomaticPullNodes.size(); ++i) |
| 802 m_renderingAutomaticPullNodes[i]->processIfNecessary(framesToProcess); | 841 m_renderingAutomaticPullNodes[i]->processIfNecessary(framesToProcess); |
| 803 } | 842 } |
| 804 | 843 |
| 844 void AudioContext::resolvePromisesForResumeOnMainThread() | |
| 845 { | |
| 846 ASSERT(isMainThread); | |
|
yhirano
2014/10/08 01:12:14
Please acquire the lock.
yhirano
2014/10/08 01:15:54
Oh, I found AudioContext::lock is not callable fro
Raymond Toy
2014/10/14 17:16:59
Done.
| |
| 847 | |
| 848 for (unsigned k = 0; k < m_resumePromises.size(); ++k) | |
| 849 m_resumePromises[k]->resolve(); | |
| 850 | |
| 851 m_resumePromises.clear(); | |
| 852 m_isResolvingResumePromises = false; | |
| 853 } | |
| 854 | |
| 855 void AudioContext::resolvePromisesForResume() | |
| 856 { | |
| 857 ASSERT(isAudioThread()); | |
| 858 | |
|
yhirano
2014/10/08 01:12:14
Please add a comment that the lock is already acqu
Raymond Toy
2014/10/14 17:16:59
Done.
| |
| 859 // Resolve any pending promises created by resume(). Only do this we if have n't already started | |
| 860 // resolving these promises. This gets called very often and it takes some t ime use to resolve | |
| 861 // the promises in the main thread. | |
| 862 if (!m_isResolvingResumePromises && m_resumePromises.size() > 0) { | |
| 863 m_isResolvingResumePromises = true; | |
| 864 callOnMainThread(bind(&AudioContext::resolvePromisesForResumeOnMainThrea d, this)); | |
| 865 } | |
| 866 } | |
| 867 | |
| 805 const AtomicString& AudioContext::interfaceName() const | 868 const AtomicString& AudioContext::interfaceName() const |
| 806 { | 869 { |
| 807 return EventTargetNames::AudioContext; | 870 return EventTargetNames::AudioContext; |
| 808 } | 871 } |
| 809 | 872 |
| 810 ExecutionContext* AudioContext::executionContext() const | 873 ExecutionContext* AudioContext::executionContext() const |
| 811 { | 874 { |
| 812 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext(); | 875 return m_isStopScheduled ? 0 : ActiveDOMObject::executionContext(); |
| 813 } | 876 } |
| 814 | 877 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 867 | 930 |
| 868 for (HashSet<AudioNode*>::iterator k = m_deferredCountModeChange.begin(); k != m_deferredCountModeChange.end(); ++k) | 931 for (HashSet<AudioNode*>::iterator k = m_deferredCountModeChange.begin(); k != m_deferredCountModeChange.end(); ++k) |
| 869 (*k)->updateChannelCountMode(); | 932 (*k)->updateChannelCountMode(); |
| 870 | 933 |
| 871 m_deferredCountModeChange.clear(); | 934 m_deferredCountModeChange.clear(); |
| 872 } | 935 } |
| 873 | 936 |
| 874 } // namespace blink | 937 } // namespace blink |
| 875 | 938 |
| 876 #endif // ENABLE(WEB_AUDIO) | 939 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |