| 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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 return "WaveShaperNode"; | 151 return "WaveShaperNode"; |
| 152 case NodeTypeUnknown: | 152 case NodeTypeUnknown: |
| 153 case NodeTypeEnd: | 153 case NodeTypeEnd: |
| 154 default: | 154 default: |
| 155 ASSERT_NOT_REACHED(); | 155 ASSERT_NOT_REACHED(); |
| 156 return "UnknownNode"; | 156 return "UnknownNode"; |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 | 159 |
| 160 void AudioHandler::setNodeType(NodeType type) { | 160 void AudioHandler::setNodeType(NodeType type) { |
| 161 // Don't allow the node type to be changed to a different node type, after it'
s already been | 161 // Don't allow the node type to be changed to a different node type, after |
| 162 // set! And the new type can't be unknown or end! | 162 // it's already been set. And the new type can't be unknown or end. |
| 163 DCHECK_EQ(m_nodeType, NodeTypeUnknown); | 163 DCHECK_EQ(m_nodeType, NodeTypeUnknown); |
| 164 DCHECK_NE(type, NodeTypeUnknown); | 164 DCHECK_NE(type, NodeTypeUnknown); |
| 165 DCHECK_NE(type, NodeTypeEnd); | 165 DCHECK_NE(type, NodeTypeEnd); |
| 166 | 166 |
| 167 m_nodeType = type; | 167 m_nodeType = type; |
| 168 | 168 |
| 169 #if DEBUG_AUDIONODE_REFERENCES | 169 #if DEBUG_AUDIONODE_REFERENCES |
| 170 ++s_nodeCount[type]; | 170 ++s_nodeCount[type]; |
| 171 fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::AudioHandler [%3d]\n", | 171 fprintf(stderr, "[%16p]: %16p: %2d: AudioHandler::AudioHandler [%3d]\n", |
| 172 context(), this, getNodeType(), s_nodeCount[getNodeType()]); | 172 context(), this, getNodeType(), s_nodeCount[getNodeType()]); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 input->changedOutputs(); | 303 input->changedOutputs(); |
| 304 } | 304 } |
| 305 | 305 |
| 306 void AudioHandler::processIfNecessary(size_t framesToProcess) { | 306 void AudioHandler::processIfNecessary(size_t framesToProcess) { |
| 307 DCHECK(context()->isAudioThread()); | 307 DCHECK(context()->isAudioThread()); |
| 308 | 308 |
| 309 if (!isInitialized()) | 309 if (!isInitialized()) |
| 310 return; | 310 return; |
| 311 | 311 |
| 312 // Ensure that we only process once per rendering quantum. | 312 // Ensure that we only process once per rendering quantum. |
| 313 // This handles the "fanout" problem where an output is connected to multiple
inputs. | 313 // This handles the "fanout" problem where an output is connected to multiple |
| 314 // The first time we're called during this time slice we process, but after th
at we don't want to re-process, | 314 // inputs. The first time we're called during this time slice we process, but |
| 315 // instead our output(s) will already have the results cached in their bus; | 315 // after that we don't want to re-process, instead our output(s) will already |
| 316 // have the results cached in their bus; |
| 316 double currentTime = context()->currentTime(); | 317 double currentTime = context()->currentTime(); |
| 317 if (m_lastProcessingTime != currentTime) { | 318 if (m_lastProcessingTime != currentTime) { |
| 318 m_lastProcessingTime = | 319 // important to first update this time because of feedback loops in the |
| 319 currentTime; // important to first update this time because of feedback
loops in the rendering graph | 320 // rendering graph. |
| 321 m_lastProcessingTime = currentTime; |
| 320 | 322 |
| 321 pullInputs(framesToProcess); | 323 pullInputs(framesToProcess); |
| 322 | 324 |
| 323 bool silentInputs = inputsAreSilent(); | 325 bool silentInputs = inputsAreSilent(); |
| 324 if (!silentInputs) | 326 if (!silentInputs) |
| 325 m_lastNonSilentTime = | 327 m_lastNonSilentTime = |
| 326 (context()->currentSampleFrame() + framesToProcess) / | 328 (context()->currentSampleFrame() + framesToProcess) / |
| 327 static_cast<double>(m_sampleRate); | 329 static_cast<double>(m_sampleRate); |
| 328 | 330 |
| 329 if (silentInputs && propagatesSilence()) { | 331 if (silentInputs && propagatesSilence()) { |
| 330 silenceOutputs(); | 332 silenceOutputs(); |
| 331 } else { | 333 } else { |
| 332 // Unsilence the outputs first because the processing of the node may caus
e the outputs | 334 // Unsilence the outputs first because the processing of the node may |
| 333 // to go silent and we want to propagate that hint to the downstream nodes
! (For | 335 // cause the outputs to go silent and we want to propagate that hint to |
| 334 // example, a Gain node with a gain of 0 will want to silence its output.) | 336 // the downstream nodes. (For example, a Gain node with a gain of 0 will |
| 337 // want to silence its output.) |
| 335 unsilenceOutputs(); | 338 unsilenceOutputs(); |
| 336 process(framesToProcess); | 339 process(framesToProcess); |
| 337 } | 340 } |
| 338 } | 341 } |
| 339 } | 342 } |
| 340 | 343 |
| 341 void AudioHandler::checkNumberOfChannelsForInput(AudioNodeInput* input) { | 344 void AudioHandler::checkNumberOfChannelsForInput(AudioNodeInput* input) { |
| 342 DCHECK(context()->isAudioThread()); | 345 DCHECK(context()->isAudioThread()); |
| 343 ASSERT(context()->isGraphOwner()); | 346 ASSERT(context()->isGraphOwner()); |
| 344 | 347 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 DCHECK(isMainThread()); | 396 DCHECK(isMainThread()); |
| 394 BaseAudioContext::AutoLocker locker(context()); | 397 BaseAudioContext::AutoLocker locker(context()); |
| 395 | 398 |
| 396 m_isDisabled = false; | 399 m_isDisabled = false; |
| 397 for (auto& output : m_outputs) | 400 for (auto& output : m_outputs) |
| 398 output->enable(); | 401 output->enable(); |
| 399 } | 402 } |
| 400 } | 403 } |
| 401 | 404 |
| 402 void AudioHandler::disableOutputsIfNecessary() { | 405 void AudioHandler::disableOutputsIfNecessary() { |
| 403 // Disable outputs if appropriate. We do this if the number of connections is
0 or 1. The case | 406 // Disable outputs if appropriate. We do this if the number of connections is |
| 404 // of 0 is from deref() where there are no connections left. The case of 1 is
from | 407 // 0 or 1. The case of 0 is from deref() where there are no connections left. |
| 405 // AudioNodeInput::disable() where we want to disable outputs when there's onl
y one connection | 408 // The case of 1 is from AudioNodeInput::disable() where we want to disable |
| 406 // left because we're ready to go away, but can't quite yet. | 409 // outputs when there's only one connection left because we're ready to go |
| 410 // away, but can't quite yet. |
| 407 if (m_connectionRefCount <= 1 && !m_isDisabled) { | 411 if (m_connectionRefCount <= 1 && !m_isDisabled) { |
| 408 // Still may have JavaScript references, but no more "active" connection ref
erences, so put all of our outputs in a "dormant" disabled state. | 412 // Still may have JavaScript references, but no more "active" connection |
| 409 // Garbage collection may take a very long time after this time, so the "dor
mant" disabled nodes should not bog down the rendering... | 413 // references, so put all of our outputs in a "dormant" disabled state. |
| 414 // Garbage collection may take a very long time after this time, so the |
| 415 // "dormant" disabled nodes should not bog down the rendering... |
| 410 | 416 |
| 411 // As far as JavaScript is concerned, our outputs must still appear to be co
nnected. | 417 // As far as JavaScript is concerned, our outputs must still appear to be |
| 412 // But internally our outputs should be disabled from the inputs they're con
nected to. | 418 // connected. But internally our outputs should be disabled from the inputs |
| 413 // disable() can recursively deref connections (and call disable()) down a w
hole chain of connected nodes. | 419 // they're connected to. disable() can recursively deref connections (and |
| 420 // call disable()) down a whole chain of connected nodes. |
| 414 | 421 |
| 415 // TODO(rtoy,hongchan): we need special cases the convolver, delay, biquad,
and IIR since | 422 // TODO(rtoy,hongchan): we need special cases the convolver, delay, biquad, |
| 416 // they have a significant tail-time and shouldn't be disconnected simply be
cause they no | 423 // and IIR since they have a significant tail-time and shouldn't be |
| 417 // longer have any input connections. This needs to be handled more generall
y where | 424 // disconnected simply because they no longer have any input connections. |
| 418 // AudioNodes have a tailTime attribute. Then the AudioNode only needs to re
main "active" | 425 // This needs to be handled more generally where AudioNodes have a tailTime |
| 419 // for tailTime seconds after there are no longer any active connections. | 426 // attribute. Then the AudioNode only needs to remain "active" for tailTime |
| 427 // seconds after there are no longer any active connections. |
| 420 if (getNodeType() != NodeTypeConvolver && getNodeType() != NodeTypeDelay && | 428 if (getNodeType() != NodeTypeConvolver && getNodeType() != NodeTypeDelay && |
| 421 getNodeType() != NodeTypeBiquadFilter && | 429 getNodeType() != NodeTypeBiquadFilter && |
| 422 getNodeType() != NodeTypeIIRFilter) { | 430 getNodeType() != NodeTypeIIRFilter) { |
| 423 m_isDisabled = true; | 431 m_isDisabled = true; |
| 424 clearInternalStateWhenDisabled(); | 432 clearInternalStateWhenDisabled(); |
| 425 for (auto& output : m_outputs) | 433 for (auto& output : m_outputs) |
| 426 output->disable(); | 434 output->disable(); |
| 427 } | 435 } |
| 428 } | 436 } |
| 429 } | 437 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 void AudioHandler::updateChannelCountMode() { | 509 void AudioHandler::updateChannelCountMode() { |
| 502 m_channelCountMode = m_newChannelCountMode; | 510 m_channelCountMode = m_newChannelCountMode; |
| 503 updateChannelsForInputs(); | 511 updateChannelsForInputs(); |
| 504 } | 512 } |
| 505 | 513 |
| 506 void AudioHandler::updateChannelInterpretation() { | 514 void AudioHandler::updateChannelInterpretation() { |
| 507 m_channelInterpretation = m_newChannelInterpretation; | 515 m_channelInterpretation = m_newChannelInterpretation; |
| 508 } | 516 } |
| 509 | 517 |
| 510 unsigned AudioHandler::numberOfOutputChannels() const { | 518 unsigned AudioHandler::numberOfOutputChannels() const { |
| 511 // This should only be called for ScriptProcessorNodes which are the only node
s where you can | 519 // This should only be called for ScriptProcessorNodes which are the only |
| 512 // have an output with 0 channels. All other nodes have have at least one out
put channel, so | 520 // nodes where you can have an output with 0 channels. All other nodes have |
| 513 // there's no reason other nodes should ever call this function. | 521 // have at least one output channel, so there's no reason other nodes should |
| 522 // ever call this function. |
| 514 DCHECK(0) << "numberOfOutputChannels() not valid for node type " | 523 DCHECK(0) << "numberOfOutputChannels() not valid for node type " |
| 515 << getNodeType(); | 524 << getNodeType(); |
| 516 return 1; | 525 return 1; |
| 517 } | 526 } |
| 518 // ---------------------------------------------------------------- | 527 // ---------------------------------------------------------------- |
| 519 | 528 |
| 520 AudioNode::AudioNode(BaseAudioContext& context) | 529 AudioNode::AudioNode(BaseAudioContext& context) |
| 521 : m_context(context), m_handler(nullptr) { | 530 : m_context(context), m_handler(nullptr) { |
| 522 ThreadState::current()->registerPreFinalizer(this); | 531 ThreadState::current()->registerPreFinalizer(this); |
| 523 } | 532 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 return nullptr; | 617 return nullptr; |
| 609 } | 618 } |
| 610 | 619 |
| 611 if (context() != destination->context()) { | 620 if (context() != destination->context()) { |
| 612 exceptionState.throwDOMException(SyntaxError, | 621 exceptionState.throwDOMException(SyntaxError, |
| 613 "cannot connect to a destination " | 622 "cannot connect to a destination " |
| 614 "belonging to a different audio context."); | 623 "belonging to a different audio context."); |
| 615 return nullptr; | 624 return nullptr; |
| 616 } | 625 } |
| 617 | 626 |
| 618 // ScriptProcessorNodes with 0 output channels can't be connected to any desti
nation. If there | 627 // ScriptProcessorNodes with 0 output channels can't be connected to any |
| 619 // are no output channels, what would the destination receive? Just disallow
this. | 628 // destination. If there are no output channels, what would the destination |
| 629 // receive? Just disallow this. |
| 620 if (handler().getNodeType() == AudioHandler::NodeTypeJavaScript && | 630 if (handler().getNodeType() == AudioHandler::NodeTypeJavaScript && |
| 621 handler().numberOfOutputChannels() == 0) { | 631 handler().numberOfOutputChannels() == 0) { |
| 622 exceptionState.throwDOMException(InvalidAccessError, | 632 exceptionState.throwDOMException(InvalidAccessError, |
| 623 "cannot connect a ScriptProcessorNode " | 633 "cannot connect a ScriptProcessorNode " |
| 624 "with 0 output channels to any " | 634 "with 0 output channels to any " |
| 625 "destination node."); | 635 "destination node."); |
| 626 return nullptr; | 636 return nullptr; |
| 627 } | 637 } |
| 628 | 638 |
| 629 destination->handler() | 639 destination->handler() |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 } | 944 } |
| 935 | 945 |
| 936 void AudioNode::didAddOutput(unsigned numberOfOutputs) { | 946 void AudioNode::didAddOutput(unsigned numberOfOutputs) { |
| 937 m_connectedNodes.append(nullptr); | 947 m_connectedNodes.append(nullptr); |
| 938 DCHECK_EQ(numberOfOutputs, m_connectedNodes.size()); | 948 DCHECK_EQ(numberOfOutputs, m_connectedNodes.size()); |
| 939 m_connectedParams.append(nullptr); | 949 m_connectedParams.append(nullptr); |
| 940 DCHECK_EQ(numberOfOutputs, m_connectedParams.size()); | 950 DCHECK_EQ(numberOfOutputs, m_connectedParams.size()); |
| 941 } | 951 } |
| 942 | 952 |
| 943 } // namespace blink | 953 } // namespace blink |
| OLD | NEW |