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 |