#include "panner-node.hpp"
#include "audio-context.hpp"
#include "audio-param.hpp"
inline std::string fromDistanceModel(lab::PannerNode::DistanceModel mode) {
if (mode == lab::PannerNode::LINEAR_DISTANCE) {
return "linear";
} else if (mode == lab::PannerNode::INVERSE_DISTANCE) {
return "inverse";
} else {
return "exponential";
}
}
inline lab::PannerNode::DistanceModel toDistanceModel(const std::string &mode) {
if (mode == "linear") {
return lab::PannerNode::LINEAR_DISTANCE;
} else if (mode == "inverse") {
return lab::PannerNode::INVERSE_DISTANCE;
} else {
return lab::PannerNode::EXPONENTIAL_DISTANCE;
}
}
inline const char *fromPanningModel(lab::PanningModel mode) {
if (mode == lab::PanningModel::EQUALPOWER) {
return "equalpower";
} else {
return "HRTF";
}
}
inline lab::PanningModel toPanningModel(const std::string &mode) {
if (mode == "equalpower") {
return lab::PanningModel::EQUALPOWER;
} else {
return lab::PanningModel::HRTF;
}
}
IMPLEMENT_ES5_CLASS(PannerNode);
void PannerNode::init(Napi::Env env, Napi::Object exports) {
Napi::Function ctor = wrap(env);
JS_ASSIGN_SETTER(coneOuterGain);
JS_ASSIGN_SETTER(coneOuterAngle);
JS_ASSIGN_SETTER(coneInnerAngle);
JS_ASSIGN_SETTER(rolloffFactor);
JS_ASSIGN_SETTER(maxDistance);
JS_ASSIGN_SETTER(refDistance);
JS_ASSIGN_SETTER(distanceModel);
JS_ASSIGN_SETTER(panningModel);
JS_ASSIGN_METHOD(setVelocity);
JS_ASSIGN_METHOD(setOrientation);
JS_ASSIGN_METHOD(setPosition);
JS_ASSIGN_GETTER(orientationZ);
JS_ASSIGN_GETTER(orientationY);
JS_ASSIGN_GETTER(orientationX);
JS_ASSIGN_GETTER(positionZ);
JS_ASSIGN_GETTER(positionY);
JS_ASSIGN_GETTER(positionX);
JS_ASSIGN_METHOD(destroy);
exports.Set("PannerNode", ctor);
}
PannerNode::PannerNode(const Napi::CallbackInfo &info) : CommonNode(info.This(), "PannerNode") {
NAPI_ENV;
Napi::Object context = info[0].As();
Napi::Function paramCtor = info[1].As();
AudioContext *contextUnwrap = AudioContext::unwrap(context);
lab::AudioContext *contextLab = contextUnwrap->getCtx().get();
reset(context, std::make_shared(*contextLab));
lab::PannerNode *node = static_cast(_impl.get());
napi_value argv[2];
argv[0] = context;
ParamPtr positionXParam = node->positionX();
argv[1] = JS_EXT(&positionXParam);
_positionX.Reset(paramCtor.New(2, argv), 1);
ParamPtr positionYParam = node->positionY();
argv[1] = JS_EXT(&positionYParam);
_positionY.Reset(paramCtor.New(2, argv), 1);
ParamPtr positionZParam = node->positionZ();
argv[1] = JS_EXT(&positionZParam);
_positionZ.Reset(paramCtor.New(2, argv), 1);
ParamPtr orientationXParam = node->orientationX();
argv[1] = JS_EXT(&orientationXParam);
_orientationX.Reset(paramCtor.New(2, argv), 1);
ParamPtr orientationYParam = node->orientationY();
argv[1] = JS_EXT(&orientationYParam);
_orientationY.Reset(paramCtor.New(2, argv), 1);
ParamPtr orientationZParam = node->orientationZ();
argv[1] = JS_EXT(&orientationZParam);
_orientationZ.Reset(paramCtor.New(2, argv), 1);
argv[1] = JS_EXT(&_impl);
super(info, 2, argv);
}
PannerNode::~PannerNode() {
_destroy();
}
void PannerNode::_destroy() {
DES_CHECK;
_positionX.Reset();
_positionY.Reset();
_positionZ.Reset();
_orientationX.Reset();
_orientationY.Reset();
_orientationZ.Reset();
CommonNode::_destroy();
}
// ------ Methods and props
JS_IMPLEMENT_METHOD(PannerNode, setPosition) {
THIS_CHECK;
REQ_FLOAT_ARG(0, x);
REQ_FLOAT_ARG(1, y);
REQ_FLOAT_ARG(2, z);
lab::PannerNode *node = static_cast(_impl.get());
node->setPosition(x, y, z);
RET_UNDEFINED;
}
JS_IMPLEMENT_METHOD(PannerNode, setOrientation) {
THIS_CHECK;
REQ_FLOAT_ARG(0, x);
REQ_FLOAT_ARG(1, y);
REQ_FLOAT_ARG(2, z);
lab::PannerNode *node = static_cast(_impl.get());
node->setOrientation(lab::FloatPoint3D(x, y, z));
RET_UNDEFINED;
}
JS_IMPLEMENT_METHOD(PannerNode, setVelocity) {
THIS_CHECK;
REQ_FLOAT_ARG(0, x);
REQ_FLOAT_ARG(1, y);
REQ_FLOAT_ARG(2, z);
lab::PannerNode *node = static_cast(_impl.get());
node->setVelocity(x, y, z);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, panningModel) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_VALUE(JS_STR(fromPanningModel(node->panningModel())));
}
JS_IMPLEMENT_SETTER(PannerNode, panningModel) {
THIS_CHECK;
SETTER_STR_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setPanningModel(toPanningModel(v.c_str()));
emit("panningModel", 1, &value);
RET_UNDEFINED;
}
PARAM_GETTER(PannerNode, positionX);
PARAM_GETTER(PannerNode, positionY);
PARAM_GETTER(PannerNode, positionZ);
PARAM_GETTER(PannerNode, orientationX);
PARAM_GETTER(PannerNode, orientationY);
PARAM_GETTER(PannerNode, orientationZ);
JS_IMPLEMENT_GETTER(PannerNode, distanceModel) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_VALUE(JS_STR(fromDistanceModel(node->distanceModel())));
}
JS_IMPLEMENT_SETTER(PannerNode, distanceModel) {
THIS_CHECK;
SETTER_STR_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setDistanceModel(toDistanceModel(v.c_str()));
emit("distanceModel", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, refDistance) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_NUM(node->refDistance());
}
JS_IMPLEMENT_SETTER(PannerNode, refDistance) {
THIS_CHECK;
SETTER_DOUBLE_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setRefDistance(static_cast(v));
emit("refDistance", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, maxDistance) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_NUM(node->maxDistance());
}
JS_IMPLEMENT_SETTER(PannerNode, maxDistance) {
THIS_CHECK;
SETTER_DOUBLE_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setMaxDistance(static_cast(v));
emit("maxDistance", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, rolloffFactor) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_NUM(node->rolloffFactor());
}
JS_IMPLEMENT_SETTER(PannerNode, rolloffFactor) {
THIS_CHECK;
SETTER_DOUBLE_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setRolloffFactor(static_cast(v));
emit("rolloffFactor", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, coneInnerAngle) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_NUM(node->coneInnerAngle());
}
JS_IMPLEMENT_SETTER(PannerNode, coneInnerAngle) {
THIS_CHECK;
SETTER_DOUBLE_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setConeInnerAngle(static_cast(v));
emit("coneInnerAngle", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, coneOuterAngle) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_NUM(node->coneOuterAngle());
}
JS_IMPLEMENT_SETTER(PannerNode, coneOuterAngle) {
THIS_CHECK;
SETTER_DOUBLE_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setConeOuterAngle(static_cast(v));
emit("coneOuterAngle", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_GETTER(PannerNode, coneOuterGain) {
THIS_CHECK;
lab::PannerNode *node = static_cast(_impl.get());
RET_NUM(node->coneOuterGain());
}
JS_IMPLEMENT_SETTER(PannerNode, coneOuterGain) {
THIS_CHECK;
SETTER_DOUBLE_ARG;
lab::PannerNode *node = static_cast(_impl.get());
node->setConeOuterGain(static_cast(v));
emit("coneOuterGain", 1, &value);
RET_UNDEFINED;
}
JS_IMPLEMENT_METHOD(PannerNode, destroy) {
THIS_CHECK;
emit("destroy");
_destroy();
RET_UNDEFINED;
}