| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 // startFrame : Start frame for this source. | 65 // startFrame : Start frame for this source. |
| 66 // endFrame : End frame for this source. | 66 // endFrame : End frame for this source. |
| 67 size_t quantumStartFrame = context()->currentSampleFrame(); | 67 size_t quantumStartFrame = context()->currentSampleFrame(); |
| 68 size_t quantumEndFrame = quantumStartFrame + quantumFrameSize; | 68 size_t quantumEndFrame = quantumStartFrame + quantumFrameSize; |
| 69 size_t startFrame = | 69 size_t startFrame = |
| 70 AudioUtilities::timeToSampleFrame(m_startTime, sampleRate); | 70 AudioUtilities::timeToSampleFrame(m_startTime, sampleRate); |
| 71 size_t endFrame = | 71 size_t endFrame = |
| 72 m_endTime == UnknownTime ? 0 : AudioUtilities::timeToSampleFrame( | 72 m_endTime == UnknownTime ? 0 : AudioUtilities::timeToSampleFrame( |
| 73 m_endTime, sampleRate); | 73 m_endTime, sampleRate); |
| 74 | 74 |
| 75 // If we know the end time and it's already passed, then don't bother doing an
y more rendering this cycle. | 75 // If we know the end time and it's already passed, then don't bother doing |
| 76 // any more rendering this cycle. |
| 76 if (m_endTime != UnknownTime && endFrame <= quantumStartFrame) | 77 if (m_endTime != UnknownTime && endFrame <= quantumStartFrame) |
| 77 finish(); | 78 finish(); |
| 78 | 79 |
| 79 PlaybackState state = playbackState(); | 80 PlaybackState state = playbackState(); |
| 80 | 81 |
| 81 if (state == UNSCHEDULED_STATE || state == FINISHED_STATE || | 82 if (state == UNSCHEDULED_STATE || state == FINISHED_STATE || |
| 82 startFrame >= quantumEndFrame) { | 83 startFrame >= quantumEndFrame) { |
| 83 // Output silence. | 84 // Output silence. |
| 84 outputBus->zero(); | 85 outputBus->zero(); |
| 85 nonSilentFramesToProcess = 0; | 86 nonSilentFramesToProcess = 0; |
| 86 return; | 87 return; |
| 87 } | 88 } |
| 88 | 89 |
| 89 // Check if it's time to start playing. | 90 // Check if it's time to start playing. |
| 90 if (state == SCHEDULED_STATE) { | 91 if (state == SCHEDULED_STATE) { |
| 91 // Increment the active source count only if we're transitioning from SCHEDU
LED_STATE to PLAYING_STATE. | 92 // Increment the active source count only if we're transitioning from |
| 93 // SCHEDULED_STATE to PLAYING_STATE. |
| 92 setPlaybackState(PLAYING_STATE); | 94 setPlaybackState(PLAYING_STATE); |
| 93 } | 95 } |
| 94 | 96 |
| 95 quantumFrameOffset = | 97 quantumFrameOffset = |
| 96 startFrame > quantumStartFrame ? startFrame - quantumStartFrame : 0; | 98 startFrame > quantumStartFrame ? startFrame - quantumStartFrame : 0; |
| 97 quantumFrameOffset = | 99 quantumFrameOffset = |
| 98 std::min(quantumFrameOffset, quantumFrameSize); // clamp to valid range | 100 std::min(quantumFrameOffset, quantumFrameSize); // clamp to valid range |
| 99 nonSilentFramesToProcess = quantumFrameSize - quantumFrameOffset; | 101 nonSilentFramesToProcess = quantumFrameSize - quantumFrameOffset; |
| 100 | 102 |
| 101 if (!nonSilentFramesToProcess) { | 103 if (!nonSilentFramesToProcess) { |
| 102 // Output silence. | 104 // Output silence. |
| 103 outputBus->zero(); | 105 outputBus->zero(); |
| 104 return; | 106 return; |
| 105 } | 107 } |
| 106 | 108 |
| 107 // Handle silence before we start playing. | 109 // Handle silence before we start playing. |
| 108 // Zero any initial frames representing silence leading up to a rendering star
t time in the middle of the quantum. | 110 // Zero any initial frames representing silence leading up to a rendering |
| 111 // start time in the middle of the quantum. |
| 109 if (quantumFrameOffset) { | 112 if (quantumFrameOffset) { |
| 110 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) | 113 for (unsigned i = 0; i < outputBus->numberOfChannels(); ++i) |
| 111 memset(outputBus->channel(i)->mutableData(), 0, | 114 memset(outputBus->channel(i)->mutableData(), 0, |
| 112 sizeof(float) * quantumFrameOffset); | 115 sizeof(float) * quantumFrameOffset); |
| 113 } | 116 } |
| 114 | 117 |
| 115 // Handle silence after we're done playing. | 118 // Handle silence after we're done playing. |
| 116 // If the end time is somewhere in the middle of this time quantum, then zero
out the | 119 // If the end time is somewhere in the middle of this time quantum, then zero |
| 117 // frames from the end time to the very end of the quantum. | 120 // out the frames from the end time to the very end of the quantum. |
| 118 if (m_endTime != UnknownTime && endFrame >= quantumStartFrame && | 121 if (m_endTime != UnknownTime && endFrame >= quantumStartFrame && |
| 119 endFrame < quantumEndFrame) { | 122 endFrame < quantumEndFrame) { |
| 120 size_t zeroStartFrame = endFrame - quantumStartFrame; | 123 size_t zeroStartFrame = endFrame - quantumStartFrame; |
| 121 size_t framesToZero = quantumFrameSize - zeroStartFrame; | 124 size_t framesToZero = quantumFrameSize - zeroStartFrame; |
| 122 | 125 |
| 123 bool isSafe = zeroStartFrame < quantumFrameSize && | 126 bool isSafe = zeroStartFrame < quantumFrameSize && |
| 124 framesToZero <= quantumFrameSize && | 127 framesToZero <= quantumFrameSize && |
| 125 zeroStartFrame + framesToZero <= quantumFrameSize; | 128 zeroStartFrame + framesToZero <= quantumFrameSize; |
| 126 DCHECK(isSafe); | 129 DCHECK(isSafe); |
| 127 | 130 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 155 return; | 158 return; |
| 156 } | 159 } |
| 157 | 160 |
| 158 if (when < 0) { | 161 if (when < 0) { |
| 159 exceptionState.throwDOMException( | 162 exceptionState.throwDOMException( |
| 160 InvalidAccessError, | 163 InvalidAccessError, |
| 161 ExceptionMessages::indexExceedsMinimumBound("start time", when, 0.0)); | 164 ExceptionMessages::indexExceedsMinimumBound("start time", when, 0.0)); |
| 162 return; | 165 return; |
| 163 } | 166 } |
| 164 | 167 |
| 165 // The node is started. Add a reference to keep us alive so that audio will ev
entually get | 168 // The node is started. Add a reference to keep us alive so that audio will |
| 166 // played even if Javascript should drop all references to this node. The refe
rence will get | 169 // eventually get played even if Javascript should drop all references to this |
| 167 // dropped when the source has finished playing. | 170 // node. The reference will get dropped when the source has finished playing. |
| 168 context()->notifySourceNodeStartedProcessing(node()); | 171 context()->notifySourceNodeStartedProcessing(node()); |
| 169 | 172 |
| 170 // This synchronizes with process(). updateSchedulingInfo will read some of th
e variables being | 173 // This synchronizes with process(). updateSchedulingInfo will read some of |
| 171 // set here. | 174 // the variables being set here. |
| 172 MutexLocker processLocker(m_processLock); | 175 MutexLocker processLocker(m_processLock); |
| 173 | 176 |
| 174 // If |when| < currentTime, the source must start now according to the spec. | 177 // If |when| < currentTime, the source must start now according to the spec. |
| 175 // So just set startTime to currentTime in this case to start the source now. | 178 // So just set startTime to currentTime in this case to start the source now. |
| 176 m_startTime = std::max(when, context()->currentTime()); | 179 m_startTime = std::max(when, context()->currentTime()); |
| 177 | 180 |
| 178 setPlaybackState(SCHEDULED_STATE); | 181 setPlaybackState(SCHEDULED_STATE); |
| 179 } | 182 } |
| 180 | 183 |
| 181 void AudioScheduledSourceHandler::stop(double when, | 184 void AudioScheduledSourceHandler::stop(double when, |
| 182 ExceptionState& exceptionState) { | 185 ExceptionState& exceptionState) { |
| 183 DCHECK(isMainThread()); | 186 DCHECK(isMainThread()); |
| 184 | 187 |
| 185 if (playbackState() == UNSCHEDULED_STATE) { | 188 if (playbackState() == UNSCHEDULED_STATE) { |
| 186 exceptionState.throwDOMException( | 189 exceptionState.throwDOMException( |
| 187 InvalidStateError, "cannot call stop without calling start first."); | 190 InvalidStateError, "cannot call stop without calling start first."); |
| 188 return; | 191 return; |
| 189 } | 192 } |
| 190 | 193 |
| 191 if (when < 0) { | 194 if (when < 0) { |
| 192 exceptionState.throwDOMException( | 195 exceptionState.throwDOMException( |
| 193 InvalidAccessError, | 196 InvalidAccessError, |
| 194 ExceptionMessages::indexExceedsMinimumBound("stop time", when, 0.0)); | 197 ExceptionMessages::indexExceedsMinimumBound("stop time", when, 0.0)); |
| 195 return; | 198 return; |
| 196 } | 199 } |
| 197 | 200 |
| 198 // This synchronizes with process() | 201 // This synchronizes with process() |
| 199 MutexLocker processLocker(m_processLock); | 202 MutexLocker processLocker(m_processLock); |
| 200 | 203 |
| 201 // stop() can be called more than once, with the last call to stop taking effe
ct, unless the | 204 // stop() can be called more than once, with the last call to stop taking |
| 202 // source has already stopped due to earlier calls to stop. No exceptions are
thrown in any | 205 // effect, unless the source has already stopped due to earlier calls to stop. |
| 203 // case. | 206 // No exceptions are thrown in any case. |
| 204 when = std::max(0.0, when); | 207 when = std::max(0.0, when); |
| 205 m_endTime = when; | 208 m_endTime = when; |
| 206 } | 209 } |
| 207 | 210 |
| 208 void AudioScheduledSourceHandler::finishWithoutOnEnded() { | 211 void AudioScheduledSourceHandler::finishWithoutOnEnded() { |
| 209 if (playbackState() != FINISHED_STATE) { | 212 if (playbackState() != FINISHED_STATE) { |
| 210 // Let the context dereference this AudioNode. | 213 // Let the context dereference this AudioNode. |
| 211 context()->notifySourceNodeFinishedProcessing(this); | 214 context()->notifySourceNodeFinishedProcessing(this); |
| 212 setPlaybackState(FINISHED_STATE); | 215 setPlaybackState(FINISHED_STATE); |
| 213 } | 216 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 // playback state if the context is closed. | 274 // playback state if the context is closed. |
| 272 if (context()->isContextClosed()) | 275 if (context()->isContextClosed()) |
| 273 return false; | 276 return false; |
| 274 | 277 |
| 275 // If a node is scheduled or playing, do not collect the node prematurely | 278 // If a node is scheduled or playing, do not collect the node prematurely |
| 276 // even its reference is out of scope. Then fire onended event if assigned. | 279 // even its reference is out of scope. Then fire onended event if assigned. |
| 277 return audioScheduledSourceHandler().isPlayingOrScheduled(); | 280 return audioScheduledSourceHandler().isPlayingOrScheduled(); |
| 278 } | 281 } |
| 279 | 282 |
| 280 } // namespace blink | 283 } // namespace blink |
| OLD | NEW |