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 |