| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012, Google Inc. All rights reserved. | 2 * Copyright (C) 2012, 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 23 matching lines...) Expand all Loading... |
| 34 #include "platform/audio/AudioUtilities.h" | 34 #include "platform/audio/AudioUtilities.h" |
| 35 #include "wtf/MathExtras.h" | 35 #include "wtf/MathExtras.h" |
| 36 #include <algorithm> | 36 #include <algorithm> |
| 37 | 37 |
| 38 namespace blink { | 38 namespace blink { |
| 39 | 39 |
| 40 const double AudioScheduledSourceHandler::UnknownTime = -1; | 40 const double AudioScheduledSourceHandler::UnknownTime = -1; |
| 41 | 41 |
| 42 AudioScheduledSourceHandler::AudioScheduledSourceHandler(NodeType nodeType, Audi
oNode& node, float sampleRate) | 42 AudioScheduledSourceHandler::AudioScheduledSourceHandler(NodeType nodeType, Audi
oNode& node, float sampleRate) |
| 43 : AudioHandler(nodeType, node, sampleRate) | 43 : AudioHandler(nodeType, node, sampleRate) |
| 44 , m_hasEndedListener(false) |
| 44 , m_startTime(0) | 45 , m_startTime(0) |
| 45 , m_endTime(UnknownTime) | 46 , m_endTime(UnknownTime) |
| 46 , m_hasEndedListener(false) | |
| 47 , m_playbackState(UNSCHEDULED_STATE) | 47 , m_playbackState(UNSCHEDULED_STATE) |
| 48 { | 48 { |
| 49 } | 49 } |
| 50 | 50 |
| 51 void AudioScheduledSourceHandler::updateSchedulingInfo( | 51 void AudioScheduledSourceHandler::updateSchedulingInfo( |
| 52 size_t quantumFrameSize, AudioBus* outputBus, size_t& quantumFrameOffset, si
ze_t& nonSilentFramesToProcess) | 52 size_t quantumFrameSize, AudioBus* outputBus, size_t& quantumFrameOffset, si
ze_t& nonSilentFramesToProcess) |
| 53 { | 53 { |
| 54 ASSERT(outputBus); | 54 ASSERT(outputBus); |
| 55 if (!outputBus) | 55 if (!outputBus) |
| 56 return; | 56 return; |
| 57 | 57 |
| 58 ASSERT(quantumFrameSize == ProcessingSizeInFrames); | 58 ASSERT(quantumFrameSize == ProcessingSizeInFrames); |
| 59 if (quantumFrameSize != ProcessingSizeInFrames) | 59 if (quantumFrameSize != ProcessingSizeInFrames) |
| 60 return; | 60 return; |
| 61 | 61 |
| 62 double sampleRate = this->sampleRate(); | 62 double sampleRate = this->sampleRate(); |
| 63 | 63 |
| 64 // quantumStartFrame : Start frame of the current time quantum. | 64 // quantumStartFrame : Start frame of the current time quantum. |
| 65 // quantumEndFrame : End frame of the current time quantum. | 65 // quantumEndFrame : End frame of the current time quantum. |
| 66 // startFrame : Start frame for this source. | 66 // startFrame : Start frame for this source. |
| 67 // endFrame : End frame for this source. | 67 // endFrame : End frame for this source. |
| 68 size_t quantumStartFrame = context()->currentSampleFrame(); | 68 size_t quantumStartFrame = context()->currentSampleFrame(); |
| 69 size_t quantumEndFrame = quantumStartFrame + quantumFrameSize; | 69 size_t quantumEndFrame = quantumStartFrame + quantumFrameSize; |
| 70 size_t startFrame = AudioUtilities::timeToSampleFrame(m_startTime, sampleRat
e); | 70 size_t startFrame = AudioUtilities::timeToSampleFrame(startTime(), sampleRat
e); |
| 71 size_t endFrame = m_endTime == UnknownTime ? 0 : AudioUtilities::timeToSampl
eFrame(m_endTime, sampleRate); | 71 double currentEndTime = endTime(); |
| 72 size_t endFrame = currentEndTime == UnknownTime ? 0 : AudioUtilities::timeTo
SampleFrame(currentEndTime, sampleRate); |
| 72 | 73 |
| 73 // If we know the end time and it's already passed, then don't bother doing
any more rendering this cycle. | 74 // If we know the end time and it's already passed, then don't bother doing
any more rendering this cycle. |
| 74 if (m_endTime != UnknownTime && endFrame <= quantumStartFrame) | 75 if (currentEndTime != UnknownTime && endFrame <= quantumStartFrame) |
| 75 finish(); | 76 finish(); |
| 76 | 77 |
| 77 PlaybackState state = playbackState(); | 78 PlaybackState state = playbackState(); |
| 78 | 79 |
| 79 if (state == UNSCHEDULED_STATE || state == FINISHED_STATE || startFrame >= q
uantumEndFrame) { | 80 if (state == UNSCHEDULED_STATE || state == FINISHED_STATE || startFrame >= q
uantumEndFrame) { |
| 80 // Output silence. | 81 // Output silence. |
| 81 outputBus->zero(); | 82 outputBus->zero(); |
| 82 nonSilentFramesToProcess = 0; | 83 nonSilentFramesToProcess = 0; |
| 83 return; | 84 return; |
| 84 } | 85 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 102 // Handle silence before we start playing. | 103 // Handle silence before we start playing. |
| 103 // Zero any initial frames representing silence leading up to a rendering st
art time in the middle of the quantum. | 104 // Zero any initial frames representing silence leading up to a rendering st
art time in the middle of the quantum. |
| 104 if (quantumFrameOffset) { | 105 if (quantumFrameOffset) { |
| 105 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) | 106 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) |
| 106 memset(outputBus->channel(i)->mutableData(), 0, sizeof(float) * quan
tumFrameOffset); | 107 memset(outputBus->channel(i)->mutableData(), 0, sizeof(float) * quan
tumFrameOffset); |
| 107 } | 108 } |
| 108 | 109 |
| 109 // Handle silence after we're done playing. | 110 // Handle silence after we're done playing. |
| 110 // If the end time is somewhere in the middle of this time quantum, then zer
o out the | 111 // If the end time is somewhere in the middle of this time quantum, then zer
o out the |
| 111 // frames from the end time to the very end of the quantum. | 112 // frames from the end time to the very end of the quantum. |
| 112 if (m_endTime != UnknownTime && endFrame >= quantumStartFrame && endFrame <
quantumEndFrame) { | 113 if (currentEndTime != UnknownTime && endFrame >= quantumStartFrame && endFra
me < quantumEndFrame) { |
| 113 size_t zeroStartFrame = endFrame - quantumStartFrame; | 114 size_t zeroStartFrame = endFrame - quantumStartFrame; |
| 114 size_t framesToZero = quantumFrameSize - zeroStartFrame; | 115 size_t framesToZero = quantumFrameSize - zeroStartFrame; |
| 115 | 116 |
| 116 bool isSafe = zeroStartFrame < quantumFrameSize && framesToZero <= quant
umFrameSize && zeroStartFrame + framesToZero <= quantumFrameSize; | 117 bool isSafe = zeroStartFrame < quantumFrameSize && framesToZero <= quant
umFrameSize && zeroStartFrame + framesToZero <= quantumFrameSize; |
| 117 ASSERT(isSafe); | 118 ASSERT(isSafe); |
| 118 | 119 |
| 119 if (isSafe) { | 120 if (isSafe) { |
| 120 if (framesToZero > nonSilentFramesToProcess) | 121 if (framesToZero > nonSilentFramesToProcess) |
| 121 nonSilentFramesToProcess = 0; | 122 nonSilentFramesToProcess = 0; |
| 122 else | 123 else |
| (...skipping 30 matching lines...) Expand all Loading... |
| 153 return; | 154 return; |
| 154 } | 155 } |
| 155 | 156 |
| 156 // The node is started. Add a reference to keep us alive so that audio will
eventually get | 157 // The node is started. Add a reference to keep us alive so that audio will
eventually get |
| 157 // played even if Javascript should drop all references to this node. The re
ference will get | 158 // played even if Javascript should drop all references to this node. The re
ference will get |
| 158 // dropped when the source has finished playing. | 159 // dropped when the source has finished playing. |
| 159 context()->notifySourceNodeStartedProcessing(node()); | 160 context()->notifySourceNodeStartedProcessing(node()); |
| 160 | 161 |
| 161 // If |when| < currentTime, the source must start now according to the spec. | 162 // If |when| < currentTime, the source must start now according to the spec. |
| 162 // So just set startTime to currentTime in this case to start the source now
. | 163 // So just set startTime to currentTime in this case to start the source now
. |
| 163 m_startTime = std::max(when, context()->currentTime()); | 164 setStartTime(std::max(when, context()->currentTime())); |
| 164 | 165 |
| 165 setPlaybackState(SCHEDULED_STATE); | 166 setPlaybackState(SCHEDULED_STATE); |
| 166 } | 167 } |
| 167 | 168 |
| 168 void AudioScheduledSourceHandler::stop(double when, ExceptionState& exceptionSta
te) | 169 void AudioScheduledSourceHandler::stop(double when, ExceptionState& exceptionSta
te) |
| 169 { | 170 { |
| 170 ASSERT(isMainThread()); | 171 ASSERT(isMainThread()); |
| 171 | 172 |
| 172 if (playbackState() == UNSCHEDULED_STATE) { | 173 if (playbackState() == UNSCHEDULED_STATE) { |
| 173 exceptionState.throwDOMException( | 174 exceptionState.throwDOMException( |
| 174 InvalidStateError, | 175 InvalidStateError, |
| 175 "cannot call stop without calling start first."); | 176 "cannot call stop without calling start first."); |
| 176 return; | 177 return; |
| 177 } | 178 } |
| 178 | 179 |
| 179 if (when < 0) { | 180 if (when < 0) { |
| 180 exceptionState.throwDOMException( | 181 exceptionState.throwDOMException( |
| 181 InvalidAccessError, | 182 InvalidAccessError, |
| 182 ExceptionMessages::indexExceedsMinimumBound( | 183 ExceptionMessages::indexExceedsMinimumBound( |
| 183 "stop time", | 184 "stop time", |
| 184 when, | 185 when, |
| 185 0.0)); | 186 0.0)); |
| 186 return; | 187 return; |
| 187 } | 188 } |
| 188 | 189 |
| 189 // stop() can be called more than once, with the last call to stop taking ef
fect, unless the | 190 // stop() can be called more than once, with the last call to stop taking ef
fect, unless the |
| 190 // source has already stopped due to earlier calls to stop. No exceptions ar
e thrown in any | 191 // source has already stopped due to earlier calls to stop. No exceptions ar
e thrown in any |
| 191 // case. | 192 // case. |
| 192 when = std::max(0.0, when); | 193 when = std::max(0.0, when); |
| 193 m_endTime = when; | 194 setEndTime(when); |
| 194 } | 195 } |
| 195 | 196 |
| 196 void AudioScheduledSourceHandler::finishWithoutOnEnded() | 197 void AudioScheduledSourceHandler::finishWithoutOnEnded() |
| 197 { | 198 { |
| 198 if (playbackState() != FINISHED_STATE) { | 199 if (playbackState() != FINISHED_STATE) { |
| 199 // Let the context dereference this AudioNode. | 200 // Let the context dereference this AudioNode. |
| 200 context()->notifySourceNodeFinishedProcessing(this); | 201 context()->notifySourceNodeFinishedProcessing(this); |
| 201 setPlaybackState(FINISHED_STATE); | 202 setPlaybackState(FINISHED_STATE); |
| 202 } | 203 } |
| 203 } | 204 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 | 257 |
| 257 void AudioScheduledSourceNode::setOnended(PassRefPtrWillBeRawPtr<EventListener>
listener) | 258 void AudioScheduledSourceNode::setOnended(PassRefPtrWillBeRawPtr<EventListener>
listener) |
| 258 { | 259 { |
| 259 audioScheduledSourceHandler().setHasEndedListener(); | 260 audioScheduledSourceHandler().setHasEndedListener(); |
| 260 setAttributeEventListener(EventTypeNames::ended, listener); | 261 setAttributeEventListener(EventTypeNames::ended, listener); |
| 261 } | 262 } |
| 262 | 263 |
| 263 } // namespace blink | 264 } // namespace blink |
| 264 | 265 |
| 265 #endif // ENABLE(WEB_AUDIO) | 266 #endif // ENABLE(WEB_AUDIO) |
| OLD | NEW |