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 |