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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); | 178 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); |
179 ASSERT(!m_renderingAutomaticPullNodes.size()); | 179 ASSERT(!m_renderingAutomaticPullNodes.size()); |
180 } | 180 } |
181 | 181 |
182 void AudioContext::lazyInitialize() | 182 void AudioContext::lazyInitialize() |
183 { | 183 { |
184 if (!m_isInitialized) { | 184 if (!m_isInitialized) { |
185 // Don't allow the context to initialize a second time after it's alread
y been explicitly uninitialized. | 185 // Don't allow the context to initialize a second time after it's alread
y been explicitly uninitialized. |
186 ASSERT(!m_isAudioThreadFinished); | 186 ASSERT(!m_isAudioThreadFinished); |
187 if (!m_isAudioThreadFinished) { | 187 if (!m_isAudioThreadFinished) { |
| 188 // Creation of a destination node should not start the audio HW. The |
| 189 // creation of any other AudioNode will initialize the audio HW and
start processing |
188 if (m_destinationNode.get()) { | 190 if (m_destinationNode.get()) { |
189 m_destinationNode->initialize(); | 191 m_destinationNode->initialize(); |
190 | 192 |
191 if (!isOfflineContext()) { | 193 if (!isOfflineContext()) { |
192 // This starts the audio thread. The destination node's prov
ideInput() method will now be called repeatedly to render audio. | 194 // This starts the audio thread. The destination node's prov
ideInput() method will now be called repeatedly to render audio. |
193 // Each time provideInput() is called, a portion of the audi
o stream is rendered. Let's call this time period a "render quantum". | 195 // Each time provideInput() is called, a portion of the audi
o stream is rendered. Let's call this time period a "render quantum". |
194 // NOTE: for now default AudioContext does not need an expli
cit startRendering() call from JavaScript. | 196 // NOTE: for now default AudioContext does not need an expli
cit startRendering() call from JavaScript. |
195 // We may want to consider requiring it for symmetry with Of
flineAudioContext. | 197 // We may want to consider requiring it for symmetry with Of
flineAudioContext. |
196 m_destinationNode->startRendering(); | 198 m_destinationNode->startRendering(); |
197 ++s_hardwareContextCount; | 199 ++s_hardwareContextCount; |
198 } | 200 } |
199 | 201 |
| 202 m_isInitialized = true; |
200 } | 203 } |
201 m_isInitialized = true; | |
202 } | 204 } |
203 } | 205 } |
204 } | 206 } |
205 | 207 |
206 void AudioContext::clear() | 208 void AudioContext::clear() |
207 { | 209 { |
208 // We have to release our reference to the destination node before the conte
xt will ever be deleted since the destination node holds a reference to the cont
ext. | 210 // We have to release our reference to the destination node before the conte
xt will ever be deleted since the destination node holds a reference to the cont
ext. |
209 if (m_destinationNode) | 211 if (m_destinationNode) |
210 m_destinationNode.clear(); | 212 m_destinationNode.clear(); |
211 | 213 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 SyntaxError, | 341 SyntaxError, |
340 "invalid ArrayBuffer for audioData."); | 342 "invalid ArrayBuffer for audioData."); |
341 return; | 343 return; |
342 } | 344 } |
343 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa
llback); | 345 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa
llback); |
344 } | 346 } |
345 | 347 |
346 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() | 348 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() |
347 { | 349 { |
348 ASSERT(isMainThread()); | 350 ASSERT(isMainThread()); |
349 lazyInitialize(); | |
350 RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_d
estinationNode->sampleRate()); | 351 RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_d
estinationNode->sampleRate()); |
351 | 352 |
352 // 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. |
353 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). | 354 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). |
354 refNode(node.get()); | 355 refNode(node.get()); |
355 | 356 |
356 return node; | 357 return node; |
357 } | 358 } |
358 | 359 |
359 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H
TMLMediaElement* mediaElement, ExceptionState& exceptionState) | 360 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H
TMLMediaElement* mediaElement, ExceptionState& exceptionState) |
360 { | 361 { |
| 362 ASSERT(isMainThread()); |
361 if (!mediaElement) { | 363 if (!mediaElement) { |
362 exceptionState.throwDOMException( | 364 exceptionState.throwDOMException( |
363 InvalidStateError, | 365 InvalidStateError, |
364 "invalid HTMLMedialElement."); | 366 "invalid HTMLMedialElement."); |
365 return nullptr; | 367 return nullptr; |
366 } | 368 } |
367 | 369 |
368 ASSERT(isMainThread()); | |
369 lazyInitialize(); | |
370 | |
371 // First check if this media element already has a source node. | 370 // First check if this media element already has a source node. |
372 if (mediaElement->audioSourceNode()) { | 371 if (mediaElement->audioSourceNode()) { |
373 exceptionState.throwDOMException( | 372 exceptionState.throwDOMException( |
374 InvalidStateError, | 373 InvalidStateError, |
375 "invalid HTMLMediaElement."); | 374 "invalid HTMLMediaElement."); |
376 return nullptr; | 375 return nullptr; |
377 } | 376 } |
378 | 377 |
379 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea
te(this, mediaElement); | 378 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea
te(this, mediaElement); |
380 | 379 |
381 mediaElement->setAudioSourceNode(node.get()); | 380 mediaElement->setAudioSourceNode(node.get()); |
382 | 381 |
383 refNode(node.get()); // context keeps reference until node is disconnected | 382 refNode(node.get()); // context keeps reference until node is disconnected |
384 return node; | 383 return node; |
385 } | 384 } |
386 | 385 |
387 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med
iaStream* mediaStream, ExceptionState& exceptionState) | 386 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med
iaStream* mediaStream, ExceptionState& exceptionState) |
388 { | 387 { |
| 388 ASSERT(isMainThread()); |
389 if (!mediaStream) { | 389 if (!mediaStream) { |
390 exceptionState.throwDOMException( | 390 exceptionState.throwDOMException( |
391 InvalidStateError, | 391 InvalidStateError, |
392 "invalid MediaStream source"); | 392 "invalid MediaStream source"); |
393 return nullptr; | 393 return nullptr; |
394 } | 394 } |
395 | 395 |
396 ASSERT(isMainThread()); | |
397 lazyInitialize(); | |
398 | |
399 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); | 396 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); |
400 if (audioTracks.isEmpty()) { | 397 if (audioTracks.isEmpty()) { |
401 exceptionState.throwDOMException( | 398 exceptionState.throwDOMException( |
402 InvalidStateError, | 399 InvalidStateError, |
403 "MediaStream has no audio track"); | 400 "MediaStream has no audio track"); |
404 return nullptr; | 401 return nullptr; |
405 } | 402 } |
406 | 403 |
407 // Use the first audio track in the media stream. | 404 // Use the first audio track in the media stream. |
408 RefPtr<MediaStreamTrack> audioTrack = audioTracks[0]; | 405 RefPtr<MediaStreamTrack> audioTrack = audioTracks[0]; |
(...skipping 27 matching lines...) Expand all Loading... |
436 | 433 |
437 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe
rSize, size_t numberOfInputChannels, ExceptionState& exceptionState) | 434 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe
rSize, size_t numberOfInputChannels, ExceptionState& exceptionState) |
438 { | 435 { |
439 // Set number of output channels to stereo by default. | 436 // Set number of output channels to stereo by default. |
440 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, exception
State); | 437 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, exception
State); |
441 } | 438 } |
442 | 439 |
443 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe
rSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionSta
te& exceptionState) | 440 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe
rSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionSta
te& exceptionState) |
444 { | 441 { |
445 ASSERT(isMainThread()); | 442 ASSERT(isMainThread()); |
446 lazyInitialize(); | |
447 RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_desti
nationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChann
els); | 443 RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_desti
nationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChann
els); |
448 | 444 |
449 if (!node.get()) { | 445 if (!node.get()) { |
450 if (!numberOfInputChannels && !numberOfOutputChannels) { | 446 if (!numberOfInputChannels && !numberOfOutputChannels) { |
451 exceptionState.throwDOMException( | 447 exceptionState.throwDOMException( |
452 IndexSizeError, | 448 IndexSizeError, |
453 "number of input channels and output channels cannot both be zer
o."); | 449 "number of input channels and output channels cannot both be zer
o."); |
454 } else if (numberOfInputChannels > AudioContext::maxNumberOfChannels())
{ | 450 } else if (numberOfInputChannels > AudioContext::maxNumberOfChannels())
{ |
455 exceptionState.throwDOMException( | 451 exceptionState.throwDOMException( |
456 IndexSizeError, | 452 IndexSizeError, |
(...skipping 15 matching lines...) Expand all Loading... |
472 return nullptr; | 468 return nullptr; |
473 } | 469 } |
474 | 470 |
475 refNode(node.get()); // context keeps reference until we stop making javascr
ipt rendering callbacks | 471 refNode(node.get()); // context keeps reference until we stop making javascr
ipt rendering callbacks |
476 return node; | 472 return node; |
477 } | 473 } |
478 | 474 |
479 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter() | 475 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter() |
480 { | 476 { |
481 ASSERT(isMainThread()); | 477 ASSERT(isMainThread()); |
482 lazyInitialize(); | |
483 return BiquadFilterNode::create(this, m_destinationNode->sampleRate()); | 478 return BiquadFilterNode::create(this, m_destinationNode->sampleRate()); |
484 } | 479 } |
485 | 480 |
486 PassRefPtr<WaveShaperNode> AudioContext::createWaveShaper() | 481 PassRefPtr<WaveShaperNode> AudioContext::createWaveShaper() |
487 { | 482 { |
488 ASSERT(isMainThread()); | 483 ASSERT(isMainThread()); |
489 lazyInitialize(); | |
490 return WaveShaperNode::create(this); | 484 return WaveShaperNode::create(this); |
491 } | 485 } |
492 | 486 |
493 PassRefPtr<PannerNode> AudioContext::createPanner() | 487 PassRefPtr<PannerNode> AudioContext::createPanner() |
494 { | 488 { |
495 ASSERT(isMainThread()); | 489 ASSERT(isMainThread()); |
496 lazyInitialize(); | |
497 return PannerNode::create(this, m_destinationNode->sampleRate()); | 490 return PannerNode::create(this, m_destinationNode->sampleRate()); |
498 } | 491 } |
499 | 492 |
500 PassRefPtr<ConvolverNode> AudioContext::createConvolver() | 493 PassRefPtr<ConvolverNode> AudioContext::createConvolver() |
501 { | 494 { |
502 ASSERT(isMainThread()); | 495 ASSERT(isMainThread()); |
503 lazyInitialize(); | |
504 return ConvolverNode::create(this, m_destinationNode->sampleRate()); | 496 return ConvolverNode::create(this, m_destinationNode->sampleRate()); |
505 } | 497 } |
506 | 498 |
507 PassRefPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor() | 499 PassRefPtr<DynamicsCompressorNode> AudioContext::createDynamicsCompressor() |
508 { | 500 { |
509 ASSERT(isMainThread()); | 501 ASSERT(isMainThread()); |
510 lazyInitialize(); | |
511 return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate())
; | 502 return DynamicsCompressorNode::create(this, m_destinationNode->sampleRate())
; |
512 } | 503 } |
513 | 504 |
514 PassRefPtr<AnalyserNode> AudioContext::createAnalyser() | 505 PassRefPtr<AnalyserNode> AudioContext::createAnalyser() |
515 { | 506 { |
516 ASSERT(isMainThread()); | 507 ASSERT(isMainThread()); |
517 lazyInitialize(); | |
518 return AnalyserNode::create(this, m_destinationNode->sampleRate()); | 508 return AnalyserNode::create(this, m_destinationNode->sampleRate()); |
519 } | 509 } |
520 | 510 |
521 PassRefPtr<GainNode> AudioContext::createGain() | 511 PassRefPtr<GainNode> AudioContext::createGain() |
522 { | 512 { |
523 ASSERT(isMainThread()); | 513 ASSERT(isMainThread()); |
524 lazyInitialize(); | |
525 return GainNode::create(this, m_destinationNode->sampleRate()); | 514 return GainNode::create(this, m_destinationNode->sampleRate()); |
526 } | 515 } |
527 | 516 |
528 PassRefPtr<DelayNode> AudioContext::createDelay(ExceptionState& exceptionState) | 517 PassRefPtr<DelayNode> AudioContext::createDelay(ExceptionState& exceptionState) |
529 { | 518 { |
530 const double defaultMaxDelayTime = 1; | 519 const double defaultMaxDelayTime = 1; |
531 return createDelay(defaultMaxDelayTime, exceptionState); | 520 return createDelay(defaultMaxDelayTime, exceptionState); |
532 } | 521 } |
533 | 522 |
534 PassRefPtr<DelayNode> AudioContext::createDelay(double maxDelayTime, ExceptionSt
ate& exceptionState) | 523 PassRefPtr<DelayNode> AudioContext::createDelay(double maxDelayTime, ExceptionSt
ate& exceptionState) |
535 { | 524 { |
536 ASSERT(isMainThread()); | 525 ASSERT(isMainThread()); |
537 lazyInitialize(); | |
538 RefPtr<DelayNode> node = DelayNode::create(this, m_destinationNode->sampleRa
te(), maxDelayTime, exceptionState); | 526 RefPtr<DelayNode> node = DelayNode::create(this, m_destinationNode->sampleRa
te(), maxDelayTime, exceptionState); |
539 if (exceptionState.hadException()) | 527 if (exceptionState.hadException()) |
540 return nullptr; | 528 return nullptr; |
541 return node; | 529 return node; |
542 } | 530 } |
543 | 531 |
544 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(ExceptionSta
te& exceptionState) | 532 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(ExceptionSta
te& exceptionState) |
545 { | 533 { |
546 const unsigned ChannelSplitterDefaultNumberOfOutputs = 6; | 534 const unsigned ChannelSplitterDefaultNumberOfOutputs = 6; |
547 return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, exceptio
nState); | 535 return createChannelSplitter(ChannelSplitterDefaultNumberOfOutputs, exceptio
nState); |
548 } | 536 } |
549 | 537 |
550 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe
rOfOutputs, ExceptionState& exceptionState) | 538 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe
rOfOutputs, ExceptionState& exceptionState) |
551 { | 539 { |
552 ASSERT(isMainThread()); | 540 ASSERT(isMainThread()); |
553 lazyInitialize(); | |
554 | |
555 RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_desti
nationNode->sampleRate(), numberOfOutputs); | 541 RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_desti
nationNode->sampleRate(), numberOfOutputs); |
556 | 542 |
557 if (!node.get()) { | 543 if (!node.get()) { |
558 exceptionState.throwDOMException( | 544 exceptionState.throwDOMException( |
559 IndexSizeError, | 545 IndexSizeError, |
560 "number of outputs (" + String::number(numberOfOutputs) | 546 "number of outputs (" + String::number(numberOfOutputs) |
561 + ") must be between 1 and " | 547 + ") must be between 1 and " |
562 + String::number(AudioContext::maxNumberOfChannels()) + "."); | 548 + String::number(AudioContext::maxNumberOfChannels()) + "."); |
563 return nullptr; | 549 return nullptr; |
564 } | 550 } |
565 | 551 |
566 return node; | 552 return node; |
567 } | 553 } |
568 | 554 |
569 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState&
exceptionState) | 555 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState&
exceptionState) |
570 { | 556 { |
571 const unsigned ChannelMergerDefaultNumberOfInputs = 6; | 557 const unsigned ChannelMergerDefaultNumberOfInputs = 6; |
572 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, exceptionStat
e); | 558 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, exceptionStat
e); |
573 } | 559 } |
574 | 560 |
575 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI
nputs, ExceptionState& exceptionState) | 561 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI
nputs, ExceptionState& exceptionState) |
576 { | 562 { |
577 ASSERT(isMainThread()); | 563 ASSERT(isMainThread()); |
578 lazyInitialize(); | |
579 | |
580 RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinati
onNode->sampleRate(), numberOfInputs); | 564 RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinati
onNode->sampleRate(), numberOfInputs); |
581 | 565 |
582 if (!node.get()) { | 566 if (!node.get()) { |
583 exceptionState.throwDOMException( | 567 exceptionState.throwDOMException( |
584 IndexSizeError, | 568 IndexSizeError, |
585 "number of inputs (" + String::number(numberOfInputs) | 569 "number of inputs (" + String::number(numberOfInputs) |
586 + ") must be between 1 and " | 570 + ") must be between 1 and " |
587 + String::number(AudioContext::maxNumberOfChannels()) + "."); | 571 + String::number(AudioContext::maxNumberOfChannels()) + "."); |
588 return nullptr; | 572 return nullptr; |
589 } | 573 } |
590 | 574 |
591 return node; | 575 return node; |
592 } | 576 } |
593 | 577 |
594 PassRefPtr<OscillatorNode> AudioContext::createOscillator() | 578 PassRefPtr<OscillatorNode> AudioContext::createOscillator() |
595 { | 579 { |
596 ASSERT(isMainThread()); | 580 ASSERT(isMainThread()); |
597 lazyInitialize(); | |
598 | |
599 RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode
->sampleRate()); | 581 RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode
->sampleRate()); |
600 | 582 |
601 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. | 583 // Because this is an AudioScheduledSourceNode, the context keeps a referenc
e until it has finished playing. |
602 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). | 584 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext:
:notifyNodeFinishedProcessing(). |
603 refNode(node.get()); | 585 refNode(node.get()); |
604 | 586 |
605 return node; | 587 return node; |
606 } | 588 } |
607 | 589 |
608 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl
oat32Array* imag, ExceptionState& exceptionState) | 590 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl
oat32Array* imag, ExceptionState& exceptionState) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 } | 623 } |
642 | 624 |
643 if (imag->length() > 4096) { | 625 if (imag->length() > 4096) { |
644 exceptionState.throwDOMException( | 626 exceptionState.throwDOMException( |
645 IndexSizeError, | 627 IndexSizeError, |
646 "length of imaginary array (" + String::number(imag->length()) | 628 "length of imaginary array (" + String::number(imag->length()) |
647 + ") exceeds allowed maximum of 4096"); | 629 + ") exceeds allowed maximum of 4096"); |
648 return nullptr; | 630 return nullptr; |
649 } | 631 } |
650 | 632 |
651 lazyInitialize(); | |
652 return PeriodicWave::create(sampleRate(), real, imag); | 633 return PeriodicWave::create(sampleRate(), real, imag); |
653 } | 634 } |
654 | 635 |
655 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) | 636 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) |
656 { | 637 { |
657 ASSERT(isAudioThread()); | 638 ASSERT(isAudioThread()); |
658 m_finishedNodes.append(node); | 639 m_finishedNodes.append(node); |
659 } | 640 } |
660 | 641 |
661 void AudioContext::derefFinishedSourceNodes() | 642 void AudioContext::derefFinishedSourceNodes() |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1038 } | 1019 } |
1039 | 1020 |
1040 void AudioContext::decrementActiveSourceCount() | 1021 void AudioContext::decrementActiveSourceCount() |
1041 { | 1022 { |
1042 atomicDecrement(&m_activeSourceCount); | 1023 atomicDecrement(&m_activeSourceCount); |
1043 } | 1024 } |
1044 | 1025 |
1045 } // namespace WebCore | 1026 } // namespace WebCore |
1046 | 1027 |
1047 #endif // ENABLE(WEB_AUDIO) | 1028 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |