blob: afdc1392297e466c2022c726c226b3be4924f41f [file] [log] [blame]
/*
* Copyright (C) 2011, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "modules/webaudio/AudioBasicProcessorHandler.h"
#include "modules/webaudio/BaseAudioContext.h"
#include "modules/webaudio/WaveShaperNode.h"
#include "modules/webaudio/WaveShaperOptions.h"
#include "wtf/PtrUtil.h"
namespace blink {
WaveShaperNode::WaveShaperNode(BaseAudioContext& context) : AudioNode(context) {
setHandler(AudioBasicProcessorHandler::create(
AudioHandler::NodeTypeWaveShaper, *this, context.sampleRate(),
wrapUnique(new WaveShaperProcessor(context.sampleRate(), 1))));
handler().initialize();
}
WaveShaperNode* WaveShaperNode::create(BaseAudioContext& context,
ExceptionState& exceptionState) {
DCHECK(isMainThread());
if (context.isContextClosed()) {
context.throwExceptionForClosedState(exceptionState);
return nullptr;
}
return new WaveShaperNode(context);
}
WaveShaperNode* WaveShaperNode::create(BaseAudioContext* context,
const WaveShaperOptions& options,
ExceptionState& exceptionState) {
WaveShaperNode* node = create(*context, exceptionState);
if (!node)
return nullptr;
node->handleChannelOptions(options, exceptionState);
if (options.hasCurve())
node->setCurve(options.curve(), exceptionState);
if (options.hasOversample())
node->setOversample(options.oversample());
return node;
}
WaveShaperProcessor* WaveShaperNode::getWaveShaperProcessor() const {
return static_cast<WaveShaperProcessor*>(
static_cast<AudioBasicProcessorHandler&>(handler()).processor());
}
void WaveShaperNode::setCurveImpl(const float* curveData,
unsigned curveLength,
ExceptionState& exceptionState) {
DCHECK(isMainThread());
if (curveData && curveLength < 2) {
exceptionState.throwDOMException(
InvalidAccessError,
ExceptionMessages::indexExceedsMinimumBound<unsigned>("curve length",
curveLength, 2));
return;
}
getWaveShaperProcessor()->setCurve(curveData, curveLength);
}
void WaveShaperNode::setCurve(DOMFloat32Array* curve,
ExceptionState& exceptionState) {
DCHECK(isMainThread());
if (curve)
setCurveImpl(curve->data(), curve->length(), exceptionState);
else
setCurveImpl(nullptr, 0, exceptionState);
}
void WaveShaperNode::setCurve(const Vector<float>& curve,
ExceptionState& exceptionState) {
DCHECK(isMainThread());
setCurveImpl(curve.data(), curve.size(), exceptionState);
}
DOMFloat32Array* WaveShaperNode::curve() {
Vector<float>* curve = getWaveShaperProcessor()->curve();
if (!curve)
return nullptr;
unsigned size = curve->size();
RefPtr<WTF::Float32Array> newCurve = WTF::Float32Array::create(size);
memcpy(newCurve->data(), curve->data(), sizeof(float) * size);
return DOMFloat32Array::create(newCurve.release());
}
void WaveShaperNode::setOversample(const String& type) {
DCHECK(isMainThread());
// This is to synchronize with the changes made in
// AudioBasicProcessorNode::checkNumberOfChannelsForInput() where we can
// initialize() and uninitialize().
BaseAudioContext::AutoLocker contextLocker(context());
if (type == "none") {
getWaveShaperProcessor()->setOversample(
WaveShaperProcessor::OverSampleNone);
} else if (type == "2x") {
getWaveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample2x);
} else if (type == "4x") {
getWaveShaperProcessor()->setOversample(WaveShaperProcessor::OverSample4x);
} else {
ASSERT_NOT_REACHED();
}
}
String WaveShaperNode::oversample() const {
switch (const_cast<WaveShaperNode*>(this)
->getWaveShaperProcessor()
->oversample()) {
case WaveShaperProcessor::OverSampleNone:
return "none";
case WaveShaperProcessor::OverSample2x:
return "2x";
case WaveShaperProcessor::OverSample4x:
return "4x";
default:
ASSERT_NOT_REACHED();
return "none";
}
}
} // namespace blink