| Index: third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp
 | 
| diff --git a/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..7af4e078a0cf82eb82c18caf72a6fc1de0bbe333
 | 
| --- /dev/null
 | 
| +++ b/third_party/WebKit/Source/modules/webaudio/ConstantSourceNode.cpp
 | 
| @@ -0,0 +1,155 @@
 | 
| +// Copyright 2016 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +#include "modules/webaudio/ConstantSourceNode.h"
 | 
| +
 | 
| +#include "bindings/core/v8/ExceptionMessages.h"
 | 
| +#include "bindings/core/v8/ExceptionState.h"
 | 
| +#include "core/dom/ExceptionCode.h"
 | 
| +#include "modules/webaudio/AudioNodeOutput.h"
 | 
| +#include "modules/webaudio/ConstantSourceOptions.h"
 | 
| +#include "platform/audio/AudioUtilities.h"
 | 
| +#include "wtf/MathExtras.h"
 | 
| +#include "wtf/StdLibExtras.h"
 | 
| +#include <algorithm>
 | 
| +
 | 
| +namespace blink {
 | 
| +
 | 
| +ConstantSourceHandler::ConstantSourceHandler(AudioNode& node,
 | 
| +                                             float sampleRate,
 | 
| +                                             AudioParamHandler& offset)
 | 
| +    : AudioScheduledSourceHandler(NodeTypeConstantSource, node, sampleRate),
 | 
| +      m_offset(offset),
 | 
| +      m_sampleAccurateValues(ProcessingSizeInFrames) {
 | 
| +  // A ConstantSource is always mono.
 | 
| +  addOutput(1);
 | 
| +
 | 
| +  initialize();
 | 
| +}
 | 
| +
 | 
| +PassRefPtr<ConstantSourceHandler> ConstantSourceHandler::create(
 | 
| +    AudioNode& node,
 | 
| +    float sampleRate,
 | 
| +    AudioParamHandler& offset) {
 | 
| +  return adoptRef(new ConstantSourceHandler(node, sampleRate, offset));
 | 
| +}
 | 
| +
 | 
| +ConstantSourceHandler::~ConstantSourceHandler() {
 | 
| +  uninitialize();
 | 
| +}
 | 
| +
 | 
| +void ConstantSourceHandler::process(size_t framesToProcess) {
 | 
| +  AudioBus* outputBus = output(0).bus();
 | 
| +  DCHECK(outputBus);
 | 
| +
 | 
| +  if (!isInitialized() || !outputBus->numberOfChannels()) {
 | 
| +    outputBus->zero();
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  // The audio thread can't block on this lock, so we call tryLock() instead.
 | 
| +  MutexTryLocker tryLocker(m_processLock);
 | 
| +  if (!tryLocker.locked()) {
 | 
| +    // Too bad - the tryLock() failed.
 | 
| +    outputBus->zero();
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  size_t quantumFrameOffset;
 | 
| +  size_t nonSilentFramesToProcess;
 | 
| +
 | 
| +  // Figure out where in the current rendering quantum that the source is
 | 
| +  // active and for how many frames.
 | 
| +  updateSchedulingInfo(framesToProcess, outputBus, quantumFrameOffset,
 | 
| +                       nonSilentFramesToProcess);
 | 
| +
 | 
| +  if (!nonSilentFramesToProcess) {
 | 
| +    outputBus->zero();
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  if (m_offset->hasSampleAccurateValues()) {
 | 
| +    DCHECK_LE(framesToProcess, m_sampleAccurateValues.size());
 | 
| +    if (framesToProcess <= m_sampleAccurateValues.size()) {
 | 
| +      float* offsets = m_sampleAccurateValues.data();
 | 
| +      m_offset->calculateSampleAccurateValues(offsets, framesToProcess);
 | 
| +      if (nonSilentFramesToProcess > 0) {
 | 
| +        memcpy(outputBus->channel(0)->mutableData() + quantumFrameOffset,
 | 
| +               offsets + quantumFrameOffset,
 | 
| +               nonSilentFramesToProcess * sizeof(*offsets));
 | 
| +        outputBus->clearSilentFlag();
 | 
| +      } else {
 | 
| +        outputBus->zero();
 | 
| +      }
 | 
| +    }
 | 
| +  } else {
 | 
| +    float value = m_offset->value();
 | 
| +
 | 
| +    if (value == 0) {
 | 
| +      outputBus->zero();
 | 
| +    } else {
 | 
| +      float* dest = outputBus->channel(0)->mutableData();
 | 
| +      dest += quantumFrameOffset;
 | 
| +      for (unsigned k = 0; k < nonSilentFramesToProcess; ++k) {
 | 
| +        dest[k] = value;
 | 
| +      }
 | 
| +      outputBus->clearSilentFlag();
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +bool ConstantSourceHandler::propagatesSilence() const {
 | 
| +  return !isPlayingOrScheduled() || hasFinished();
 | 
| +}
 | 
| +
 | 
| +// ----------------------------------------------------------------
 | 
| +ConstantSourceNode::ConstantSourceNode(BaseAudioContext& context)
 | 
| +    : AudioScheduledSourceNode(context),
 | 
| +      m_offset(AudioParam::create(context, ParamTypeConstantSourceValue, 1)) {
 | 
| +  setHandler(ConstantSourceHandler::create(*this, context.sampleRate(),
 | 
| +                                           m_offset->handler()));
 | 
| +}
 | 
| +
 | 
| +ConstantSourceNode* ConstantSourceNode::create(BaseAudioContext& context,
 | 
| +                                               ExceptionState& exceptionState) {
 | 
| +  DCHECK(isMainThread());
 | 
| +
 | 
| +  if (context.isContextClosed()) {
 | 
| +    context.throwExceptionForClosedState(exceptionState);
 | 
| +    return nullptr;
 | 
| +  }
 | 
| +
 | 
| +  return new ConstantSourceNode(context);
 | 
| +}
 | 
| +
 | 
| +ConstantSourceNode* ConstantSourceNode::create(
 | 
| +    BaseAudioContext* context,
 | 
| +    const ConstantSourceOptions& options,
 | 
| +    ExceptionState& exceptionState) {
 | 
| +  DCHECK(isMainThread());
 | 
| +
 | 
| +  ConstantSourceNode* node = create(*context, exceptionState);
 | 
| +
 | 
| +  if (!node)
 | 
| +    return nullptr;
 | 
| +
 | 
| +  node->offset()->setValue(options.offset());
 | 
| +
 | 
| +  return node;
 | 
| +}
 | 
| +
 | 
| +DEFINE_TRACE(ConstantSourceNode) {
 | 
| +  visitor->trace(m_offset);
 | 
| +  AudioScheduledSourceNode::trace(visitor);
 | 
| +}
 | 
| +
 | 
| +ConstantSourceHandler& ConstantSourceNode::constantSourceHandler() const {
 | 
| +  return static_cast<ConstantSourceHandler&>(handler());
 | 
| +}
 | 
| +
 | 
| +AudioParam* ConstantSourceNode::offset() {
 | 
| +  return m_offset;
 | 
| +}
 | 
| +
 | 
| +}  // namespace blink
 | 
| 
 |