OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, 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 10 matching lines...) Expand all Loading... | |
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 | 26 |
27 #if ENABLE(WEB_AUDIO) | 27 #if ENABLE(WEB_AUDIO) |
28 | 28 |
29 #include "modules/webaudio/AudioContext.h" | 29 #include "modules/webaudio/AudioContext.h" |
30 | 30 |
31 #include "bindings/v8/ExceptionMessages.h" | |
31 #include "bindings/v8/ExceptionState.h" | 32 #include "bindings/v8/ExceptionState.h" |
32 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
33 #include "core/dom/ExceptionCode.h" | 34 #include "core/dom/ExceptionCode.h" |
34 #include "core/html/HTMLMediaElement.h" | 35 #include "core/html/HTMLMediaElement.h" |
35 #include "core/inspector/ScriptCallStack.h" | 36 #include "core/inspector/ScriptCallStack.h" |
36 #include "core/platform/audio/FFTFrame.h" | 37 #include "core/platform/audio/FFTFrame.h" |
37 #include "core/platform/audio/HRTFDatabaseLoader.h" | 38 #include "core/platform/audio/HRTFDatabaseLoader.h" |
38 #include "core/platform/audio/HRTFPanner.h" | 39 #include "core/platform/audio/HRTFPanner.h" |
39 #include "modules/mediastream/MediaStream.h" | 40 #include "modules/mediastream/MediaStream.h" |
40 #include "modules/webaudio/AnalyserNode.h" | 41 #include "modules/webaudio/AnalyserNode.h" |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other | 287 // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other |
287 // ActiveDOMObjects so let's schedule uninitialize() to be called later. | 288 // ActiveDOMObjects so let's schedule uninitialize() to be called later. |
288 // FIXME: see if there's a more direct way to handle this issue. | 289 // FIXME: see if there's a more direct way to handle this issue. |
289 callOnMainThread(stopDispatch, this); | 290 callOnMainThread(stopDispatch, this); |
290 } | 291 } |
291 | 292 |
292 PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, si ze_t numberOfFrames, float sampleRate, ExceptionState& es) | 293 PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, si ze_t numberOfFrames, float sampleRate, ExceptionState& es) |
293 { | 294 { |
294 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numb erOfFrames, sampleRate); | 295 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numb erOfFrames, sampleRate); |
295 if (!audioBuffer.get()) { | 296 if (!audioBuffer.get()) { |
296 es.throwUninformativeAndGenericDOMException(SyntaxError); | 297 es.throwDOMException( |
298 SyntaxError, | |
299 ExceptionMessages::failedToConstruct( | |
300 "AudioBuffer", | |
301 "invalid number of channels, frames, or sample rate.")); | |
Mike West
2013/09/27 06:44:39
For these kinds of errors, it would be nice to tel
Raymond Toy (Google)
2013/09/27 16:24:10
Agreed. I'll try to make this (and all others) mor
| |
297 return 0; | 302 return 0; |
298 } | 303 } |
299 | 304 |
300 return audioBuffer; | 305 return audioBuffer; |
301 } | 306 } |
302 | 307 |
303 PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, boo l mixToMono, ExceptionState& es) | 308 PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, boo l mixToMono, ExceptionState& es) |
304 { | 309 { |
305 ASSERT(arrayBuffer); | 310 ASSERT(arrayBuffer); |
306 if (!arrayBuffer) { | 311 if (!arrayBuffer) { |
307 es.throwUninformativeAndGenericDOMException(SyntaxError); | 312 es.throwDOMException( |
313 SyntaxError, | |
314 ExceptionMessages::failedToConstruct( | |
315 "AudioBuffer", | |
316 "invalid ArrayBuffer.")); | |
308 return 0; | 317 return 0; |
309 } | 318 } |
310 | 319 |
311 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(array Buffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate()); | 320 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(array Buffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate()); |
312 if (!audioBuffer.get()) { | 321 if (!audioBuffer.get()) { |
313 es.throwUninformativeAndGenericDOMException(SyntaxError); | 322 es.throwDOMException( |
323 SyntaxError, | |
324 ExceptionMessages::failedToConstruct( | |
325 "AudioBuffer", | |
326 "invalid audio data in ArrayBuffer.")); | |
314 return 0; | 327 return 0; |
315 } | 328 } |
316 | 329 |
317 return audioBuffer; | 330 return audioBuffer; |
318 } | 331 } |
319 | 332 |
320 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassRefPtr<AudioBuffe rCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback, Excep tionState& es) | 333 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassRefPtr<AudioBuffe rCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback, Excep tionState& es) |
321 { | 334 { |
322 if (!audioData) { | 335 if (!audioData) { |
323 es.throwUninformativeAndGenericDOMException(SyntaxError); | 336 es.throwDOMException( |
337 SyntaxError, | |
338 ExceptionMessages::failedToExecute( | |
339 "decodeAudioData", | |
340 "AudioContext", | |
341 "invalid ArrayBuffer for audioData.")); | |
324 return; | 342 return; |
325 } | 343 } |
326 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa llback); | 344 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa llback); |
327 } | 345 } |
328 | 346 |
329 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() | 347 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() |
330 { | 348 { |
331 ASSERT(isMainThread()); | 349 ASSERT(isMainThread()); |
332 lazyInitialize(); | 350 lazyInitialize(); |
333 RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_d estinationNode->sampleRate()); | 351 RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_d estinationNode->sampleRate()); |
334 | 352 |
335 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing. | 353 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing. |
336 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing(). | 354 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing(). |
337 refNode(node.get()); | 355 refNode(node.get()); |
338 | 356 |
339 return node; | 357 return node; |
340 } | 358 } |
341 | 359 |
342 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H TMLMediaElement* mediaElement, ExceptionState& es) | 360 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H TMLMediaElement* mediaElement, ExceptionState& es) |
343 { | 361 { |
344 ASSERT(mediaElement); | |
Mike West
2013/09/27 06:44:39
Why drop the ASSERT?
Raymond Toy (Google)
2013/09/27 16:24:10
When running the webaudio layout tests in debug mo
| |
345 if (!mediaElement) { | 362 if (!mediaElement) { |
346 es.throwUninformativeAndGenericDOMException(InvalidStateError); | 363 es.throwDOMException( |
364 InvalidStateError, | |
365 ExceptionMessages::failedToConstruct( | |
366 "MediaElementAudioSourceNode", | |
367 "invalid HTMLMedialElement.")); | |
347 return 0; | 368 return 0; |
348 } | 369 } |
349 | 370 |
350 ASSERT(isMainThread()); | 371 ASSERT(isMainThread()); |
351 lazyInitialize(); | 372 lazyInitialize(); |
352 | 373 |
353 // First check if this media element already has a source node. | 374 // First check if this media element already has a source node. |
354 if (mediaElement->audioSourceNode()) { | 375 if (mediaElement->audioSourceNode()) { |
355 es.throwUninformativeAndGenericDOMException(InvalidStateError); | 376 es.throwDOMException( |
377 InvalidStateError, | |
378 ExceptionMessages::failedToConstruct( | |
379 "MediaElementAudioSourceNode", | |
380 "invalid HTMLMediaElement.")); | |
356 return 0; | 381 return 0; |
357 } | 382 } |
358 | 383 |
359 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea te(this, mediaElement); | 384 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea te(this, mediaElement); |
360 | 385 |
361 mediaElement->setAudioSourceNode(node.get()); | 386 mediaElement->setAudioSourceNode(node.get()); |
362 | 387 |
363 refNode(node.get()); // context keeps reference until node is disconnected | 388 refNode(node.get()); // context keeps reference until node is disconnected |
364 return node; | 389 return node; |
365 } | 390 } |
366 | 391 |
367 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med iaStream* mediaStream, ExceptionState& es) | 392 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med iaStream* mediaStream, ExceptionState& es) |
368 { | 393 { |
369 ASSERT(mediaStream); | |
370 if (!mediaStream) { | 394 if (!mediaStream) { |
371 es.throwUninformativeAndGenericDOMException(InvalidStateError); | 395 es.throwDOMException( |
396 InvalidStateError, | |
397 ExceptionMessages::failedToConstruct("MediaStreamAudioSourceNode")); | |
Mike West
2013/09/27 06:44:39
"invalid MediaStream source"?
| |
372 return 0; | 398 return 0; |
373 } | 399 } |
374 | 400 |
375 ASSERT(isMainThread()); | 401 ASSERT(isMainThread()); |
376 lazyInitialize(); | 402 lazyInitialize(); |
377 | 403 |
378 AudioSourceProvider* provider = 0; | 404 AudioSourceProvider* provider = 0; |
379 | 405 |
380 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); | 406 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); |
381 | 407 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, es); | 442 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, es); |
417 } | 443 } |
418 | 444 |
419 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe rSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionSta te& es) | 445 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe rSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionSta te& es) |
420 { | 446 { |
421 ASSERT(isMainThread()); | 447 ASSERT(isMainThread()); |
422 lazyInitialize(); | 448 lazyInitialize(); |
423 RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_desti nationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChann els); | 449 RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_desti nationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChann els); |
424 | 450 |
425 if (!node.get()) { | 451 if (!node.get()) { |
426 es.throwUninformativeAndGenericDOMException(SyntaxError); | 452 es.throwDOMException( |
453 SyntaxError, | |
454 ExceptionMessages::failedToConstruct( | |
455 "ScriptProcessorNode", | |
456 "invalid buffer size, or number of input/outputs.")); | |
427 return 0; | 457 return 0; |
428 } | 458 } |
429 | 459 |
430 refNode(node.get()); // context keeps reference until we stop making javascr ipt rendering callbacks | 460 refNode(node.get()); // context keeps reference until we stop making javascr ipt rendering callbacks |
431 return node; | 461 return node; |
432 } | 462 } |
433 | 463 |
434 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter() | 464 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter() |
435 { | 465 { |
436 ASSERT(isMainThread()); | 466 ASSERT(isMainThread()); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
503 } | 533 } |
504 | 534 |
505 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe rOfOutputs, ExceptionState& es) | 535 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe rOfOutputs, ExceptionState& es) |
506 { | 536 { |
507 ASSERT(isMainThread()); | 537 ASSERT(isMainThread()); |
508 lazyInitialize(); | 538 lazyInitialize(); |
509 | 539 |
510 RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_desti nationNode->sampleRate(), numberOfOutputs); | 540 RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_desti nationNode->sampleRate(), numberOfOutputs); |
511 | 541 |
512 if (!node.get()) { | 542 if (!node.get()) { |
513 es.throwUninformativeAndGenericDOMException(SyntaxError); | 543 es.throwDOMException( |
544 SyntaxError, | |
545 ExceptionMessages::failedToConstruct( | |
546 "ChannelSplitterNode", | |
547 "invalid number of outputs.")); | |
Mike West
2013/09/27 06:44:39
"The number of outputs (" + String::number(numberO
| |
514 return 0; | 548 return 0; |
515 } | 549 } |
516 | 550 |
517 return node; | 551 return node; |
518 } | 552 } |
519 | 553 |
520 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState& es) | 554 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState& es) |
521 { | 555 { |
522 const unsigned ChannelMergerDefaultNumberOfInputs = 6; | 556 const unsigned ChannelMergerDefaultNumberOfInputs = 6; |
523 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, es); | 557 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, es); |
524 } | 558 } |
525 | 559 |
526 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI nputs, ExceptionState& es) | 560 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI nputs, ExceptionState& es) |
527 { | 561 { |
528 ASSERT(isMainThread()); | 562 ASSERT(isMainThread()); |
529 lazyInitialize(); | 563 lazyInitialize(); |
530 | 564 |
531 RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinati onNode->sampleRate(), numberOfInputs); | 565 RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinati onNode->sampleRate(), numberOfInputs); |
532 | 566 |
533 if (!node.get()) { | 567 if (!node.get()) { |
534 es.throwUninformativeAndGenericDOMException(SyntaxError); | 568 es.throwDOMException( |
569 SyntaxError, | |
570 ExceptionMessages::failedToConstruct( | |
571 "ChannelMergerNode", | |
572 "invalid number of inputs.")); | |
Mike West
2013/09/27 06:44:39
Same as for outputs.
| |
535 return 0; | 573 return 0; |
536 } | 574 } |
537 | 575 |
538 return node; | 576 return node; |
539 } | 577 } |
540 | 578 |
541 PassRefPtr<OscillatorNode> AudioContext::createOscillator() | 579 PassRefPtr<OscillatorNode> AudioContext::createOscillator() |
542 { | 580 { |
543 ASSERT(isMainThread()); | 581 ASSERT(isMainThread()); |
544 lazyInitialize(); | 582 lazyInitialize(); |
545 | 583 |
546 RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode ->sampleRate()); | 584 RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode ->sampleRate()); |
547 | 585 |
548 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing. | 586 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing. |
549 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing(). | 587 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing(). |
550 refNode(node.get()); | 588 refNode(node.get()); |
551 | 589 |
552 return node; | 590 return node; |
553 } | 591 } |
554 | 592 |
555 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl oat32Array* imag, ExceptionState& es) | 593 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl oat32Array* imag, ExceptionState& es) |
556 { | 594 { |
557 ASSERT(isMainThread()); | 595 ASSERT(isMainThread()); |
558 | 596 |
559 if (!real || !imag || (real->length() != imag->length())) { | 597 if (!real || !imag || (real->length() != imag->length())) { |
560 es.throwUninformativeAndGenericDOMException(SyntaxError); | 598 es.throwDOMException( |
599 SyntaxError, | |
600 ExceptionMessages::failedToConstruct( | |
601 "WaveTable", | |
602 "invalid real or imag arrays for wave table.")); | |
Mike West
2013/09/27 06:44:39
One option would be to split this up into multiple
| |
561 return 0; | 603 return 0; |
562 } | 604 } |
563 | 605 |
564 lazyInitialize(); | 606 lazyInitialize(); |
565 return PeriodicWave::create(sampleRate(), real, imag); | 607 return PeriodicWave::create(sampleRate(), real, imag); |
566 } | 608 } |
567 | 609 |
568 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) | 610 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) |
569 { | 611 { |
570 ASSERT(isAudioThread()); | 612 ASSERT(isAudioThread()); |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
951 } | 993 } |
952 | 994 |
953 void AudioContext::decrementActiveSourceCount() | 995 void AudioContext::decrementActiveSourceCount() |
954 { | 996 { |
955 atomicDecrement(&m_activeSourceCount); | 997 atomicDecrement(&m_activeSourceCount); |
956 } | 998 } |
957 | 999 |
958 } // namespace WebCore | 1000 } // namespace WebCore |
959 | 1001 |
960 #endif // ENABLE(WEB_AUDIO) | 1002 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |