| 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 |