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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 Document* document = toDocument(context); | 59 Document* document = toDocument(context); |
60 | 60 |
61 if (!numberOfFrames) { | 61 if (!numberOfFrames) { |
62 exceptionState.throwDOMException(SyntaxError, | 62 exceptionState.throwDOMException(SyntaxError, |
63 "number of frames cannot be zero."); | 63 "number of frames cannot be zero."); |
64 return nullptr; | 64 return nullptr; |
65 } | 65 } |
66 | 66 |
67 if (numberOfChannels > BaseAudioContext::maxNumberOfChannels()) { | 67 if (numberOfChannels > BaseAudioContext::maxNumberOfChannels()) { |
68 exceptionState.throwDOMException( | 68 exceptionState.throwDOMException( |
69 IndexSizeError, ExceptionMessages::indexOutsideRange<unsigned>( | 69 IndexSizeError, |
70 "number of channels", numberOfChannels, 0, | 70 ExceptionMessages::indexOutsideRange<unsigned>( |
71 ExceptionMessages::InclusiveBound, | 71 "number of channels", numberOfChannels, 0, |
72 BaseAudioContext::maxNumberOfChannels(), | 72 ExceptionMessages::InclusiveBound, |
73 ExceptionMessages::InclusiveBound)); | 73 BaseAudioContext::maxNumberOfChannels(), |
| 74 ExceptionMessages::InclusiveBound)); |
74 return nullptr; | 75 return nullptr; |
75 } | 76 } |
76 | 77 |
77 if (!AudioUtilities::isValidAudioBufferSampleRate(sampleRate)) { | 78 if (!AudioUtilities::isValidAudioBufferSampleRate(sampleRate)) { |
78 exceptionState.throwDOMException( | 79 exceptionState.throwDOMException( |
79 IndexSizeError, ExceptionMessages::indexOutsideRange( | 80 IndexSizeError, |
80 "sampleRate", sampleRate, | 81 ExceptionMessages::indexOutsideRange( |
81 AudioUtilities::minAudioBufferSampleRate(), | 82 "sampleRate", sampleRate, |
82 ExceptionMessages::InclusiveBound, | 83 AudioUtilities::minAudioBufferSampleRate(), |
83 AudioUtilities::maxAudioBufferSampleRate(), | 84 ExceptionMessages::InclusiveBound, |
84 ExceptionMessages::InclusiveBound)); | 85 AudioUtilities::maxAudioBufferSampleRate(), |
| 86 ExceptionMessages::InclusiveBound)); |
85 return nullptr; | 87 return nullptr; |
86 } | 88 } |
87 | 89 |
88 OfflineAudioContext* audioContext = new OfflineAudioContext( | 90 OfflineAudioContext* audioContext = new OfflineAudioContext( |
89 document, numberOfChannels, numberOfFrames, sampleRate, exceptionState); | 91 document, numberOfChannels, numberOfFrames, sampleRate, exceptionState); |
90 | 92 |
91 if (!audioContext->destination()) { | 93 if (!audioContext->destination()) { |
92 exceptionState.throwDOMException( | 94 exceptionState.throwDOMException( |
93 NotSupportedError, "OfflineAudioContext(" + | 95 NotSupportedError, |
94 String::number(numberOfChannels) + ", " + | 96 "OfflineAudioContext(" + String::number(numberOfChannels) + ", " + |
95 String::number(numberOfFrames) + ", " + | 97 String::number(numberOfFrames) + ", " + String::number(sampleRate) + |
96 String::number(sampleRate) + ")"); | 98 ")"); |
97 } | 99 } |
98 | 100 |
99 #if DEBUG_AUDIONODE_REFERENCES | 101 #if DEBUG_AUDIONODE_REFERENCES |
100 fprintf(stderr, "[%16p]: OfflineAudioContext::OfflineAudioContext()\n", | 102 fprintf(stderr, "[%16p]: OfflineAudioContext::OfflineAudioContext()\n", |
101 audioContext); | 103 audioContext); |
102 #endif | 104 #endif |
103 DEFINE_STATIC_LOCAL(SparseHistogram, offlineContextChannelCountHistogram, | 105 DEFINE_STATIC_LOCAL(SparseHistogram, offlineContextChannelCountHistogram, |
104 ("WebAudio.OfflineAudioContext.ChannelCount")); | 106 ("WebAudio.OfflineAudioContext.ChannelCount")); |
105 // Arbitrarly limit the maximum length to 1 million frames (about 20 sec | 107 // Arbitrarly limit the maximum length to 1 million frames (about 20 sec |
106 // at 48kHz). The number of buckets is fairly arbitrary. | 108 // at 48kHz). The number of buckets is fairly arbitrary. |
(...skipping 28 matching lines...) Expand all Loading... |
135 m_renderTarget = | 137 m_renderTarget = |
136 AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); | 138 AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate); |
137 | 139 |
138 // Throw an exception if the render target is not ready. | 140 // Throw an exception if the render target is not ready. |
139 if (m_renderTarget) { | 141 if (m_renderTarget) { |
140 m_destinationNode = | 142 m_destinationNode = |
141 OfflineAudioDestinationNode::create(this, m_renderTarget.get()); | 143 OfflineAudioDestinationNode::create(this, m_renderTarget.get()); |
142 initialize(); | 144 initialize(); |
143 } else { | 145 } else { |
144 exceptionState.throwRangeError(ExceptionMessages::failedToConstruct( | 146 exceptionState.throwRangeError(ExceptionMessages::failedToConstruct( |
145 "OfflineAudioContext", "failed to create OfflineAudioContext(" + | 147 "OfflineAudioContext", |
146 String::number(numberOfChannels) + ", " + | 148 "failed to create OfflineAudioContext(" + |
147 String::number(numberOfFrames) + ", " + | 149 String::number(numberOfChannels) + ", " + |
148 String::number(sampleRate) + ")")); | 150 String::number(numberOfFrames) + ", " + String::number(sampleRate) + |
| 151 ")")); |
149 } | 152 } |
150 } | 153 } |
151 | 154 |
152 OfflineAudioContext::~OfflineAudioContext() { | 155 OfflineAudioContext::~OfflineAudioContext() { |
153 #if DEBUG_AUDIONODE_REFERENCES | 156 #if DEBUG_AUDIONODE_REFERENCES |
154 fprintf(stderr, "[%16p]: OfflineAudioContext::~OfflineAudioContext()\n", | 157 fprintf(stderr, "[%16p]: OfflineAudioContext::~OfflineAudioContext()\n", |
155 this); | 158 this); |
156 #endif | 159 #endif |
157 } | 160 } |
158 | 161 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 size_t frame = when * sampleRate(); | 244 size_t frame = when * sampleRate(); |
242 frame -= frame % destinationHandler().renderQuantumFrames(); | 245 frame -= frame % destinationHandler().renderQuantumFrames(); |
243 | 246 |
244 // The suspend time should be earlier than the total render frame. If the | 247 // The suspend time should be earlier than the total render frame. If the |
245 // requested suspension time is equal to the total render frame, the promise | 248 // requested suspension time is equal to the total render frame, the promise |
246 // will be rejected. | 249 // will be rejected. |
247 if (m_totalRenderFrames <= frame) { | 250 if (m_totalRenderFrames <= frame) { |
248 resolver->reject(DOMException::create( | 251 resolver->reject(DOMException::create( |
249 InvalidStateError, | 252 InvalidStateError, |
250 "cannot schedule a suspend at frame " + String::number(frame) + " (" + | 253 "cannot schedule a suspend at frame " + String::number(frame) + " (" + |
251 String::number(when) + " seconds) " + "because it is greater than " | 254 String::number(when) + " seconds) " + |
252 "or equal to the total " | 255 "because it is greater than " |
253 "render duration of " + | 256 "or equal to the total " |
| 257 "render duration of " + |
254 String::number(m_totalRenderFrames) + " frames")); | 258 String::number(m_totalRenderFrames) + " frames")); |
255 return promise; | 259 return promise; |
256 } | 260 } |
257 | 261 |
258 // The specified suspend time is in the past; reject the promise. | 262 // The specified suspend time is in the past; reject the promise. |
259 if (frame < currentSampleFrame()) { | 263 if (frame < currentSampleFrame()) { |
260 size_t currentFrameClamped = std::min(currentSampleFrame(), length()); | 264 size_t currentFrameClamped = std::min(currentSampleFrame(), length()); |
261 double currentTimeClamped = | 265 double currentTimeClamped = |
262 std::min(currentTime(), length() / static_cast<double>(sampleRate())); | 266 std::min(currentTime(), length() / static_cast<double>(sampleRate())); |
263 resolver->reject(DOMException::create( | 267 resolver->reject(DOMException::create( |
264 InvalidStateError, | 268 InvalidStateError, |
265 "suspend(" + String::number(when) + ") failed to suspend at frame " + | 269 "suspend(" + String::number(when) + ") failed to suspend at frame " + |
266 String::number(frame) + " because it is earlier than the current " + | 270 String::number(frame) + " because it is earlier than the current " + |
267 "frame of " + String::number(currentFrameClamped) + " (" + | 271 "frame of " + String::number(currentFrameClamped) + " (" + |
268 String::number(currentTimeClamped) + " seconds)")); | 272 String::number(currentTimeClamped) + " seconds)")); |
269 return promise; | 273 return promise; |
270 } | 274 } |
271 | 275 |
272 // Wait until the suspend map is available for the insertion. Here we should | 276 // Wait until the suspend map is available for the insertion. Here we should |
273 // use AutoLocker because it locks the graph from the main thread. | 277 // use AutoLocker because it locks the graph from the main thread. |
274 AutoLocker locker(this); | 278 AutoLocker locker(this); |
275 | 279 |
276 // If there is a duplicate suspension at the same quantized frame, | 280 // If there is a duplicate suspension at the same quantized frame, |
277 // reject the promise. | 281 // reject the promise. |
278 if (m_scheduledSuspends.contains(frame)) { | 282 if (m_scheduledSuspends.contains(frame)) { |
279 resolver->reject(DOMException::create( | 283 resolver->reject(DOMException::create( |
280 InvalidStateError, "cannot schedule more than one suspend at frame " + | 284 InvalidStateError, |
281 String::number(frame) + " (" + | 285 "cannot schedule more than one suspend at frame " + |
282 String::number(when) + " seconds)")); | 286 String::number(frame) + " (" + String::number(when) + " seconds)")); |
283 return promise; | 287 return promise; |
284 } | 288 } |
285 | 289 |
286 m_scheduledSuspends.insert(frame, resolver); | 290 m_scheduledSuspends.insert(frame, resolver); |
287 | 291 |
288 return promise; | 292 return promise; |
289 } | 293 } |
290 | 294 |
291 ScriptPromise OfflineAudioContext::resumeContext(ScriptState* scriptState) { | 295 ScriptPromise OfflineAudioContext::resumeContext(ScriptState* scriptState) { |
292 DCHECK(isMainThread()); | 296 DCHECK(isMainThread()); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 | 447 |
444 // Note that the GraphLock is required before this check. Since this needs | 448 // Note that the GraphLock is required before this check. Since this needs |
445 // to run on the audio thread, OfflineGraphAutoLocker must be used. | 449 // to run on the audio thread, OfflineGraphAutoLocker must be used. |
446 if (m_scheduledSuspends.contains(currentSampleFrame())) | 450 if (m_scheduledSuspends.contains(currentSampleFrame())) |
447 return true; | 451 return true; |
448 | 452 |
449 return false; | 453 return false; |
450 } | 454 } |
451 | 455 |
452 } // namespace blink | 456 } // namespace blink |
OLD | NEW |